From acad737843f49f05e281eff580816c48d63c77ef Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Sun, 23 Jan 2022 22:49:05 +0800 Subject: [PATCH 001/125] update some controllers --- .../greate/community/config/QuartzConfig.java | 2 +- .../controller/CommentController.java | 9 ++- .../community/controller/DataController.java | 70 +++++++++++----- .../controller/DiscussPostController.java | 79 +++++++++++++------ .../controller/FollowController.java | 56 ++++++++----- .../community/controller/IndexController.java | 51 +++++++----- .../com/greate/community/entity/Result.java | 2 +- .../resources/templates/site/profile.html | 2 +- 8 files changed, 180 insertions(+), 91 deletions(-) diff --git a/src/main/java/com/greate/community/config/QuartzConfig.java b/src/main/java/com/greate/community/config/QuartzConfig.java index 5292131..f641dde 100644 --- a/src/main/java/com/greate/community/config/QuartzConfig.java +++ b/src/main/java/com/greate/community/config/QuartzConfig.java @@ -12,7 +12,7 @@ import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean; * Spring Quartz 配置类,用于将数据存入数据库,以后直接从数据库中调用数据 */ @Configuration -public class QuartzConfig { +public class QuartzConfig { /** * 刷新帖子分数任务 diff --git a/src/main/java/com/greate/community/controller/CommentController.java b/src/main/java/com/greate/community/controller/CommentController.java index a713ebf..dc36427 100644 --- a/src/main/java/com/greate/community/controller/CommentController.java +++ b/src/main/java/com/greate/community/controller/CommentController.java @@ -3,6 +3,7 @@ package com.greate.community.controller; import com.greate.community.entity.Comment; import com.greate.community.entity.DiscussPost; import com.greate.community.entity.Event; +import com.greate.community.entity.Result; import com.greate.community.event.EventProducer; import com.greate.community.service.CommentService; import com.greate.community.service.DiscussPostService; @@ -15,6 +16,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; import java.util.Date; @@ -47,7 +49,8 @@ public class CommentController implements CommunityConstant { * @return */ @PostMapping("/add/{discussPostId}") - public String addComment(@PathVariable("discussPostId") int discussPostId, Comment comment) { + @ResponseBody + public Result addComment(@PathVariable("discussPostId") int discussPostId, Comment comment) { comment.setUserId(hostHolder.getUser().getId()); comment.setStatus(0); comment.setCreateTime(new Date()); @@ -84,7 +87,9 @@ public class CommentController implements CommunityConstant { redisTemplate.opsForSet().add(redisKey, discussPostId); } - return "redirect:/discuss/detail/" + discussPostId; + return new Result("success",Result.SUCCESS,"redirect:/discuss/detail/"+discussPostId); + } + } diff --git a/src/main/java/com/greate/community/controller/DataController.java b/src/main/java/com/greate/community/controller/DataController.java index a541a38..eca7c87 100644 --- a/src/main/java/com/greate/community/controller/DataController.java +++ b/src/main/java/com/greate/community/controller/DataController.java @@ -1,15 +1,19 @@ package com.greate.community.controller; +import com.greate.community.entity.Result; import com.greate.community.service.DataService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.*; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.Date; +import java.util.HashMap; +import java.util.Map; /** * 网站数据 @@ -23,6 +27,8 @@ public class DataController { /** * 进入统计界面 * @return + * + * 前端直接跳转到/site/admin/data */ @RequestMapping(value = "/data", method = {RequestMethod.GET, RequestMethod.POST}) public String getDataPage() { @@ -34,16 +40,30 @@ public class DataController { * @param start * @param end * @return + * + * */ @PostMapping("/data/uv") - public String getUV(@DateTimeFormat(pattern = "yyyy-MM-dd") Date start, - @DateTimeFormat(pattern = "yyyy-MM-dd") Date end, - Model model) { - long uv = dataService.calculateUV(start, end); - model.addAttribute("uvResult", uv); - model.addAttribute("uvStartDate", start); - model.addAttribute("uvEndDate", end); - return "forward:/data"; + @ResponseBody + public Result getUV(@RequestBody Map map) throws ParseException { + String start = map.get("start"); + String end = map.get("end"); + + HashMap hashMap = new HashMap<>(); + + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); + long uv = dataService.calculateUV(format.parse(start), format.parse(end)); +// model.addAttribute("uvResult", uv); + hashMap.put("uvResult", uv); + +// model.addAttribute("uvStartDate", start); + hashMap.put("uvStartDate", start); + +// model.addAttribute("uvEndDate", end); + hashMap.put("uvEndDate", end); + +// return "forward:/data"; + return new Result("success", Result.SUCCESS, hashMap); } /** @@ -53,14 +73,26 @@ public class DataController { * @return */ @PostMapping("/data/dau") - public String getDAU(@DateTimeFormat(pattern = "yyyy-MM-dd") Date start, - @DateTimeFormat(pattern = "yyyy-MM-dd") Date end, - Model model) { - long dau = dataService.calculateDAU(start, end); - model.addAttribute("dauResult", dau); - model.addAttribute("dauStartDate", start); - model.addAttribute("dauEndDate", end); - return "forward:/data"; + @ResponseBody + public Result getDAU(@RequestBody Map map) throws ParseException { + String start = map.get("start"); + String end = map.get("end"); + + HashMap hashMap = new HashMap<>(); + + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); + long dau = dataService.calculateUV(format.parse(start), format.parse(end)); +// model.addAttribute("dauResult", dau); + hashMap.put("dauResult", dau); + +// model.addAttribute("dauStartDate", start); + hashMap.put("dauStartDate", start); + +// model.addAttribute("dauEndDate", end); + hashMap.put("dauEndDate", end); + +// return "forward:/data"; + return new Result("success", Result.SUCCESS, hashMap); } } diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index b21e39f..062526a 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -66,6 +66,8 @@ public class DiscussPostController implements CommunityConstant { /** * 进入帖子发布页 * @return + * + * 前端点击直接跳转到/site/discuss-publish页面,无传入参数也无返回参数 */ @GetMapping("/publish") public String getPublishPage () { @@ -76,10 +78,11 @@ public class DiscussPostController implements CommunityConstant { * markdown 图片上传 * @param file * @return + * */ @PostMapping("/uploadMdPic") @ResponseBody - public String uploadMdPic(@RequestParam(value = "editormd-image-file", required = false) MultipartFile file) { + public Result uploadMdPic(@RequestParam(value = "editormd-image-file", required = false) MultipartFile file) { String url = null; // 图片访问地址 try { @@ -101,24 +104,29 @@ public class DiscussPostController implements CommunityConstant { url = domain + contextPath + "/editor-md-upload/" + fileName; } catch (Exception e) { e.printStackTrace(); - return CommunityUtil.getEditorMdJSONString(0, "上传失败", url); +// return CommunityUtil.getEditorMdJSONString(0, "上传失败", url); + return new Result("fail",Result.INTERNAL_SERVER_ERROR,url); } - return CommunityUtil.getEditorMdJSONString(1, "上传成功", url); +// return CommunityUtil.getEditorMdJSONString(1, "上传成功", url); + return new Result("success",Result.SUCCESS,url); } /** * 添加帖子(发帖) - * @param title - * @param content * @return + * */ @PostMapping("/add") @ResponseBody - public String addDiscussPost(@NotEmpty(message = "文章标题不能为空") String title, String content) { + public Result addDiscussPost(HashMap map) { + String title = map.get("title"); + String content = map.get("content"); + User user = hostHolder.getUser(); if (user == null) { - return CommunityUtil.getJSONString(403, "您还未登录"); +// return CommunityUtil.getJSONString(403, "您还未登录"); + return new Result("forbidden","403","您还未登录"+"---"+title+"---"+content); } DiscussPost discussPost = new DiscussPost(); @@ -141,7 +149,8 @@ public class DiscussPostController implements CommunityConstant { String redisKey = RedisKeyUtil.getPostScoreKey(); redisTemplate.opsForSet().add(redisKey, discussPost.getId()); - return CommunityUtil.getJSONString(0, "发布成功"); +// return CommunityUtil.getJSONString(0, "发布成功"); + return new Result("success","200","发布成功"); } /** @@ -151,22 +160,32 @@ public class DiscussPostController implements CommunityConstant { * @return */ @GetMapping("/detail/{discussPostId}") - public String getDiscussPost(@PathVariable("discussPostId") int discussPostId, Model model, Page page) { + @ResponseBody + public Result getDiscussPost(@PathVariable("discussPostId") int discussPostId, Model model,@RequestBody Page page) { + HashMap resultMap=new HashMap<>(); + // 帖子 DiscussPost discussPost = discussPostService.findDiscussPostById(discussPostId); String content = HtmlUtils.htmlUnescape(discussPost.getContent()); // 内容反转义,不然 markDown 格式无法显示 discussPost.setContent(content); - model.addAttribute("post", discussPost); +// model.addAttribute("post", discussPost); + resultMap.put("post",discussPost); + // 作者 User user = userService.findUserById(discussPost.getUserId()); - model.addAttribute("user", user); +// model.addAttribute("user", user); + resultMap.put("user",user); + // 点赞数量 long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, discussPostId); - model.addAttribute("likeCount", likeCount); +// model.addAttribute("likeCount", likeCount); + resultMap.put("likeCount",likeCount); + // 当前登录用户的点赞状态 int likeStatus = hostHolder.getUser() == null ? 0 : likeService.findEntityLikeStatus(hostHolder.getUser().getId(), ENTITY_TYPE_POST, discussPostId); - model.addAttribute("likeStatus", likeStatus); +// model.addAttribute("likeStatus", likeStatus); + resultMap.put("likeStatus",likeStatus); // 评论分页信息 page.setLimit(5); @@ -213,7 +232,7 @@ public class DiscussPostController implements CommunityConstant { } } commentVo.put("replys", replyVoList); - + // 每个评论对应的回复数量 int replyCount = commentService.findCommentCount(ENTITY_TYPE_COMMENT, comment.getId()); commentVo.put("replyCount", replyCount); @@ -222,20 +241,24 @@ public class DiscussPostController implements CommunityConstant { } } - model.addAttribute("comments", commentVoList); - - return "/site/discuss-detail"; +// model.addAttribute("comments", commentVoList); + resultMap.put("comments",commentVoList); +// return "/site/discuss-detail"; + return new Result("success",Result.SUCCESS,resultMap); } /** * 置顶帖子 - * @param id * @return + * */ @PostMapping("/top") @ResponseBody - public String updateTop(int id, int type) { + public Result updateTop(@RequestBody HashMap map) { + int id = map.get("id"); + int type = map.get("type"); + discussPostService.updateType(id, type); // 触发发帖事件,通过消息队列将其存入 Elasticsearch 服务器 @@ -246,18 +269,20 @@ public class DiscussPostController implements CommunityConstant { .setEntityId(id); eventProducer.fireEvent(event); - return CommunityUtil.getJSONString(0); +// return CommunityUtil.getJSONString(0); + return new Result("success",Result.SUCCESS,""); } /** * 加精帖子 - * @param id * @return */ @PostMapping("/wonderful") @ResponseBody - public String setWonderful(int id) { + public Result setWonderful(@RequestBody HashMap map) { + int id = map.get("id"); + discussPostService.updateStatus(id, 1); // 触发发帖事件,通过消息队列将其存入 Elasticsearch 服务器 @@ -272,18 +297,19 @@ public class DiscussPostController implements CommunityConstant { String redisKey = RedisKeyUtil.getPostScoreKey(); redisTemplate.opsForSet().add(redisKey, id); - return CommunityUtil.getJSONString(0); +// return CommunityUtil.getJSONString(0); + return new Result("success",Result.SUCCESS,""); } /** * 删除帖子 - * @param id * @return */ @PostMapping("/delete") @ResponseBody - public String setDelete(int id) { + public Result setDelete(@RequestBody HashMap map) { + int id = map.get("id"); discussPostService.updateStatus(id, 2); // 触发删帖事件,通过消息队列更新 Elasticsearch 服务器 @@ -294,7 +320,8 @@ public class DiscussPostController implements CommunityConstant { .setEntityId(id); eventProducer.fireEvent(event); - return CommunityUtil.getJSONString(0); +// return CommunityUtil.getJSONString(0); + return new Result("success",Result.SUCCESS,"删除成功"); } diff --git a/src/main/java/com/greate/community/controller/FollowController.java b/src/main/java/com/greate/community/controller/FollowController.java index 5981e42..63681dc 100644 --- a/src/main/java/com/greate/community/controller/FollowController.java +++ b/src/main/java/com/greate/community/controller/FollowController.java @@ -2,6 +2,7 @@ package com.greate.community.controller; import com.greate.community.entity.Event; import com.greate.community.entity.Page; +import com.greate.community.entity.Result; import com.greate.community.entity.User; import com.greate.community.event.EventProducer; import com.greate.community.service.FollowService; @@ -12,11 +13,9 @@ import com.greate.community.util.HostHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -40,13 +39,15 @@ public class FollowController implements CommunityConstant{ /** * 关注 - * @param entityType - * @param entityId * @return + * */ @PostMapping("/follow") @ResponseBody - public String follow(int entityType, int entityId) { + public Result follow(@RequestBody HashMap map) { + int entityType = map.get("entityType"); + int entityId = map.get("entityId"); + User user = hostHolder.getUser(); followService.follow(user.getId(), entityType, entityId); @@ -60,23 +61,26 @@ public class FollowController implements CommunityConstant{ .setEntityUserId(entityId); eventProducer.fireEvent(event); - return CommunityUtil.getJSONString(0, "已关注"); +// return CommunityUtil.getJSONString(0, "已关注"); + return new Result("success",Result.SUCCESS,"已关注"); } /** * 取消关注 - * @param entityType - * @param entityId * @return */ @PostMapping("/unfollow") @ResponseBody - public String unfollow(int entityType, int entityId) { + public Result unfollow(@RequestBody HashMap map) { + int entityType = map.get("entityType"); + int entityId = map.get("entityId"); + User user = hostHolder.getUser(); followService.unfollow(user.getId(), entityType, entityId); - return CommunityUtil.getJSONString(0, "已取消关注"); +// return CommunityUtil.getJSONString(0, "已取消关注"); + return new Result("success",Result.SUCCESS,"已取消关注"); } /** @@ -87,12 +91,16 @@ public class FollowController implements CommunityConstant{ * @return */ @GetMapping("/followees/{userId}") - public String getFollowees(@PathVariable("userId") int userId, Page page, Model model) { + @ResponseBody + public Result getFollowees(@PathVariable("userId") int userId,@RequestBody Page page, Model model) { + HashMap hashMap = new HashMap<>(); + User user = userService.findUserById(userId); if (user == null) { throw new RuntimeException("该用户不存在"); } - model.addAttribute("user", user); +// model.addAttribute("user", user); + hashMap.put("user", user);//正在查看的用户信息 page.setLimit(5); page.setPath("/followees/" + userId); @@ -108,9 +116,11 @@ public class FollowController implements CommunityConstant{ } } - model.addAttribute("users", userList); +// model.addAttribute("users", userList); + hashMap.put("users", userList);//正在查看的用户所关注的用户列表 - return "/site/followee"; +// return "/site/followee"; + return new Result("success", Result.SUCCESS, hashMap); } /** @@ -121,12 +131,16 @@ public class FollowController implements CommunityConstant{ * @return */ @GetMapping("/followers/{userId}") - public String getFollowers(@PathVariable("userId") int userId, Page page, Model model) { + @ResponseBody + public Result getFollowers(@PathVariable("userId") int userId,@RequestBody Page page, Model model) { + HashMap hashMap = new HashMap<>(); + User user = userService.findUserById(userId); if (user == null) { throw new RuntimeException("该用户不存在"); } - model.addAttribute("user", user); +// model.addAttribute("user", user); + hashMap.put("user", user);//正在查看的用户信息 page.setLimit(5); page.setPath("/followers/" + userId); @@ -142,9 +156,11 @@ public class FollowController implements CommunityConstant{ } } - model.addAttribute("users", userList); +// model.addAttribute("users", userList); + hashMap.put("users", userList);//正在查看的用户的粉丝列表 - return "/site/follower"; +// return "/site/follower"; + return new Result("success",Result.SUCCESS,hashMap); } /** diff --git a/src/main/java/com/greate/community/controller/IndexController.java b/src/main/java/com/greate/community/controller/IndexController.java index af14757..5fc98e8 100644 --- a/src/main/java/com/greate/community/controller/IndexController.java +++ b/src/main/java/com/greate/community/controller/IndexController.java @@ -2,6 +2,7 @@ package com.greate.community.controller; import com.greate.community.entity.DiscussPost; import com.greate.community.entity.Page; +import com.greate.community.entity.Result; import com.greate.community.entity.User; import com.greate.community.service.DiscussPostService; import com.greate.community.service.LikeService; @@ -11,7 +12,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; import java.util.ArrayList; import java.util.HashMap; @@ -46,7 +49,10 @@ public class IndexController implements CommunityConstant { * @return */ @GetMapping("/index") - public String getIndexPage(Model model, Page page, @RequestParam(name = "orderMode", defaultValue = "0") int orderMode) { + @ResponseBody + public Result getIndexPage(Model model,@RequestBody Page page, @RequestParam(name = "orderMode", defaultValue = "0") int orderMode) { + HashMap hashMap = new HashMap<>(); + // 获取总页数 page.setRows(discussPostService.findDiscussPostRows(0)); page.setPath("/index?orderMode=" + orderMode); @@ -67,29 +73,32 @@ public class IndexController implements CommunityConstant { discussPosts.add(map); } } - model.addAttribute("discussPosts", discussPosts); - model.addAttribute("orderMode", orderMode); - return "index"; - } - +// model.addAttribute("discussPosts", discussPosts); +// model.addAttribute("orderMode", orderMode); + hashMap.put("discussPosts", discussPosts); + hashMap.put("orderMode", orderMode); - /** - * 进入 500 错误界面 - * @return - */ - @GetMapping("/error") - public String getErrorPage() { - return "/error/500"; +// return "index"; + return new Result("success",Result.SUCCESS,hashMap); } - /** - * 没有权限访问时的错误界面(也是 404) - * @return - */ - @GetMapping("/denied") - public String getDeniedPage() { - return "/error/404"; - } +// /** +// * 进入 500 错误界面 +// * @return +// */ +// @GetMapping("/error") +// public String getErrorPage() { +// return "/error/500"; +// } +// +// /** +// * 没有权限访问时的错误界面(也是 404) +// * @return +// */ +// @GetMapping("/denied") +// public String getDeniedPage() { +// return "/error/404"; +// } } diff --git a/src/main/java/com/greate/community/entity/Result.java b/src/main/java/com/greate/community/entity/Result.java index 10b0b17..c6fed28 100644 --- a/src/main/java/com/greate/community/entity/Result.java +++ b/src/main/java/com/greate/community/entity/Result.java @@ -18,7 +18,7 @@ public class Result { /** * 失败, 服务器未能理解请求 */ - public static final String FAIL = "200"; + public static final String FAIL = "400"; /** * 未认证(签名错误) diff --git a/src/main/resources/templates/site/profile.html b/src/main/resources/templates/site/profile.html index d2bb50f..0da08b1 100644 --- a/src/main/resources/templates/site/profile.html +++ b/src/main/resources/templates/site/profile.html @@ -46,7 +46,7 @@ 注册于
- + -- Gitee From aec9f4ac24d07cc67694b0d5c78d0ad53c00641b Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Fri, 28 Jan 2022 21:11:48 +0800 Subject: [PATCH 002/125] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E5=8F=8A=E5=AE=89=E5=85=A8=E8=AE=A4=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 19 +- .../community/config/KaptchaConfig.java | 37 -- .../community/config/SecurityConfig.java | 48 +- .../greate/community/config/WebMvcConfig.java | 6 - .../community/controller/BaseController.java | 19 + .../community/controller/LikeController.java | 63 ++- .../community/controller/LoginController.java | 420 +++++++++++------- .../controller/MessageController.java | 276 ++++++++++-- .../controller/SearchController.java | 47 +- .../community/controller/UserController.java | 211 +++++++-- .../controller/advice/ExceptionAdvice.java | 19 +- .../interceptor/LoginTicketInterceptor.java | 195 ++++---- .../filter/AuthenticationTokenFilter.java | 61 +++ .../greate/community/service/UserService.java | 83 ++-- .../community/util/CommunityConstant.java | 2 +- .../com/greate/community/util/EmailUtil.java | 198 +++++++++ .../resources/application-develop.properties | 25 +- .../resources/application-produce.properties | 12 +- .../java/com/greate/community/MailTests.java | 26 +- 19 files changed, 1236 insertions(+), 531 deletions(-) delete mode 100644 src/main/java/com/greate/community/config/KaptchaConfig.java create mode 100644 src/main/java/com/greate/community/controller/BaseController.java create mode 100644 src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java create mode 100644 src/main/java/com/greate/community/util/EmailUtil.java diff --git a/pom.xml b/pom.xml index 9765fdc..af48f8f 100644 --- a/pom.xml +++ b/pom.xml @@ -31,10 +31,10 @@ - - org.springframework.boot - spring-boot-starter-thymeleaf - + + + + @@ -149,6 +149,17 @@ 2.7.0 + + cn.hutool + hutool-all + 5.7.20 + + + + org.projectlombok + lombok + + diff --git a/src/main/java/com/greate/community/config/KaptchaConfig.java b/src/main/java/com/greate/community/config/KaptchaConfig.java deleted file mode 100644 index 997e18d..0000000 --- a/src/main/java/com/greate/community/config/KaptchaConfig.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.greate.community.config; - -import com.google.code.kaptcha.Producer; -import com.google.code.kaptcha.impl.DefaultKaptcha; -import com.google.code.kaptcha.util.Config; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import java.util.Properties; - -/** - * Kaptcha 配置类(验证码) - */ -@Configuration -public class KaptchaConfig { - - @Bean - public Producer kaptchaProducer() { - Properties properties = new Properties(); - properties.setProperty("kaptcha.image.width", "100"); - properties.setProperty("kaptcha.image.height", "40"); - properties.setProperty("kaptcha.textproducer.font.size", "32"); - properties.setProperty("kaptcha.textproducer.font.color", "black"); - // 随机生成字符的范围 - properties.setProperty("kaptcha.textproducer.char.string", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"); - // 生成几个字符 - properties.setProperty("kaptcha.textproducer.char.length", "4"); - // 添加噪声 - properties.setProperty("kaptcha.textproducer.noise.impl", "com.google.code.kaptcha.impl.NoNoise"); - - DefaultKaptcha kaptcha = new DefaultKaptcha(); - Config config = new Config(properties); - kaptcha.setConfig(config); - return kaptcha; - } - -} diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index e413d47..3afb60e 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -1,7 +1,9 @@ package com.greate.community.config; +import com.greate.community.filter.AuthenticationTokenFilter; import com.greate.community.util.CommunityConstant; import com.greate.community.util.CommunityUtil; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -10,6 +12,7 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -20,8 +23,12 @@ import java.io.PrintWriter; @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter implements CommunityConstant { + @Autowired + private AuthenticationTokenFilter authenticationTokenFilter; + /** * 静态资源 + * * @param web * @throws Exception */ @@ -32,17 +39,18 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm // 认证环节我们使用自己的代码 LoginController,绕过 Spring Security 的 - /** * 授权 + * * @param http * @throws Exception */ @Override protected void configure(HttpSecurity http) throws Exception { - http.authorizeRequests() + http.cors().and().csrf().disable() + .authorizeRequests() .antMatchers( - "/user/setting", + "/user/setting", "/user/upload", "/discuss/add", "/discuss/publish", @@ -60,7 +68,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm ) .antMatchers( - "/discuss/top", + "/discuss/top", "/discuss/wonderful" ) .hasAnyAuthority( @@ -80,40 +88,28 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm .and().csrf().disable(); + //添加jwt认证器 + http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); // 权限不够时的处理 http.exceptionHandling() // 1. 未登录时的处理 .authenticationEntryPoint(new AuthenticationEntryPoint() { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException { - String xRequestedWith = request.getHeader("x-requested-with"); - if ("XMLHttpRequest".equals(xRequestedWith)) { - // 异步请求 - response.setContentType("application/plain;charset=utf-8"); - PrintWriter writer = response.getWriter(); - writer.write(CommunityUtil.getJSONString(403, "你还没有登录")); - } - else { - // 普通请求 - response.sendRedirect(request.getContextPath() + "/login"); - } + // 异步请求 + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/plain;charset=utf-8"); + response.getWriter().write(CommunityUtil.getJSONString(403, "你还没有登录")); } }) // 2. 权限不够时的处理 .accessDeniedHandler(new AccessDeniedHandler() { @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException { - String xRequestedWith = request.getHeader("x-requested-with"); - if ("XMLHttpRequest".equals(xRequestedWith)) { - // 异步请求 - response.setContentType("application/plain;charset=utf-8"); - PrintWriter writer = response.getWriter(); - writer.write(CommunityUtil.getJSONString(403, "你没有访问该功能的权限")); - } - else { - // 普通请求 - response.sendRedirect(request.getContextPath() + "/denied"); - } + // 异步请求 + response.setContentType("application/plain;charset=utf-8"); + PrintWriter writer = response.getWriter(); + writer.write(CommunityUtil.getJSONString(403, "你没有访问该功能的权限")); } }); diff --git a/src/main/java/com/greate/community/config/WebMvcConfig.java b/src/main/java/com/greate/community/config/WebMvcConfig.java index fc270bb..9e06584 100644 --- a/src/main/java/com/greate/community/config/WebMvcConfig.java +++ b/src/main/java/com/greate/community/config/WebMvcConfig.java @@ -1,7 +1,6 @@ package com.greate.community.config; import com.greate.community.controller.interceptor.DataInterceptor; -import com.greate.community.controller.interceptor.LoginTicketInterceptor; import com.greate.community.controller.interceptor.MessageInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; @@ -15,9 +14,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebMvcConfig implements WebMvcConfigurer { - @Autowired - private LoginTicketInterceptor loginTicketInterceptor; - @Autowired private MessageInterceptor messageInterceptor; @@ -27,8 +23,6 @@ public class WebMvcConfig implements WebMvcConfigurer { // 对除静态资源外所有路径进行拦截 @Override public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(loginTicketInterceptor) - .excludePathPatterns("/css/**", "/js/**", "/img/**", "/editor-md/**", "/editor-md-upload/**"); registry.addInterceptor(messageInterceptor) .excludePathPatterns("/css/**", "/js/**", "/img/**", "/editor-md/**", "/editor-md-upload/**"); diff --git a/src/main/java/com/greate/community/controller/BaseController.java b/src/main/java/com/greate/community/controller/BaseController.java new file mode 100644 index 0000000..79ef913 --- /dev/null +++ b/src/main/java/com/greate/community/controller/BaseController.java @@ -0,0 +1,19 @@ +package com.greate.community.controller; + +import com.greate.community.entity.User; +import org.springframework.security.core.context.SecurityContextHolder; + +/** + * 类名称:BaseController + * 类描述:控制类基类 + * 创建人:CSUpipixia + * 创建时间:2022/1/28 13:54 + * + * @version v1.0 + */ +public class BaseController { + + protected User getUser() { + return (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + } +} diff --git a/src/main/java/com/greate/community/controller/LikeController.java b/src/main/java/com/greate/community/controller/LikeController.java index 47a6224..df2fef9 100644 --- a/src/main/java/com/greate/community/controller/LikeController.java +++ b/src/main/java/com/greate/community/controller/LikeController.java @@ -1,6 +1,7 @@ package com.greate.community.controller; import com.greate.community.entity.Event; +import com.greate.community.entity.Result; import com.greate.community.entity.User; import com.greate.community.event.EventProducer; import com.greate.community.service.LikeService; @@ -8,22 +9,24 @@ import com.greate.community.util.CommunityConstant; import com.greate.community.util.CommunityUtil; import com.greate.community.util.HostHolder; import com.greate.community.util.RedisKeyUtil; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + import java.util.HashMap; import java.util.Map; /** * 点赞 */ -@Controller -public class LikeController implements CommunityConstant { - - @Autowired - private HostHolder hostHolder; +@Slf4j +@RestController +public class LikeController extends BaseController implements CommunityConstant { @Autowired private LikeService likeService; @@ -36,16 +39,19 @@ public class LikeController implements CommunityConstant { /** * 点赞 - * @param entityType - * @param entityId + * + * @param entityType 点赞实体对象 1-帖子 2-评论 + * @param entityId 点赞对象id * @param entityUserId 赞的帖子/评论的作者 id - * @param postId 帖子的 id (点赞了哪个帖子,点赞的评论属于哪个帖子,点赞的回复属于哪个帖子) + * @param postId 帖子的 id (点赞了哪个帖子,点赞的评论属于哪个帖子,点赞的回复属于哪个帖子) * @return */ @PostMapping("/like") @ResponseBody - public String like(int entityType, int entityId, int entityUserId, int postId) { - User user = hostHolder.getUser(); + public Result like(int entityType, int entityId, int entityUserId, int postId) { + User user = getUser(); + + log.info("点赞用户: " + user.toString()); // 点赞 likeService.like(user.getId(), entityType, entityId, entityUserId); // 点赞数量 @@ -61,7 +67,7 @@ public class LikeController implements CommunityConstant { if (likeStatus == 1) { Event event = new Event() .setTopic(TOPIC_LIKE) - .setUserId(hostHolder.getUser().getId()) + .setUserId(getUser().getId()) .setEntityType(entityType) .setEntityId(entityId) .setEntityUserId(entityUserId) @@ -75,7 +81,40 @@ public class LikeController implements CommunityConstant { redisTemplate.opsForSet().add(redisKey, postId); } - return CommunityUtil.getJSONString(0, null, map); + return new Result("success", Result.SUCCESS, map); } +// public String like(int entityType, int entityId, int entityUserId, int postId) { +// User user = hostHolder.getUser(); +// // 点赞 +// likeService.like(user.getId(), entityType, entityId, entityUserId); +// // 点赞数量 +// long likeCount = likeService.findEntityLikeCount(entityType, entityId); +// // 点赞状态 +// int likeStatus = likeService.findEntityLikeStatus(user.getId(), entityType, entityId); +// +// Map map = new HashMap<>(); +// map.put("likeCount", likeCount); +// map.put("likeStatus", likeStatus); +// +// // 触发点赞事件(系统通知) - 取消点赞不通知 +// if (likeStatus == 1) { +// Event event = new Event() +// .setTopic(TOPIC_LIKE) +// .setUserId(hostHolder.getUser().getId()) +// .setEntityType(entityType) +// .setEntityId(entityId) +// .setEntityUserId(entityUserId) +// .setData("postId", postId); +// eventProducer.fireEvent(event); +// } +// +// if (entityType == ENTITY_TYPE_POST) { +// // 计算帖子分数 +// String redisKey = RedisKeyUtil.getPostScoreKey(); +// redisTemplate.opsForSet().add(redisKey, postId); +// } +// +// return CommunityUtil.getJSONString(0, null, map); +// } } diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index 638a8d3..77aac2b 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -1,10 +1,14 @@ package com.greate.community.controller; +import cn.hutool.captcha.CaptchaUtil; +import cn.hutool.captcha.LineCaptcha; +import cn.hutool.core.lang.UUID; +import com.alibaba.fastjson.JSONObject; import com.google.code.kaptcha.Producer; +import com.greate.community.entity.Result; import com.greate.community.entity.User; import com.greate.community.service.UserService; import com.greate.community.util.CommunityConstant; -import com.greate.community.util.CommunityUtil; import com.greate.community.util.RedisKeyUtil; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -13,15 +17,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; -import javax.imageio.ImageIO; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; -import java.awt.image.BufferedImage; -import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.constraints.NotEmpty; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -29,134 +28,168 @@ import java.util.concurrent.TimeUnit; /** * 登录、登出、注册 */ -@Controller -public class LoginController implements CommunityConstant { +@RestController +public class LoginController extends BaseController implements CommunityConstant { private static final Logger logger = LoggerFactory.getLogger(LoginController.class); @Autowired private UserService userService; - @Autowired - private Producer kaptchaProducer; - @Autowired private RedisTemplate redisTemplate; @Value("${server.servlet.context-path}") private String contextPath; - /** - * 进入注册界面 - * @return - */ - @GetMapping("/register") - public String getRegisterPage() { - return "site/register"; - } + @Value("${bbs.captcha-enable}") + private boolean captchaEnable; - /** - * 进入登录界面 - * @return - */ - @GetMapping("/login") - public String getLoginPage() { - return "site/login"; - } - - /** - * 进入重置密码界面 - */ - @GetMapping("/resetPwd") - public String getResetPwdPage() { - return "site/reset-pwd"; - } +// /** +// * 进入注册界面 +// * +// * @return +// */ +// @GetMapping("/register") +// public String getRegisterPage() { +// return "site/register"; +// } +// +// /** +// * 进入登录界面 +// * +// * @return +// */ +// @GetMapping("/login") +// public String getLoginPage() { +// return "site/login"; +// } +// +// /** +// * 进入重置密码界面 +// */ +// @GetMapping("/resetPwd") +// public String getResetPwdPage() { +// return "site/reset-pwd"; +// } /** * 注册用户 - * @param model + * * @param user * @return */ @PostMapping("/register") - public String register(Model model, User user) { + public Result register(@RequestBody User user) { Map map = userService.register(user); if (map == null || map.isEmpty()) { - model.addAttribute("msg", "注册成功, 我们已经向您的邮箱发送了一封激活邮件,请尽快激活!"); - model.addAttribute("target", "/index"); - return "/site/operate-result"; + return new Result("success", Result.SUCCESS, "注册成功, 我们已经向您的邮箱发送了一封激活邮件,请尽快激活!"); } else { - model.addAttribute("usernameMsg", map.get("usernameMsg")); - model.addAttribute("passwordMsg", map.get("passwordMsg")); - model.addAttribute("emailMsg", map.get("emailMsg")); - return "/site/register"; + return new Result("fail", Result.FAIL, map); } } +// public String register(Model model, User user) { +// Map map = userService.register(user); +// if (map == null || map.isEmpty()) { +// model.addAttribute("msg", "注册成功, 我们已经向您的邮箱发送了一封激活邮件,请尽快激活!"); +// model.addAttribute("target", "/index"); +// return "/site/operate-result"; +// } else { +// model.addAttribute("usernameMsg", map.get("usernameMsg")); +// model.addAttribute("passwordMsg", map.get("passwordMsg")); +// model.addAttribute("emailMsg", map.get("emailMsg")); +// return "/site/register"; +// } +// } /** * 激活用户 - * @param model + * * @param userId - * @param code 激活码 - * @return - * http://localhost:8080/echo/activation/用户id/激活码 + * @param code 激活码 + * @return http://localhost:8080/echo/activation/用户id/激活码 */ @GetMapping("/activation/{userId}/{code}") - public String activation(Model model, @PathVariable("userId") int userId, +// public String activation(Model model, @PathVariable("userId") int userId, +// @PathVariable("code") String code) { +// int result = userService.activation(userId, code); +// if (result == ACTIVATION_SUCCESS) { +// model.addAttribute("msg", "激活成功, 您的账号已经可以正常使用!"); +// model.addAttribute("target", "/login"); +// } +// else if (result == ACTIVATION_REPEAT) { +// model.addAttribute("msg", "无效的操作, 您的账号已被激活过!"); +// model.addAttribute("target", "/index"); +// } +// else { +// model.addAttribute("msg", "激活失败, 您提供的激活码不正确!"); +// model.addAttribute("target", "/index"); +// } +// return "/site/operate-result"; +// } + public Result activation(@PathVariable("userId") int userId, @PathVariable("code") String code) { int result = userService.activation(userId, code); if (result == ACTIVATION_SUCCESS) { - model.addAttribute("msg", "激活成功, 您的账号已经可以正常使用!"); - model.addAttribute("target", "/login"); - } - else if (result == ACTIVATION_REPEAT) { - model.addAttribute("msg", "无效的操作, 您的账号已被激活过!"); - model.addAttribute("target", "/index"); - } - else { - model.addAttribute("msg", "激活失败, 您提供的激活码不正确!"); - model.addAttribute("target", "/index"); + return new Result("success", Result.SUCCESS, "激活成功, 您的账号已经可以正常使用!"); + } else if (result == ACTIVATION_REPEAT) { + return new Result("fail", "1", "无效的操作, 您的账号已被激活过!"); + } else { + return new Result("fail", "2", "激活失败, 您提供的激活码不正确!"); } - return "/site/operate-result"; } /** * 生成验证码, 并存入 Redis - * @param response */ - @GetMapping("/kaptcha") - public void getKaptcha(HttpServletResponse response) { - // 生成验证码 - String text = kaptchaProducer.createText(); // 生成随机字符 - System.out.println("验证码:" + text); - BufferedImage image = kaptchaProducer.createImage(text); // 生成图片 - - // 验证码的归属者 - String kaptchaOwner = CommunityUtil.generateUUID(); - Cookie cookie = new Cookie("kaptchaOwner", kaptchaOwner); - cookie.setMaxAge(60); - cookie.setPath(contextPath); - response.addCookie(cookie); + @GetMapping("/captcha") + public Result getCaptcha() { + //定义图形验证码的长和宽 // 4位验证码 + LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(137, 40, 4, 80); + lineCaptcha.createCode(); //生成code + // 将验证码存入 redis - String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner); - redisTemplate.opsForValue().set(redisKey, text, 60, TimeUnit.SECONDS); + String captchaToken = UUID.fastUUID().toString(); + String redisKey = RedisKeyUtil.getKaptchaKey(captchaToken); + redisTemplate.opsForValue().set(redisKey, lineCaptcha.getCode(), 60, TimeUnit.SECONDS); - // 将图片输出给浏览器 - response.setContentType("image/png"); - try { - ServletOutputStream os = response.getOutputStream(); - ImageIO.write(image, "png", os); - } catch (IOException e) { - logger.error("响应验证码失败", e.getMessage()); - } + JSONObject result = new JSONObject(); + result.put("imageBase64Data", lineCaptcha.getImageBase64Data()); + result.put("captchaToken", captchaToken); + return new Result("success", Result.SUCCESS, result); } +// public void getKaptcha(HttpServletResponse response) { +// // 生成验证码 +// String text = kaptchaProducer.createText(); // 生成随机字符 +// System.out.println("验证码:" + text); +// BufferedImage image = kaptchaProducer.createImage(text); // 生成图片 +// +// // 验证码的归属者 +// String kaptchaOwner = CommunityUtil.generateUUID(); +// Cookie cookie = new Cookie("kaptchaOwner", kaptchaOwner); +// cookie.setMaxAge(60); +// cookie.setPath(contextPath); +// response.addCookie(cookie); +// // 将验证码存入 redis +// String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner); +// redisTemplate.opsForValue().set(redisKey, text, 60, TimeUnit.SECONDS); +// +// // 将图片输出给浏览器 +// response.setContentType("image/png"); +// try { +// ServletOutputStream os = response.getOutputStream(); +// ImageIO.write(image, "png", os); +// } catch (IOException e) { +// logger.error("响应验证码失败", e.getMessage()); +// } +// } /** * 验证用户输入的图片验证码是否和redis中存入的是否相等 * * @param kaptchaOwner 从 cookie 中取出的 kaptchaOwner - * @param checkCode 用户输入的图片验证码 + * @param checkCode 用户输入的图片验证码 * @return 失败则返回原因, 验证成功返回 "", */ private String checkKaptchaCode(String kaptchaOwner, String checkCode) { @@ -175,32 +208,32 @@ public class LoginController implements CommunityConstant { /** * 用户登录 - * @param username 用户名 - * @param password 密码 - * @param code 验证码 - * @param rememberMe 是否记住我(点击记住我后,凭证的有效期延长) - * @param model - * @param kaptchaOwner 从 cookie 中取出的 kaptchaOwner - * @param response + * + * @param username 用户名 + * @param password 密码 + * @param code 验证码 + * @param rememberMe 是否记住我(点击记住我后,凭证的有效期延长) + * @param captchaToken 验证码标识 * @return */ @PostMapping("/login") - public String login(@RequestParam("username") String username, + public Result login(@RequestParam("username") String username, @RequestParam("password") String password, @RequestParam("code") String code, - @RequestParam(value = "rememberMe", required = false) boolean rememberMe, - Model model, HttpServletResponse response, - @CookieValue("kaptchaOwner") String kaptchaOwner) { + @RequestParam("rememberMe") boolean rememberMe, + @RequestParam("captchaToken") String captchaToken) { // 检查验证码 - String kaptcha = null; - if (StringUtils.isNotBlank(kaptchaOwner)) { - String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner); - kaptcha = (String) redisTemplate.opsForValue().get(redisKey); - } + if (captchaEnable) { + String captcha = null; + if (StringUtils.isNotBlank(captchaToken)) { + String redisKey = RedisKeyUtil.getKaptchaKey(captchaToken); + captcha = (String) redisTemplate.opsForValue().get(redisKey); + } + + if (StringUtils.isBlank(captcha) || StringUtils.isBlank(code) || !captcha.equalsIgnoreCase(code)) { - if (StringUtils.isBlank(kaptcha) || StringUtils.isBlank(code) || !kaptcha.equalsIgnoreCase(code)) { - model.addAttribute("codeMsg", "验证码错误"); - return "/site/login"; + return new Result("fail", "1", "验证码错误"); + } } // 凭证过期时间(是否记住我) @@ -208,31 +241,60 @@ public class LoginController implements CommunityConstant { // 验证用户名和密码 Map map = userService.login(username, password, expiredSeconds); if (map.containsKey("ticket")) { - // 账号和密码均正确,则服务端会生成 ticket,浏览器通过 cookie 存储 ticket - Cookie cookie = new Cookie("ticket", map.get("ticket").toString()); - cookie.setPath(contextPath); // cookie 有效范围 - cookie.setMaxAge(expiredSeconds); - response.addCookie(cookie); - return "redirect:/index"; + String ticket = map.get("ticket").toString(); + return new Result("success", Result.SUCCESS, ticket); } else { - model.addAttribute("usernameMsg", map.get("usernameMsg")); - model.addAttribute("passwordMsg", map.get("passwordMsg")); - return "/site/login"; + return new Result("fail", "2", map); } - } +// public String login(@RequestParam("username") String username, +// @RequestParam("password") String password, +// @RequestParam("code") String code, +// @RequestParam(value = "rememberMe", required = false) boolean rememberMe, +// Model model, HttpServletResponse response, +// @CookieValue("kaptchaOwner") String kaptchaOwner) { +// // 检查验证码 +// String kaptcha = null; +// if (StringUtils.isNotBlank(kaptchaOwner)) { +// String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner); +// kaptcha = (String) redisTemplate.opsForValue().get(redisKey); +// } +// +// if (StringUtils.isBlank(kaptcha) || StringUtils.isBlank(code) || !kaptcha.equalsIgnoreCase(code)) { +// model.addAttribute("codeMsg", "验证码错误"); +// return "/site/login"; +// } +// +// // 凭证过期时间(是否记住我) +// int expiredSeconds = rememberMe ? REMEMBER_EXPIRED_SECONDS : DEFAULT_EXPIRED_SECONDS; +// // 验证用户名和密码 +// Map map = userService.login(username, password, expiredSeconds); +// if (map.containsKey("ticket")) { +// // 账号和密码均正确,则服务端会生成 ticket,浏览器通过 cookie 存储 ticket +// Cookie cookie = new Cookie("ticket", map.get("ticket").toString()); +// cookie.setPath(contextPath); // cookie 有效范围 +// cookie.setMaxAge(expiredSeconds); +// response.addCookie(cookie); +// return "redirect:/index"; +// } else { +// model.addAttribute("usernameMsg", map.get("usernameMsg")); +// model.addAttribute("passwordMsg", map.get("passwordMsg")); +// return "/site/login"; +// } +// } /** * 用户登出 - * @param ticket 设置凭证状态为无效 + * * @return */ @GetMapping("/logout") - public String logout(@CookieValue("ticket") String ticket) { + public Result logout(HttpServletRequest request) { + String ticket = request.getHeader("ticket"); userService.logout(ticket); SecurityContextHolder.clearContext(); - return "redirect:/login"; + return new Result("success", Result.SUCCESS, "退出成功"); } /** @@ -240,76 +302,114 @@ public class LoginController implements CommunityConstant { */ @PostMapping("/resetPwd") @ResponseBody - public Map resetPwd(@RequestParam("username") String username, - @RequestParam("password") String password, - @RequestParam("emailVerifyCode") String emailVerifyCode, - @RequestParam("kaptchaCode") String kaptcha, - Model model, - @CookieValue("kaptchaOwner") String kaptchaOwner) { + public Result resetPwd(@RequestParam("email") String email, + @RequestParam("password") String password, + @RequestParam("emailVerifyCode") String emailVerifyCode) { Map map = new HashMap<>(4); - // 检查图片验证码 - String kaptchaCheckRst = checkKaptchaCode(kaptchaOwner, kaptcha); - if (StringUtils.isNotBlank(kaptchaCheckRst)) { - map.put("status", "1"); - map.put("errMsg", kaptchaCheckRst); - } // 检查邮件验证码 - String emailVerifyCodeCheckRst = checkRedisResetPwdEmailCode(username, emailVerifyCode); + String emailVerifyCodeCheckRst = checkRedisResetPwdEmailCode(email, emailVerifyCode); if (StringUtils.isNotBlank(emailVerifyCodeCheckRst)) { - map.put("status", "1"); map.put("errMsg", emailVerifyCodeCheckRst); + return new Result("fail", "1", map); } // 执行重置密码操作 - Map stringObjectMap = userService.doResetPwd(username, password); + Map stringObjectMap = userService.doResetPwd(email, password); String usernameMsg = (String) stringObjectMap.get("errMsg"); if (StringUtils.isBlank(usernameMsg)) { - map.put("status", "0"); - map.put("msg", "重置密码成功!"); - map.put("target", "/login"); + return new Result("success", Result.SUCCESS, "重置密码成功!"); } - return map; + return new Result("fail", "1", map); } +// public Map resetPwd(@RequestParam("username") String username, +// @RequestParam("password") String password, +// @RequestParam("emailVerifyCode") String emailVerifyCode, +// @RequestParam("kaptchaCode") String kaptcha, +// Model model, +// @CookieValue("kaptchaOwner") String kaptchaOwner) { +// Map map = new HashMap<>(4); +// // 检查图片验证码 +// String kaptchaCheckRst = checkKaptchaCode(kaptchaOwner, kaptcha); +// if (StringUtils.isNotBlank(kaptchaCheckRst)) { +// map.put("status", "1"); +// map.put("errMsg", kaptchaCheckRst); +// } +// // 检查邮件验证码 +// String emailVerifyCodeCheckRst = checkRedisResetPwdEmailCode(username, emailVerifyCode); +// if (StringUtils.isNotBlank(emailVerifyCodeCheckRst)) { +// map.put("status", "1"); +// map.put("errMsg", emailVerifyCodeCheckRst); +// } +// // 执行重置密码操作 +// Map stringObjectMap = userService.doResetPwd(username, password); +// String usernameMsg = (String) stringObjectMap.get("errMsg"); +// if (StringUtils.isBlank(usernameMsg)) { +// map.put("status", "0"); +// map.put("msg", "重置密码成功!"); +// map.put("target", "/login"); +// } +// return map; +// } /** * 发送邮件验证码(用于重置密码) * - * @param kaptchaOwner 从 cookie 中取出的 kaptchaOwner - * @param kaptcha 用户输入的图片验证码 - * @param username 用户输入的需要找回的账号 + * @param captchaToken + * @param captchaCode + * @param email */ @PostMapping("/sendEmailCodeForResetPwd") @ResponseBody - public Map sendEmailCodeForResetPwd(Model model, @CookieValue("kaptchaOwner") String kaptchaOwner, - @RequestParam("kaptcha") String kaptcha, - @RequestParam("username") String username) { + public Result sendEmailCodeForResetPwd(@RequestParam("captchaToken") String captchaToken, + @RequestParam("captchaCode") String captchaCode, + @RequestParam("email") String email) { Map map = new HashMap<>(3); - // 检查图片验证码 - String kaptchaCheckRst = checkKaptchaCode(kaptchaOwner, kaptcha); - if (StringUtils.isNotBlank(kaptchaCheckRst)) { - map.put("status", "1"); - map.put("errMsg", kaptchaCheckRst); + + if (captchaEnable) { + // 检查图片验证码 + String kaptchaCheckRst = checkKaptchaCode(captchaToken, captchaCode); + if (StringUtils.isNotBlank(kaptchaCheckRst)) { + return new Result("fail", "1", "验证码错误"); + } } - Map stringObjectMap = userService.doSendEmailCode4ResetPwd(username); - String usernameMsg = (String) stringObjectMap.get("errMsg"); - if (StringUtils.isBlank(usernameMsg)) { - map.put("status", "0"); - map.put("msg", "已经往您的邮箱发送了一封验证码邮件, 请查收!"); + + Map stringObjectMap = userService.doSendEmailCode4ResetPwd(email); + String errMsg = (String) stringObjectMap.get("errMsg"); + if (StringUtils.isNotBlank(errMsg)) { + return new Result("fail", "2", errMsg); } - return map; + return new Result("success", Result.SUCCESS, "发送邮箱成功!"); } +// public Map sendEmailCodeForResetPwd(Model model, @CookieValue("kaptchaOwner") String kaptchaOwner, +// @RequestParam("kaptcha") String kaptcha, +// @RequestParam("username") String username) { +// Map map = new HashMap<>(3); +// // 检查图片验证码 +// String kaptchaCheckRst = checkKaptchaCode(kaptchaOwner, kaptcha); +// if (StringUtils.isNotBlank(kaptchaCheckRst)) { +// map.put("status", "1"); +// map.put("errMsg", kaptchaCheckRst); +// } +// Map stringObjectMap = userService.doSendEmailCode4ResetPwd(username); +// String usernameMsg = (String) stringObjectMap.get("errMsg"); +// if (StringUtils.isBlank(usernameMsg)) { +// map.put("status", "0"); +// map.put("msg", "已经往您的邮箱发送了一封验证码邮件, 请查收!"); +// } +// return map; +// } /** * 检查 邮件 验证码 * - * @param username 用户名 - * @param checkCode 用户输入的图片验证码 + * @param email 邮箱 + * @param checkCode 用户输入的邮箱验证码 * @return 验证成功 返回"", 失败则返回原因 */ - private String checkRedisResetPwdEmailCode(String username, String checkCode) { + private String checkRedisResetPwdEmailCode(String email, String checkCode) { if (StringUtils.isBlank(checkCode)) { return "未发现输入的邮件验证码"; } - final String redisKey = "EmailCode4ResetPwd:" + username; + final String redisKey = "EmailCode4ResetPwd:" + email; String emailVerifyCodeInRedis = (String) redisTemplate.opsForValue().get(redisKey); if (StringUtils.isBlank(emailVerifyCodeInRedis)) { return "邮件验证码已过期"; diff --git a/src/main/java/com/greate/community/controller/MessageController.java b/src/main/java/com/greate/community/controller/MessageController.java index d6e099b..974c098 100644 --- a/src/main/java/com/greate/community/controller/MessageController.java +++ b/src/main/java/com/greate/community/controller/MessageController.java @@ -3,6 +3,7 @@ package com.greate.community.controller; import com.alibaba.fastjson.JSONObject; import com.greate.community.entity.Message; import com.greate.community.entity.Page; +import com.greate.community.entity.Result; import com.greate.community.entity.User; import com.greate.community.service.MessageService; import com.greate.community.service.UserService; @@ -19,11 +20,8 @@ import java.util.*; /** * 私信/系统通知 */ -@Controller -public class MessageController implements CommunityConstant { - - @Autowired - private HostHolder hostHolder; +@RestController +public class MessageController extends BaseController implements CommunityConstant { @Autowired private MessageService messageService; @@ -33,26 +31,27 @@ public class MessageController implements CommunityConstant { /** * 私信列表 - * @param model * @param page * @return */ @GetMapping("/letter/list") - public String getLetterList(Model model, Page page) { + public Result getLetterList(Page page) { // Integer.valueOf("abc"); // 测试统一异常处理(普通请求) + JSONObject jsonObject = new JSONObject(); // 获取当前登录用户信息 - User user = hostHolder.getUser(); + User user = getUser(); // 分页信息 page.setLimit(5); page.setPath("/letter/list"); + // 查询会话总数 page.setRows(messageService.findConversationCout(user.getId())); // 私信列表 List conversationList = messageService.findConversations( user.getId(), page.getOffset(), page.getLimit()); List> conversations = new ArrayList<>(); - if (conversationList != null) { + if (conversationList != null && !conversationList.isEmpty()) { for (Message message : conversationList) { Map map = new HashMap<>(); map.put("conversation", message); // 私信 @@ -66,27 +65,67 @@ public class MessageController implements CommunityConstant { conversations.add(map); } } - model.addAttribute("conversations", conversations); + jsonObject.put("conversations", conversations); - // 查询当前用户的所有未读消息数量 + // 查询当前用户的所有未读私信数量 int letterUnreadCount = messageService.findLetterUnreadCount(user.getId(), null); - model.addAttribute("letterUnreadCount", letterUnreadCount); + jsonObject.put("letterUnreadCount", letterUnreadCount); + // 查询当前用户的所有未读系统通知数量 int noticeUnreadCount = messageService.findNoticeUnReadCount(user.getId(), null); - model.addAttribute("noticeUnreadCount", noticeUnreadCount); - - return "/site/letter"; + jsonObject.put("noticeUnreadCount", noticeUnreadCount); + return new Result("success", Result.SUCCESS, jsonObject); } +// public String getLetterList(Model model, Page page) { +// // Integer.valueOf("abc"); // 测试统一异常处理(普通请求) +// +// // 获取当前登录用户信息 +// User user = hostHolder.getUser(); +// // 分页信息 +// page.setLimit(5); +// page.setPath("/letter/list"); +// page.setRows(messageService.findConversationCout(user.getId())); +// // 私信列表 +// List conversationList = messageService.findConversations( +// user.getId(), page.getOffset(), page.getLimit()); +// +// List> conversations = new ArrayList<>(); +// if (conversationList != null) { +// for (Message message : conversationList) { +// Map map = new HashMap<>(); +// map.put("conversation", message); // 私信 +// map.put("letterCount", messageService.findLetterCount( +// message.getConversationId())); // 私信数量 +// map.put("unreadCount", messageService.findLetterUnreadCount( +// user.getId(), message.getConversationId())); // 未读私信数量 +// int targetId = user.getId() == message.getFromId() ? message.getToId() : message.getFromId(); +// map.put("target", userService.findUserById(targetId)); // 私信对方 +// +// conversations.add(map); +// } +// } +// model.addAttribute("conversations", conversations); +// +// // 查询当前用户的所有未读消息数量 +// int letterUnreadCount = messageService.findLetterUnreadCount(user.getId(), null); +// model.addAttribute("letterUnreadCount", letterUnreadCount); +// int noticeUnreadCount = messageService.findNoticeUnReadCount(user.getId(), null); +// model.addAttribute("noticeUnreadCount", noticeUnreadCount); +// +// return "/site/letter"; +// +// } /** * 私信详情页 * @param conversationId * @param page - * @param model * @return */ @GetMapping("/letter/detail/{conversationId}") - public String getLetterDetail(@PathVariable("conversationId") String conversationId, Page page, Model model) { + public Result getLetterDetail(@PathVariable("conversationId") String conversationId, Page page) { + JSONObject jsonObject = new JSONObject(); + // 分页信息 page.setLimit(5); page.setPath("/letter/detail/" + conversationId); @@ -96,7 +135,7 @@ public class MessageController implements CommunityConstant { List letterList = messageService.findLetters(conversationId, page.getOffset(), page.getLimit()); List> letters = new ArrayList<>(); - if (letterList != null) { + if (letterList != null && !letterList.isEmpty()) { for (Message message : letterList) { Map map = new HashMap<>(); map.put("letter", message); @@ -104,10 +143,10 @@ public class MessageController implements CommunityConstant { letters.add(map); } } - model.addAttribute("letters", letters); + jsonObject.put("letters", letters); // 私信目标 - model.addAttribute("target", getLetterTarget(conversationId)); + jsonObject.put("target", getLetterTarget(conversationId)); // 将私信列表中的未读消息改为已读 List ids = getUnreadLetterIds(letterList); @@ -115,8 +154,39 @@ public class MessageController implements CommunityConstant { messageService.readMessage(ids); } - return "/site/letter-detail"; + return new Result("success", Result.SUCCESS, jsonObject); } +// public String getLetterDetail(@PathVariable("conversationId") String conversationId, Page page, Model model) { +// // 分页信息 +// page.setLimit(5); +// page.setPath("/letter/detail/" + conversationId); +// page.setRows(messageService.findLetterCount(conversationId)); +// +// // 私信列表 +// List letterList = messageService.findLetters(conversationId, page.getOffset(), page.getLimit()); +// +// List> letters = new ArrayList<>(); +// if (letterList != null) { +// for (Message message : letterList) { +// Map map = new HashMap<>(); +// map.put("letter", message); +// map.put("fromUser", userService.findUserById(message.getFromId())); +// letters.add(map); +// } +// } +// model.addAttribute("letters", letters); +// +// // 私信目标 +// model.addAttribute("target", getLetterTarget(conversationId)); +// +// // 将私信列表中的未读消息改为已读 +// List ids = getUnreadLetterIds(letterList); +// if (!ids.isEmpty()) { +// messageService.readMessage(ids); +// } +// +// return "/site/letter-detail"; +// } /** * 获取私信对方对象 @@ -128,7 +198,7 @@ public class MessageController implements CommunityConstant { int id0 = Integer.parseInt(ids[0]); int id1 = Integer.parseInt(ids[1]); - if (hostHolder.getUser().getId() == id0) { + if (getUser().getId() == id0) { return userService.findUserById(id1); } else { @@ -147,7 +217,7 @@ public class MessageController implements CommunityConstant { if (letterList != null) { for (Message message : letterList) { // 当前用户是私信的接收者且该私信处于未读状态 - if (hostHolder.getUser().getId() == message.getToId() && message.getStatus() == 0) { + if (getUser().getId() == message.getToId() && message.getStatus() == 0) { ids.add(message.getId()); } } @@ -158,21 +228,20 @@ public class MessageController implements CommunityConstant { /** * 发送私信 - * @param toName 收信人 username + * @param userId 收信人 userId * @param content 内容 * @return */ @PostMapping("/letter/send") @ResponseBody - public String sendLetter(String toName, String content) { - // Integer.valueOf("abc"); // 测试统一异常处理(异步请求) - User target = userService.findUserByName(toName); + public Result sendLetter(int userId, String content) { + User target = userService.findUserById(userId); if (target == null) { - return CommunityUtil.getJSONString(1, "目标用户不存在"); + return new Result("fail", "1", "目标用户不存在!"); } Message message = new Message(); - message.setFromId(hostHolder.getUser().getId()); + message.setFromId(getUser().getId()); message.setToId(target.getId()); if (message.getFromId() < message.getToId()) { message.setConversationId(message.getFromId() + "_" + message.getToId()); @@ -186,17 +255,17 @@ public class MessageController implements CommunityConstant { messageService.addMessage(message); - return CommunityUtil.getJSONString(0); + return new Result("success", Result.SUCCESS, "发送成功"); } /** * 通知列表(只显示最新一条消息) - * @param model * @return */ @GetMapping("/notice/list") - public String getNoticeList(Model model) { - User user = hostHolder.getUser(); + public Result getNoticeList() { + JSONObject jsonObject = new JSONObject(); + User user = getUser(); // 查询评论类通知 Message message = messageService.findLatestNotice(user.getId(), TOPIC_COMMNET); @@ -220,7 +289,7 @@ public class MessageController implements CommunityConstant { int unread = messageService.findNoticeUnReadCount(user.getId(), TOPIC_COMMNET); messageVO.put("unread", unread); - model.addAttribute("commentNotice", messageVO); + jsonObject.put("commentNotice", messageVO); } // 查询点赞类通知 @@ -244,7 +313,7 @@ public class MessageController implements CommunityConstant { int unread = messageService.findNoticeUnReadCount(user.getId(), TOPIC_LIKE); messageVO.put("unread", unread); - model.addAttribute("likeNotice", messageVO); + jsonObject.put("likeNotice", messageVO); } // 查询关注类通知 @@ -267,33 +336,116 @@ public class MessageController implements CommunityConstant { int unread = messageService.findNoticeUnReadCount(user.getId(), TOPIC_FOLLOW); messageVO.put("unread", unread); - model.addAttribute("followNotice", messageVO); + jsonObject.put("followNotice", messageVO); } // 查询未读消息数量 int letterUnreadCount = messageService.findLetterUnreadCount(user.getId(), null); - model.addAttribute("letterUnreadCount", letterUnreadCount); + jsonObject.put("letterUnreadCount", letterUnreadCount); int noticeUnreadCount = messageService.findNoticeUnReadCount(user.getId(), null); - model.addAttribute("noticeUnreadCount", noticeUnreadCount); + jsonObject.put("noticeUnreadCount", noticeUnreadCount); - return "/site/notice"; + return new Result("success", Result.SUCCESS, jsonObject); } +// public String getNoticeList(Model model) { +// User user = hostHolder.getUser(); +// +// // 查询评论类通知 +// Message message = messageService.findLatestNotice(user.getId(), TOPIC_COMMNET); +// // 封装通知需要的各种数据 +// if (message != null) { +// Map messageVO = new HashMap<>(); +// +// messageVO.put("message", message); +// +// String content = HtmlUtils.htmlUnescape(message.getContent()); +// Map data = JSONObject.parseObject(content, HashMap.class); +// +// messageVO.put("user", userService.findUserById((Integer) data.get("userId"))); +// messageVO.put("entityType", data.get("entityType")); +// messageVO.put("entityId", data.get("entityId")); +// messageVO.put("postId", data.get("postId")); +// +// int count = messageService.findNoticeCount(user.getId(), TOPIC_COMMNET); +// messageVO.put("count", count); +// +// int unread = messageService.findNoticeUnReadCount(user.getId(), TOPIC_COMMNET); +// messageVO.put("unread", unread); +// +// model.addAttribute("commentNotice", messageVO); +// } +// +// // 查询点赞类通知 +// message = messageService.findLatestNotice(user.getId(), TOPIC_LIKE); +// if (message != null) { +// Map messageVO = new HashMap<>(); +// +// messageVO.put("message", message); +// +// String content = HtmlUtils.htmlUnescape(message.getContent()); +// Map data = JSONObject.parseObject(content, HashMap.class); +// +// messageVO.put("user", userService.findUserById((Integer) data.get("userId"))); +// messageVO.put("entityType", data.get("entityType")); +// messageVO.put("entityId", data.get("entityId")); +// messageVO.put("postId", data.get("postId")); +// +// int count = messageService.findNoticeCount(user.getId(), TOPIC_LIKE); +// messageVO.put("count", count); +// +// int unread = messageService.findNoticeUnReadCount(user.getId(), TOPIC_LIKE); +// messageVO.put("unread", unread); +// +// model.addAttribute("likeNotice", messageVO); +// } +// +// // 查询关注类通知 +// message = messageService.findLatestNotice(user.getId(), TOPIC_FOLLOW); +// if (message != null) { +// Map messageVO = new HashMap<>(); +// +// messageVO.put("message", message); +// +// String content = HtmlUtils.htmlUnescape(message.getContent()); +// Map data = JSONObject.parseObject(content, HashMap.class); +// +// messageVO.put("user", userService.findUserById((Integer) data.get("userId"))); +// messageVO.put("entityType", data.get("entityType")); +// messageVO.put("entityId", data.get("entityId")); +// +// int count = messageService.findNoticeCount(user.getId(), TOPIC_FOLLOW); +// messageVO.put("count", count); +// +// int unread = messageService.findNoticeUnReadCount(user.getId(), TOPIC_FOLLOW); +// messageVO.put("unread", unread); +// +// model.addAttribute("followNotice", messageVO); +// } +// +// // 查询未读消息数量 +// int letterUnreadCount = messageService.findLetterUnreadCount(user.getId(), null); +// model.addAttribute("letterUnreadCount", letterUnreadCount); +// int noticeUnreadCount = messageService.findNoticeUnReadCount(user.getId(), null); +// model.addAttribute("noticeUnreadCount", noticeUnreadCount); +// +// return "/site/notice"; +// } /** * 查询某个主题所包含的通知列表 * @param topic * @param page - * @param model * @return */ @GetMapping("/notice/detail/{topic}") - public String getNoticeDetail(@PathVariable("topic") String topic, Page page, Model model) { - User user = hostHolder.getUser(); + public Result getNoticeDetail(@PathVariable("topic") String topic, Page page) { + User user = getUser(); page.setLimit(5); page.setPath("/notice/detail/" + topic); page.setRows(messageService.findNoticeCount(user.getId(), topic)); + // 查询某个主题所包含的通知列表 List noticeList = messageService.findNotices(user.getId(), topic,page.getOffset(), page.getLimit()); List> noticeVoList = new ArrayList<>(); if (noticeList != null) { @@ -314,7 +466,6 @@ public class MessageController implements CommunityConstant { noticeVoList.add(map); } } - model.addAttribute("notices", noticeVoList); // 设置已读 List ids = getUnreadLetterIds(noticeList); @@ -322,6 +473,43 @@ public class MessageController implements CommunityConstant { messageService.readMessage(ids); } - return "/site/notice-detail"; + return new Result("success", Result.SUCCESS, noticeVoList); } +// public String getNoticeDetail(@PathVariable("topic") String topic, Page page, Model model) { +// User user = hostHolder.getUser(); +// +// page.setLimit(5); +// page.setPath("/notice/detail/" + topic); +// page.setRows(messageService.findNoticeCount(user.getId(), topic)); +// +// List noticeList = messageService.findNotices(user.getId(), topic,page.getOffset(), page.getLimit()); +// List> noticeVoList = new ArrayList<>(); +// if (noticeList != null) { +// for (Message notice : noticeList) { +// Map map = new HashMap<>(); +// // 通知 +// map.put("notice", notice); +// // 内容 +// String content = HtmlUtils.htmlUnescape(notice.getContent()); +// Map data = JSONObject.parseObject(content, HashMap.class); +// map.put("user", userService.findUserById((Integer) data.get("userId"))); +// map.put("entityType", data.get("entityType")); +// map.put("entityId", data.get("entityId")); +// map.put("postId", data.get("postId")); +// // 发送系统通知的作者 +// map.put("fromUser", userService.findUserById(notice.getFromId())); +// +// noticeVoList.add(map); +// } +// } +// model.addAttribute("notices", noticeVoList); +// +// // 设置已读 +// List ids = getUnreadLetterIds(noticeList); +// if (!ids.isEmpty()) { +// messageService.readMessage(ids); +// } +// +// return "/site/notice-detail"; +// } } diff --git a/src/main/java/com/greate/community/controller/SearchController.java b/src/main/java/com/greate/community/controller/SearchController.java index df7f228..8f820fb 100644 --- a/src/main/java/com/greate/community/controller/SearchController.java +++ b/src/main/java/com/greate/community/controller/SearchController.java @@ -1,24 +1,24 @@ package com.greate.community.controller; +import com.alibaba.fastjson.JSONObject; import com.greate.community.entity.DiscussPost; import com.greate.community.entity.Page; -import com.greate.community.service.DiscussPostService; import com.greate.community.service.ElasticsearchService; import com.greate.community.service.LikeService; import com.greate.community.service.UserService; import com.greate.community.util.CommunityConstant; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.*; /** * 搜索 */ -@Controller -public class SearchController implements CommunityConstant { +@RestController +public class SearchController extends BaseController implements CommunityConstant { @Autowired private ElasticsearchService elasticsearchService; @@ -34,14 +34,14 @@ public class SearchController implements CommunityConstant { * search?keword=xxx * @param keyword 关键词 * @param page - * @param model * @return */ @GetMapping("/search") - public String search(String keyword, Page page, Model model) { + public String search(String keyword, Page page) { + JSONObject jsonObject = new JSONObject(); // 搜索帖子 (Spring 提供的 Page 当前页码从 0 开始计数) org.springframework.data.domain.Page searchResult = - elasticsearchService.searchDiscussPost(keyword, page.getCurrent()-1, page.getLimit()); + elasticsearchService.searchDiscussPost(keyword, page.getCurrent()-1, page.getLimit()); // 聚合数据 List> discussPosts = new ArrayList<>(); if (searchResult != null) { @@ -58,8 +58,8 @@ public class SearchController implements CommunityConstant { } } - model.addAttribute("discussPosts", discussPosts); - model.addAttribute("keyword", keyword); + jsonObject.put("keyword", keyword); + jsonObject.put("discussPosts", discussPosts); // 设置分页 page.setPath("/search?keyword="+ keyword); @@ -67,6 +67,35 @@ public class SearchController implements CommunityConstant { return "/site/search"; } +// public String search(String keyword, Page page, Model model) { +// // 搜索帖子 (Spring 提供的 Page 当前页码从 0 开始计数) +// org.springframework.data.domain.Page searchResult = +// elasticsearchService.searchDiscussPost(keyword, page.getCurrent()-1, page.getLimit()); +// // 聚合数据 +// List> discussPosts = new ArrayList<>(); +// if (searchResult != null) { +// for (DiscussPost post : searchResult) { +// Map map = new HashMap<>(); +// // 帖子 +// map.put("post", post); +// // 作者 +// map.put("user", userService.findUserById(post.getUserId())); +// // 点赞数量 +// map.put("likeCount", likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId())); +// +// discussPosts.add(map); +// } +// } +// +// model.addAttribute("discussPosts", discussPosts); +// model.addAttribute("keyword", keyword); +// +// // 设置分页 +// page.setPath("/search?keyword="+ keyword); +// page.setRows(searchResult == null ? 0 : (int) searchResult.getTotalElements()); +// +// return "/site/search"; +// } } diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 4cdd1c0..835a12b 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -1,13 +1,10 @@ package com.greate.community.controller; -import com.greate.community.entity.Comment; -import com.greate.community.entity.DiscussPost; -import com.greate.community.entity.Page; -import com.greate.community.entity.User; +import com.alibaba.fastjson.JSONObject; +import com.greate.community.entity.*; import com.greate.community.service.*; import com.greate.community.util.CommunityConstant; import com.greate.community.util.CommunityUtil; -import com.greate.community.util.HostHolder; import com.qiniu.util.Auth; import com.qiniu.util.StringMap; import org.apache.commons.lang3.StringUtils; @@ -15,7 +12,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import java.util.*; @@ -24,18 +20,15 @@ import java.util.*; /** * 用户 */ -@Controller +@RestController @RequestMapping("/user") -public class UserController implements CommunityConstant { +public class UserController extends BaseController implements CommunityConstant { private static final Logger logger = LoggerFactory.getLogger(UserController.class); @Autowired private UserService userService; - @Autowired - private HostHolder hostHolder; - @Autowired private LikeService likeService; @@ -103,7 +96,7 @@ public class UserController implements CommunityConstant { // 文件在云服务器上的的访问路径 String url = headerBucketUrl + "/" + fileName; - userService.updateHeader(hostHolder.getUser().getId(), url); + userService.updateHeader(getUser().getId(), url); return CommunityUtil.getJSONString(0); @@ -113,85 +106,130 @@ public class UserController implements CommunityConstant { * 修改用户密码 * @param oldPassword 原密码 * @param newPassword 新密码 - * @param model * @return */ @PostMapping("/password") - public String updatePassword(String oldPassword, String newPassword, Model model) { + public Result updatePassword(@RequestBody String oldPassword, @RequestBody String newPassword) { // 验证原密码是否正确 - User user = hostHolder.getUser(); + User user = getUser(); String md5OldPassword = CommunityUtil.md5(oldPassword + user.getSalt()); if (!user.getPassword().equals(md5OldPassword)) { - model.addAttribute("oldPasswordError", "原密码错误"); - return "/site/setting"; + return new Result("fail", "1", "原密码错误"); } // 判断新密码是否合法 String md5NewPassword = CommunityUtil.md5(newPassword + user.getSalt()); if (user.getPassword().equals(md5NewPassword)) { - model.addAttribute("newPasswordError", "新密码和原密码相同"); - return "/site/setting"; + return new Result("fail", "2", "新密码不能和原密码相同"); } // 修改用户密码 userService.updatePassword(user.getId(), newPassword); - return "redirect:/index"; + return new Result("success", Result.SUCCESS, "修改密码成功"); } +// public String updatePassword(String oldPassword, String newPassword, Model model) { +// // 验证原密码是否正确 +// User user = hostHolder.getUser(); +// String md5OldPassword = CommunityUtil.md5(oldPassword + user.getSalt()); +// if (!user.getPassword().equals(md5OldPassword)) { +// model.addAttribute("oldPasswordError", "原密码错误"); +// return "/site/setting"; +// } +// +// // 判断新密码是否合法 +// String md5NewPassword = CommunityUtil.md5(newPassword + user.getSalt()); +// if (user.getPassword().equals(md5NewPassword)) { +// model.addAttribute("newPasswordError", "新密码和原密码相同"); +// return "/site/setting"; +// } +// +// // 修改用户密码 +// userService.updatePassword(user.getId(), newPassword); +// +// return "redirect:/index"; +// } /** * 进入个人主页 * @param userId 可以进入任意用户的个人主页 - * @param model * @return */ @GetMapping("/profile/{userId}") - public String getProfilePage(@PathVariable("userId") int userId, Model model) { + public Result getProfilePage(@PathVariable("userId") int userId) { + JSONObject jsonObject = new JSONObject(); User user = userService.findUserById(userId); if (user == null) { - throw new RuntimeException("该用户不存在"); + return new Result("fail", "1", "该用户不存在"); } // 用户 - model.addAttribute("user", user); + jsonObject.put("user", user); // 获赞数量 int userLikeCount = likeService.findUserLikeCount(userId); - model.addAttribute("userLikeCount", userLikeCount); + jsonObject.put("userLikeCount", userLikeCount); // 关注数量 long followeeCount = followService.findFolloweeCount(userId, ENTITY_TYPE_USER); - model.addAttribute("followeeCount", followeeCount); + jsonObject.put("followeeCount", followeeCount); // 粉丝数量 long followerCount = followService.findFollowerCount(ENTITY_TYPE_USER, userId); - model.addAttribute("followerCount", followerCount); + jsonObject.put("followerCount", followerCount); // 当前登录用户是否已关注该用户 boolean hasFollowed = false; - if (hostHolder.getUser() != null) { - hasFollowed = followService.hasFollowed(hostHolder.getUser().getId(), ENTITY_TYPE_USER, userId); + if (getUser() != null) { + hasFollowed = followService.hasFollowed(getUser().getId(), ENTITY_TYPE_USER, userId); } - model.addAttribute("hasFollowed", hasFollowed); - model.addAttribute("tab", "profile"); // 该字段用于指示标签栏高亮 + jsonObject.put("hasFollowed", hasFollowed); - return "/site/profile"; + return new Result("success", Result.SUCCESS, jsonObject); } +// public String getProfilePage(@PathVariable("userId") int userId, Model model) { +// JSONObject jsonObject = new JSONObject(); +// User user = userService.findUserById(userId); +// if (user == null) { +// throw new RuntimeException("该用户不存在"); +// } +// +// // 用户 +// model.addAttribute("user", user); +// // 获赞数量 +// int userLikeCount = likeService.findUserLikeCount(userId); +// model.addAttribute("userLikeCount", userLikeCount); +// // 关注数量 +// long followeeCount = followService.findFolloweeCount(userId, ENTITY_TYPE_USER); +// model.addAttribute("followeeCount", followeeCount); +// // 粉丝数量 +// long followerCount = followService.findFollowerCount(ENTITY_TYPE_USER, userId); +// model.addAttribute("followerCount", followerCount); +// // 当前登录用户是否已关注该用户 +// boolean hasFollowed = false; +// if (hostHolder.getUser() != null) { +// hasFollowed = followService.hasFollowed(hostHolder.getUser().getId(), ENTITY_TYPE_USER, userId); +// } +// model.addAttribute("hasFollowed", hasFollowed); +// model.addAttribute("tab", "profile"); // 该字段用于指示标签栏高亮 +// +// return "/site/profile"; +// } /** * 进入我的帖子(查询某个用户的帖子列表) * @param userId * @param page - * @param model * @return */ @GetMapping("/discuss/{userId}") - public String getMyDiscussPosts(@PathVariable("userId") int userId, Page page, Model model) { + public Result getMyDiscussPosts(@PathVariable("userId") int userId, Page page) { + JSONObject jsonObject = new JSONObject(); User user = userService.findUserById(userId); if (user == null) { - throw new RuntimeException("该用户不存在"); + return new Result("fail", "1", "该用户不存在"); } - model.addAttribute("user", user); + jsonObject.put("user", user); // 该用户的帖子总数 int rows = discussPostService.findDiscussPostRows(userId); - model.addAttribute("rows", rows); + jsonObject.put("rows", rows); page.setLimit(5); page.setPath("/user/discuss/" + userId); @@ -211,30 +249,63 @@ public class UserController implements CommunityConstant { discussPosts.add(map); } } - model.addAttribute("discussPosts", discussPosts); - model.addAttribute("tab", "mypost"); // 该字段用于指示标签栏高亮 + jsonObject.put("discussPosts", discussPosts); - return "/site/my-post"; + return new Result("success", Result.SUCCESS, jsonObject); } +// public String getMyDiscussPosts(@PathVariable("userId") int userId, Page page, Model model) { +// User user = userService.findUserById(userId); +// if (user == null) { +// throw new RuntimeException("该用户不存在"); +// } +// model.addAttribute("user", user); +// +// // 该用户的帖子总数 +// int rows = discussPostService.findDiscussPostRows(userId); +// model.addAttribute("rows", rows); +// +// page.setLimit(5); +// page.setPath("/user/discuss/" + userId); +// page.setRows(rows); +// +// // 分页查询(按照最新查询) +// List list = discussPostService.findDiscussPosts(userId, page.getOffset(), page.getLimit(), 0); +// // 封装帖子和该帖子对应的用户信息 +// List> discussPosts = new ArrayList<>(); +// if (list != null) { +// for (DiscussPost post : list) { +// Map map = new HashMap<>(); +// map.put("post", post); +// long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId()); +// map.put("likeCount", likeCount); +// +// discussPosts.add(map); +// } +// } +// model.addAttribute("discussPosts", discussPosts); +// model.addAttribute("tab", "mypost"); // 该字段用于指示标签栏高亮 +// +// return "/site/my-post"; +// } /** * 进入我的评论/回复(查询某个用户的评论/回复列表) * @param userId * @param page - * @param model * @return */ @GetMapping("/comment/{userId}") - public String getMyComments(@PathVariable("userId") int userId, Page page, Model model) { + public Result getMyComments(@PathVariable("userId") int userId, Page page) { + JSONObject jsonObject = new JSONObject(); User user = userService.findUserById(userId); if (user == null) { - throw new RuntimeException("该用户不存在"); + return new Result("fail", "1", "该用户不存在"); } - model.addAttribute("user", user); + jsonObject.put("user", user); // 该用户的评论/回复总数 int commentCounts = commentService.findCommentCountByUserId(userId); - model.addAttribute("commentCounts", commentCounts); + jsonObject.put("commentCounts", commentCounts); page.setLimit(5); page.setPath("/user/comment/" + userId); @@ -264,11 +335,55 @@ public class UserController implements CommunityConstant { comments.add(map); } } - model.addAttribute("comments", comments); - model.addAttribute("tab", "myreply"); // 该字段用于指示标签栏高亮 + jsonObject.put("comments", comments); - return "/site/my-reply"; + return new Result("success", Result.SUCCESS, jsonObject); } +// public String getMyComments(@PathVariable("userId") int userId, Page page, Model model) { +// User user = userService.findUserById(userId); +// if (user == null) { +// throw new RuntimeException("该用户不存在"); +// } +// model.addAttribute("user", user); +// +// // 该用户的评论/回复总数 +// int commentCounts = commentService.findCommentCountByUserId(userId); +// model.addAttribute("commentCounts", commentCounts); +// +// page.setLimit(5); +// page.setPath("/user/comment/" + userId); +// page.setRows(commentCounts); +// +// // 分页查询 +// List list = commentService.findCommentByUserId(userId, page.getOffset(), page.getLimit()); +// // 封装评论和该评论对应的帖子信息 +// List> comments = new ArrayList<>(); +// if (list != null) { +// for (Comment comment : list) { +// Map map = new HashMap<>(); +// map.put("comment", comment); +// // 显示评论/回复对应的文章信息 +// if (comment.getEntityType() == ENTITY_TYPE_POST) { +// // 如果是对帖子的评论,则直接查询 target_id 即可 +// DiscussPost post = discussPostService.findDiscussPostById(comment.getEntityId()); +// map.put("post", post); +// } +// else if (comment.getEntityType() == ENTITY_TYPE_COMMENT) { +// // 如过是对评论的回复,则先根据该回复的 target_id 查询评论的 id, 再根据该评论的 target_id 查询帖子的 id +// Comment targetComment = commentService.findCommentById(comment.getEntityId()); +// DiscussPost post = discussPostService.findDiscussPostById(targetComment.getEntityId()); +// map.put("post", post); +// } +// +// comments.add(map); +// } +// } +// model.addAttribute("comments", comments); +// model.addAttribute("tab", "myreply"); // 该字段用于指示标签栏高亮 +// +// return "/site/my-reply"; +// +// } } diff --git a/src/main/java/com/greate/community/controller/advice/ExceptionAdvice.java b/src/main/java/com/greate/community/controller/advice/ExceptionAdvice.java index 52ca9f3..b8e4b80 100644 --- a/src/main/java/com/greate/community/controller/advice/ExceptionAdvice.java +++ b/src/main/java/com/greate/community/controller/advice/ExceptionAdvice.java @@ -6,6 +6,7 @@ import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -15,7 +16,7 @@ import java.io.PrintWriter; /** * 处理服务端异常(500) */ -@ControllerAdvice(annotations = Controller.class) // 扫描带有 @Controller 的组件 +@ControllerAdvice(annotations = RestController.class) // 扫描带有 @RestController 的组件 public class ExceptionAdvice { private static final Logger logger = LoggerFactory.getLogger(ExceptionAdvice.class); @@ -26,18 +27,10 @@ public class ExceptionAdvice { for (StackTraceElement element : e.getStackTrace()) { logger.error(element.toString()); } - // 区分异步请求和普通请求 - String xRequestedWith = request.getHeader("x-requested-with"); - if ("XMLHttpRequest".equals(xRequestedWith)) { - // 异步请求(希望返回的是 JSON 数据) - response.setContentType("application/plain;charset=utf-8"); - PrintWriter writer = response.getWriter(); - writer.write(CommunityUtil.getJSONString(1, "服务器异常")); - } - else { - // 普通请求(希望返回的是一个网页) - response.sendRedirect(request.getContextPath() + "/error"); - } + + response.setContentType("application/plain;charset=utf-8"); + PrintWriter writer = response.getWriter(); + writer.write(CommunityUtil.getJSONString(500, "服务器异常: " + e.getMessage())); } } diff --git a/src/main/java/com/greate/community/controller/interceptor/LoginTicketInterceptor.java b/src/main/java/com/greate/community/controller/interceptor/LoginTicketInterceptor.java index 959f247..430ae3c 100644 --- a/src/main/java/com/greate/community/controller/interceptor/LoginTicketInterceptor.java +++ b/src/main/java/com/greate/community/controller/interceptor/LoginTicketInterceptor.java @@ -1,95 +1,100 @@ -package com.greate.community.controller.interceptor; - -import com.greate.community.entity.LoginTicket; -import com.greate.community.entity.User; -import com.greate.community.service.UserService; -import com.greate.community.util.CookieUtil; -import com.greate.community.util.HostHolder; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.context.SecurityContextImpl; -import org.springframework.stereotype.Component; -import org.springframework.web.servlet.HandlerInterceptor; -import org.springframework.web.servlet.ModelAndView; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.Date; - -@Component -public class LoginTicketInterceptor implements HandlerInterceptor { - - @Autowired - private UserService userService; - - @Autowired - private HostHolder hostHolder; - - /** - * 在 Controller 执行之前被调用 - * 检查凭证状态,若凭证有效则在本次请求中持有该用户信息 - * @param request - * @param response - * @param handler - * @return - * @throws Exception - */ - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - // 从 cookie 中获取凭证 - String ticket = CookieUtil.getValue(request, "ticket"); - if (ticket != null) { - // 查询凭证 - LoginTicket loginTicket = userService.findLoginTicket(ticket); - // 检查凭证状态(是否有效)以及是否过期 - if (loginTicket != null && loginTicket.getStatus() == 0 && loginTicket.getExpired().after(new Date())) { - // 根据凭证查询用户 - User user = userService.findUserById(loginTicket.getUserId()); - // 在本次请求中持有用户信息 - hostHolder.setUser(user); - - // 构建用户认证的结果,并存入 SecurityContext, 以便于 Spring Security 进行授权 - Authentication authentication = new UsernamePasswordAuthenticationToken( - user, user.getPassword(), userService.getAuthorities(user.getId()) - ); - SecurityContextHolder.setContext(new SecurityContextImpl(authentication)); - } - } - - return true; - } - - /** - * 在模板引擎之前被调用 - * 将用户信息存入 modelAndView, 便于模板引擎调用 - * @param request - * @param response - * @param handler - * @param modelAndView - * @throws Exception - */ - @Override - public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { - User user = hostHolder.getUser(); - if (user != null && modelAndView != null) { - modelAndView.addObject("loginUser", user); - } - } - - /** - * 在 Controller 执行之后(即服务端对本次请求做出响应后)被调用 - * 清理本次请求持有的用户信息 - * @param request - * @param response - * @param handler - * @param ex - * @throws Exception - */ - @Override - public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { - hostHolder.clear(); - SecurityContextHolder.clearContext(); - } -} +//package com.greate.community.controller.interceptor; +// +//import com.greate.community.entity.LoginTicket; +//import com.greate.community.entity.User; +//import com.greate.community.service.UserService; +//import com.greate.community.util.HostHolder; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +//import org.springframework.security.core.Authentication; +//import org.springframework.security.core.context.SecurityContextHolder; +//import org.springframework.security.core.context.SecurityContextImpl; +//import org.springframework.stereotype.Component; +//import org.springframework.web.servlet.HandlerInterceptor; +//import org.springframework.web.servlet.ModelAndView; +// +//import javax.servlet.http.HttpServletRequest; +//import javax.servlet.http.HttpServletResponse; +//import java.util.Date; +// +//@Slf4j +//@Component +//public class LoginTicketInterceptor implements HandlerInterceptor { +// +// @Autowired +// private UserService userService; +// +// @Autowired +// private HostHolder hostHolder; +// +// /** +// * 在 Controller 执行之前被调用 +// * 检查凭证状态,若凭证有效则在本次请求中持有该用户信息 +// * @param request +// * @param response +// * @param handler +// * @return +// * @throws Exception +// */ +// @Override +// public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { +// // 从 cookie 中获取凭证 +//// String ticket = CookieUtil.getValue(request, "ticket"); +// String ticket = request.getHeader("ticket"); +// log.info("request请求地址path[{}] uri[{}]", request.getServletPath(),request.getRequestURI()); +// log.info("获取ticket: " + ticket); +// if (ticket != null) { +// // 查询凭证 +// LoginTicket loginTicket = userService.findLoginTicket(ticket); +// // 检查凭证状态(是否有效)以及是否过期 +// if (loginTicket != null && loginTicket.getStatus() == 0 && loginTicket.getExpired().after(new Date())) { +// // 根据凭证查询用户 +// User user = userService.findUserById(loginTicket.getUserId()); +// log.info("用会话户信息: " + user.toString()); +// // 在本次请求中持有用户信息 +// hostHolder.setUser(user); +// +// // 构建用户认证的结果,并存入 SecurityContext, 以便于 Spring Security 进行授权 +// Authentication authentication = new UsernamePasswordAuthenticationToken( +// user, user.getPassword(), userService.getAuthorities(user.getId()) +// ); +// SecurityContextHolder.setContext(new SecurityContextImpl(authentication)); +// } +// } +// +// return true; +// } +// +// /** +// * 在模板引擎之前被调用 +// * 将用户信息存入 modelAndView, 便于模板引擎调用 +// * @param request +// * @param response +// * @param handler +// * @param modelAndView +// * @throws Exception +// */ +// @Override +// public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { +// User user = hostHolder.getUser(); +// if (user != null && modelAndView != null) { +// modelAndView.addObject("loginUser", user); +// } +// } +// +// /** +// * 在 Controller 执行之后(即服务端对本次请求做出响应后)被调用 +// * 清理本次请求持有的用户信息 +// * @param request +// * @param response +// * @param handler +// * @param ex +// * @throws Exception +// */ +// @Override +// public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { +// hostHolder.clear(); +// SecurityContextHolder.clearContext(); +// } +//} diff --git a/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java b/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java new file mode 100644 index 0000000..8ced5aa --- /dev/null +++ b/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java @@ -0,0 +1,61 @@ +package com.greate.community.filter; + +import com.greate.community.entity.LoginTicket; +import com.greate.community.entity.User; +import com.greate.community.service.UserService; +import com.greate.community.util.HostHolder; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.context.SecurityContextImpl; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Date; + +/** + * 类名称:AuthenticationTokenFilter + * 类描述:认证拦截器 + * 创建人:CSUpipixia + * 创建时间:2022/1/28 13:43 + * + * @version v1.0 + */ +@Slf4j +@Component +public class AuthenticationTokenFilter extends OncePerRequestFilter { + + @Autowired + private UserService userService; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + String ticket = request.getHeader("ticket"); + log.info("request请求地址: path[{}] uri[{}]", request.getServletPath(),request.getRequestURI()); + log.info("获取ticket: " + ticket); + if (ticket != null) { + // 查询凭证 + LoginTicket loginTicket = userService.findLoginTicket(ticket); + // 检查凭证状态(是否有效)以及是否过期 + if (loginTicket != null && loginTicket.getStatus() == 0 && loginTicket.getExpired().after(new Date())) { + // 根据凭证查询用户 + User user = userService.findUserById(loginTicket.getUserId()); + log.info("用会话户信息: " + user.toString()); + + // 构建用户认证的结果,并存入 SecurityContext, 以便于 Spring Security 进行授权 + Authentication authentication = new UsernamePasswordAuthenticationToken( + user, user.getPassword(), userService.getAuthorities(user.getId()) + ); + SecurityContextHolder.setContext(new SecurityContextImpl(authentication)); + } + } + filterChain.doFilter(request, response); + } +} diff --git a/src/main/java/com/greate/community/service/UserService.java b/src/main/java/com/greate/community/service/UserService.java index 5d9b33c..3de81d2 100644 --- a/src/main/java/com/greate/community/service/UserService.java +++ b/src/main/java/com/greate/community/service/UserService.java @@ -3,18 +3,14 @@ package com.greate.community.service; import com.greate.community.dao.UserMapper; import com.greate.community.entity.LoginTicket; import com.greate.community.entity.User; -import com.greate.community.util.CommunityConstant; -import com.greate.community.util.CommunityUtil; -import com.greate.community.util.MailClient; -import com.greate.community.util.RedisKeyUtil; +import com.greate.community.util.*; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.core.GrantedAuthority; import org.springframework.stereotype.Service; -import org.thymeleaf.TemplateEngine; -import org.thymeleaf.context.Context; import java.util.*; import java.util.concurrent.TimeUnit; @@ -23,17 +19,18 @@ import java.util.concurrent.TimeUnit; /** * 用户相关 */ +@Slf4j @Service public class UserService implements CommunityConstant { @Autowired - private UserMapper userMapper; + EmailUtil emailUtil; @Autowired - private MailClient mailClient; + private UserMapper userMapper; @Autowired - private TemplateEngine templateEngine; + private MailClient mailClient; @Autowired private RedisTemplate redisTemplate; @@ -98,14 +95,14 @@ public class UserService implements CommunityConstant { // 验证账号是否已存在 User u = userMapper.selectByName(user.getUsername()); if (u != null) { - map.put("usernameMsg", "该账号已存在"); + map.put("userExistMsg", "该账号已存在"); return map; } // 验证邮箱是否已存在 u = userMapper.selectByEmail(user.getEmail()); if (u != null) { - map.put("emailMsg", "该邮箱已被注册"); + map.put("emailExistMsg", "该邮箱已被注册"); return map; } @@ -114,20 +111,23 @@ public class UserService implements CommunityConstant { user.setPassword(CommunityUtil.md5(user.getPassword() + user.getSalt())); // 加盐加密 user.setType(0); // 默认普通用户 user.setStatus(0); // 默认未激活 - user.setActivationCode(CommunityUtil.generateUUID()); // 激活码 + + // 给注册用户发送激活邮件 + String code = emailUtil.sendRegistrationCode(user.getEmail()); + user.setActivationCode(code); // 激活码 + // 随机头像(用户登录后可以自行修改) user.setHeaderUrl(String.format("http://images.nowcoder.com/head/%dt.png", new Random().nextInt(1000))); user.setCreateTime(new Date()); // 注册时间 userMapper.insertUser(user); - // 给注册用户发送激活邮件 - Context context = new Context(); - context.setVariable("email", user.getEmail()); - // http://localhost:8080/echo/activation/用户id/激活码 - String url = domain + contextPath + "/activation/" + user.getId() + "/" + user.getActivationCode(); - context.setVariable("url", url); - String content = templateEngine.process("/mail/activation", context); - mailClient.sendMail(user.getEmail(),"激活 Echo 账号", content); +// Context context = new Context(); +// context.setVariable("email", user.getEmail()); +// // http://localhost:8080/echo/activation/用户id/激活码 +// String url = domain + contextPath + "/activation/" + user.getId() + "/" + user.getActivationCode(); +// context.setVariable("url", url); +// String content = templateEngine.process("/mail/activation", context); +// mailClient.sendMail(user.getEmail(),"激活账号", content); return map; } @@ -178,7 +178,7 @@ public class UserService implements CommunityConstant { // 验证账号 User user = userMapper.selectByName(username); if (user == null) { - map.put("usernameMsg", "该账号不存在"); + map.put("passwordMsg", "密码错误"); return map; } @@ -321,53 +321,48 @@ public class UserService implements CommunityConstant { /** * 发送邮箱验证码 - * @param account 账户名, 目前是用户名 + * @param email 账户邮箱 * * @return Map 返回错误提示消息,如果返回的 map 为空,则说明发送验证码成功 */ - public Map doSendEmailCode4ResetPwd(String account) { + public Map doSendEmailCode4ResetPwd(String email) { Map map = new HashMap<>(2); - User user = userMapper.selectByName(account); + User user = userMapper.selectByEmail(email); if (user == null) { - map.put("errMsg", "未发现账号"); - return map; - } - final String email = user.getEmail(); - if (StringUtils.isBlank(email)) { - map.put("errMsg", "该账号未绑定邮箱"); + map.put("errMsg", "该邮箱未绑定账号"); return map; } - // 生成6位验证码 - String randomCode = CommunityUtil.getRandomCode(6); // 给注册用户发送激活邮件 - Context context = new Context(); - context.setVariable("email", "您的验证码是 " + randomCode); - // http://localhost:8080/echo/activation/用户id/激活码 - String url = domain + contextPath + "/activation/" + user.getId() + "/" + user.getActivationCode(); - context.setVariable("url", url); - String content = templateEngine.process("/mail/activation", context); - mailClient.sendMail(email,"重置 Echo 账号密码", content); + String code = emailUtil.sendRetrievePasswordCode(email); + +// Context context = new Context(); +// context.setVariable("email", "您的验证码是 " + randomCode); +// // http://localhost:8080/echo/activation/用户id/激活码 +// String url = domain + contextPath + "/activation/" + user.getId() + "/" + user.getActivationCode(); +// context.setVariable("url", url); +// String content = templateEngine.process("/mail/activation", context); +// mailClient.sendMail(email,"重置账号密码", content); - final String redisKey = "EmailCode4ResetPwd:" + account; + final String redisKey = "EmailCode4ResetPwd:" + email; - redisTemplate.opsForValue().set(redisKey, randomCode, 600, TimeUnit.SECONDS); + redisTemplate.opsForValue().set(redisKey, code, 600, TimeUnit.SECONDS); return map; } /** * 发送邮箱验证码 - * @param account 账户名, 目前是用户名 + * @param email 账户邮箱 * * @return Map 返回错误提示消息,如果返回的 map 为空,则说明发送验证码成功 */ - public Map doResetPwd(String account, String password) { + public Map doResetPwd(String email, String password) { Map map = new HashMap<>(2); if (StringUtils.isBlank(password)) { map.put("errMsg", "密码不能为空"); return map; } - User user = userMapper.selectByName(account); + User user = userMapper.selectByEmail(email); if (user == null) { map.put("errMsg", "未发现账号"); return map; diff --git a/src/main/java/com/greate/community/util/CommunityConstant.java b/src/main/java/com/greate/community/util/CommunityConstant.java index cc0a638..90a6ee6 100644 --- a/src/main/java/com/greate/community/util/CommunityConstant.java +++ b/src/main/java/com/greate/community/util/CommunityConstant.java @@ -26,7 +26,7 @@ public interface CommunityConstant { // 实体类型:评论 int ENTITY_TYPE_COMMENT = 2; - // 实体类型:人 + // 实体类型:用户 int ENTITY_TYPE_USER = 3; // Kafka 主题:评论 diff --git a/src/main/java/com/greate/community/util/EmailUtil.java b/src/main/java/com/greate/community/util/EmailUtil.java new file mode 100644 index 0000000..512ecb9 --- /dev/null +++ b/src/main/java/com/greate/community/util/EmailUtil.java @@ -0,0 +1,198 @@ +package com.greate.community.util; + +import com.greate.community.controller.LoginController; +import lombok.Data; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Lazy; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +import javax.mail.MessagingException; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; +import java.io.UnsupportedEncodingException; +import java.util.Date; +import java.util.Properties; +import java.util.Random; + +/** + * 类名称:MailUtil + * 类描述:邮件服务工具类 + * 创建人:CSUpipixia + * 创建时间:2022/1/23 13:34 + * + * @version v1.0 + */ +@Data +@Component +public class EmailUtil { + + private static final Logger logger = LoggerFactory.getLogger(LoginController.class); + + private static final String SUBJECT_REGISTER = "注册验证码"; + + private static final String SUBJECT_FORGETPASSWORD = "找回密码"; + + @Value("${spring.mail.username}") + private String username; + + @Value("${spring.mail.password}") + private String password; // 授权码 + + @Value("${spring.mail.host}") + private String host; // 服务器地址 + + @Value("${spring.mail.personal}") + private String personal; // 别名 + + @Value("${spring.mail.code-expiration}") + private Long codeExpiration; // 过期时间 + + @Value("${spring.mail.reg-header}") + private String regHeader; + + @Value("${spring.mail.forget-password-header}") + private String forgetPasswordHeader; + + @Autowired + @Lazy + private RedisTemplate redisTemplate; + + /** + * 发送注册邮箱验证码 + * @param receiver + * @return + */ + public String sendRegistrationCode(String receiver) { + + String code = getRandomString(6); + + String content = getResigerEmail(receiver, code); + + sendEmail(receiver, SUBJECT_REGISTER ,content); + + return code; + } + + /** + * 发送找回密码邮箱验证码 + * @param receiver + * @return + */ + public String sendRetrievePasswordCode(String receiver) { + + String code = getRandomString(6); + + String content = getRetrievePasswordEmail(receiver, code); + + sendEmail(receiver, SUBJECT_FORGETPASSWORD, content); + + return code; + } + + /** + * 注册邮箱模板 + * @param receiver + * @param code + * @return + */ + private String getResigerEmail(String receiver, String code) { + String[] tos = receiver.split("@"); + String sub = tos[0].substring(0,2); + String email = sub+"*******@"+tos[1]; + String html = + "

账号注册验证码

" + + "
" + + "
您的注册验证码为:"+code+"
" + + "
谢谢!
" + + "
"; + return html; + } + + /** + * 注册邮箱模板 + * @param receiver + * @param code + * @return + */ + private String getRetrievePasswordEmail(String receiver, String code) { + String[] tos = receiver.split("@"); + String sub = tos[0].substring(0,2); + String email = sub+"*******@"+tos[1]; + String html = + "

找回密码验证码

" + + "
您好,您正在使用"+email+"找回密码。
" + + "
您的找回密码验证码为:"+code+"
" + + "
谢谢!
" + + ""; + return html; + } + + /** + * 获得固定长度的字符串充当验证码 + * @param length + * @return + */ + private static String getRandomString(int length) { + String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + Random random = new Random(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < length; i++) { + int number = random.nextInt(str.length()); + sb.append(str.charAt(number)); + } + return sb.toString(); + } + + private void sendEmail(String receiver, String subject, String content) { + try { + Properties properties = new Properties(); + properties.setProperty("mail.transport.protocol", "smtp"); + properties.setProperty("mail.smtp.host", host); + properties.setProperty("mail.smtp.auth", "true"); + Session session = Session.getInstance(properties); + + Transport transport = session.getTransport(); + + MimeMessage mimeMessage = new MimeMessage(session); + + // 发件人,可以设置发件人的别名 + mimeMessage.setFrom(new InternetAddress(username, personal,"UTF-8")); + // 收件人 + mimeMessage.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(receiver)); + // 主题 + mimeMessage.setSubject(subject); + // 容器类 附件 + MimeMultipart mimeMultipart = new MimeMultipart(); + // 可以包装文本,图片,附件 + MimeBodyPart bodyPart = new MimeBodyPart(); + // 设置内容 getEmailHtml是邮箱内容模板 + bodyPart.setContent(content, "text/html; charset=UTF-8"); + mimeMultipart.addBodyPart(bodyPart); + // 添加图片&附件 +// bodyPart = new MimeBodyPart(); +// bodyPart.attachFile(fileSrc); +// mimeMultipart.addBodyPart(bodyPart); + mimeMessage.setContent(mimeMultipart); + + // 时间 + mimeMessage.setSentDate(new Date()); + mimeMessage.saveChanges(); + + transport.connect(username, password); + transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients()); + + transport.close(); + + } catch (UnsupportedEncodingException | MessagingException e) { + logger.error("发送"+ subject +"邮件失败:"+ receiver +" ----"+e.getMessage()); + } + } +} diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index 52d47f0..1c66080 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -1,3 +1,6 @@ +# ???? +bbs.captcha-enable = false + # ˿ server.port = 8080 # Ŀ(Ŀ·) http://localhost:8080/...... @@ -13,7 +16,7 @@ community.path.editormdUploadPath = E:/GreateCommunity/src/main/resources/static spring.thymeleaf.cache=false # MySQL -spring.datasource.url = jdbc:mysql://gz-cdb-ejk0kptx.sql.tencentcdb.com:57734/bbs-dev?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong +spring.datasource.url = jdbc:mysql://gz-cdb-ejk0kptx.sql.tencentcdb.com:57734/bbs?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong spring.datasource.username = root spring.datasource.password = Root@2021 # Mysql 5.0+ 汾ʹ com.mysql.jdbc.Driver @@ -27,12 +30,16 @@ mybatis.configuration.useGeneratedKeys = true mybatis.configuration.mapUnderscoreToCamelCase = true # Spring Mail -spring.mail.host = smtp.sina.com -spring.mail.port = 465 -spring.mail.username = greatetest@sina.com -spring.mail.password = 88161b147d8eff41 +spring.mail.host = smtp.qq.com +spring.mail.username = xuetao1999@vip.qq.com +spring.mail.personal = HUSTer +spring.mail.password = ttgqzosyzyjmdhja spring.mail.protocol = smtps spring.mail.properties.mail.smtp.ssl.enable = true +# ??????????????????? +spring.mail.code-expiration=3600000 +spring.mail.reg-header=Register +spring.mail.forget-password-header=Register # Redis spring.redis.database = 10 @@ -48,8 +55,12 @@ spring.kafka.consumer.enable-auto-commit = true spring.kafka.consumer.auto-commit-interval = 3000 # Elasticsearch -spring.data.elasticsearch.cluster-name = community -spring.data.elasticsearch.cluster-nodes = es-50b9cgrk.public.tencentelasticsearch.com:9200 +spring.data.elasticsearch.cluster-name = elastic +spring.data.elasticsearch.cluster-nodes = 127.0.0.1:9300 +spring.data.elasticsearch.repositories.enabled = true +spring.elasticsearch.rest.uris = https://es-50b9cgrk.public.tencentelasticsearch.com:9200 +spring.elasticsearch.rest.username = elastic +spring.elasticsearch.rest.password = elastic2021. # Quartz spring.quartz.job-store-type = jdbc diff --git a/src/main/resources/application-produce.properties b/src/main/resources/application-produce.properties index 8929aee..54c848c 100644 --- a/src/main/resources/application-produce.properties +++ b/src/main/resources/application-produce.properties @@ -24,12 +24,16 @@ mybatis.configuration.useGeneratedKeys = true mybatis.configuration.mapUnderscoreToCamelCase = true # Spring Mail -spring.mail.host = smtp.sina.com -spring.mail.port = 465 -spring.mail.username = greatetest@sina.com -spring.mail.password = xxxxxxxxxxxxxxx +spring.mail.host = smtp.qq.com +spring.mail.username = csuxiaoxi@qq.com +spring.mail.personal=CSUer +spring.mail.password = scsmtmeogsgddcdg spring.mail.protocol = smtps spring.mail.properties.mail.smtp.ssl.enable = true +# ??????????????????? +spring.mail.code-expiration=3600000 +spring.mail.reg-header=Register +spring.mail.forget-password-header=Register # Redis spring.redis.database = 11 diff --git a/src/test/java/com/greate/community/MailTests.java b/src/test/java/com/greate/community/MailTests.java index eccd307..76da6c1 100644 --- a/src/test/java/com/greate/community/MailTests.java +++ b/src/test/java/com/greate/community/MailTests.java @@ -1,14 +1,14 @@ package com.greate.community; +import com.greate.community.util.EmailUtil; import com.greate.community.util.MailClient; +import lombok.ToString; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; -import org.thymeleaf.TemplateEngine; -import org.thymeleaf.context.Context; @RunWith(SpringRunner.class) @ContextConfiguration(classes = CommunityApplication.class) @@ -16,26 +16,10 @@ import org.thymeleaf.context.Context; public class MailTests { @Autowired - private MailClient mailClient; - - @Autowired - private TemplateEngine templateEngine; + private EmailUtil emailUtil; @Test - public void testTextMail() { - mailClient.sendMail("1912420914@qq.com", "TEST", "Welcome"); - + public void sendEmail() { + emailUtil.sendRegistrationCode("2224236998@qq.com"); } - - @Test - public void testHtmlMail() { - Context context = new Context(); - context.setVariable("username", "Jack"); - - String content = templateEngine.process("/mail/demo", context); - System.out.println(content); - - mailClient.sendMail("1912420914@qq.com", "HTMLTEST", content); - } - } -- Gitee From 701ccc77d6666e854e8b0fdcd58d7f1abd7b09a9 Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Sat, 29 Jan 2022 18:19:20 +0800 Subject: [PATCH 003/125] =?UTF-8?q?=E5=90=88=E5=B9=B6dev=E5=88=86=E6=94=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/greate/community/controller/DataController.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/greate/community/controller/DataController.java b/src/main/java/com/greate/community/controller/DataController.java index eca7c87..6a61c7d 100644 --- a/src/main/java/com/greate/community/controller/DataController.java +++ b/src/main/java/com/greate/community/controller/DataController.java @@ -68,8 +68,6 @@ public class DataController { /** * 统计网站 DAU - * @param start - * @param end * @return */ @PostMapping("/data/dau") -- Gitee From 466d2c2114d9a696e272ecc8598155256ab4250f Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Sun, 30 Jan 2022 22:38:09 +0800 Subject: [PATCH 004/125] =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E8=B4=A6=E5=8F=B7?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E4=B8=8E=E5=88=86=E9=A1=B5=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 22 +++ .../auth/wechatauth/domain/UserWeChat.java | 64 +++++++++ .../properties/WeChatProperties.java | 28 ++++ .../auth/wechatauth/sso/ClientResources.java | 29 ++++ .../wechatauth/sso/SocialClientResource.java | 33 +++++ .../wechat/WeChatAuthorizationConfig.java | 107 ++++++++++++++ .../WeChatOAuth2ClientContextFilter.java | 68 +++++++++ .../wechat/WeChatRequestEnhancer.java | 35 +++++ .../wechatauth/wechat/WeChatRestTemplate.java | 59 ++++++++ .../wechat/WeChatUserPrincipalExtractor.java | 34 +++++ .../community/config/SecurityConfig.java | 133 +++++++++++++++++- .../controller/DiscussPostController.java | 2 +- .../controller/FollowController.java | 4 +- .../community/controller/LoginController.java | 72 +++++++++- .../controller/MessageController.java | 12 +- .../controller/SearchController.java | 3 +- .../community/controller/UserController.java | 8 +- .../resources/application-develop.properties | 24 +++- .../java/com/greate/community/MailTests.java | 50 +++---- 19 files changed, 739 insertions(+), 48 deletions(-) create mode 100644 src/main/java/com/greate/community/auth/wechatauth/domain/UserWeChat.java create mode 100644 src/main/java/com/greate/community/auth/wechatauth/properties/WeChatProperties.java create mode 100644 src/main/java/com/greate/community/auth/wechatauth/sso/ClientResources.java create mode 100644 src/main/java/com/greate/community/auth/wechatauth/sso/SocialClientResource.java create mode 100644 src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatAuthorizationConfig.java create mode 100644 src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatOAuth2ClientContextFilter.java create mode 100644 src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatRequestEnhancer.java create mode 100644 src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatRestTemplate.java create mode 100644 src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatUserPrincipalExtractor.java diff --git a/pom.xml b/pom.xml index af48f8f..346cf1f 100644 --- a/pom.xml +++ b/pom.xml @@ -116,6 +116,13 @@ spring-boot-starter-security + + + org.springframework.security.oauth.boot + spring-security-oauth2-autoconfigure + 2.1.4.RELEASE + + org.thymeleaf.extras @@ -155,6 +162,12 @@ 5.7.20 + + + org.springframework.boot + spring-boot-configuration-processor + + org.projectlombok lombok @@ -169,6 +182,15 @@ org.springframework.boot spring-boot-maven-plugin + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + diff --git a/src/main/java/com/greate/community/auth/wechatauth/domain/UserWeChat.java b/src/main/java/com/greate/community/auth/wechatauth/domain/UserWeChat.java new file mode 100644 index 0000000..fe817b6 --- /dev/null +++ b/src/main/java/com/greate/community/auth/wechatauth/domain/UserWeChat.java @@ -0,0 +1,64 @@ +package com.greate.community.auth.wechatauth.domain; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * + * * https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842 + * *

+ * * openid 用户的唯一标识 + * * nickname 用户昵称 + * * sex 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知 + * * province 用户个人资料填写的省份 + * * city 普通用户个人资料填写的城市 + * * country 国家,如中国为CN + * * headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。 + * * privilege 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom) + * * unionid 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。 + * + * @author xzx + * @date 2022/1/29 18:32 + */ +@Data +@Accessors(chain = true) +@JsonIgnoreProperties(ignoreUnknown = true) +public class UserWeChat { + + private Integer id; + + @JsonProperty("openid") + private String openId; + + @JsonProperty("appid") + private String appId; + + @JsonProperty("nickname") + private String nickName; + + private String sex; + + private String language; + + private String city; + + private String country; + + @JsonProperty("province") + private String province; + + @JsonProperty("headimgurl") + private String headimgurl; + + @JsonProperty("bind_wechat_time") + private Long bondTime; + + @JsonProperty("update_wechat_time") + private Long updatedTime; + + @JsonProperty("unionid") + private String unionId; + +} diff --git a/src/main/java/com/greate/community/auth/wechatauth/properties/WeChatProperties.java b/src/main/java/com/greate/community/auth/wechatauth/properties/WeChatProperties.java new file mode 100644 index 0000000..dfa70b7 --- /dev/null +++ b/src/main/java/com/greate/community/auth/wechatauth/properties/WeChatProperties.java @@ -0,0 +1,28 @@ +package com.greate.community.auth.wechatauth.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author xzx + * @date 2022/1/29 18:29 + */ +@ConfigurationProperties("wechat.config") +@Component +@Data +public class WeChatProperties { + + private String appId = "appid"; + + private String clientId = "client_id"; + + private String secret = "secret"; + + private String clientSecret = "client_secret"; + + private String state = "state"; + + private String wechatRedirect = "wechat_redirect"; + +} diff --git a/src/main/java/com/greate/community/auth/wechatauth/sso/ClientResources.java b/src/main/java/com/greate/community/auth/wechatauth/sso/ClientResources.java new file mode 100644 index 0000000..2458062 --- /dev/null +++ b/src/main/java/com/greate/community/auth/wechatauth/sso/ClientResources.java @@ -0,0 +1,29 @@ +package com.greate.community.auth.wechatauth.sso; + +import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; + +/** + * oauth2 认证信息注入 + * + * @author xzx + * @date 2022/1/29 18:37 + */ +public class ClientResources { + + @NestedConfigurationProperty + private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails(); + + @NestedConfigurationProperty + private ResourceServerProperties resource = new ResourceServerProperties(); + + public AuthorizationCodeResourceDetails getClient() { + return client; + } + + public ResourceServerProperties getResource() { + return resource; + } + +} diff --git a/src/main/java/com/greate/community/auth/wechatauth/sso/SocialClientResource.java b/src/main/java/com/greate/community/auth/wechatauth/sso/SocialClientResource.java new file mode 100644 index 0000000..264a490 --- /dev/null +++ b/src/main/java/com/greate/community/auth/wechatauth/sso/SocialClientResource.java @@ -0,0 +1,33 @@ +package com.greate.community.auth.wechatauth.sso; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * + * 第三方登录授权认证 + * + * @author xzx + * @date 2022/1/29 18:38 + */ +@Configuration +public class SocialClientResource { + + /** + * wechat client config + * + * @return clientResource + */ + @Bean + @ConfigurationProperties("wechat") + public ClientResources weChat() { + return new ClientResources(); + } + + /** + * other client config + * ... + */ + +} diff --git a/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatAuthorizationConfig.java b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatAuthorizationConfig.java new file mode 100644 index 0000000..ec389b0 --- /dev/null +++ b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatAuthorizationConfig.java @@ -0,0 +1,107 @@ +package com.greate.community.auth.wechatauth.wechat; + +import com.greate.community.auth.wechatauth.sso.ClientResources; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.security.oauth2.resource.PrincipalExtractor; +import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.client.OAuth2ClientContext; +import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter; +import org.springframework.security.oauth2.client.token.RequestEnhancer; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +/** + * * https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842 + * * 微信登录流程 + * + * @author xzx + * @date 2022/1/29 18:40 + */ +@Configuration +@EnableOAuth2Client +@Order(200) +public class WeChatAuthorizationConfig { + + private static final String WE_CHAT_LOGIN_URL = "/wechat/oauth2/login";//微信认证登录的URL + private static final String WE_CHAT_AUTHENTICATION_SUCCESS_URL = "/wechat/login";//认证成功后跳转的URL + + private final OAuth2ClientContext context; + private final RequestEnhancer requestEnhancer; + private final PrincipalExtractor principalExtractor; + private final ClientResources clientResources; + + public WeChatAuthorizationConfig( + @Qualifier("oauth2ClientContext") OAuth2ClientContext context, + @Qualifier("weChatRequestEnhancer") RequestEnhancer requestEnhancer, + @Qualifier("weChatUserPrincipalExtractor") PrincipalExtractor principalExtractor, + @Qualifier("weChat") ClientResources clientResources + ) { + this.context = context; + this.requestEnhancer = requestEnhancer; + this.principalExtractor = principalExtractor; + this.clientResources = clientResources; + } + + private static List> convertMediaTypes() { + MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter(); + messageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.TEXT_PLAIN)); + return Collections.singletonList(messageConverter); + } + + private AuthorizationCodeAccessTokenProvider accessTokenProvider() { + AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider(); + provider.setAuthorizationRequestEnhancer(requestEnhancer); + provider.setTokenRequestEnhancer(requestEnhancer); + provider.setMessageConverters(WeChatAuthorizationConfig.convertMediaTypes()); + return provider; + } + + private WeChatRestTemplate restTemplate() { + WeChatRestTemplate template = new WeChatRestTemplate(clientResources.getClient(), context); + template.setAccessTokenProvider(accessTokenProvider()); + template.setMessageConverters(WeChatAuthorizationConfig.convertMediaTypes()); + return template; + } + + public OAuth2ClientAuthenticationProcessingFilter weChatFilter() { + OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(WE_CHAT_LOGIN_URL); + + + filter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler() { + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + this.setDefaultTargetUrl(WE_CHAT_AUTHENTICATION_SUCCESS_URL); + super.onAuthenticationSuccess(request, response, authentication); + } + }); + + + + WeChatRestTemplate template = restTemplate(); + filter.setRestTemplate(template); + UserInfoTokenServices tokenServices = tokenServices(template); + filter.setTokenServices(tokenServices); + return filter; + } + + private UserInfoTokenServices tokenServices(WeChatRestTemplate template) { + UserInfoTokenServices tokenServices = new UserInfoTokenServices( + clientResources.getResource().getUserInfoUri(), clientResources.getResource().getClientId()); + tokenServices.setRestTemplate(template); + tokenServices.setPrincipalExtractor(principalExtractor); + return tokenServices; + } +} diff --git a/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatOAuth2ClientContextFilter.java b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatOAuth2ClientContextFilter.java new file mode 100644 index 0000000..6c15db0 --- /dev/null +++ b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatOAuth2ClientContextFilter.java @@ -0,0 +1,68 @@ +package com.greate.community.auth.wechatauth.wechat; + +import com.greate.community.auth.wechatauth.properties.WeChatProperties; +import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter; +import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; +import org.springframework.security.web.DefaultRedirectStrategy; +import org.springframework.security.web.RedirectStrategy; +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.web.util.UriComponentsBuilder; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 扩展 OAuth2ClientContextFilter + * 重写请求的字段,按顺序设置查询参数 + *

+ * client_id -> appid,添加 #wechat_redirect + * + */ +@Component +public class WeChatOAuth2ClientContextFilter extends OAuth2ClientContextFilter { + + private RedirectStrategy redirectStrategy; + private final WeChatProperties weChatProperties; + + public WeChatOAuth2ClientContextFilter(WeChatProperties weChatProperties) { + this.weChatProperties = weChatProperties; + redirectStrategy = new DefaultRedirectStrategy(); + } + + @Override + protected void redirectUser(UserRedirectRequiredException e, HttpServletRequest request, HttpServletResponse response) throws IOException { + UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(e.getRedirectUri()); + + e.getRequestParams().put(weChatProperties.getAppId(), e.getRequestParams().remove(weChatProperties.getClientId())); + + Map> map = e.getRequestParams().entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, it -> Collections.singletonList(it.getValue()))); + map.put(weChatProperties.getState(), Collections.singletonList(e.getStateKey())); + + //按照微信接口要求,使得参数按照一定顺序排列,没按照规定顺序的话,接口会请求失败 + LinkedMultiValueMap linkedMultiValueMap = new LinkedMultiValueMap<>(); + linkedMultiValueMap.put("appid", map.remove("appid")); + linkedMultiValueMap.put("redirect_uri", map.remove("redirect_uri")); + linkedMultiValueMap.put("response_type", map.remove("response_type")); + linkedMultiValueMap.put("scope", map.remove("scope")); + linkedMultiValueMap.put("state", map.remove("state")); + + builder.queryParams(linkedMultiValueMap); + + builder.fragment(weChatProperties.getWechatRedirect()); + + this.redirectStrategy.sendRedirect(request, response, builder.build().encode().toUriString()); + } + + @Override + public void setRedirectStrategy(RedirectStrategy redirectStrategy) { + this.redirectStrategy = redirectStrategy; + } + +} diff --git a/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatRequestEnhancer.java b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatRequestEnhancer.java new file mode 100644 index 0000000..c6343d1 --- /dev/null +++ b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatRequestEnhancer.java @@ -0,0 +1,35 @@ +package com.greate.community.auth.wechatauth.wechat; + +import com.greate.community.auth.wechatauth.properties.WeChatProperties; +import lombok.extern.log4j.Log4j2; +import org.springframework.http.HttpHeaders; +import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.client.token.AccessTokenRequest; +import org.springframework.security.oauth2.client.token.RequestEnhancer; +import org.springframework.stereotype.Component; +import org.springframework.util.MultiValueMap; + +/** + * 实现 RequestEnhancer 接口 + * client_id -> appid + * client_secret -> secret + * + */ +@Component +@Log4j2 +public class WeChatRequestEnhancer implements RequestEnhancer { + private final WeChatProperties weChatProperties; + + public WeChatRequestEnhancer(WeChatProperties weChatProperties) { + this.weChatProperties = weChatProperties; + } + + @Override + public void enhance(AccessTokenRequest request, OAuth2ProtectedResourceDetails resource, MultiValueMap form, HttpHeaders headers) { + form.put(weChatProperties.getAppId(), form.remove(weChatProperties.getClientId())); + form.put(weChatProperties.getSecret(), form.remove(weChatProperties.getClientSecret())); + if (log.isDebugEnabled()) { + log.debug("form = {}", form.toSingleValueMap()); + } + } +} diff --git a/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatRestTemplate.java b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatRestTemplate.java new file mode 100644 index 0000000..5594fe9 --- /dev/null +++ b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatRestTemplate.java @@ -0,0 +1,59 @@ +package com.greate.community.auth.wechatauth.wechat; + +import org.springframework.security.oauth2.client.OAuth2ClientContext; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.common.OAuth2AccessToken; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +/** + * {@link org.springframework.security.oauth2.client.OAuth2RestTemplate#appendQueryParameter} + * 参考 appendQueryParameter,重写某些字段 + */ +public class WeChatRestTemplate extends OAuth2RestTemplate { + + WeChatRestTemplate(OAuth2ProtectedResourceDetails resource, OAuth2ClientContext context) { + super(resource, context); + } + + @Override + protected URI appendQueryParameter(URI uri, OAuth2AccessToken accessToken) { + try { + String query = uri.getRawQuery(); + String tokenQueryFragment = this.getResource().getTokenName() + "=" + + URLEncoder.encode(accessToken.getValue(), "UTF-8"); + if (query == null) { + query = tokenQueryFragment; + } else { + query = query + "&" + tokenQueryFragment; + } + + String openid = (String) accessToken.getAdditionalInformation().get("openid"); + if (openid != null) { + String openIdQueryFragment = "openid=" + URLEncoder.encode(openid, "UTF-8"); + query = query + "&" + openIdQueryFragment; + } + + URI update = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), + uri.getPath(), null, null); + + StringBuilder result = new StringBuilder(update.toString()); + result.append("?"); + result.append(query); + if (uri.getFragment() != null) { + result.append("#"); + result.append(uri.getFragment()); + } + + return new URI(result.toString()); + + } catch (URISyntaxException | UnsupportedEncodingException e) { + throw new IllegalArgumentException("Could not parse URI", e); + } + } +} diff --git a/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatUserPrincipalExtractor.java b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatUserPrincipalExtractor.java new file mode 100644 index 0000000..7d4da35 --- /dev/null +++ b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatUserPrincipalExtractor.java @@ -0,0 +1,34 @@ +package com.greate.community.auth.wechatauth.wechat; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.greate.community.auth.wechatauth.domain.UserWeChat; +import lombok.extern.log4j.Log4j2; +import org.springframework.boot.autoconfigure.security.oauth2.resource.PrincipalExtractor; +import org.springframework.context.annotation.Configuration; + +import java.io.IOException; +import java.util.Map; + +@Configuration +@Log4j2 +public class WeChatUserPrincipalExtractor implements PrincipalExtractor { + + @Override + public Object extractPrincipal(Map map) { + UserWeChat weChat; + try { + String valueAsString = new ObjectMapper().writeValueAsString(map); + weChat = new ObjectMapper().readValue(valueAsString, UserWeChat.class); + if (log.isDebugEnabled()) { + log.debug("convent success, wechat {}", weChat.toString()); + } + } catch (IOException e) { + log.error("convent error", e); + return null; + } + + log.debug(weChat); + return weChat; + } +} + diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index 3afb60e..4631908 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -1,18 +1,24 @@ package com.greate.community.config; +import com.greate.community.auth.wechatauth.wechat.WeChatAuthorizationConfig; +import com.greate.community.auth.wechatauth.wechat.WeChatOAuth2ClientContextFilter; import com.greate.community.filter.AuthenticationTokenFilter; import com.greate.community.util.CommunityConstant; import com.greate.community.util.CommunityUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.AuthenticationException; +import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -20,12 +26,124 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; +//@Configuration +//public class SecurityConfig extends WebSecurityConfigurerAdapter implements CommunityConstant { +// +// @Autowired +// private AuthenticationTokenFilter authenticationTokenFilter; +// +// /** +// * 静态资源 +// * +// * @param web +// * @throws Exception +// */ +// @Override +// public void configure(WebSecurity web) throws Exception { +// web.ignoring().antMatchers("/resources/**"); +// } +// +// // 认证环节我们使用自己的代码 LoginController,绕过 Spring Security 的 +// +// /** +// * 授权 +// * +// * @param http +// * @throws Exception +// */ +// @Override +// protected void configure(HttpSecurity http) throws Exception { +// http.cors().and().csrf().disable() +// .authorizeRequests() +// .antMatchers( +// "/user/setting", +// "/user/upload", +// "/discuss/add", +// "/discuss/publish", +// "/comment/add/**", +// "/letter/**", +// "/notice/**", +// "/like", +// "/follow", +// "/unfollow" +// ) +// .hasAnyAuthority( +// AUTHORITY_USER, +// AUTHORITY_ADMIN, +// AUTHORITY_MODERATOR +// ) +// +// .antMatchers( +// "/discuss/top", +// "/discuss/wonderful" +// ) +// .hasAnyAuthority( +// AUTHORITY_MODERATOR +// ) +// +// .antMatchers( +// "/discuss/delete", +// "/discuss/delete/", +// "/data/**" +// ) +// .hasAnyAuthority( +// AUTHORITY_ADMIN +// ) +// +// .anyRequest().permitAll() +// +// .and().csrf().disable(); +// +// //添加jwt认证器 +// http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); +// // 权限不够时的处理 +// http.exceptionHandling() +// // 1. 未登录时的处理 +// .authenticationEntryPoint(new AuthenticationEntryPoint() { +// @Override +// public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException { +// // 异步请求 +// response.setCharacterEncoding("UTF-8"); +// response.setContentType("application/plain;charset=utf-8"); +// response.getWriter().write(CommunityUtil.getJSONString(403, "你还没有登录")); +// } +// }) +// // 2. 权限不够时的处理 +// .accessDeniedHandler(new AccessDeniedHandler() { +// @Override +// public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException { +// // 异步请求 +// response.setContentType("application/plain;charset=utf-8"); +// PrintWriter writer = response.getWriter(); +// writer.write(CommunityUtil.getJSONString(403, "你没有访问该功能的权限")); +// } +// }); +// +// // Security 底层会默认拦截 /logout 请求,进行退出处理 +// // 此处赋予它一个根本不存在的退出路径,使得程序能够执行到我们自己编写的退出代码 +// http.logout().logoutUrl("/securitylogout"); +// +// http.headers().frameOptions().sameOrigin(); +// } +//} + + @Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter implements CommunityConstant { @Autowired private AuthenticationTokenFilter authenticationTokenFilter; + private final WeChatAuthorizationConfig weChatAuthorizationConfig; + private final WeChatOAuth2ClientContextFilter weChatOAuth2ClientContextFilter; + + public SecurityConfig(WeChatAuthorizationConfig weChatAuthorizationConfig, WeChatOAuth2ClientContextFilter weChatOAuth2ClientContextFilter) { + this.weChatAuthorizationConfig = weChatAuthorizationConfig; + this.weChatOAuth2ClientContextFilter = weChatOAuth2ClientContextFilter; + } + /** * 静态资源 * @@ -38,7 +156,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm } // 认证环节我们使用自己的代码 LoginController,绕过 Spring Security 的 - /** * 授权 * @@ -47,6 +164,14 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm */ @Override protected void configure(HttpSecurity http) throws Exception { + //添加jwt认证器 + http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); + /** + * WeChat login + */ + http.addFilterBefore(weChatAuthorizationConfig.weChatFilter(), BasicAuthenticationFilter.class).addFilterBefore(weChatOAuth2ClientContextFilter, OAuth2ClientAuthenticationProcessingFilter.class); + + http.cors().and().csrf().disable() .authorizeRequests() .antMatchers( @@ -84,12 +209,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm AUTHORITY_ADMIN ) - .anyRequest().permitAll() + .anyRequest().permitAll(); - .and().csrf().disable(); - - //添加jwt认证器 - http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); // 权限不够时的处理 http.exceptionHandling() // 1. 未登录时的处理 diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index 062526a..e845164 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -188,7 +188,7 @@ public class DiscussPostController implements CommunityConstant { resultMap.put("likeStatus",likeStatus); // 评论分页信息 - page.setLimit(5); +// page.setLimit(5);//前端注入 page.setPath("/discuss/detail/" + discussPostId); page.setRows(discussPost.getCommentCount()); diff --git a/src/main/java/com/greate/community/controller/FollowController.java b/src/main/java/com/greate/community/controller/FollowController.java index 63681dc..b054b53 100644 --- a/src/main/java/com/greate/community/controller/FollowController.java +++ b/src/main/java/com/greate/community/controller/FollowController.java @@ -102,7 +102,7 @@ public class FollowController implements CommunityConstant{ // model.addAttribute("user", user); hashMap.put("user", user);//正在查看的用户信息 - page.setLimit(5); +// page.setLimit(5);//前端注入 page.setPath("/followees/" + userId); page.setRows((int) followService.findFolloweeCount(userId, ENTITY_TYPE_USER)); @@ -142,7 +142,7 @@ public class FollowController implements CommunityConstant{ // model.addAttribute("user", user); hashMap.put("user", user);//正在查看的用户信息 - page.setLimit(5); +// page.setLimit(5);//前端注入 page.setPath("/followers/" + userId); page.setRows((int) followService.findFollowerCount(ENTITY_TYPE_USER, userId)); diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index 77aac2b..48453f8 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -4,11 +4,14 @@ import cn.hutool.captcha.CaptchaUtil; import cn.hutool.captcha.LineCaptcha; import cn.hutool.core.lang.UUID; import com.alibaba.fastjson.JSONObject; -import com.google.code.kaptcha.Producer; +import com.greate.community.auth.wechatauth.domain.UserWeChat; +import com.greate.community.dao.UserMapper; +import com.greate.community.entity.LoginTicket; import com.greate.community.entity.Result; import com.greate.community.entity.User; import com.greate.community.service.UserService; import com.greate.community.util.CommunityConstant; +import com.greate.community.util.CommunityUtil; import com.greate.community.util.RedisKeyUtil; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -16,11 +19,12 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; -import javax.validation.constraints.NotEmpty; +import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -36,6 +40,9 @@ public class LoginController extends BaseController implements CommunityConstant @Autowired private UserService userService; + @Autowired + private UserMapper userMapper; + @Autowired private RedisTemplate redisTemplate; @@ -284,6 +291,67 @@ public class LoginController extends BaseController implements CommunityConstant // } // } + + + + + + /** + * 用户使用微信账号第三方登录成功后,后端回调此链接向前端返回响应 + * + * @return + */ + @GetMapping("/wechat/login") + public Result wechatLogin(@AuthenticationPrincipal UserWeChat userWeChat) { + String username = userWeChat.getNickName();//微信昵称 + String password = CommunityUtil.generateUUID();//随机密码,不能随便让人破解 + String headerUrl = userWeChat.getHeadimgurl();//微信头像地址 + String email = "wechat@none.com";//微信登录的用户,邮箱是一个特殊标识字符串 + + + // 若微信用户对应的账号已存在,跳过模拟注册操作,直接进入登录过程 + User u = userMapper.selectByName(username); + User user = new User(); + if (u == null) { + /**模拟注册操作**/ + user.setUsername(username); + user.setPassword(password); + user.setEmail(email); + user.setType(0); // 默认普通用户 + user.setStatus(1); // 微信登录用户默认激活,无需邮箱验证 + + // 用户头像 + user.setHeaderUrl(headerUrl);//微信头像地址 + user.setCreateTime(new Date()); // 注册时间 + + userMapper.insertUser(user); + // 这一步主要是为了获取userId + user = userMapper.selectByName(username); + /**模拟注册操作**/ + }else { + user = u; + } + + /**模拟普通登录过程**/ + // 凭证过期时间 + int expiredSeconds = DEFAULT_EXPIRED_SECONDS; + + // 用户名和密码均正确,为该用户生成登录凭证 + LoginTicket loginTicket = new LoginTicket(); + loginTicket.setUserId(user.getId()); + loginTicket.setTicket(CommunityUtil.generateUUID()); // 随机凭证 + loginTicket.setStatus(0); // 设置凭证状态为有效(当用户登出的时候,设置凭证状态为无效) + loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000)); // 设置凭证到期时间 + + // 将登录凭证存入 redis + String redisKey = RedisKeyUtil.getTicketKey(loginTicket.getTicket()); + redisTemplate.opsForValue().set(redisKey, loginTicket); + + String ticket = loginTicket.getTicket(); + return new Result("success", Result.SUCCESS, ticket); + /**模拟普通登录过程**/ + } + /** * 用户登出 * diff --git a/src/main/java/com/greate/community/controller/MessageController.java b/src/main/java/com/greate/community/controller/MessageController.java index 974c098..a3916ec 100644 --- a/src/main/java/com/greate/community/controller/MessageController.java +++ b/src/main/java/com/greate/community/controller/MessageController.java @@ -35,14 +35,14 @@ public class MessageController extends BaseController implements CommunityConsta * @return */ @GetMapping("/letter/list") - public Result getLetterList(Page page) { + public Result getLetterList(@RequestBody Page page) { // Integer.valueOf("abc"); // 测试统一异常处理(普通请求) JSONObject jsonObject = new JSONObject(); // 获取当前登录用户信息 User user = getUser(); // 分页信息 - page.setLimit(5); +// page.setLimit(5);//前端注入 page.setPath("/letter/list"); // 查询会话总数 page.setRows(messageService.findConversationCout(user.getId())); @@ -123,11 +123,11 @@ public class MessageController extends BaseController implements CommunityConsta * @return */ @GetMapping("/letter/detail/{conversationId}") - public Result getLetterDetail(@PathVariable("conversationId") String conversationId, Page page) { + public Result getLetterDetail(@PathVariable("conversationId") String conversationId, @RequestBody Page page) { JSONObject jsonObject = new JSONObject(); // 分页信息 - page.setLimit(5); +// page.setLimit(5);//前端注入 page.setPath("/letter/detail/" + conversationId); page.setRows(messageService.findLetterCount(conversationId)); @@ -438,10 +438,10 @@ public class MessageController extends BaseController implements CommunityConsta * @return */ @GetMapping("/notice/detail/{topic}") - public Result getNoticeDetail(@PathVariable("topic") String topic, Page page) { + public Result getNoticeDetail(@PathVariable("topic") String topic, @RequestBody Page page) { User user = getUser(); - page.setLimit(5); +// page.setLimit(5);//前端注入 page.setPath("/notice/detail/" + topic); page.setRows(messageService.findNoticeCount(user.getId(), topic)); diff --git a/src/main/java/com/greate/community/controller/SearchController.java b/src/main/java/com/greate/community/controller/SearchController.java index 8f820fb..fe45a3d 100644 --- a/src/main/java/com/greate/community/controller/SearchController.java +++ b/src/main/java/com/greate/community/controller/SearchController.java @@ -10,6 +10,7 @@ import com.greate.community.util.CommunityConstant; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import java.util.*; @@ -37,7 +38,7 @@ public class SearchController extends BaseController implements CommunityConstan * @return */ @GetMapping("/search") - public String search(String keyword, Page page) { + public String search(String keyword, @RequestBody Page page) { JSONObject jsonObject = new JSONObject(); // 搜索帖子 (Spring 提供的 Page 当前页码从 0 开始计数) org.springframework.data.domain.Page searchResult = diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 835a12b..95d45e3 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -219,7 +219,7 @@ public class UserController extends BaseController implements CommunityConstant * @return */ @GetMapping("/discuss/{userId}") - public Result getMyDiscussPosts(@PathVariable("userId") int userId, Page page) { + public Result getMyDiscussPosts(@PathVariable("userId") int userId, @RequestBody Page page) { JSONObject jsonObject = new JSONObject(); User user = userService.findUserById(userId); if (user == null) { @@ -231,7 +231,7 @@ public class UserController extends BaseController implements CommunityConstant int rows = discussPostService.findDiscussPostRows(userId); jsonObject.put("rows", rows); - page.setLimit(5); +// page.setLimit(5);//前端注入 page.setPath("/user/discuss/" + userId); page.setRows(rows); @@ -295,7 +295,7 @@ public class UserController extends BaseController implements CommunityConstant * @return */ @GetMapping("/comment/{userId}") - public Result getMyComments(@PathVariable("userId") int userId, Page page) { + public Result getMyComments(@PathVariable("userId") int userId, @RequestBody Page page) { JSONObject jsonObject = new JSONObject(); User user = userService.findUserById(userId); if (user == null) { @@ -307,7 +307,7 @@ public class UserController extends BaseController implements CommunityConstant int commentCounts = commentService.findCommentCountByUserId(userId); jsonObject.put("commentCounts", commentCounts); - page.setLimit(5); +// page.setLimit(5);//前端注入 page.setPath("/user/comment/" + userId); page.setRows(commentCounts); diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index 1c66080..07ff657 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -3,6 +3,7 @@ bbs.captcha-enable = false # ˿ server.port = 8080 +#server.port = 80 # Ŀ(Ŀ·) http://localhost:8080/...... server.servlet.context-path = @@ -81,4 +82,25 @@ qiniu.bucket.header.url = http://qnvxyvq1p.hd-bkt.clouddn.com # Caffeine caffeine.posts.max-size = 15 -caffeine.posts.expire-seconds = 180 \ No newline at end of file +caffeine.posts.expire-seconds = 180 + + +# OAuth2 ΢ŵ¼ +wechat.client.clientId = wxa75d140e71f8903e +wechat.client.clientSecret = 2e6dbcad650a9fa495a762c0eb28906a +wechat.client.accessTokenUri = https://api.weixin.qq.com/sns/oauth2/access_token +wechat.client.userAuthorizationUri = https://open.weixin.qq.com/connect/oauth2/authorize +wechat.client.tokenName = access_token +wechat.client.authenticationScheme = query +wechat.client.clientAuthenticationScheme = form +wechat.client.scope = snsapi_userinfo +wechat.resource.userInfoUri = https://api.weixin.qq.com/sns/userinfo +wechat.config.app-id = appid +wechat.config.client-id = client_id +wechat.config.secret = secret +wechat.config.client-secret = client_secret +wechat.config.state = state +wechat.config.wechat-redirect = wechat_redirect + +logging.level.com.greate = debug +logging.level.org.springframework.security = DEBUG \ No newline at end of file diff --git a/src/test/java/com/greate/community/MailTests.java b/src/test/java/com/greate/community/MailTests.java index 76da6c1..bb1bcf3 100644 --- a/src/test/java/com/greate/community/MailTests.java +++ b/src/test/java/com/greate/community/MailTests.java @@ -1,25 +1,25 @@ -package com.greate.community; - -import com.greate.community.util.EmailUtil; -import com.greate.community.util.MailClient; -import lombok.ToString; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@ContextConfiguration(classes = CommunityApplication.class) -@SpringBootTest -public class MailTests { - - @Autowired - private EmailUtil emailUtil; - - @Test - public void sendEmail() { - emailUtil.sendRegistrationCode("2224236998@qq.com"); - } -} +//package com.greate.community; +// +//import com.greate.community.util.EmailUtil; +//import com.greate.community.util.MailClient; +//import lombok.ToString; +//import org.junit.Test; +//import org.junit.runner.RunWith; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.test.context.SpringBootTest; +//import org.springframework.test.context.ContextConfiguration; +//import org.springframework.test.context.junit4.SpringRunner; +// +//@RunWith(SpringRunner.class) +//@ContextConfiguration(classes = CommunityApplication.class) +//@SpringBootTest +//public class MailTests { +// +// @Autowired +// private EmailUtil emailUtil; +// +// @Test +// public void sendEmail() { +// emailUtil.sendRegistrationCode("2224236998@qq.com"); +// } +//} -- Gitee From 55b897917fe282ad9af03cd1a8a4674854d2db6c Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Wed, 2 Feb 2022 16:17:46 +0800 Subject: [PATCH 005/125] =?UTF-8?q?=E5=90=88=E5=B9=B6dev=E5=88=86=E6=94=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + pom.xml | 2 +- src/main/resources/META-INF/MANIFEST.MF | 63 ++++++ .../com/greate/community/CaffeineTest.java | 48 ----- .../community/CommunityApplicationTests.java | 21 -- .../greate/community/ElasticsearchTests.java | 203 ------------------ .../java/com/greate/community/KafkaTests.java | 54 ----- .../java/com/greate/community/MailTests.java | 25 --- .../com/greate/community/QuartzTests.java | 30 --- .../com/greate/community/SensitiveTests.java | 28 --- 10 files changed, 65 insertions(+), 410 deletions(-) create mode 100644 src/main/resources/META-INF/MANIFEST.MF delete mode 100644 src/test/java/com/greate/community/CaffeineTest.java delete mode 100644 src/test/java/com/greate/community/CommunityApplicationTests.java delete mode 100644 src/test/java/com/greate/community/ElasticsearchTests.java delete mode 100644 src/test/java/com/greate/community/KafkaTests.java delete mode 100644 src/test/java/com/greate/community/MailTests.java delete mode 100644 src/test/java/com/greate/community/QuartzTests.java delete mode 100644 src/test/java/com/greate/community/SensitiveTests.java diff --git a/.gitignore b/.gitignore index 9b8d421..dbd8d6c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ target/ log/ sql/ docs/ +out/ ### STS ### .apt_generated diff --git a/pom.xml b/pom.xml index af48f8f..767d64d 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ 0.0.1-SNAPSHOT community great community — Echo - war + jar 1.8 diff --git a/src/main/resources/META-INF/MANIFEST.MF b/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 0000000..2b7b3ce --- /dev/null +++ b/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1,63 @@ +Manifest-Version: 1.0 +Main-Class: com.greate.community.CommunityApplication +Class-Path: elasticsearch-secure-sm-6.4.3.jar parent-join-client-6.4.3.j + ar log4j-api-2.11.2.jar spring-oxm-5.1.7.RELEASE.jar validation-api-2.0 + .1.Final.jar transport-6.4.3.jar lombok-1.18.8.jar okio-1.14.0.jar reac + tor-core-3.2.9.RELEASE.jar HdrHistogram-2.1.9.jar mybatis-spring-boot-a + utoconfigure-2.1.3.jar lz4-java-1.4.1.jar httpasyncclient-4.1.4.jar spr + ing-boot-starter-aop-2.1.5.RELEASE.jar spring-security-config-5.1.5.REL + EASE.jar lucene-core-7.4.0.jar elasticsearch-core-6.4.3.jar jboss-loggi + ng-3.3.2.Final.jar spring-retry-1.2.4.RELEASE.jar jopt-simple-5.0.2.jar + mysql-connector-java-5.1.47.jar spring-boot-starter-2.1.5.RELEASE.jar + reactive-streams-1.0.2.jar snakeyaml-1.23.jar quartz-2.3.1.jar filters- + 2.0.235-1.jar caffeine-2.7.0.jar lucene-spatial3d-7.4.0.jar kaptcha-2.3 + .2.jar httpcore-nio-4.4.11.jar aspectjweaver-1.9.4.jar qiniu-java-sdk-7 + .2.23.jar lucene-memory-7.4.0.jar rank-eval-client-6.4.3.jar lucene-san + dbox-7.4.0.jar spring-boot-devtools-2.1.5.RELEASE.jar elasticsearch-x-c + ontent-6.4.3.jar lucene-queryparser-7.4.0.jar spring-security-core-5.1. + 5.RELEASE.jar elasticsearch-cli-6.4.3.jar spring-data-redis-2.1.8.RELEA + SE.jar spring-data-keyvalue-2.1.8.RELEASE.jar percolator-client-6.4.3.j + ar jasypt-1.9.3.jar kafka-clients-2.0.1.jar commons-lang3-3.9.jar sprin + g-boot-starter-data-redis-2.1.5.RELEASE.jar spring-boot-starter-tomcat- + 2.1.5.RELEASE.jar tomcat-embed-websocket-9.0.19.jar HikariCP-3.2.0.jar + netty-transport-4.1.36.Final.jar netty-handler-4.1.36.Final.jar spring- + jcl-5.1.7.RELEASE.jar spring-messaging-5.1.7.RELEASE.jar lucene-suggest + -7.4.0.jar javax.servlet-api-4.0.1.jar jackson-datatype-jsr310-2.9.8.ja + r lucene-analyzers-common-7.4.0.jar logback-core-1.2.3.jar jackson-data + type-jdk8-2.9.8.jar jackson-dataformat-cbor-2.9.8.jar spring-boot-start + er-jdbc-2.1.5.RELEASE.jar tomcat-embed-core-9.0.19.jar spring-kafka-2.2 + .6.RELEASE.jar jackson-module-parameter-names-2.9.8.jar spring-boot-sta + rter-data-elasticsearch-2.1.5.RELEASE.jar spring-boot-starter-quartz-2. + 1.5.RELEASE.jar gson-2.8.5.jar joda-time-2.10.2.jar mchange-commons-jav + a-0.2.15.jar spring-core-5.1.7.RELEASE.jar log4j-to-slf4j-2.11.2.jar ch + ecker-qual-2.6.0.jar lucene-highlighter-7.4.0.jar fastjson-1.2.58.jar m + ybatis-3.5.5.jar elasticsearch-rest-client-6.4.3.jar spring-web-5.1.7.R + ELEASE.jar jasypt-spring-boot-starter-2.1.2.jar spring-aop-5.1.7.RELEAS + E.jar spring-boot-starter-logging-2.1.5.RELEASE.jar httpclient-4.5.8.ja + r spring-boot-starter-web-2.1.5.RELEASE.jar javax.annotation-api-1.3.2. + jar netty-resolver-4.1.36.Final.jar spring-boot-starter-json-2.1.5.RELE + ASE.jar reindex-client-6.4.3.jar logback-classic-1.2.3.jar spring-tx-5. + 1.7.RELEASE.jar httpcore-4.4.11.jar jasypt-spring-boot-2.1.2.jar netty- + common-4.1.36.Final.jar lettuce-core-5.1.6.RELEASE.jar spring-boot-2.1. + 5.RELEASE.jar lucene-misc-7.4.0.jar mybatis-spring-2.0.5.jar jackson-da + taformat-yaml-2.9.8.jar slf4j-api-1.7.26.jar lucene-queries-7.4.0.jar s + pring-context-5.1.7.RELEASE.jar spring-data-commons-2.1.8.RELEASE.jar t + -digest-3.2.jar spring-boot-starter-mail-2.1.5.RELEASE.jar netty-buffer + -4.1.36.Final.jar elasticsearch-6.4.3.jar lucene-grouping-7.4.0.jar spr + ing-security-web-5.1.5.RELEASE.jar spring-boot-autoconfigure-2.1.5.RELE + ASE.jar spring-jdbc-5.1.7.RELEASE.jar tomcat-embed-el-9.0.19.jar classm + ate-1.4.0.jar compiler-0.9.3.jar jackson-databind-2.9.8.jar spring-expr + ession-5.1.7.RELEASE.jar javax.mail-1.6.2.jar hutool-all-5.7.20.jar act + ivation-1.1.jar commons-codec-1.11.jar lucene-backward-codecs-7.4.0.jar + mybatis-spring-boot-starter-2.1.3.jar snappy-java-1.1.7.1.jar jackson- + core-2.9.8.jar hppc-0.7.1.jar jackson-dataformat-smile-2.9.8.jar lucene + -spatial-extras-7.4.0.jar spring-webmvc-5.1.7.RELEASE.jar jackson-annot + ations-2.9.0.jar okhttp-3.11.0.jar spring-beans-5.1.7.RELEASE.jar jul-t + o-slf4j-1.7.26.jar spring-context-support-5.1.7.RELEASE.jar jna-4.5.1.j + ar spring-data-elasticsearch-3.1.8.RELEASE.jar lang-mustache-client-6.4 + .3.jar transport-netty4-client-6.4.3.jar hibernate-validator-6.0.16.Fin + al.jar netty-codec-http-4.1.36.Final.jar netty-codec-4.1.36.Final.jar t + hymeleaf-extras-springsecurity5-3.0.4.RELEASE.jar error_prone_annotatio + ns-2.3.3.jar spring-boot-starter-security-2.1.5.RELEASE.jar lucene-spat + ial-7.4.0.jar lucene-join-7.4.0.jar + diff --git a/src/test/java/com/greate/community/CaffeineTest.java b/src/test/java/com/greate/community/CaffeineTest.java deleted file mode 100644 index 500b171..0000000 --- a/src/test/java/com/greate/community/CaffeineTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.greate.community; - -import com.greate.community.entity.DiscussPost; -import com.greate.community.service.DiscussPostService; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; - -import java.util.Date; - -@RunWith(SpringRunner.class) -@ContextConfiguration(classes = CommunityApplication.class) -@SpringBootTest -public class CaffeineTest { - - @Autowired - private DiscussPostService postService; - - /** - * 注入大量数据,才能体现缓存的好处 - */ - @Ignore - @Test - public void initDataForTest() { - for (int i = 0; i < 300000; i++) { - DiscussPost post = new DiscussPost(); - post.setUserId(111); - post.setTitle("测试数据"); - post.setContent("兄弟们,冲"); - post.setCreateTime(new Date()); - post.setScore(Math.random() * 2000); - postService.addDiscussPost(post); - } - } - - @Ignore - @Test - public void testCache() { - System.out.println(postService.findDiscussPosts(0, 0, 10, 1)); - System.out.println(postService.findDiscussPosts(0, 0, 10, 1)); - System.out.println(postService.findDiscussPosts(0, 0, 10, 1)); - System.out.println(postService.findDiscussPosts(0, 0, 10, 0)); - } -} diff --git a/src/test/java/com/greate/community/CommunityApplicationTests.java b/src/test/java/com/greate/community/CommunityApplicationTests.java deleted file mode 100644 index 0deac87..0000000 --- a/src/test/java/com/greate/community/CommunityApplicationTests.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.greate.community; - -import com.greate.community.dao.DiscussPostMapper; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@ContextConfiguration(classes = CommunityApplication.class) -@SpringBootTest -class CommunityApplicationTests { - - @Test - void contextLoads() { - - } - -} diff --git a/src/test/java/com/greate/community/ElasticsearchTests.java b/src/test/java/com/greate/community/ElasticsearchTests.java deleted file mode 100644 index 4336f1c..0000000 --- a/src/test/java/com/greate/community/ElasticsearchTests.java +++ /dev/null @@ -1,203 +0,0 @@ -package com.greate.community; - -import com.greate.community.dao.DiscussPostMapper; -import com.greate.community.dao.elasticsearch.DiscussPostRepository; -import com.greate.community.entity.DiscussPost; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.index.query.QueryBuilder; -import org.elasticsearch.index.query.QueryBuilders; -import org.elasticsearch.search.SearchHit; -import org.elasticsearch.search.SearchHits; -import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; -import org.elasticsearch.search.fetch.subphase.highlight.HighlightField; -import org.elasticsearch.search.sort.SortBuilders; -import org.elasticsearch.search.sort.SortOrder; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; -import org.springframework.data.elasticsearch.core.SearchResultMapper; -import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage; -import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl; -import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; -import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; -import org.springframework.data.elasticsearch.core.query.SearchQuery; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -@RunWith(SpringRunner.class) -@ContextConfiguration(classes = CommunityApplication.class) -@SpringBootTest -public class ElasticsearchTests { - - @Autowired - private DiscussPostMapper discussPostMapper; - - @Autowired - private DiscussPostRepository discussPostRepository; - - @Autowired - private ElasticsearchTemplate elasticsearchTemplate; - - /** - * 测试插入数据 - */ - @Test - public void testInsert() { - discussPostRepository.save(discussPostMapper.selectDiscussPostById(241)); - discussPostRepository.save(discussPostMapper.selectDiscussPostById(242)); - discussPostRepository.save(discussPostMapper.selectDiscussPostById(243)); - } - - /** - * 测试批量插入数据 - */ - @Test - public void testInsetList() { - discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(101, 0, 100, 0)); - discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(102, 0, 100, 0)); - discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(103, 0, 100, 0)); - discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(111, 0, 100, 0)); - discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(112, 0, 100, 0)); - discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(131, 0, 100, 0)); - discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(132, 0, 100, 0)); - discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(133, 0, 100, 0)); - discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(134, 0, 100, 0)); - } - - /** - * 测试修改数据 - */ - @Test - public void testUpdate() { - DiscussPost discussPost = discussPostMapper.selectDiscussPostById(231); - discussPost.setContent("Great Elasticsearch"); - discussPostRepository.save(discussPost); - } - - /** - * 测试删除数据(注意数据库中的数据并未被删除) - */ - @Test - public void testDelete() { - discussPostRepository.deleteById(231); - // discussPostRepository.deleteAll(); - } - - /** - * 测试使用 ElasticsearchRepository 进行搜索 - */ - @Test - public void testSearchByRepository() { - SearchQuery searchQuery = new NativeSearchQueryBuilder() - .withQuery(QueryBuilders.multiMatchQuery("互联网寒冬", "title", "content")) - .withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC)) - .withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC)) - .withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC)) - .withPageable(PageRequest.of(0, 10)) - .withHighlightFields( - new HighlightBuilder.Field("title").preTags("").postTags(""), - new HighlightBuilder.Field("content").preTags("").postTags("") - ).build(); - - // elasticsearchTemplate.queryForPage(searchQuery, class, SearchResultMapper); - // 底层获取到了高亮显示的值,但是没有做处理(所以想要更加完善的话需要使用 ElasticsearchTemplate) - - Page page = discussPostRepository.search(searchQuery); - - System.out.println(page.getTotalElements()); - System.out.println(page.getTotalPages()); - System.out.println(page.getNumber()); - System.out.println(page.getSize()); - for (DiscussPost post : page) { - System.out.println(post); - } - } - - /** - * 测试使用 ElasticsearchTemplate 进行搜索 - */ - @Test - public void testSearchTemplate() { - SearchQuery searchQuery = new NativeSearchQueryBuilder() - .withQuery(QueryBuilders.multiMatchQuery("互联网寒冬", "title", "content")) - .withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC)) - .withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC)) - .withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC)) - .withPageable(PageRequest.of(0, 10)) - .withHighlightFields( - new HighlightBuilder.Field("title").preTags("").postTags(""), - new HighlightBuilder.Field("content").preTags("").postTags("") - ).build(); - - Page page = elasticsearchTemplate.queryForPage(searchQuery, DiscussPost.class, new SearchResultMapper() { - @Override - public AggregatedPage mapResults(SearchResponse searchResponse, Class aClass, Pageable pageable) { - SearchHits hits = searchResponse.getHits(); - if (hits.getTotalHits() <= 0) { - return null; - } - - List list = new ArrayList<>(); - - for (SearchHit hit : hits) { - DiscussPost post = new DiscussPost(); - - String id = hit.getSourceAsMap().get("id").toString(); - post.setId(Integer.valueOf(id)); - - String userId = hit.getSourceAsMap().get("userId").toString(); - post.setUserId(Integer.valueOf(userId)); - - String title = hit.getSourceAsMap().get("title").toString(); - post.setTitle(title); - - String content = hit.getSourceAsMap().get("content").toString(); - post.setContent(content); - - String status = hit.getSourceAsMap().get("status").toString(); - post.setStatus(Integer.valueOf(status)); - - String createTime = hit.getSourceAsMap().get("createTime").toString(); - post.setCreateTime(new Date(Long.valueOf(createTime))); - - String commentCount = hit.getSourceAsMap().get("commentCount").toString(); - post.setCommentCount(Integer.valueOf(commentCount)); - - // 处理高亮显示的内容 - HighlightField titleField = hit.getHighlightFields().get("title"); - if (titleField != null) { - post.setTitle(titleField.getFragments()[0].toString()); - } - - HighlightField contentField = hit.getHighlightFields().get("content"); - if (contentField != null) { - post.setContent(contentField.getFragments()[0].toString()); - } - - list.add(post); - } - - return new AggregatedPageImpl(list, pageable, - hits.getTotalHits(), searchResponse.getAggregations(), searchResponse.getScrollId(), hits.getMaxScore()); - } -}); - - System.out.println(page.getTotalElements()); - System.out.println(page.getTotalPages()); - System.out.println(page.getNumber()); - System.out.println(page.getSize()); - for (DiscussPost post : page) { - System.out.println(post); - } - } - -} diff --git a/src/test/java/com/greate/community/KafkaTests.java b/src/test/java/com/greate/community/KafkaTests.java deleted file mode 100644 index 73574da..0000000 --- a/src/test/java/com/greate/community/KafkaTests.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.greate.community; - -import org.apache.kafka.clients.consumer.ConsumerRecord; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.kafka.annotation.KafkaListener; -import org.springframework.kafka.core.KafkaTemplate; -import org.springframework.stereotype.Component; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@ContextConfiguration(classes = CommunityApplication.class) -@SpringBootTest -public class KafkaTests { - @Autowired - private KafkaProducer kafkaProducer; - - @Test - public void testKafka() { - kafkaProducer.sendMessage("test", "Hello"); - kafkaProducer.sendMessage("test", "World"); - try { - Thread.sleep(1000 * 10); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - -} - -@Component -class KafkaProducer { - - @Autowired - private KafkaTemplate kafkaTemplate; - - public void sendMessage(String topic, String content) { - kafkaTemplate.send(topic, content); - } - -} - -@Component -class KafkaConsumer { - - @KafkaListener(topics = {"test"}) - public void handlerMessage(ConsumerRecord consumerRecord) { - System.out.println(consumerRecord.value()); - } - -} diff --git a/src/test/java/com/greate/community/MailTests.java b/src/test/java/com/greate/community/MailTests.java deleted file mode 100644 index 76da6c1..0000000 --- a/src/test/java/com/greate/community/MailTests.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.greate.community; - -import com.greate.community.util.EmailUtil; -import com.greate.community.util.MailClient; -import lombok.ToString; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@ContextConfiguration(classes = CommunityApplication.class) -@SpringBootTest -public class MailTests { - - @Autowired - private EmailUtil emailUtil; - - @Test - public void sendEmail() { - emailUtil.sendRegistrationCode("2224236998@qq.com"); - } -} diff --git a/src/test/java/com/greate/community/QuartzTests.java b/src/test/java/com/greate/community/QuartzTests.java deleted file mode 100644 index 2d0a50d..0000000 --- a/src/test/java/com/greate/community/QuartzTests.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.greate.community; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.quartz.JobKey; -import org.quartz.Scheduler; -import org.quartz.SchedulerException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@ContextConfiguration(classes = CommunityApplication.class) -@SpringBootTest -public class QuartzTests { - - @Autowired - private Scheduler scheduler; - - @Test - public void deleteJob(){ - try { - boolean result = scheduler.deleteJob(new JobKey("", "")); - System.out.println(result); - } catch (SchedulerException e) { - e.printStackTrace(); - } - } -} diff --git a/src/test/java/com/greate/community/SensitiveTests.java b/src/test/java/com/greate/community/SensitiveTests.java deleted file mode 100644 index 2ee0f18..0000000 --- a/src/test/java/com/greate/community/SensitiveTests.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.greate.community; - -import com.greate.community.util.SensitiveFilter; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@ContextConfiguration(classes = CommunityApplication.class) -@SpringBootTest -public class SensitiveTests { - - @Autowired - private SensitiveFilter sensitiveFilter; - - @Test - public void testSensitiveFilter() { - String text1 = "这里可以赌博、可以嫖娼、可以吸毒,哈哈!"; - System.out.println(sensitiveFilter.filter(text1)); - - String text2 = "这里可以☆赌☆☆博、可以☆☆嫖☆娼☆☆、可以☆吸☆☆毒,哈哈!"; - System.out.println(sensitiveFilter.filter(text2)); - } - -} -- Gitee From 149471641617d1e3decd98a717ccb6a1f9b508aa Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Wed, 2 Feb 2022 16:55:53 +0800 Subject: [PATCH 006/125] update user property --- .../interceptor/LoginTicketInterceptor.java | 100 ------------------ .../com/greate/community/dao/UserMapper.java | 28 ++--- .../com/greate/community/entity/User.java | 70 ++++++++++++ .../greate/community/service/UserService.java | 3 - .../com/greate/community/util/MailClient.java | 49 --------- src/main/resources/mapper/user-mapper.xml | 12 ++- 6 files changed, 91 insertions(+), 171 deletions(-) delete mode 100644 src/main/java/com/greate/community/controller/interceptor/LoginTicketInterceptor.java delete mode 100644 src/main/java/com/greate/community/util/MailClient.java diff --git a/src/main/java/com/greate/community/controller/interceptor/LoginTicketInterceptor.java b/src/main/java/com/greate/community/controller/interceptor/LoginTicketInterceptor.java deleted file mode 100644 index 430ae3c..0000000 --- a/src/main/java/com/greate/community/controller/interceptor/LoginTicketInterceptor.java +++ /dev/null @@ -1,100 +0,0 @@ -//package com.greate.community.controller.interceptor; -// -//import com.greate.community.entity.LoginTicket; -//import com.greate.community.entity.User; -//import com.greate.community.service.UserService; -//import com.greate.community.util.HostHolder; -//import lombok.extern.slf4j.Slf4j; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -//import org.springframework.security.core.Authentication; -//import org.springframework.security.core.context.SecurityContextHolder; -//import org.springframework.security.core.context.SecurityContextImpl; -//import org.springframework.stereotype.Component; -//import org.springframework.web.servlet.HandlerInterceptor; -//import org.springframework.web.servlet.ModelAndView; -// -//import javax.servlet.http.HttpServletRequest; -//import javax.servlet.http.HttpServletResponse; -//import java.util.Date; -// -//@Slf4j -//@Component -//public class LoginTicketInterceptor implements HandlerInterceptor { -// -// @Autowired -// private UserService userService; -// -// @Autowired -// private HostHolder hostHolder; -// -// /** -// * 在 Controller 执行之前被调用 -// * 检查凭证状态,若凭证有效则在本次请求中持有该用户信息 -// * @param request -// * @param response -// * @param handler -// * @return -// * @throws Exception -// */ -// @Override -// public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { -// // 从 cookie 中获取凭证 -//// String ticket = CookieUtil.getValue(request, "ticket"); -// String ticket = request.getHeader("ticket"); -// log.info("request请求地址path[{}] uri[{}]", request.getServletPath(),request.getRequestURI()); -// log.info("获取ticket: " + ticket); -// if (ticket != null) { -// // 查询凭证 -// LoginTicket loginTicket = userService.findLoginTicket(ticket); -// // 检查凭证状态(是否有效)以及是否过期 -// if (loginTicket != null && loginTicket.getStatus() == 0 && loginTicket.getExpired().after(new Date())) { -// // 根据凭证查询用户 -// User user = userService.findUserById(loginTicket.getUserId()); -// log.info("用会话户信息: " + user.toString()); -// // 在本次请求中持有用户信息 -// hostHolder.setUser(user); -// -// // 构建用户认证的结果,并存入 SecurityContext, 以便于 Spring Security 进行授权 -// Authentication authentication = new UsernamePasswordAuthenticationToken( -// user, user.getPassword(), userService.getAuthorities(user.getId()) -// ); -// SecurityContextHolder.setContext(new SecurityContextImpl(authentication)); -// } -// } -// -// return true; -// } -// -// /** -// * 在模板引擎之前被调用 -// * 将用户信息存入 modelAndView, 便于模板引擎调用 -// * @param request -// * @param response -// * @param handler -// * @param modelAndView -// * @throws Exception -// */ -// @Override -// public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { -// User user = hostHolder.getUser(); -// if (user != null && modelAndView != null) { -// modelAndView.addObject("loginUser", user); -// } -// } -// -// /** -// * 在 Controller 执行之后(即服务端对本次请求做出响应后)被调用 -// * 清理本次请求持有的用户信息 -// * @param request -// * @param response -// * @param handler -// * @param ex -// * @throws Exception -// */ -// @Override -// public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { -// hostHolder.clear(); -// SecurityContextHolder.clearContext(); -// } -//} diff --git a/src/main/java/com/greate/community/dao/UserMapper.java b/src/main/java/com/greate/community/dao/UserMapper.java index f1fc41a..923377b 100644 --- a/src/main/java/com/greate/community/dao/UserMapper.java +++ b/src/main/java/com/greate/community/dao/UserMapper.java @@ -8,54 +8,46 @@ public interface UserMapper { /** * 根据 id 查询用户 - * @param id - * @return */ - User selectById (int id); + User selectById(int id); /** * 根据 username 查询用户 - * @param username - * @return */ User selectByName(String username); /** * 根据 email 查询用户 - * @param email - * @return */ User selectByEmail(String email); /** * 插入用户(注册) - * @param user - * @return */ int insertUser(User user); /** * 修改用户状态 - * @param id - * @param status 0:未激活,1:已激活 - * @return */ int updateStatus(int id, int status); /** * 修改头像 - * @param id - * @param headerUrl - * @return */ int updateHeader(int id, String headerUrl); /** * 修改密码 - * @param id - * @param password 新密码 - * @return */ int updatePassword(int id, String password); + /** + * 修改经验值 + */ + int updateExp(int id, int exp); + + /** + * 修改经验值 + */ + int updateRank(int id, int rank); } diff --git a/src/main/java/com/greate/community/entity/User.java b/src/main/java/com/greate/community/entity/User.java index b9b7bba..8cea0b9 100644 --- a/src/main/java/com/greate/community/entity/User.java +++ b/src/main/java/com/greate/community/entity/User.java @@ -13,11 +13,18 @@ public class User { private String password; private String salt; private String email; + private int exp; + private int rank; private int type; private int status; private String activationCode; private String headerUrl; private Date createTime; + private String studentCardUrl; + private String studentCode; + private String realName; + private String institute; + private String professionalClass; public int getId() { return id; @@ -59,6 +66,22 @@ public class User { this.email = email; } + public int getExp() { + return exp; + } + + public void setExp(int exp) { + this.exp = exp; + } + + public int getRank() { + return rank; + } + + public void setRank(int rank) { + this.rank = rank; + } + public int getType() { return type; } @@ -91,6 +114,46 @@ public class User { this.headerUrl = headerUrl; } + public String getStudentCardUrl() { + return studentCardUrl; + } + + public void setStudentCardUrl(String studentCardUrl) { + this.studentCardUrl = studentCardUrl; + } + + public String getStudentCode() { + return studentCode; + } + + public void setStudentCode(String studentCode) { + this.studentCode = studentCode; + } + + public String getRealName() { + return realName; + } + + public void setRealName(String realName) { + this.realName = realName; + } + + public String getInstitute() { + return institute; + } + + public void setInstitute(String institute) { + this.institute = institute; + } + + public String getProfessionalClass() { + return professionalClass; + } + + public void setProfessionalClass(String professionalClass) { + this.professionalClass = professionalClass; + } + public Date getCreateTime() { return createTime; } @@ -107,10 +170,17 @@ public class User { ", password='" + password + '\'' + ", salt='" + salt + '\'' + ", email='" + email + '\'' + + ", exp='" + exp + '\'' + + ", rank='" + rank + '\'' + ", type=" + type + ", status=" + status + ", activationCode='" + activationCode + '\'' + ", headerUrl='" + headerUrl + '\'' + + ", studentCardUrl=" + studentCardUrl + + ", studentCode=" + studentCode + + ", realName=" + realName + + ", institute=" + institute + + ", professionalClass=" + professionalClass + ", createTime=" + createTime + '}'; } diff --git a/src/main/java/com/greate/community/service/UserService.java b/src/main/java/com/greate/community/service/UserService.java index 3de81d2..ccd183e 100644 --- a/src/main/java/com/greate/community/service/UserService.java +++ b/src/main/java/com/greate/community/service/UserService.java @@ -29,9 +29,6 @@ public class UserService implements CommunityConstant { @Autowired private UserMapper userMapper; - @Autowired - private MailClient mailClient; - @Autowired private RedisTemplate redisTemplate; diff --git a/src/main/java/com/greate/community/util/MailClient.java b/src/main/java/com/greate/community/util/MailClient.java deleted file mode 100644 index 8f7dceb..0000000 --- a/src/main/java/com/greate/community/util/MailClient.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.greate.community.util; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.mail.javamail.MimeMessageHelper; -import org.springframework.stereotype.Component; - -import javax.mail.MessagingException; -import javax.mail.internet.MimeMessage; - -/** - * 发送激活邮件(用于注册) - */ -@Component -public class MailClient { - - private static final Logger logger = LoggerFactory.getLogger(MailClient.class); - - @Autowired - private JavaMailSender mailSender; - - // 邮件发送方 - @Value("${spring.mail.username}") - private String from; - - /** - * 发送邮件 - * @param to 接收方 - * @param subject 邮件主题 - * @param content 邮件内容 - */ - public void sendMail(String to, String subject, String content) { - try { - MimeMessage mimeMessage = mailSender.createMimeMessage(); - MimeMessageHelper helper = new MimeMessageHelper(mimeMessage); - helper.setFrom(from); - helper.setTo(to); - helper.setSubject(subject); - helper.setText(content, true); - mailSender.send(helper.getMimeMessage()); - } catch (MessagingException e) { - logger.error("发送邮件失败" + e.getMessage()); - } - } - -} diff --git a/src/main/resources/mapper/user-mapper.xml b/src/main/resources/mapper/user-mapper.xml index 64bf577..c8bf51e 100644 --- a/src/main/resources/mapper/user-mapper.xml +++ b/src/main/resources/mapper/user-mapper.xml @@ -9,7 +9,7 @@ - id, username, password, salt, email, type, status, activation_code, header_url, create_time + id, username, password, salt, email, exp, rank, type, status, activation_code, header_url, create_time @@ -54,4 +54,14 @@ update user set password = #{password} where id = #{id} + + + update user set exp = #{exp} where id = #{id} + + + + + update user set rank = #{rank} where id = #{id} + + \ No newline at end of file -- Gitee From 921fc18ea4582d583551b2501421add9b058cc31 Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Wed, 2 Feb 2022 19:05:32 +0800 Subject: [PATCH 007/125] add tencent cos --- pom.xml | 6 + .../community/controller/CosController.java | 35 +++ .../community/util/CommunityConstant.java | 7 + .../community/util/CosStsClientUtil.java | 212 ++++++++++++++++++ .../resources/application-develop.properties | 4 + .../greate/community/CosStsClientTest.java | 158 +++++++++++++ 6 files changed, 422 insertions(+) create mode 100644 src/main/java/com/greate/community/controller/CosController.java create mode 100644 src/main/java/com/greate/community/util/CosStsClientUtil.java create mode 100644 src/test/java/com/greate/community/CosStsClientTest.java diff --git a/pom.xml b/pom.xml index 767d64d..1697fce 100644 --- a/pom.xml +++ b/pom.xml @@ -142,6 +142,12 @@ 7.2.23 + + com.qcloud + cos-sts_api + 3.1.0 + + com.github.ben-manes.caffeine diff --git a/src/main/java/com/greate/community/controller/CosController.java b/src/main/java/com/greate/community/controller/CosController.java new file mode 100644 index 0000000..795c906 --- /dev/null +++ b/src/main/java/com/greate/community/controller/CosController.java @@ -0,0 +1,35 @@ +package com.greate.community.controller; + +import com.greate.community.entity.Result; +import com.greate.community.util.CommunityConstant; +import com.greate.community.util.CosStsClientUtil; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Arrays; + +/** + * 类名称:CosController + * 类描述:获取腾讯云COS上传凭证 + * 创建人:CSUpipixia + * 创建时间:2022/2/2 18:08 + * + * @version v1.0 + */ +@RestController +public class CosController { + + @Autowired + private CosStsClientUtil cosStsClientUtil; + + @GetMapping("/cos/credential") + public Result getCredential(@RequestParam("type") String type) { + if (StringUtils.isBlank(type) || Arrays.asList(CommunityConstant.COS_TYPE).contains(type)) { + return new Result("fail", "1", "the request parameters are invalid"); + } + return new Result("success", Result.SUCCESS, cosStsClientUtil.getCredential()); + } +} diff --git a/src/main/java/com/greate/community/util/CommunityConstant.java b/src/main/java/com/greate/community/util/CommunityConstant.java index 90a6ee6..b35d270 100644 --- a/src/main/java/com/greate/community/util/CommunityConstant.java +++ b/src/main/java/com/greate/community/util/CommunityConstant.java @@ -1,5 +1,7 @@ package com.greate.community.util; +import java.util.HashMap; + /** * 常量 */ @@ -57,4 +59,9 @@ public interface CommunityConstant { // 权限:版主 String AUTHORITY_MODERATOR = "moderator"; + String[] COS_TYPE = new String[] { + "avatar", + "picture", + "studentCard" + }; } diff --git a/src/main/java/com/greate/community/util/CosStsClientUtil.java b/src/main/java/com/greate/community/util/CosStsClientUtil.java new file mode 100644 index 0000000..28d7db1 --- /dev/null +++ b/src/main/java/com/greate/community/util/CosStsClientUtil.java @@ -0,0 +1,212 @@ +package com.greate.community.util; + +import java.io.File; +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.TreeMap; + +import com.tencent.cloud.*; +import com.tencent.cloud.cos.util.Jackson; + +import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Data +@Component +public class CosStsClientUtil { + + @Value("${tencent.secretId}") + private String secretId; + + @Value("${tencent.secretKey}") + private String secretKey; + +// @Value("${https.proxyHost}") +// private String proxyHost; + + /** + * 基本的临时密钥申请,适合对一个桶内的一批对象路径,统一授予一批操作权限 + */ + public Response getCredential() { + TreeMap config = new TreeMap(); + + try { +// Properties properties = new Properties(); +// File configFile = new File("application-develop.properties"); +// properties.load(new FileInputStream(configFile)); + +// // 云 api 密钥 SecretId +// config.put("secretId", properties.getProperty("tencent.secretId")); +// // 云 api 密钥 SecretKey +// config.put("secretKey", properties.getProperty("tencent.secretKey")); + + // 云 api 密钥 SecretId + config.put("secretId", secretId); + // 云 api 密钥 SecretKey + config.put("secretKey", secretKey); + +// if (StringUtils.isNotEmpty(proxyHost)) { +// System.out.println("proxyHost is not empty"); +// System.setProperty("https.proxyHost", properties.getProperty("https.proxyHost")); +// System.setProperty("https.proxyPort", properties.getProperty("https.proxyPort")); +// } + + // 设置域名 + //config.put("host", "sts.internal.tencentcloudapi.com"); + + // 临时密钥有效时长,单位是秒 + config.put("durationSeconds", 1800); + + // 换成你的 bucket + config.put("bucket", "test-1306812178"); + // 换成 bucket 所在地区 + config.put("region", "ap-guangzhou"); + + // 可以通过 allowPrefixes 指定前缀数组, 例子: a.jpg 或者 a/* 或者 * (使用通配符*存在重大安全风险, 请谨慎评估使用) +// config.put("allowPrefixes", new String[] { +// "exampleobject", +// "exampleobject2" +// }); + + // 密钥的权限列表。简单上传和分片需要以下的权限,其他权限列表请看 https://cloud.tencent.com/document/product/436/31923 + String[] allowActions = new String[] { + // 简单上传 + "name/cos:PutObject", + "name/cos:PostObject", + // 分片上传 + "name/cos:InitiateMultipartUpload", + "name/cos:ListMultipartUploads", + "name/cos:ListParts", + "name/cos:UploadPart", + "name/cos:CompleteMultipartUpload" + }; + config.put("allowActions", allowActions); + + return CosStsClient.getCredential(config); + } catch (Exception e) { + e.printStackTrace(); + throw new IllegalArgumentException("no valid secret !"); + } + } + + /** + * 基本的临时密钥申请示例,适用于对多个桶的对应文件路径设置分别多条权限 + */ + public void testGetCredential2() { + TreeMap config = new TreeMap(); + + try { + Properties properties = new Properties(); + File configFile = new File("local.properties"); + properties.load(new FileInputStream(configFile)); + + // 固定密钥 SecretId + config.put("secretId", properties.getProperty("SecretId")); + // 固定密钥 SecretKey + config.put("secretKey", properties.getProperty("SecretKey")); + + if (properties.containsKey("https.proxyHost")) { + System.setProperty("https.proxyHost", properties.getProperty("https.proxyHost")); + System.setProperty("https.proxyPort", properties.getProperty("https.proxyPort")); + } + + // 临时密钥有效时长,单位是秒 + config.put("durationSeconds", 1800); + + //设置 policy + List scopes = new ArrayList(); + Scope scope = new Scope("name/cos:PutObject", "sts-sdk-test-1251668577", "ap-chengdu", "/test.txt"); + scopes.add(scope); + scopes.add(new Scope("name/cos:GetObject", "sts-sdk-test-1251668577", "ap-chengdu", "/test.txt")); + config.put("policy", CosStsClient.getPolicy(scopes)); + + Response credential = CosStsClient.getCredential(config); + System.out.println(Jackson.toJsonPrettyString(credential)); + } catch (Exception e) { + e.printStackTrace(); + throw new IllegalArgumentException("no valid secret !"); + } + } + + /** + * 更细致粒度设置的临时密钥申请示例,根据 https://cloud.tencent.com/document/product/598/10603 中列出的元素设置临时密钥权限 + */ + public void testGetCredential3() { + TreeMap config = new TreeMap(); + + try { + Properties properties = new Properties(); + File configFile = new File("local.properties"); + properties.load(new FileInputStream(configFile)); + + // 云 api 密钥 SecretId + config.put("secretId", properties.getProperty("SecretId")); + // 云 api 密钥 SecretKey + config.put("secretKey", properties.getProperty("SecretKey")); + + if (properties.containsKey("https.proxyHost")) { + System.setProperty("https.proxyHost", properties.getProperty("https.proxyHost")); + System.setProperty("https.proxyPort", properties.getProperty("https.proxyPort")); + } + + // 初始化 policy + Policy policy = new Policy(); + policy.setVersion("2.0"); + + // 开始构建一条 statement + Statement statement = new Statement(); + // 声明设置的结果是允许操作 + statement.setEffect("allow"); + // 添加一批操作权限 + statement.addActions(new String[] { + "name/cos:PutObject", + "name/cos:PostObject", + // 分片上传 + "name/cos:InitiateMultipartUpload", + "name/cos:ListMultipartUploads", + "name/cos:ListParts", + "name/cos:UploadPart", + "name/cos:CompleteMultipartUpload" + }); + // 添加一批资源路径 + // 一条资源的规则是:qcs::cos::uid/:/ + statement.addResources(new String[] { + String.format("qcs::cos:%s:uid/%s:%s/%s", + "ap-chengdu", "1251668577", "sts-sdk-test-1251668577", "exampleObject") + }); + + // 开始构建生效条件 condition + // 关于 condition 的详细设置规则可以参考 https://cloud.tencent.com/document/product/598/10604#.E5.AD.97.E7.AC.A6.E4.B8.B2.E8.AF.B4.E6.98.8E + ConditionTypeValue conditionTypeValue = new ConditionTypeValue(); + conditionTypeValue.setKey("qcs:ip"); + conditionTypeValue.addValue("10.10.10.10"); + conditionTypeValue.addValue("10.10.10.11"); + + // 增加规则 + statement.addCondition("ip_equal", conditionTypeValue); + + // 把一条 statement 添加到 policy + // 可以添加多条 + policy.addStatement(statement); + + // 临时密钥有效时长,单位是秒 + config.put("durationSeconds", 1800); + // 换成 bucket 所在地区 + config.put("region", "ap-chengdu"); + + // 将 Policy 示例转化成 String,可以使用任何 json 转化方式,这里是本 SDK 自带的推荐方式 + config.put("policy", Jackson.toJsonPrettyString(policy)); + + Response response = CosStsClient.getCredential(config); + System.out.println(Jackson.toJsonPrettyString(response)); + } catch (Exception e) { + e.printStackTrace(); + throw new IllegalArgumentException("no valid secret !"); + } + } +} + diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index 1c66080..b727fc5 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -79,6 +79,10 @@ qiniu.key.secret = Htl8C-_oHhy_FUjirGEdDo0ztDeAI_WXoBfDqfpi qiniu.bucket.header.name = header--community qiniu.bucket.header.url = http://qnvxyvq1p.hd-bkt.clouddn.com +# tencent cos +tencent.secretId = AKID1rR2RcXCcmgMo1yf7LK34uUosgEXaPyI +tencent.secretKey = 5uUnpb8OO9gxyjEVVFjywd3EApDLCm6B + # Caffeine caffeine.posts.max-size = 15 caffeine.posts.expire-seconds = 180 \ No newline at end of file diff --git a/src/test/java/com/greate/community/CosStsClientTest.java b/src/test/java/com/greate/community/CosStsClientTest.java new file mode 100644 index 0000000..3988a71 --- /dev/null +++ b/src/test/java/com/greate/community/CosStsClientTest.java @@ -0,0 +1,158 @@ +package com.greate.community; + +import java.io.File; +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.TreeMap; + +import com.greate.community.util.CosStsClientUtil; +import com.tencent.cloud.*; +import com.tencent.cloud.cos.util.Jackson; + +import lombok.Data; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +@Data +public class CosStsClientTest { + + @Autowired + private CosStsClientUtil cosStsClientUtil; + + /** + * 基本的临时密钥申请示例,适合对一个桶内的一批对象路径,统一授予一批操作权限 + */ + @Test + public void testGetCredential() { + try { + Response response = cosStsClientUtil.getCredential(); + System.out.println(response.credentials.tmpSecretId); + System.out.println(response.credentials.tmpSecretKey); + System.out.println(response.credentials.sessionToken); + } catch (Exception e) { + e.printStackTrace(); + throw new IllegalArgumentException("no valid secret !"); + } + } + + /** + * 基本的临时密钥申请示例,适用于对多个桶的对应文件路径设置分别多条权限 + */ + @Test + public void testGetCredential2() { + TreeMap config = new TreeMap(); + + try { + Properties properties = new Properties(); + File configFile = new File("local.properties"); + properties.load(new FileInputStream(configFile)); + + // 固定密钥 SecretId + config.put("secretId", properties.getProperty("SecretId")); + // 固定密钥 SecretKey + config.put("secretKey", properties.getProperty("SecretKey")); + + if (properties.containsKey("https.proxyHost")) { + System.setProperty("https.proxyHost", properties.getProperty("https.proxyHost")); + System.setProperty("https.proxyPort", properties.getProperty("https.proxyPort")); + } + + // 临时密钥有效时长,单位是秒 + config.put("durationSeconds", 1800); + + //设置 policy + List scopes = new ArrayList(); + Scope scope = new Scope("name/cos:PutObject", "sts-sdk-test-1251668577", "ap-chengdu", "/test.txt"); + scopes.add(scope); + scopes.add(new Scope("name/cos:GetObject", "sts-sdk-test-1251668577", "ap-chengdu", "/test.txt")); + config.put("policy", CosStsClient.getPolicy(scopes)); + + Response credential = CosStsClient.getCredential(config); + System.out.println(Jackson.toJsonPrettyString(credential)); + } catch (Exception e) { + e.printStackTrace(); + throw new IllegalArgumentException("no valid secret !"); + } + } + + /** + * 更细致粒度设置的临时密钥申请示例,根据 https://cloud.tencent.com/document/product/598/10603 中列出的元素设置临时密钥权限 + */ + @Test + public void testGetCredential3() { + TreeMap config = new TreeMap(); + + try { + Properties properties = new Properties(); + File configFile = new File("local.properties"); + properties.load(new FileInputStream(configFile)); + + // 云 api 密钥 SecretId + config.put("secretId", properties.getProperty("SecretId")); + // 云 api 密钥 SecretKey + config.put("secretKey", properties.getProperty("SecretKey")); + + if (properties.containsKey("https.proxyHost")) { + System.setProperty("https.proxyHost", properties.getProperty("https.proxyHost")); + System.setProperty("https.proxyPort", properties.getProperty("https.proxyPort")); + } + + // 初始化 policy + Policy policy = new Policy(); + policy.setVersion("2.0"); + + // 开始构建一条 statement + Statement statement = new Statement(); + // 声明设置的结果是允许操作 + statement.setEffect("allow"); + // 添加一批操作权限 + statement.addActions(new String[] { + "name/cos:PutObject", + "name/cos:PostObject", + // 分片上传 + "name/cos:InitiateMultipartUpload", + "name/cos:ListMultipartUploads", + "name/cos:ListParts", + "name/cos:UploadPart", + "name/cos:CompleteMultipartUpload" + }); + // 添加一批资源路径 + // 一条资源的规则是:qcs::cos::uid/:/ + statement.addResources(new String[] { + String.format("qcs::cos:%s:uid/%s:%s/%s", + "ap-chengdu", "1251668577", "sts-sdk-test-1251668577", "exampleObject") + }); + + // 开始构建生效条件 condition + // 关于 condition 的详细设置规则可以参考 https://cloud.tencent.com/document/product/598/10604#.E5.AD.97.E7.AC.A6.E4.B8.B2.E8.AF.B4.E6.98.8E + ConditionTypeValue conditionTypeValue = new ConditionTypeValue(); + conditionTypeValue.setKey("qcs:ip"); + conditionTypeValue.addValue("10.10.10.10"); + conditionTypeValue.addValue("10.10.10.11"); + + // 增加规则 + statement.addCondition("ip_equal", conditionTypeValue); + + // 把一条 statement 添加到 policy + // 可以添加多条 + policy.addStatement(statement); + + // 临时密钥有效时长,单位是秒 + config.put("durationSeconds", 1800); + // 换成 bucket 所在地区 + config.put("region", "ap-chengdu"); + + // 将 Policy 示例转化成 String,可以使用任何 json 转化方式,这里是本 SDK 自带的推荐方式 + config.put("policy", Jackson.toJsonPrettyString(policy)); + + Response response = CosStsClient.getCredential(config); + System.out.println(Jackson.toJsonPrettyString(response)); + } catch (Exception e) { + e.printStackTrace(); + throw new IllegalArgumentException("no valid secret !"); + } + } + +} -- Gitee From 29e499b356149fa7cf3c08d2268be67cee95706b Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Thu, 3 Feb 2022 20:00:19 +0800 Subject: [PATCH 008/125] update cos service --- .../community/config/SecurityConfig.java | 3 +- .../community/controller/CosController.java | 14 ++++-- .../greate/community/service/CosService.java | 27 ++++++++++ .../community/util/CommunityConstant.java | 14 ++++-- .../community/util/CosStsClientUtil.java | 50 +++++++++---------- .../resources/application-develop.properties | 2 +- .../greate/community/CosStsClientTest.java | 2 +- 7 files changed, 74 insertions(+), 38 deletions(-) create mode 100644 src/main/java/com/greate/community/service/CosService.java diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index 3afb60e..501dc4f 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -59,7 +59,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm "/notice/**", "/like", "/follow", - "/unfollow" + "/unfollow", + "/cos/credential" ) .hasAnyAuthority( AUTHORITY_USER, diff --git a/src/main/java/com/greate/community/controller/CosController.java b/src/main/java/com/greate/community/controller/CosController.java index 795c906..cb45fdf 100644 --- a/src/main/java/com/greate/community/controller/CosController.java +++ b/src/main/java/com/greate/community/controller/CosController.java @@ -1,8 +1,10 @@ package com.greate.community.controller; import com.greate.community.entity.Result; +import com.greate.community.service.CosService; import com.greate.community.util.CommunityConstant; import com.greate.community.util.CosStsClientUtil; +import com.tencent.cloud.Response; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; @@ -20,16 +22,20 @@ import java.util.Arrays; * @version v1.0 */ @RestController -public class CosController { +public class CosController extends BaseController { @Autowired - private CosStsClientUtil cosStsClientUtil; + private CosService cosService; @GetMapping("/cos/credential") public Result getCredential(@RequestParam("type") String type) { - if (StringUtils.isBlank(type) || Arrays.asList(CommunityConstant.COS_TYPE).contains(type)) { + if (StringUtils.isBlank(type)) { return new Result("fail", "1", "the request parameters are invalid"); } - return new Result("success", Result.SUCCESS, cosStsClientUtil.getCredential()); + Response response = cosService.getCredential(type, getUser().getId()); + if (response == null) { + return new Result("fail", "1", "the request parameters are invalid"); + } + return new Result("success", Result.SUCCESS, response); } } diff --git a/src/main/java/com/greate/community/service/CosService.java b/src/main/java/com/greate/community/service/CosService.java new file mode 100644 index 0000000..bdfe2c3 --- /dev/null +++ b/src/main/java/com/greate/community/service/CosService.java @@ -0,0 +1,27 @@ +package com.greate.community.service; + +import com.greate.community.util.CommunityConstant; +import com.greate.community.util.CosStsClientUtil; +import com.tencent.cloud.Response; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 类名称:CosService + * 类描述:对象存储服务类 + * 创建人:CSUpipixia + * 创建时间:2022/2/3 19:21 + * + * @version v1.0 + */ +@Service +public class CosService { + + @Autowired + private CosStsClientUtil cosStsClientUtil; + + public Response getCredential(String type, int userId) { + + return cosStsClientUtil.getCredential(type, String.valueOf(userId)); + } +} diff --git a/src/main/java/com/greate/community/util/CommunityConstant.java b/src/main/java/com/greate/community/util/CommunityConstant.java index b35d270..00c3d69 100644 --- a/src/main/java/com/greate/community/util/CommunityConstant.java +++ b/src/main/java/com/greate/community/util/CommunityConstant.java @@ -59,9 +59,13 @@ public interface CommunityConstant { // 权限:版主 String AUTHORITY_MODERATOR = "moderator"; - String[] COS_TYPE = new String[] { - "avatar", - "picture", - "studentCard" - }; + // 对象存储类型:头像 + String COS_TYPE_AVATAR = "avatar"; + + // 对象存储类型:图片 + String COS_TYPE_PICTURE = "picture"; + + // 对象存储类型:学生证 + String COS_TYPE_STUDENT_CARD = "studentCard"; + } diff --git a/src/main/java/com/greate/community/util/CosStsClientUtil.java b/src/main/java/com/greate/community/util/CosStsClientUtil.java index 28d7db1..48880c8 100644 --- a/src/main/java/com/greate/community/util/CosStsClientUtil.java +++ b/src/main/java/com/greate/community/util/CosStsClientUtil.java @@ -25,57 +25,55 @@ public class CosStsClientUtil { @Value("${tencent.secretKey}") private String secretKey; -// @Value("${https.proxyHost}") -// private String proxyHost; + @Value("${https.proxyHost:}") + private String proxyHost; + + @Value("${https.proxyPort:}") + private String proxyPort; /** * 基本的临时密钥申请,适合对一个桶内的一批对象路径,统一授予一批操作权限 */ - public Response getCredential() { + public Response getCredential(String type, String... allowPrefixes) { TreeMap config = new TreeMap(); try { -// Properties properties = new Properties(); -// File configFile = new File("application-develop.properties"); -// properties.load(new FileInputStream(configFile)); - -// // 云 api 密钥 SecretId -// config.put("secretId", properties.getProperty("tencent.secretId")); -// // 云 api 密钥 SecretKey -// config.put("secretKey", properties.getProperty("tencent.secretKey")); // 云 api 密钥 SecretId config.put("secretId", secretId); // 云 api 密钥 SecretKey config.put("secretKey", secretKey); -// if (StringUtils.isNotEmpty(proxyHost)) { -// System.out.println("proxyHost is not empty"); -// System.setProperty("https.proxyHost", properties.getProperty("https.proxyHost")); -// System.setProperty("https.proxyPort", properties.getProperty("https.proxyPort")); -// } + if (StringUtils.isNotEmpty(proxyHost)) { + System.setProperty("https.proxyHost", proxyHost); + System.setProperty("https.proxyPort", proxyPort); + } - // 设置域名 - //config.put("host", "sts.internal.tencentcloudapi.com"); + // 如果您使用了腾讯云 cvm,可以设置内部域名 +// config.put("host", "sts.internal.tencentcloudapi.com"); - // 临时密钥有效时长,单位是秒 + // 临时密钥有效时长,单位是秒,默认 1800 秒,目前主账号最长 2 小时(即 7200 秒),子账号最长 36 小时(即 129600)秒 config.put("durationSeconds", 1800); - // 换成你的 bucket + // bucket名称 config.put("bucket", "test-1306812178"); - // 换成 bucket 所在地区 + // bucket所在地区 config.put("region", "ap-guangzhou"); - // 可以通过 allowPrefixes 指定前缀数组, 例子: a.jpg 或者 a/* 或者 * (使用通配符*存在重大安全风险, 请谨慎评估使用) -// config.put("allowPrefixes", new String[] { -// "exampleobject", -// "exampleobject2" -// }); + // 这里改成允许的路径前缀,可以根据自己网站的用户登录态判断允许上传的具体路径 + // 列举几种典型的前缀授权场景: + // 1、允许访问所有对象:"*" + // 2、允许访问指定的对象:"a/a1.txt", "b/b1.txt" + // 3、允许访问指定前缀的对象:"a*", "a/*", "b/*" + // 如果填写了“*”,将允许用户访问所有资源;除非业务需要,否则请按照最小权限原则授予用户相应的访问权限范围(使用通配符*存在重大安全风险, 请谨慎评估使用) + config.put("allowPrefixes", allowPrefixes); + // 密钥的权限列表。必须在这里指定本次临时密钥所需要的权限。 // 密钥的权限列表。简单上传和分片需要以下的权限,其他权限列表请看 https://cloud.tencent.com/document/product/436/31923 String[] allowActions = new String[] { // 简单上传 "name/cos:PutObject", + // 表单上传、小程序上传 "name/cos:PostObject", // 分片上传 "name/cos:InitiateMultipartUpload", diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index b727fc5..ad5cd3d 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -16,7 +16,7 @@ community.path.editormdUploadPath = E:/GreateCommunity/src/main/resources/static spring.thymeleaf.cache=false # MySQL -spring.datasource.url = jdbc:mysql://gz-cdb-ejk0kptx.sql.tencentcdb.com:57734/bbs?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong +spring.datasource.url = jdbc:mysql://gz-cdb-ejk0kptx.sql.tencentcdb.com:57734/bbs-dev?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong spring.datasource.username = root spring.datasource.password = Root@2021 # Mysql 5.0+ 汾ʹ com.mysql.jdbc.Driver diff --git a/src/test/java/com/greate/community/CosStsClientTest.java b/src/test/java/com/greate/community/CosStsClientTest.java index 3988a71..938129e 100644 --- a/src/test/java/com/greate/community/CosStsClientTest.java +++ b/src/test/java/com/greate/community/CosStsClientTest.java @@ -27,7 +27,7 @@ public class CosStsClientTest { @Test public void testGetCredential() { try { - Response response = cosStsClientUtil.getCredential(); + Response response = cosStsClientUtil.getCredential("", ""); System.out.println(response.credentials.tmpSecretId); System.out.println(response.credentials.tmpSecretKey); System.out.println(response.credentials.sessionToken); -- Gitee From 2f4e5c2853a29fb65727785b792f582dbe6fe49e Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Mon, 7 Feb 2022 19:43:30 +0800 Subject: [PATCH 009/125] add: get user by ticket --- .../community/config/SecurityConfig.java | 1 + .../community/controller/UserController.java | 150 +----------------- .../community/util/CosStsClientUtil.java | 1 + 3 files changed, 7 insertions(+), 145 deletions(-) diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index 501dc4f..7fbf6e4 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -50,6 +50,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm http.cors().and().csrf().disable() .authorizeRequests() .antMatchers( + "/user/get", "/user/setting", "/user/upload", "/discuss/add", diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 835a12b..953d420 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -62,24 +62,13 @@ public class UserController extends BaseController implements CommunityConstant private String headerBucketUrl; /** - * 跳转至账号设置界面 + * 通过ticket获取user * @return */ - @GetMapping("/setting") - public String getSettingPage(Model model) { - // 生成上传文件的名称 - String fileName = CommunityUtil.generateUUID(); - model.addAttribute("fileName", fileName); - - // 设置响应信息(qiniu 的规定写法) - StringMap policy = new StringMap(); - policy.put("returnBody", CommunityUtil.getJSONString(0)); - // 生成上传到 qiniu 的凭证(qiniu 的规定写法) - Auth auth = Auth.create(accessKey, secretKey); - String uploadToken = auth.uploadToken(headerBucketName, fileName, 3600, policy); - model.addAttribute("uploadToken", uploadToken); - - return "/site/setting"; + @GetMapping("/get") + public Result getUserByTicket() { + User user = getUser(); + return new Result("success", Result.SUCCESS, userService.findUserById(user.getId())); } /** @@ -128,27 +117,6 @@ public class UserController extends BaseController implements CommunityConstant return new Result("success", Result.SUCCESS, "修改密码成功"); } -// public String updatePassword(String oldPassword, String newPassword, Model model) { -// // 验证原密码是否正确 -// User user = hostHolder.getUser(); -// String md5OldPassword = CommunityUtil.md5(oldPassword + user.getSalt()); -// if (!user.getPassword().equals(md5OldPassword)) { -// model.addAttribute("oldPasswordError", "原密码错误"); -// return "/site/setting"; -// } -// -// // 判断新密码是否合法 -// String md5NewPassword = CommunityUtil.md5(newPassword + user.getSalt()); -// if (user.getPassword().equals(md5NewPassword)) { -// model.addAttribute("newPasswordError", "新密码和原密码相同"); -// return "/site/setting"; -// } -// -// // 修改用户密码 -// userService.updatePassword(user.getId(), newPassword); -// -// return "redirect:/index"; -// } /** * 进入个人主页 @@ -183,34 +151,6 @@ public class UserController extends BaseController implements CommunityConstant return new Result("success", Result.SUCCESS, jsonObject); } -// public String getProfilePage(@PathVariable("userId") int userId, Model model) { -// JSONObject jsonObject = new JSONObject(); -// User user = userService.findUserById(userId); -// if (user == null) { -// throw new RuntimeException("该用户不存在"); -// } -// -// // 用户 -// model.addAttribute("user", user); -// // 获赞数量 -// int userLikeCount = likeService.findUserLikeCount(userId); -// model.addAttribute("userLikeCount", userLikeCount); -// // 关注数量 -// long followeeCount = followService.findFolloweeCount(userId, ENTITY_TYPE_USER); -// model.addAttribute("followeeCount", followeeCount); -// // 粉丝数量 -// long followerCount = followService.findFollowerCount(ENTITY_TYPE_USER, userId); -// model.addAttribute("followerCount", followerCount); -// // 当前登录用户是否已关注该用户 -// boolean hasFollowed = false; -// if (hostHolder.getUser() != null) { -// hasFollowed = followService.hasFollowed(hostHolder.getUser().getId(), ENTITY_TYPE_USER, userId); -// } -// model.addAttribute("hasFollowed", hasFollowed); -// model.addAttribute("tab", "profile"); // 该字段用于指示标签栏高亮 -// -// return "/site/profile"; -// } /** * 进入我的帖子(查询某个用户的帖子列表) @@ -253,40 +193,6 @@ public class UserController extends BaseController implements CommunityConstant return new Result("success", Result.SUCCESS, jsonObject); } -// public String getMyDiscussPosts(@PathVariable("userId") int userId, Page page, Model model) { -// User user = userService.findUserById(userId); -// if (user == null) { -// throw new RuntimeException("该用户不存在"); -// } -// model.addAttribute("user", user); -// -// // 该用户的帖子总数 -// int rows = discussPostService.findDiscussPostRows(userId); -// model.addAttribute("rows", rows); -// -// page.setLimit(5); -// page.setPath("/user/discuss/" + userId); -// page.setRows(rows); -// -// // 分页查询(按照最新查询) -// List list = discussPostService.findDiscussPosts(userId, page.getOffset(), page.getLimit(), 0); -// // 封装帖子和该帖子对应的用户信息 -// List> discussPosts = new ArrayList<>(); -// if (list != null) { -// for (DiscussPost post : list) { -// Map map = new HashMap<>(); -// map.put("post", post); -// long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId()); -// map.put("likeCount", likeCount); -// -// discussPosts.add(map); -// } -// } -// model.addAttribute("discussPosts", discussPosts); -// model.addAttribute("tab", "mypost"); // 该字段用于指示标签栏高亮 -// -// return "/site/my-post"; -// } /** * 进入我的评论/回复(查询某个用户的评论/回复列表) @@ -340,50 +246,4 @@ public class UserController extends BaseController implements CommunityConstant return new Result("success", Result.SUCCESS, jsonObject); } -// public String getMyComments(@PathVariable("userId") int userId, Page page, Model model) { -// User user = userService.findUserById(userId); -// if (user == null) { -// throw new RuntimeException("该用户不存在"); -// } -// model.addAttribute("user", user); -// -// // 该用户的评论/回复总数 -// int commentCounts = commentService.findCommentCountByUserId(userId); -// model.addAttribute("commentCounts", commentCounts); -// -// page.setLimit(5); -// page.setPath("/user/comment/" + userId); -// page.setRows(commentCounts); -// -// // 分页查询 -// List list = commentService.findCommentByUserId(userId, page.getOffset(), page.getLimit()); -// // 封装评论和该评论对应的帖子信息 -// List> comments = new ArrayList<>(); -// if (list != null) { -// for (Comment comment : list) { -// Map map = new HashMap<>(); -// map.put("comment", comment); -// // 显示评论/回复对应的文章信息 -// if (comment.getEntityType() == ENTITY_TYPE_POST) { -// // 如果是对帖子的评论,则直接查询 target_id 即可 -// DiscussPost post = discussPostService.findDiscussPostById(comment.getEntityId()); -// map.put("post", post); -// } -// else if (comment.getEntityType() == ENTITY_TYPE_COMMENT) { -// // 如过是对评论的回复,则先根据该回复的 target_id 查询评论的 id, 再根据该评论的 target_id 查询帖子的 id -// Comment targetComment = commentService.findCommentById(comment.getEntityId()); -// DiscussPost post = discussPostService.findDiscussPostById(targetComment.getEntityId()); -// map.put("post", post); -// } -// -// comments.add(map); -// } -// } -// model.addAttribute("comments", comments); -// model.addAttribute("tab", "myreply"); // 该字段用于指示标签栏高亮 -// -// return "/site/my-reply"; -// -// } - } diff --git a/src/main/java/com/greate/community/util/CosStsClientUtil.java b/src/main/java/com/greate/community/util/CosStsClientUtil.java index 48880c8..5aa75c6 100644 --- a/src/main/java/com/greate/community/util/CosStsClientUtil.java +++ b/src/main/java/com/greate/community/util/CosStsClientUtil.java @@ -60,6 +60,7 @@ public class CosStsClientUtil { // bucket所在地区 config.put("region", "ap-guangzhou"); + // /userid/* // 这里改成允许的路径前缀,可以根据自己网站的用户登录态判断允许上传的具体路径 // 列举几种典型的前缀授权场景: // 1、允许访问所有对象:"*" -- Gitee From 7fc7b101f3178d6e4dc5b7ff6654335f4939b3f7 Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Mon, 7 Feb 2022 20:17:31 +0800 Subject: [PATCH 010/125] merge dev-xzx --- pom.xml | 22 ++ .../auth/wechatauth/domain/UserWeChat.java | 64 +++++ .../properties/WeChatProperties.java | 28 +++ .../auth/wechatauth/sso/ClientResources.java | 29 +++ .../wechatauth/sso/SocialClientResource.java | 33 +++ .../wechat/WeChatAuthorizationConfig.java | 107 ++++++++ .../WeChatOAuth2ClientContextFilter.java | 68 +++++ .../wechat/WeChatRequestEnhancer.java | 35 +++ .../wechatauth/wechat/WeChatRestTemplate.java | 59 +++++ .../wechat/WeChatUserPrincipalExtractor.java | 34 +++ .../community/config/SecurityConfig.java | 133 +++++++++- .../community/controller/DataController.java | 2 - .../controller/DiscussPostController.java | 2 +- .../controller/FollowController.java | 4 +- .../community/controller/LikeController.java | 33 --- .../community/controller/LoginController.java | 233 +++++------------- .../controller/MessageController.java | 51 +--- .../controller/SearchController.java | 32 +-- .../community/controller/UserController.java | 8 +- .../resources/application-develop.properties | 24 +- .../java/com/greate/community/MailTests.java | 25 ++ 21 files changed, 735 insertions(+), 291 deletions(-) create mode 100644 src/main/java/com/greate/community/auth/wechatauth/domain/UserWeChat.java create mode 100644 src/main/java/com/greate/community/auth/wechatauth/properties/WeChatProperties.java create mode 100644 src/main/java/com/greate/community/auth/wechatauth/sso/ClientResources.java create mode 100644 src/main/java/com/greate/community/auth/wechatauth/sso/SocialClientResource.java create mode 100644 src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatAuthorizationConfig.java create mode 100644 src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatOAuth2ClientContextFilter.java create mode 100644 src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatRequestEnhancer.java create mode 100644 src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatRestTemplate.java create mode 100644 src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatUserPrincipalExtractor.java create mode 100644 src/test/java/com/greate/community/MailTests.java diff --git a/pom.xml b/pom.xml index 1697fce..a3fb457 100644 --- a/pom.xml +++ b/pom.xml @@ -116,6 +116,13 @@ spring-boot-starter-security + + + org.springframework.security.oauth.boot + spring-security-oauth2-autoconfigure + 2.1.4.RELEASE + + org.thymeleaf.extras @@ -161,6 +168,12 @@ 5.7.20 + + + org.springframework.boot + spring-boot-configuration-processor + + org.projectlombok lombok @@ -175,6 +188,15 @@ org.springframework.boot spring-boot-maven-plugin + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + diff --git a/src/main/java/com/greate/community/auth/wechatauth/domain/UserWeChat.java b/src/main/java/com/greate/community/auth/wechatauth/domain/UserWeChat.java new file mode 100644 index 0000000..fe817b6 --- /dev/null +++ b/src/main/java/com/greate/community/auth/wechatauth/domain/UserWeChat.java @@ -0,0 +1,64 @@ +package com.greate.community.auth.wechatauth.domain; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * + * * https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842 + * *

+ * * openid 用户的唯一标识 + * * nickname 用户昵称 + * * sex 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知 + * * province 用户个人资料填写的省份 + * * city 普通用户个人资料填写的城市 + * * country 国家,如中国为CN + * * headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。 + * * privilege 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom) + * * unionid 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。 + * + * @author xzx + * @date 2022/1/29 18:32 + */ +@Data +@Accessors(chain = true) +@JsonIgnoreProperties(ignoreUnknown = true) +public class UserWeChat { + + private Integer id; + + @JsonProperty("openid") + private String openId; + + @JsonProperty("appid") + private String appId; + + @JsonProperty("nickname") + private String nickName; + + private String sex; + + private String language; + + private String city; + + private String country; + + @JsonProperty("province") + private String province; + + @JsonProperty("headimgurl") + private String headimgurl; + + @JsonProperty("bind_wechat_time") + private Long bondTime; + + @JsonProperty("update_wechat_time") + private Long updatedTime; + + @JsonProperty("unionid") + private String unionId; + +} diff --git a/src/main/java/com/greate/community/auth/wechatauth/properties/WeChatProperties.java b/src/main/java/com/greate/community/auth/wechatauth/properties/WeChatProperties.java new file mode 100644 index 0000000..dfa70b7 --- /dev/null +++ b/src/main/java/com/greate/community/auth/wechatauth/properties/WeChatProperties.java @@ -0,0 +1,28 @@ +package com.greate.community.auth.wechatauth.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author xzx + * @date 2022/1/29 18:29 + */ +@ConfigurationProperties("wechat.config") +@Component +@Data +public class WeChatProperties { + + private String appId = "appid"; + + private String clientId = "client_id"; + + private String secret = "secret"; + + private String clientSecret = "client_secret"; + + private String state = "state"; + + private String wechatRedirect = "wechat_redirect"; + +} diff --git a/src/main/java/com/greate/community/auth/wechatauth/sso/ClientResources.java b/src/main/java/com/greate/community/auth/wechatauth/sso/ClientResources.java new file mode 100644 index 0000000..2458062 --- /dev/null +++ b/src/main/java/com/greate/community/auth/wechatauth/sso/ClientResources.java @@ -0,0 +1,29 @@ +package com.greate.community.auth.wechatauth.sso; + +import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; + +/** + * oauth2 认证信息注入 + * + * @author xzx + * @date 2022/1/29 18:37 + */ +public class ClientResources { + + @NestedConfigurationProperty + private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails(); + + @NestedConfigurationProperty + private ResourceServerProperties resource = new ResourceServerProperties(); + + public AuthorizationCodeResourceDetails getClient() { + return client; + } + + public ResourceServerProperties getResource() { + return resource; + } + +} diff --git a/src/main/java/com/greate/community/auth/wechatauth/sso/SocialClientResource.java b/src/main/java/com/greate/community/auth/wechatauth/sso/SocialClientResource.java new file mode 100644 index 0000000..264a490 --- /dev/null +++ b/src/main/java/com/greate/community/auth/wechatauth/sso/SocialClientResource.java @@ -0,0 +1,33 @@ +package com.greate.community.auth.wechatauth.sso; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * + * 第三方登录授权认证 + * + * @author xzx + * @date 2022/1/29 18:38 + */ +@Configuration +public class SocialClientResource { + + /** + * wechat client config + * + * @return clientResource + */ + @Bean + @ConfigurationProperties("wechat") + public ClientResources weChat() { + return new ClientResources(); + } + + /** + * other client config + * ... + */ + +} diff --git a/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatAuthorizationConfig.java b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatAuthorizationConfig.java new file mode 100644 index 0000000..ec389b0 --- /dev/null +++ b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatAuthorizationConfig.java @@ -0,0 +1,107 @@ +package com.greate.community.auth.wechatauth.wechat; + +import com.greate.community.auth.wechatauth.sso.ClientResources; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.security.oauth2.resource.PrincipalExtractor; +import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.client.OAuth2ClientContext; +import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter; +import org.springframework.security.oauth2.client.token.RequestEnhancer; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +/** + * * https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842 + * * 微信登录流程 + * + * @author xzx + * @date 2022/1/29 18:40 + */ +@Configuration +@EnableOAuth2Client +@Order(200) +public class WeChatAuthorizationConfig { + + private static final String WE_CHAT_LOGIN_URL = "/wechat/oauth2/login";//微信认证登录的URL + private static final String WE_CHAT_AUTHENTICATION_SUCCESS_URL = "/wechat/login";//认证成功后跳转的URL + + private final OAuth2ClientContext context; + private final RequestEnhancer requestEnhancer; + private final PrincipalExtractor principalExtractor; + private final ClientResources clientResources; + + public WeChatAuthorizationConfig( + @Qualifier("oauth2ClientContext") OAuth2ClientContext context, + @Qualifier("weChatRequestEnhancer") RequestEnhancer requestEnhancer, + @Qualifier("weChatUserPrincipalExtractor") PrincipalExtractor principalExtractor, + @Qualifier("weChat") ClientResources clientResources + ) { + this.context = context; + this.requestEnhancer = requestEnhancer; + this.principalExtractor = principalExtractor; + this.clientResources = clientResources; + } + + private static List> convertMediaTypes() { + MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter(); + messageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.TEXT_PLAIN)); + return Collections.singletonList(messageConverter); + } + + private AuthorizationCodeAccessTokenProvider accessTokenProvider() { + AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider(); + provider.setAuthorizationRequestEnhancer(requestEnhancer); + provider.setTokenRequestEnhancer(requestEnhancer); + provider.setMessageConverters(WeChatAuthorizationConfig.convertMediaTypes()); + return provider; + } + + private WeChatRestTemplate restTemplate() { + WeChatRestTemplate template = new WeChatRestTemplate(clientResources.getClient(), context); + template.setAccessTokenProvider(accessTokenProvider()); + template.setMessageConverters(WeChatAuthorizationConfig.convertMediaTypes()); + return template; + } + + public OAuth2ClientAuthenticationProcessingFilter weChatFilter() { + OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(WE_CHAT_LOGIN_URL); + + + filter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler() { + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + this.setDefaultTargetUrl(WE_CHAT_AUTHENTICATION_SUCCESS_URL); + super.onAuthenticationSuccess(request, response, authentication); + } + }); + + + + WeChatRestTemplate template = restTemplate(); + filter.setRestTemplate(template); + UserInfoTokenServices tokenServices = tokenServices(template); + filter.setTokenServices(tokenServices); + return filter; + } + + private UserInfoTokenServices tokenServices(WeChatRestTemplate template) { + UserInfoTokenServices tokenServices = new UserInfoTokenServices( + clientResources.getResource().getUserInfoUri(), clientResources.getResource().getClientId()); + tokenServices.setRestTemplate(template); + tokenServices.setPrincipalExtractor(principalExtractor); + return tokenServices; + } +} diff --git a/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatOAuth2ClientContextFilter.java b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatOAuth2ClientContextFilter.java new file mode 100644 index 0000000..6c15db0 --- /dev/null +++ b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatOAuth2ClientContextFilter.java @@ -0,0 +1,68 @@ +package com.greate.community.auth.wechatauth.wechat; + +import com.greate.community.auth.wechatauth.properties.WeChatProperties; +import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter; +import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; +import org.springframework.security.web.DefaultRedirectStrategy; +import org.springframework.security.web.RedirectStrategy; +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.web.util.UriComponentsBuilder; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 扩展 OAuth2ClientContextFilter + * 重写请求的字段,按顺序设置查询参数 + *

+ * client_id -> appid,添加 #wechat_redirect + * + */ +@Component +public class WeChatOAuth2ClientContextFilter extends OAuth2ClientContextFilter { + + private RedirectStrategy redirectStrategy; + private final WeChatProperties weChatProperties; + + public WeChatOAuth2ClientContextFilter(WeChatProperties weChatProperties) { + this.weChatProperties = weChatProperties; + redirectStrategy = new DefaultRedirectStrategy(); + } + + @Override + protected void redirectUser(UserRedirectRequiredException e, HttpServletRequest request, HttpServletResponse response) throws IOException { + UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(e.getRedirectUri()); + + e.getRequestParams().put(weChatProperties.getAppId(), e.getRequestParams().remove(weChatProperties.getClientId())); + + Map> map = e.getRequestParams().entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, it -> Collections.singletonList(it.getValue()))); + map.put(weChatProperties.getState(), Collections.singletonList(e.getStateKey())); + + //按照微信接口要求,使得参数按照一定顺序排列,没按照规定顺序的话,接口会请求失败 + LinkedMultiValueMap linkedMultiValueMap = new LinkedMultiValueMap<>(); + linkedMultiValueMap.put("appid", map.remove("appid")); + linkedMultiValueMap.put("redirect_uri", map.remove("redirect_uri")); + linkedMultiValueMap.put("response_type", map.remove("response_type")); + linkedMultiValueMap.put("scope", map.remove("scope")); + linkedMultiValueMap.put("state", map.remove("state")); + + builder.queryParams(linkedMultiValueMap); + + builder.fragment(weChatProperties.getWechatRedirect()); + + this.redirectStrategy.sendRedirect(request, response, builder.build().encode().toUriString()); + } + + @Override + public void setRedirectStrategy(RedirectStrategy redirectStrategy) { + this.redirectStrategy = redirectStrategy; + } + +} diff --git a/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatRequestEnhancer.java b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatRequestEnhancer.java new file mode 100644 index 0000000..c6343d1 --- /dev/null +++ b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatRequestEnhancer.java @@ -0,0 +1,35 @@ +package com.greate.community.auth.wechatauth.wechat; + +import com.greate.community.auth.wechatauth.properties.WeChatProperties; +import lombok.extern.log4j.Log4j2; +import org.springframework.http.HttpHeaders; +import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.client.token.AccessTokenRequest; +import org.springframework.security.oauth2.client.token.RequestEnhancer; +import org.springframework.stereotype.Component; +import org.springframework.util.MultiValueMap; + +/** + * 实现 RequestEnhancer 接口 + * client_id -> appid + * client_secret -> secret + * + */ +@Component +@Log4j2 +public class WeChatRequestEnhancer implements RequestEnhancer { + private final WeChatProperties weChatProperties; + + public WeChatRequestEnhancer(WeChatProperties weChatProperties) { + this.weChatProperties = weChatProperties; + } + + @Override + public void enhance(AccessTokenRequest request, OAuth2ProtectedResourceDetails resource, MultiValueMap form, HttpHeaders headers) { + form.put(weChatProperties.getAppId(), form.remove(weChatProperties.getClientId())); + form.put(weChatProperties.getSecret(), form.remove(weChatProperties.getClientSecret())); + if (log.isDebugEnabled()) { + log.debug("form = {}", form.toSingleValueMap()); + } + } +} diff --git a/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatRestTemplate.java b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatRestTemplate.java new file mode 100644 index 0000000..5594fe9 --- /dev/null +++ b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatRestTemplate.java @@ -0,0 +1,59 @@ +package com.greate.community.auth.wechatauth.wechat; + +import org.springframework.security.oauth2.client.OAuth2ClientContext; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.common.OAuth2AccessToken; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +/** + * {@link org.springframework.security.oauth2.client.OAuth2RestTemplate#appendQueryParameter} + * 参考 appendQueryParameter,重写某些字段 + */ +public class WeChatRestTemplate extends OAuth2RestTemplate { + + WeChatRestTemplate(OAuth2ProtectedResourceDetails resource, OAuth2ClientContext context) { + super(resource, context); + } + + @Override + protected URI appendQueryParameter(URI uri, OAuth2AccessToken accessToken) { + try { + String query = uri.getRawQuery(); + String tokenQueryFragment = this.getResource().getTokenName() + "=" + + URLEncoder.encode(accessToken.getValue(), "UTF-8"); + if (query == null) { + query = tokenQueryFragment; + } else { + query = query + "&" + tokenQueryFragment; + } + + String openid = (String) accessToken.getAdditionalInformation().get("openid"); + if (openid != null) { + String openIdQueryFragment = "openid=" + URLEncoder.encode(openid, "UTF-8"); + query = query + "&" + openIdQueryFragment; + } + + URI update = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), + uri.getPath(), null, null); + + StringBuilder result = new StringBuilder(update.toString()); + result.append("?"); + result.append(query); + if (uri.getFragment() != null) { + result.append("#"); + result.append(uri.getFragment()); + } + + return new URI(result.toString()); + + } catch (URISyntaxException | UnsupportedEncodingException e) { + throw new IllegalArgumentException("Could not parse URI", e); + } + } +} diff --git a/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatUserPrincipalExtractor.java b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatUserPrincipalExtractor.java new file mode 100644 index 0000000..7d4da35 --- /dev/null +++ b/src/main/java/com/greate/community/auth/wechatauth/wechat/WeChatUserPrincipalExtractor.java @@ -0,0 +1,34 @@ +package com.greate.community.auth.wechatauth.wechat; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.greate.community.auth.wechatauth.domain.UserWeChat; +import lombok.extern.log4j.Log4j2; +import org.springframework.boot.autoconfigure.security.oauth2.resource.PrincipalExtractor; +import org.springframework.context.annotation.Configuration; + +import java.io.IOException; +import java.util.Map; + +@Configuration +@Log4j2 +public class WeChatUserPrincipalExtractor implements PrincipalExtractor { + + @Override + public Object extractPrincipal(Map map) { + UserWeChat weChat; + try { + String valueAsString = new ObjectMapper().writeValueAsString(map); + weChat = new ObjectMapper().readValue(valueAsString, UserWeChat.class); + if (log.isDebugEnabled()) { + log.debug("convent success, wechat {}", weChat.toString()); + } + } catch (IOException e) { + log.error("convent error", e); + return null; + } + + log.debug(weChat); + return weChat; + } +} + diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index 7fbf6e4..f6b2b16 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -1,18 +1,24 @@ package com.greate.community.config; +import com.greate.community.auth.wechatauth.wechat.WeChatAuthorizationConfig; +import com.greate.community.auth.wechatauth.wechat.WeChatOAuth2ClientContextFilter; import com.greate.community.filter.AuthenticationTokenFilter; import com.greate.community.util.CommunityConstant; import com.greate.community.util.CommunityUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.AuthenticationException; +import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -20,12 +26,124 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; +//@Configuration +//public class SecurityConfig extends WebSecurityConfigurerAdapter implements CommunityConstant { +// +// @Autowired +// private AuthenticationTokenFilter authenticationTokenFilter; +// +// /** +// * 静态资源 +// * +// * @param web +// * @throws Exception +// */ +// @Override +// public void configure(WebSecurity web) throws Exception { +// web.ignoring().antMatchers("/resources/**"); +// } +// +// // 认证环节我们使用自己的代码 LoginController,绕过 Spring Security 的 +// +// /** +// * 授权 +// * +// * @param http +// * @throws Exception +// */ +// @Override +// protected void configure(HttpSecurity http) throws Exception { +// http.cors().and().csrf().disable() +// .authorizeRequests() +// .antMatchers( +// "/user/setting", +// "/user/upload", +// "/discuss/add", +// "/discuss/publish", +// "/comment/add/**", +// "/letter/**", +// "/notice/**", +// "/like", +// "/follow", +// "/unfollow" +// ) +// .hasAnyAuthority( +// AUTHORITY_USER, +// AUTHORITY_ADMIN, +// AUTHORITY_MODERATOR +// ) +// +// .antMatchers( +// "/discuss/top", +// "/discuss/wonderful" +// ) +// .hasAnyAuthority( +// AUTHORITY_MODERATOR +// ) +// +// .antMatchers( +// "/discuss/delete", +// "/discuss/delete/", +// "/data/**" +// ) +// .hasAnyAuthority( +// AUTHORITY_ADMIN +// ) +// +// .anyRequest().permitAll() +// +// .and().csrf().disable(); +// +// //添加jwt认证器 +// http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); +// // 权限不够时的处理 +// http.exceptionHandling() +// // 1. 未登录时的处理 +// .authenticationEntryPoint(new AuthenticationEntryPoint() { +// @Override +// public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException { +// // 异步请求 +// response.setCharacterEncoding("UTF-8"); +// response.setContentType("application/plain;charset=utf-8"); +// response.getWriter().write(CommunityUtil.getJSONString(403, "你还没有登录")); +// } +// }) +// // 2. 权限不够时的处理 +// .accessDeniedHandler(new AccessDeniedHandler() { +// @Override +// public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException { +// // 异步请求 +// response.setContentType("application/plain;charset=utf-8"); +// PrintWriter writer = response.getWriter(); +// writer.write(CommunityUtil.getJSONString(403, "你没有访问该功能的权限")); +// } +// }); +// +// // Security 底层会默认拦截 /logout 请求,进行退出处理 +// // 此处赋予它一个根本不存在的退出路径,使得程序能够执行到我们自己编写的退出代码 +// http.logout().logoutUrl("/securitylogout"); +// +// http.headers().frameOptions().sameOrigin(); +// } +//} + + @Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter implements CommunityConstant { @Autowired private AuthenticationTokenFilter authenticationTokenFilter; + private final WeChatAuthorizationConfig weChatAuthorizationConfig; + private final WeChatOAuth2ClientContextFilter weChatOAuth2ClientContextFilter; + + public SecurityConfig(WeChatAuthorizationConfig weChatAuthorizationConfig, WeChatOAuth2ClientContextFilter weChatOAuth2ClientContextFilter) { + this.weChatAuthorizationConfig = weChatAuthorizationConfig; + this.weChatOAuth2ClientContextFilter = weChatOAuth2ClientContextFilter; + } + /** * 静态资源 * @@ -38,7 +156,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm } // 认证环节我们使用自己的代码 LoginController,绕过 Spring Security 的 - /** * 授权 * @@ -47,6 +164,14 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm */ @Override protected void configure(HttpSecurity http) throws Exception { + //添加jwt认证器 + http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); + /** + * WeChat login + */ + http.addFilterBefore(weChatAuthorizationConfig.weChatFilter(), BasicAuthenticationFilter.class).addFilterBefore(weChatOAuth2ClientContextFilter, OAuth2ClientAuthenticationProcessingFilter.class); + + http.cors().and().csrf().disable() .authorizeRequests() .antMatchers( @@ -86,12 +211,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm AUTHORITY_ADMIN ) - .anyRequest().permitAll() + .anyRequest().permitAll(); - .and().csrf().disable(); - - //添加jwt认证器 - http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); // 权限不够时的处理 http.exceptionHandling() // 1. 未登录时的处理 diff --git a/src/main/java/com/greate/community/controller/DataController.java b/src/main/java/com/greate/community/controller/DataController.java index eca7c87..6a61c7d 100644 --- a/src/main/java/com/greate/community/controller/DataController.java +++ b/src/main/java/com/greate/community/controller/DataController.java @@ -68,8 +68,6 @@ public class DataController { /** * 统计网站 DAU - * @param start - * @param end * @return */ @PostMapping("/data/dau") diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index 062526a..e845164 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -188,7 +188,7 @@ public class DiscussPostController implements CommunityConstant { resultMap.put("likeStatus",likeStatus); // 评论分页信息 - page.setLimit(5); +// page.setLimit(5);//前端注入 page.setPath("/discuss/detail/" + discussPostId); page.setRows(discussPost.getCommentCount()); diff --git a/src/main/java/com/greate/community/controller/FollowController.java b/src/main/java/com/greate/community/controller/FollowController.java index 63681dc..b054b53 100644 --- a/src/main/java/com/greate/community/controller/FollowController.java +++ b/src/main/java/com/greate/community/controller/FollowController.java @@ -102,7 +102,7 @@ public class FollowController implements CommunityConstant{ // model.addAttribute("user", user); hashMap.put("user", user);//正在查看的用户信息 - page.setLimit(5); +// page.setLimit(5);//前端注入 page.setPath("/followees/" + userId); page.setRows((int) followService.findFolloweeCount(userId, ENTITY_TYPE_USER)); @@ -142,7 +142,7 @@ public class FollowController implements CommunityConstant{ // model.addAttribute("user", user); hashMap.put("user", user);//正在查看的用户信息 - page.setLimit(5); +// page.setLimit(5);//前端注入 page.setPath("/followers/" + userId); page.setRows((int) followService.findFollowerCount(ENTITY_TYPE_USER, userId)); diff --git a/src/main/java/com/greate/community/controller/LikeController.java b/src/main/java/com/greate/community/controller/LikeController.java index df2fef9..e9d9320 100644 --- a/src/main/java/com/greate/community/controller/LikeController.java +++ b/src/main/java/com/greate/community/controller/LikeController.java @@ -83,38 +83,5 @@ public class LikeController extends BaseController implements CommunityConstant return new Result("success", Result.SUCCESS, map); } -// public String like(int entityType, int entityId, int entityUserId, int postId) { -// User user = hostHolder.getUser(); -// // 点赞 -// likeService.like(user.getId(), entityType, entityId, entityUserId); -// // 点赞数量 -// long likeCount = likeService.findEntityLikeCount(entityType, entityId); -// // 点赞状态 -// int likeStatus = likeService.findEntityLikeStatus(user.getId(), entityType, entityId); -// -// Map map = new HashMap<>(); -// map.put("likeCount", likeCount); -// map.put("likeStatus", likeStatus); -// -// // 触发点赞事件(系统通知) - 取消点赞不通知 -// if (likeStatus == 1) { -// Event event = new Event() -// .setTopic(TOPIC_LIKE) -// .setUserId(hostHolder.getUser().getId()) -// .setEntityType(entityType) -// .setEntityId(entityId) -// .setEntityUserId(entityUserId) -// .setData("postId", postId); -// eventProducer.fireEvent(event); -// } -// -// if (entityType == ENTITY_TYPE_POST) { -// // 计算帖子分数 -// String redisKey = RedisKeyUtil.getPostScoreKey(); -// redisTemplate.opsForSet().add(redisKey, postId); -// } -// -// return CommunityUtil.getJSONString(0, null, map); -// } } diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index 77aac2b..13d8afe 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -4,11 +4,14 @@ import cn.hutool.captcha.CaptchaUtil; import cn.hutool.captcha.LineCaptcha; import cn.hutool.core.lang.UUID; import com.alibaba.fastjson.JSONObject; -import com.google.code.kaptcha.Producer; +import com.greate.community.auth.wechatauth.domain.UserWeChat; +import com.greate.community.dao.UserMapper; +import com.greate.community.entity.LoginTicket; import com.greate.community.entity.Result; import com.greate.community.entity.User; import com.greate.community.service.UserService; import com.greate.community.util.CommunityConstant; +import com.greate.community.util.CommunityUtil; import com.greate.community.util.RedisKeyUtil; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -16,11 +19,12 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; -import javax.validation.constraints.NotEmpty; +import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -36,6 +40,9 @@ public class LoginController extends BaseController implements CommunityConstant @Autowired private UserService userService; + @Autowired + private UserMapper userMapper; + @Autowired private RedisTemplate redisTemplate; @@ -45,34 +52,6 @@ public class LoginController extends BaseController implements CommunityConstant @Value("${bbs.captcha-enable}") private boolean captchaEnable; -// /** -// * 进入注册界面 -// * -// * @return -// */ -// @GetMapping("/register") -// public String getRegisterPage() { -// return "site/register"; -// } -// -// /** -// * 进入登录界面 -// * -// * @return -// */ -// @GetMapping("/login") -// public String getLoginPage() { -// return "site/login"; -// } -// -// /** -// * 进入重置密码界面 -// */ -// @GetMapping("/resetPwd") -// public String getResetPwdPage() { -// return "site/reset-pwd"; -// } - /** * 注册用户 * @@ -88,19 +67,7 @@ public class LoginController extends BaseController implements CommunityConstant return new Result("fail", Result.FAIL, map); } } -// public String register(Model model, User user) { -// Map map = userService.register(user); -// if (map == null || map.isEmpty()) { -// model.addAttribute("msg", "注册成功, 我们已经向您的邮箱发送了一封激活邮件,请尽快激活!"); -// model.addAttribute("target", "/index"); -// return "/site/operate-result"; -// } else { -// model.addAttribute("usernameMsg", map.get("usernameMsg")); -// model.addAttribute("passwordMsg", map.get("passwordMsg")); -// model.addAttribute("emailMsg", map.get("emailMsg")); -// return "/site/register"; -// } -// } + /** * 激活用户 @@ -110,23 +77,6 @@ public class LoginController extends BaseController implements CommunityConstant * @return http://localhost:8080/echo/activation/用户id/激活码 */ @GetMapping("/activation/{userId}/{code}") -// public String activation(Model model, @PathVariable("userId") int userId, -// @PathVariable("code") String code) { -// int result = userService.activation(userId, code); -// if (result == ACTIVATION_SUCCESS) { -// model.addAttribute("msg", "激活成功, 您的账号已经可以正常使用!"); -// model.addAttribute("target", "/login"); -// } -// else if (result == ACTIVATION_REPEAT) { -// model.addAttribute("msg", "无效的操作, 您的账号已被激活过!"); -// model.addAttribute("target", "/index"); -// } -// else { -// model.addAttribute("msg", "激活失败, 您提供的激活码不正确!"); -// model.addAttribute("target", "/index"); -// } -// return "/site/operate-result"; -// } public Result activation(@PathVariable("userId") int userId, @PathVariable("code") String code) { int result = userService.activation(userId, code); @@ -159,31 +109,6 @@ public class LoginController extends BaseController implements CommunityConstant result.put("captchaToken", captchaToken); return new Result("success", Result.SUCCESS, result); } -// public void getKaptcha(HttpServletResponse response) { -// // 生成验证码 -// String text = kaptchaProducer.createText(); // 生成随机字符 -// System.out.println("验证码:" + text); -// BufferedImage image = kaptchaProducer.createImage(text); // 生成图片 -// -// // 验证码的归属者 -// String kaptchaOwner = CommunityUtil.generateUUID(); -// Cookie cookie = new Cookie("kaptchaOwner", kaptchaOwner); -// cookie.setMaxAge(60); -// cookie.setPath(contextPath); -// response.addCookie(cookie); -// // 将验证码存入 redis -// String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner); -// redisTemplate.opsForValue().set(redisKey, text, 60, TimeUnit.SECONDS); -// -// // 将图片输出给浏览器 -// response.setContentType("image/png"); -// try { -// ServletOutputStream os = response.getOutputStream(); -// ImageIO.write(image, "png", os); -// } catch (IOException e) { -// logger.error("响应验证码失败", e.getMessage()); -// } -// } /** * 验证用户输入的图片验证码是否和redis中存入的是否相等 @@ -248,41 +173,62 @@ public class LoginController extends BaseController implements CommunityConstant return new Result("fail", "2", map); } } -// public String login(@RequestParam("username") String username, -// @RequestParam("password") String password, -// @RequestParam("code") String code, -// @RequestParam(value = "rememberMe", required = false) boolean rememberMe, -// Model model, HttpServletResponse response, -// @CookieValue("kaptchaOwner") String kaptchaOwner) { -// // 检查验证码 -// String kaptcha = null; -// if (StringUtils.isNotBlank(kaptchaOwner)) { -// String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner); -// kaptcha = (String) redisTemplate.opsForValue().get(redisKey); -// } -// -// if (StringUtils.isBlank(kaptcha) || StringUtils.isBlank(code) || !kaptcha.equalsIgnoreCase(code)) { -// model.addAttribute("codeMsg", "验证码错误"); -// return "/site/login"; -// } -// -// // 凭证过期时间(是否记住我) -// int expiredSeconds = rememberMe ? REMEMBER_EXPIRED_SECONDS : DEFAULT_EXPIRED_SECONDS; -// // 验证用户名和密码 -// Map map = userService.login(username, password, expiredSeconds); -// if (map.containsKey("ticket")) { -// // 账号和密码均正确,则服务端会生成 ticket,浏览器通过 cookie 存储 ticket -// Cookie cookie = new Cookie("ticket", map.get("ticket").toString()); -// cookie.setPath(contextPath); // cookie 有效范围 -// cookie.setMaxAge(expiredSeconds); -// response.addCookie(cookie); -// return "redirect:/index"; -// } else { -// model.addAttribute("usernameMsg", map.get("usernameMsg")); -// model.addAttribute("passwordMsg", map.get("passwordMsg")); -// return "/site/login"; -// } -// } + + /** + * 用户使用微信账号第三方登录成功后,后端回调此链接向前端返回响应 + * + * @return + */ + @GetMapping("/wechat/login") + public Result wechatLogin(@AuthenticationPrincipal UserWeChat userWeChat) { + String username = userWeChat.getNickName();//微信昵称 + String password = CommunityUtil.generateUUID();//随机密码,不能随便让人破解 + String headerUrl = userWeChat.getHeadimgurl();//微信头像地址 + String email = "wechat@none.com";//微信登录的用户,邮箱是一个特殊标识字符串 + + + // 若微信用户对应的账号已存在,跳过模拟注册操作,直接进入登录过程 + User u = userMapper.selectByName(username); + User user = new User(); + if (u == null) { + /**模拟注册操作**/ + user.setUsername(username); + user.setPassword(password); + user.setEmail(email); + user.setType(0); // 默认普通用户 + user.setStatus(1); // 微信登录用户默认激活,无需邮箱验证 + + // 用户头像 + user.setHeaderUrl(headerUrl);//微信头像地址 + user.setCreateTime(new Date()); // 注册时间 + + userMapper.insertUser(user); + // 这一步主要是为了获取userId + user = userMapper.selectByName(username); + /**模拟注册操作**/ + }else { + user = u; + } + + /**模拟普通登录过程**/ + // 凭证过期时间 + int expiredSeconds = DEFAULT_EXPIRED_SECONDS; + + // 用户名和密码均正确,为该用户生成登录凭证 + LoginTicket loginTicket = new LoginTicket(); + loginTicket.setUserId(user.getId()); + loginTicket.setTicket(CommunityUtil.generateUUID()); // 随机凭证 + loginTicket.setStatus(0); // 设置凭证状态为有效(当用户登出的时候,设置凭证状态为无效) + loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000)); // 设置凭证到期时间 + + // 将登录凭证存入 redis + String redisKey = RedisKeyUtil.getTicketKey(loginTicket.getTicket()); + redisTemplate.opsForValue().set(redisKey, loginTicket); + + String ticket = loginTicket.getTicket(); + return new Result("success", Result.SUCCESS, ticket); + /**模拟普通登录过程**/ + } /** * 用户登出 @@ -320,35 +266,6 @@ public class LoginController extends BaseController implements CommunityConstant } return new Result("fail", "1", map); } -// public Map resetPwd(@RequestParam("username") String username, -// @RequestParam("password") String password, -// @RequestParam("emailVerifyCode") String emailVerifyCode, -// @RequestParam("kaptchaCode") String kaptcha, -// Model model, -// @CookieValue("kaptchaOwner") String kaptchaOwner) { -// Map map = new HashMap<>(4); -// // 检查图片验证码 -// String kaptchaCheckRst = checkKaptchaCode(kaptchaOwner, kaptcha); -// if (StringUtils.isNotBlank(kaptchaCheckRst)) { -// map.put("status", "1"); -// map.put("errMsg", kaptchaCheckRst); -// } -// // 检查邮件验证码 -// String emailVerifyCodeCheckRst = checkRedisResetPwdEmailCode(username, emailVerifyCode); -// if (StringUtils.isNotBlank(emailVerifyCodeCheckRst)) { -// map.put("status", "1"); -// map.put("errMsg", emailVerifyCodeCheckRst); -// } -// // 执行重置密码操作 -// Map stringObjectMap = userService.doResetPwd(username, password); -// String usernameMsg = (String) stringObjectMap.get("errMsg"); -// if (StringUtils.isBlank(usernameMsg)) { -// map.put("status", "0"); -// map.put("msg", "重置密码成功!"); -// map.put("target", "/login"); -// } -// return map; -// } /** * 发送邮件验证码(用于重置密码) @@ -379,24 +296,6 @@ public class LoginController extends BaseController implements CommunityConstant } return new Result("success", Result.SUCCESS, "发送邮箱成功!"); } -// public Map sendEmailCodeForResetPwd(Model model, @CookieValue("kaptchaOwner") String kaptchaOwner, -// @RequestParam("kaptcha") String kaptcha, -// @RequestParam("username") String username) { -// Map map = new HashMap<>(3); -// // 检查图片验证码 -// String kaptchaCheckRst = checkKaptchaCode(kaptchaOwner, kaptcha); -// if (StringUtils.isNotBlank(kaptchaCheckRst)) { -// map.put("status", "1"); -// map.put("errMsg", kaptchaCheckRst); -// } -// Map stringObjectMap = userService.doSendEmailCode4ResetPwd(username); -// String usernameMsg = (String) stringObjectMap.get("errMsg"); -// if (StringUtils.isBlank(usernameMsg)) { -// map.put("status", "0"); -// map.put("msg", "已经往您的邮箱发送了一封验证码邮件, 请查收!"); -// } -// return map; -// } /** * 检查 邮件 验证码 diff --git a/src/main/java/com/greate/community/controller/MessageController.java b/src/main/java/com/greate/community/controller/MessageController.java index 974c098..2c1e898 100644 --- a/src/main/java/com/greate/community/controller/MessageController.java +++ b/src/main/java/com/greate/community/controller/MessageController.java @@ -35,14 +35,14 @@ public class MessageController extends BaseController implements CommunityConsta * @return */ @GetMapping("/letter/list") - public Result getLetterList(Page page) { + public Result getLetterList(@RequestBody Page page) { // Integer.valueOf("abc"); // 测试统一异常处理(普通请求) JSONObject jsonObject = new JSONObject(); // 获取当前登录用户信息 User user = getUser(); // 分页信息 - page.setLimit(5); +// page.setLimit(5);//前端注入 page.setPath("/letter/list"); // 查询会话总数 page.setRows(messageService.findConversationCout(user.getId())); @@ -76,45 +76,6 @@ public class MessageController extends BaseController implements CommunityConsta return new Result("success", Result.SUCCESS, jsonObject); } -// public String getLetterList(Model model, Page page) { -// // Integer.valueOf("abc"); // 测试统一异常处理(普通请求) -// -// // 获取当前登录用户信息 -// User user = hostHolder.getUser(); -// // 分页信息 -// page.setLimit(5); -// page.setPath("/letter/list"); -// page.setRows(messageService.findConversationCout(user.getId())); -// // 私信列表 -// List conversationList = messageService.findConversations( -// user.getId(), page.getOffset(), page.getLimit()); -// -// List> conversations = new ArrayList<>(); -// if (conversationList != null) { -// for (Message message : conversationList) { -// Map map = new HashMap<>(); -// map.put("conversation", message); // 私信 -// map.put("letterCount", messageService.findLetterCount( -// message.getConversationId())); // 私信数量 -// map.put("unreadCount", messageService.findLetterUnreadCount( -// user.getId(), message.getConversationId())); // 未读私信数量 -// int targetId = user.getId() == message.getFromId() ? message.getToId() : message.getFromId(); -// map.put("target", userService.findUserById(targetId)); // 私信对方 -// -// conversations.add(map); -// } -// } -// model.addAttribute("conversations", conversations); -// -// // 查询当前用户的所有未读消息数量 -// int letterUnreadCount = messageService.findLetterUnreadCount(user.getId(), null); -// model.addAttribute("letterUnreadCount", letterUnreadCount); -// int noticeUnreadCount = messageService.findNoticeUnReadCount(user.getId(), null); -// model.addAttribute("noticeUnreadCount", noticeUnreadCount); -// -// return "/site/letter"; -// -// } /** * 私信详情页 @@ -123,11 +84,11 @@ public class MessageController extends BaseController implements CommunityConsta * @return */ @GetMapping("/letter/detail/{conversationId}") - public Result getLetterDetail(@PathVariable("conversationId") String conversationId, Page page) { + public Result getLetterDetail(@PathVariable("conversationId") String conversationId, @RequestBody Page page) { JSONObject jsonObject = new JSONObject(); // 分页信息 - page.setLimit(5); +// page.setLimit(5);//前端注入 page.setPath("/letter/detail/" + conversationId); page.setRows(messageService.findLetterCount(conversationId)); @@ -438,10 +399,10 @@ public class MessageController extends BaseController implements CommunityConsta * @return */ @GetMapping("/notice/detail/{topic}") - public Result getNoticeDetail(@PathVariable("topic") String topic, Page page) { + public Result getNoticeDetail(@PathVariable("topic") String topic, @RequestBody Page page) { User user = getUser(); - page.setLimit(5); +// page.setLimit(5);//前端注入 page.setPath("/notice/detail/" + topic); page.setRows(messageService.findNoticeCount(user.getId(), topic)); diff --git a/src/main/java/com/greate/community/controller/SearchController.java b/src/main/java/com/greate/community/controller/SearchController.java index 8f820fb..3a68f3f 100644 --- a/src/main/java/com/greate/community/controller/SearchController.java +++ b/src/main/java/com/greate/community/controller/SearchController.java @@ -10,6 +10,7 @@ import com.greate.community.util.CommunityConstant; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import java.util.*; @@ -37,7 +38,7 @@ public class SearchController extends BaseController implements CommunityConstan * @return */ @GetMapping("/search") - public String search(String keyword, Page page) { + public String search(String keyword, @RequestBody Page page) { JSONObject jsonObject = new JSONObject(); // 搜索帖子 (Spring 提供的 Page 当前页码从 0 开始计数) org.springframework.data.domain.Page searchResult = @@ -67,35 +68,6 @@ public class SearchController extends BaseController implements CommunityConstan return "/site/search"; } -// public String search(String keyword, Page page, Model model) { -// // 搜索帖子 (Spring 提供的 Page 当前页码从 0 开始计数) -// org.springframework.data.domain.Page searchResult = -// elasticsearchService.searchDiscussPost(keyword, page.getCurrent()-1, page.getLimit()); -// // 聚合数据 -// List> discussPosts = new ArrayList<>(); -// if (searchResult != null) { -// for (DiscussPost post : searchResult) { -// Map map = new HashMap<>(); -// // 帖子 -// map.put("post", post); -// // 作者 -// map.put("user", userService.findUserById(post.getUserId())); -// // 点赞数量 -// map.put("likeCount", likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId())); -// -// discussPosts.add(map); -// } -// } -// -// model.addAttribute("discussPosts", discussPosts); -// model.addAttribute("keyword", keyword); -// -// // 设置分页 -// page.setPath("/search?keyword="+ keyword); -// page.setRows(searchResult == null ? 0 : (int) searchResult.getTotalElements()); -// -// return "/site/search"; -// } } diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 953d420..f23fe87 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -159,7 +159,7 @@ public class UserController extends BaseController implements CommunityConstant * @return */ @GetMapping("/discuss/{userId}") - public Result getMyDiscussPosts(@PathVariable("userId") int userId, Page page) { + public Result getMyDiscussPosts(@PathVariable("userId") int userId, @RequestBody Page page) { JSONObject jsonObject = new JSONObject(); User user = userService.findUserById(userId); if (user == null) { @@ -171,7 +171,7 @@ public class UserController extends BaseController implements CommunityConstant int rows = discussPostService.findDiscussPostRows(userId); jsonObject.put("rows", rows); - page.setLimit(5); +// page.setLimit(5);//前端注入 page.setPath("/user/discuss/" + userId); page.setRows(rows); @@ -201,7 +201,7 @@ public class UserController extends BaseController implements CommunityConstant * @return */ @GetMapping("/comment/{userId}") - public Result getMyComments(@PathVariable("userId") int userId, Page page) { + public Result getMyComments(@PathVariable("userId") int userId, @RequestBody Page page) { JSONObject jsonObject = new JSONObject(); User user = userService.findUserById(userId); if (user == null) { @@ -213,7 +213,7 @@ public class UserController extends BaseController implements CommunityConstant int commentCounts = commentService.findCommentCountByUserId(userId); jsonObject.put("commentCounts", commentCounts); - page.setLimit(5); +// page.setLimit(5);//前端注入 page.setPath("/user/comment/" + userId); page.setRows(commentCounts); diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index ad5cd3d..d2f979d 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -3,6 +3,7 @@ bbs.captcha-enable = false # ˿ server.port = 8080 +#server.port = 80 # Ŀ(Ŀ·) http://localhost:8080/...... server.servlet.context-path = @@ -85,4 +86,25 @@ tencent.secretKey = 5uUnpb8OO9gxyjEVVFjywd3EApDLCm6B # Caffeine caffeine.posts.max-size = 15 -caffeine.posts.expire-seconds = 180 \ No newline at end of file +caffeine.posts.expire-seconds = 180 + + +# OAuth2 ΢ŵ¼ +wechat.client.clientId = wxa75d140e71f8903e +wechat.client.clientSecret = 2e6dbcad650a9fa495a762c0eb28906a +wechat.client.accessTokenUri = https://api.weixin.qq.com/sns/oauth2/access_token +wechat.client.userAuthorizationUri = https://open.weixin.qq.com/connect/oauth2/authorize +wechat.client.tokenName = access_token +wechat.client.authenticationScheme = query +wechat.client.clientAuthenticationScheme = form +wechat.client.scope = snsapi_userinfo +wechat.resource.userInfoUri = https://api.weixin.qq.com/sns/userinfo +wechat.config.app-id = appid +wechat.config.client-id = client_id +wechat.config.secret = secret +wechat.config.client-secret = client_secret +wechat.config.state = state +wechat.config.wechat-redirect = wechat_redirect + +logging.level.com.greate = debug +logging.level.org.springframework.security = DEBUG \ No newline at end of file diff --git a/src/test/java/com/greate/community/MailTests.java b/src/test/java/com/greate/community/MailTests.java new file mode 100644 index 0000000..bb1bcf3 --- /dev/null +++ b/src/test/java/com/greate/community/MailTests.java @@ -0,0 +1,25 @@ +//package com.greate.community; +// +//import com.greate.community.util.EmailUtil; +//import com.greate.community.util.MailClient; +//import lombok.ToString; +//import org.junit.Test; +//import org.junit.runner.RunWith; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.test.context.SpringBootTest; +//import org.springframework.test.context.ContextConfiguration; +//import org.springframework.test.context.junit4.SpringRunner; +// +//@RunWith(SpringRunner.class) +//@ContextConfiguration(classes = CommunityApplication.class) +//@SpringBootTest +//public class MailTests { +// +// @Autowired +// private EmailUtil emailUtil; +// +// @Test +// public void sendEmail() { +// emailUtil.sendRegistrationCode("2224236998@qq.com"); +// } +//} -- Gitee From dba1ac404b416d58e0138194e9dc0fbd4b8bd788 Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Tue, 8 Feb 2022 19:36:42 +0800 Subject: [PATCH 011/125] fix: delete old getUser method --- .../community/aspect/ServiceLogAspect.java | 3 +-- .../controller/CommentController.java | 9 +++---- .../controller/DiscussPostController.java | 26 ++++++++----------- .../controller/FollowController.java | 16 +++++------- .../community/controller/IndexController.java | 21 --------------- 5 files changed, 22 insertions(+), 53 deletions(-) diff --git a/src/main/java/com/greate/community/aspect/ServiceLogAspect.java b/src/main/java/com/greate/community/aspect/ServiceLogAspect.java index a8fb9ce..06b58e1 100644 --- a/src/main/java/com/greate/community/aspect/ServiceLogAspect.java +++ b/src/main/java/com/greate/community/aspect/ServiceLogAspect.java @@ -25,7 +25,6 @@ public class ServiceLogAspect { @Pointcut("execution(* com.greate.community.service.*.*(..))") public void pointcut() { - } @Before("pointcut()") @@ -33,7 +32,7 @@ public class ServiceLogAspect { // 用户[IP 地址], 在某个时间访问了 [com.greate.community.service.xxx] ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (attributes == null) { - return ; + return; } HttpServletRequest request = attributes.getRequest(); String ip = request.getRemoteHost(); diff --git a/src/main/java/com/greate/community/controller/CommentController.java b/src/main/java/com/greate/community/controller/CommentController.java index dc36427..15d5cdb 100644 --- a/src/main/java/com/greate/community/controller/CommentController.java +++ b/src/main/java/com/greate/community/controller/CommentController.java @@ -25,10 +25,7 @@ import java.util.Date; */ @Controller @RequestMapping("/comment") -public class CommentController implements CommunityConstant { - - @Autowired - private HostHolder hostHolder; +public class CommentController extends BaseController implements CommunityConstant { @Autowired private CommentService commentService; @@ -51,7 +48,7 @@ public class CommentController implements CommunityConstant { @PostMapping("/add/{discussPostId}") @ResponseBody public Result addComment(@PathVariable("discussPostId") int discussPostId, Comment comment) { - comment.setUserId(hostHolder.getUser().getId()); + comment.setUserId(getUser().getId()); comment.setStatus(0); comment.setCreateTime(new Date()); commentService.addComment(comment); @@ -59,7 +56,7 @@ public class CommentController implements CommunityConstant { // 触发评论事件(系统通知) Event event = new Event() .setTopic(TOPIC_COMMNET) - .setUserId(hostHolder.getUser().getId()) + .setUserId(getUser().getId()) .setEntityType(comment.getEntityType()) .setEntityId(comment.getEntityId()) .setData("postId", discussPostId); diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index e845164..fc03411 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -19,7 +19,6 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.util.HtmlUtils; -import javax.validation.constraints.NotEmpty; import java.io.File; import java.util.*; @@ -28,14 +27,11 @@ import java.util.*; */ @Controller @RequestMapping("/discuss") -public class DiscussPostController implements CommunityConstant { +public class DiscussPostController extends BaseController implements CommunityConstant { @Autowired private DiscussPostService discussPostService; - @Autowired - private HostHolder hostHolder; - @Autowired private UserService userService; @@ -123,7 +119,7 @@ public class DiscussPostController implements CommunityConstant { String title = map.get("title"); String content = map.get("content"); - User user = hostHolder.getUser(); + User user = getUser(); if (user == null) { // return CommunityUtil.getJSONString(403, "您还未登录"); return new Result("forbidden","403","您还未登录"+"---"+title+"---"+content); @@ -182,8 +178,8 @@ public class DiscussPostController implements CommunityConstant { resultMap.put("likeCount",likeCount); // 当前登录用户的点赞状态 - int likeStatus = hostHolder.getUser() == null ? 0 : - likeService.findEntityLikeStatus(hostHolder.getUser().getId(), ENTITY_TYPE_POST, discussPostId); + int likeStatus = getUser() == null ? 0 : + likeService.findEntityLikeStatus(getUser().getId(), ENTITY_TYPE_POST, discussPostId); // model.addAttribute("likeStatus", likeStatus); resultMap.put("likeStatus",likeStatus); @@ -206,8 +202,8 @@ public class DiscussPostController implements CommunityConstant { commentVo.put("user", userService.findUserById(comment.getUserId())); // 发布评论的作者 likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_COMMENT, comment.getId()); // 该评论点赞数量 commentVo.put("likeCount", likeCount); - likeStatus = hostHolder.getUser() == null ? 0 : likeService.findEntityLikeStatus( - hostHolder.getUser().getId(), ENTITY_TYPE_COMMENT, comment.getId()); // 当前登录用户对该评论的点赞状态 + likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( + getUser().getId(), ENTITY_TYPE_COMMENT, comment.getId()); // 当前登录用户对该评论的点赞状态 commentVo.put("likeStatus", likeStatus); @@ -224,8 +220,8 @@ public class DiscussPostController implements CommunityConstant { replyVo.put("target", target); // 该回复的目标用户 likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_COMMENT, reply.getId()); replyVo.put("likeCount", likeCount); // 该回复的点赞数量 - likeStatus = hostHolder.getUser() == null ? 0 : likeService.findEntityLikeStatus( - hostHolder.getUser().getId(), ENTITY_TYPE_COMMENT, reply.getId()); + likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( + getUser().getId(), ENTITY_TYPE_COMMENT, reply.getId()); replyVo.put("likeStatus", likeStatus); // 当前登录用户的点赞状态 replyVoList.add(replyVo); @@ -264,7 +260,7 @@ public class DiscussPostController implements CommunityConstant { // 触发发帖事件,通过消息队列将其存入 Elasticsearch 服务器 Event event = new Event() .setTopic(TOPIC_PUBLISH) - .setUserId(hostHolder.getUser().getId()) + .setUserId(getUser().getId()) .setEntityType(ENTITY_TYPE_POST) .setEntityId(id); eventProducer.fireEvent(event); @@ -288,7 +284,7 @@ public class DiscussPostController implements CommunityConstant { // 触发发帖事件,通过消息队列将其存入 Elasticsearch 服务器 Event event = new Event() .setTopic(TOPIC_PUBLISH) - .setUserId(hostHolder.getUser().getId()) + .setUserId(getUser().getId()) .setEntityType(ENTITY_TYPE_POST) .setEntityId(id); eventProducer.fireEvent(event); @@ -315,7 +311,7 @@ public class DiscussPostController implements CommunityConstant { // 触发删帖事件,通过消息队列更新 Elasticsearch 服务器 Event event = new Event() .setTopic(TOPIC_DELETE) - .setUserId(hostHolder.getUser().getId()) + .setUserId(getUser().getId()) .setEntityType(ENTITY_TYPE_POST) .setEntityId(id); eventProducer.fireEvent(event); diff --git a/src/main/java/com/greate/community/controller/FollowController.java b/src/main/java/com/greate/community/controller/FollowController.java index b054b53..cca0994 100644 --- a/src/main/java/com/greate/community/controller/FollowController.java +++ b/src/main/java/com/greate/community/controller/FollowController.java @@ -10,6 +10,7 @@ import com.greate.community.service.UserService; import com.greate.community.util.CommunityConstant; import com.greate.community.util.CommunityUtil; import com.greate.community.util.HostHolder; +import org.codehaus.jackson.map.Serializers; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -23,14 +24,11 @@ import java.util.Map; * 关注(目前只做了关注用户) */ @Controller -public class FollowController implements CommunityConstant{ +public class FollowController extends BaseController implements CommunityConstant{ @Autowired private FollowService followService; - @Autowired - private HostHolder hostHolder; - @Autowired private UserService userService; @@ -48,14 +46,14 @@ public class FollowController implements CommunityConstant{ int entityType = map.get("entityType"); int entityId = map.get("entityId"); - User user = hostHolder.getUser(); + User user = getUser(); followService.follow(user.getId(), entityType, entityId); // 触发关注事件(系统通知) Event event = new Event() .setTopic(TOPIC_FOLLOW) - .setUserId(hostHolder.getUser().getId()) + .setUserId(getUser().getId()) .setEntityType(entityType) .setEntityId(entityId) .setEntityUserId(entityId); @@ -75,7 +73,7 @@ public class FollowController implements CommunityConstant{ int entityType = map.get("entityType"); int entityId = map.get("entityId"); - User user = hostHolder.getUser(); + User user = getUser(); followService.unfollow(user.getId(), entityType, entityId); @@ -169,11 +167,11 @@ public class FollowController implements CommunityConstant{ * @return */ private boolean hasFollowed(int userId) { - if (hostHolder.getUser() == null) { + if (getUser() == null) { return false; } - return followService.hasFollowed(hostHolder.getUser().getId(), ENTITY_TYPE_USER, userId); + return followService.hasFollowed(getUser().getId(), ENTITY_TYPE_USER, userId); } diff --git a/src/main/java/com/greate/community/controller/IndexController.java b/src/main/java/com/greate/community/controller/IndexController.java index 5fc98e8..28bfb99 100644 --- a/src/main/java/com/greate/community/controller/IndexController.java +++ b/src/main/java/com/greate/community/controller/IndexController.java @@ -74,31 +74,10 @@ public class IndexController implements CommunityConstant { } } -// model.addAttribute("discussPosts", discussPosts); -// model.addAttribute("orderMode", orderMode); hashMap.put("discussPosts", discussPosts); hashMap.put("orderMode", orderMode); -// return "index"; return new Result("success",Result.SUCCESS,hashMap); } -// /** -// * 进入 500 错误界面 -// * @return -// */ -// @GetMapping("/error") -// public String getErrorPage() { -// return "/error/500"; -// } -// -// /** -// * 没有权限访问时的错误界面(也是 404) -// * @return -// */ -// @GetMapping("/denied") -// public String getDeniedPage() { -// return "/error/404"; -// } - } -- Gitee From 10be3cf82df8a04f6a9b6fdd556164270a046467 Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Tue, 8 Feb 2022 20:09:54 +0800 Subject: [PATCH 012/125] fix: fix add post method --- .../controller/CommentController.java | 7 ++----- .../community/controller/DataController.java | 15 +------------ .../controller/DiscussPostController.java | 21 +++---------------- .../controller/FollowController.java | 2 +- .../community/controller/IndexController.java | 12 ++--------- .../controller/SearchController.java | 5 +++-- 6 files changed, 12 insertions(+), 50 deletions(-) diff --git a/src/main/java/com/greate/community/controller/CommentController.java b/src/main/java/com/greate/community/controller/CommentController.java index 15d5cdb..5ce38cd 100644 --- a/src/main/java/com/greate/community/controller/CommentController.java +++ b/src/main/java/com/greate/community/controller/CommentController.java @@ -13,17 +13,14 @@ import com.greate.community.util.RedisKeyUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import java.util.Date; /** * 评论/回复 */ -@Controller +@RestController @RequestMapping("/comment") public class CommentController extends BaseController implements CommunityConstant { diff --git a/src/main/java/com/greate/community/controller/DataController.java b/src/main/java/com/greate/community/controller/DataController.java index 6a61c7d..1933142 100644 --- a/src/main/java/com/greate/community/controller/DataController.java +++ b/src/main/java/com/greate/community/controller/DataController.java @@ -18,27 +18,14 @@ import java.util.Map; /** * 网站数据 */ -@Controller +@RestController public class DataController { @Autowired private DataService dataService; - /** - * 进入统计界面 - * @return - * - * 前端直接跳转到/site/admin/data - */ - @RequestMapping(value = "/data", method = {RequestMethod.GET, RequestMethod.POST}) - public String getDataPage() { - return "/site/admin/data"; - } - /** * 统计网站 uv - * @param start - * @param end * @return * * diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index fc03411..77493ae 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -25,7 +25,7 @@ import java.util.*; /** * 帖子 */ -@Controller +@RestController @RequestMapping("/discuss") public class DiscussPostController extends BaseController implements CommunityConstant { @@ -59,17 +59,6 @@ public class DiscussPostController extends BaseController implements CommunityCo @Value("${community.path.editormdUploadPath}") private String editormdUploadPath; - /** - * 进入帖子发布页 - * @return - * - * 前端点击直接跳转到/site/discuss-publish页面,无传入参数也无返回参数 - */ - @GetMapping("/publish") - public String getPublishPage () { - return "/site/discuss-publish"; - } - /** * markdown 图片上传 * @param file @@ -114,15 +103,13 @@ public class DiscussPostController extends BaseController implements CommunityCo * */ @PostMapping("/add") - @ResponseBody - public Result addDiscussPost(HashMap map) { + public Result addDiscussPost(@RequestBody HashMap map) { String title = map.get("title"); String content = map.get("content"); User user = getUser(); if (user == null) { -// return CommunityUtil.getJSONString(403, "您还未登录"); - return new Result("forbidden","403","您还未登录"+"---"+title+"---"+content); + return new Result("forbidden","403","您还未登录"); } DiscussPost discussPost = new DiscussPost(); @@ -145,7 +132,6 @@ public class DiscussPostController extends BaseController implements CommunityCo String redisKey = RedisKeyUtil.getPostScoreKey(); redisTemplate.opsForSet().add(redisKey, discussPost.getId()); -// return CommunityUtil.getJSONString(0, "发布成功"); return new Result("success","200","发布成功"); } @@ -275,7 +261,6 @@ public class DiscussPostController extends BaseController implements CommunityCo * @return */ @PostMapping("/wonderful") - @ResponseBody public Result setWonderful(@RequestBody HashMap map) { int id = map.get("id"); diff --git a/src/main/java/com/greate/community/controller/FollowController.java b/src/main/java/com/greate/community/controller/FollowController.java index cca0994..1acc60e 100644 --- a/src/main/java/com/greate/community/controller/FollowController.java +++ b/src/main/java/com/greate/community/controller/FollowController.java @@ -23,7 +23,7 @@ import java.util.Map; /** * 关注(目前只做了关注用户) */ -@Controller +@RestController public class FollowController extends BaseController implements CommunityConstant{ @Autowired diff --git a/src/main/java/com/greate/community/controller/IndexController.java b/src/main/java/com/greate/community/controller/IndexController.java index 28bfb99..24ed4c7 100644 --- a/src/main/java/com/greate/community/controller/IndexController.java +++ b/src/main/java/com/greate/community/controller/IndexController.java @@ -11,10 +11,7 @@ import com.greate.community.util.CommunityConstant; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import java.util.ArrayList; import java.util.HashMap; @@ -24,7 +21,7 @@ import java.util.Map; /** * 首页 */ -@Controller +@RestController public class IndexController implements CommunityConstant { @Autowired @@ -36,11 +33,6 @@ public class IndexController implements CommunityConstant { @Autowired private LikeService likeService; - @GetMapping("/") - public String root() { - return "forward:/index"; - } - /** * 进入首页 * @param model diff --git a/src/main/java/com/greate/community/controller/SearchController.java b/src/main/java/com/greate/community/controller/SearchController.java index 3a68f3f..448e55d 100644 --- a/src/main/java/com/greate/community/controller/SearchController.java +++ b/src/main/java/com/greate/community/controller/SearchController.java @@ -3,6 +3,7 @@ package com.greate.community.controller; import com.alibaba.fastjson.JSONObject; import com.greate.community.entity.DiscussPost; import com.greate.community.entity.Page; +import com.greate.community.entity.Result; import com.greate.community.service.ElasticsearchService; import com.greate.community.service.LikeService; import com.greate.community.service.UserService; @@ -38,7 +39,7 @@ public class SearchController extends BaseController implements CommunityConstan * @return */ @GetMapping("/search") - public String search(String keyword, @RequestBody Page page) { + public Result search(String keyword, @RequestBody Page page) { JSONObject jsonObject = new JSONObject(); // 搜索帖子 (Spring 提供的 Page 当前页码从 0 开始计数) org.springframework.data.domain.Page searchResult = @@ -66,7 +67,7 @@ public class SearchController extends BaseController implements CommunityConstan page.setPath("/search?keyword="+ keyword); page.setRows(searchResult == null ? 0 : (int) searchResult.getTotalElements()); - return "/site/search"; + return new Result("success", Result.SUCCESS, jsonObject); } -- Gitee From 7438ac9fcb6d1fd844c7e340bcbd288e72ffceba Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Tue, 8 Feb 2022 22:25:35 +0800 Subject: [PATCH 013/125] =?UTF-8?q?=E5=88=86=E9=A1=B5=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E6=8E=A5=E6=94=B6=E5=8F=82=E6=95=B0=E5=BD=A2=E5=BC=8F=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/DiscussPostController.java | 2 +- .../controller/FollowController.java | 4 +- .../community/controller/IndexController.java | 2 +- .../community/controller/LoginController.java | 61 ------------------- .../controller/MessageController.java | 6 +- .../controller/SearchController.java | 2 +- .../community/controller/UserController.java | 4 +- 7 files changed, 10 insertions(+), 71 deletions(-) diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index 77493ae..9857dc2 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -143,7 +143,7 @@ public class DiscussPostController extends BaseController implements CommunityCo */ @GetMapping("/detail/{discussPostId}") @ResponseBody - public Result getDiscussPost(@PathVariable("discussPostId") int discussPostId, Model model,@RequestBody Page page) { + public Result getDiscussPost(@PathVariable("discussPostId") int discussPostId, Model model, Page page) { HashMap resultMap=new HashMap<>(); // 帖子 diff --git a/src/main/java/com/greate/community/controller/FollowController.java b/src/main/java/com/greate/community/controller/FollowController.java index 1acc60e..86a75ff 100644 --- a/src/main/java/com/greate/community/controller/FollowController.java +++ b/src/main/java/com/greate/community/controller/FollowController.java @@ -90,7 +90,7 @@ public class FollowController extends BaseController implements CommunityConstan */ @GetMapping("/followees/{userId}") @ResponseBody - public Result getFollowees(@PathVariable("userId") int userId,@RequestBody Page page, Model model) { + public Result getFollowees(@PathVariable("userId") int userId,Page page, Model model) { HashMap hashMap = new HashMap<>(); User user = userService.findUserById(userId); @@ -130,7 +130,7 @@ public class FollowController extends BaseController implements CommunityConstan */ @GetMapping("/followers/{userId}") @ResponseBody - public Result getFollowers(@PathVariable("userId") int userId,@RequestBody Page page, Model model) { + public Result getFollowers(@PathVariable("userId") int userId, Page page, Model model) { HashMap hashMap = new HashMap<>(); User user = userService.findUserById(userId); diff --git a/src/main/java/com/greate/community/controller/IndexController.java b/src/main/java/com/greate/community/controller/IndexController.java index 24ed4c7..723e9f6 100644 --- a/src/main/java/com/greate/community/controller/IndexController.java +++ b/src/main/java/com/greate/community/controller/IndexController.java @@ -42,7 +42,7 @@ public class IndexController implements CommunityConstant { */ @GetMapping("/index") @ResponseBody - public Result getIndexPage(Model model,@RequestBody Page page, @RequestParam(name = "orderMode", defaultValue = "0") int orderMode) { + public Result getIndexPage(Model model, Page page, @RequestParam(name = "orderMode", defaultValue = "0") int orderMode) { HashMap hashMap = new HashMap<>(); // 获取总页数 diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index 67fdcaa..13d8afe 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -174,67 +174,6 @@ public class LoginController extends BaseController implements CommunityConstant } } - /** - * 用户使用微信账号第三方登录成功后,后端回调此链接向前端返回响应 - * - * @return - */ - @GetMapping("/wechat/login") - public Result wechatLogin(@AuthenticationPrincipal UserWeChat userWeChat) { - String username = userWeChat.getNickName();//微信昵称 - String password = CommunityUtil.generateUUID();//随机密码,不能随便让人破解 - String headerUrl = userWeChat.getHeadimgurl();//微信头像地址 - String email = "wechat@none.com";//微信登录的用户,邮箱是一个特殊标识字符串 - - - // 若微信用户对应的账号已存在,跳过模拟注册操作,直接进入登录过程 - User u = userMapper.selectByName(username); - User user = new User(); - if (u == null) { - /**模拟注册操作**/ - user.setUsername(username); - user.setPassword(password); - user.setEmail(email); - user.setType(0); // 默认普通用户 - user.setStatus(1); // 微信登录用户默认激活,无需邮箱验证 - - // 用户头像 - user.setHeaderUrl(headerUrl);//微信头像地址 - user.setCreateTime(new Date()); // 注册时间 - - userMapper.insertUser(user); - // 这一步主要是为了获取userId - user = userMapper.selectByName(username); - /**模拟注册操作**/ - }else { - user = u; - } - - /**模拟普通登录过程**/ - // 凭证过期时间 - int expiredSeconds = DEFAULT_EXPIRED_SECONDS; - - // 用户名和密码均正确,为该用户生成登录凭证 - LoginTicket loginTicket = new LoginTicket(); - loginTicket.setUserId(user.getId()); - loginTicket.setTicket(CommunityUtil.generateUUID()); // 随机凭证 - loginTicket.setStatus(0); // 设置凭证状态为有效(当用户登出的时候,设置凭证状态为无效) - loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000)); // 设置凭证到期时间 - - // 将登录凭证存入 redis - String redisKey = RedisKeyUtil.getTicketKey(loginTicket.getTicket()); - redisTemplate.opsForValue().set(redisKey, loginTicket); - - String ticket = loginTicket.getTicket(); - return new Result("success", Result.SUCCESS, ticket); - /**模拟普通登录过程**/ - } - - - - - - /** * 用户使用微信账号第三方登录成功后,后端回调此链接向前端返回响应 * diff --git a/src/main/java/com/greate/community/controller/MessageController.java b/src/main/java/com/greate/community/controller/MessageController.java index 2c1e898..a166b82 100644 --- a/src/main/java/com/greate/community/controller/MessageController.java +++ b/src/main/java/com/greate/community/controller/MessageController.java @@ -35,7 +35,7 @@ public class MessageController extends BaseController implements CommunityConsta * @return */ @GetMapping("/letter/list") - public Result getLetterList(@RequestBody Page page) { + public Result getLetterList( Page page) { // Integer.valueOf("abc"); // 测试统一异常处理(普通请求) JSONObject jsonObject = new JSONObject(); @@ -84,7 +84,7 @@ public class MessageController extends BaseController implements CommunityConsta * @return */ @GetMapping("/letter/detail/{conversationId}") - public Result getLetterDetail(@PathVariable("conversationId") String conversationId, @RequestBody Page page) { + public Result getLetterDetail(@PathVariable("conversationId") String conversationId, Page page) { JSONObject jsonObject = new JSONObject(); // 分页信息 @@ -399,7 +399,7 @@ public class MessageController extends BaseController implements CommunityConsta * @return */ @GetMapping("/notice/detail/{topic}") - public Result getNoticeDetail(@PathVariable("topic") String topic, @RequestBody Page page) { + public Result getNoticeDetail(@PathVariable("topic") String topic, Page page) { User user = getUser(); // page.setLimit(5);//前端注入 diff --git a/src/main/java/com/greate/community/controller/SearchController.java b/src/main/java/com/greate/community/controller/SearchController.java index 448e55d..635262f 100644 --- a/src/main/java/com/greate/community/controller/SearchController.java +++ b/src/main/java/com/greate/community/controller/SearchController.java @@ -39,7 +39,7 @@ public class SearchController extends BaseController implements CommunityConstan * @return */ @GetMapping("/search") - public Result search(String keyword, @RequestBody Page page) { + public Result search(String keyword, Page page) { JSONObject jsonObject = new JSONObject(); // 搜索帖子 (Spring 提供的 Page 当前页码从 0 开始计数) org.springframework.data.domain.Page searchResult = diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index f23fe87..30ef73d 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -159,7 +159,7 @@ public class UserController extends BaseController implements CommunityConstant * @return */ @GetMapping("/discuss/{userId}") - public Result getMyDiscussPosts(@PathVariable("userId") int userId, @RequestBody Page page) { + public Result getMyDiscussPosts(@PathVariable("userId") int userId, Page page) { JSONObject jsonObject = new JSONObject(); User user = userService.findUserById(userId); if (user == null) { @@ -201,7 +201,7 @@ public class UserController extends BaseController implements CommunityConstant * @return */ @GetMapping("/comment/{userId}") - public Result getMyComments(@PathVariable("userId") int userId, @RequestBody Page page) { + public Result getMyComments(@PathVariable("userId") int userId, Page page) { JSONObject jsonObject = new JSONObject(); User user = userService.findUserById(userId); if (user == null) { -- Gitee From 382cc30ddef1fe516bbd0deaf8297a30059e75d5 Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Wed, 9 Feb 2022 19:19:30 +0800 Subject: [PATCH 014/125] fix search --- .../community/config/SecurityConfig.java | 124 ++---------------- .../controller/SearchController.java | 3 +- .../greate/community/service/UserService.java | 17 --- .../greate/community/ElasticsearchTest.java | 18 +++ 4 files changed, 31 insertions(+), 131 deletions(-) create mode 100644 src/test/java/com/greate/community/ElasticsearchTest.java diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index f6b2b16..716e9e8 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -7,6 +7,7 @@ import com.greate.community.util.CommunityConstant; import com.greate.community.util.CommunityUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -26,108 +27,6 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; -//@Configuration -//public class SecurityConfig extends WebSecurityConfigurerAdapter implements CommunityConstant { -// -// @Autowired -// private AuthenticationTokenFilter authenticationTokenFilter; -// -// /** -// * 静态资源 -// * -// * @param web -// * @throws Exception -// */ -// @Override -// public void configure(WebSecurity web) throws Exception { -// web.ignoring().antMatchers("/resources/**"); -// } -// -// // 认证环节我们使用自己的代码 LoginController,绕过 Spring Security 的 -// -// /** -// * 授权 -// * -// * @param http -// * @throws Exception -// */ -// @Override -// protected void configure(HttpSecurity http) throws Exception { -// http.cors().and().csrf().disable() -// .authorizeRequests() -// .antMatchers( -// "/user/setting", -// "/user/upload", -// "/discuss/add", -// "/discuss/publish", -// "/comment/add/**", -// "/letter/**", -// "/notice/**", -// "/like", -// "/follow", -// "/unfollow" -// ) -// .hasAnyAuthority( -// AUTHORITY_USER, -// AUTHORITY_ADMIN, -// AUTHORITY_MODERATOR -// ) -// -// .antMatchers( -// "/discuss/top", -// "/discuss/wonderful" -// ) -// .hasAnyAuthority( -// AUTHORITY_MODERATOR -// ) -// -// .antMatchers( -// "/discuss/delete", -// "/discuss/delete/", -// "/data/**" -// ) -// .hasAnyAuthority( -// AUTHORITY_ADMIN -// ) -// -// .anyRequest().permitAll() -// -// .and().csrf().disable(); -// -// //添加jwt认证器 -// http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); -// // 权限不够时的处理 -// http.exceptionHandling() -// // 1. 未登录时的处理 -// .authenticationEntryPoint(new AuthenticationEntryPoint() { -// @Override -// public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException { -// // 异步请求 -// response.setCharacterEncoding("UTF-8"); -// response.setContentType("application/plain;charset=utf-8"); -// response.getWriter().write(CommunityUtil.getJSONString(403, "你还没有登录")); -// } -// }) -// // 2. 权限不够时的处理 -// .accessDeniedHandler(new AccessDeniedHandler() { -// @Override -// public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException { -// // 异步请求 -// response.setContentType("application/plain;charset=utf-8"); -// PrintWriter writer = response.getWriter(); -// writer.write(CommunityUtil.getJSONString(403, "你没有访问该功能的权限")); -// } -// }); -// -// // Security 底层会默认拦截 /logout 请求,进行退出处理 -// // 此处赋予它一个根本不存在的退出路径,使得程序能够执行到我们自己编写的退出代码 -// http.logout().logoutUrl("/securitylogout"); -// -// http.headers().frameOptions().sameOrigin(); -// } -//} - - @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) @@ -156,6 +55,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm } // 认证环节我们使用自己的代码 LoginController,绕过 Spring Security 的 + /** * 授权 * @@ -164,14 +64,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm */ @Override protected void configure(HttpSecurity http) throws Exception { - //添加jwt认证器 - http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); - /** - * WeChat login - */ - http.addFilterBefore(weChatAuthorizationConfig.weChatFilter(), BasicAuthenticationFilter.class).addFilterBefore(weChatOAuth2ClientContextFilter, OAuth2ClientAuthenticationProcessingFilter.class); - - http.cors().and().csrf().disable() .authorizeRequests() .antMatchers( @@ -193,7 +85,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm AUTHORITY_ADMIN, AUTHORITY_MODERATOR ) - .antMatchers( "/discuss/top", "/discuss/wonderful" @@ -201,7 +92,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm .hasAnyAuthority( AUTHORITY_MODERATOR ) - .antMatchers( "/discuss/delete", "/discuss/delete/", @@ -210,8 +100,16 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm .hasAnyAuthority( AUTHORITY_ADMIN ) + .anyRequest().permitAll() + //不拦截所有OPTIONS请求 + .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() + .and().headers().cacheControl(); - .anyRequest().permitAll(); + //添加jwt认证器 + http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); + // 添加微信登录认证器 + http.addFilterBefore(weChatAuthorizationConfig.weChatFilter(), BasicAuthenticationFilter.class); + http.addFilterBefore(weChatOAuth2ClientContextFilter, OAuth2ClientAuthenticationProcessingFilter.class); // 权限不够时的处理 http.exceptionHandling() diff --git a/src/main/java/com/greate/community/controller/SearchController.java b/src/main/java/com/greate/community/controller/SearchController.java index 448e55d..c8c9c3a 100644 --- a/src/main/java/com/greate/community/controller/SearchController.java +++ b/src/main/java/com/greate/community/controller/SearchController.java @@ -11,6 +11,7 @@ import com.greate.community.util.CommunityConstant; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @@ -38,7 +39,7 @@ public class SearchController extends BaseController implements CommunityConstan * @param page * @return */ - @GetMapping("/search") + @PostMapping("/search") public Result search(String keyword, @RequestBody Page page) { JSONObject jsonObject = new JSONObject(); // 搜索帖子 (Spring 提供的 Page 当前页码从 0 开始计数) diff --git a/src/main/java/com/greate/community/service/UserService.java b/src/main/java/com/greate/community/service/UserService.java index ccd183e..6725cf3 100644 --- a/src/main/java/com/greate/community/service/UserService.java +++ b/src/main/java/com/greate/community/service/UserService.java @@ -118,14 +118,6 @@ public class UserService implements CommunityConstant { user.setCreateTime(new Date()); // 注册时间 userMapper.insertUser(user); -// Context context = new Context(); -// context.setVariable("email", user.getEmail()); -// // http://localhost:8080/echo/activation/用户id/激活码 -// String url = domain + contextPath + "/activation/" + user.getId() + "/" + user.getActivationCode(); -// context.setVariable("url", url); -// String content = templateEngine.process("/mail/activation", context); -// mailClient.sendMail(user.getEmail(),"激活账号", content); - return map; } @@ -240,7 +232,6 @@ public class UserService implements CommunityConstant { * @return */ public int updateHeader(int userId, String headUrl) { - // return userMapper.updateHeader(userId, headUrl); int rows = userMapper.updateHeader(userId, headUrl); clearCache(userId); return rows; @@ -333,14 +324,6 @@ public class UserService implements CommunityConstant { // 给注册用户发送激活邮件 String code = emailUtil.sendRetrievePasswordCode(email); -// Context context = new Context(); -// context.setVariable("email", "您的验证码是 " + randomCode); -// // http://localhost:8080/echo/activation/用户id/激活码 -// String url = domain + contextPath + "/activation/" + user.getId() + "/" + user.getActivationCode(); -// context.setVariable("url", url); -// String content = templateEngine.process("/mail/activation", context); -// mailClient.sendMail(email,"重置账号密码", content); - final String redisKey = "EmailCode4ResetPwd:" + email; redisTemplate.opsForValue().set(redisKey, code, 600, TimeUnit.SECONDS); diff --git a/src/test/java/com/greate/community/ElasticsearchTest.java b/src/test/java/com/greate/community/ElasticsearchTest.java new file mode 100644 index 0000000..3bf9bfd --- /dev/null +++ b/src/test/java/com/greate/community/ElasticsearchTest.java @@ -0,0 +1,18 @@ +package com.greate.community; + +import com.greate.community.service.ElasticsearchService; +import lombok.Data; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +@Data +public class ElasticsearchTest { + + @Autowired + private ElasticsearchService elasticsearchService; + + @Test + public void testAdd() { + + } +} -- Gitee From 6fcc88af2f4ffb47c3a364dcaddcf2d709f7a123 Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Wed, 9 Feb 2022 22:50:24 +0800 Subject: [PATCH 015/125] update es --- pom.xml | 16 +- .../community/config/ElasticSearchConfig.java | 64 +++++++ .../community/config/SecurityConfig.java | 5 +- .../controller/SearchController.java | 2 - .../elasticsearch/DiscussPostRepository.java | 10 -- .../greate/community/entity/DiscussPost.java | 2 +- .../greate/community/event/EventConsumer.java | 4 +- .../community/quartz/PostScoreRefreshJob.java | 2 +- .../service/ElasticsearchService.java | 161 ++++++++++-------- .../resources/application-develop.properties | 13 +- .../greate/community/ElasticsearchTest.java | 17 +- 11 files changed, 191 insertions(+), 105 deletions(-) create mode 100644 src/main/java/com/greate/community/config/ElasticSearchConfig.java delete mode 100644 src/main/java/com/greate/community/dao/elasticsearch/DiscussPostRepository.java diff --git a/pom.xml b/pom.xml index a3fb457..20d7a48 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 2.1.5.RELEASE + 2.6.1 com.greate @@ -105,9 +105,14 @@ + + + + - org.springframework.boot - spring-boot-starter-data-elasticsearch + org.springframework.data + spring-data-elasticsearch + 4.2.1 @@ -178,6 +183,11 @@ org.projectlombok lombok + + junit + junit + test + diff --git a/src/main/java/com/greate/community/config/ElasticSearchConfig.java b/src/main/java/com/greate/community/config/ElasticSearchConfig.java new file mode 100644 index 0000000..65f3f7c --- /dev/null +++ b/src/main/java/com/greate/community/config/ElasticSearchConfig.java @@ -0,0 +1,64 @@ +package com.greate.community.config; + +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; +import org.elasticsearch.client.RestHighLevelClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; + +/** + * 类名称:ElasticSearchConfig + * 类描述:ElasticSearch配置类 + * 创建人:CSUpipixia + * 创建时间:2022/2/9 19:49 + * + * @version v1.0 + */ +@Configuration +public class ElasticSearchConfig { + + @Value("${elasticsearch.username}") + private String username; + + @Value("${elasticsearch.password}") + private String password; + + @Value("${elasticsearch.hostname}") + private String hostname; + + @Value("${elasticsearch.port}") + private int port; + + @Bean + public RestHighLevelClient restHighLevelClient() { + + final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(AuthScope.ANY, + new UsernamePasswordCredentials(username, password)); + + RestClientBuilder builder = RestClient.builder( + new HttpHost(hostname, port, "https")) + .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() { + @Override + public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) { + return httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + } + }); + + return new RestHighLevelClient(builder); + } + + @Bean + ElasticsearchRestTemplate elasticsearchRestTemplate(@Autowired RestHighLevelClient restHighLevelClient) { + return new ElasticsearchRestTemplate(restHighLevelClient); + } +} diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index 716e9e8..5f78f33 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -100,10 +100,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm .hasAnyAuthority( AUTHORITY_ADMIN ) - .anyRequest().permitAll() - //不拦截所有OPTIONS请求 - .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() - .and().headers().cacheControl(); + .anyRequest().permitAll(); //添加jwt认证器 http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); diff --git a/src/main/java/com/greate/community/controller/SearchController.java b/src/main/java/com/greate/community/controller/SearchController.java index c8c9c3a..8b1adbd 100644 --- a/src/main/java/com/greate/community/controller/SearchController.java +++ b/src/main/java/com/greate/community/controller/SearchController.java @@ -9,8 +9,6 @@ import com.greate.community.service.LikeService; import com.greate.community.service.UserService; import com.greate.community.util.CommunityConstant; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; diff --git a/src/main/java/com/greate/community/dao/elasticsearch/DiscussPostRepository.java b/src/main/java/com/greate/community/dao/elasticsearch/DiscussPostRepository.java deleted file mode 100644 index c68454f..0000000 --- a/src/main/java/com/greate/community/dao/elasticsearch/DiscussPostRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.greate.community.dao.elasticsearch; - -import com.greate.community.entity.DiscussPost; -import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface DiscussPostRepository extends ElasticsearchRepository { - -} diff --git a/src/main/java/com/greate/community/entity/DiscussPost.java b/src/main/java/com/greate/community/entity/DiscussPost.java index db41959..85c03c0 100644 --- a/src/main/java/com/greate/community/entity/DiscussPost.java +++ b/src/main/java/com/greate/community/entity/DiscussPost.java @@ -11,7 +11,7 @@ import java.util.Date; * 讨论贴 * 对应数据库表 `discuss_post` */ -@Document(indexName = "discusspost", type = "_doc", shards = 6, replicas = 3) +@Document(indexName = "discusspost") public class DiscussPost { @Id diff --git a/src/main/java/com/greate/community/event/EventConsumer.java b/src/main/java/com/greate/community/event/EventConsumer.java index 650446d..90104e3 100644 --- a/src/main/java/com/greate/community/event/EventConsumer.java +++ b/src/main/java/com/greate/community/event/EventConsumer.java @@ -90,7 +90,7 @@ public class EventConsumer implements CommunityConstant { } DiscussPost post = discussPostService.findDiscussPostById(event.getEntityId()); - elasticsearchService.saveDiscusspost(post); + elasticsearchService.saveDiscussPost(post); } @@ -109,7 +109,7 @@ public class EventConsumer implements CommunityConstant { return ; } - elasticsearchService.deleteDiscusspost(event.getEntityId()); + elasticsearchService.deleteDiscussPost(event.getEntityId()); } diff --git a/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java b/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java index c0a7d86..f1b2742 100644 --- a/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java +++ b/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java @@ -94,7 +94,7 @@ public class PostScoreRefreshJob implements Job, CommunityConstant { discussPostService.updateScore(postId, score); // 同步搜索数据 post.setScore(score); - elasticsearchService.saveDiscusspost(post); + elasticsearchService.saveDiscussPost(post); } } diff --git a/src/main/java/com/greate/community/service/ElasticsearchService.java b/src/main/java/com/greate/community/service/ElasticsearchService.java index 0c2a780..ef3a6a2 100644 --- a/src/main/java/com/greate/community/service/ElasticsearchService.java +++ b/src/main/java/com/greate/community/service/ElasticsearchService.java @@ -1,29 +1,23 @@ package com.greate.community.service; -import com.greate.community.dao.elasticsearch.DiscussPostRepository; import com.greate.community.entity.DiscussPost; -import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.index.query.QueryBuilders; -import org.elasticsearch.search.SearchHit; -import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; -import org.elasticsearch.search.fetch.subphase.highlight.HighlightField; import org.elasticsearch.search.sort.SortBuilders; import org.elasticsearch.search.sort.SortOrder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; -import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; -import org.springframework.data.elasticsearch.core.SearchResultMapper; -import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage; -import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl; +import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; +import org.springframework.data.elasticsearch.core.SearchHit; +import org.springframework.data.elasticsearch.core.SearchHits; +import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; -import org.springframework.data.elasticsearch.core.query.SearchQuery; import org.springframework.stereotype.Service; import java.util.ArrayList; -import java.util.Date; import java.util.List; /** @@ -32,26 +26,28 @@ import java.util.List; @Service public class ElasticsearchService { - @Autowired - private DiscussPostRepository discussPostRepository; +// @Autowired +// private DiscussPostRepository discussPostRepository; @Autowired - private ElasticsearchTemplate elasticsearchTemplate; +// private ElasticsearchTemplate elasticsearchTemplate; + private ElasticsearchRestTemplate elasticsearchRestTemplate; /** * 将数据插入 Elasticsearch 服务器 * @param post */ - public void saveDiscusspost(DiscussPost post) { - discussPostRepository.save(post); + public void saveDiscussPost(DiscussPost post) { + elasticsearchRestTemplate.save(post); +// discussPostRepository.save(post); } /** * 将数据从 Elasticsearch 服务器中删除 * @param id */ - public void deleteDiscusspost(int id) { - discussPostRepository.deleteById(id); + public void deleteDiscussPost(int id) { + elasticsearchRestTemplate.delete(String.valueOf(id), DiscussPost.class); } /** @@ -62,7 +58,8 @@ public class ElasticsearchService { * @return */ public Page searchDiscussPost(String keyword, int current, int limit) { - SearchQuery searchQuery = new NativeSearchQueryBuilder() + Pageable pageable = PageRequest.of(current,limit); + NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.multiMatchQuery(keyword, "title", "content")) .withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC)) .withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC)) @@ -73,60 +70,80 @@ public class ElasticsearchService { new HighlightBuilder.Field("content").preTags("").postTags("") ).build(); - return elasticsearchTemplate.queryForPage(searchQuery, DiscussPost.class, new SearchResultMapper() { - @Override - public AggregatedPage mapResults(SearchResponse searchResponse, Class aClass, Pageable pageable) { - // 获取命中的数据 - SearchHits hits = searchResponse.getHits(); - if (hits.getTotalHits() <= 0) { - return null; - } - - // 处理命中的数据 - List list = new ArrayList<>(); - for (SearchHit hit : hits) { - DiscussPost post = new DiscussPost(); - - String id = hit.getSourceAsMap().get("id").toString(); - post.setId(Integer.valueOf(id)); - - String userId = hit.getSourceAsMap().get("userId").toString(); - post.setUserId(Integer.valueOf(userId)); - - String title = hit.getSourceAsMap().get("title").toString(); - post.setTitle(title); - - String content = hit.getSourceAsMap().get("content").toString(); - post.setContent(content); - - String status = hit.getSourceAsMap().get("status").toString(); - post.setStatus(Integer.valueOf(status)); - - String createTime = hit.getSourceAsMap().get("createTime").toString(); - post.setCreateTime(new Date(Long.valueOf(createTime))); - - String commentCount = hit.getSourceAsMap().get("commentCount").toString(); - post.setCommentCount(Integer.valueOf(commentCount)); - - // 处理高亮显示的内容 - HighlightField titleField = hit.getHighlightFields().get("title"); - if (titleField != null) { - post.setTitle(titleField.getFragments()[0].toString()); - } - - HighlightField contentField = hit.getHighlightFields().get("content"); - if (contentField != null) { - post.setContent(contentField.getFragments()[0].toString()); - } - - list.add(post); - } - - return new AggregatedPageImpl(list, pageable, - hits.getTotalHits(), searchResponse.getAggregations(), searchResponse.getScrollId(), hits.getMaxScore()); - } - }); + SearchHits searchHits = elasticsearchRestTemplate.search(searchQuery, DiscussPost.class); + //封装page对象 + List content = new ArrayList<>(); + for (SearchHit productSearchHit:searchHits) + content.add(productSearchHit.getContent()); + return new PageImpl<>(content,pageable,searchHits.getTotalHits()); } +// public Page searchDiscussPost(String keyword, int current, int limit) { +// SearchQuery searchQuery = new NativeSearchQueryBuilder() +// .withQuery(QueryBuilders.multiMatchQuery(keyword, "title", "content")) +// .withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC)) +// .withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC)) +// .withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC)) +// .withPageable(PageRequest.of(current, limit)) +// .withHighlightFields( +// new HighlightBuilder.Field("title").preTags("").postTags(""), +// new HighlightBuilder.Field("content").preTags("").postTags("") +// ).build(); +// +// return elasticsearchTemplate.queryForPage(searchQuery, DiscussPost.class, new SearchResultMapper() { +// @Override +// public AggregatedPage mapResults(SearchResponse searchResponse, Class aClass, Pageable pageable) { +// // 获取命中的数据 +// SearchHits hits = searchResponse.getHits(); +// if (hits.getTotalHits() <= 0) { +// return null; +// } +// +// // 处理命中的数据 +// List list = new ArrayList<>(); +// for (SearchHit hit : hits) { +// DiscussPost post = new DiscussPost(); +// +// String id = hit.getSourceAsMap().get("id").toString(); +// post.setId(Integer.valueOf(id)); +// +// String userId = hit.getSourceAsMap().get("userId").toString(); +// post.setUserId(Integer.valueOf(userId)); +// +// String title = hit.getSourceAsMap().get("title").toString(); +// post.setTitle(title); +// +// String content = hit.getSourceAsMap().get("content").toString(); +// post.setContent(content); +// +// String status = hit.getSourceAsMap().get("status").toString(); +// post.setStatus(Integer.valueOf(status)); +// +// String createTime = hit.getSourceAsMap().get("createTime").toString(); +// post.setCreateTime(new Date(Long.valueOf(createTime))); +// +// String commentCount = hit.getSourceAsMap().get("commentCount").toString(); +// post.setCommentCount(Integer.valueOf(commentCount)); +// +// // 处理高亮显示的内容 +// HighlightField titleField = hit.getHighlightFields().get("title"); +// if (titleField != null) { +// post.setTitle(titleField.getFragments()[0].toString()); +// } +// +// HighlightField contentField = hit.getHighlightFields().get("content"); +// if (contentField != null) { +// post.setContent(contentField.getFragments()[0].toString()); +// } +// +// list.add(post); +// } +// +// return new AggregatedPageImpl(list, pageable, +// hits.getTotalHits(), searchResponse.getAggregations(), searchResponse.getScrollId(), hits.getMaxScore()); +// } +// }); +// +// } } diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index d2f979d..8ca5108 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -50,24 +50,21 @@ spring.redis.password = root2021 # Kafka spring.kafka.bootstrap-servers = 159.75.254.198:9092 -# ֶμ Kafka װе consumer.proerties޸, ޸ϺҪ Kafka spring.kafka.consumer.group-id = test-consumer-group spring.kafka.consumer.enable-auto-commit = true spring.kafka.consumer.auto-commit-interval = 3000 # Elasticsearch -spring.data.elasticsearch.cluster-name = elastic -spring.data.elasticsearch.cluster-nodes = 127.0.0.1:9300 -spring.data.elasticsearch.repositories.enabled = true -spring.elasticsearch.rest.uris = https://es-50b9cgrk.public.tencentelasticsearch.com:9200 -spring.elasticsearch.rest.username = elastic -spring.elasticsearch.rest.password = elastic2021. +elasticsearch.username = elastic +elasticsearch.password = elastic2021. +elasticsearch.hostname = es-50b9cgrk.public.tencentelasticsearch.com +elasticsearch.port = 9200 # Quartz spring.quartz.job-store-type = jdbc spring.quartz.scheduler-name = communityScheduler spring.quartz.properties.org.quartz.scheduler.instanceId = AUTO -spring.quartz.properties.org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX +spring.quartz.properties.org.quartz.jobStore.class = org.springframework.scheduling.quartz.LocalDataSourceJobStore spring.quartz.properties.org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate spring.quartz.properties.org.quartz.jobStore.isClustered = true spring.quartz.properties.org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool diff --git a/src/test/java/com/greate/community/ElasticsearchTest.java b/src/test/java/com/greate/community/ElasticsearchTest.java index 3bf9bfd..ec8210e 100644 --- a/src/test/java/com/greate/community/ElasticsearchTest.java +++ b/src/test/java/com/greate/community/ElasticsearchTest.java @@ -1,18 +1,31 @@ package com.greate.community; +import com.greate.community.dao.DiscussPostMapper; import com.greate.community.service.ElasticsearchService; import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.checkerframework.checker.units.qual.A; import org.junit.Test; +import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @Data +@Slf4j +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes=CommunityApplication.class) public class ElasticsearchTest { + @Autowired + private DiscussPostMapper discussPostMapper; + @Autowired private ElasticsearchService elasticsearchService; @Test - public void testAdd() { - + public void testInsert() { + elasticsearchService.saveDiscussPost(discussPostMapper.selectDiscussPostById(1)); + elasticsearchService.saveDiscussPost(discussPostMapper.selectDiscussPostById(2)); } } -- Gitee From 4c0235ae11d394e1127f2bc0c2c64638cfb86d4b Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Wed, 9 Feb 2022 22:53:20 +0800 Subject: [PATCH 016/125] update project name --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 20d7a48..b940a96 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ community 0.0.1-SNAPSHOT community - great community — Echo + hust bbs jar @@ -192,7 +192,7 @@ - ROOT + hust-bbs org.springframework.boot -- Gitee From f56db909a7bc6bd2adeff1dd6fcd06eb02333fe4 Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Fri, 11 Feb 2022 22:13:32 +0800 Subject: [PATCH 017/125] add exp functions --- .../community/config/SecurityConfig.java | 3 +- .../greate/community/config/WebMvcConfig.java | 8 - .../controller/DiscussPostController.java | 64 ++------ .../community/controller/ExpController.java | 32 ++++ .../community/controller/IndexController.java | 1 - .../community/controller/LoginController.java | 7 + .../controller/MessageController.java | 151 ------------------ .../community/controller/UserController.java | 3 +- .../interceptor/DataInterceptor.java | 16 +- .../interceptor/MessageInterceptor.java | 80 +++++----- .../com/greate/community/dao/ExpMapper.java | 35 ++++ .../com/greate/community/dao/UserMapper.java | 9 +- .../java/com/greate/community/entity/Exp.java | 27 ++++ .../com/greate/community/entity/Page.java | 4 + .../com/greate/community/entity/User.java | 146 +---------------- .../greate/community/event/EventConsumer.java | 18 +++ .../greate/community/service/DataService.java | 4 + .../community/service/DiscussPostService.java | 23 ++- .../greate/community/service/ExpService.java | 85 ++++++++++ .../community/service/FollowService.java | 11 +- .../greate/community/service/LikeService.java | 9 +- .../greate/community/service/UserService.java | 42 ++--- .../community/util/CommunityConstant.java | 2 +- .../com/greate/community/util/ExpType.java | 116 ++++++++++++++ src/main/resources/mapper/exp-mapper.xml | 43 +++++ src/main/resources/mapper/user-mapper.xml | 11 +- .../com/greate/community/ExpServiceTest.java | 29 ++++ 27 files changed, 529 insertions(+), 450 deletions(-) create mode 100644 src/main/java/com/greate/community/controller/ExpController.java create mode 100644 src/main/java/com/greate/community/dao/ExpMapper.java create mode 100644 src/main/java/com/greate/community/entity/Exp.java create mode 100644 src/main/java/com/greate/community/service/ExpService.java create mode 100644 src/main/java/com/greate/community/util/ExpType.java create mode 100644 src/main/resources/mapper/exp-mapper.xml create mode 100644 src/test/java/com/greate/community/ExpServiceTest.java diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index 5f78f33..e85b79b 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -78,7 +78,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm "/like", "/follow", "/unfollow", - "/cos/credential" + "/cos/credential", + "/exp/**" ) .hasAnyAuthority( AUTHORITY_USER, diff --git a/src/main/java/com/greate/community/config/WebMvcConfig.java b/src/main/java/com/greate/community/config/WebMvcConfig.java index 9e06584..cae98fc 100644 --- a/src/main/java/com/greate/community/config/WebMvcConfig.java +++ b/src/main/java/com/greate/community/config/WebMvcConfig.java @@ -1,7 +1,6 @@ package com.greate.community.config; import com.greate.community.controller.interceptor.DataInterceptor; -import com.greate.community.controller.interceptor.MessageInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; @@ -14,19 +13,12 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebMvcConfig implements WebMvcConfigurer { - @Autowired - private MessageInterceptor messageInterceptor; - @Autowired private DataInterceptor dataInterceptor; // 对除静态资源外所有路径进行拦截 @Override public void addInterceptors(InterceptorRegistry registry) { - - registry.addInterceptor(messageInterceptor) - .excludePathPatterns("/css/**", "/js/**", "/img/**", "/editor-md/**", "/editor-md-upload/**"); - registry.addInterceptor(dataInterceptor) .excludePathPatterns("/css/**", "/js/**", "/img/**", "/editor-md/**", "/editor-md-upload/**"); } diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index 77493ae..b190a19 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -1,15 +1,11 @@ package com.greate.community.controller; +import com.greate.community.dao.ExpMapper; import com.greate.community.entity.*; import com.greate.community.event.EventProducer; -import com.greate.community.service.CommentService; -import com.greate.community.service.DiscussPostService; -import com.greate.community.service.LikeService; -import com.greate.community.service.UserService; -import com.greate.community.util.CommunityConstant; -import com.greate.community.util.CommunityUtil; -import com.greate.community.util.HostHolder; -import com.greate.community.util.RedisKeyUtil; +import com.greate.community.service.*; +import com.greate.community.util.*; +import org.checkerframework.checker.units.qual.A; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; @@ -35,6 +31,9 @@ public class DiscussPostController extends BaseController implements CommunityCo @Autowired private UserService userService; + @Autowired + private ExpService expService; + @Autowired private CommentService commentService; @@ -55,48 +54,6 @@ public class DiscussPostController extends BaseController implements CommunityCo @Value("${server.servlet.context-path}") private String contextPath; - // editorMd 图片上传地址 - @Value("${community.path.editormdUploadPath}") - private String editormdUploadPath; - - /** - * markdown 图片上传 - * @param file - * @return - * - */ - @PostMapping("/uploadMdPic") - @ResponseBody - public Result uploadMdPic(@RequestParam(value = "editormd-image-file", required = false) MultipartFile file) { - - String url = null; // 图片访问地址 - try { - // 获取上传文件的名称 - String trueFileName = file.getOriginalFilename(); - String suffix = trueFileName.substring(trueFileName.lastIndexOf(".")); - String fileName = CommunityUtil.generateUUID() + suffix; - - // 图片存储路径 - File dest = new File(editormdUploadPath + "/" + fileName); - if (!dest.getParentFile().exists()) { - dest.getParentFile().mkdirs(); - } - - // 保存图片到存储路径 - file.transferTo(dest); - - // 图片访问地址 - url = domain + contextPath + "/editor-md-upload/" + fileName; - } catch (Exception e) { - e.printStackTrace(); -// return CommunityUtil.getEditorMdJSONString(0, "上传失败", url); - return new Result("fail",Result.INTERNAL_SERVER_ERROR,url); - } - -// return CommunityUtil.getEditorMdJSONString(1, "上传成功", url); - return new Result("success",Result.SUCCESS,url); - } - /** * 添加帖子(发帖) * @return @@ -223,10 +180,13 @@ public class DiscussPostController extends BaseController implements CommunityCo } } -// model.addAttribute("comments", commentVoList); resultMap.put("comments",commentVoList); -// return "/site/discuss-detail"; + //增加经验 + if (getUser() != null) { + expService.handleGetExp(getUser().getId(), ExpType.EXP_BROWSE.getName()); + } + return new Result("success",Result.SUCCESS,resultMap); } diff --git a/src/main/java/com/greate/community/controller/ExpController.java b/src/main/java/com/greate/community/controller/ExpController.java new file mode 100644 index 0000000..d8c08c5 --- /dev/null +++ b/src/main/java/com/greate/community/controller/ExpController.java @@ -0,0 +1,32 @@ +package com.greate.community.controller; + +import com.google.gson.JsonObject; +import com.greate.community.entity.Page; +import com.greate.community.entity.Result; +import com.greate.community.entity.User; +import com.greate.community.service.ExpService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +/** + * 类名称:ExpController + * 类描述:经验控制器 + * 创建人:CSUpipixia + * 创建时间:2022/2/10 13:31 + * + * @version v1.0 + */ +@RestController +public class ExpController extends BaseController { + + @Autowired + private ExpService expService; + + @PostMapping("/exp/page") + public Result getPageOfExpLog(@RequestBody Page page) { + + return new Result("success", Result.SUCCESS, expService.getExpPageByUserId(getUser().getId(), page.getOffset(), page.getLimit())); + } +} diff --git a/src/main/java/com/greate/community/controller/IndexController.java b/src/main/java/com/greate/community/controller/IndexController.java index 24ed4c7..0238d92 100644 --- a/src/main/java/com/greate/community/controller/IndexController.java +++ b/src/main/java/com/greate/community/controller/IndexController.java @@ -9,7 +9,6 @@ import com.greate.community.service.LikeService; import com.greate.community.service.UserService; import com.greate.community.util.CommunityConstant; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index 13d8afe..ab2466c 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -9,9 +9,11 @@ import com.greate.community.dao.UserMapper; import com.greate.community.entity.LoginTicket; import com.greate.community.entity.Result; import com.greate.community.entity.User; +import com.greate.community.service.ExpService; import com.greate.community.service.UserService; import com.greate.community.util.CommunityConstant; import com.greate.community.util.CommunityUtil; +import com.greate.community.util.ExpType; import com.greate.community.util.RedisKeyUtil; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -40,6 +42,9 @@ public class LoginController extends BaseController implements CommunityConstant @Autowired private UserService userService; + @Autowired + private ExpService expService; + @Autowired private UserMapper userMapper; @@ -167,6 +172,8 @@ public class LoginController extends BaseController implements CommunityConstant Map map = userService.login(username, password, expiredSeconds); if (map.containsKey("ticket")) { String ticket = map.get("ticket").toString(); + // 增加经验 + expService.handleGetExp(Integer.parseInt(map.get("userId").toString()), ExpType.EXP_LOGIN.getName()); return new Result("success", Result.SUCCESS, ticket); } else { diff --git a/src/main/java/com/greate/community/controller/MessageController.java b/src/main/java/com/greate/community/controller/MessageController.java index 2c1e898..db7d73a 100644 --- a/src/main/java/com/greate/community/controller/MessageController.java +++ b/src/main/java/com/greate/community/controller/MessageController.java @@ -117,37 +117,6 @@ public class MessageController extends BaseController implements CommunityConsta return new Result("success", Result.SUCCESS, jsonObject); } -// public String getLetterDetail(@PathVariable("conversationId") String conversationId, Page page, Model model) { -// // 分页信息 -// page.setLimit(5); -// page.setPath("/letter/detail/" + conversationId); -// page.setRows(messageService.findLetterCount(conversationId)); -// -// // 私信列表 -// List letterList = messageService.findLetters(conversationId, page.getOffset(), page.getLimit()); -// -// List> letters = new ArrayList<>(); -// if (letterList != null) { -// for (Message message : letterList) { -// Map map = new HashMap<>(); -// map.put("letter", message); -// map.put("fromUser", userService.findUserById(message.getFromId())); -// letters.add(map); -// } -// } -// model.addAttribute("letters", letters); -// -// // 私信目标 -// model.addAttribute("target", getLetterTarget(conversationId)); -// -// // 将私信列表中的未读消息改为已读 -// List ids = getUnreadLetterIds(letterList); -// if (!ids.isEmpty()) { -// messageService.readMessage(ids); -// } -// -// return "/site/letter-detail"; -// } /** * 获取私信对方对象 @@ -308,89 +277,6 @@ public class MessageController extends BaseController implements CommunityConsta return new Result("success", Result.SUCCESS, jsonObject); } -// public String getNoticeList(Model model) { -// User user = hostHolder.getUser(); -// -// // 查询评论类通知 -// Message message = messageService.findLatestNotice(user.getId(), TOPIC_COMMNET); -// // 封装通知需要的各种数据 -// if (message != null) { -// Map messageVO = new HashMap<>(); -// -// messageVO.put("message", message); -// -// String content = HtmlUtils.htmlUnescape(message.getContent()); -// Map data = JSONObject.parseObject(content, HashMap.class); -// -// messageVO.put("user", userService.findUserById((Integer) data.get("userId"))); -// messageVO.put("entityType", data.get("entityType")); -// messageVO.put("entityId", data.get("entityId")); -// messageVO.put("postId", data.get("postId")); -// -// int count = messageService.findNoticeCount(user.getId(), TOPIC_COMMNET); -// messageVO.put("count", count); -// -// int unread = messageService.findNoticeUnReadCount(user.getId(), TOPIC_COMMNET); -// messageVO.put("unread", unread); -// -// model.addAttribute("commentNotice", messageVO); -// } -// -// // 查询点赞类通知 -// message = messageService.findLatestNotice(user.getId(), TOPIC_LIKE); -// if (message != null) { -// Map messageVO = new HashMap<>(); -// -// messageVO.put("message", message); -// -// String content = HtmlUtils.htmlUnescape(message.getContent()); -// Map data = JSONObject.parseObject(content, HashMap.class); -// -// messageVO.put("user", userService.findUserById((Integer) data.get("userId"))); -// messageVO.put("entityType", data.get("entityType")); -// messageVO.put("entityId", data.get("entityId")); -// messageVO.put("postId", data.get("postId")); -// -// int count = messageService.findNoticeCount(user.getId(), TOPIC_LIKE); -// messageVO.put("count", count); -// -// int unread = messageService.findNoticeUnReadCount(user.getId(), TOPIC_LIKE); -// messageVO.put("unread", unread); -// -// model.addAttribute("likeNotice", messageVO); -// } -// -// // 查询关注类通知 -// message = messageService.findLatestNotice(user.getId(), TOPIC_FOLLOW); -// if (message != null) { -// Map messageVO = new HashMap<>(); -// -// messageVO.put("message", message); -// -// String content = HtmlUtils.htmlUnescape(message.getContent()); -// Map data = JSONObject.parseObject(content, HashMap.class); -// -// messageVO.put("user", userService.findUserById((Integer) data.get("userId"))); -// messageVO.put("entityType", data.get("entityType")); -// messageVO.put("entityId", data.get("entityId")); -// -// int count = messageService.findNoticeCount(user.getId(), TOPIC_FOLLOW); -// messageVO.put("count", count); -// -// int unread = messageService.findNoticeUnReadCount(user.getId(), TOPIC_FOLLOW); -// messageVO.put("unread", unread); -// -// model.addAttribute("followNotice", messageVO); -// } -// -// // 查询未读消息数量 -// int letterUnreadCount = messageService.findLetterUnreadCount(user.getId(), null); -// model.addAttribute("letterUnreadCount", letterUnreadCount); -// int noticeUnreadCount = messageService.findNoticeUnReadCount(user.getId(), null); -// model.addAttribute("noticeUnreadCount", noticeUnreadCount); -// -// return "/site/notice"; -// } /** * 查询某个主题所包含的通知列表 @@ -436,41 +322,4 @@ public class MessageController extends BaseController implements CommunityConsta return new Result("success", Result.SUCCESS, noticeVoList); } -// public String getNoticeDetail(@PathVariable("topic") String topic, Page page, Model model) { -// User user = hostHolder.getUser(); -// -// page.setLimit(5); -// page.setPath("/notice/detail/" + topic); -// page.setRows(messageService.findNoticeCount(user.getId(), topic)); -// -// List noticeList = messageService.findNotices(user.getId(), topic,page.getOffset(), page.getLimit()); -// List> noticeVoList = new ArrayList<>(); -// if (noticeList != null) { -// for (Message notice : noticeList) { -// Map map = new HashMap<>(); -// // 通知 -// map.put("notice", notice); -// // 内容 -// String content = HtmlUtils.htmlUnescape(notice.getContent()); -// Map data = JSONObject.parseObject(content, HashMap.class); -// map.put("user", userService.findUserById((Integer) data.get("userId"))); -// map.put("entityType", data.get("entityType")); -// map.put("entityId", data.get("entityId")); -// map.put("postId", data.get("postId")); -// // 发送系统通知的作者 -// map.put("fromUser", userService.findUserById(notice.getFromId())); -// -// noticeVoList.add(map); -// } -// } -// model.addAttribute("notices", noticeVoList); -// -// // 设置已读 -// List ids = getUnreadLetterIds(noticeList); -// if (!ids.isEmpty()) { -// messageService.readMessage(ids); -// } -// -// return "/site/notice-detail"; -// } } diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index f23fe87..8284c32 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -224,8 +224,8 @@ public class UserController extends BaseController implements CommunityConstant if (list != null) { for (Comment comment : list) { Map map = new HashMap<>(); - map.put("comment", comment); // 显示评论/回复对应的文章信息 + map.put("comment", comment); if (comment.getEntityType() == ENTITY_TYPE_POST) { // 如果是对帖子的评论,则直接查询 target_id 即可 DiscussPost post = discussPostService.findDiscussPostById(comment.getEntityId()); @@ -234,6 +234,7 @@ public class UserController extends BaseController implements CommunityConstant else if (comment.getEntityType() == ENTITY_TYPE_COMMENT) { // 如过是对评论的回复,则先根据该回复的 target_id 查询评论的 id, 再根据该评论的 target_id 查询帖子的 id Comment targetComment = commentService.findCommentById(comment.getEntityId()); + map.put("parent", targetComment); DiscussPost post = discussPostService.findDiscussPostById(targetComment.getEntityId()); map.put("post", post); } diff --git a/src/main/java/com/greate/community/controller/interceptor/DataInterceptor.java b/src/main/java/com/greate/community/controller/interceptor/DataInterceptor.java index f2d0032..04adcd0 100644 --- a/src/main/java/com/greate/community/controller/interceptor/DataInterceptor.java +++ b/src/main/java/com/greate/community/controller/interceptor/DataInterceptor.java @@ -4,6 +4,7 @@ import com.greate.community.entity.User; import com.greate.community.service.DataService; import com.greate.community.util.HostHolder; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; @@ -16,20 +17,17 @@ public class DataInterceptor implements HandlerInterceptor { @Autowired private DataService dataService; - @Autowired - private HostHolder hostHolder; - @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 统计 UV - String ip = request.getRemoteHost(); - dataService.recordUV(ip); +// String ip = request.getRemoteHost(); +// dataService.recordUV(ip); // 统计 DAU - User user = hostHolder.getUser(); - if (user != null) { - dataService.recordDAU(user.getId()); - } +// User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); +// if (user != null) { +// dataService.recordDAU(user.getId()); +// } return true; } diff --git a/src/main/java/com/greate/community/controller/interceptor/MessageInterceptor.java b/src/main/java/com/greate/community/controller/interceptor/MessageInterceptor.java index d324728..596dac5 100644 --- a/src/main/java/com/greate/community/controller/interceptor/MessageInterceptor.java +++ b/src/main/java/com/greate/community/controller/interceptor/MessageInterceptor.java @@ -1,41 +1,39 @@ -package com.greate.community.controller.interceptor; - -import com.greate.community.entity.User; -import com.greate.community.service.MessageService; -import com.greate.community.util.HostHolder; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.springframework.web.servlet.HandlerInterceptor; -import org.springframework.web.servlet.ModelAndView; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -@Component -public class MessageInterceptor implements HandlerInterceptor { - - @Autowired - private HostHolder hostHolder; - - @Autowired - private MessageService messageService; - - /** - * Controller之后模板之前被调用 - * 获取未读私信/系统通知的数量 - * @param request - * @param response - * @param handler - * @param modelAndView - * @throws Exception - */ - @Override - public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { - User user = hostHolder.getUser(); - if (user != null && modelAndView != null) { - int letterUnreadCount = messageService.findLetterUnreadCount(user.getId(), null); - int noticeUnreadCount = messageService.findNoticeUnReadCount(user.getId(), null); - modelAndView.addObject("allUnreadCount", letterUnreadCount + noticeUnreadCount); - } - } -} +//package com.greate.community.controller.interceptor; +// +//import com.greate.community.entity.User; +//import com.greate.community.service.MessageService; +//import com.greate.community.util.HostHolder; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.security.core.context.SecurityContextHolder; +//import org.springframework.stereotype.Component; +//import org.springframework.web.servlet.HandlerInterceptor; +//import org.springframework.web.servlet.ModelAndView; +// +//import javax.servlet.http.HttpServletRequest; +//import javax.servlet.http.HttpServletResponse; +// +//@Component +//public class MessageInterceptor implements HandlerInterceptor { +// +// @Autowired +// private MessageService messageService; +// +// /** +// * Controller之后模板之前被调用 +// * 获取未读私信/系统通知的数量 +// * @param request +// * @param response +// * @param handler +// * @param modelAndView +// * @throws Exception +// */ +// @Override +// public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { +// User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); +// if (user != null && modelAndView != null) { +// int letterUnreadCount = messageService.findLetterUnreadCount(user.getId(), null); +// int noticeUnreadCount = messageService.findNoticeUnReadCount(user.getId(), null); +// modelAndView.addObject("allUnreadCount", letterUnreadCount + noticeUnreadCount); +// } +// } +//} diff --git a/src/main/java/com/greate/community/dao/ExpMapper.java b/src/main/java/com/greate/community/dao/ExpMapper.java new file mode 100644 index 0000000..e8d980b --- /dev/null +++ b/src/main/java/com/greate/community/dao/ExpMapper.java @@ -0,0 +1,35 @@ +package com.greate.community.dao; + +import com.greate.community.entity.Exp; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Date; +import java.util.List; + +@Mapper +public interface ExpMapper { + + /** + * 增加经验 + * @param exp + * @return + */ + int insertExp(Exp exp); + + /** + * 查询经验列表,type为空时查询全部类型 + * @param userId + * @param type + * @param start + * @param end + * @return + */ + List searchExpsByUserIdAndTypeAndDate(int userId, String type, String start, String end, int offset, int limit); + + /** + * 通过userId查询经验记录列表 + * @param userId + * @return + */ + List searchExpByUserId(int userId, int offset, int limit); +} diff --git a/src/main/java/com/greate/community/dao/UserMapper.java b/src/main/java/com/greate/community/dao/UserMapper.java index 923377b..6e1ae20 100644 --- a/src/main/java/com/greate/community/dao/UserMapper.java +++ b/src/main/java/com/greate/community/dao/UserMapper.java @@ -42,12 +42,7 @@ public interface UserMapper { int updatePassword(int id, String password); /** - * 修改经验值 + * 修改经验值和等级 */ - int updateExp(int id, int exp); - - /** - * 修改经验值 - */ - int updateRank(int id, int rank); + int updateExpAndLevel(int id, int exp, int level); } diff --git a/src/main/java/com/greate/community/entity/Exp.java b/src/main/java/com/greate/community/entity/Exp.java new file mode 100644 index 0000000..675e16a --- /dev/null +++ b/src/main/java/com/greate/community/entity/Exp.java @@ -0,0 +1,27 @@ +package com.greate.community.entity; + +import lombok.Data; + +import java.util.Date; + +/** + * 类名称:Exp + * 类描述:经验 + * 创建人:CSUpipixia + * 创建时间:2022/2/10 16:01 + * + * @version v1.0 + */ +@Data +public class Exp { + + int id; + // 经验值 + int count; + // 经验类型 + String type; + // 获得经验的用户id + int userId; + // 创建时间 + private Date createTime; +} diff --git a/src/main/java/com/greate/community/entity/Page.java b/src/main/java/com/greate/community/entity/Page.java index b704f1a..86311f1 100644 --- a/src/main/java/com/greate/community/entity/Page.java +++ b/src/main/java/com/greate/community/entity/Page.java @@ -1,6 +1,8 @@ package com.greate.community.entity; +import com.alibaba.fastjson.JSONObject; + /** * 封装分页相关的信息 */ @@ -12,6 +14,8 @@ public class Page { private int limit = 10; // 帖子总数(用于计算总页数) private int rows; + // 返回内容 + private JSONObject results; // 查询路径(用于复用分页链接, 因为我们不只在首页中有分页,其他界面也会有分页) private String path; diff --git a/src/main/java/com/greate/community/entity/User.java b/src/main/java/com/greate/community/entity/User.java index 8cea0b9..14ba618 100644 --- a/src/main/java/com/greate/community/entity/User.java +++ b/src/main/java/com/greate/community/entity/User.java @@ -1,11 +1,14 @@ package com.greate.community.entity; +import lombok.Data; + import java.util.Date; /** * 用户 * 对应数据库表 `user` */ +@Data public class User { private int id; @@ -14,153 +17,18 @@ public class User { private String salt; private String email; private int exp; - private int rank; + private int level; private int type; private int status; private String activationCode; private String headerUrl; - private Date createTime; private String studentCardUrl; private String studentCode; private String realName; private String institute; private String professionalClass; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getSalt() { - return salt; - } - - public void setSalt(String salt) { - this.salt = salt; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public int getExp() { - return exp; - } - - public void setExp(int exp) { - this.exp = exp; - } - - public int getRank() { - return rank; - } - - public void setRank(int rank) { - this.rank = rank; - } - - public int getType() { - return type; - } - - public void setType(int type) { - this.type = type; - } - - public int getStatus() { - return status; - } - - public void setStatus(int status) { - this.status = status; - } - - public String getActivationCode() { - return activationCode; - } - - public void setActivationCode(String activationCode) { - this.activationCode = activationCode; - } - - public String getHeaderUrl() { - return headerUrl; - } - - public void setHeaderUrl(String headerUrl) { - this.headerUrl = headerUrl; - } - - public String getStudentCardUrl() { - return studentCardUrl; - } - - public void setStudentCardUrl(String studentCardUrl) { - this.studentCardUrl = studentCardUrl; - } - - public String getStudentCode() { - return studentCode; - } - - public void setStudentCode(String studentCode) { - this.studentCode = studentCode; - } - - public String getRealName() { - return realName; - } - - public void setRealName(String realName) { - this.realName = realName; - } - - public String getInstitute() { - return institute; - } - - public void setInstitute(String institute) { - this.institute = institute; - } - - public String getProfessionalClass() { - return professionalClass; - } - - public void setProfessionalClass(String professionalClass) { - this.professionalClass = professionalClass; - } - - public Date getCreateTime() { - return createTime; - } - - public void setCreateTime(Date createTime) { - this.createTime = createTime; - } + private int auditStatus; + private Date createTime; @Override public String toString() { @@ -171,7 +39,7 @@ public class User { ", salt='" + salt + '\'' + ", email='" + email + '\'' + ", exp='" + exp + '\'' + - ", rank='" + rank + '\'' + + ", level='" + level + '\'' + ", type=" + type + ", status=" + status + ", activationCode='" + activationCode + '\'' + diff --git a/src/main/java/com/greate/community/event/EventConsumer.java b/src/main/java/com/greate/community/event/EventConsumer.java index 90104e3..79fd7b2 100644 --- a/src/main/java/com/greate/community/event/EventConsumer.java +++ b/src/main/java/com/greate/community/event/EventConsumer.java @@ -6,8 +6,10 @@ import com.greate.community.entity.Event; import com.greate.community.entity.Message; import com.greate.community.service.DiscussPostService; import com.greate.community.service.ElasticsearchService; +import com.greate.community.service.ExpService; import com.greate.community.service.MessageService; import com.greate.community.util.CommunityConstant; +import com.greate.community.util.ExpType; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,6 +20,7 @@ import org.springframework.stereotype.Component; import java.util.Date; import java.util.HashMap; import java.util.Map; +import java.util.Objects; /** * 事件消费者 @@ -30,6 +33,9 @@ public class EventConsumer implements CommunityConstant { @Autowired private MessageService messageService; + @Autowired + private ExpService expService; + @Autowired private DiscussPostService discussPostService; @@ -52,6 +58,14 @@ public class EventConsumer implements CommunityConstant { return ; } + // 增加经验 + if (Objects.equals(event.getTopic(), TOPIC_LIKE)) { + expService.handleGetExp(event.getUserId(), ExpType.EXP_LIKE.getName()); + } + if (Objects.equals(event.getTopic(), TOPIC_COMMNET)) { + expService.handleGetExp(event.getUserId(), ExpType.EXP_COMMENT.getName()); + } + // 发送系统通知 Message message = new Message(); message.setFromId(SYSTEM_USER_ID); @@ -89,6 +103,10 @@ public class EventConsumer implements CommunityConstant { return ; } + // 增加经验 + expService.handleGetExp(event.getUserId(), ExpType.EXP_PUBLISH.getName()); + + // 将帖子转存到elasticsearch DiscussPost post = discussPostService.findDiscussPostById(event.getEntityId()); elasticsearchService.saveDiscussPost(post); diff --git a/src/main/java/com/greate/community/service/DataService.java b/src/main/java/com/greate/community/service/DataService.java index 77e76c6..a2b47c2 100644 --- a/src/main/java/com/greate/community/service/DataService.java +++ b/src/main/java/com/greate/community/service/DataService.java @@ -28,6 +28,7 @@ public class DataService { /** * 将指定的 IP 计入当天的 UV + * * @param ip */ public void recordUV(String ip) { @@ -37,6 +38,7 @@ public class DataService { /** * 统计指定日期范围内的 UV + * * @param start * @param end * @return @@ -66,6 +68,7 @@ public class DataService { /** * 将指定的 IP 计入当天的 DAU + * * @param userId */ public void recordDAU(int userId) { @@ -75,6 +78,7 @@ public class DataService { /** * 统计指定日期范围内的 DAU + * * @param start * @param end * @return diff --git a/src/main/java/com/greate/community/service/DiscussPostService.java b/src/main/java/com/greate/community/service/DiscussPostService.java index a3e5048..b899df9 100644 --- a/src/main/java/com/greate/community/service/DiscussPostService.java +++ b/src/main/java/com/greate/community/service/DiscussPostService.java @@ -98,14 +98,14 @@ public class DiscussPostService { /** * 分页查询讨论帖信息 * - * @param userId 当传入的 userId = 0 时查找所有用户的帖子 - * 当传入的 userId != 0 时,查找该指定用户的帖子 - * @param offset 每页的起始索引 - * @param limit 每页显示多少条数据 - * @param orderMode 排行模式(若传入 1, 则按照热度来排序) + * @param userId 当传入的 userId = 0 时查找所有用户的帖子 + * 当传入的 userId != 0 时,查找该指定用户的帖子 + * @param offset 每页的起始索引 + * @param limit 每页显示多少条数据 + * @param orderMode 排行模式(若传入 1, 则按照热度来排序) * @return */ - public List findDiscussPosts (int userId, int offset, int limit, int orderMode) { + public List findDiscussPosts(int userId, int offset, int limit, int orderMode) { // 查询本地缓存(当查询的是所有用户的帖子并且按照热度排序时) if (userId == 0 && orderMode == 1) { return postListCache.get(offset + ":" + limit); @@ -117,11 +117,12 @@ public class DiscussPostService { /** * 查询讨论贴的个数 + * * @param userId 当传入的 userId = 0 时计算所有用户的帖子总数 * 当传入的 userId != 0 时计算该指定用户的帖子总数 * @return */ - public int findDiscussPostRows (int userId) { + public int findDiscussPostRows(int userId) { // 查询本地缓存(当查询的是所有用户的帖子总数时) if (userId == 0) { return postRowsCache.get(userId); @@ -133,6 +134,7 @@ public class DiscussPostService { /** * 添加帖子 + * * @param discussPost * @return */ @@ -154,6 +156,7 @@ public class DiscussPostService { /** * 根据 id 查询帖子 + * * @param id * @return */ @@ -163,7 +166,8 @@ public class DiscussPostService { /** * 修改帖子的评论数量 - * @param id 帖子 id + * + * @param id 帖子 id * @param commentCount * @return */ @@ -173,6 +177,7 @@ public class DiscussPostService { /** * 修改帖子类型:0-普通; 1-置顶; + * * @param id * @param type * @return @@ -183,6 +188,7 @@ public class DiscussPostService { /** * 修改帖子状态:0-正常; 1-精华; 2-拉黑; + * * @param id * @param status * @return @@ -193,6 +199,7 @@ public class DiscussPostService { /** * 修改帖子分数 + * * @param id * @param score * @return diff --git a/src/main/java/com/greate/community/service/ExpService.java b/src/main/java/com/greate/community/service/ExpService.java new file mode 100644 index 0000000..39a44c6 --- /dev/null +++ b/src/main/java/com/greate/community/service/ExpService.java @@ -0,0 +1,85 @@ +package com.greate.community.service; + +import com.greate.community.dao.ExpMapper; +import com.greate.community.entity.Exp; +import com.greate.community.entity.User; +import com.greate.community.util.ExpType; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +/** + * 类名称:ExpService + * 类描述:经验服务类 + * 创建人:CSUpipixia + * 创建时间:2022/2/10 21:31 + * + * @version v1.0 + */ +@Slf4j +@Service +public class ExpService { + + @Autowired + private ExpMapper expMapper; + + @Autowired + private UserService userService; + + private final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); + + public int handleGetExp(int userId, String type) { + int exp_count = 0; + + // 未实名无法获得经验值 + User user = userService.findUserById(userId); + if (user.getAuditStatus() != 2) { + return 0; + } + // 经验值不符合类型 + ExpType expType = ExpType.resolve(type); + if (expType == null) { + return 0; + } + + Calendar calendar = Calendar.getInstance(); + Date today = calendar.getTime(); + String start = formatter.format(today); + calendar.add(Calendar.DATE, 1); // 加一天 + String end = formatter.format(calendar.getTime()); + // 判断是否达到上限 + if (expMapper.searchExpsByUserIdAndTypeAndDate(userId, expType.getName(), start, end, 0, 100) + .stream().mapToInt(Exp::getCount).sum() + < expType.getLimit()) { + exp_count = expType.getCount(); + } + + // 得到了经验值,记录本次经验值,并更新用户exp和rank + if (exp_count > 0) { + // 记录本次经验值 + Exp exp = new Exp(); + exp.setCount(exp_count); + exp.setType(type); + exp.setUserId(userId); + exp.setCreateTime(today); + expMapper.insertExp(exp); + + // 更新用户exp和rank + int newExp = user.getExp() + exp_count; + int newLevel = ExpType.getLevel(newExp); + userService.updateExpAndLevel(userId, newExp, newLevel); + } + + return exp_count; + } + + public List getExpPageByUserId(int userId, int offset, int limit) { + return expMapper.searchExpByUserId(userId, offset, limit); + } + +} diff --git a/src/main/java/com/greate/community/service/FollowService.java b/src/main/java/com/greate/community/service/FollowService.java index 40ade2f..1f4582a 100644 --- a/src/main/java/com/greate/community/service/FollowService.java +++ b/src/main/java/com/greate/community/service/FollowService.java @@ -26,6 +26,7 @@ public class FollowService implements CommunityConstant { /** * 关注 + * * @param userId * @param entityType * @param entityId @@ -53,6 +54,7 @@ public class FollowService implements CommunityConstant { /** * 取消关注 + * * @param userId * @param entityType * @param entityId @@ -80,7 +82,8 @@ public class FollowService implements CommunityConstant { /** * 查询某个用户关注的实体的数量 - * @param userId 用户 id + * + * @param userId 用户 id * @param entityType 实体类型 * @return */ @@ -91,6 +94,7 @@ public class FollowService implements CommunityConstant { /** * 查询某个实体的粉丝数量 + * * @param entityType * @param entityId * @return @@ -102,6 +106,7 @@ public class FollowService implements CommunityConstant { /** * 判断当前用户是否已关注该实体 + * * @param userId * @param entityType * @param entityId @@ -109,11 +114,12 @@ public class FollowService implements CommunityConstant { */ public boolean hasFollowed(int userId, int entityType, int entityId) { String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); - return redisTemplate.opsForZSet().score(followeeKey, entityId) != null ; + return redisTemplate.opsForZSet().score(followeeKey, entityId) != null; } /** * 分页查询某个用户关注的人(偷个懒,此处没有做对其他实体的关注) + * * @param userId * @param offset * @param limit @@ -142,6 +148,7 @@ public class FollowService implements CommunityConstant { /** * 分页查询某个用户的粉丝(偷个懒,此处没有做对其他实体的粉丝) + * * @param userId * @param offset * @param limit diff --git a/src/main/java/com/greate/community/service/LikeService.java b/src/main/java/com/greate/community/service/LikeService.java index a10fe6f..0ce5e5f 100644 --- a/src/main/java/com/greate/community/service/LikeService.java +++ b/src/main/java/com/greate/community/service/LikeService.java @@ -19,7 +19,8 @@ public class LikeService { /** * 点赞 - * @param userId 点赞的用户 id + * + * @param userId 点赞的用户 id * @param entityType * @param entityId * @param entityUserId 被赞的帖子/评论的作者 id @@ -40,8 +41,7 @@ public class LikeService { // 如果用户已经点过赞,点第二次则取消赞 redisOperations.opsForSet().remove(entityLikeKey, userId); redisOperations.opsForValue().decrement(userLikeKey); - } - else { + } else { redisTemplate.opsForSet().add(entityLikeKey, userId); redisOperations.opsForValue().increment(userLikeKey); } @@ -53,6 +53,7 @@ public class LikeService { /** * 查询某实体被点赞的数量 + * * @param entityType * @param entityId * @return @@ -64,6 +65,7 @@ public class LikeService { /** * 查询某个用户对某个实体的点赞状态(是否已赞) + * * @param userId * @param entityType * @param entityId @@ -76,6 +78,7 @@ public class LikeService { /** * 查询某个用户获得赞数量 + * * @param userId * @return */ diff --git a/src/main/java/com/greate/community/service/UserService.java b/src/main/java/com/greate/community/service/UserService.java index 6725cf3..56221ff 100644 --- a/src/main/java/com/greate/community/service/UserService.java +++ b/src/main/java/com/greate/community/service/UserService.java @@ -7,7 +7,6 @@ import com.greate.community.util.*; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.core.GrantedAuthority; import org.springframework.stereotype.Service; @@ -32,20 +31,13 @@ public class UserService implements CommunityConstant { @Autowired private RedisTemplate redisTemplate; - // 网站域名 - @Value("${community.path.domain}") - private String domain; - - // 项目名(访问路径) - @Value("${server.servlet.context-path}") - private String contextPath; - /** * 根据 Id 查询用户 + * * @param id * @return */ - public User findUserById (int id) { + public User findUserById(int id) { // return userMapper.selectById(id); User user = getCache(id); // 优先从缓存中查询数据 if (user == null) { @@ -56,6 +48,7 @@ public class UserService implements CommunityConstant { /** * 根据 username 查询用户 + * * @param username * @return */ @@ -65,6 +58,7 @@ public class UserService implements CommunityConstant { /** * 用户注册 + * * @param user * @return Map 返回错误提示消息,如果返回的 map 为空,则说明注册成功 */ @@ -123,8 +117,9 @@ public class UserService implements CommunityConstant { /** * 激活用户 + * * @param userId 用户 id - * @param code 激活码 + * @param code 激活码 * @return */ public int activation(int userId, String code) { @@ -132,20 +127,19 @@ public class UserService implements CommunityConstant { if (user.getStatus() == 1) { // 用户已激活 return ACTIVATION_REPEAT; - } - else if (user.getActivationCode().equals(code)) { + } else if (user.getActivationCode().equals(code)) { // 修改用户状态为已激活 userMapper.updateStatus(userId, 1); clearCache(userId); // 用户信息变更,清除缓存中的旧数据 return ACTIVATION_SUCCESS; - } - else { + } else { return ACTIVATION_FAILURE; } } /** * 用户登录(为用户创建凭证) + * * @param username * @param password * @param expiredSeconds 多少秒后凭证过期 @@ -196,6 +190,7 @@ public class UserService implements CommunityConstant { String redisKey = RedisKeyUtil.getTicketKey(loginTicket.getTicket()); redisTemplate.opsForValue().set(redisKey, loginTicket); + map.put("userId", user.getId()); map.put("ticket", loginTicket.getTicket()); return map; @@ -203,6 +198,7 @@ public class UserService implements CommunityConstant { /** * 用户退出(将凭证状态设为无效) + * * @param ticket */ public void logout(String ticket) { @@ -216,6 +212,7 @@ public class UserService implements CommunityConstant { /** * 根据 ticket 查询 LoginTicket 信息 + * * @param ticket * @return */ @@ -227,6 +224,7 @@ public class UserService implements CommunityConstant { /** * 修改用户头像 + * * @param userId * @param headUrl * @return @@ -239,6 +237,7 @@ public class UserService implements CommunityConstant { /** * 修改用户密码(对新密码加盐加密存入数据库) + * * @param userId * @param newPassword 新密码 * @return @@ -253,6 +252,7 @@ public class UserService implements CommunityConstant { /** * 优先从缓存中取值 + * * @param userId * @return */ @@ -263,6 +263,7 @@ public class UserService implements CommunityConstant { /** * 缓存中没有该用户信息时,则将其存入缓存 + * * @param userId * @return */ @@ -275,6 +276,7 @@ public class UserService implements CommunityConstant { /** * 用户信息变更时清除对应缓存数据 + * * @param userId */ private void clearCache(int userId) { @@ -284,6 +286,7 @@ public class UserService implements CommunityConstant { /** * 获取某个用户的权限 + * * @param userId * @return */ @@ -309,8 +312,8 @@ public class UserService implements CommunityConstant { /** * 发送邮箱验证码 - * @param email 账户邮箱 * + * @param email 账户邮箱 * @return Map 返回错误提示消息,如果返回的 map 为空,则说明发送验证码成功 */ public Map doSendEmailCode4ResetPwd(String email) { @@ -332,8 +335,8 @@ public class UserService implements CommunityConstant { /** * 发送邮箱验证码 - * @param email 账户邮箱 * + * @param email 账户邮箱 * @return Map 返回错误提示消息,如果返回的 map 为空,则说明发送验证码成功 */ public Map doResetPwd(String email, String password) { @@ -357,5 +360,8 @@ public class UserService implements CommunityConstant { return map; } - + void updateExpAndLevel(int userId, int exp, int level) { + userMapper.updateExpAndLevel(userId, exp, level); + clearCache(userId); + } } diff --git a/src/main/java/com/greate/community/util/CommunityConstant.java b/src/main/java/com/greate/community/util/CommunityConstant.java index 00c3d69..ca1bdc8 100644 --- a/src/main/java/com/greate/community/util/CommunityConstant.java +++ b/src/main/java/com/greate/community/util/CommunityConstant.java @@ -46,7 +46,6 @@ public interface CommunityConstant { // Kafka 主题:删帖 String TOPIC_DELETE = "delete"; - // 系统用户的 id int SYSTEM_USER_ID = 1; @@ -68,4 +67,5 @@ public interface CommunityConstant { // 对象存储类型:学生证 String COS_TYPE_STUDENT_CARD = "studentCard"; + } diff --git a/src/main/java/com/greate/community/util/ExpType.java b/src/main/java/com/greate/community/util/ExpType.java new file mode 100644 index 0000000..c471704 --- /dev/null +++ b/src/main/java/com/greate/community/util/ExpType.java @@ -0,0 +1,116 @@ +package com.greate.community.util; + +import org.springframework.lang.Nullable; + +import java.util.Objects; + +public enum ExpType { + + EXP_LOGIN(5, LoopModes.DAY, 5, "login", "每日首次登录"), + EXP_BROWSE(5, LoopModes.DAY, 5, "browse", "每日首次浏览"), + EXP_SHARE(5, LoopModes.DAY, 5, "share", "每日首次分享"), + EXP_LIKE(5, LoopModes.DAY, 25, "like", "点赞帖子"), + EXP_COMMENT(5, LoopModes.DAY, 25, "comment", "发表评论"), + EXP_PUBLISH(10, LoopModes.DAY, 30, "publish", "发表帖子"); + + static int ONE_LEVEL_OF_EXP = 0; // 通过实名认证 + static int TWO_LEVEL_OF_EXP = 200; + static int THREE_LEVEL_OF_EXP = 1000; // 10天 + static int FOUR_LEVEL_OF_EXP = 2333; // 1个月 + static int FIVE_LEVEL_OF_EXP = 6666; // 2个月 + static int SIX_LEVEL_OF_EXP = 16666; // 半年 + + private static final ExpType[] TYPES = values(); + private final int count; + private final ExpType.LoopModes loopMode; + private final int limit; + private final String name; + private final String content; + + private ExpType(int count, ExpType.LoopModes loopMode, int limit, String name, String content) { + this.count = count; + this.loopMode = loopMode; + this.limit = limit; + this.name = name; + this.content = content; + } + + public int getCount() { + return this.count; + } + + public ExpType.LoopModes getLoopMode() { + return this.loopMode; + } + + public int getLimit() { + return this.limit; + } + + public String getName() { + return this.name; + } + + public String getContent() { + return this.content; + } + + /** + * 根据名称遍历查找经验类型 + * + * @param expTypeName + * @return + */ + @Nullable + public static ExpType resolve(String expTypeName) { + for (ExpType expType : TYPES) { + if (Objects.equals(expType.name, expTypeName)) { + return expType; + } + } + + return null; + } + + /** + * 根据经验值判断等级 + * + * @param totalExp + * @return + */ + public static int getLevel(int totalExp) { + if (totalExp >= SIX_LEVEL_OF_EXP) { + return 6; + } else if (totalExp >= FIVE_LEVEL_OF_EXP) { + return 5; + } else if (totalExp >= FOUR_LEVEL_OF_EXP) { + return 4; + } else if (totalExp >= THREE_LEVEL_OF_EXP) { + return 3; + } else if (totalExp >= TWO_LEVEL_OF_EXP) { + return 2; + } else if (totalExp >= ONE_LEVEL_OF_EXP) { + return 1; + } else { + return 0; + } + } + + public static enum LoopModes { + + ONLY_ONE("only_one"), + DAY("day"), + MONTH("month"), + YEAR("year"); + + private final String value; + + private LoopModes(String value) { + this.value = value; + } + + public String value() { + return this.value; + } + } +} diff --git a/src/main/resources/mapper/exp-mapper.xml b/src/main/resources/mapper/exp-mapper.xml new file mode 100644 index 0000000..49f8665 --- /dev/null +++ b/src/main/resources/mapper/exp-mapper.xml @@ -0,0 +1,43 @@ + + + + + + + count, type, user_id, create_time + + + + id, count, type, user_id, create_time + + + + insert into exp () + values(#{count}, #{type}, #{userId}, #{createTime}) + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/user-mapper.xml b/src/main/resources/mapper/user-mapper.xml index c8bf51e..1b72a14 100644 --- a/src/main/resources/mapper/user-mapper.xml +++ b/src/main/resources/mapper/user-mapper.xml @@ -9,7 +9,7 @@ - id, username, password, salt, email, exp, rank, type, status, activation_code, header_url, create_time + id, username, password, salt, email, exp, level, type, status, activation_code, header_url, audit_status, create_time @@ -55,13 +55,8 @@ - - update user set exp = #{exp} where id = #{id} - - - - - update user set rank = #{rank} where id = #{id} + + update user set exp = #{exp}, level = #{level} where id = #{id} \ No newline at end of file diff --git a/src/test/java/com/greate/community/ExpServiceTest.java b/src/test/java/com/greate/community/ExpServiceTest.java new file mode 100644 index 0000000..7d3c023 --- /dev/null +++ b/src/test/java/com/greate/community/ExpServiceTest.java @@ -0,0 +1,29 @@ +package com.greate.community; + +import com.greate.community.service.ExpService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * 类名称:ExpServiceTest + * 类描述:TODO + * 创建人:CSUpipixia + * 创建时间:2022/2/11 21:53 + * + * @version v1.0 + */ +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes=CommunityApplication.class) +public class ExpServiceTest { + + @Autowired + private ExpService expService; + + @Test + public void handleGetExp() { + expService.handleGetExp(101, "login"); + } +} -- Gitee From 8baa0fe6e42a7a415c6952d749b11c3b1d4b3432 Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Fri, 11 Feb 2022 22:32:18 +0800 Subject: [PATCH 018/125] fix package error --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index b940a96..eca76dc 100644 --- a/pom.xml +++ b/pom.xml @@ -199,6 +199,12 @@ spring-boot-maven-plugin + + org.apache.maven.plugins + maven-resources-plugin + 2.6 + + org.apache.maven.plugins -- Gitee From ddd210d4d86eb79d9cc25b5e3948750164937734 Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Sat, 12 Feb 2022 16:43:07 +0800 Subject: [PATCH 019/125] =?UTF-8?q?=E5=AE=9E=E5=90=8D=E8=AE=A4=E8=AF=81?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E4=B8=8E=E5=BE=AE=E4=BF=A1=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/config/SecurityConfig.java | 4 +- .../community/controller/AuditController.java | 125 +++++ .../community/controller/LoginController.java | 10 +- .../community/controller/UserController.java | 17 + .../com/greate/community/dao/UserMapper.java | 44 ++ .../com/greate/community/entity/User.java | 10 + .../greate/community/service/UserService.java | 60 +++ src/main/resources/mapper/user-mapper.xml | 36 ++ src/main/resources/templates/index.html | 460 +++++++++--------- 9 files changed, 533 insertions(+), 233 deletions(-) create mode 100644 src/main/java/com/greate/community/controller/AuditController.java diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index f6b2b16..1178072 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -178,6 +178,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm "/user/get", "/user/setting", "/user/upload", + "user/studentCard/url", "/discuss/add", "/discuss/publish", "/comment/add/**", @@ -205,7 +206,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm .antMatchers( "/discuss/delete", "/discuss/delete/", - "/data/**" + "/data/**", + "/admin/**" ) .hasAnyAuthority( AUTHORITY_ADMIN diff --git a/src/main/java/com/greate/community/controller/AuditController.java b/src/main/java/com/greate/community/controller/AuditController.java new file mode 100644 index 0000000..d705e24 --- /dev/null +++ b/src/main/java/com/greate/community/controller/AuditController.java @@ -0,0 +1,125 @@ +package com.greate.community.controller; + +import com.greate.community.entity.Page; +import com.greate.community.entity.Result; +import com.greate.community.entity.User; +import com.greate.community.service.UserService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 用户身份实名认证审核模块 + * @author xzx + * @date 2022/2/9 21:41 + */ +@RestController +public class AuditController { + @Autowired + private UserService userService; + + /** + * 通过或驳回实名信息 + */ + @PostMapping("/admin/audit") + public Result audit(@RequestBody HashMap map){ + int userId = map.get("userId"); + int auditStatus = map.get("auditStatus"); + + if (auditStatus == 2){ + userService.updateAuditStatus(userId, auditStatus); + return new Result("success", Result.SUCCESS, "用户id--"+userId+"--审核通过成功"); + } + else if (auditStatus == 3){ + userService.updateAuditStatus(userId, auditStatus); + return new Result("success", Result.SUCCESS, "用户id--"+userId+"--审核驳回成功"); + } + else { + return new Result("fail", "1", "the request parameters are invalid"); + } + } + + /** + * 查看用户实名列表简略信息 + */ + @GetMapping("/admin/user/brief") + public Result getBriefUsers(Page page, int auditStatus) { + if(auditStatus == 0 || auditStatus == 1 || auditStatus == 2 || auditStatus == 3){ + page.setPath("/admin/user/brief"); + page.setRows(userService.findRealNameRows(auditStatus)); + + List briefUserList = userService.findRealNameList(auditStatus, page.getOffset(), page.getLimit(),0); + List> resultBriefUserList = new ArrayList<>(); + + for(User user : briefUserList){ + HashMap resultBriefUser = new HashMap<>(); + resultBriefUser.put("id", user.getId()); + resultBriefUser.put("username", user.getUsername()); + resultBriefUser.put("email", user.getEmail()); + resultBriefUserList.add(resultBriefUser); + } + + return new Result("success", Result.SUCCESS, resultBriefUserList); + } + else { + return new Result("fail", "1", "the request parameters are invalid"); + } + } + + /** + * 查看用户实名列表详细信息 + */ + @GetMapping("/admin/user/detailed") + public Result getDetailedUsers(Page page, int auditStatus) { + if(auditStatus == 0 || auditStatus == 1 || auditStatus == 2 || auditStatus == 3){ + page.setPath("/admin/user/detailed"); + page.setRows(userService.findRealNameRows(auditStatus)); + + List detailedUserList = userService.findRealNameList(auditStatus, page.getOffset(), page.getLimit(),1); + List> resultDetailedUserList = new ArrayList<>(); + + for(User user : detailedUserList){ + HashMap resultDetailedUser = new HashMap<>(); + resultDetailedUser.put("id", user.getId()); + resultDetailedUser.put("username", user.getUsername()); + resultDetailedUser.put("email", user.getEmail()); + resultDetailedUser.put("student_card_url", user.getStudentCardUrl()); + resultDetailedUser.put("student_code", user.getStudentCode()); + resultDetailedUser.put("real_name", user.getRealName()); + resultDetailedUser.put("institute", user.getInstitute()); + resultDetailedUser.put("professional_class", user.getProfessionalClass()); + resultDetailedUserList.add(resultDetailedUser); + } + + return new Result("success", Result.SUCCESS, resultDetailedUserList); + } + else { + return new Result("fail", "1", "the request parameters are invalid"); + } + } + + /** + * 依据userId查询用户实名详细信息 + */ + @GetMapping("/admin/user/detailedById") + public Result getDetailedUserById(int userId) { + User user = userService.findRealNameUserById(userId); + HashMap resultDetailedUser = new HashMap<>(); + resultDetailedUser.put("id", user.getId()); + resultDetailedUser.put("username", user.getUsername()); + resultDetailedUser.put("email", user.getEmail()); + resultDetailedUser.put("student_card_url", user.getStudentCardUrl()); + resultDetailedUser.put("student_code", user.getStudentCode()); + resultDetailedUser.put("real_name", user.getRealName()); + resultDetailedUser.put("institute", user.getInstitute()); + resultDetailedUser.put("professional_class", user.getProfessionalClass()); + + return new Result("success", Result.SUCCESS, resultDetailedUser); + } +} diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index 13d8afe..6f76827 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -24,6 +24,8 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -180,7 +182,7 @@ public class LoginController extends BaseController implements CommunityConstant * @return */ @GetMapping("/wechat/login") - public Result wechatLogin(@AuthenticationPrincipal UserWeChat userWeChat) { + public void wechatLogin(@AuthenticationPrincipal UserWeChat userWeChat, HttpServletResponse response) throws IOException { String username = userWeChat.getNickName();//微信昵称 String password = CommunityUtil.generateUUID();//随机密码,不能随便让人破解 String headerUrl = userWeChat.getHeadimgurl();//微信头像地址 @@ -226,8 +228,12 @@ public class LoginController extends BaseController implements CommunityConstant redisTemplate.opsForValue().set(redisKey, loginTicket); String ticket = loginTicket.getTicket(); - return new Result("success", Result.SUCCESS, ticket); /**模拟普通登录过程**/ + + //return new Result("success", Result.SUCCESS, ticket); + + //todo 带上ticket重定向到前端 + response.sendRedirect("http://119.91.149.96:8080/?ticket="+ticket); } /** diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 30ef73d..81d45fb 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -244,6 +244,23 @@ public class UserController extends BaseController implements CommunityConstant jsonObject.put("comments", comments); return new Result("success", Result.SUCCESS, jsonObject); + } + + /** + * 更新用户实名信息 + * @param user + * @return + */ + @PostMapping("/realname") + public Result updateStudentCard(@RequestBody User user) { + if (user == null){ + return new Result("fail", "1", "the request parameters are invalid"); + } + + int userId = getUser().getId(); + user.setId(userId); + userService.updateRealNameInfo(user); + return new Result("success", Result.SUCCESS, "用户实名信息更新成功"); } } diff --git a/src/main/java/com/greate/community/dao/UserMapper.java b/src/main/java/com/greate/community/dao/UserMapper.java index 923377b..9b93e84 100644 --- a/src/main/java/com/greate/community/dao/UserMapper.java +++ b/src/main/java/com/greate/community/dao/UserMapper.java @@ -2,6 +2,9 @@ package com.greate.community.dao; import com.greate.community.entity.User; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; @Mapper public interface UserMapper { @@ -50,4 +53,45 @@ public interface UserMapper { * 修改经验值 */ int updateRank(int id, int rank); + + /** + * 修改用户实名信息审核状态 + */ + int updateAuditStatus(int userId, int auditStatus); + + /** + * 分页查询实名信息(已激活的用户) + * + * @param auditStatus 当传入的 auditStatus = 0 时,查找所有 未上传学生证图片 的用户信息 + * 当传入的 auditStatus = 1 时,查找所有 未审核 的用户信息 + * 当传入的 auditStatus = 2 时,查找所有 审核通过 的用户信息 + * 当传入的 auditStatus = 3 时,查找所有 审核驳回 的用户信息 + * @param offset 每页的起始索引 + * @param limit 每页显示多少条数据 + * @param detailed 是否查询实名详细信息,0-简略信息,1-详细信息 + * @return + */ + List selectRealNameList(int auditStatus, int offset, int limit, int detailed); + + /** + * 查询实名用户个数 + * @param auditStatus 当传入的 auditStatus = 0 时,查找所有 未上传学生证图片 的用户信息 + * 当传入的 auditStatus = 1 时,查找所有 未审核 的用户信息 + * 当传入的 auditStatus = 2 时,查找所有 审核通过 的用户信息 + * 当传入的 auditStatus = 3 时,查找所有 审核驳回 的用户信息 + * @return + */ + int selectRealNameRows(int auditStatus); + + /** + * 依据userId查询用户实名详细信息 + * @param id 用户id + * @return + */ + User selectRealNameUserById(int id); + + /** + * 更新用户实名信息 + */ + int updateRealNameInfo(User user); } diff --git a/src/main/java/com/greate/community/entity/User.java b/src/main/java/com/greate/community/entity/User.java index 8cea0b9..1f22c6d 100644 --- a/src/main/java/com/greate/community/entity/User.java +++ b/src/main/java/com/greate/community/entity/User.java @@ -25,6 +25,7 @@ public class User { private String realName; private String institute; private String professionalClass; + private int auditStatus; public int getId() { return id; @@ -162,6 +163,14 @@ public class User { this.createTime = createTime; } + public int getAuditStatus() { + return auditStatus; + } + + public void setAuditStatus(int auditStatus) { + this.auditStatus = auditStatus; + } + @Override public String toString() { return "User{" + @@ -182,6 +191,7 @@ public class User { ", institute=" + institute + ", professionalClass=" + professionalClass + ", createTime=" + createTime + + ", auditStatus=" + auditStatus + '}'; } diff --git a/src/main/java/com/greate/community/service/UserService.java b/src/main/java/com/greate/community/service/UserService.java index ccd183e..578bd25 100644 --- a/src/main/java/com/greate/community/service/UserService.java +++ b/src/main/java/com/greate/community/service/UserService.java @@ -1,6 +1,7 @@ package com.greate.community.service; import com.greate.community.dao.UserMapper; +import com.greate.community.entity.DiscussPost; import com.greate.community.entity.LoginTicket; import com.greate.community.entity.User; import com.greate.community.util.*; @@ -375,4 +376,63 @@ public class UserService implements CommunityConstant { } + /** + * 修改用户实名信息审核状态,保存用户实名信息 + * @param userId + * @param auditStatus + * @return + */ + public int updateAuditStatus(int userId, int auditStatus) { + return userMapper.updateAuditStatus(userId, auditStatus); + } + + /** + * 分页查询实名信息(已激活的用户) + * + * @param auditStatus 当传入的 auditStatus = 0 时,查找所有 未上传学生证图片 的用户信息 + * 当传入的 auditStatus = 1 时,查找所有 未审核 的用户信息 + * 当传入的 auditStatus = 2 时,查找所有 审核通过 的用户信息 + * 当传入的 auditStatus = 3 时,查找所有 审核驳回 的用户信息 + * @param offset 每页的起始索引 + * @param limit 每页显示多少条数据 + * @param detailed 是否查询实名详细信息,0-简略信息,1-详细信息 + * @return + */ + public List findRealNameList (int auditStatus, int offset, int limit, int detailed) { + return userMapper.selectRealNameList(auditStatus, offset, limit, detailed); + } + + /** + * 查询实名用户个数 + * @param auditStatus 当传入的 auditStatus = 0 时,查找所有 未上传学生证图片 的用户信息 + * 当传入的 auditStatus = 1 时,查找所有 未审核 的用户信息 + * 当传入的 auditStatus = 2 时,查找所有 审核通过 的用户信息 + * 当传入的 auditStatus = 3 时,查找所有 审核驳回 的用户信息 + * @return + */ + public int findRealNameRows (int auditStatus) { + return userMapper.selectRealNameRows(auditStatus); + } + + /** + * 依据userId查询用户实名详细信息 + * @param userId 用户id + * @return + */ + public User findRealNameUserById (int userId) { + return userMapper.selectRealNameUserById(userId); + } + + /** + * 更新用户实名信息 + * @param user + * @return + */ + public int updateRealNameInfo(User user) { + // return userMapper.updateHeader(userId, headUrl); + int rows = userMapper.updateRealNameInfo(user); + //clearCache(userId); + return rows; + } + } diff --git a/src/main/resources/mapper/user-mapper.xml b/src/main/resources/mapper/user-mapper.xml index c8bf51e..522b734 100644 --- a/src/main/resources/mapper/user-mapper.xml +++ b/src/main/resources/mapper/user-mapper.xml @@ -64,4 +64,40 @@ update user set rank = #{rank} where id = #{id} + + + update user set audit_status = #{auditStatus} where id = #{id} + + + + + + + + + + + + + + update user set student_card_url = #{studentCardUrl} , student_code = #{studentCode}, real_name = #{realName}, institute = #{institute}, professional_class = #{professionalClass}, audit_status = 1 where id = #{id} + \ No newline at end of file diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 94809fa..42a8e1f 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -1,230 +1,230 @@ - - - - - - - - - - Echo - 首页 - - -

- -
-
- - -
-
- - -
-
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
  • - - 用户头像 - -
    -
    - - - -
    -
    - 发布于 -
      -
    • -
    • |
    • -
    • 回帖
    • -
    -
    -
    -
  • -
- - -
-
- - - -
-
-
- -
- -
- -
-
-
- -
-
-
- -
- -
-
-
-
-
- - - - - - - - + + + + + + + + + + Echo - 首页 + + +
+ +
+
+ + +
+
+ + +
+
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
  • + + 用户头像 + +
    +
    + + + +
    +
    + 发布于 +
      +
    • +
    • |
    • +
    • 回帖
    • +
    +
    +
    +
  • +
+ + +
+
+ + + +
+
+
+ +
+ +
+ +
+
+
+ +
+
+
+ +
+ +
+
+
+
+
+ + + + + + + + -- Gitee From eabe2e8de08e8645cce0607bf6296360479d65ea Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Sat, 12 Feb 2022 23:42:25 +0800 Subject: [PATCH 020/125] =?UTF-8?q?=E5=B8=96=E5=AD=90=E9=85=8D=E5=9B=BEurl?= =?UTF-8?q?=E4=B8=8A=E4=BC=A0-pic=5Furls=E8=A7=A3=E6=9E=90=E6=88=90json?= =?UTF-8?q?=E6=95=B0=E7=BB=84=E8=BF=94=E5=9B=9E=E5=89=8D=E7=AB=AF-?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=A4=B4=E5=83=8Furl=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/config/SecurityConfig.java | 3 +- .../controller/DiscussPostController.java | 52 +++--- .../community/controller/IndexController.java | 7 +- .../controller/SearchController.java | 14 +- .../community/controller/UserController.java | 35 +++- .../com/greate/community/dao/UserMapper.java | 2 +- .../greate/community/entity/DiscussPost.java | 14 ++ .../community/service/DiscussPostService.java | 22 +++ .../resources/mapper/discusspost-mapper.xml | 164 +++++++++--------- 9 files changed, 193 insertions(+), 120 deletions(-) diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index ed4d44f..b01cf77 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -70,7 +70,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm "/user/get", "/user/setting", "/user/upload", - "user/studentCard/url", + "/user/studentCard/url", + "/user/updateHeader", "/discuss/add", "/discuss/publish", "/comment/add/**", diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index 7457eb9..708a83b 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -1,21 +1,18 @@ package com.greate.community.controller; -import com.greate.community.dao.ExpMapper; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; import com.greate.community.entity.*; import com.greate.community.event.EventProducer; import com.greate.community.service.*; import com.greate.community.util.*; -import org.checkerframework.checker.units.qual.A; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; import org.springframework.web.util.HtmlUtils; -import java.io.File; import java.util.*; /** @@ -46,23 +43,28 @@ public class DiscussPostController extends BaseController implements CommunityCo @Autowired private RedisTemplate redisTemplate; - // 网站域名 - @Value("${community.path.domain}") - private String domain; - - // 项目名(访问路径) - @Value("${server.servlet.context-path}") - private String contextPath; - /** * 添加帖子(发帖) * @return * */ @PostMapping("/add") - public Result addDiscussPost(@RequestBody HashMap map) { - String title = map.get("title"); - String content = map.get("content"); + public Result addDiscussPost(@RequestBody HashMap map) { + String title = (String) map.get("title"); + String content = (String) map.get("content"); + ArrayList picUrlList = (ArrayList) map.get("picUrls"); + + String picUrls = ""; + int picNum = 0; + + if(picUrlList != null){ + for(String picUrl : picUrlList){ + picUrls = picUrls + picUrl + ","; + picNum++; + } + //删除最后一个 , + picUrls = picUrls.substring(0, picUrls.length() - 1); + } User user = getUser(); if (user == null) { @@ -73,6 +75,7 @@ public class DiscussPostController extends BaseController implements CommunityCo discussPost.setUserId(user.getId()); discussPost.setTitle(title); discussPost.setContent(content); + discussPost.setPicUrls(picUrls); discussPost.setCreateTime(new Date()); discussPostService.addDiscussPost(discussPost); @@ -89,7 +92,7 @@ public class DiscussPostController extends BaseController implements CommunityCo String redisKey = RedisKeyUtil.getPostScoreKey(); redisTemplate.opsForSet().add(redisKey, discussPost.getId()); - return new Result("success","200","发布成功"); + return new Result("success","200","帖子发布成功," + "配图 " + picNum + " 张"); } /** @@ -107,27 +110,24 @@ public class DiscussPostController extends BaseController implements CommunityCo DiscussPost discussPost = discussPostService.findDiscussPostById(discussPostId); String content = HtmlUtils.htmlUnescape(discussPost.getContent()); // 内容反转义,不然 markDown 格式无法显示 discussPost.setContent(content); -// model.addAttribute("post", discussPost); - resultMap.put("post",discussPost); + + //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 + resultMap.put("post", discussPostService.toDiscussPostJsonObject(discussPost)); // 作者 User user = userService.findUserById(discussPost.getUserId()); -// model.addAttribute("user", user); resultMap.put("user",user); // 点赞数量 long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, discussPostId); -// model.addAttribute("likeCount", likeCount); resultMap.put("likeCount",likeCount); // 当前登录用户的点赞状态 int likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus(getUser().getId(), ENTITY_TYPE_POST, discussPostId); -// model.addAttribute("likeStatus", likeStatus); resultMap.put("likeStatus",likeStatus); // 评论分页信息 -// page.setLimit(5);//前端注入 page.setPath("/discuss/detail/" + discussPostId); page.setRows(discussPost.getCommentCount()); @@ -211,7 +211,6 @@ public class DiscussPostController extends BaseController implements CommunityCo .setEntityId(id); eventProducer.fireEvent(event); -// return CommunityUtil.getJSONString(0); return new Result("success",Result.SUCCESS,""); } @@ -238,7 +237,6 @@ public class DiscussPostController extends BaseController implements CommunityCo String redisKey = RedisKeyUtil.getPostScoreKey(); redisTemplate.opsForSet().add(redisKey, id); -// return CommunityUtil.getJSONString(0); return new Result("success",Result.SUCCESS,""); } @@ -261,9 +259,7 @@ public class DiscussPostController extends BaseController implements CommunityCo .setEntityId(id); eventProducer.fireEvent(event); -// return CommunityUtil.getJSONString(0); return new Result("success",Result.SUCCESS,"删除成功"); } - } diff --git a/src/main/java/com/greate/community/controller/IndexController.java b/src/main/java/com/greate/community/controller/IndexController.java index 1922d34..d2ed963 100644 --- a/src/main/java/com/greate/community/controller/IndexController.java +++ b/src/main/java/com/greate/community/controller/IndexController.java @@ -1,5 +1,7 @@ package com.greate.community.controller; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; import com.greate.community.entity.DiscussPost; import com.greate.community.entity.Page; import com.greate.community.entity.Result; @@ -55,7 +57,10 @@ public class IndexController implements CommunityConstant { if (list != null) { for (DiscussPost post : list) { Map map = new HashMap<>(); - map.put("post", post); + + //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 + map.put("post", discussPostService.toDiscussPostJsonObject(post)); + User user = userService.findUserById(post.getUserId()); map.put("user", user); long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId()); diff --git a/src/main/java/com/greate/community/controller/SearchController.java b/src/main/java/com/greate/community/controller/SearchController.java index 8b1adbd..3ad35da 100644 --- a/src/main/java/com/greate/community/controller/SearchController.java +++ b/src/main/java/com/greate/community/controller/SearchController.java @@ -1,9 +1,11 @@ package com.greate.community.controller; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.greate.community.entity.DiscussPost; import com.greate.community.entity.Page; import com.greate.community.entity.Result; +import com.greate.community.service.DiscussPostService; import com.greate.community.service.ElasticsearchService; import com.greate.community.service.LikeService; import com.greate.community.service.UserService; @@ -30,15 +32,18 @@ public class SearchController extends BaseController implements CommunityConstan @Autowired private LikeService likeService; + @Autowired + private DiscussPostService discussPostService; + /** * 搜索 - * search?keword=xxx + * search?keword=xxx¤t=2&limit=2 * @param keyword 关键词 * @param page * @return */ @PostMapping("/search") - public Result search(String keyword, @RequestBody Page page) { + public Result search(String keyword, Page page) { JSONObject jsonObject = new JSONObject(); // 搜索帖子 (Spring 提供的 Page 当前页码从 0 开始计数) org.springframework.data.domain.Page searchResult = @@ -49,7 +54,10 @@ public class SearchController extends BaseController implements CommunityConstan for (DiscussPost post : searchResult) { Map map = new HashMap<>(); // 帖子 - map.put("post", post); +// map.put("post", post); + //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 + map.put("post", discussPostService.toDiscussPostJsonObject(post)); + // 作者 map.put("user", userService.findUserById(post.getUserId())); // 点赞数量 diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index e5c227d..448f5a3 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -1,5 +1,6 @@ package com.greate.community.controller; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.greate.community.entity.*; import com.greate.community.service.*; @@ -182,7 +183,11 @@ public class UserController extends BaseController implements CommunityConstant if (list != null) { for (DiscussPost post : list) { Map map = new HashMap<>(); - map.put("post", post); +// map.put("post", post); + + //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 + map.put("post", discussPostService.toDiscussPostJsonObject(post)); + long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId()); map.put("likeCount", likeCount); @@ -229,14 +234,18 @@ public class UserController extends BaseController implements CommunityConstant if (comment.getEntityType() == ENTITY_TYPE_POST) { // 如果是对帖子的评论,则直接查询 target_id 即可 DiscussPost post = discussPostService.findDiscussPostById(comment.getEntityId()); - map.put("post", post); + //map.put("post", post); + //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 + map.put("post", discussPostService.toDiscussPostJsonObject(post)); } else if (comment.getEntityType() == ENTITY_TYPE_COMMENT) { // 如过是对评论的回复,则先根据该回复的 target_id 查询评论的 id, 再根据该评论的 target_id 查询帖子的 id Comment targetComment = commentService.findCommentById(comment.getEntityId()); map.put("parent", targetComment); DiscussPost post = discussPostService.findDiscussPostById(targetComment.getEntityId()); - map.put("post", post); + //map.put("post", post); + //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 + map.put("post", discussPostService.toDiscussPostJsonObject(post)); } comments.add(map); @@ -253,7 +262,7 @@ public class UserController extends BaseController implements CommunityConstant * @return */ @PostMapping("/realname") - public Result updateStudentCard(@RequestBody User user) { + public Result updateRealNameInfo(@RequestBody User user) { if (user == null){ return new Result("fail", "1", "the request parameters are invalid"); } @@ -264,4 +273,22 @@ public class UserController extends BaseController implements CommunityConstant userService.updateRealNameInfo(user); return new Result("success", Result.SUCCESS, "用户实名信息更新成功"); } + + /** + * 更新用户头像 + * @param jsonObject + * @return + */ + @PostMapping("/updateHeader") + public Result updateHeader(@RequestBody JSONObject jsonObject) { + String headerUrl = jsonObject.getString("headerUrl"); + + if (headerUrl == null){ + return new Result("fail", "1", "the request parameters are invalid"); + } + + int userId = getUser().getId(); + userService.updateHeader(userId, headerUrl); + return new Result("success", Result.SUCCESS, "用户头像更新成功"); + } } diff --git a/src/main/java/com/greate/community/dao/UserMapper.java b/src/main/java/com/greate/community/dao/UserMapper.java index 0fb1e55..62ceb0f 100644 --- a/src/main/java/com/greate/community/dao/UserMapper.java +++ b/src/main/java/com/greate/community/dao/UserMapper.java @@ -52,7 +52,7 @@ public interface UserMapper { /** * 修改用户实名信息审核状态 */ - int updateAuditStatus(int userId, int auditStatus); + int updateAuditStatus(int id, int auditStatus); /** * 分页查询实名信息(已激活的用户) diff --git a/src/main/java/com/greate/community/entity/DiscussPost.java b/src/main/java/com/greate/community/entity/DiscussPost.java index 85c03c0..c284dc9 100644 --- a/src/main/java/com/greate/community/entity/DiscussPost.java +++ b/src/main/java/com/greate/community/entity/DiscussPost.java @@ -1,5 +1,7 @@ package com.greate.community.entity; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; @@ -26,6 +28,9 @@ public class DiscussPost { @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart") private String content; + @Field(type = FieldType.Text) + private String picUrls; + @Field(type = FieldType.Integer) private int type; @@ -73,6 +78,14 @@ public class DiscussPost { this.content = content; } + public String getPicUrls() { + return picUrls; + } + + public void setPicUrls(String picUrls) { + this.picUrls = picUrls; + } + public int getType() { return type; } @@ -120,6 +133,7 @@ public class DiscussPost { ", userId=" + userId + ", title='" + title + '\'' + ", content='" + content + '\'' + + ", picUrls ='" + picUrls + '\'' + ", type=" + type + ", status=" + status + ", createTime=" + createTime + diff --git a/src/main/java/com/greate/community/service/DiscussPostService.java b/src/main/java/com/greate/community/service/DiscussPostService.java index b899df9..f8cd48a 100644 --- a/src/main/java/com/greate/community/service/DiscussPostService.java +++ b/src/main/java/com/greate/community/service/DiscussPostService.java @@ -1,5 +1,7 @@ package com.greate.community.service; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; import com.github.benmanes.caffeine.cache.CacheLoader; import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; @@ -208,4 +210,24 @@ public class DiscussPostService { return discussPostMapper.updateScore(id, score); } + /** + * 将discuss_post表中以 , 分隔的pic_urls转为json数组并将DiscussPost对象转换成JSONObject返回 + * + * @param discussPost + * @return + */ + public JSONObject toDiscussPostJsonObject(DiscussPost discussPost){ + if(("").equals(discussPost.getPicUrls())){ + discussPost.setPicUrls(null); + } + JSONObject discussPostJsonObject = (JSONObject) JSONObject.toJSON(discussPost); + String picUrls = discussPostJsonObject.getString("picUrls"); + if(picUrls!=null){ + String[] picUrlArray = picUrls.split(","); + JSONArray picUrlJSONArray = (JSONArray) JSONArray.toJSON(picUrlArray); + discussPostJsonObject.remove("picUrls"); + discussPostJsonObject.put("picUrls",picUrlJSONArray); + } + return discussPostJsonObject; + } } diff --git a/src/main/resources/mapper/discusspost-mapper.xml b/src/main/resources/mapper/discusspost-mapper.xml index 05e2b97..0f212ad 100644 --- a/src/main/resources/mapper/discusspost-mapper.xml +++ b/src/main/resources/mapper/discusspost-mapper.xml @@ -1,83 +1,83 @@ - - - - - - id, user_id, title, content, type, status, create_time, comment_count, score - - - - user_id, title, content, type, status, create_time, comment_count, score - - - - - - - - - - - - insert into discuss_post () - values(#{userId}, #{title}, #{content}, #{type}, #{status}, #{createTime}, #{commentCount}, #{score}) - - - - - - - update discuss_post - set comment_count = #{commentCount} - where id = #{id} - - - - - update discuss_post - set type = #{type} - where id = #{id} - - - - - update discuss_post - set status = #{status} - where id = #{id} - - - - - update discuss_post - set score = #{score} - where id = #{id} - - + + + + + + id, user_id, title, content, pic_urls, type, status, create_time, comment_count, score + + + + user_id, title, content, pic_urls, type, status, create_time, comment_count, score + + + + + + + + + + + + insert into discuss_post () + values(#{userId}, #{title}, #{content}, #{picUrls}, #{type}, #{status}, #{createTime}, #{commentCount}, #{score}) + + + + + + + update discuss_post + set comment_count = #{commentCount} + where id = #{id} + + + + + update discuss_post + set type = #{type} + where id = #{id} + + + + + update discuss_post + set status = #{status} + where id = #{id} + + + + + update discuss_post + set score = #{score} + where id = #{id} + + \ No newline at end of file -- Gitee From b93fa7de2267b09ce061bbd7027b898bd108fe5c Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Sun, 13 Feb 2022 12:47:38 +0800 Subject: [PATCH 021/125] update cos path --- .../community/controller/AuditController.java | 39 +++++++------- .../community/controller/BaseController.java | 3 ++ .../controller/DiscussPostController.java | 51 ++++++++++--------- .../controller/FollowController.java | 29 ++++++----- .../community/controller/LoginController.java | 4 +- .../controller/MessageController.java | 20 +++++--- .../community/controller/UserController.java | 38 ++++++++------ .../greate/community/service/CosService.java | 5 +- .../greate/community/service/LikeService.java | 6 +-- .../greate/community/service/UserService.java | 18 ++++--- 10 files changed, 117 insertions(+), 96 deletions(-) diff --git a/src/main/java/com/greate/community/controller/AuditController.java b/src/main/java/com/greate/community/controller/AuditController.java index d705e24..d621fc1 100644 --- a/src/main/java/com/greate/community/controller/AuditController.java +++ b/src/main/java/com/greate/community/controller/AuditController.java @@ -16,6 +16,7 @@ import java.util.Map; /** * 用户身份实名认证审核模块 + * * @author xzx * @date 2022/2/9 21:41 */ @@ -28,19 +29,17 @@ public class AuditController { * 通过或驳回实名信息 */ @PostMapping("/admin/audit") - public Result audit(@RequestBody HashMap map){ + public Result audit(@RequestBody HashMap map) { int userId = map.get("userId"); int auditStatus = map.get("auditStatus"); - if (auditStatus == 2){ + if (auditStatus == 2) { userService.updateAuditStatus(userId, auditStatus); - return new Result("success", Result.SUCCESS, "用户id--"+userId+"--审核通过成功"); - } - else if (auditStatus == 3){ + return new Result("success", Result.SUCCESS, "用户id--" + userId + "--审核通过成功"); + } else if (auditStatus == 3) { userService.updateAuditStatus(userId, auditStatus); - return new Result("success", Result.SUCCESS, "用户id--"+userId+"--审核驳回成功"); - } - else { + return new Result("success", Result.SUCCESS, "用户id--" + userId + "--审核驳回成功"); + } else { return new Result("fail", "1", "the request parameters are invalid"); } } @@ -50,15 +49,15 @@ public class AuditController { */ @GetMapping("/admin/user/brief") public Result getBriefUsers(Page page, int auditStatus) { - if(auditStatus == 0 || auditStatus == 1 || auditStatus == 2 || auditStatus == 3){ + if (auditStatus == 0 || auditStatus == 1 || auditStatus == 2 || auditStatus == 3) { page.setPath("/admin/user/brief"); page.setRows(userService.findRealNameRows(auditStatus)); - List briefUserList = userService.findRealNameList(auditStatus, page.getOffset(), page.getLimit(),0); + List briefUserList = userService.findRealNameList(auditStatus, page.getOffset(), page.getLimit(), 0); List> resultBriefUserList = new ArrayList<>(); - for(User user : briefUserList){ - HashMap resultBriefUser = new HashMap<>(); + for (User user : briefUserList) { + HashMap resultBriefUser = new HashMap<>(); resultBriefUser.put("id", user.getId()); resultBriefUser.put("username", user.getUsername()); resultBriefUser.put("email", user.getEmail()); @@ -66,8 +65,7 @@ public class AuditController { } return new Result("success", Result.SUCCESS, resultBriefUserList); - } - else { + } else { return new Result("fail", "1", "the request parameters are invalid"); } } @@ -77,15 +75,15 @@ public class AuditController { */ @GetMapping("/admin/user/detailed") public Result getDetailedUsers(Page page, int auditStatus) { - if(auditStatus == 0 || auditStatus == 1 || auditStatus == 2 || auditStatus == 3){ + if (auditStatus == 0 || auditStatus == 1 || auditStatus == 2 || auditStatus == 3) { page.setPath("/admin/user/detailed"); page.setRows(userService.findRealNameRows(auditStatus)); - List detailedUserList = userService.findRealNameList(auditStatus, page.getOffset(), page.getLimit(),1); + List detailedUserList = userService.findRealNameList(auditStatus, page.getOffset(), page.getLimit(), 1); List> resultDetailedUserList = new ArrayList<>(); - for(User user : detailedUserList){ - HashMap resultDetailedUser = new HashMap<>(); + for (User user : detailedUserList) { + HashMap resultDetailedUser = new HashMap<>(); resultDetailedUser.put("id", user.getId()); resultDetailedUser.put("username", user.getUsername()); resultDetailedUser.put("email", user.getEmail()); @@ -98,8 +96,7 @@ public class AuditController { } return new Result("success", Result.SUCCESS, resultDetailedUserList); - } - else { + } else { return new Result("fail", "1", "the request parameters are invalid"); } } @@ -110,7 +107,7 @@ public class AuditController { @GetMapping("/admin/user/detailedById") public Result getDetailedUserById(int userId) { User user = userService.findRealNameUserById(userId); - HashMap resultDetailedUser = new HashMap<>(); + HashMap resultDetailedUser = new HashMap<>(); resultDetailedUser.put("id", user.getId()); resultDetailedUser.put("username", user.getUsername()); resultDetailedUser.put("email", user.getEmail()); diff --git a/src/main/java/com/greate/community/controller/BaseController.java b/src/main/java/com/greate/community/controller/BaseController.java index 79ef913..063afc3 100644 --- a/src/main/java/com/greate/community/controller/BaseController.java +++ b/src/main/java/com/greate/community/controller/BaseController.java @@ -1,6 +1,7 @@ package com.greate.community.controller; import com.greate.community.entity.User; +import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.context.SecurityContextHolder; /** @@ -11,9 +12,11 @@ import org.springframework.security.core.context.SecurityContextHolder; * * @version v1.0 */ +@Slf4j public class BaseController { protected User getUser() { + log.info(SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString()); return (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); } } diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index 708a83b..09b4474 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -45,11 +45,11 @@ public class DiscussPostController extends BaseController implements CommunityCo /** * 添加帖子(发帖) - * @return * + * @return */ @PostMapping("/add") - public Result addDiscussPost(@RequestBody HashMap map) { + public Result addDiscussPost(@RequestBody HashMap map) { String title = (String) map.get("title"); String content = (String) map.get("content"); ArrayList picUrlList = (ArrayList) map.get("picUrls"); @@ -57,8 +57,8 @@ public class DiscussPostController extends BaseController implements CommunityCo String picUrls = ""; int picNum = 0; - if(picUrlList != null){ - for(String picUrl : picUrlList){ + if (picUrlList != null) { + for (String picUrl : picUrlList) { picUrls = picUrls + picUrl + ","; picNum++; } @@ -68,7 +68,7 @@ public class DiscussPostController extends BaseController implements CommunityCo User user = getUser(); if (user == null) { - return new Result("forbidden","403","您还未登录"); + return new Result("forbidden", "403", "您还未登录"); } DiscussPost discussPost = new DiscussPost(); @@ -92,19 +92,19 @@ public class DiscussPostController extends BaseController implements CommunityCo String redisKey = RedisKeyUtil.getPostScoreKey(); redisTemplate.opsForSet().add(redisKey, discussPost.getId()); - return new Result("success","200","帖子发布成功," + "配图 " + picNum + " 张"); + return new Result("success", "200", "帖子发布成功," + "配图 " + picNum + " 张"); } /** * 进入帖子详情页 + * * @param discussPostId - * @param model * @return */ @GetMapping("/detail/{discussPostId}") @ResponseBody - public Result getDiscussPost(@PathVariable("discussPostId") int discussPostId, Model model, Page page) { - HashMap resultMap=new HashMap<>(); + public Result getDiscussPost(@PathVariable("discussPostId") int discussPostId, Page page) { + HashMap resultMap = new HashMap<>(); // 帖子 DiscussPost discussPost = discussPostService.findDiscussPostById(discussPostId); @@ -116,16 +116,16 @@ public class DiscussPostController extends BaseController implements CommunityCo // 作者 User user = userService.findUserById(discussPost.getUserId()); - resultMap.put("user",user); + resultMap.put("user", user); // 点赞数量 long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, discussPostId); - resultMap.put("likeCount",likeCount); + resultMap.put("likeCount", likeCount); // 当前登录用户的点赞状态 int likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus(getUser().getId(), ENTITY_TYPE_POST, discussPostId); - resultMap.put("likeStatus",likeStatus); + resultMap.put("likeStatus", likeStatus); // 评论分页信息 page.setPath("/discuss/detail/" + discussPostId); @@ -138,7 +138,7 @@ public class DiscussPostController extends BaseController implements CommunityCo // 封装评论及其相关信息 List> commentVoList = new ArrayList<>(); if (commentList != null) { - for (Comment comment : commentList) { + for (Comment comment : commentList) { // 存储对帖子的评论 Map commentVo = new HashMap<>(); commentVo.put("comment", comment); // 评论 @@ -149,10 +149,9 @@ public class DiscussPostController extends BaseController implements CommunityCo getUser().getId(), ENTITY_TYPE_COMMENT, comment.getId()); // 当前登录用户对该评论的点赞状态 commentVo.put("likeStatus", likeStatus); - // 存储每个评论对应的回复(不做分页) List replyList = commentService.findCommentByEntity( - ENTITY_TYPE_COMMENT, comment.getId(), 0, Integer.MAX_VALUE); + ENTITY_TYPE_COMMENT, comment.getId(), 0, Integer.MAX_VALUE); List> replyVoList = new ArrayList<>(); // 封装对评论的评论和评论的作者信息 if (replyList != null) { for (Comment reply : replyList) { @@ -177,27 +176,27 @@ public class DiscussPostController extends BaseController implements CommunityCo commentVo.put("replyCount", replyCount); commentVoList.add(commentVo); - } + } } - resultMap.put("comments",commentVoList); + resultMap.put("comments", commentVoList); //增加经验 if (getUser() != null) { expService.handleGetExp(getUser().getId(), ExpType.EXP_BROWSE.getName()); } - return new Result("success",Result.SUCCESS,resultMap); + return new Result("success", Result.SUCCESS, resultMap); } /** * 置顶帖子 - * @return * + * @return */ @PostMapping("/top") @ResponseBody - public Result updateTop(@RequestBody HashMap map) { + public Result updateTop(@RequestBody HashMap map) { int id = map.get("id"); int type = map.get("type"); @@ -211,16 +210,17 @@ public class DiscussPostController extends BaseController implements CommunityCo .setEntityId(id); eventProducer.fireEvent(event); - return new Result("success",Result.SUCCESS,""); + return new Result("success", Result.SUCCESS, ""); } /** * 加精帖子 + * * @return */ @PostMapping("/wonderful") - public Result setWonderful(@RequestBody HashMap map) { + public Result setWonderful(@RequestBody HashMap map) { int id = map.get("id"); discussPostService.updateStatus(id, 1); @@ -237,17 +237,18 @@ public class DiscussPostController extends BaseController implements CommunityCo String redisKey = RedisKeyUtil.getPostScoreKey(); redisTemplate.opsForSet().add(redisKey, id); - return new Result("success",Result.SUCCESS,""); + return new Result("success", Result.SUCCESS, ""); } /** * 删除帖子 + * * @return */ @PostMapping("/delete") @ResponseBody - public Result setDelete(@RequestBody HashMap map) { + public Result setDelete(@RequestBody HashMap map) { int id = map.get("id"); discussPostService.updateStatus(id, 2); @@ -259,7 +260,7 @@ public class DiscussPostController extends BaseController implements CommunityCo .setEntityId(id); eventProducer.fireEvent(event); - return new Result("success",Result.SUCCESS,"删除成功"); + return new Result("success", Result.SUCCESS, "删除成功"); } } diff --git a/src/main/java/com/greate/community/controller/FollowController.java b/src/main/java/com/greate/community/controller/FollowController.java index 86a75ff..a3cd9ad 100644 --- a/src/main/java/com/greate/community/controller/FollowController.java +++ b/src/main/java/com/greate/community/controller/FollowController.java @@ -24,7 +24,7 @@ import java.util.Map; * 关注(目前只做了关注用户) */ @RestController -public class FollowController extends BaseController implements CommunityConstant{ +public class FollowController extends BaseController implements CommunityConstant { @Autowired private FollowService followService; @@ -37,12 +37,12 @@ public class FollowController extends BaseController implements CommunityConstan /** * 关注 - * @return * + * @return */ @PostMapping("/follow") @ResponseBody - public Result follow(@RequestBody HashMap map) { + public Result follow(@RequestBody HashMap map) { int entityType = map.get("entityType"); int entityId = map.get("entityId"); @@ -59,17 +59,17 @@ public class FollowController extends BaseController implements CommunityConstan .setEntityUserId(entityId); eventProducer.fireEvent(event); -// return CommunityUtil.getJSONString(0, "已关注"); - return new Result("success",Result.SUCCESS,"已关注"); + return new Result("success", Result.SUCCESS, "已关注"); } /** * 取消关注 + * * @return */ @PostMapping("/unfollow") @ResponseBody - public Result unfollow(@RequestBody HashMap map) { + public Result unfollow(@RequestBody HashMap map) { int entityType = map.get("entityType"); int entityId = map.get("entityId"); @@ -77,12 +77,12 @@ public class FollowController extends BaseController implements CommunityConstan followService.unfollow(user.getId(), entityType, entityId); -// return CommunityUtil.getJSONString(0, "已取消关注"); - return new Result("success",Result.SUCCESS,"已取消关注"); + return new Result("success", Result.SUCCESS, "已取消关注"); } /** * 某个用户的关注列表(人) + * * @param userId * @param page * @param model @@ -90,8 +90,8 @@ public class FollowController extends BaseController implements CommunityConstan */ @GetMapping("/followees/{userId}") @ResponseBody - public Result getFollowees(@PathVariable("userId") int userId,Page page, Model model) { - HashMap hashMap = new HashMap<>(); + public Result getFollowees(@PathVariable("userId") int userId, Page page, Model model) { + HashMap hashMap = new HashMap<>(); User user = userService.findUserById(userId); if (user == null) { @@ -115,7 +115,7 @@ public class FollowController extends BaseController implements CommunityConstan } // model.addAttribute("users", userList); - hashMap.put("users", userList);//正在查看的用户所关注的用户列表 + hashMap.put("users", userList); //正在查看的用户所关注的用户列表 // return "/site/followee"; return new Result("success", Result.SUCCESS, hashMap); @@ -123,6 +123,7 @@ public class FollowController extends BaseController implements CommunityConstan /** * 某个用户的粉丝列表 + * * @param userId * @param page * @param model @@ -131,7 +132,7 @@ public class FollowController extends BaseController implements CommunityConstan @GetMapping("/followers/{userId}") @ResponseBody public Result getFollowers(@PathVariable("userId") int userId, Page page, Model model) { - HashMap hashMap = new HashMap<>(); + HashMap hashMap = new HashMap<>(); User user = userService.findUserById(userId); if (user == null) { @@ -158,11 +159,12 @@ public class FollowController extends BaseController implements CommunityConstan hashMap.put("users", userList);//正在查看的用户的粉丝列表 // return "/site/follower"; - return new Result("success",Result.SUCCESS,hashMap); + return new Result("success", Result.SUCCESS, hashMap); } /** * 判断当前登录用户是否已关注某个用户 + * * @param userId 某个用户 * @return */ @@ -175,5 +177,4 @@ public class FollowController extends BaseController implements CommunityConstan } - } diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index ec28d08..5f88fed 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -15,6 +15,7 @@ import com.greate.community.util.CommunityConstant; import com.greate.community.util.CommunityUtil; import com.greate.community.util.ExpType; import com.greate.community.util.RedisKeyUtil; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,11 +37,10 @@ import java.util.concurrent.TimeUnit; /** * 登录、登出、注册 */ +@Slf4j @RestController public class LoginController extends BaseController implements CommunityConstant { - private static final Logger logger = LoggerFactory.getLogger(LoginController.class); - @Autowired private UserService userService; diff --git a/src/main/java/com/greate/community/controller/MessageController.java b/src/main/java/com/greate/community/controller/MessageController.java index 1068880..6032e58 100644 --- a/src/main/java/com/greate/community/controller/MessageController.java +++ b/src/main/java/com/greate/community/controller/MessageController.java @@ -15,6 +15,7 @@ import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import org.springframework.web.util.HtmlUtils; + import java.util.*; /** @@ -31,11 +32,12 @@ public class MessageController extends BaseController implements CommunityConsta /** * 私信列表 + * * @param page * @return */ @GetMapping("/letter/list") - public Result getLetterList( Page page) { + public Result getLetterList(Page page) { // Integer.valueOf("abc"); // 测试统一异常处理(普通请求) JSONObject jsonObject = new JSONObject(); @@ -79,6 +81,7 @@ public class MessageController extends BaseController implements CommunityConsta /** * 私信详情页 + * * @param conversationId * @param page * @return @@ -120,6 +123,7 @@ public class MessageController extends BaseController implements CommunityConsta /** * 获取私信对方对象 + * * @param conversationId * @return */ @@ -130,14 +134,14 @@ public class MessageController extends BaseController implements CommunityConsta if (getUser().getId() == id0) { return userService.findUserById(id1); - } - else { + } else { return userService.findUserById(id0); } } /** * 获取当前登录用户未读私信的 id + * * @param letterList * @return */ @@ -158,7 +162,8 @@ public class MessageController extends BaseController implements CommunityConsta /** * 发送私信 - * @param userId 收信人 userId + * + * @param userId 收信人 userId * @param content 内容 * @return */ @@ -175,8 +180,7 @@ public class MessageController extends BaseController implements CommunityConsta message.setToId(target.getId()); if (message.getFromId() < message.getToId()) { message.setConversationId(message.getFromId() + "_" + message.getToId()); - } - else { + } else { message.setConversationId(message.getToId() + "_" + message.getFromId()); } message.setContent(content); @@ -190,6 +194,7 @@ public class MessageController extends BaseController implements CommunityConsta /** * 通知列表(只显示最新一条消息) + * * @return */ @GetMapping("/notice/list") @@ -280,6 +285,7 @@ public class MessageController extends BaseController implements CommunityConsta /** * 查询某个主题所包含的通知列表 + * * @param topic * @param page * @return @@ -293,7 +299,7 @@ public class MessageController extends BaseController implements CommunityConsta page.setRows(messageService.findNoticeCount(user.getId(), topic)); // 查询某个主题所包含的通知列表 - List noticeList = messageService.findNotices(user.getId(), topic,page.getOffset(), page.getLimit()); + List noticeList = messageService.findNotices(user.getId(), topic, page.getOffset(), page.getLimit()); List> noticeVoList = new ArrayList<>(); if (noticeList != null) { for (Message notice : noticeList) { diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 448f5a3..312a182 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -50,15 +50,6 @@ public class UserController extends BaseController implements CommunityConstant @Value("${server.servlet.context-path}") private String contextPath; - @Value("${qiniu.key.access}") - private String accessKey; - - @Value("${qiniu.key.secret}") - private String secretKey; - - @Value("${qiniu.bucket.header.name}") - private String headerBucketName; - @Value("${qiniu.bucket.header.url}") private String headerBucketUrl; @@ -66,10 +57,28 @@ public class UserController extends BaseController implements CommunityConstant * 通过ticket获取user * @return */ + @Deprecated @GetMapping("/get") public Result getUserByTicket() { + JSONObject jsonObject = new JSONObject(); User user = getUser(); - return new Result("success", Result.SUCCESS, userService.findUserById(user.getId())); + if (user == null) { + return new Result("fail", "1", "该用户不存在"); + } + + // 用户 + jsonObject.put("user", user); + // 获赞数量 + int userLikeCount = likeService.findUserLikeCount(user.getId()); + jsonObject.put("userLikeCount", userLikeCount); + // 关注数量 + long followeeCount = followService.findFolloweeCount(user.getId(), ENTITY_TYPE_USER); + jsonObject.put("followeeCount", followeeCount); + // 粉丝数量 + long followerCount = followService.findFollowerCount(ENTITY_TYPE_USER, user.getId()); + jsonObject.put("followerCount", followerCount); + + return new Result("success", Result.SUCCESS, jsonObject); } /** @@ -89,7 +98,6 @@ public class UserController extends BaseController implements CommunityConstant userService.updateHeader(getUser().getId(), url); return CommunityUtil.getJSONString(0); - } /** @@ -120,11 +128,11 @@ public class UserController extends BaseController implements CommunityConstant } /** - * 进入个人主页 + * 获取用户信息 * @param userId 可以进入任意用户的个人主页 * @return */ - @GetMapping("/profile/{userId}") + @GetMapping("/{userId}") public Result getProfilePage(@PathVariable("userId") int userId) { JSONObject jsonObject = new JSONObject(); User user = userService.findUserById(userId); @@ -263,7 +271,7 @@ public class UserController extends BaseController implements CommunityConstant */ @PostMapping("/realname") public Result updateRealNameInfo(@RequestBody User user) { - if (user == null){ + if (user == null) { return new Result("fail", "1", "the request parameters are invalid"); } @@ -283,7 +291,7 @@ public class UserController extends BaseController implements CommunityConstant public Result updateHeader(@RequestBody JSONObject jsonObject) { String headerUrl = jsonObject.getString("headerUrl"); - if (headerUrl == null){ + if (headerUrl == null) { return new Result("fail", "1", "the request parameters are invalid"); } diff --git a/src/main/java/com/greate/community/service/CosService.java b/src/main/java/com/greate/community/service/CosService.java index bdfe2c3..beee41a 100644 --- a/src/main/java/com/greate/community/service/CosService.java +++ b/src/main/java/com/greate/community/service/CosService.java @@ -1,6 +1,5 @@ package com.greate.community.service; -import com.greate.community.util.CommunityConstant; import com.greate.community.util.CosStsClientUtil; import com.tencent.cloud.Response; import org.springframework.beans.factory.annotation.Autowired; @@ -22,6 +21,8 @@ public class CosService { public Response getCredential(String type, int userId) { - return cosStsClientUtil.getCredential(type, String.valueOf(userId)); + String allPrefixes = userId + "/*"; + + return cosStsClientUtil.getCredential(type, allPrefixes); } } diff --git a/src/main/java/com/greate/community/service/LikeService.java b/src/main/java/com/greate/community/service/LikeService.java index 0ce5e5f..3237627 100644 --- a/src/main/java/com/greate/community/service/LikeService.java +++ b/src/main/java/com/greate/community/service/LikeService.java @@ -21,9 +21,9 @@ public class LikeService { * 点赞 * * @param userId 点赞的用户 id - * @param entityType - * @param entityId - * @param entityUserId 被赞的帖子/评论的作者 id + * @param entityType 点赞实体类型 + * @param entityId 点赞实体 id + * @param entityUserId 点赞实体对应用户 id */ public void like(int userId, int entityType, int entityId, int entityUserId) { redisTemplate.execute(new SessionCallback() { diff --git a/src/main/java/com/greate/community/service/UserService.java b/src/main/java/com/greate/community/service/UserService.java index 8b3e6dd..bcf681a 100644 --- a/src/main/java/com/greate/community/service/UserService.java +++ b/src/main/java/com/greate/community/service/UserService.java @@ -367,6 +367,7 @@ public class UserService implements CommunityConstant { /** * 修改用户实名信息审核状态,保存用户实名信息 + * * @param userId * @param auditStatus * @return @@ -382,45 +383,48 @@ public class UserService implements CommunityConstant { * 当传入的 auditStatus = 1 时,查找所有 未审核 的用户信息 * 当传入的 auditStatus = 2 时,查找所有 审核通过 的用户信息 * 当传入的 auditStatus = 3 时,查找所有 审核驳回 的用户信息 - * @param offset 每页的起始索引 - * @param limit 每页显示多少条数据 - * @param detailed 是否查询实名详细信息,0-简略信息,1-详细信息 + * @param offset 每页的起始索引 + * @param limit 每页显示多少条数据 + * @param detailed 是否查询实名详细信息,0-简略信息,1-详细信息 * @return */ - public List findRealNameList (int auditStatus, int offset, int limit, int detailed) { + public List findRealNameList(int auditStatus, int offset, int limit, int detailed) { return userMapper.selectRealNameList(auditStatus, offset, limit, detailed); } /** * 查询实名用户个数 + * * @param auditStatus 当传入的 auditStatus = 0 时,查找所有 未上传学生证图片 的用户信息 * 当传入的 auditStatus = 1 时,查找所有 未审核 的用户信息 * 当传入的 auditStatus = 2 时,查找所有 审核通过 的用户信息 * 当传入的 auditStatus = 3 时,查找所有 审核驳回 的用户信息 * @return */ - public int findRealNameRows (int auditStatus) { + public int findRealNameRows(int auditStatus) { return userMapper.selectRealNameRows(auditStatus); } /** * 依据userId查询用户实名详细信息 + * * @param userId 用户id * @return */ - public User findRealNameUserById (int userId) { + public User findRealNameUserById(int userId) { return userMapper.selectRealNameUserById(userId); } /** * 更新用户实名信息 + * * @param user * @return */ public int updateRealNameInfo(User user) { // return userMapper.updateHeader(userId, headUrl); int rows = userMapper.updateRealNameInfo(user); - //clearCache(userId); + clearCache(user.getId()); return rows; } -- Gitee From 9379abc8a7a6a634e8f7b88dad9109c669bc5121 Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Sun, 13 Feb 2022 16:37:31 +0800 Subject: [PATCH 022/125] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=88=86=E9=A1=B5?= =?UTF-8?q?=E7=BB=93=E6=9E=9C=E6=95=B0=E6=8D=AE=E8=BF=94=E5=9B=9E=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/CommunityApplication.java | 66 ++++++++++++------- .../community/controller/AuditController.java | 12 +++- .../controller/DiscussPostController.java | 8 ++- .../community/controller/ExpController.java | 12 +++- .../controller/FollowController.java | 21 +++--- .../community/controller/IndexController.java | 5 +- .../controller/MessageController.java | 26 +++++--- .../controller/SearchController.java | 12 ++-- .../community/controller/UserController.java | 11 +++- .../com/greate/community/entity/Page.java | 27 ++++++-- src/main/resources/mapper/exp-mapper.xml | 2 +- 11 files changed, 136 insertions(+), 66 deletions(-) diff --git a/src/main/java/com/greate/community/CommunityApplication.java b/src/main/java/com/greate/community/CommunityApplication.java index 07b617a..110d6a1 100644 --- a/src/main/java/com/greate/community/CommunityApplication.java +++ b/src/main/java/com/greate/community/CommunityApplication.java @@ -1,23 +1,43 @@ -package com.greate.community; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -import javax.annotation.PostConstruct; - -@SpringBootApplication -public class CommunityApplication { - - /** - * 解决 Elasticsearch 和 Redis 底层的 Netty 启动冲突问题 - */ - @PostConstruct - public void init() { - System.setProperty("es.set.netty.runtime.available.processors", "false"); - } - - public static void main(String[] args) { - SpringApplication.run(CommunityApplication.class, args); - } - -} +package com.greate.community; + +import com.alibaba.fastjson.serializer.SerializerFeature; +import com.alibaba.fastjson.support.config.FastJsonConfig; +import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.http.HttpMessageConverters; +import org.springframework.context.annotation.Bean; +import org.springframework.http.converter.HttpMessageConverter; + +import javax.annotation.PostConstruct; + +@SpringBootApplication +public class CommunityApplication { + + /** + * 解决 Elasticsearch 和 Redis 底层的 Netty 启动冲突问题 + */ + @PostConstruct + public void init() { + System.setProperty("es.set.netty.runtime.available.processors", "false"); + } + + /** + * Sprintboot默认通过jackson来转换JSON,配置成以fastjson来转换JSON,以扫描@JSONField(serialize = false)注解, + */ + @Bean + public HttpMessageConverters fastJsonHttpMessageConverters() { + FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); + FastJsonConfig fastJsonConfig = new FastJsonConfig(); + fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat,SerializerFeature.WriteMapNullValue); + fastConverter.setFastJsonConfig(fastJsonConfig); + HttpMessageConverter converter = fastConverter; + return new HttpMessageConverters(converter); + } + + public static void main(String[] args) { + SpringApplication.run(CommunityApplication.class, args); + } + + +} diff --git a/src/main/java/com/greate/community/controller/AuditController.java b/src/main/java/com/greate/community/controller/AuditController.java index d705e24..4a0d512 100644 --- a/src/main/java/com/greate/community/controller/AuditController.java +++ b/src/main/java/com/greate/community/controller/AuditController.java @@ -1,5 +1,7 @@ package com.greate.community.controller; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; import com.greate.community.entity.Page; import com.greate.community.entity.Result; import com.greate.community.entity.User; @@ -65,7 +67,10 @@ public class AuditController { resultBriefUserList.add(resultBriefUser); } - return new Result("success", Result.SUCCESS, resultBriefUserList); + JSONArray result = (JSONArray) JSONArray.toJSON(resultBriefUserList); + page.setResult(result); + + return new Result("success", Result.SUCCESS, page); } else { return new Result("fail", "1", "the request parameters are invalid"); @@ -97,7 +102,10 @@ public class AuditController { resultDetailedUserList.add(resultDetailedUser); } - return new Result("success", Result.SUCCESS, resultDetailedUserList); + JSONArray result = (JSONArray) JSONArray.toJSON(resultDetailedUserList); + page.setResult(result); + + return new Result("success", Result.SUCCESS, page); } else { return new Result("fail", "1", "the request parameters are invalid"); diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index 708a83b..4636d40 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -132,8 +132,7 @@ public class DiscussPostController extends BaseController implements CommunityCo page.setRows(discussPost.getCommentCount()); // 帖子的评论列表 - List commentList = commentService.findCommentByEntity( - ENTITY_TYPE_POST, discussPost.getId(), page.getOffset(), page.getLimit()); + List commentList = commentService.findCommentByEntity(ENTITY_TYPE_POST, discussPost.getId(), page.getOffset(), page.getLimit()); // 封装评论及其相关信息 List> commentVoList = new ArrayList<>(); @@ -180,7 +179,10 @@ public class DiscussPostController extends BaseController implements CommunityCo } } - resultMap.put("comments",commentVoList); +// resultMap.put("comments",commentVoList); + JSONArray result = (JSONArray) JSONArray.toJSON(commentVoList); + page.setResult(result); + resultMap.put("comments",page); //增加经验 if (getUser() != null) { diff --git a/src/main/java/com/greate/community/controller/ExpController.java b/src/main/java/com/greate/community/controller/ExpController.java index d8c08c5..63fc3be 100644 --- a/src/main/java/com/greate/community/controller/ExpController.java +++ b/src/main/java/com/greate/community/controller/ExpController.java @@ -1,6 +1,8 @@ package com.greate.community.controller; +import com.alibaba.fastjson.JSONArray; import com.google.gson.JsonObject; +import com.greate.community.entity.Exp; import com.greate.community.entity.Page; import com.greate.community.entity.Result; import com.greate.community.entity.User; @@ -10,6 +12,8 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import java.util.List; + /** * 类名称:ExpController * 类描述:经验控制器 @@ -26,7 +30,11 @@ public class ExpController extends BaseController { @PostMapping("/exp/page") public Result getPageOfExpLog(@RequestBody Page page) { - - return new Result("success", Result.SUCCESS, expService.getExpPageByUserId(getUser().getId(), page.getOffset(), page.getLimit())); +// return new Result("success", Result.SUCCESS, expService.getExpPageByUserId(getUser().getId(), page.getOffset(), page.getLimit())); +// + List expList = expService.getExpPageByUserId(getUser().getId(), page.getOffset(), page.getLimit()); + JSONArray result = (JSONArray) JSONArray.toJSON(expList); + page.setResult(result); + return new Result("success", Result.SUCCESS, page); } } diff --git a/src/main/java/com/greate/community/controller/FollowController.java b/src/main/java/com/greate/community/controller/FollowController.java index 86a75ff..6b6cb80 100644 --- a/src/main/java/com/greate/community/controller/FollowController.java +++ b/src/main/java/com/greate/community/controller/FollowController.java @@ -1,5 +1,6 @@ package com.greate.community.controller; +import com.alibaba.fastjson.JSONArray; import com.greate.community.entity.Event; import com.greate.community.entity.Page; import com.greate.community.entity.Result; @@ -97,10 +98,8 @@ public class FollowController extends BaseController implements CommunityConstan if (user == null) { throw new RuntimeException("该用户不存在"); } -// model.addAttribute("user", user); hashMap.put("user", user);//正在查看的用户信息 -// page.setLimit(5);//前端注入 page.setPath("/followees/" + userId); page.setRows((int) followService.findFolloweeCount(userId, ENTITY_TYPE_USER)); @@ -113,11 +112,11 @@ public class FollowController extends BaseController implements CommunityConstan map.put("hasFollowed", hasFollowed(u.getId())); // 判断当前登录用户是否已关注这个关注列表中的某个用户 } } +// hashMap.put("users", userList);//正在查看的用户所关注的用户列表 + JSONArray result = (JSONArray) JSONArray.toJSON(userList); + page.setResult(result); + hashMap.put("users", page);//正在查看的用户所关注的用户列表 -// model.addAttribute("users", userList); - hashMap.put("users", userList);//正在查看的用户所关注的用户列表 - -// return "/site/followee"; return new Result("success", Result.SUCCESS, hashMap); } @@ -137,10 +136,8 @@ public class FollowController extends BaseController implements CommunityConstan if (user == null) { throw new RuntimeException("该用户不存在"); } -// model.addAttribute("user", user); hashMap.put("user", user);//正在查看的用户信息 -// page.setLimit(5);//前端注入 page.setPath("/followers/" + userId); page.setRows((int) followService.findFollowerCount(ENTITY_TYPE_USER, userId)); @@ -153,11 +150,11 @@ public class FollowController extends BaseController implements CommunityConstan map.put("hasFollowed", hasFollowed(u.getId())); // 判断当前登录用户是否已关注这个关注列表中的某个用户 } } +// hashMap.put("users", userList);//正在查看的用户的粉丝列表 + JSONArray result = (JSONArray) JSONArray.toJSON(userList); + page.setResult(result); + hashMap.put("users", page);//正在查看的用户的粉丝列表 -// model.addAttribute("users", userList); - hashMap.put("users", userList);//正在查看的用户的粉丝列表 - -// return "/site/follower"; return new Result("success",Result.SUCCESS,hashMap); } diff --git a/src/main/java/com/greate/community/controller/IndexController.java b/src/main/java/com/greate/community/controller/IndexController.java index d2ed963..9f54942 100644 --- a/src/main/java/com/greate/community/controller/IndexController.java +++ b/src/main/java/com/greate/community/controller/IndexController.java @@ -69,8 +69,11 @@ public class IndexController implements CommunityConstant { discussPosts.add(map); } } +// hashMap.put("discussPosts", discussPosts); + JSONArray result = (JSONArray) JSONArray.toJSON(discussPosts); + page.setResult(result); + hashMap.put("discussPosts", page); - hashMap.put("discussPosts", discussPosts); hashMap.put("orderMode", orderMode); return new Result("success",Result.SUCCESS,hashMap); diff --git a/src/main/java/com/greate/community/controller/MessageController.java b/src/main/java/com/greate/community/controller/MessageController.java index 1068880..4d275db 100644 --- a/src/main/java/com/greate/community/controller/MessageController.java +++ b/src/main/java/com/greate/community/controller/MessageController.java @@ -1,5 +1,6 @@ package com.greate.community.controller; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.greate.community.entity.Message; import com.greate.community.entity.Page; @@ -47,25 +48,25 @@ public class MessageController extends BaseController implements CommunityConsta // 查询会话总数 page.setRows(messageService.findConversationCout(user.getId())); // 私信列表 - List conversationList = messageService.findConversations( - user.getId(), page.getOffset(), page.getLimit()); + List conversationList = messageService.findConversations(user.getId(), page.getOffset(), page.getLimit()); List> conversations = new ArrayList<>(); if (conversationList != null && !conversationList.isEmpty()) { for (Message message : conversationList) { Map map = new HashMap<>(); map.put("conversation", message); // 私信 - map.put("letterCount", messageService.findLetterCount( - message.getConversationId())); // 私信数量 - map.put("unreadCount", messageService.findLetterUnreadCount( - user.getId(), message.getConversationId())); // 未读私信数量 + map.put("letterCount", messageService.findLetterCount(message.getConversationId())); // 私信数量 + map.put("unreadCount", messageService.findLetterUnreadCount(user.getId(), message.getConversationId())); // 未读私信数量 int targetId = user.getId() == message.getFromId() ? message.getToId() : message.getFromId(); map.put("target", userService.findUserById(targetId)); // 私信对方 conversations.add(map); } } - jsonObject.put("conversations", conversations); + + JSONArray result = (JSONArray) JSONArray.toJSON(conversations); + page.setResult(result); + jsonObject.put("conversations",page); // 查询当前用户的所有未读私信数量 int letterUnreadCount = messageService.findLetterUnreadCount(user.getId(), null); @@ -104,7 +105,10 @@ public class MessageController extends BaseController implements CommunityConsta letters.add(map); } } - jsonObject.put("letters", letters); +// jsonObject.put("letters", letters); + JSONArray result = (JSONArray) JSONArray.toJSON(letters); + page.setResult(result); + jsonObject.put("letters", page); // 私信目标 jsonObject.put("target", getLetterTarget(conversationId)); @@ -314,12 +318,16 @@ public class MessageController extends BaseController implements CommunityConsta } } + JSONArray result = (JSONArray) JSONArray.toJSON(noticeVoList); + page.setResult(result); + // 设置已读 List ids = getUnreadLetterIds(noticeList); if (!ids.isEmpty()) { messageService.readMessage(ids); } - return new Result("success", Result.SUCCESS, noticeVoList); +// return new Result("success", Result.SUCCESS, noticeVoList); + return new Result("success", Result.SUCCESS, page); } } diff --git a/src/main/java/com/greate/community/controller/SearchController.java b/src/main/java/com/greate/community/controller/SearchController.java index 3ad35da..3188970 100644 --- a/src/main/java/com/greate/community/controller/SearchController.java +++ b/src/main/java/com/greate/community/controller/SearchController.java @@ -46,8 +46,7 @@ public class SearchController extends BaseController implements CommunityConstan public Result search(String keyword, Page page) { JSONObject jsonObject = new JSONObject(); // 搜索帖子 (Spring 提供的 Page 当前页码从 0 开始计数) - org.springframework.data.domain.Page searchResult = - elasticsearchService.searchDiscussPost(keyword, page.getCurrent()-1, page.getLimit()); + org.springframework.data.domain.Page searchResult = elasticsearchService.searchDiscussPost(keyword, page.getCurrent()-1, page.getLimit()); // 聚合数据 List> discussPosts = new ArrayList<>(); if (searchResult != null) { @@ -67,13 +66,16 @@ public class SearchController extends BaseController implements CommunityConstan } } - jsonObject.put("keyword", keyword); - jsonObject.put("discussPosts", discussPosts); - // 设置分页 page.setPath("/search?keyword="+ keyword); page.setRows(searchResult == null ? 0 : (int) searchResult.getTotalElements()); + jsonObject.put("keyword", keyword); +// jsonObject.put("discussPosts", discussPosts); + JSONArray result = (JSONArray) JSONArray.toJSON(discussPosts); + page.setResult(result); + jsonObject.put("discussPosts", discussPosts); + return new Result("success", Result.SUCCESS, jsonObject); } diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 448f5a3..42b356f 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -194,7 +194,10 @@ public class UserController extends BaseController implements CommunityConstant discussPosts.add(map); } } - jsonObject.put("discussPosts", discussPosts); +// jsonObject.put("discussPosts", discussPosts); + JSONArray result = (JSONArray) JSONArray.toJSON(discussPosts); + page.setResult(result); + jsonObject.put("discussPosts", page); return new Result("success", Result.SUCCESS, jsonObject); } @@ -218,7 +221,6 @@ public class UserController extends BaseController implements CommunityConstant int commentCounts = commentService.findCommentCountByUserId(userId); jsonObject.put("commentCounts", commentCounts); -// page.setLimit(5);//前端注入 page.setPath("/user/comment/" + userId); page.setRows(commentCounts); @@ -251,7 +253,10 @@ public class UserController extends BaseController implements CommunityConstant comments.add(map); } } - jsonObject.put("comments", comments); +// jsonObject.put("comments", comments); + JSONArray result = (JSONArray) JSONArray.toJSON(comments); + page.setResult(result); + jsonObject.put("comments", page); return new Result("success", Result.SUCCESS, jsonObject); } diff --git a/src/main/java/com/greate/community/entity/Page.java b/src/main/java/com/greate/community/entity/Page.java index 86311f1..fb8e71c 100644 --- a/src/main/java/com/greate/community/entity/Page.java +++ b/src/main/java/com/greate/community/entity/Page.java @@ -1,7 +1,8 @@ package com.greate.community.entity; -import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.annotation.JSONField; /** * 封装分页相关的信息 @@ -10,12 +11,12 @@ public class Page { // 当前的页码 private int current = 1; - // 单页显示的帖子数量上限 + // 单页显示的条目上限 private int limit = 10; - // 帖子总数(用于计算总页数) + // 条目总数(用于计算总页数) private int rows; - // 返回内容 - private JSONObject results; + // 封装返回内容 + private JSONArray result; // 查询路径(用于复用分页链接, 因为我们不只在首页中有分页,其他界面也会有分页) private String path; @@ -49,6 +50,14 @@ public class Page { } } + public JSONArray getResult() { + return result; + } + + public void setResult(JSONArray result) { + this.result = result; + } + public String getPath() { return path; } @@ -57,10 +66,16 @@ public class Page { this.path = path; } + + + + + /** * 获取当前页的起始索引 offset * @return */ + @JSONField(serialize = false) public int getOffset() { return current * limit - limit; } @@ -83,6 +98,7 @@ public class Page { * 分页栏显示当前页码及其前后两页 * @return */ + @JSONField(serialize = false) public int getFrom() { int from = current - 2; return from < 1 ? 1 : from; @@ -92,6 +108,7 @@ public class Page { * 获取分页栏结束页码 * @return */ + @JSONField(serialize = false) public int getTo() { int to = current + 2; int total = getTotal(); diff --git a/src/main/resources/mapper/exp-mapper.xml b/src/main/resources/mapper/exp-mapper.xml index 49f8665..d78bcd2 100644 --- a/src/main/resources/mapper/exp-mapper.xml +++ b/src/main/resources/mapper/exp-mapper.xml @@ -36,7 +36,7 @@ -- Gitee From 51597af40e6f1726202e6ae11b9e7f1d5c510d0a Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Sun, 13 Feb 2022 16:52:30 +0800 Subject: [PATCH 023/125] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=AF=B9=E9=A6=96=E9=A1=B5=E5=B8=96=E5=AD=90?= =?UTF-8?q?=E7=9A=84=E7=82=B9=E8=B5=9E=E7=8A=B6=E6=80=81=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/greate/community/controller/IndexController.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/greate/community/controller/IndexController.java b/src/main/java/com/greate/community/controller/IndexController.java index 9f54942..06b40fb 100644 --- a/src/main/java/com/greate/community/controller/IndexController.java +++ b/src/main/java/com/greate/community/controller/IndexController.java @@ -1,7 +1,6 @@ package com.greate.community.controller; import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; import com.greate.community.entity.DiscussPost; import com.greate.community.entity.Page; import com.greate.community.entity.Result; @@ -23,7 +22,7 @@ import java.util.Map; * 首页 */ @RestController -public class IndexController implements CommunityConstant { +public class IndexController extends BaseController implements CommunityConstant { @Autowired private DiscussPostService discussPostService; @@ -66,6 +65,11 @@ public class IndexController implements CommunityConstant { long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId()); map.put("likeCount", likeCount); + // 当前登录用户对帖子的点赞状态 + int likeStatus = getUser() == null ? 0 : + likeService.findEntityLikeStatus(getUser().getId(), ENTITY_TYPE_POST, post.getId()); + map.put("likeStatus",likeStatus); + discussPosts.add(map); } } -- Gitee From 8b46919381c3be9d72298329a9cf81c02dc6169d Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Sun, 13 Feb 2022 19:28:59 +0800 Subject: [PATCH 024/125] =?UTF-8?q?=E8=A7=A3=E5=86=B3toDiscussPostJsonObje?= =?UTF-8?q?ct=E6=96=B9=E6=B3=95=E5=85=A5=E5=8F=82=E4=B8=BAnull=E6=97=B6?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/service/DiscussPostService.java | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/greate/community/service/DiscussPostService.java b/src/main/java/com/greate/community/service/DiscussPostService.java index f8cd48a..d664c9f 100644 --- a/src/main/java/com/greate/community/service/DiscussPostService.java +++ b/src/main/java/com/greate/community/service/DiscussPostService.java @@ -217,17 +217,21 @@ public class DiscussPostService { * @return */ public JSONObject toDiscussPostJsonObject(DiscussPost discussPost){ - if(("").equals(discussPost.getPicUrls())){ - discussPost.setPicUrls(null); + if(discussPost == null){ + return null; + }else { + if(("").equals(discussPost.getPicUrls())){ + discussPost.setPicUrls(null); + } + JSONObject discussPostJsonObject = (JSONObject) JSONObject.toJSON(discussPost); + String picUrls = discussPostJsonObject.getString("picUrls"); + if(picUrls!=null){ + String[] picUrlArray = picUrls.split(","); + JSONArray picUrlJSONArray = (JSONArray) JSONArray.toJSON(picUrlArray); + discussPostJsonObject.remove("picUrls"); + discussPostJsonObject.put("picUrls",picUrlJSONArray); + } + return discussPostJsonObject; } - JSONObject discussPostJsonObject = (JSONObject) JSONObject.toJSON(discussPost); - String picUrls = discussPostJsonObject.getString("picUrls"); - if(picUrls!=null){ - String[] picUrlArray = picUrls.split(","); - JSONArray picUrlJSONArray = (JSONArray) JSONArray.toJSON(picUrlArray); - discussPostJsonObject.remove("picUrls"); - discussPostJsonObject.put("picUrls",picUrlJSONArray); - } - return discussPostJsonObject; } } -- Gitee From 73a6eb898070dc29022b664219c13baff1bfffbc Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Sun, 13 Feb 2022 23:21:09 +0800 Subject: [PATCH 025/125] update like with mysql --- .../com/greate/community/dao/LikeMapper.java | 29 ++++++++++++++++++ .../com/greate/community/entity/Like.java | 26 ++++++++++++++++ .../com/greate/community/entity/User.java | 26 ++-------------- .../greate/community/service/LikeService.java | 4 +++ .../community/util/CosStsClientUtil.java | 1 + src/main/resources/mapper/like-mapper.xml | 30 +++++++++++++++++++ 6 files changed, 92 insertions(+), 24 deletions(-) create mode 100644 src/main/java/com/greate/community/dao/LikeMapper.java create mode 100644 src/main/java/com/greate/community/entity/Like.java create mode 100644 src/main/resources/mapper/like-mapper.xml diff --git a/src/main/java/com/greate/community/dao/LikeMapper.java b/src/main/java/com/greate/community/dao/LikeMapper.java new file mode 100644 index 0000000..a1bdbf2 --- /dev/null +++ b/src/main/java/com/greate/community/dao/LikeMapper.java @@ -0,0 +1,29 @@ +package com.greate.community.dao; + +import com.greate.community.entity.Like; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface LikeMapper { + + /** + * 插入点赞记录 + * @param like + * @return + */ + int insertLike(Like like); + + /** + * 查询用户是否点赞某个实体 + * @return + */ + int countLikeByUserIdAndEntity(int userId, int entityType, int entityId); + + /** + * 查询某个实体点赞数量 + * @param entityType + * @param entityId + * @return + */ + int countLikeByEntity(int entityType, int entityId); +} diff --git a/src/main/java/com/greate/community/entity/Like.java b/src/main/java/com/greate/community/entity/Like.java new file mode 100644 index 0000000..22ae263 --- /dev/null +++ b/src/main/java/com/greate/community/entity/Like.java @@ -0,0 +1,26 @@ +package com.greate.community.entity; + +import lombok.Data; +import lombok.ToString; + +import java.util.Date; + +/** + * 类名称:Like + * 类描述:点赞实体类 + * 创建人:CSUpipixia + * 创建时间:2022/2/13 13:00 + * + * @version v1.0 + */ +@Data +@ToString +public class Like { + + private int id; + private int userId; // 点赞用户 id + private String entityType; // 点赞实体类型 + private int entityId; // 点赞实体 id + private String entityUserId; // 点赞实体对应用户 id + private Date createTime; +} diff --git a/src/main/java/com/greate/community/entity/User.java b/src/main/java/com/greate/community/entity/User.java index bd85dde..c5d8d17 100644 --- a/src/main/java/com/greate/community/entity/User.java +++ b/src/main/java/com/greate/community/entity/User.java @@ -1,6 +1,7 @@ package com.greate.community.entity; import lombok.Data; +import lombok.ToString; import java.util.Date; @@ -9,6 +10,7 @@ import java.util.Date; * 对应数据库表 `user` */ @Data +@ToString public class User { private int id; @@ -30,28 +32,4 @@ public class User { private int auditStatus; private Date createTime; - @Override - public String toString() { - return "User{" + - "id=" + id + - ", username='" + username + '\'' + - ", password='" + password + '\'' + - ", salt='" + salt + '\'' + - ", email='" + email + '\'' + - ", exp='" + exp + '\'' + - ", level='" + level + '\'' + - ", type=" + type + - ", status=" + status + - ", activationCode='" + activationCode + '\'' + - ", headerUrl='" + headerUrl + '\'' + - ", studentCardUrl=" + studentCardUrl + - ", studentCode=" + studentCode + - ", realName=" + realName + - ", institute=" + institute + - ", professionalClass=" + professionalClass + - ", createTime=" + createTime + - ", auditStatus=" + auditStatus + - '}'; - } - } diff --git a/src/main/java/com/greate/community/service/LikeService.java b/src/main/java/com/greate/community/service/LikeService.java index 3237627..fa70762 100644 --- a/src/main/java/com/greate/community/service/LikeService.java +++ b/src/main/java/com/greate/community/service/LikeService.java @@ -1,5 +1,6 @@ package com.greate.community.service; +import com.greate.community.dao.LikeMapper; import com.greate.community.util.RedisKeyUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; @@ -17,6 +18,9 @@ public class LikeService { @Autowired private RedisTemplate redisTemplate; + @Autowired + private LikeMapper likeMapper; + /** * 点赞 * diff --git a/src/main/java/com/greate/community/util/CosStsClientUtil.java b/src/main/java/com/greate/community/util/CosStsClientUtil.java index 5aa75c6..7458c3d 100644 --- a/src/main/java/com/greate/community/util/CosStsClientUtil.java +++ b/src/main/java/com/greate/community/util/CosStsClientUtil.java @@ -55,6 +55,7 @@ public class CosStsClientUtil { // 临时密钥有效时长,单位是秒,默认 1800 秒,目前主账号最长 2 小时(即 7200 秒),子账号最长 36 小时(即 129600)秒 config.put("durationSeconds", 1800); + // todo 分桶 // bucket名称 config.put("bucket", "test-1306812178"); // bucket所在地区 diff --git a/src/main/resources/mapper/like-mapper.xml b/src/main/resources/mapper/like-mapper.xml new file mode 100644 index 0000000..b39d313 --- /dev/null +++ b/src/main/resources/mapper/like-mapper.xml @@ -0,0 +1,30 @@ + + + + + + + user_id, entity_type, entity_id, entity_user_id, create_time + + + + insert into `like` () + values(#{userId}, #{entityType}, #{entityId}, #{entityUserId}, #{createTime}) + + + + + + \ No newline at end of file -- Gitee From 13ed4996c2e0edbf76f61e44015689ed8a673bef Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Mon, 14 Feb 2022 14:39:45 +0800 Subject: [PATCH 026/125] =?UTF-8?q?=E4=BF=AE=E6=94=B9fastjson=E6=97=A5?= =?UTF-8?q?=E6=9C=9F=E6=95=B0=E6=8D=AE=E8=BF=94=E5=9B=9E=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?-=E8=A7=A3=E5=86=B3=E6=9C=AA=E7=99=BB=E5=BD=95=E6=97=B6BaseCont?= =?UTF-8?q?roller=E4=B8=ADgetUser=E6=96=B9=E6=B3=95=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/greate/community/CommunityApplication.java | 3 +++ .../community/controller/BaseController.java | 14 +++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/greate/community/CommunityApplication.java b/src/main/java/com/greate/community/CommunityApplication.java index 110d6a1..361e0ae 100644 --- a/src/main/java/com/greate/community/CommunityApplication.java +++ b/src/main/java/com/greate/community/CommunityApplication.java @@ -29,7 +29,10 @@ public class CommunityApplication { public HttpMessageConverters fastJsonHttpMessageConverters() { FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); FastJsonConfig fastJsonConfig = new FastJsonConfig(); + // SerializerFeature.WriteMapNullValue 指定value为null的key输出到前端 fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat,SerializerFeature.WriteMapNullValue); + //全局指定日期格式 + fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss"); fastConverter.setFastJsonConfig(fastJsonConfig); HttpMessageConverter converter = fastConverter; return new HttpMessageConverters(converter); diff --git a/src/main/java/com/greate/community/controller/BaseController.java b/src/main/java/com/greate/community/controller/BaseController.java index 79ef913..0e6474c 100644 --- a/src/main/java/com/greate/community/controller/BaseController.java +++ b/src/main/java/com/greate/community/controller/BaseController.java @@ -14,6 +14,18 @@ import org.springframework.security.core.context.SecurityContextHolder; public class BaseController { protected User getUser() { - return (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); +// return (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + + Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + /** + * 当未登录时,SecurityContextHolder.getContext().getAuthentication().getPrincipal()返回值 + * 为String类型字符串 "anonymousUser" ,无法直接转成 User 类型,会抛出异常,这里做一定处理 + */ + if("anonymousUser".equals(principal)){ + return null; + } + else { + return (User) principal; + } } } -- Gitee From a02889fb5f16f95055746d60cd5423c760f98ef4 Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Mon, 14 Feb 2022 16:18:56 +0800 Subject: [PATCH 027/125] update like service with redis and mysql --- .../community/controller/UserController.java | 4 +- .../com/greate/community/dao/LikeMapper.java | 13 ++++ .../com/greate/community/entity/Like.java | 4 +- .../greate/community/service/LikeService.java | 69 +++++++++++++++---- .../greate/community/util/RedisKeyUtil.java | 33 +++++++-- src/main/resources/mapper/like-mapper.xml | 8 +++ 6 files changed, 111 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 3c16e99..206cbd5 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -71,7 +71,7 @@ public class UserController extends BaseController implements CommunityConstant // 用户 jsonObject.put("user", user); // 获赞数量 - int userLikeCount = likeService.findUserLikeCount(user.getId()); + long userLikeCount = likeService.findUserLikeCount(user.getId()); jsonObject.put("userLikeCount", userLikeCount); // 关注数量 long followeeCount = followService.findFolloweeCount(user.getId(), ENTITY_TYPE_USER); @@ -148,7 +148,7 @@ public class UserController extends BaseController implements CommunityConstant // 用户 jsonObject.put("user", user); // 获赞数量 - int userLikeCount = likeService.findUserLikeCount(userId); + long userLikeCount = likeService.findUserLikeCount(userId); jsonObject.put("userLikeCount", userLikeCount); // 关注数量 long followeeCount = followService.findFolloweeCount(userId, ENTITY_TYPE_USER); diff --git a/src/main/java/com/greate/community/dao/LikeMapper.java b/src/main/java/com/greate/community/dao/LikeMapper.java index a1bdbf2..bb6fb6c 100644 --- a/src/main/java/com/greate/community/dao/LikeMapper.java +++ b/src/main/java/com/greate/community/dao/LikeMapper.java @@ -8,6 +8,7 @@ public interface LikeMapper { /** * 插入点赞记录 + * * @param like * @return */ @@ -15,15 +16,27 @@ public interface LikeMapper { /** * 查询用户是否点赞某个实体 + * * @return */ int countLikeByUserIdAndEntity(int userId, int entityType, int entityId); /** * 查询某个实体点赞数量 + * * @param entityType * @param entityId * @return */ int countLikeByEntity(int entityType, int entityId); + + /** + * 删除点赞 + * + * @param userId + * @param entityType + * @param entityId + * @return + */ + int deleteLikeByUserIdAndEntity(int userId, int entityType, int entityId); } diff --git a/src/main/java/com/greate/community/entity/Like.java b/src/main/java/com/greate/community/entity/Like.java index 22ae263..7d16213 100644 --- a/src/main/java/com/greate/community/entity/Like.java +++ b/src/main/java/com/greate/community/entity/Like.java @@ -19,8 +19,8 @@ public class Like { private int id; private int userId; // 点赞用户 id - private String entityType; // 点赞实体类型 + private int entityType; // 点赞实体类型 private int entityId; // 点赞实体 id - private String entityUserId; // 点赞实体对应用户 id + private int entityUserId; // 点赞实体对应用户 id private Date createTime; } diff --git a/src/main/java/com/greate/community/service/LikeService.java b/src/main/java/com/greate/community/service/LikeService.java index fa70762..a71b643 100644 --- a/src/main/java/com/greate/community/service/LikeService.java +++ b/src/main/java/com/greate/community/service/LikeService.java @@ -1,6 +1,7 @@ package com.greate.community.service; import com.greate.community.dao.LikeMapper; +import com.greate.community.entity.Like; import com.greate.community.util.RedisKeyUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; @@ -9,6 +10,8 @@ import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.SessionCallback; import org.springframework.stereotype.Service; +import java.util.Date; + /** * 点赞相关 */ @@ -30,24 +33,41 @@ public class LikeService { * @param entityUserId 点赞实体对应用户 id */ public void like(int userId, int entityType, int entityId, int entityUserId) { + // 判断是否点过赞 + int likeStatus = findEntityLikeStatus(userId, entityType, entityId); + + if (likeStatus == 1) { + // 如果用户已经点过赞,点第二次则取消赞 + likeMapper.deleteLikeByUserIdAndEntity(userId, entityType, entityId); + } else { + Like like = new Like(); + like.setUserId(userId); + like.setEntityType(entityType); + like.setEntityId(entityId); + like.setEntityUserId(entityUserId); + like.setCreateTime(new Date()); + likeMapper.insertLike(like); + } + + // 处理 redis redisTemplate.execute(new SessionCallback() { @Override public Object execute(RedisOperations redisOperations) throws DataAccessException { + String userIdOfLikeKey = RedisKeyUtil.getUserIdOfLikeKey(entityType, entityId); String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId); String userLikeKey = RedisKeyUtil.getUserLikeKey(entityUserId); - // 判断用户是否已经点过赞了 - boolean isMember = redisOperations.opsForSet().isMember(entityLikeKey, userId); - redisOperations.multi(); // 开启事务 - if (isMember) { + if (likeStatus == 1) { // 如果用户已经点过赞,点第二次则取消赞 - redisOperations.opsForSet().remove(entityLikeKey, userId); - redisOperations.opsForValue().decrement(userLikeKey); + redisOperations.opsForSet().remove(userIdOfLikeKey, userId); // 删除实体对应的点赞 userId + redisOperations.opsForValue().decrement(entityLikeKey); // 实体获赞数量-1 + redisOperations.opsForValue().decrement(userLikeKey); // 用户获赞数量-1 } else { - redisTemplate.opsForSet().add(entityLikeKey, userId); - redisOperations.opsForValue().increment(userLikeKey); + redisOperations.opsForSet().add(userIdOfLikeKey, userId); // 删除实体对应的点赞 userId + redisOperations.opsForValue().increment(entityLikeKey); // 实体获赞数量+1 + redisOperations.opsForValue().increment(userLikeKey); // 用户获赞数量+1 } return redisOperations.exec(); // 提交事务 @@ -63,8 +83,21 @@ public class LikeService { * @return */ public long findEntityLikeCount(int entityType, int entityId) { + long count = 0; String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId); - return redisTemplate.opsForSet().size(entityLikeKey); + + if (redisTemplate.hasKey(entityLikeKey)) { + // redis 中查询 + Integer num = (Integer) redisTemplate.opsForValue().get(entityLikeKey); + count = num == null ? 0 : num; + } else { + // mysql 中查询 + count = likeMapper.countLikeByEntity(entityType, entityId); + // 找到了之后存入 redis + redisTemplate.opsForValue().set(entityLikeKey, count); + } + + return count; } /** @@ -76,8 +109,19 @@ public class LikeService { * @return 1:已赞,0:未赞 */ public int findEntityLikeStatus(int userId, int entityType, int entityId) { - String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId); - return redisTemplate.opsForSet().isMember(entityLikeKey, userId) ? 1 : 0; + int likeStatus = 0; + // 查询 redis + String userIdOfLikeKey = RedisKeyUtil.getUserIdOfLikeKey(entityType, entityId); + if (redisTemplate.hasKey(userIdOfLikeKey)) { + // redis 中找 + likeStatus = redisTemplate.opsForSet().isMember(userIdOfLikeKey, userId) ? 1 : 0; + } else { + // mysql 中找 + likeStatus = likeMapper.countLikeByUserIdAndEntity(userId, entityType, entityId) > 0 ? 1 : 0; + // 找到了之后存入 redis + redisTemplate.opsForSet().add(userIdOfLikeKey, userId); + } + return likeStatus; } /** @@ -86,7 +130,8 @@ public class LikeService { * @param userId * @return */ - public int findUserLikeCount(int userId) { + public long findUserLikeCount(int userId) { + // todo 将用户获赞数存入 mysql user 表中 String userLikeKey = RedisKeyUtil.getUserLikeKey(userId); Integer count = (Integer) redisTemplate.opsForValue().get(userLikeKey); return count == null ? 0 : count; diff --git a/src/main/java/com/greate/community/util/RedisKeyUtil.java b/src/main/java/com/greate/community/util/RedisKeyUtil.java index e722a84..ac57dbb 100644 --- a/src/main/java/com/greate/community/util/RedisKeyUtil.java +++ b/src/main/java/com/greate/community/util/RedisKeyUtil.java @@ -6,6 +6,7 @@ package com.greate.community.util; public class RedisKeyUtil { private static final String SPLIT = ":"; + private static final String PREFIX_USER_ID_LIKE = "like:userId"; // 点赞的用户id private static final String PREFIX_ENTITY_LIKE = "like:entity"; // 实体的获赞 private static final String PREFIX_USER_LIKE = "like:user"; // 用户的获赞 private static final String PREFIX_FOLLOWER = "follower"; // 被关注(粉丝) @@ -18,9 +19,22 @@ public class RedisKeyUtil { private static final String PREFIX_POST = "post"; // 用于统计帖子分数 /** - * 某个实体(帖子、评论/回复)的获赞 + * 某个实体点赞的 userId * like:entity:entityType:entityId -> set(userId) - * 谁给这个实体点了赞,就将这个用户的id存到这个实体对应的集合里 + * 谁给这个实体点了赞,就将这个用户的 id 存到这个实体对应的集合里 + * + * @param entityType + * @param entityId + * @return + */ + public static String getUserIdOfLikeKey(int entityType, int entityId) { + return PREFIX_USER_ID_LIKE + SPLIT + entityType + SPLIT + entityId; + } + + /** + * 某个实体(帖子、评论/回复)的获赞数量 + * like:entity:entityType:entityId -> int + * * @param entityType * @param entityId * @return @@ -32,6 +46,7 @@ public class RedisKeyUtil { /** * 某个用户的获赞数量 * like:user:userId -> int + * * @param userId 获赞用户的 id * @return */ @@ -42,6 +57,7 @@ public class RedisKeyUtil { /** * 某个用户关注的实体 * followee:userId:entityType -> zset(entityId, now) 以当前关注的时间进行排序 + * * @param userId * @param entityType 关注的实体类型 * @return @@ -53,16 +69,18 @@ public class RedisKeyUtil { /** * 某个实体拥有的粉丝 * follower:entityType:entityId -> zset(userId, now) + * * @param entityType * @param entityId * @return */ - public static String getFollowerKey(int entityType, int entityId) { + public static String getFollowerKey(int entityType, int entityId) { return PREFIX_FOLLOWER + SPLIT + entityType + SPLIT + entityId; - } + } /** * 登录验证码(指定这个验证码是针对哪个用户的) + * * @param owner 用户进入登录页面的时候,由于此时用户还未登录,无法通过 id 标识用户 * 随机生成一个字符串,短暂的存入 cookie,使用这个字符串来标识这个用户 * @return @@ -73,6 +91,7 @@ public class RedisKeyUtil { /** * 登陆凭证 + * * @param ticket * @return */ @@ -82,6 +101,7 @@ public class RedisKeyUtil { /** * 用户信息 + * * @param userId * @return */ @@ -91,6 +111,7 @@ public class RedisKeyUtil { /** * 单日 UV + * * @param date * @return */ @@ -100,6 +121,7 @@ public class RedisKeyUtil { /** * 区间 UV + * * @param startDate * @param endDate * @return @@ -110,6 +132,7 @@ public class RedisKeyUtil { /** * 单日 DAU + * * @param date * @return */ @@ -119,6 +142,7 @@ public class RedisKeyUtil { /** * 区间 DAU + * * @param startDate * @param endDate * @return @@ -129,6 +153,7 @@ public class RedisKeyUtil { /** * 帖子分数 + * * @return */ public static String getPostScoreKey() { diff --git a/src/main/resources/mapper/like-mapper.xml b/src/main/resources/mapper/like-mapper.xml index b39d313..0718620 100644 --- a/src/main/resources/mapper/like-mapper.xml +++ b/src/main/resources/mapper/like-mapper.xml @@ -27,4 +27,12 @@ where entity_type = #{entityType} and entity_user_id = #{entityId} + + + delete * + from `like` + where user_id = #{userId} + and entity_type = #{entityType} + and entity_user_id = #{entityId} + \ No newline at end of file -- Gitee From 090b5fe7c08d7d124d629243a563ffffdb99bca7 Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Mon, 14 Feb 2022 17:10:05 +0800 Subject: [PATCH 028/125] fix: select comment by user id and some like problem --- .../community/controller/LikeController.java | 2 +- .../community/controller/UserController.java | 7 ++- .../com/greate/community/dao/LikeMapper.java | 2 +- .../greate/community/service/LikeService.java | 2 +- src/main/resources/mapper/like-mapper.xml | 15 ++++--- .../com/greate/community/LikeServiceTest.java | 44 +++++++++++++++++++ .../java/com/greate/community/MailTests.java | 25 ----------- 7 files changed, 61 insertions(+), 36 deletions(-) create mode 100644 src/test/java/com/greate/community/LikeServiceTest.java delete mode 100644 src/test/java/com/greate/community/MailTests.java diff --git a/src/main/java/com/greate/community/controller/LikeController.java b/src/main/java/com/greate/community/controller/LikeController.java index e9d9320..f9cd96c 100644 --- a/src/main/java/com/greate/community/controller/LikeController.java +++ b/src/main/java/com/greate/community/controller/LikeController.java @@ -53,7 +53,7 @@ public class LikeController extends BaseController implements CommunityConstant log.info("点赞用户: " + user.toString()); // 点赞 - likeService.like(user.getId(), entityType, entityId, entityUserId); + likeService.insertLike(user.getId(), entityType, entityId, entityUserId); // 点赞数量 long likeCount = likeService.findEntityLikeCount(entityType, entityId); // 点赞状态 diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 206cbd5..2f0b3a4 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -7,6 +7,7 @@ import com.greate.community.service.*; import com.greate.community.util.CommunityConstant; import com.greate.community.util.CommunityUtil; import com.qiniu.util.Auth; +import com.qiniu.util.Json; import com.qiniu.util.StringMap; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -255,9 +256,13 @@ public class UserController extends BaseController implements CommunityConstant //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 map.put("post", discussPostService.toDiscussPostJsonObject(post)); } else if (comment.getEntityType() == ENTITY_TYPE_COMMENT) { + JSONObject parent = new JSONObject(); // 如过是对评论的回复,则先根据该回复的 target_id 查询评论的 id, 再根据该评论的 target_id 查询帖子的 id Comment targetComment = commentService.findCommentById(comment.getEntityId()); - map.put("parent", targetComment); + parent.put("comment", targetComment); + User parentUser = userService.findUserById(targetComment.getUserId()); + parent.put("user", parentUser); + map.put("parent", parent); DiscussPost post = discussPostService.findDiscussPostById(targetComment.getEntityId()); //map.put("post", post); //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 diff --git a/src/main/java/com/greate/community/dao/LikeMapper.java b/src/main/java/com/greate/community/dao/LikeMapper.java index bb6fb6c..b0d0991 100644 --- a/src/main/java/com/greate/community/dao/LikeMapper.java +++ b/src/main/java/com/greate/community/dao/LikeMapper.java @@ -35,7 +35,7 @@ public interface LikeMapper { * * @param userId * @param entityType - * @param entityId + * @param entityUserId * @return */ int deleteLikeByUserIdAndEntity(int userId, int entityType, int entityId); diff --git a/src/main/java/com/greate/community/service/LikeService.java b/src/main/java/com/greate/community/service/LikeService.java index a71b643..4880aba 100644 --- a/src/main/java/com/greate/community/service/LikeService.java +++ b/src/main/java/com/greate/community/service/LikeService.java @@ -32,7 +32,7 @@ public class LikeService { * @param entityId 点赞实体 id * @param entityUserId 点赞实体对应用户 id */ - public void like(int userId, int entityType, int entityId, int entityUserId) { + public void insertLike(int userId, int entityType, int entityId, int entityUserId) { // 判断是否点过赞 int likeStatus = findEntityLikeStatus(userId, entityType, entityId); diff --git a/src/main/resources/mapper/like-mapper.xml b/src/main/resources/mapper/like-mapper.xml index 0718620..f52a769 100644 --- a/src/main/resources/mapper/like-mapper.xml +++ b/src/main/resources/mapper/like-mapper.xml @@ -4,8 +4,9 @@ - - user_id, entity_type, entity_id, entity_user_id, create_time + + user_id + , entity_type, entity_id, entity_user_id, create_time @@ -13,7 +14,7 @@ values(#{userId}, #{entityType}, #{entityId}, #{entityUserId}, #{createTime}) - select count(id) from `like` where user_id = #{userId} @@ -21,7 +22,7 @@ and entity_user_id = #{entityId} - select count(id) from `like` where entity_type = #{entityType} @@ -29,10 +30,10 @@ - delete * + delete from `like` where user_id = #{userId} - and entity_type = #{entityType} - and entity_user_id = #{entityId} + and entity_type = #{entityType} + and entity_id = #{entityId} \ No newline at end of file diff --git a/src/test/java/com/greate/community/LikeServiceTest.java b/src/test/java/com/greate/community/LikeServiceTest.java new file mode 100644 index 0000000..0b8c517 --- /dev/null +++ b/src/test/java/com/greate/community/LikeServiceTest.java @@ -0,0 +1,44 @@ +package com.greate.community; + +import com.greate.community.service.LikeService; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@Slf4j +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes=CommunityApplication.class) +public class LikeServiceTest { + + @Autowired + private LikeService likeService; + + @Test + public void insertLikeTest() { + likeService.insertLike(101, 1, 1, 101); + likeService.insertLike(101, 1, 2, 101); + likeService.insertLike(101, 1, 3, 101); + + likeService.insertLike(101, 1, 1, 101); + } + + @Test + public void findEntityLikeCountTest() { + log.info(String.valueOf(likeService.findEntityLikeCount(1, 1))); + log.info(String.valueOf(likeService.findEntityLikeCount(1, 2))); + } + + @Test + public void findEntityLikeStatusTest() { + log.info(String.valueOf(likeService.findEntityLikeStatus(101, 1, 1))); + log.info(String.valueOf(likeService.findEntityLikeStatus(101, 1, 2))); + } + + @Test + public void findUserLikeCountTest() { + + } +} diff --git a/src/test/java/com/greate/community/MailTests.java b/src/test/java/com/greate/community/MailTests.java deleted file mode 100644 index bb1bcf3..0000000 --- a/src/test/java/com/greate/community/MailTests.java +++ /dev/null @@ -1,25 +0,0 @@ -//package com.greate.community; -// -//import com.greate.community.util.EmailUtil; -//import com.greate.community.util.MailClient; -//import lombok.ToString; -//import org.junit.Test; -//import org.junit.runner.RunWith; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.boot.test.context.SpringBootTest; -//import org.springframework.test.context.ContextConfiguration; -//import org.springframework.test.context.junit4.SpringRunner; -// -//@RunWith(SpringRunner.class) -//@ContextConfiguration(classes = CommunityApplication.class) -//@SpringBootTest -//public class MailTests { -// -// @Autowired -// private EmailUtil emailUtil; -// -// @Test -// public void sendEmail() { -// emailUtil.sendRegistrationCode("2224236998@qq.com"); -// } -//} -- Gitee From 62bc451613b6db7258e6b9d931731e43e4ef2bde Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Mon, 14 Feb 2022 19:02:43 +0800 Subject: [PATCH 029/125] fix like problem --- .../com/greate/community/service/LikeService.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/greate/community/service/LikeService.java b/src/main/java/com/greate/community/service/LikeService.java index 4880aba..182ea9d 100644 --- a/src/main/java/com/greate/community/service/LikeService.java +++ b/src/main/java/com/greate/community/service/LikeService.java @@ -112,14 +112,15 @@ public class LikeService { int likeStatus = 0; // 查询 redis String userIdOfLikeKey = RedisKeyUtil.getUserIdOfLikeKey(entityType, entityId); - if (redisTemplate.hasKey(userIdOfLikeKey)) { - // redis 中找 - likeStatus = redisTemplate.opsForSet().isMember(userIdOfLikeKey, userId) ? 1 : 0; - } else { + likeStatus = redisTemplate.opsForSet().isMember(userIdOfLikeKey, userId) ? 1 : 0; + + if (likeStatus == 0) { // mysql 中找 likeStatus = likeMapper.countLikeByUserIdAndEntity(userId, entityType, entityId) > 0 ? 1 : 0; // 找到了之后存入 redis - redisTemplate.opsForSet().add(userIdOfLikeKey, userId); + if (likeStatus == 1) { + redisTemplate.opsForSet().add(userIdOfLikeKey, userId); + } } return likeStatus; } -- Gitee From f850a59f5d1ea3846bf8c96571c86124559631ae Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Thu, 17 Feb 2022 18:33:54 +0800 Subject: [PATCH 030/125] update: get message list --- .../controller/MessageController.java | 38 +++++++++++-------- .../community/service/MessageService.java | 2 +- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/greate/community/controller/MessageController.java b/src/main/java/com/greate/community/controller/MessageController.java index 17045ee..43bbbfd 100644 --- a/src/main/java/com/greate/community/controller/MessageController.java +++ b/src/main/java/com/greate/community/controller/MessageController.java @@ -2,18 +2,13 @@ package com.greate.community.controller; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.greate.community.entity.Message; -import com.greate.community.entity.Page; -import com.greate.community.entity.Result; -import com.greate.community.entity.User; +import com.greate.community.entity.*; +import com.greate.community.service.CommentService; +import com.greate.community.service.DiscussPostService; import com.greate.community.service.MessageService; import com.greate.community.service.UserService; import com.greate.community.util.CommunityConstant; -import com.greate.community.util.CommunityUtil; -import com.greate.community.util.HostHolder; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import org.springframework.web.util.HtmlUtils; @@ -31,6 +26,12 @@ public class MessageController extends BaseController implements CommunityConsta @Autowired private UserService userService; + @Autowired + private DiscussPostService discussPostService; + + @Autowired + private CommentService commentService; + /** * 私信列表 * @@ -48,7 +49,7 @@ public class MessageController extends BaseController implements CommunityConsta // page.setLimit(5);//前端注入 page.setPath("/letter/list"); // 查询会话总数 - page.setRows(messageService.findConversationCout(user.getId())); + page.setRows(messageService.findConversationCount(user.getId())); // 私信列表 List conversationList = messageService.findConversations(user.getId(), page.getOffset(), page.getLimit()); @@ -92,7 +93,6 @@ public class MessageController extends BaseController implements CommunityConsta JSONObject jsonObject = new JSONObject(); // 分页信息 -// page.setLimit(5);//前端注入 page.setPath("/letter/detail/" + conversationId); page.setRows(messageService.findLetterCount(conversationId)); @@ -108,7 +108,7 @@ public class MessageController extends BaseController implements CommunityConsta letters.add(map); } } -// jsonObject.put("letters", letters); + JSONArray result = (JSONArray) JSONArray.toJSON(letters); page.setResult(result); jsonObject.put("letters", page); @@ -298,7 +298,6 @@ public class MessageController extends BaseController implements CommunityConsta public Result getNoticeDetail(@PathVariable("topic") String topic, Page page) { User user = getUser(); -// page.setLimit(5);//前端注入 page.setPath("/notice/detail/" + topic); page.setRows(messageService.findNoticeCount(user.getId(), topic)); @@ -313,10 +312,17 @@ public class MessageController extends BaseController implements CommunityConsta // 内容 String content = HtmlUtils.htmlUnescape(notice.getContent()); Map data = JSONObject.parseObject(content, HashMap.class); - map.put("user", userService.findUserById((Integer) data.get("userId"))); - map.put("entityType", data.get("entityType")); - map.put("entityId", data.get("entityId")); - map.put("postId", data.get("postId")); + map.put("user", userService.findUserById((Integer) data.get("userId"))); // 发送消息的用户 + map.put("entityType", data.get("entityType")); // 实体类型 + map.put("entityId", data.get("entityId")); // 实体id + if ((Integer) data.get("entityType") == 2) { // 若为评论或者回复 + Comment comment = commentService.findCommentById((Integer) data.get("entityId")); + map.put("comment", comment); + if (comment.getEntityType() == 2) { // 若为回复,继续查找父评论 + map.put("parent", commentService.findCommentById(comment.getEntityId())); + } + } + map.put("post", discussPostService.findDiscussPostById((Integer) data.get("postId"))); // 帖子 // 发送系统通知的作者 map.put("fromUser", userService.findUserById(notice.getFromId())); diff --git a/src/main/java/com/greate/community/service/MessageService.java b/src/main/java/com/greate/community/service/MessageService.java index c9f43b1..af27519 100644 --- a/src/main/java/com/greate/community/service/MessageService.java +++ b/src/main/java/com/greate/community/service/MessageService.java @@ -37,7 +37,7 @@ public class MessageService { * @param userId * @return */ - public int findConversationCout(int userId) { + public int findConversationCount(int userId) { return messageMapper.selectConversationCount(userId); } -- Gitee From 75356c8743431082606ec7caf4fde201cc780fba Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Thu, 17 Feb 2022 21:59:16 +0800 Subject: [PATCH 031/125] fix: get message --- .../community/controller/MessageController.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/greate/community/controller/MessageController.java b/src/main/java/com/greate/community/controller/MessageController.java index 43bbbfd..fe1f2e8 100644 --- a/src/main/java/com/greate/community/controller/MessageController.java +++ b/src/main/java/com/greate/community/controller/MessageController.java @@ -69,7 +69,7 @@ public class MessageController extends BaseController implements CommunityConsta JSONArray result = (JSONArray) JSONArray.toJSON(conversations); page.setResult(result); - jsonObject.put("conversations",page); + jsonObject.put("conversations", page); // 查询当前用户的所有未读私信数量 int letterUnreadCount = messageService.findLetterUnreadCount(user.getId(), null); @@ -315,14 +315,20 @@ public class MessageController extends BaseController implements CommunityConsta map.put("user", userService.findUserById((Integer) data.get("userId"))); // 发送消息的用户 map.put("entityType", data.get("entityType")); // 实体类型 map.put("entityId", data.get("entityId")); // 实体id - if ((Integer) data.get("entityType") == 2) { // 若为评论或者回复 + // 若为评论或者回复的消息 + if (Objects.equals(notice.getConversationId(), TOPIC_COMMNET)) { + map.put("post", discussPostService.findDiscussPostById((Integer) data.get("postId"))); Comment comment = commentService.findCommentById((Integer) data.get("entityId")); map.put("comment", comment); - if (comment.getEntityType() == 2) { // 若为回复,继续查找父评论 + if (comment.getEntityType() == ENTITY_TYPE_COMMENT) { // 回复 map.put("parent", commentService.findCommentById(comment.getEntityId())); } } - map.put("post", discussPostService.findDiscussPostById((Integer) data.get("postId"))); // 帖子 + if (Objects.equals(notice.getConversationId(), TOPIC_LIKE)) { + // 帖子信息 + map.put("post", discussPostService.findDiscussPostById((Integer) data.get("postId"))); + } + // 发送系统通知的作者 map.put("fromUser", userService.findUserById(notice.getFromId())); -- Gitee From c2a4316716eb78352b5cde76023df3fe0704cbb8 Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Sun, 20 Feb 2022 14:40:31 +0800 Subject: [PATCH 032/125] update: comment --- .../controller/CommentController.java | 113 ++++++++++++++---- .../controller/DiscussPostController.java | 59 +-------- .../greate/community/dao/CommentMapper.java | 15 +++ .../com/greate/community/entity/Comment.java | 92 ++------------ .../com/greate/community/entity/Page.java | 5 - .../community/service/CommentService.java | 18 ++- .../community/service/DiscussPostService.java | 14 +-- .../greate/community/service/ExpService.java | 1 + .../community/util/StringListConvertor.java | 57 +++++++++ src/main/resources/mapper/comment-mapper.xml | 25 +++- 10 files changed, 224 insertions(+), 175 deletions(-) create mode 100644 src/main/java/com/greate/community/util/StringListConvertor.java diff --git a/src/main/java/com/greate/community/controller/CommentController.java b/src/main/java/com/greate/community/controller/CommentController.java index 5ce38cd..e84585a 100644 --- a/src/main/java/com/greate/community/controller/CommentController.java +++ b/src/main/java/com/greate/community/controller/CommentController.java @@ -1,21 +1,19 @@ package com.greate.community.controller; -import com.greate.community.entity.Comment; -import com.greate.community.entity.DiscussPost; -import com.greate.community.entity.Event; -import com.greate.community.entity.Result; +import com.alibaba.fastjson.JSONArray; +import com.greate.community.entity.*; import com.greate.community.event.EventProducer; import com.greate.community.service.CommentService; import com.greate.community.service.DiscussPostService; -import com.greate.community.util.CommunityConstant; -import com.greate.community.util.HostHolder; -import com.greate.community.util.RedisKeyUtil; +import com.greate.community.service.LikeService; +import com.greate.community.service.UserService; +import com.greate.community.util.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; -import java.util.Date; +import java.util.*; /** * 评论/回复 @@ -24,6 +22,12 @@ import java.util.Date; @RequestMapping("/comment") public class CommentController extends BaseController implements CommunityConstant { + @Autowired + private UserService userService; + + @Autowired + private LikeService likeService; + @Autowired private CommentService commentService; @@ -38,15 +42,23 @@ public class CommentController extends BaseController implements CommunityConsta /** * 添加评论 - * @param discussPostId - * @param comment - * @return */ - @PostMapping("/add/{discussPostId}") - @ResponseBody - public Result addComment(@PathVariable("discussPostId") int discussPostId, Comment comment) { + @PostMapping("/add") + public Result addComment(@RequestBody HashMap map) { + Comment comment = new Comment(); + + comment.setContent((String) map.get("content")); + comment.setPicUrls(StringListConvertor.join((List) map.get("picUrls"))); + comment.setEntityType((Integer) map.get("entityType")); + comment.setEntityId((Integer) map.get("entityId")); + if ((comment.getEntityType() == ENTITY_TYPE_COMMENT)) { + comment.setRootId((Integer) map.get("rootId")); + } + comment.setPostId((Integer) map.get("postId")); + comment.setTargetId((Integer) map.get("targetId")); + comment.setUserId(getUser().getId()); - comment.setStatus(0); + comment.setStatus(0); // 正常 comment.setCreateTime(new Date()); commentService.addComment(comment); @@ -56,12 +68,11 @@ public class CommentController extends BaseController implements CommunityConsta .setUserId(getUser().getId()) .setEntityType(comment.getEntityType()) .setEntityId(comment.getEntityId()) - .setData("postId", discussPostId); + .setData("postId", comment.getPostId()); if (comment.getEntityType() == ENTITY_TYPE_POST) { DiscussPost target = discussPostService.findDiscussPostById(comment.getEntityId()); event.setEntityUserId(target.getUserId()); - } - else if (comment.getEntityType() == ENTITY_TYPE_COMMENT) { + } else if (comment.getEntityType() == ENTITY_TYPE_COMMENT) { Comment target = commentService.findCommentById(comment.getEntityId()); event.setEntityUserId(target.getUserId()); } @@ -73,17 +84,75 @@ public class CommentController extends BaseController implements CommunityConsta .setTopic(TOPIC_PUBLISH) .setUserId(comment.getUserId()) .setEntityType(ENTITY_TYPE_POST) - .setEntityId(discussPostId); + .setEntityId(comment.getPostId()); eventProducer.fireEvent(event); // 计算帖子分数 String redisKey = RedisKeyUtil.getPostScoreKey(); - redisTemplate.opsForSet().add(redisKey, discussPostId); + redisTemplate.opsForSet().add(redisKey, comment.getPostId()); } - return new Result("success",Result.SUCCESS,"redirect:/discuss/detail/"+discussPostId); - + return new Result("success", Result.SUCCESS, "评论成功"); } + /** + * 获取帖子的评论列表 + */ + @GetMapping("/list/{discussPostId}") + public Result getCommentsByPostId(@PathVariable("discussPostId") int discussPostId, Page page) { + page.setPath("/comment/get/" + discussPostId); + + // 帖子的评论列表 + List commentList = commentService.findCommentByEntity( + ENTITY_TYPE_POST, discussPostId, page.getOffset(), page.getLimit()); + + // 封装评论及其相关信息 + List> commentVoList = new ArrayList<>(); + if (commentList != null) { + for (Comment comment : commentList) { + Map commentVo = new HashMap<>(); + commentVo.put("comment", StringListConvertor.toJsonObject(comment, "picUrls")); // 评论 + commentVo.put("user", userService.findUserById(comment.getUserId())); // 发布评论的作者 + long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_COMMENT, comment.getId()); // 该评论点赞数量 + commentVo.put("likeCount", likeCount); + int likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( + getUser().getId(), ENTITY_TYPE_COMMENT, comment.getId()); // 当前登录用户对该评论的点赞状态 + commentVo.put("likeStatus", likeStatus); + + // 存储每个评论对应的回复(不做分页) + // todo: 对回复做分页和排序处理 + List replyList = commentService.findReplyByComment( + comment.getId(), 0, Integer.MAX_VALUE); + List> replyVoList = new ArrayList<>(); // 封装对评论的评论和评论的作者信息 + if (replyList != null) { + for (Comment reply : replyList) { + Map replyVo = new HashMap<>(); + replyVo.put("reply", StringListConvertor.toJsonObject(reply, "picUrls")); // 回复 + replyVo.put("user", userService.findUserById(reply.getUserId())); // 发布该回复的作者 + User target = reply.getTargetId() == 0 ? null : userService.findUserById(reply.getTargetId()); + replyVo.put("target", target); // 该回复的目标用户 + likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_COMMENT, reply.getId()); + replyVo.put("likeCount", likeCount); // 该回复的点赞数量 + likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( + getUser().getId(), ENTITY_TYPE_COMMENT, reply.getId()); + replyVo.put("likeStatus", likeStatus); // 当前登录用户的点赞状态 + + replyVoList.add(replyVo); + } + } + commentVo.put("replys", replyVoList); + // 每个评论对应的回复数量 + int replyCount = commentService.findReplyCount(comment.getId()); + commentVo.put("replyCount", replyCount); + + commentVoList.add(commentVo); + } + } + + JSONArray result = (JSONArray) JSONArray.toJSON(commentVoList); + page.setResult(result); + + return new Result("success", Result.SUCCESS, page); + } } diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index 5b1c604..1b609c4 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -103,7 +103,7 @@ public class DiscussPostController extends BaseController implements CommunityCo */ @GetMapping("/detail/{discussPostId}") @ResponseBody - public Result getDiscussPost(@PathVariable("discussPostId") int discussPostId, Page page) { + public Result getDiscussPost(@PathVariable("discussPostId") int discussPostId) { HashMap resultMap = new HashMap<>(); // 帖子 @@ -127,62 +127,7 @@ public class DiscussPostController extends BaseController implements CommunityCo likeService.findEntityLikeStatus(getUser().getId(), ENTITY_TYPE_POST, discussPostId); resultMap.put("likeStatus", likeStatus); - // 评论分页信息 - page.setPath("/discuss/detail/" + discussPostId); - page.setRows(discussPost.getCommentCount()); - - // 帖子的评论列表 - List commentList = commentService.findCommentByEntity(ENTITY_TYPE_POST, discussPost.getId(), page.getOffset(), page.getLimit()); - - // 封装评论及其相关信息 - List> commentVoList = new ArrayList<>(); - if (commentList != null) { - for (Comment comment : commentList) { - // 存储对帖子的评论 - Map commentVo = new HashMap<>(); - commentVo.put("comment", comment); // 评论 - commentVo.put("user", userService.findUserById(comment.getUserId())); // 发布评论的作者 - likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_COMMENT, comment.getId()); // 该评论点赞数量 - commentVo.put("likeCount", likeCount); - likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( - getUser().getId(), ENTITY_TYPE_COMMENT, comment.getId()); // 当前登录用户对该评论的点赞状态 - commentVo.put("likeStatus", likeStatus); - - // 存储每个评论对应的回复(不做分页) - List replyList = commentService.findCommentByEntity( - ENTITY_TYPE_COMMENT, comment.getId(), 0, Integer.MAX_VALUE); - List> replyVoList = new ArrayList<>(); // 封装对评论的评论和评论的作者信息 - if (replyList != null) { - for (Comment reply : replyList) { - Map replyVo = new HashMap<>(); - replyVo.put("reply", reply); // 回复 - replyVo.put("user", userService.findUserById(reply.getUserId())); // 发布该回复的作者 - User target = reply.getTargetId() == 0 ? null : userService.findUserById(reply.getTargetId()); - replyVo.put("target", target); // 该回复的目标用户 - likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_COMMENT, reply.getId()); - replyVo.put("likeCount", likeCount); // 该回复的点赞数量 - likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( - getUser().getId(), ENTITY_TYPE_COMMENT, reply.getId()); - replyVo.put("likeStatus", likeStatus); // 当前登录用户的点赞状态 - - replyVoList.add(replyVo); - } - } - commentVo.put("replys", replyVoList); - - // 每个评论对应的回复数量 - int replyCount = commentService.findCommentCount(ENTITY_TYPE_COMMENT, comment.getId()); - commentVo.put("replyCount", replyCount); - - commentVoList.add(commentVo); - } - } - - JSONArray result = (JSONArray) JSONArray.toJSON(commentVoList); - page.setResult(result); - resultMap.put("comments",page); - - //增加经验 + // 增加浏览帖子经验 if (getUser() != null) { expService.handleGetExp(getUser().getId(), ExpType.EXP_BROWSE.getName()); } diff --git a/src/main/java/com/greate/community/dao/CommentMapper.java b/src/main/java/com/greate/community/dao/CommentMapper.java index 5921c33..ed5e1a9 100644 --- a/src/main/java/com/greate/community/dao/CommentMapper.java +++ b/src/main/java/com/greate/community/dao/CommentMapper.java @@ -25,6 +25,14 @@ public interface CommentMapper { */ List selectCommentByEntity(int entityType, int entityId, int offset, int limit); + /** + * 根据根评论对回复进行分页查询 + * @param rootId 根评论id + * @param offset 每页的起始索引 + * @param limit 每页显示多少条数据 + * @return + */ + List selectCommentByRootId(int rootId, int offset, int limit); /** * 查询评论的数量 @@ -34,6 +42,13 @@ public interface CommentMapper { */ int selectCountByEntity(int entityType, int entityId); + /** + * 查询回复的数量 + * @param rootId + * @return + */ + int selectCountByRootId(int rootId); + /** * 添加评论 * @param comment diff --git a/src/main/java/com/greate/community/entity/Comment.java b/src/main/java/com/greate/community/entity/Comment.java index 7f00ce7..a1ea516 100644 --- a/src/main/java/com/greate/community/entity/Comment.java +++ b/src/main/java/com/greate/community/entity/Comment.java @@ -1,103 +1,37 @@ package com.greate.community.entity; +import lombok.Data; +import lombok.ToString; + import java.util.Date; /** * 评论 */ +@Data +@ToString public class Comment { private int id; + // 内容 + private String content; + // 图片,用","分隔开 + private String picUrls; // 发布评论的作者 private int userId; // 评论目标的类型(帖子、评论) private int entityType; + // 回复的根评论 id + private int rootId; // 评论目标的 id private int entityId; // 指明对哪个用户进行评论(用户 id) private int targetId; - // 内容 - private String content; + // 帖子 id + private int postId; // 状态:0 正常,1 禁用 private int status; // 发布时间 private Date createTime; - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public int getUserId() { - return userId; - } - - public void setUserId(int userId) { - this.userId = userId; - } - - public int getEntityType() { - return entityType; - } - - public void setEntityType(int entityType) { - this.entityType = entityType; - } - - public int getEntityId() { - return entityId; - } - - public void setEntityId(int entityId) { - this.entityId = entityId; - } - - public int getTargetId() { - return targetId; - } - - public void setTargetId(int targetId) { - this.targetId = targetId; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - public int getStatus() { - return status; - } - - public void setStatus(int status) { - this.status = status; - } - - public Date getCreateTime() { - return createTime; - } - - public void setCreateTime(Date createTime) { - this.createTime = createTime; - } - - @Override - public String toString() { - return "Comment{" + - "id=" + id + - ", userId=" + userId + - ", entityType=" + entityType + - ", entityId=" + entityId + - ", targetId=" + targetId + - ", content='" + content + '\'' + - ", status=" + status + - ", createTime=" + createTime + - '}'; - } } diff --git a/src/main/java/com/greate/community/entity/Page.java b/src/main/java/com/greate/community/entity/Page.java index fb8e71c..99f41eb 100644 --- a/src/main/java/com/greate/community/entity/Page.java +++ b/src/main/java/com/greate/community/entity/Page.java @@ -66,11 +66,6 @@ public class Page { this.path = path; } - - - - - /** * 获取当前页的起始索引 offset * @return diff --git a/src/main/java/com/greate/community/service/CommentService.java b/src/main/java/com/greate/community/service/CommentService.java index 0e213cb..e1b429d 100644 --- a/src/main/java/com/greate/community/service/CommentService.java +++ b/src/main/java/com/greate/community/service/CommentService.java @@ -1,7 +1,10 @@ package com.greate.community.service; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; import com.greate.community.dao.CommentMapper; import com.greate.community.entity.Comment; +import com.greate.community.entity.DiscussPost; import com.greate.community.util.CommunityConstant; import com.greate.community.util.SensitiveFilter; import org.springframework.beans.factory.annotation.Autowired; @@ -37,7 +40,6 @@ public class CommentService implements CommunityConstant { return commentMapper.selectCommentById(id); } - /** * 根据评论目标(类别、id)对评论进行分页查询 * @param entityType @@ -50,6 +52,10 @@ public class CommentService implements CommunityConstant { return commentMapper.selectCommentByEntity(entityType, entityId, offset, limit); } + public List findReplyByComment(int rootId, int offset, int limit) { + return commentMapper.selectCommentByRootId(rootId, offset, limit); + } + /** * 查询评论的数量 * @param entityType @@ -60,6 +66,15 @@ public class CommentService implements CommunityConstant { return commentMapper.selectCountByEntity(entityType, entityId); } + /** + * 查询回复的数量 + * @param rootId + * @return + */ + public int findReplyCount(int rootId) { + return commentMapper.selectCountByRootId(rootId); + } + /** * 分页查询某个用户的评论/回复列表 * @param userId @@ -108,5 +123,4 @@ public class CommentService implements CommunityConstant { return rows; } - } diff --git a/src/main/java/com/greate/community/service/DiscussPostService.java b/src/main/java/com/greate/community/service/DiscussPostService.java index d664c9f..404e84a 100644 --- a/src/main/java/com/greate/community/service/DiscussPostService.java +++ b/src/main/java/com/greate/community/service/DiscussPostService.java @@ -169,7 +169,7 @@ public class DiscussPostService { /** * 修改帖子的评论数量 * - * @param id 帖子 id + * @param id 帖子 id * @param commentCount * @return */ @@ -216,20 +216,20 @@ public class DiscussPostService { * @param discussPost * @return */ - public JSONObject toDiscussPostJsonObject(DiscussPost discussPost){ - if(discussPost == null){ + public JSONObject toDiscussPostJsonObject(DiscussPost discussPost) { + if (discussPost == null) { return null; - }else { - if(("").equals(discussPost.getPicUrls())){ + } else { + if (("").equals(discussPost.getPicUrls())) { discussPost.setPicUrls(null); } JSONObject discussPostJsonObject = (JSONObject) JSONObject.toJSON(discussPost); String picUrls = discussPostJsonObject.getString("picUrls"); - if(picUrls!=null){ + if (picUrls != null) { String[] picUrlArray = picUrls.split(","); JSONArray picUrlJSONArray = (JSONArray) JSONArray.toJSON(picUrlArray); discussPostJsonObject.remove("picUrls"); - discussPostJsonObject.put("picUrls",picUrlJSONArray); + discussPostJsonObject.put("picUrls", picUrlJSONArray); } return discussPostJsonObject; } diff --git a/src/main/java/com/greate/community/service/ExpService.java b/src/main/java/com/greate/community/service/ExpService.java index 39a44c6..8e16f06 100644 --- a/src/main/java/com/greate/community/service/ExpService.java +++ b/src/main/java/com/greate/community/service/ExpService.java @@ -60,6 +60,7 @@ public class ExpService { } // 得到了经验值,记录本次经验值,并更新用户exp和rank + // todo: 需要做事务处理 if (exp_count > 0) { // 记录本次经验值 Exp exp = new Exp(); diff --git a/src/main/java/com/greate/community/util/StringListConvertor.java b/src/main/java/com/greate/community/util/StringListConvertor.java new file mode 100644 index 0000000..ebf48a2 --- /dev/null +++ b/src/main/java/com/greate/community/util/StringListConvertor.java @@ -0,0 +1,57 @@ +package com.greate.community.util; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.greate.community.entity.DiscussPost; +import com.sun.corba.se.spi.ior.ObjectKey; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; + +public class StringListConvertor { + + final static String separator = ","; + + /** + * 将列表List,转成字符串隔开,默认使用"," + * + * @param list + * @return + */ + public static String join(List list) { + String str = ""; + for (int i = 0; i < list.size(); i++) { + if (i > 0) { + str += separator; + } + str += list.get(i); + } + return str; + } + + /** + * 将对象中以 "," 分隔的字段转为json数组,并将对象转换成JSONObject返回 + * + * @param object + * @param key + * @return + */ + public static JSONObject toJsonObject(Object object, String key) { + if (object == null) { + return null; + } else { + JSONObject discussPostJsonObject = (JSONObject) JSONObject.toJSON(object); + String value = discussPostJsonObject.getString(key); + if (StringUtils.isNotEmpty(value.trim())) { + String[] picUrlArray = value.split(separator); + JSONArray picUrlJSONArray = (JSONArray) JSONArray.toJSON(picUrlArray); + discussPostJsonObject.remove(key); + discussPostJsonObject.put(key, picUrlJSONArray); + } else { + discussPostJsonObject.remove(key); + discussPostJsonObject.put(key, null); + } + return discussPostJsonObject; + } + } +} diff --git a/src/main/resources/mapper/comment-mapper.xml b/src/main/resources/mapper/comment-mapper.xml index b9058fc..3c493d3 100644 --- a/src/main/resources/mapper/comment-mapper.xml +++ b/src/main/resources/mapper/comment-mapper.xml @@ -5,11 +5,11 @@ - id, user_id, entity_type, entity_id, target_id, content, status, create_time + id, content, pic_urls, user_id, entity_type, entity_id, root_id, target_id, post_id, status, create_time - user_id, entity_type, entity_id, target_id, content, status, create_time + content, pic_urls, user_id, entity_type, entity_id, root_id, target_id, post_id, status, create_time + + + + + + + insert into comment() - values(#{userId}, #{entityType}, #{entityId}, #{targetId}, #{content}, #{status}, #{createTime}) + values(#{content}, #{picUrls}, #{userId}, #{entityType}, #{entityId}, #{rootId}, #{targetId}, #{postId}, #{status}, #{createTime}) -- Gitee From a19ca14fa15fce96b1b08efb7b712761a21158d3 Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Mon, 21 Feb 2022 11:24:15 +0800 Subject: [PATCH 033/125] update: cos file path --- .../java/com/greate/community/config/SecurityConfig.java | 1 - .../com/greate/community/controller/CosController.java | 5 +++-- src/main/java/com/greate/community/service/CosService.java | 7 ++----- .../java/com/greate/community/util/CosStsClientUtil.java | 1 - 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index b01cf77..1a3175f 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -80,7 +80,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm "/like", "/follow", "/unfollow", - "/cos/credential", "/exp/**" ) .hasAnyAuthority( diff --git a/src/main/java/com/greate/community/controller/CosController.java b/src/main/java/com/greate/community/controller/CosController.java index cb45fdf..c4945f1 100644 --- a/src/main/java/com/greate/community/controller/CosController.java +++ b/src/main/java/com/greate/community/controller/CosController.java @@ -28,11 +28,12 @@ public class CosController extends BaseController { private CosService cosService; @GetMapping("/cos/credential") - public Result getCredential(@RequestParam("type") String type) { + public Result getCredential(@RequestParam("type") String type, @RequestParam("fileName") String fileName) { if (StringUtils.isBlank(type)) { return new Result("fail", "1", "the request parameters are invalid"); } - Response response = cosService.getCredential(type, getUser().getId()); + String userId = String.valueOf(getUser().getId()); + Response response = cosService.getCredential(type, "/" + userId + "/" + fileName); if (response == null) { return new Result("fail", "1", "the request parameters are invalid"); } diff --git a/src/main/java/com/greate/community/service/CosService.java b/src/main/java/com/greate/community/service/CosService.java index beee41a..17cb4b7 100644 --- a/src/main/java/com/greate/community/service/CosService.java +++ b/src/main/java/com/greate/community/service/CosService.java @@ -19,10 +19,7 @@ public class CosService { @Autowired private CosStsClientUtil cosStsClientUtil; - public Response getCredential(String type, int userId) { - - String allPrefixes = userId + "/*"; - - return cosStsClientUtil.getCredential(type, allPrefixes); + public Response getCredential(String type, String filePath) { + return cosStsClientUtil.getCredential(type, filePath); } } diff --git a/src/main/java/com/greate/community/util/CosStsClientUtil.java b/src/main/java/com/greate/community/util/CosStsClientUtil.java index 7458c3d..05abba3 100644 --- a/src/main/java/com/greate/community/util/CosStsClientUtil.java +++ b/src/main/java/com/greate/community/util/CosStsClientUtil.java @@ -36,7 +36,6 @@ public class CosStsClientUtil { */ public Response getCredential(String type, String... allowPrefixes) { TreeMap config = new TreeMap(); - try { // 云 api 密钥 SecretId -- Gitee From 34e5484f6a941e167f4f46d99f861a11d84f963d Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Mon, 21 Feb 2022 15:32:03 +0800 Subject: [PATCH 034/125] add: get unread message count --- .../community/config/SecurityConfig.java | 3 +- .../controller/MessageController.java | 14 ++++++- .../interceptor/MessageInterceptor.java | 39 ------------------- 3 files changed, 15 insertions(+), 41 deletions(-) delete mode 100644 src/main/java/com/greate/community/controller/interceptor/MessageInterceptor.java diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index 1a3175f..ef53684 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -80,7 +80,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm "/like", "/follow", "/unfollow", - "/exp/**" + "/exp/**", + "/cos/credential" ) .hasAnyAuthority( AUTHORITY_USER, diff --git a/src/main/java/com/greate/community/controller/MessageController.java b/src/main/java/com/greate/community/controller/MessageController.java index fe1f2e8..34d4095 100644 --- a/src/main/java/com/greate/community/controller/MessageController.java +++ b/src/main/java/com/greate/community/controller/MessageController.java @@ -9,6 +9,7 @@ import com.greate.community.service.MessageService; import com.greate.community.service.UserService; import com.greate.community.util.CommunityConstant; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.concurrent.SuccessCallback; import org.springframework.web.bind.annotation.*; import org.springframework.web.util.HtmlUtils; @@ -32,6 +33,18 @@ public class MessageController extends BaseController implements CommunityConsta @Autowired private CommentService commentService; + @GetMapping("/message/unread") + public Result getUnreadMessage() { + JSONObject result = new JSONObject(); + // 查询当前用户的所有未读私信数量 + int letterUnreadCount = messageService.findLetterUnreadCount(getUser().getId(), null); + result.put("letterUnreadCount", letterUnreadCount); + // 查询当前用户的所有未读系统通知数量 + int noticeUnreadCount = messageService.findNoticeUnReadCount(getUser().getId(), null); + result.put("noticeUnreadCount", noticeUnreadCount); + return new Result("success", Result.SUCCESS, result); + } + /** * 私信列表 * @@ -46,7 +59,6 @@ public class MessageController extends BaseController implements CommunityConsta // 获取当前登录用户信息 User user = getUser(); // 分页信息 -// page.setLimit(5);//前端注入 page.setPath("/letter/list"); // 查询会话总数 page.setRows(messageService.findConversationCount(user.getId())); diff --git a/src/main/java/com/greate/community/controller/interceptor/MessageInterceptor.java b/src/main/java/com/greate/community/controller/interceptor/MessageInterceptor.java deleted file mode 100644 index 596dac5..0000000 --- a/src/main/java/com/greate/community/controller/interceptor/MessageInterceptor.java +++ /dev/null @@ -1,39 +0,0 @@ -//package com.greate.community.controller.interceptor; -// -//import com.greate.community.entity.User; -//import com.greate.community.service.MessageService; -//import com.greate.community.util.HostHolder; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.security.core.context.SecurityContextHolder; -//import org.springframework.stereotype.Component; -//import org.springframework.web.servlet.HandlerInterceptor; -//import org.springframework.web.servlet.ModelAndView; -// -//import javax.servlet.http.HttpServletRequest; -//import javax.servlet.http.HttpServletResponse; -// -//@Component -//public class MessageInterceptor implements HandlerInterceptor { -// -// @Autowired -// private MessageService messageService; -// -// /** -// * Controller之后模板之前被调用 -// * 获取未读私信/系统通知的数量 -// * @param request -// * @param response -// * @param handler -// * @param modelAndView -// * @throws Exception -// */ -// @Override -// public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { -// User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); -// if (user != null && modelAndView != null) { -// int letterUnreadCount = messageService.findLetterUnreadCount(user.getId(), null); -// int noticeUnreadCount = messageService.findNoticeUnReadCount(user.getId(), null); -// modelAndView.addObject("allUnreadCount", letterUnreadCount + noticeUnreadCount); -// } -// } -//} -- Gitee From aa990d469ccb27ef70142402b63fd67e7951bc81 Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Tue, 22 Feb 2022 10:18:17 +0800 Subject: [PATCH 035/125] =?UTF-8?q?=E5=85=B3=E6=B3=A8=E6=95=B4=E5=90=88?= =?UTF-8?q?=E5=88=B0mysql-=E5=8F=91=E5=B8=96=E9=85=8D=E5=9B=BEbug=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/DiscussPostController.java | 2 +- .../controller/FollowController.java | 64 ++- .../greate/community/dao/FollowMapper.java | 84 ++++ .../com/greate/community/dao/LikeMapper.java | 2 +- .../com/greate/community/entity/Follow.java | 22 + .../community/service/FollowService.java | 392 +++++++++++++++--- .../community/util/StringListConvertor.java | 2 - src/main/resources/mapper/follow-mapper.xml | 63 +++ 8 files changed, 540 insertions(+), 91 deletions(-) create mode 100644 src/main/java/com/greate/community/dao/FollowMapper.java create mode 100644 src/main/java/com/greate/community/entity/Follow.java create mode 100644 src/main/resources/mapper/follow-mapper.xml diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index 1b609c4..5705147 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -52,7 +52,7 @@ public class DiscussPostController extends BaseController implements CommunityCo public Result addDiscussPost(@RequestBody HashMap map) { String title = (String) map.get("title"); String content = (String) map.get("content"); - ArrayList picUrlList = (ArrayList) map.get("picUrls"); + List picUrlList = (List) map.get("picUrls"); String picUrls = ""; int picNum = 0; diff --git a/src/main/java/com/greate/community/controller/FollowController.java b/src/main/java/com/greate/community/controller/FollowController.java index c4fdaa7..8f1fe27 100644 --- a/src/main/java/com/greate/community/controller/FollowController.java +++ b/src/main/java/com/greate/community/controller/FollowController.java @@ -49,18 +49,25 @@ public class FollowController extends BaseController implements CommunityConstan User user = getUser(); - followService.follow(user.getId(), entityType, entityId); - - // 触发关注事件(系统通知) - Event event = new Event() - .setTopic(TOPIC_FOLLOW) - .setUserId(getUser().getId()) - .setEntityType(entityType) - .setEntityId(entityId) - .setEntityUserId(entityId); - eventProducer.fireEvent(event); - - return new Result("success", Result.SUCCESS, "已关注"); +// followService.follow(user.getId(), entityType, entityId); + + boolean hasFollowed = hasFollowed(entityType, entityId);//判断当前登录用户是否关注该实体类型的实体id + if(hasFollowed){ + return new Result("success", Result.SUCCESS, "您已关注过该用户,无需再次关注"); + }else{ + //未关注该用户,执行关注操作 + followService.followOrUnfollow(user.getId(), entityType, entityId); + // 触发关注事件(系统通知) + Event event = new Event() + .setTopic(TOPIC_FOLLOW) + .setUserId(getUser().getId()) + .setEntityType(entityType) + .setEntityId(entityId) + .setEntityUserId(entityId); + eventProducer.fireEvent(event); + + return new Result("success", Result.SUCCESS, "关注用户成功"); + } } /** @@ -76,9 +83,18 @@ public class FollowController extends BaseController implements CommunityConstan User user = getUser(); - followService.unfollow(user.getId(), entityType, entityId); +// followService.unfollow(user.getId(), entityType, entityId); + + boolean hasFollowed = hasFollowed(entityType, entityId);//判断当前登录用户是否关注该实体类型的实体id + if(hasFollowed){ + //已经关注该用户,执行取关操作 + followService.followOrUnfollow(user.getId(), entityType, entityId); - return new Result("success", Result.SUCCESS, "已取消关注"); + return new Result("success", Result.SUCCESS, "已取消关注"); + }else{ + //未关注该用户 + return new Result("success", Result.SUCCESS, "您尚未关注该用户,无需取消关注"); + } } /** @@ -86,12 +102,11 @@ public class FollowController extends BaseController implements CommunityConstan * * @param userId * @param page - * @param model * @return */ @GetMapping("/followees/{userId}") @ResponseBody - public Result getFollowees(@PathVariable("userId") int userId, Page page, Model model) { + public Result getFollowees(@PathVariable("userId") int userId, Page page) { HashMap hashMap = new HashMap<>(); User user = userService.findUserById(userId); @@ -126,12 +141,11 @@ public class FollowController extends BaseController implements CommunityConstan * * @param userId * @param page - * @param model * @return */ @GetMapping("/followers/{userId}") @ResponseBody - public Result getFollowers(@PathVariable("userId") int userId, Page page, Model model) { + public Result getFollowers(@PathVariable("userId") int userId, Page page) { HashMap hashMap = new HashMap<>(); User user = userService.findUserById(userId); @@ -175,4 +189,18 @@ public class FollowController extends BaseController implements CommunityConstan } + /** + * 判断当前登录用户是否已关注某类型实体的实体id + * + * @param entityType 实体类型 + * @param entityId 实体id + * @return + */ + private boolean hasFollowed(int entityType, int entityId) { + if (getUser() == null) { + return false; + } + + return followService.hasFollowed(getUser().getId(), entityType, entityId); + } } diff --git a/src/main/java/com/greate/community/dao/FollowMapper.java b/src/main/java/com/greate/community/dao/FollowMapper.java new file mode 100644 index 0000000..da46cff --- /dev/null +++ b/src/main/java/com/greate/community/dao/FollowMapper.java @@ -0,0 +1,84 @@ +package com.greate.community.dao; + +import com.greate.community.entity.Follow; +import com.greate.community.entity.Like; +import com.greate.community.entity.User; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Date; +import java.util.List; + +/** + * @author xzx + * @date 2022/2/20 19:04 + */ +@Mapper +public interface FollowMapper { + /** + * 插入关注记录 + * + * @param follow + * @return + */ + int insertFollow(Follow follow); + + /** + * 取消关注 + * + * @param userId + * @param entityType + * @param entityId + * @return + */ + int deleteFollowByUserIdAndEntity(int userId, int entityType, int entityId); + + /** + * 查询用户关注某类型实体的所有记录,记录中仅 entityId 与 createTime 字段有效, + * 不要使用其它字段 + * + * @param userId + * @param entityType + * @return + */ + List selectRowsByUserIdAndEntityType(int userId, int entityType); + + /** + * 查询某个实体的所有粉丝,返回的 Follow 对象中仅 userId 与 createTime 字段有效, + * 不要使用其它字段 + * + * @param entityType + * @param entityId + * @return + */ + List selectRowsByEntityTypeAndEntityId(int entityType, int entityId); + + /** + * 查询用户是否关注某个实体,如果关注了,则返回关注时间 createTime + * + * @param userId + * @param entityType + * @param entityId + * @return + */ + Date selectByUserIdAndEntity(int userId, int entityType, int entityId); + + /** + * 分页查询用户所关注的所有用户实体 + * + * @param userId + * @param offset + * @param limit + * @return + */ + List selectFolloweeUsers(int userId, int offset, int limit); + + /** + * 分页查询关注该用户实体的所有用户,即该用户实体的粉丝 + * + * @param entityId + * @param offset + * @param limit + * @return + */ + List selectFollowerUsers(int entityId, int offset, int limit); +} diff --git a/src/main/java/com/greate/community/dao/LikeMapper.java b/src/main/java/com/greate/community/dao/LikeMapper.java index b0d0991..bb6fb6c 100644 --- a/src/main/java/com/greate/community/dao/LikeMapper.java +++ b/src/main/java/com/greate/community/dao/LikeMapper.java @@ -35,7 +35,7 @@ public interface LikeMapper { * * @param userId * @param entityType - * @param entityUserId + * @param entityId * @return */ int deleteLikeByUserIdAndEntity(int userId, int entityType, int entityId); diff --git a/src/main/java/com/greate/community/entity/Follow.java b/src/main/java/com/greate/community/entity/Follow.java new file mode 100644 index 0000000..f068f07 --- /dev/null +++ b/src/main/java/com/greate/community/entity/Follow.java @@ -0,0 +1,22 @@ +package com.greate.community.entity; + +import lombok.Data; +import lombok.ToString; + +import java.util.Date; + +/** + * @author xzx + * @date 2022/2/20 18:55 + * + * 关注实体类 + */ +@Data +@ToString +public class Follow { + private int id; + private int userId; // 执行关注操作的用户id + private int entityType; // 关注的实体类型,3-用户 + private int entityId; // 关注的实体id + private Date createTime; //关注的时间 +} diff --git a/src/main/java/com/greate/community/service/FollowService.java b/src/main/java/com/greate/community/service/FollowService.java index 1f4582a..3bce24a 100644 --- a/src/main/java/com/greate/community/service/FollowService.java +++ b/src/main/java/com/greate/community/service/FollowService.java @@ -1,8 +1,11 @@ package com.greate.community.service; +import com.greate.community.dao.FollowMapper; +import com.greate.community.entity.Follow; import com.greate.community.entity.User; import com.greate.community.util.CommunityConstant; import com.greate.community.util.RedisKeyUtil; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.core.RedisOperations; @@ -15,6 +18,7 @@ import java.util.*; /** * 关注相关 */ +@Slf4j @Service public class FollowService implements CommunityConstant { @@ -24,14 +28,57 @@ public class FollowService implements CommunityConstant { @Autowired private UserService userService; + @Autowired + private FollowMapper followMapper; + /** - * 关注 + * 关注或取关 * - * @param userId - * @param entityType - * @param entityId + * @param userId 执行操作的用户id + * @param entityType 关注的实体类型,3-用户 + * @param entityId 关注的实体id */ - public void follow(int userId, int entityType, int entityId) { + public void followOrUnfollow(int userId, int entityType, int entityId) { +// redisTemplate.execute(new SessionCallback() { +// @Override +// public Object execute(RedisOperations redisOperations) throws DataAccessException { +// // 生成 Redis 的 key +// String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); +// String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId); +// +// // 开启事务管理 +// redisOperations.multi(); +// +// // 插入数据 +// redisOperations.opsForZSet().add(followeeKey, entityId, System.currentTimeMillis()); +// redisOperations.opsForZSet().add(followerKey, userId, System.currentTimeMillis()); +// +// // 提交事务 +// return redisOperations.exec(); +// } +// }); + + // 判断用户是否已经关注该实体类型的实体id +// int followStatus = findEntityFollowStatus(userId, entityType, entityId); + log.info("followOrUnfollow 方法执行"); + boolean hasFollowed = hasFollowed(userId, entityType, entityId); + + //先对mysql进行处理 + if (hasFollowed) { + // 如果用户已经关注该实体,点第二次则取消关注 + followMapper.deleteFollowByUserIdAndEntity(userId, entityType, entityId); + log.info("用户已关注该实体,执行取关操作,删除 mysql 记录"); + } else { + Follow follow = new Follow(); + follow.setUserId(userId); + follow.setEntityType(entityType); + follow.setEntityId(entityId); + follow.setCreateTime(new Date()); + followMapper.insertFollow(follow); + log.info("用户尚未关注该实体,执行关注操作,插入 mysql 记录"); + } + + //再对redis进行处理 redisTemplate.execute(new SessionCallback() { @Override public Object execute(RedisOperations redisOperations) throws DataAccessException { @@ -39,57 +86,118 @@ public class FollowService implements CommunityConstant { String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId); - // 开启事务管理 - redisOperations.multi(); + redisOperations.multi(); // 开启事务 - // 插入数据 - redisOperations.opsForZSet().add(followeeKey, entityId, System.currentTimeMillis()); - redisOperations.opsForZSet().add(followerKey, userId, System.currentTimeMillis()); + if (hasFollowed) { + // 如果用户已经关注该实体,点第二次则取消关注 + // 删除数据 + log.info("用户已关注该实体,执行取关操作,删除 redis 记录"); + redisOperations.opsForZSet().remove(followeeKey, entityId); + redisOperations.opsForZSet().remove(followerKey, userId); + } else { + // 插入数据 + log.info("用户尚未关注该实体,执行关注操作,插入 redis 记录"); + long currentTimeMillis = System.currentTimeMillis(); + redisOperations.opsForZSet().add(followeeKey, entityId, currentTimeMillis); + redisOperations.opsForZSet().add(followerKey, userId, currentTimeMillis); + } - // 提交事务 - return redisOperations.exec(); + return redisOperations.exec(); // 提交事务 } }); + } - /** - * 取消关注 - * - * @param userId - * @param entityType - * @param entityId - */ - public void unfollow(int userId, int entityType, int entityId) { - redisTemplate.execute(new SessionCallback() { - @Override - public Object execute(RedisOperations redisOperations) throws DataAccessException { - // 生成 Redis 的 key - String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); - String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId); +// /** +// * 查询某个用户是否已经关注该实体类型的实体id +// * +// * @param userId +// * @param entityType +// * @param entityId +// * @return 1:已关注,0:未关注 +// */ +// public int findEntityFollowStatus(int userId, int entityType, int entityId){ +// int followStatus = 0; +// // 查询 redis +// String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); +// followStatus = redisTemplate.opsForZSet().score(followeeKey, entityId) != null ? 1 : 0; +// +// if (followStatus == 0) { +// // mysql 中找 +// followStatus = followMapper.countByUserIdAndEntity(userId, entityType, entityId)> 0 ? 1 : 0; +// +// // 找到了之后存入 redis +// if (followStatus == 1) { +// redisTemplate.opsForZSet().add(followeeKey, entityId, System.currentTimeMillis()); +// } +// } +// return followStatus; +// } - // 开启事务管理 - redisOperations.multi(); - // 删除数据 - redisOperations.opsForZSet().remove(followeeKey, entityId); - redisOperations.opsForZSet().remove(followerKey, userId); - // 提交事务 - return redisOperations.exec(); - } - }); - } + + +// /** +// * 取消关注 +// * +// * @param userId +// * @param entityType +// * @param entityId +// */ +// public void unfollow(int userId, int entityType, int entityId) { +// redisTemplate.execute(new SessionCallback() { +// @Override +// public Object execute(RedisOperations redisOperations) throws DataAccessException { +// // 生成 Redis 的 key +// String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); +// String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId); +// +// // 开启事务管理 +// redisOperations.multi(); +// +// // 删除数据 +// redisOperations.opsForZSet().remove(followeeKey, entityId); +// redisOperations.opsForZSet().remove(followerKey, userId); +// +// // 提交事务 +// return redisOperations.exec(); +// } +// }); +// } /** - * 查询某个用户关注的实体的数量 + * 查询某个用户关注的某类型实体的数量 * * @param userId 用户 id * @param entityType 实体类型 * @return */ public long findFolloweeCount(int userId, int entityType) { +// String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); +// return redisTemplate.opsForZSet().zCard(followeeKey); + + log.info("findFolloweeCount 方法执行"); String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); - return redisTemplate.opsForZSet().zCard(followeeKey); + long count = 0; + + if (redisTemplate.hasKey(followeeKey)) { + // 先在 redis 中查询 + Long num = redisTemplate.opsForZSet().zCard(followeeKey); + count = num == null ? 0 : num; + log.info("redis 中查询,count=" + count); + } else { + // redis中没有,则在 mysql 中查询 + List followeeList = followMapper.selectRowsByUserIdAndEntityType(userId, entityType); + count = followeeList.size(); + log.info("mysql 中查询,count=" + count); + // 找到了之后存入 redis + for(Follow follow : followeeList){ + redisTemplate.opsForZSet().add(followeeKey, follow.getEntityId(), follow.getCreateTime().getTime()); + log.info("存入 redis --> "+follow.toString()); + } + } + return count; } /** @@ -100,8 +208,30 @@ public class FollowService implements CommunityConstant { * @return */ public long findFollowerCount(int entityType, int entityId) { +// String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId); +// return redisTemplate.opsForZSet().zCard(followerKey); + + log.info("findFollowerCount 方法执行"); String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId); - return redisTemplate.opsForZSet().zCard(followerKey); + long count = 0; + + if (redisTemplate.hasKey(followerKey)) { + // 先在 redis 中查询 + Long num = redisTemplate.opsForZSet().zCard(followerKey); + count = num == null ? 0 : num; + log.info("redis 中查询,count=" + count); + } else { + // redis中没有,则在 mysql 中查询 + List followerList = followMapper.selectRowsByEntityTypeAndEntityId(entityType,entityId); + count = followerList.size(); + log.info("mysql 中查询,count=" + count); + // 找到了之后存入 redis + for(Follow follow : followerList){ + redisTemplate.opsForZSet().add(followerKey, follow.getUserId(), follow.getCreateTime().getTime()); + log.info("存入 redis --> "+follow.toString()); + } + } + return count; } /** @@ -113,8 +243,58 @@ public class FollowService implements CommunityConstant { * @return */ public boolean hasFollowed(int userId, int entityType, int entityId) { +// String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); +// return redisTemplate.opsForZSet().score(followeeKey, entityId) != null; + + log.info("hasFollowed 方法执行"); + String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); + boolean hasFollowed = false; + if (redisTemplate.hasKey(followeeKey)) { + // 先在 redis 中查询 + hasFollowed = redisTemplate.opsForZSet().score(followeeKey, entityId) != null; + log.info("redis 中查询,hasFollowed="+hasFollowed); + } else { + // redis中没有,则在 mysql 中查询 + Date createTime = followMapper.selectByUserIdAndEntity(userId, entityType, entityId); + log.info("mysql 中查询,createTime="+createTime); + if(createTime != null){ + hasFollowed = true; + // 找到了之后存入 redis + redisTemplate.opsForZSet().add(followeeKey, entityId, createTime.getTime()); + log.info("存入 redis"); + } + + } + return hasFollowed; + } + + /** + * 查询用户关注某实体的关注时间,如果还未关注,返回 null 值 + * + * @param userId + * @param entityType + * @param entityId + * @return + */ + public Date findFollowTime(int userId, int entityType, int entityId){ + log.info("findFollowTime 方法执行"); + String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); - return redisTemplate.opsForZSet().score(followeeKey, entityId) != null; + Date followTime = null; + if (redisTemplate.hasKey(followeeKey)) { + // 先在 redis 中查询 + Double score = redisTemplate.opsForZSet().score(followeeKey, entityId); + followTime = new Date(score.longValue()); + log.info("redis 中查询"); + }else { + // redis中没有,则在 mysql 中查询 + Date createTime = followMapper.selectByUserIdAndEntity(userId, entityType, entityId); + if (createTime != null){ + followTime = createTime; + } + log.info("mysql 中查询"); + } + return followTime; } /** @@ -126,26 +306,62 @@ public class FollowService implements CommunityConstant { * @return */ public List> findFollowees(int userId, int offset, int limit) { +// String followeeKey = RedisKeyUtil.getFolloweeKey(userId, ENTITY_TYPE_USER); +// Set targetIds = redisTemplate.opsForZSet().reverseRange(followeeKey, offset, offset + limit - 1); +// if (targetIds == null) { +// return null; +// } +// List> list = new ArrayList<>(); +// for (Integer targetId : targetIds) { +// Map map = new HashMap<>(); +// +// User user = userService.findUserById(targetId); +// map.put("user", user); +// Double score = redisTemplate.opsForZSet().score(followeeKey, targetId); +// map.put("followTime", new Date(score.longValue())); +// +// list.add(map); +// } +// +// return list; + + log.info("findFollowees 方法执行"); String followeeKey = RedisKeyUtil.getFolloweeKey(userId, ENTITY_TYPE_USER); + //先查 redis Set targetIds = redisTemplate.opsForZSet().reverseRange(followeeKey, offset, offset + limit - 1); if (targetIds == null) { - return null; - } - List> list = new ArrayList<>(); - for (Integer targetId : targetIds) { - Map map = new HashMap<>(); - - User user = userService.findUserById(targetId); - map.put("user", user); - Double score = redisTemplate.opsForZSet().score(followeeKey, targetId); - map.put("followTime", new Date(score.longValue())); - - list.add(map); + // redis 中没有,查 mysql + List followeeUsers = followMapper.selectFolloweeUsers(userId, offset, limit); + log.info("redis 中没有,查 mysql"); + if(followeeUsers.size() == 0){ + return null; + } + else { + List> list = new ArrayList<>(); + for(User user:followeeUsers){ + Map map = new HashMap<>(); + map.put("user", user); + Date followTime = findFollowTime(userId, ENTITY_TYPE_USER, user.getId()); + map.put("followTime", followTime); + list.add(map); + } + return list; + } + }else { + // redis 中有,则直接查 redis + log.info("redis 中有,则直接查 redis"); + List> list = new ArrayList<>(); + for (Integer targetId : targetIds) { + Map map = new HashMap<>(); + User user = userService.findUserById(targetId); + map.put("user", user); + Date followTime = findFollowTime(userId, ENTITY_TYPE_USER, user.getId()); + map.put("followTime", followTime); + list.add(map); + } + return list; } - - return list; } - /** * 分页查询某个用户的粉丝(偷个懒,此处没有做对其他实体的粉丝) * @@ -155,25 +371,63 @@ public class FollowService implements CommunityConstant { * @return */ public List> findFollowers(int userId, int offset, int limit) { +// String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER, userId); +// Set targetIds = redisTemplate.opsForZSet().reverseRange(followerKey, offset, offset + limit - 1); +// if (targetIds == null) { +// return null; +// } +// List> list = new ArrayList<>(); +// for (Integer targetId : targetIds) { +// Map map = new HashMap<>(); +// +// User user = userService.findUserById(targetId); +// map.put("user", user); +// Double score = redisTemplate.opsForZSet().score(followerKey, targetId); +// map.put("followTime", new Date(score.longValue())); +// +// list.add(map); +// } +// +// return list; + + log.info("findFollowers 方法执行"); String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER, userId); + //先查 redis Set targetIds = redisTemplate.opsForZSet().reverseRange(followerKey, offset, offset + limit - 1); if (targetIds == null) { - return null; - } - List> list = new ArrayList<>(); - for (Integer targetId : targetIds) { - Map map = new HashMap<>(); - - User user = userService.findUserById(targetId); - map.put("user", user); - Double score = redisTemplate.opsForZSet().score(followerKey, targetId); - map.put("followTime", new Date(score.longValue())); + // redis 中没有,查 mysql + List followerUsers = followMapper.selectFollowerUsers(userId, offset, limit); + log.info("redis 中没有,查 mysql"); - list.add(map); - } + if(followerUsers.size() == 0){ + return null; + } + else { + List> list = new ArrayList<>(); + for(User user:followerUsers){ + Map map = new HashMap<>(); + map.put("user", user); + Date followTime = findFollowTime(userId, ENTITY_TYPE_USER, user.getId()); + map.put("followTime", followTime); + list.add(map); + } + return list; + } + }else { + // redis 中有,则直接查 redis + log.info("redis 中有,则直接查 redis"); + List> list = new ArrayList<>(); + for (Integer targetId : targetIds) { + Map map = new HashMap<>(); - return list; + User user = userService.findUserById(targetId); + map.put("user", user); + Date followTime = findFollowTime(userId, ENTITY_TYPE_USER, user.getId()); + map.put("followTime", followTime); + list.add(map); + } + return list; + } } - } diff --git a/src/main/java/com/greate/community/util/StringListConvertor.java b/src/main/java/com/greate/community/util/StringListConvertor.java index ebf48a2..651e351 100644 --- a/src/main/java/com/greate/community/util/StringListConvertor.java +++ b/src/main/java/com/greate/community/util/StringListConvertor.java @@ -2,8 +2,6 @@ package com.greate.community.util; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.greate.community.entity.DiscussPost; -import com.sun.corba.se.spi.ior.ObjectKey; import org.apache.commons.lang3.StringUtils; import java.util.List; diff --git a/src/main/resources/mapper/follow-mapper.xml b/src/main/resources/mapper/follow-mapper.xml new file mode 100644 index 0000000..39dc422 --- /dev/null +++ b/src/main/resources/mapper/follow-mapper.xml @@ -0,0 +1,63 @@ + + + + + + + entity_type, entity_id, user_id, create_time + + + + insert into `follow` () + values(#{entityType}, #{entityId}, #{userId}, #{createTime}) + + + + delete + from `follow` + where user_id = #{userId} + and entity_type = #{entityType} + and entity_id = #{entityId} + + + + + + + + + + + + + + + + \ No newline at end of file -- Gitee From 8522f603d8766c757a5c41550f8b9f9e3a729a1f Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Tue, 22 Feb 2022 10:55:14 +0800 Subject: [PATCH 036/125] =?UTF-8?q?=E5=8F=91=E5=B8=96=E9=85=8D=E5=9B=BE?= =?UTF-8?q?=E4=B8=BA=E7=A9=BA=E6=95=B0=E7=BB=84=E6=97=B6bug=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/greate/community/controller/DiscussPostController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index 5705147..6591dfc 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -57,7 +57,7 @@ public class DiscussPostController extends BaseController implements CommunityCo String picUrls = ""; int picNum = 0; - if (picUrlList != null) { + if (picUrlList != null && picUrlList.size() != 0) { for (String picUrl : picUrlList) { picUrls = picUrls + picUrl + ","; picNum++; -- Gitee From 3b8b3350da6af2cb1092aead5e18b4dd658b6d31 Mon Sep 17 00:00:00 2001 From: CSUpipixia Date: Tue, 22 Feb 2022 16:43:38 +0800 Subject: [PATCH 037/125] update like message --- .../controller/MessageController.java | 3 + .../interceptor/DataInterceptor.java | 3 - .../service/ElasticsearchService.java | 85 +- .../resources/static/css/bootstrap.min.css | 7 - .../resources/static/css/discuss-detail.css | 40 - src/main/resources/static/css/editormd.css | 4450 --------- src/main/resources/static/css/global.css | 198 - src/main/resources/static/css/letter.css | 17 - src/main/resources/static/css/login.css | 13 - src/main/resources/static/css/my-reply.css | 5 - .../05ed9c9c900d475b86a66bee7c39642e.jpeg | Bin 89202 -> 0 bytes .../323b95b3bc6e43f7a8824b43b1e8100c.jpg | Bin 14054 -> 0 bytes .../5f84429642a042fe8cc0db924a606666.jpeg | Bin 20980 -> 0 bytes .../ed84395548b045b386ec2f1ca6dde32d.jpeg | Bin 89202 -> 0 bytes .../resources/static/editor-md/.gitignore | 15 - src/main/resources/static/editor-md/.jshintrc | 20 - src/main/resources/static/editor-md/BUGS.md | 22 - src/main/resources/static/editor-md/CHANGE.md | 534 - .../resources/static/editor-md/Gulpfile.js | 342 - src/main/resources/static/editor-md/LICENSE | 22 - src/main/resources/static/editor-md/README.md | 268 - .../resources/static/editor-md/bower.json | 24 - .../static/editor-md/css/editormd.css | 4450 --------- .../static/editor-md/css/editormd.logo.css | 98 - .../editor-md/css/editormd.logo.min.css | 2 - .../static/editor-md/css/editormd.min.css | 5 - .../static/editor-md/css/editormd.preview.css | 3554 ------- .../editor-md/css/editormd.preview.min.css | 5 - .../static/editor-md/editormd.amd.js | 4667 --------- .../static/editor-md/editormd.amd.min.js | 4 - .../resources/static/editor-md/editormd.js | 4598 --------- .../static/editor-md/editormd.min.js | 3 - .../static/editor-md/examples/@links.html | 135 - .../editor-md/examples/auto-height.html | 55 - .../editor-md/examples/change-mode.html | 508 - .../static/editor-md/examples/code-fold.html | 44 - .../static/editor-md/examples/css/style.css | 94 - .../examples/custom-keyboard-shortcuts.html | 118 - .../editor-md/examples/custom-toolbar.html | 178 - .../editor-md/examples/define-plugin.html | 151 - .../examples/delay-renderer-preview.html | 56 - .../examples/dynamic-create-editormd.html | 47 - .../static/editor-md/examples/emoji.html | 191 - .../static/editor-md/examples/extends.html | 153 - .../editor-md/examples/external-use.html | 119 - .../static/editor-md/examples/flowchart.html | 53 - .../editor-md/examples/form-get-value.html | 92 - .../static/editor-md/examples/full.html | 231 - .../static/editor-md/examples/goto-line.html | 84 - ...markdown-to-html-custom-toc-container.html | 180 - .../html-preview-markdown-to-html.html | 142 - .../editor-md/examples/html-tags-decode.html | 119 - .../examples/image-cross-domain-upload.html | 109 - .../editor-md/examples/image-upload.html | 68 - .../static/editor-md/examples/images/4.jpg | Bin 121969 -> 0 bytes .../static/editor-md/examples/images/7.jpg | Bin 95090 -> 0 bytes .../static/editor-md/examples/images/8.jpg | Bin 17555 -> 0 bytes .../examples/images/editormd-screenshot.png | Bin 81096 -> 0 bytes .../static/editor-md/examples/index.html | 356 - .../editor-md/examples/js/jquery.min.js | 4 - .../editor-md/examples/js/require.min.js | 36 - .../static/editor-md/examples/js/sea.js | 2 - .../editor-md/examples/js/seajs-main.js | 74 - .../static/editor-md/examples/js/zepto.min.js | 2 - .../static/editor-md/examples/katex.html | 192 - .../examples/manually-load-modules.html | 109 - .../editor-md/examples/multi-editormd.html | 64 - .../editor-md/examples/multi-languages.html | 89 - .../static/editor-md/examples/on-off.html | 103 - .../static/editor-md/examples/onchange.html | 49 - .../editor-md/examples/onfullscreen.html | 55 - .../static/editor-md/examples/onload.html | 52 - .../examples/onpreviewing-onpreviewed.html | 55 - .../static/editor-md/examples/onresize.html | 49 - .../examples/onscroll-onpreviewscroll.html | 63 - .../editor-md/examples/onwatch-onunwatch.html | 51 - .../static/editor-md/examples/page-break.html | 87 - .../examples/php/cross-domain-upload.php | 54 - .../examples/php/editormd.uploader.class.php | 341 - .../static/editor-md/examples/php/post.php | 18 - .../static/editor-md/examples/php/upload.php | 51 - .../examples/php/upload_callback.html | 35 - .../static/editor-md/examples/readonly.html | 60 - .../static/editor-md/examples/resettings.html | 144 - .../editor-md/examples/search-replace.html | 46 - .../editor-md/examples/sequence-diagram.html | 65 - .../examples/set-get-replace-selection.html | 110 - .../static/editor-md/examples/simple.html | 76 - .../editor-md/examples/sync-scrolling.html | 70 - .../static/editor-md/examples/task-lists.html | 65 - .../static/editor-md/examples/test.md | 365 - .../static/editor-md/examples/themes.html | 207 - .../static/editor-md/examples/toc.html | 199 - .../examples/toolbar-auto-fixed.html | 122 - .../editor-md/examples/use-requirejs.html | 174 - .../static/editor-md/examples/use-seajs.html | 176 - .../static/editor-md/examples/use-zepto.html | 126 - .../static/editor-md/fonts/FontAwesome.otf | Bin 93888 -> 0 bytes .../static/editor-md/fonts/editormd-logo.eot | Bin 1320 -> 0 bytes .../static/editor-md/fonts/editormd-logo.svg | 11 - .../static/editor-md/fonts/editormd-logo.ttf | Bin 1156 -> 0 bytes .../static/editor-md/fonts/editormd-logo.woff | Bin 1232 -> 0 bytes .../editor-md/fonts/fontawesome-webfont.eot | Bin 60767 -> 0 bytes .../editor-md/fonts/fontawesome-webfont.svg | 565 -- .../editor-md/fonts/fontawesome-webfont.ttf | Bin 122092 -> 0 bytes .../editor-md/fonts/fontawesome-webfont.woff | Bin 71508 -> 0 bytes .../editor-md/fonts/fontawesome-webfont.woff2 | Bin 56780 -> 0 bytes .../static/editor-md/images/loading.gif | Bin 7726 -> 0 bytes .../static/editor-md/images/loading@2x.gif | Bin 16166 -> 0 bytes .../static/editor-md/images/loading@3x.gif | Bin 21727 -> 0 bytes .../images/logos/editormd-favicon-16x16.ico | Bin 1150 -> 0 bytes .../images/logos/editormd-favicon-24x24.ico | Bin 1150 -> 0 bytes .../images/logos/editormd-favicon-32x32.ico | Bin 5430 -> 0 bytes .../images/logos/editormd-favicon-48x48.ico | Bin 15086 -> 0 bytes .../images/logos/editormd-favicon-64x64.ico | Bin 32038 -> 0 bytes .../images/logos/editormd-logo-114x114.png | Bin 5869 -> 0 bytes .../images/logos/editormd-logo-120x120.png | Bin 6141 -> 0 bytes .../images/logos/editormd-logo-144x144.png | Bin 7545 -> 0 bytes .../images/logos/editormd-logo-16x16.png | Bin 1448 -> 0 bytes .../images/logos/editormd-logo-180x180.png | Bin 7963 -> 0 bytes .../images/logos/editormd-logo-240x240.png | Bin 10470 -> 0 bytes .../images/logos/editormd-logo-24x24.png | Bin 1790 -> 0 bytes .../images/logos/editormd-logo-320x320.png | Bin 14714 -> 0 bytes .../images/logos/editormd-logo-32x32.png | Bin 2064 -> 0 bytes .../images/logos/editormd-logo-48x48.png | Bin 2701 -> 0 bytes .../images/logos/editormd-logo-57x57.png | Bin 3054 -> 0 bytes .../images/logos/editormd-logo-64x64.png | Bin 3408 -> 0 bytes .../images/logos/editormd-logo-72x72.png | Bin 3691 -> 0 bytes .../images/logos/editormd-logo-96x96.png | Bin 4857 -> 0 bytes .../static/editor-md/images/logos/vi.png | Bin 46203 -> 0 bytes .../static/editor-md/languages/en.js | 129 - .../static/editor-md/languages/zh-tw.js | 129 - .../static/editor-md/lib/codemirror/AUTHORS | 436 - .../static/editor-md/lib/codemirror/LICENSE | 19 - .../static/editor-md/lib/codemirror/README.md | 12 - .../lib/codemirror/addon/comment/comment.js | 183 - .../addon/comment/continuecomment.js | 85 - .../lib/codemirror/addon/dialog/dialog.css | 32 - .../lib/codemirror/addon/dialog/dialog.js | 155 - .../codemirror/addon/display/fullscreen.css | 6 - .../codemirror/addon/display/fullscreen.js | 41 - .../lib/codemirror/addon/display/panel.js | 94 - .../codemirror/addon/display/placeholder.js | 58 - .../lib/codemirror/addon/display/rulers.js | 64 - .../codemirror/addon/edit/closebrackets.js | 161 - .../lib/codemirror/addon/edit/closetag.js | 166 - .../lib/codemirror/addon/edit/continuelist.js | 51 - .../codemirror/addon/edit/matchbrackets.js | 120 - .../lib/codemirror/addon/edit/matchtags.js | 66 - .../codemirror/addon/edit/trailingspace.js | 27 - .../lib/codemirror/addon/fold/brace-fold.js | 105 - .../lib/codemirror/addon/fold/comment-fold.js | 57 - .../lib/codemirror/addon/fold/foldcode.js | 149 - .../lib/codemirror/addon/fold/foldgutter.css | 20 - .../lib/codemirror/addon/fold/foldgutter.js | 144 - .../lib/codemirror/addon/fold/indent-fold.js | 44 - .../codemirror/addon/fold/markdown-fold.js | 49 - .../lib/codemirror/addon/fold/xml-fold.js | 182 - .../lib/codemirror/addon/hint/anyword-hint.js | 41 - .../lib/codemirror/addon/hint/css-hint.js | 56 - .../lib/codemirror/addon/hint/html-hint.js | 348 - .../codemirror/addon/hint/javascript-hint.js | 146 - .../lib/codemirror/addon/hint/show-hint.css | 38 - .../lib/codemirror/addon/hint/show-hint.js | 394 - .../lib/codemirror/addon/hint/sql-hint.js | 240 - .../lib/codemirror/addon/hint/xml-hint.js | 110 - .../addon/lint/coffeescript-lint.js | 41 - .../lib/codemirror/addon/lint/css-lint.js | 35 - .../codemirror/addon/lint/javascript-lint.js | 136 - .../lib/codemirror/addon/lint/json-lint.js | 31 - .../lib/codemirror/addon/lint/lint.css | 73 - .../lib/codemirror/addon/lint/lint.js | 205 - .../lib/codemirror/addon/lint/yaml-lint.js | 28 - .../lib/codemirror/addon/merge/merge.css | 112 - .../lib/codemirror/addon/merge/merge.js | 735 -- .../lib/codemirror/addon/mode/loadmode.js | 64 - .../lib/codemirror/addon/mode/multiplex.js | 118 - .../codemirror/addon/mode/multiplex_test.js | 33 - .../lib/codemirror/addon/mode/overlay.js | 85 - .../lib/codemirror/addon/mode/simple.js | 213 - .../lib/codemirror/addon/runmode/colorize.js | 40 - .../addon/runmode/runmode-standalone.js | 157 - .../lib/codemirror/addon/runmode/runmode.js | 72 - .../codemirror/addon/runmode/runmode.node.js | 120 - .../addon/scroll/annotatescrollbar.js | 100 - .../codemirror/addon/scroll/scrollpastend.js | 46 - .../addon/scroll/simplescrollbars.css | 66 - .../addon/scroll/simplescrollbars.js | 141 - .../addon/search/match-highlighter.js | 128 - .../addon/search/matchesonscrollbar.css | 8 - .../addon/search/matchesonscrollbar.js | 95 - .../lib/codemirror/addon/search/search.js | 164 - .../codemirror/addon/search/searchcursor.js | 189 - .../codemirror/addon/selection/active-line.js | 71 - .../addon/selection/mark-selection.js | 118 - .../addon/selection/selection-pointer.js | 98 - .../lib/codemirror/addon/tern/tern.css | 86 - .../lib/codemirror/addon/tern/tern.js | 697 -- .../lib/codemirror/addon/tern/worker.js | 44 - .../lib/codemirror/addon/wrap/hardwrap.js | 139 - .../editor-md/lib/codemirror/addons.min.js | 4 - .../editor-md/lib/codemirror/bower.json | 16 - .../lib/codemirror/codemirror.min.css | 3 - .../lib/codemirror/codemirror.min.js | 54 - .../lib/codemirror/lib/codemirror.css | 331 - .../lib/codemirror/lib/codemirror.js | 8645 ----------------- .../editor-md/lib/codemirror/mode/apl/apl.js | 175 - .../lib/codemirror/mode/apl/index.html | 72 - .../lib/codemirror/mode/asterisk/asterisk.js | 198 - .../lib/codemirror/mode/asterisk/index.html | 154 - .../lib/codemirror/mode/clike/clike.js | 493 - .../lib/codemirror/mode/clike/index.html | 251 - .../lib/codemirror/mode/clike/scala.html | 767 -- .../lib/codemirror/mode/clojure/clojure.js | 243 - .../lib/codemirror/mode/clojure/index.html | 88 - .../lib/codemirror/mode/cobol/cobol.js | 255 - .../lib/codemirror/mode/cobol/index.html | 210 - .../mode/coffeescript/coffeescript.js | 369 - .../codemirror/mode/coffeescript/index.html | 740 -- .../codemirror/mode/commonlisp/commonlisp.js | 122 - .../lib/codemirror/mode/commonlisp/index.html | 177 - .../editor-md/lib/codemirror/mode/css/css.js | 766 -- .../lib/codemirror/mode/css/index.html | 75 - .../lib/codemirror/mode/css/less.html | 152 - .../lib/codemirror/mode/css/less_test.js | 51 - .../lib/codemirror/mode/css/scss.html | 157 - .../lib/codemirror/mode/css/scss_test.js | 110 - .../editor-md/lib/codemirror/mode/css/test.js | 195 - .../lib/codemirror/mode/cypher/cypher.js | 146 - .../lib/codemirror/mode/cypher/index.html | 63 - .../editor-md/lib/codemirror/mode/d/d.js | 218 - .../lib/codemirror/mode/d/index.html | 273 - .../lib/codemirror/mode/dart/dart.js | 50 - .../lib/codemirror/mode/dart/index.html | 71 - .../lib/codemirror/mode/diff/diff.js | 47 - .../lib/codemirror/mode/diff/index.html | 117 - .../lib/codemirror/mode/django/django.js | 67 - .../lib/codemirror/mode/django/index.html | 63 - .../codemirror/mode/dockerfile/dockerfile.js | 76 - .../lib/codemirror/mode/dockerfile/index.html | 73 - .../editor-md/lib/codemirror/mode/dtd/dtd.js | 142 - .../lib/codemirror/mode/dtd/index.html | 89 - .../lib/codemirror/mode/dylan/dylan.js | 299 - .../lib/codemirror/mode/dylan/index.html | 407 - .../lib/codemirror/mode/ebnf/ebnf.js | 195 - .../lib/codemirror/mode/ebnf/index.html | 102 - .../editor-md/lib/codemirror/mode/ecl/ecl.js | 207 - .../lib/codemirror/mode/ecl/index.html | 52 - .../lib/codemirror/mode/eiffel/eiffel.js | 162 - .../lib/codemirror/mode/eiffel/index.html | 429 - .../lib/codemirror/mode/erlang/erlang.js | 622 -- .../lib/codemirror/mode/erlang/index.html | 76 - .../lib/codemirror/mode/forth/forth.js | 180 - .../lib/codemirror/mode/forth/index.html | 75 - .../lib/codemirror/mode/fortran/fortran.js | 188 - .../lib/codemirror/mode/fortran/index.html | 81 - .../editor-md/lib/codemirror/mode/gas/gas.js | 345 - .../lib/codemirror/mode/gas/index.html | 68 - .../editor-md/lib/codemirror/mode/gfm/gfm.js | 123 - .../lib/codemirror/mode/gfm/index.html | 93 - .../editor-md/lib/codemirror/mode/gfm/test.js | 213 - .../lib/codemirror/mode/gherkin/gherkin.js | 178 - .../lib/codemirror/mode/gherkin/index.html | 48 - .../editor-md/lib/codemirror/mode/go/go.js | 185 - .../lib/codemirror/mode/go/index.html | 85 - .../lib/codemirror/mode/groovy/groovy.js | 226 - .../lib/codemirror/mode/groovy/index.html | 84 - .../lib/codemirror/mode/haml/haml.js | 159 - .../lib/codemirror/mode/haml/index.html | 79 - .../lib/codemirror/mode/haml/test.js | 97 - .../lib/codemirror/mode/haskell/haskell.js | 267 - .../lib/codemirror/mode/haskell/index.html | 73 - .../lib/codemirror/mode/haxe/haxe.js | 518 - .../lib/codemirror/mode/haxe/index.html | 124 - .../mode/htmlembedded/htmlembedded.js | 86 - .../codemirror/mode/htmlembedded/index.html | 58 - .../codemirror/mode/htmlmixed/htmlmixed.js | 121 - .../lib/codemirror/mode/htmlmixed/index.html | 89 - .../lib/codemirror/mode/http/http.js | 113 - .../lib/codemirror/mode/http/index.html | 45 - .../editor-md/lib/codemirror/mode/idl/idl.js | 290 - .../lib/codemirror/mode/idl/index.html | 64 - .../editor-md/lib/codemirror/mode/index.html | 134 - .../lib/codemirror/mode/jade/index.html | 70 - .../lib/codemirror/mode/jade/jade.js | 590 -- .../lib/codemirror/mode/javascript/index.html | 114 - .../codemirror/mode/javascript/javascript.js | 692 -- .../codemirror/mode/javascript/json-ld.html | 72 - .../lib/codemirror/mode/javascript/test.js | 200 - .../mode/javascript/typescript.html | 61 - .../lib/codemirror/mode/jinja2/index.html | 54 - .../lib/codemirror/mode/jinja2/jinja2.js | 142 - .../lib/codemirror/mode/julia/index.html | 195 - .../lib/codemirror/mode/julia/julia.js | 301 - .../lib/codemirror/mode/kotlin/index.html | 89 - .../lib/codemirror/mode/kotlin/kotlin.js | 280 - .../lib/codemirror/mode/livescript/index.html | 459 - .../codemirror/mode/livescript/livescript.js | 280 - .../lib/codemirror/mode/lua/index.html | 85 - .../editor-md/lib/codemirror/mode/lua/lua.js | 159 - .../lib/codemirror/mode/markdown/index.html | 359 - .../lib/codemirror/mode/markdown/markdown.js | 765 -- .../lib/codemirror/mode/markdown/test.js | 754 -- .../editor-md/lib/codemirror/mode/meta.js | 177 - .../lib/codemirror/mode/mirc/index.html | 160 - .../lib/codemirror/mode/mirc/mirc.js | 193 - .../lib/codemirror/mode/mllike/index.html | 179 - .../lib/codemirror/mode/mllike/mllike.js | 205 - .../lib/codemirror/mode/modelica/index.html | 67 - .../lib/codemirror/mode/modelica/modelica.js | 245 - .../lib/codemirror/mode/nginx/index.html | 181 - .../lib/codemirror/mode/nginx/nginx.js | 178 - .../lib/codemirror/mode/ntriples/index.html | 45 - .../lib/codemirror/mode/ntriples/ntriples.js | 186 - .../lib/codemirror/mode/octave/index.html | 83 - .../lib/codemirror/mode/octave/octave.js | 135 - .../lib/codemirror/mode/pascal/index.html | 61 - .../lib/codemirror/mode/pascal/pascal.js | 109 - .../lib/codemirror/mode/pegjs/index.html | 66 - .../lib/codemirror/mode/pegjs/pegjs.js | 114 - .../lib/codemirror/mode/perl/index.html | 75 - .../lib/codemirror/mode/perl/perl.js | 837 -- .../lib/codemirror/mode/php/index.html | 64 - .../editor-md/lib/codemirror/mode/php/php.js | 226 - .../editor-md/lib/codemirror/mode/php/test.js | 154 - .../lib/codemirror/mode/pig/index.html | 55 - .../editor-md/lib/codemirror/mode/pig/pig.js | 188 - .../lib/codemirror/mode/properties/index.html | 53 - .../codemirror/mode/properties/properties.js | 78 - .../lib/codemirror/mode/puppet/index.html | 121 - .../lib/codemirror/mode/puppet/puppet.js | 220 - .../lib/codemirror/mode/python/index.html | 198 - .../lib/codemirror/mode/python/python.js | 359 - .../lib/codemirror/mode/q/index.html | 144 - .../editor-md/lib/codemirror/mode/q/q.js | 139 - .../lib/codemirror/mode/r/index.html | 85 - .../editor-md/lib/codemirror/mode/r/r.js | 162 - .../codemirror/mode/rpm/changes/index.html | 66 - .../lib/codemirror/mode/rpm/index.html | 149 - .../editor-md/lib/codemirror/mode/rpm/rpm.js | 101 - .../lib/codemirror/mode/rst/index.html | 535 - .../editor-md/lib/codemirror/mode/rst/rst.js | 557 -- .../lib/codemirror/mode/ruby/index.html | 183 - .../lib/codemirror/mode/ruby/ruby.js | 285 - .../lib/codemirror/mode/ruby/test.js | 14 - .../lib/codemirror/mode/rust/index.html | 60 - .../lib/codemirror/mode/rust/rust.js | 451 - .../lib/codemirror/mode/sass/index.html | 66 - .../lib/codemirror/mode/sass/sass.js | 414 - .../lib/codemirror/mode/scheme/index.html | 77 - .../lib/codemirror/mode/scheme/scheme.js | 248 - .../lib/codemirror/mode/shell/index.html | 66 - .../lib/codemirror/mode/shell/shell.js | 139 - .../lib/codemirror/mode/shell/test.js | 58 - .../lib/codemirror/mode/sieve/index.html | 93 - .../lib/codemirror/mode/sieve/sieve.js | 193 - .../lib/codemirror/mode/slim/index.html | 96 - .../lib/codemirror/mode/slim/slim.js | 575 -- .../lib/codemirror/mode/slim/test.js | 96 - .../lib/codemirror/mode/smalltalk/index.html | 68 - .../codemirror/mode/smalltalk/smalltalk.js | 168 - .../lib/codemirror/mode/smarty/index.html | 136 - .../lib/codemirror/mode/smarty/smarty.js | 221 - .../codemirror/mode/smartymixed/index.html | 114 - .../mode/smartymixed/smartymixed.js | 197 - .../lib/codemirror/mode/solr/index.html | 57 - .../lib/codemirror/mode/solr/solr.js | 104 - .../lib/codemirror/mode/soy/index.html | 68 - .../editor-md/lib/codemirror/mode/soy/soy.js | 198 - .../lib/codemirror/mode/sparql/index.html | 61 - .../lib/codemirror/mode/sparql/sparql.js | 174 - .../codemirror/mode/spreadsheet/index.html | 42 - .../mode/spreadsheet/spreadsheet.js | 109 - .../lib/codemirror/mode/stex/index.html | 110 - .../lib/codemirror/mode/stex/stex.js | 251 - .../lib/codemirror/mode/stex/test.js | 123 - .../lib/codemirror/mode/stylus/index.html | 104 - .../lib/codemirror/mode/stylus/stylus.js | 444 - .../lib/codemirror/mode/tcl/index.html | 142 - .../editor-md/lib/codemirror/mode/tcl/tcl.js | 147 - .../lib/codemirror/mode/textile/index.html | 191 - .../lib/codemirror/mode/textile/test.js | 417 - .../lib/codemirror/mode/textile/textile.js | 469 - .../lib/codemirror/mode/tiddlywiki/index.html | 154 - .../codemirror/mode/tiddlywiki/tiddlywiki.css | 14 - .../codemirror/mode/tiddlywiki/tiddlywiki.js | 369 - .../lib/codemirror/mode/tiki/index.html | 95 - .../lib/codemirror/mode/tiki/tiki.css | 26 - .../lib/codemirror/mode/tiki/tiki.js | 323 - .../lib/codemirror/mode/toml/index.html | 73 - .../lib/codemirror/mode/toml/toml.js | 88 - .../lib/codemirror/mode/tornado/index.html | 63 - .../lib/codemirror/mode/tornado/tornado.js | 68 - .../lib/codemirror/mode/turtle/index.html | 50 - .../lib/codemirror/mode/turtle/turtle.js | 162 - .../lib/codemirror/mode/vb/index.html | 102 - .../editor-md/lib/codemirror/mode/vb/vb.js | 274 - .../lib/codemirror/mode/vbscript/index.html | 55 - .../lib/codemirror/mode/vbscript/vbscript.js | 350 - .../lib/codemirror/mode/velocity/index.html | 118 - .../lib/codemirror/mode/velocity/velocity.js | 201 - .../lib/codemirror/mode/verilog/index.html | 120 - .../lib/codemirror/mode/verilog/test.js | 273 - .../lib/codemirror/mode/verilog/verilog.js | 537 - .../lib/codemirror/mode/xml/index.html | 57 - .../editor-md/lib/codemirror/mode/xml/test.js | 51 - .../editor-md/lib/codemirror/mode/xml/xml.js | 384 - .../lib/codemirror/mode/xquery/index.html | 210 - .../lib/codemirror/mode/xquery/test.js | 67 - .../lib/codemirror/mode/xquery/xquery.js | 447 - .../lib/codemirror/mode/yaml/index.html | 80 - .../lib/codemirror/mode/yaml/yaml.js | 117 - .../lib/codemirror/mode/z80/index.html | 52 - .../editor-md/lib/codemirror/mode/z80/z80.js | 100 - .../editor-md/lib/codemirror/modes.min.js | 10 - .../editor-md/lib/codemirror/package.json | 21 - .../lib/codemirror/theme/3024-day.css | 40 - .../lib/codemirror/theme/3024-night.css | 39 - .../lib/codemirror/theme/ambiance-mobile.css | 5 - .../lib/codemirror/theme/ambiance.css | 75 - .../lib/codemirror/theme/base16-dark.css | 38 - .../lib/codemirror/theme/base16-light.css | 38 - .../lib/codemirror/theme/blackboard.css | 32 - .../editor-md/lib/codemirror/theme/cobalt.css | 25 - .../lib/codemirror/theme/colorforth.css | 33 - .../lib/codemirror/theme/eclipse.css | 23 - .../lib/codemirror/theme/elegant.css | 13 - .../lib/codemirror/theme/erlang-dark.css | 34 - .../lib/codemirror/theme/lesser-dark.css | 47 - .../editor-md/lib/codemirror/theme/mbo.css | 37 - .../lib/codemirror/theme/mdn-like.css | 46 - .../lib/codemirror/theme/midnight.css | 47 - .../lib/codemirror/theme/monokai.css | 33 - .../editor-md/lib/codemirror/theme/neat.css | 12 - .../editor-md/lib/codemirror/theme/neo.css | 43 - .../editor-md/lib/codemirror/theme/night.css | 28 - .../lib/codemirror/theme/paraiso-dark.css | 38 - .../lib/codemirror/theme/paraiso-light.css | 38 - .../lib/codemirror/theme/pastel-on-dark.css | 53 - .../lib/codemirror/theme/rubyblue.css | 25 - .../lib/codemirror/theme/solarized.css | 165 - .../lib/codemirror/theme/the-matrix.css | 30 - .../theme/tomorrow-night-bright.css | 35 - .../theme/tomorrow-night-eighties.css | 38 - .../lib/codemirror/theme/twilight.css | 32 - .../lib/codemirror/theme/vibrant-ink.css | 34 - .../lib/codemirror/theme/xq-dark.css | 53 - .../lib/codemirror/theme/xq-light.css | 43 - .../lib/codemirror/theme/zenburn.css | 37 - .../static/editor-md/lib/flowchart.min.js | 5 - .../editor-md/lib/jquery.flowchart.min.js | 2 - .../static/editor-md/lib/marked.min.js | 9 - .../static/editor-md/lib/prettify.min.js | 15 - .../static/editor-md/lib/raphael.min.js | 11 - .../editor-md/lib/sequence-diagram.min.js | 7 - .../static/editor-md/lib/underscore.min.js | 5 - .../resources/static/editor-md/package.json | 42 - .../code-block-dialog/code-block-dialog.js | 237 - .../plugins/emoji-dialog/emoji-dialog.js | 327 - .../editor-md/plugins/emoji-dialog/emoji.json | 28 - .../goto-line-dialog/goto-line-dialog.js | 157 - .../plugins/help-dialog/help-dialog.js | 102 - .../html-entities-dialog.js | 173 - .../html-entities-dialog/html-entities.json | 936 -- .../plugins/image-dialog/image-dialog.js | 227 - .../plugins/link-dialog/link-dialog.js | 133 - .../editor-md/plugins/plugin-template.js | 111 - .../preformatted-text-dialog.js | 172 - .../reference-link-dialog.js | 153 - .../plugins/table-dialog/table-dialog.js | 218 - .../plugins/test-plugin/test-plugin.js | 66 - .../editor-md/scss/editormd.codemirror.scss | 90 - .../editor-md/scss/editormd.dialog.scss | 184 - .../static/editor-md/scss/editormd.form.scss | 130 - .../static/editor-md/scss/editormd.grid.scss | 36 - .../static/editor-md/scss/editormd.logo.scss | 89 - .../static/editor-md/scss/editormd.menu.scss | 113 - .../editor-md/scss/editormd.preview.scss | 322 - .../scss/editormd.preview.themes.scss | 131 - .../static/editor-md/scss/editormd.scss | 137 - .../static/editor-md/scss/editormd.tab.scss | 49 - .../editor-md/scss/editormd.themes.scss | 28 - .../static/editor-md/scss/font-awesome.scss | 1801 ---- .../editor-md/scss/github-markdown.scss | 665 -- .../static/editor-md/scss/lib/prefixes.scss | 784 -- .../static/editor-md/scss/lib/variables.scss | 11 - .../static/editor-md/scss/prettify.scss | 53 - .../static/editor-md/src/editormd.js | 4588 --------- .../editor-md/tests/bootstrap-test.html | 63 - .../tests/codemirror-searchbox-test.html | 109 - .../editor-md/tests/codemirror-test.html | 75 - .../tests/css/bootstrap-theme.min.css | 5 - .../editor-md/tests/css/bootstrap.min.css | 5 - .../editor-md/tests/js/bootstrap.min.js | 7 - .../static/editor-md/tests/js/searchbox.js | 674 -- .../static/editor-md/tests/katex-tests.html | 132 - .../editor-md/tests/marked-@at-test.html | 221 - .../editor-md/tests/marked-emoji-test.html | 231 - .../tests/marked-heading-link-test.html | 138 - .../tests/marked-todo-list-test.html | 61 - .../editor-md/tests/qunit/qunit-1.16.0.css | 264 - .../editor-md/tests/qunit/qunit-1.16.0.js | 2819 ------ src/main/resources/static/img/404.png | Bin 27828 -> 0 bytes src/main/resources/static/img/500.png | Bin 34589 -> 0 bytes src/main/resources/static/img/captcha.png | Bin 4166 -> 0 bytes src/main/resources/static/img/favicon.ico | Bin 9603 -> 0 bytes src/main/resources/static/img/logo.png | Bin 5401 -> 0 bytes src/main/resources/static/js/bootstrap.min.js | 7 - .../static/js/bs-custom-file-input.js | 167 - .../resources/static/js/discuss-publish.js | 38 - src/main/resources/static/js/discuss.js | 82 - src/main/resources/static/js/global.js | 34 - src/main/resources/static/js/index.js | 33 - .../resources/static/js/jquery-3.1.0.min.js | 4 - src/main/resources/static/js/letter.js | 35 - src/main/resources/static/js/popper.min.js | 5 - src/main/resources/static/js/profile.js | 40 - src/main/resources/static/js/register.js | 18 - src/main/resources/static/js/reset-pwd.js | 165 - src/main/resources/static/js/setting.js | 40 - src/main/resources/templates/error/404.html | 33 - src/main/resources/templates/error/500.html | 33 - src/main/resources/templates/index.html | 230 - .../resources/templates/mail/activation.html | 19 - src/main/resources/templates/mail/forget.html | 19 - .../resources/templates/site/admin/data.html | 65 - .../templates/site/discuss-detail.html | 224 - .../templates/site/discuss-publish.html | 122 - .../resources/templates/site/followee.html | 72 - .../resources/templates/site/follower.html | 74 - src/main/resources/templates/site/forget.html | 106 - .../templates/site/letter-detail.html | 115 - src/main/resources/templates/site/letter.html | 124 - src/main/resources/templates/site/login.html | 88 - .../resources/templates/site/my-post.html | 55 - .../resources/templates/site/my-reply.html | 57 - .../templates/site/notice-detail.html | 88 - src/main/resources/templates/site/notice.html | 123 - .../templates/site/operate-result.html | 49 - .../resources/templates/site/profile.html | 80 - .../resources/templates/site/register.html | 86 - .../resources/templates/site/reset-pwd.html | 106 - src/main/resources/templates/site/search.html | 56 - .../resources/templates/site/setting.html | 98 - 544 files changed, 12 insertions(+), 109255 deletions(-) delete mode 100644 src/main/resources/static/css/bootstrap.min.css delete mode 100644 src/main/resources/static/css/discuss-detail.css delete mode 100644 src/main/resources/static/css/editormd.css delete mode 100644 src/main/resources/static/css/global.css delete mode 100644 src/main/resources/static/css/letter.css delete mode 100644 src/main/resources/static/css/login.css delete mode 100644 src/main/resources/static/css/my-reply.css delete mode 100644 src/main/resources/static/editor-md-upload/05ed9c9c900d475b86a66bee7c39642e.jpeg delete mode 100644 src/main/resources/static/editor-md-upload/323b95b3bc6e43f7a8824b43b1e8100c.jpg delete mode 100644 src/main/resources/static/editor-md-upload/5f84429642a042fe8cc0db924a606666.jpeg delete mode 100644 src/main/resources/static/editor-md-upload/ed84395548b045b386ec2f1ca6dde32d.jpeg delete mode 100644 src/main/resources/static/editor-md/.gitignore delete mode 100644 src/main/resources/static/editor-md/.jshintrc delete mode 100644 src/main/resources/static/editor-md/BUGS.md delete mode 100644 src/main/resources/static/editor-md/CHANGE.md delete mode 100644 src/main/resources/static/editor-md/Gulpfile.js delete mode 100644 src/main/resources/static/editor-md/LICENSE delete mode 100644 src/main/resources/static/editor-md/README.md delete mode 100644 src/main/resources/static/editor-md/bower.json delete mode 100644 src/main/resources/static/editor-md/css/editormd.css delete mode 100644 src/main/resources/static/editor-md/css/editormd.logo.css delete mode 100644 src/main/resources/static/editor-md/css/editormd.logo.min.css delete mode 100644 src/main/resources/static/editor-md/css/editormd.min.css delete mode 100644 src/main/resources/static/editor-md/css/editormd.preview.css delete mode 100644 src/main/resources/static/editor-md/css/editormd.preview.min.css delete mode 100644 src/main/resources/static/editor-md/editormd.amd.js delete mode 100644 src/main/resources/static/editor-md/editormd.amd.min.js delete mode 100644 src/main/resources/static/editor-md/editormd.js delete mode 100644 src/main/resources/static/editor-md/editormd.min.js delete mode 100644 src/main/resources/static/editor-md/examples/@links.html delete mode 100644 src/main/resources/static/editor-md/examples/auto-height.html delete mode 100644 src/main/resources/static/editor-md/examples/change-mode.html delete mode 100644 src/main/resources/static/editor-md/examples/code-fold.html delete mode 100644 src/main/resources/static/editor-md/examples/css/style.css delete mode 100644 src/main/resources/static/editor-md/examples/custom-keyboard-shortcuts.html delete mode 100644 src/main/resources/static/editor-md/examples/custom-toolbar.html delete mode 100644 src/main/resources/static/editor-md/examples/define-plugin.html delete mode 100644 src/main/resources/static/editor-md/examples/delay-renderer-preview.html delete mode 100644 src/main/resources/static/editor-md/examples/dynamic-create-editormd.html delete mode 100644 src/main/resources/static/editor-md/examples/emoji.html delete mode 100644 src/main/resources/static/editor-md/examples/extends.html delete mode 100644 src/main/resources/static/editor-md/examples/external-use.html delete mode 100644 src/main/resources/static/editor-md/examples/flowchart.html delete mode 100644 src/main/resources/static/editor-md/examples/form-get-value.html delete mode 100644 src/main/resources/static/editor-md/examples/full.html delete mode 100644 src/main/resources/static/editor-md/examples/goto-line.html delete mode 100644 src/main/resources/static/editor-md/examples/html-preview-markdown-to-html-custom-toc-container.html delete mode 100644 src/main/resources/static/editor-md/examples/html-preview-markdown-to-html.html delete mode 100644 src/main/resources/static/editor-md/examples/html-tags-decode.html delete mode 100644 src/main/resources/static/editor-md/examples/image-cross-domain-upload.html delete mode 100644 src/main/resources/static/editor-md/examples/image-upload.html delete mode 100644 src/main/resources/static/editor-md/examples/images/4.jpg delete mode 100644 src/main/resources/static/editor-md/examples/images/7.jpg delete mode 100644 src/main/resources/static/editor-md/examples/images/8.jpg delete mode 100644 src/main/resources/static/editor-md/examples/images/editormd-screenshot.png delete mode 100644 src/main/resources/static/editor-md/examples/index.html delete mode 100644 src/main/resources/static/editor-md/examples/js/jquery.min.js delete mode 100644 src/main/resources/static/editor-md/examples/js/require.min.js delete mode 100644 src/main/resources/static/editor-md/examples/js/sea.js delete mode 100644 src/main/resources/static/editor-md/examples/js/seajs-main.js delete mode 100644 src/main/resources/static/editor-md/examples/js/zepto.min.js delete mode 100644 src/main/resources/static/editor-md/examples/katex.html delete mode 100644 src/main/resources/static/editor-md/examples/manually-load-modules.html delete mode 100644 src/main/resources/static/editor-md/examples/multi-editormd.html delete mode 100644 src/main/resources/static/editor-md/examples/multi-languages.html delete mode 100644 src/main/resources/static/editor-md/examples/on-off.html delete mode 100644 src/main/resources/static/editor-md/examples/onchange.html delete mode 100644 src/main/resources/static/editor-md/examples/onfullscreen.html delete mode 100644 src/main/resources/static/editor-md/examples/onload.html delete mode 100644 src/main/resources/static/editor-md/examples/onpreviewing-onpreviewed.html delete mode 100644 src/main/resources/static/editor-md/examples/onresize.html delete mode 100644 src/main/resources/static/editor-md/examples/onscroll-onpreviewscroll.html delete mode 100644 src/main/resources/static/editor-md/examples/onwatch-onunwatch.html delete mode 100644 src/main/resources/static/editor-md/examples/page-break.html delete mode 100644 src/main/resources/static/editor-md/examples/php/cross-domain-upload.php delete mode 100644 src/main/resources/static/editor-md/examples/php/editormd.uploader.class.php delete mode 100644 src/main/resources/static/editor-md/examples/php/post.php delete mode 100644 src/main/resources/static/editor-md/examples/php/upload.php delete mode 100644 src/main/resources/static/editor-md/examples/php/upload_callback.html delete mode 100644 src/main/resources/static/editor-md/examples/readonly.html delete mode 100644 src/main/resources/static/editor-md/examples/resettings.html delete mode 100644 src/main/resources/static/editor-md/examples/search-replace.html delete mode 100644 src/main/resources/static/editor-md/examples/sequence-diagram.html delete mode 100644 src/main/resources/static/editor-md/examples/set-get-replace-selection.html delete mode 100644 src/main/resources/static/editor-md/examples/simple.html delete mode 100644 src/main/resources/static/editor-md/examples/sync-scrolling.html delete mode 100644 src/main/resources/static/editor-md/examples/task-lists.html delete mode 100644 src/main/resources/static/editor-md/examples/test.md delete mode 100644 src/main/resources/static/editor-md/examples/themes.html delete mode 100644 src/main/resources/static/editor-md/examples/toc.html delete mode 100644 src/main/resources/static/editor-md/examples/toolbar-auto-fixed.html delete mode 100644 src/main/resources/static/editor-md/examples/use-requirejs.html delete mode 100644 src/main/resources/static/editor-md/examples/use-seajs.html delete mode 100644 src/main/resources/static/editor-md/examples/use-zepto.html delete mode 100644 src/main/resources/static/editor-md/fonts/FontAwesome.otf delete mode 100644 src/main/resources/static/editor-md/fonts/editormd-logo.eot delete mode 100644 src/main/resources/static/editor-md/fonts/editormd-logo.svg delete mode 100644 src/main/resources/static/editor-md/fonts/editormd-logo.ttf delete mode 100644 src/main/resources/static/editor-md/fonts/editormd-logo.woff delete mode 100644 src/main/resources/static/editor-md/fonts/fontawesome-webfont.eot delete mode 100644 src/main/resources/static/editor-md/fonts/fontawesome-webfont.svg delete mode 100644 src/main/resources/static/editor-md/fonts/fontawesome-webfont.ttf delete mode 100644 src/main/resources/static/editor-md/fonts/fontawesome-webfont.woff delete mode 100644 src/main/resources/static/editor-md/fonts/fontawesome-webfont.woff2 delete mode 100644 src/main/resources/static/editor-md/images/loading.gif delete mode 100644 src/main/resources/static/editor-md/images/loading@2x.gif delete mode 100644 src/main/resources/static/editor-md/images/loading@3x.gif delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-favicon-16x16.ico delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-favicon-24x24.ico delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-favicon-32x32.ico delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-favicon-48x48.ico delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-favicon-64x64.ico delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-logo-114x114.png delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-logo-120x120.png delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-logo-144x144.png delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-logo-16x16.png delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-logo-180x180.png delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-logo-240x240.png delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-logo-24x24.png delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-logo-320x320.png delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-logo-32x32.png delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-logo-48x48.png delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-logo-57x57.png delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-logo-64x64.png delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-logo-72x72.png delete mode 100644 src/main/resources/static/editor-md/images/logos/editormd-logo-96x96.png delete mode 100644 src/main/resources/static/editor-md/images/logos/vi.png delete mode 100644 src/main/resources/static/editor-md/languages/en.js delete mode 100644 src/main/resources/static/editor-md/languages/zh-tw.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/AUTHORS delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/LICENSE delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/README.md delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/comment/comment.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/comment/continuecomment.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/dialog/dialog.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/dialog/dialog.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/display/fullscreen.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/display/fullscreen.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/display/panel.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/display/placeholder.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/display/rulers.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/edit/closebrackets.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/edit/closetag.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/edit/continuelist.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/edit/matchbrackets.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/edit/matchtags.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/edit/trailingspace.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/fold/brace-fold.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/fold/comment-fold.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/fold/foldcode.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/fold/foldgutter.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/fold/foldgutter.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/fold/indent-fold.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/fold/markdown-fold.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/fold/xml-fold.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/hint/anyword-hint.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/hint/css-hint.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/hint/html-hint.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/hint/javascript-hint.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/hint/show-hint.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/hint/show-hint.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/hint/sql-hint.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/hint/xml-hint.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/lint/coffeescript-lint.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/lint/css-lint.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/lint/javascript-lint.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/lint/json-lint.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/lint/lint.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/lint/lint.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/lint/yaml-lint.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/merge/merge.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/merge/merge.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/mode/loadmode.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/mode/multiplex.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/mode/multiplex_test.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/mode/overlay.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/mode/simple.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/runmode/colorize.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/runmode/runmode-standalone.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/runmode/runmode.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/runmode/runmode.node.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/scroll/annotatescrollbar.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/scroll/scrollpastend.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/scroll/simplescrollbars.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/scroll/simplescrollbars.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/search/match-highlighter.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/search/matchesonscrollbar.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/search/matchesonscrollbar.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/search/search.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/search/searchcursor.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/selection/active-line.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/selection/mark-selection.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/selection/selection-pointer.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/tern/tern.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/tern/tern.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/tern/worker.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addon/wrap/hardwrap.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/addons.min.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/bower.json delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/codemirror.min.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/codemirror.min.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/lib/codemirror.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/lib/codemirror.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/apl/apl.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/apl/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/asterisk/asterisk.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/asterisk/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/clike/clike.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/clike/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/clike/scala.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/clojure/clojure.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/clojure/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/cobol/cobol.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/cobol/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/coffeescript/coffeescript.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/coffeescript/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/commonlisp/commonlisp.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/commonlisp/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/css/css.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/css/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/css/less.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/css/less_test.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/css/scss.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/css/scss_test.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/css/test.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/cypher/cypher.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/cypher/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/d/d.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/d/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/dart/dart.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/dart/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/diff/diff.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/diff/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/django/django.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/django/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/dockerfile/dockerfile.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/dockerfile/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/dtd/dtd.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/dtd/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/dylan/dylan.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/dylan/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/ebnf/ebnf.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/ebnf/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/ecl/ecl.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/ecl/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/eiffel/eiffel.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/eiffel/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/erlang/erlang.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/erlang/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/forth/forth.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/forth/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/fortran/fortran.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/fortran/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/gas/gas.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/gas/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/gfm/gfm.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/gfm/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/gfm/test.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/gherkin/gherkin.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/gherkin/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/go/go.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/go/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/groovy/groovy.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/groovy/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/haml/haml.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/haml/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/haml/test.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/haskell/haskell.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/haskell/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/haxe/haxe.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/haxe/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/htmlembedded/htmlembedded.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/htmlembedded/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/htmlmixed/htmlmixed.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/htmlmixed/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/http/http.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/http/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/idl/idl.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/idl/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/jade/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/jade/jade.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/javascript/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/javascript/javascript.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/javascript/json-ld.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/javascript/test.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/javascript/typescript.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/jinja2/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/jinja2/jinja2.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/julia/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/julia/julia.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/kotlin/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/kotlin/kotlin.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/livescript/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/livescript/livescript.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/lua/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/lua/lua.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/markdown/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/markdown/markdown.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/markdown/test.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/meta.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/mirc/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/mirc/mirc.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/mllike/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/mllike/mllike.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/modelica/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/modelica/modelica.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/nginx/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/nginx/nginx.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/ntriples/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/ntriples/ntriples.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/octave/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/octave/octave.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/pascal/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/pascal/pascal.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/pegjs/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/pegjs/pegjs.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/perl/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/perl/perl.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/php/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/php/php.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/php/test.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/pig/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/pig/pig.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/properties/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/properties/properties.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/puppet/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/puppet/puppet.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/python/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/python/python.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/q/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/q/q.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/r/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/r/r.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/rpm/changes/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/rpm/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/rpm/rpm.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/rst/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/rst/rst.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/ruby/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/ruby/ruby.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/ruby/test.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/rust/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/rust/rust.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/sass/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/sass/sass.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/scheme/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/scheme/scheme.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/shell/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/shell/shell.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/shell/test.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/sieve/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/sieve/sieve.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/slim/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/slim/slim.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/slim/test.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/smalltalk/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/smalltalk/smalltalk.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/smarty/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/smarty/smarty.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/smartymixed/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/smartymixed/smartymixed.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/solr/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/solr/solr.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/soy/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/soy/soy.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/sparql/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/sparql/sparql.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/spreadsheet/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/spreadsheet/spreadsheet.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/stex/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/stex/stex.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/stex/test.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/stylus/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/stylus/stylus.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/tcl/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/tcl/tcl.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/textile/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/textile/test.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/textile/textile.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/tiddlywiki/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/tiddlywiki/tiddlywiki.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/tiddlywiki/tiddlywiki.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/tiki/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/tiki/tiki.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/tiki/tiki.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/toml/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/toml/toml.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/tornado/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/tornado/tornado.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/turtle/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/turtle/turtle.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/vb/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/vb/vb.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/vbscript/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/vbscript/vbscript.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/velocity/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/velocity/velocity.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/verilog/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/verilog/test.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/verilog/verilog.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/xml/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/xml/test.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/xml/xml.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/xquery/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/xquery/test.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/xquery/xquery.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/yaml/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/yaml/yaml.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/z80/index.html delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/mode/z80/z80.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/modes.min.js delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/package.json delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/3024-day.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/3024-night.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/ambiance-mobile.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/ambiance.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/base16-dark.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/base16-light.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/blackboard.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/cobalt.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/colorforth.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/eclipse.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/elegant.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/erlang-dark.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/lesser-dark.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/mbo.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/mdn-like.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/midnight.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/monokai.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/neat.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/neo.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/night.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/paraiso-dark.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/paraiso-light.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/pastel-on-dark.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/rubyblue.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/solarized.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/the-matrix.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/tomorrow-night-bright.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/tomorrow-night-eighties.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/twilight.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/vibrant-ink.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/xq-dark.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/xq-light.css delete mode 100644 src/main/resources/static/editor-md/lib/codemirror/theme/zenburn.css delete mode 100644 src/main/resources/static/editor-md/lib/flowchart.min.js delete mode 100644 src/main/resources/static/editor-md/lib/jquery.flowchart.min.js delete mode 100644 src/main/resources/static/editor-md/lib/marked.min.js delete mode 100644 src/main/resources/static/editor-md/lib/prettify.min.js delete mode 100644 src/main/resources/static/editor-md/lib/raphael.min.js delete mode 100644 src/main/resources/static/editor-md/lib/sequence-diagram.min.js delete mode 100644 src/main/resources/static/editor-md/lib/underscore.min.js delete mode 100644 src/main/resources/static/editor-md/package.json delete mode 100644 src/main/resources/static/editor-md/plugins/code-block-dialog/code-block-dialog.js delete mode 100644 src/main/resources/static/editor-md/plugins/emoji-dialog/emoji-dialog.js delete mode 100644 src/main/resources/static/editor-md/plugins/emoji-dialog/emoji.json delete mode 100644 src/main/resources/static/editor-md/plugins/goto-line-dialog/goto-line-dialog.js delete mode 100644 src/main/resources/static/editor-md/plugins/help-dialog/help-dialog.js delete mode 100644 src/main/resources/static/editor-md/plugins/html-entities-dialog/html-entities-dialog.js delete mode 100644 src/main/resources/static/editor-md/plugins/html-entities-dialog/html-entities.json delete mode 100644 src/main/resources/static/editor-md/plugins/image-dialog/image-dialog.js delete mode 100644 src/main/resources/static/editor-md/plugins/link-dialog/link-dialog.js delete mode 100644 src/main/resources/static/editor-md/plugins/plugin-template.js delete mode 100644 src/main/resources/static/editor-md/plugins/preformatted-text-dialog/preformatted-text-dialog.js delete mode 100644 src/main/resources/static/editor-md/plugins/reference-link-dialog/reference-link-dialog.js delete mode 100644 src/main/resources/static/editor-md/plugins/table-dialog/table-dialog.js delete mode 100644 src/main/resources/static/editor-md/plugins/test-plugin/test-plugin.js delete mode 100644 src/main/resources/static/editor-md/scss/editormd.codemirror.scss delete mode 100644 src/main/resources/static/editor-md/scss/editormd.dialog.scss delete mode 100644 src/main/resources/static/editor-md/scss/editormd.form.scss delete mode 100644 src/main/resources/static/editor-md/scss/editormd.grid.scss delete mode 100644 src/main/resources/static/editor-md/scss/editormd.logo.scss delete mode 100644 src/main/resources/static/editor-md/scss/editormd.menu.scss delete mode 100644 src/main/resources/static/editor-md/scss/editormd.preview.scss delete mode 100644 src/main/resources/static/editor-md/scss/editormd.preview.themes.scss delete mode 100644 src/main/resources/static/editor-md/scss/editormd.scss delete mode 100644 src/main/resources/static/editor-md/scss/editormd.tab.scss delete mode 100644 src/main/resources/static/editor-md/scss/editormd.themes.scss delete mode 100644 src/main/resources/static/editor-md/scss/font-awesome.scss delete mode 100644 src/main/resources/static/editor-md/scss/github-markdown.scss delete mode 100644 src/main/resources/static/editor-md/scss/lib/prefixes.scss delete mode 100644 src/main/resources/static/editor-md/scss/lib/variables.scss delete mode 100644 src/main/resources/static/editor-md/scss/prettify.scss delete mode 100644 src/main/resources/static/editor-md/src/editormd.js delete mode 100644 src/main/resources/static/editor-md/tests/bootstrap-test.html delete mode 100644 src/main/resources/static/editor-md/tests/codemirror-searchbox-test.html delete mode 100644 src/main/resources/static/editor-md/tests/codemirror-test.html delete mode 100644 src/main/resources/static/editor-md/tests/css/bootstrap-theme.min.css delete mode 100644 src/main/resources/static/editor-md/tests/css/bootstrap.min.css delete mode 100644 src/main/resources/static/editor-md/tests/js/bootstrap.min.js delete mode 100644 src/main/resources/static/editor-md/tests/js/searchbox.js delete mode 100644 src/main/resources/static/editor-md/tests/katex-tests.html delete mode 100644 src/main/resources/static/editor-md/tests/marked-@at-test.html delete mode 100644 src/main/resources/static/editor-md/tests/marked-emoji-test.html delete mode 100644 src/main/resources/static/editor-md/tests/marked-heading-link-test.html delete mode 100644 src/main/resources/static/editor-md/tests/marked-todo-list-test.html delete mode 100644 src/main/resources/static/editor-md/tests/qunit/qunit-1.16.0.css delete mode 100644 src/main/resources/static/editor-md/tests/qunit/qunit-1.16.0.js delete mode 100644 src/main/resources/static/img/404.png delete mode 100644 src/main/resources/static/img/500.png delete mode 100644 src/main/resources/static/img/captcha.png delete mode 100644 src/main/resources/static/img/favicon.ico delete mode 100644 src/main/resources/static/img/logo.png delete mode 100644 src/main/resources/static/js/bootstrap.min.js delete mode 100644 src/main/resources/static/js/bs-custom-file-input.js delete mode 100644 src/main/resources/static/js/discuss-publish.js delete mode 100644 src/main/resources/static/js/discuss.js delete mode 100644 src/main/resources/static/js/global.js delete mode 100644 src/main/resources/static/js/index.js delete mode 100644 src/main/resources/static/js/jquery-3.1.0.min.js delete mode 100644 src/main/resources/static/js/letter.js delete mode 100644 src/main/resources/static/js/popper.min.js delete mode 100644 src/main/resources/static/js/profile.js delete mode 100644 src/main/resources/static/js/register.js delete mode 100644 src/main/resources/static/js/reset-pwd.js delete mode 100644 src/main/resources/static/js/setting.js delete mode 100644 src/main/resources/templates/error/404.html delete mode 100644 src/main/resources/templates/error/500.html delete mode 100644 src/main/resources/templates/index.html delete mode 100644 src/main/resources/templates/mail/activation.html delete mode 100644 src/main/resources/templates/mail/forget.html delete mode 100644 src/main/resources/templates/site/admin/data.html delete mode 100644 src/main/resources/templates/site/discuss-detail.html delete mode 100644 src/main/resources/templates/site/discuss-publish.html delete mode 100644 src/main/resources/templates/site/followee.html delete mode 100644 src/main/resources/templates/site/follower.html delete mode 100644 src/main/resources/templates/site/forget.html delete mode 100644 src/main/resources/templates/site/letter-detail.html delete mode 100644 src/main/resources/templates/site/letter.html delete mode 100644 src/main/resources/templates/site/login.html delete mode 100644 src/main/resources/templates/site/my-post.html delete mode 100644 src/main/resources/templates/site/my-reply.html delete mode 100644 src/main/resources/templates/site/notice-detail.html delete mode 100644 src/main/resources/templates/site/notice.html delete mode 100644 src/main/resources/templates/site/operate-result.html delete mode 100644 src/main/resources/templates/site/profile.html delete mode 100644 src/main/resources/templates/site/register.html delete mode 100644 src/main/resources/templates/site/reset-pwd.html delete mode 100644 src/main/resources/templates/site/search.html delete mode 100644 src/main/resources/templates/site/setting.html diff --git a/src/main/java/com/greate/community/controller/MessageController.java b/src/main/java/com/greate/community/controller/MessageController.java index 34d4095..de75dc4 100644 --- a/src/main/java/com/greate/community/controller/MessageController.java +++ b/src/main/java/com/greate/community/controller/MessageController.java @@ -339,6 +339,9 @@ public class MessageController extends BaseController implements CommunityConsta if (Objects.equals(notice.getConversationId(), TOPIC_LIKE)) { // 帖子信息 map.put("post", discussPostService.findDiscussPostById((Integer) data.get("postId"))); + if ((Integer) data.get("entityType") == ENTITY_TYPE_COMMENT) { + map.put("comment", commentService.findCommentById((Integer) data.get("entityId"))); + } } // 发送系统通知的作者 diff --git a/src/main/java/com/greate/community/controller/interceptor/DataInterceptor.java b/src/main/java/com/greate/community/controller/interceptor/DataInterceptor.java index 04adcd0..0ac5593 100644 --- a/src/main/java/com/greate/community/controller/interceptor/DataInterceptor.java +++ b/src/main/java/com/greate/community/controller/interceptor/DataInterceptor.java @@ -1,10 +1,7 @@ package com.greate.community.controller.interceptor; -import com.greate.community.entity.User; import com.greate.community.service.DataService; -import com.greate.community.util.HostHolder; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; diff --git a/src/main/java/com/greate/community/service/ElasticsearchService.java b/src/main/java/com/greate/community/service/ElasticsearchService.java index ef3a6a2..968c83b 100644 --- a/src/main/java/com/greate/community/service/ElasticsearchService.java +++ b/src/main/java/com/greate/community/service/ElasticsearchService.java @@ -26,24 +26,21 @@ import java.util.List; @Service public class ElasticsearchService { -// @Autowired -// private DiscussPostRepository discussPostRepository; - @Autowired -// private ElasticsearchTemplate elasticsearchTemplate; private ElasticsearchRestTemplate elasticsearchRestTemplate; /** * 将数据插入 Elasticsearch 服务器 + * * @param post */ public void saveDiscussPost(DiscussPost post) { elasticsearchRestTemplate.save(post); -// discussPostRepository.save(post); } /** * 将数据从 Elasticsearch 服务器中删除 + * * @param id */ public void deleteDiscussPost(int id) { @@ -52,13 +49,14 @@ public class ElasticsearchService { /** * 分页搜索 + * * @param keyword 搜索的关键词 * @param current 当前页码(这里的 Page 是 Spring 提供的,而非我们自己实现的那个) - * @param limit 每页显示多少条数据 + * @param limit 每页显示多少条数据 * @return */ public Page searchDiscussPost(String keyword, int current, int limit) { - Pageable pageable = PageRequest.of(current,limit); + Pageable pageable = PageRequest.of(current, limit); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.multiMatchQuery(keyword, "title", "content")) .withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC)) @@ -74,76 +72,11 @@ public class ElasticsearchService { //封装page对象 List content = new ArrayList<>(); - for (SearchHit productSearchHit:searchHits) + for (SearchHit productSearchHit : searchHits) { content.add(productSearchHit.getContent()); - return new PageImpl<>(content,pageable,searchHits.getTotalHits()); + } + + return new PageImpl<>(content, pageable, searchHits.getTotalHits()); } -// public Page searchDiscussPost(String keyword, int current, int limit) { -// SearchQuery searchQuery = new NativeSearchQueryBuilder() -// .withQuery(QueryBuilders.multiMatchQuery(keyword, "title", "content")) -// .withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC)) -// .withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC)) -// .withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC)) -// .withPageable(PageRequest.of(current, limit)) -// .withHighlightFields( -// new HighlightBuilder.Field("title").preTags("").postTags(""), -// new HighlightBuilder.Field("content").preTags("").postTags("") -// ).build(); -// -// return elasticsearchTemplate.queryForPage(searchQuery, DiscussPost.class, new SearchResultMapper() { -// @Override -// public AggregatedPage mapResults(SearchResponse searchResponse, Class aClass, Pageable pageable) { -// // 获取命中的数据 -// SearchHits hits = searchResponse.getHits(); -// if (hits.getTotalHits() <= 0) { -// return null; -// } -// -// // 处理命中的数据 -// List list = new ArrayList<>(); -// for (SearchHit hit : hits) { -// DiscussPost post = new DiscussPost(); -// -// String id = hit.getSourceAsMap().get("id").toString(); -// post.setId(Integer.valueOf(id)); -// -// String userId = hit.getSourceAsMap().get("userId").toString(); -// post.setUserId(Integer.valueOf(userId)); -// -// String title = hit.getSourceAsMap().get("title").toString(); -// post.setTitle(title); -// -// String content = hit.getSourceAsMap().get("content").toString(); -// post.setContent(content); -// -// String status = hit.getSourceAsMap().get("status").toString(); -// post.setStatus(Integer.valueOf(status)); -// -// String createTime = hit.getSourceAsMap().get("createTime").toString(); -// post.setCreateTime(new Date(Long.valueOf(createTime))); -// -// String commentCount = hit.getSourceAsMap().get("commentCount").toString(); -// post.setCommentCount(Integer.valueOf(commentCount)); -// -// // 处理高亮显示的内容 -// HighlightField titleField = hit.getHighlightFields().get("title"); -// if (titleField != null) { -// post.setTitle(titleField.getFragments()[0].toString()); -// } -// -// HighlightField contentField = hit.getHighlightFields().get("content"); -// if (contentField != null) { -// post.setContent(contentField.getFragments()[0].toString()); -// } -// -// list.add(post); -// } -// -// return new AggregatedPageImpl(list, pageable, -// hits.getTotalHits(), searchResponse.getAggregations(), searchResponse.getScrollId(), hits.getMaxScore()); -// } -// }); -// -// } } diff --git a/src/main/resources/static/css/bootstrap.min.css b/src/main/resources/static/css/bootstrap.min.css deleted file mode 100644 index 92e3fe8..0000000 --- a/src/main/resources/static/css/bootstrap.min.css +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Bootstrap v4.3.1 (https://getbootstrap.com/) - * Copyright 2011-2019 The Bootstrap Authors - * Copyright 2011-2019 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-break:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#7abaff}.table-hover .table-primary:hover{background-color:#9fcdff}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding-top:.375rem;padding-bottom:.375rem;margin-bottom:0;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.form-control.is-valid,.was-validated .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:center right calc(.375em + .1875rem);background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-control.is-valid~.valid-feedback,.form-control.is-valid~.valid-tooltip,.was-validated .form-control:valid~.valid-feedback,.was-validated .form-control:valid~.valid-tooltip{display:block}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-valid,.was-validated .custom-select:valid{border-color:#28a745;padding-right:calc((1em + .75rem) * 3 / 4 + 1.75rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-select.is-valid~.valid-feedback,.custom-select.is-valid~.valid-tooltip,.was-validated .custom-select:valid~.valid-feedback,.was-validated .custom-select:valid~.valid-tooltip{display:block}.form-control-file.is-valid~.valid-feedback,.form-control-file.is-valid~.valid-tooltip,.was-validated .form-control-file:valid~.valid-feedback,.was-validated .form-control-file:valid~.valid-tooltip{display:block}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{border-color:#28a745}.custom-control-input.is-valid~.valid-feedback,.custom-control-input.is-valid~.valid-tooltip,.was-validated .custom-control-input:valid~.valid-feedback,.was-validated .custom-control-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid~.valid-feedback,.custom-file-input.is-valid~.valid-tooltip,.was-validated .custom-file-input:valid~.valid-feedback,.was-validated .custom-file-input:valid~.valid-tooltip{display:block}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E");background-repeat:no-repeat;background-position:center right calc(.375em + .1875rem);background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-control.is-invalid~.invalid-feedback,.form-control.is-invalid~.invalid-tooltip,.was-validated .form-control:invalid~.invalid-feedback,.was-validated .form-control:invalid~.invalid-tooltip{display:block}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{border-color:#dc3545;padding-right:calc((1em + .75rem) * 3 / 4 + 1.75rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-select.is-invalid~.invalid-feedback,.custom-select.is-invalid~.invalid-tooltip,.was-validated .custom-select:invalid~.invalid-feedback,.was-validated .custom-select:invalid~.invalid-tooltip{display:block}.form-control-file.is-invalid~.invalid-feedback,.form-control-file.is-invalid~.invalid-tooltip,.was-validated .form-control-file:invalid~.invalid-feedback,.was-validated .form-control-file:invalid~.invalid-tooltip{display:block}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{border-color:#dc3545}.custom-control-input.is-invalid~.invalid-feedback,.custom-control-input.is-invalid~.invalid-tooltip,.was-validated .custom-control-input:invalid~.invalid-feedback,.was-validated .custom-control-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid~.invalid-feedback,.custom-file-input.is-invalid~.invalid-tooltip,.was-validated .custom-file-input:invalid~.invalid-feedback,.was-validated .custom-file-input:invalid~.invalid-tooltip{display:block}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;-ms-flex-negative:0;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#007bff;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;text-decoration:none}.btn-link:hover{color:#0056b3;text-decoration:underline}.btn-link.focus,.btn-link:focus{text-decoration:underline;box-shadow:none}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#6c757d;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:1 1 auto;flex:1 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:1}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:1}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:last-child),.input-group>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-append,.input-group-prepend{display:-ms-flexbox;display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;z-index:-1;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#007bff;background-color:#007bff}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#80bdff}.custom-control-input:not(:disabled):active~.custom-control-label::before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:#adb5bd solid 1px}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:no-repeat 50%/50% 50%}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#007bff;background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label::after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label::after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;-webkit-transform:translateX(.75rem);transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:disabled~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:calc(1rem + .4rem);padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{transition:none}}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{transition:none}}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label::before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{transition:none}}.nav{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar>.container,.navbar>.container-fluid{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;background-size:100% 100%}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img{width:100%;border-radius:calc(.25rem - 1px)}.card-img-top{width:100%;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img-bottom{width:100%;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{display:-ms-flexbox;display:flex;-ms-flex:1 0 0%;flex:1 0 0%;-ms-flex-direction:column;flex-direction:column;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion>.card{overflow:hidden}.accordion>.card:not(:first-of-type) .card-header:first-child{border-radius:0}.accordion>.card:not(:first-of-type):not(:last-of-type){border-bottom:0;border-radius:0}.accordion>.card:first-of-type{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:last-of-type{border-top-left-radius:0;border-top-right-radius:0}.accordion>.card .card-header{margin-bottom:-1px}.breadcrumb{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:2;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:1;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}a.badge-primary:focus,a.badge-primary:hover{color:#fff;background-color:#0062cc}a.badge-primary.focus,a.badge-primary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:focus,a.badge-secondary:hover{color:#fff;background-color:#545b62}a.badge-secondary.focus,a.badge-secondary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:focus,a.badge-success:hover{color:#fff;background-color:#1e7e34}a.badge-success.focus,a.badge-success:focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:focus,a.badge-info:hover{color:#fff;background-color:#117a8b}a.badge-info.focus,a.badge-info:focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.badge-warning{color:#212529;background-color:#ffc107}a.badge-warning:focus,a.badge-warning:hover{color:#212529;background-color:#d39e00}a.badge-warning.focus,a.badge-warning:focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:focus,a.badge-danger:hover{color:#fff;background-color:#bd2130}a.badge-danger.focus,a.badge-danger:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-light{color:#212529;background-color:#f8f9fa}a.badge-light:focus,a.badge-light:hover{color:#212529;background-color:#dae0e5}a.badge-light.focus,a.badge-light:focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:focus,a.badge-dark:hover{color:#fff;background-color:#1d2124}a.badge-dark.focus,a.badge-dark:focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.media{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start}.media-body{-ms-flex:1;flex:1}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;margin-bottom:-1px;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-horizontal{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}@media (min-width:576px){.list-group-horizontal-sm{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-sm .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal-sm .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}}@media (min-width:768px){.list-group-horizontal-md{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-md .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal-md .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}}@media (min-width:992px){.list-group-horizontal-lg{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-lg .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal-lg .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}}@media (min-width:1200px){.list-group-horizontal-xl{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-xl .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal-xl .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}}.list-group-flush .list-group-item{border-right:0;border-left:0;border-radius:0}.list-group-flush .list-group-item:last-child{margin-bottom:-1px}.list-group-flush:first-child .list-group-item:first-child{border-top:0}.list-group-flush:last-child .list-group-item:last-child{margin-bottom:0;border-bottom:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}a.close.disabled{pointer-events:none}.toast{max-width:350px;overflow:hidden;font-size:.875rem;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-50px);transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{-webkit-transform:none;transform:none}.modal-dialog-scrollable{display:-ms-flexbox;display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{-ms-flex-negative:0;flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);content:""}.modal-dialog-centered.modal-dialog-scrollable{-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:.3rem;border-top-right-radius:.3rem}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:1rem;border-top:1px solid #dee2e6;border-bottom-right-radius:.3rem;border-bottom-left-radius:.3rem}.modal-footer>:not(:first-child){margin-left:.25rem}.modal-footer>:not(:last-child){margin-right:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem)}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow::before,.bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::after,.popover .arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc((.5rem + 1px) * -1)}.bs-popover-auto[x-placement^=top]>.arrow::before,.bs-popover-top>.arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top]>.arrow::after,.bs-popover-top>.arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{left:calc((.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right]>.arrow::before,.bs-popover-right>.arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right]>.arrow::after,.bs-popover-right>.arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc((.5rem + 1px) * -1)}.bs-popover-auto[x-placement^=bottom]>.arrow::before,.bs-popover-bottom>.arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom]>.arrow::after,.bs-popover-bottom>.arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{right:calc((.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left]>.arrow::before,.bs-popover-left>.arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left]>.arrow::after,.bs-popover-left>.arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{-ms-touch-action:pan-y;touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){-webkit-transform:translateX(100%);transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){-webkit-transform:translateX(-100%);transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;-webkit-transform:none;transform:none}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:0s .6s opacity}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:no-repeat 50%/100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@-webkit-keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid currentColor;border-right-color:transparent;border-radius:50%;-webkit-animation:spinner-border .75s linear infinite;animation:spinner-border .75s linear infinite}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1}}@keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:spinner-grow .75s linear infinite;animation:spinner-grow .75s linear infinite}.spinner-grow-sm{width:1rem;height:1rem}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0056b3!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#494f54!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#19692c!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#0f6674!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#ba8b00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#a71d2a!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none!important}.text-break{word-break:break-word!important;overflow-wrap:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,::after,::before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}} -/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/src/main/resources/static/css/discuss-detail.css b/src/main/resources/static/css/discuss-detail.css deleted file mode 100644 index 417737b..0000000 --- a/src/main/resources/static/css/discuss-detail.css +++ /dev/null @@ -1,40 +0,0 @@ -.content { - font-size: 16px; - line-height: 2em; -} - -.replyform textarea { - width: 100%; - height: 200px; -} - -.floor { - background: #dcdadc; - padding: 4px 12px; - border-radius: 3px; - font-size: 14px; -} - -.bg-gray { - background: rgb(238, 238, 238) !important; - border-radius: 20px; -} - -.input-size { - width: 100%; - height: 35px; -} - -/*防止帖子内容超出页面*/ -.mt-4, .my-4 { - margin-top: 1.5rem!important; - word-wrap: break-word; - word-break: normal; -} - -/*防止评论内容超出页面*/ -.media-body { - -ms-flex: 1; - flex: 1; - width: 80%; -} \ No newline at end of file diff --git a/src/main/resources/static/css/editormd.css b/src/main/resources/static/css/editormd.css deleted file mode 100644 index 261b3d9..0000000 --- a/src/main/resources/static/css/editormd.css +++ /dev/null @@ -1,4450 +0,0 @@ -/* - * Editor.md - * - * @file editormd.css - * @version v1.5.0 - * @description Open source online markdown editor. - * @license MIT License - * @author Pandao - * {@link https://github.com/pandao/editor.md} - * @updateTime 2015-06-09 - */ - -@charset "UTF-8"; -/*! prefixes.scss v0.1.0 | Author: Pandao | https://github.com/pandao/prefixes.scss | MIT license | Copyright (c) 2015 */ -.editormd { - width: 90%; - height: 640px; - margin: 0 auto; - text-align: left; - overflow: hidden; - position: relative; - margin-bottom: 15px; - border: 1px solid #ddd; - font-family: "Meiryo UI", "Microsoft YaHei", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, "Monaco", monospace, Tahoma, STXihei, "华文细黑", STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, "宋体", Heiti, "黑体", sans-serif; -} -.editormd *, .editormd *:before, .editormd *:after { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -.editormd a { - text-decoration: none; -} -.editormd img { - border: none; - vertical-align: middle; -} -.editormd > textarea, -.editormd .editormd-html-textarea, -.editormd .editormd-markdown-textarea { - width: 0; - height: 0; - outline: 0; - resize: none; -} -.editormd .editormd-html-textarea, -.editormd .editormd-markdown-textarea { - display: none; -} -.editormd input[type="text"], -.editormd input[type="button"], -.editormd input[type="submit"], -.editormd select, .editormd textarea, .editormd button { - -webkit-appearance: none; - -moz-appearance: none; - -ms-appearance: none; - appearance: none; -} -.editormd ::-webkit-scrollbar { - height: 10px; - width: 7px; - background: rgba(0, 0, 0, 0.1); -} -.editormd ::-webkit-scrollbar:hover { - background: rgba(0, 0, 0, 0.2); -} -.editormd ::-webkit-scrollbar-thumb { - background: rgba(0, 0, 0, 0.3); - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - -ms-border-radius: 6px; - -o-border-radius: 6px; - border-radius: 6px; -} -.editormd ::-webkit-scrollbar-thumb:hover { - -webkit-box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.25); - /* Webkit browsers */ - -moz-box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.25); - /* Firefox */ - -ms-box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.25); - /* IE9 */ - -o-box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.25); - /* Opera(Old) */ - box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.25); - /* IE9+, News */ - background-color: rgba(0, 0, 0, 0.4); -} - -.editormd-user-unselect { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -o-user-select: none; - user-select: none; -} - -.editormd-toolbar { - width: 100%; - min-height: 37px; - background: #fff; - display: none; - position: absolute; - top: 0; - left: 0; - z-index: 10; - border-bottom: 1px solid #ddd; -} - -.editormd-toolbar-container { - padding: 0 8px; - min-height: 35px; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -o-user-select: none; - user-select: none; -} - -.editormd-menu { - margin: 0; - padding: 0; - list-style: none; -} -.editormd-menu > li { - margin: 0; - padding: 5px 1px; - display: inline-block; - position: relative; -} -.editormd-menu > li.divider { - display: inline-block; - text-indent: -9999px; - margin: 0 5px; - height: 65%; - border-right: 1px solid #ddd; -} -.editormd-menu > li > a { - outline: 0; - color: #666; - display: inline-block; - min-width: 24px; - font-size: 16px; - text-decoration: none; - text-align: center; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - -ms-border-radius: 2px; - -o-border-radius: 2px; - border-radius: 2px; - border: 1px solid #fff; - -webkit-transition: all 300ms ease-out; - /* Safari, Chrome */ - -moz-transition: all 300ms ease-out; - /* Firefox 4.0~16.0 */ - transition: all 300ms ease-out; - /* IE >9, FF >15, Opera >12.0 */ -} -.editormd-menu > li > a:hover, .editormd-menu > li > a.active { - border: 1px solid #ddd; - background: #eee; -} -.editormd-menu > li > a > .fa { - text-align: center; - display: block; - padding: 5px; -} -.editormd-menu > li > a > .editormd-bold { - padding: 5px 2px; - display: inline-block; - font-weight: bold; -} -.editormd-menu > li:hover .editormd-dropdown-menu { - display: block; -} -.editormd-menu > li + li > a { - margin-left: 3px; -} - -.editormd-dropdown-menu { - display: none; - background: #fff; - border: 1px solid #ddd; - width: 148px; - list-style: none; - position: absolute; - top: 33px; - left: 0; - z-index: 100; - -webkit-box-shadow: 1px 2px 6px rgba(0, 0, 0, 0.15); - /* Webkit browsers */ - -moz-box-shadow: 1px 2px 6px rgba(0, 0, 0, 0.15); - /* Firefox */ - -ms-box-shadow: 1px 2px 6px rgba(0, 0, 0, 0.15); - /* IE9 */ - -o-box-shadow: 1px 2px 6px rgba(0, 0, 0, 0.15); - /* Opera(Old) */ - box-shadow: 1px 2px 6px rgba(0, 0, 0, 0.15); - /* IE9+, News */ -} -.editormd-dropdown-menu:before, .editormd-dropdown-menu:after { - width: 0; - height: 0; - display: block; - content: ""; - position: absolute; - top: -11px; - left: 8px; - border: 5px solid transparent; -} -.editormd-dropdown-menu:before { - border-bottom-color: #ccc; -} -.editormd-dropdown-menu:after { - border-bottom-color: #ffffff; - top: -10px; -} -.editormd-dropdown-menu > li > a { - color: #666; - display: block; - text-decoration: none; - padding: 8px 10px; -} -.editormd-dropdown-menu > li > a:hover { - background: #f6f6f6; - -webkit-transition: all 300ms ease-out; - /* Safari, Chrome */ - -moz-transition: all 300ms ease-out; - /* Firefox 4.0~16.0 */ - transition: all 300ms ease-out; - /* IE >9, FF >15, Opera >12.0 */ -} -.editormd-dropdown-menu > li + li { - border-top: 1px solid #ddd; -} - -.editormd-container { - margin: 0; - width: 100%; - height: 100%; - overflow: hidden; - padding: 35px 0 0; - position: relative; - background: #fff; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.editormd-dialog { - color: #666; - position: fixed; - z-index: 99999; - display: none; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - -ms-border-radius: 3px; - -o-border-radius: 3px; - border-radius: 3px; - -webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); - /* Webkit browsers */ - -moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); - /* Firefox */ - -ms-box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); - /* IE9 */ - -o-box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); - /* Opera(Old) */ - box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); - /* IE9+, News */ - background: #fff; - font-size: 14px; -} - -.editormd-dialog-container { - position: relative; - padding: 20px; - line-height: 1.4; -} -.editormd-dialog-container h1 { - font-size: 24px; - margin-bottom: 10px; -} -.editormd-dialog-container h1 .fa { - color: #2C7EEA; - padding-right: 5px; -} -.editormd-dialog-container h1 small { - padding-left: 5px; - font-weight: normal; - font-size: 12px; - color: #999; -} -.editormd-dialog-container select { - color: #999; - padding: 3px 8px; - border: 1px solid #ddd; -} - -.editormd-dialog-close { - position: absolute; - top: 12px; - right: 15px; - font-size: 18px; - color: #ccc; - -webkit-transition: color 300ms ease-out; - /* Safari, Chrome */ - -moz-transition: color 300ms ease-out; - /* Firefox 4.0~16.0 */ - transition: color 300ms ease-out; - /* IE >9, FF >15, Opera >12.0 */ -} -.editormd-dialog-close:hover { - color: #999; -} - -.editormd-dialog-header { - padding: 11px 20px; - border-bottom: 1px solid #eee; - -webkit-transition: background 300ms ease-out; - /* Safari, Chrome */ - -moz-transition: background 300ms ease-out; - /* Firefox 4.0~16.0 */ - transition: background 300ms ease-out; - /* IE >9, FF >15, Opera >12.0 */ -} -.editormd-dialog-header:hover { - background: #f6f6f6; -} - -.editormd-dialog-title { - font-size: 14px; -} - -.editormd-dialog-footer { - padding: 10px 0 0 0; - text-align: right; -} - -.editormd-dialog-info { - width: 420px; -} -.editormd-dialog-info h1 { - font-weight: normal; -} -.editormd-dialog-info .editormd-dialog-container { - padding: 20px 25px 25px; -} -.editormd-dialog-info .editormd-dialog-close { - top: 10px; - right: 10px; -} -.editormd-dialog-info p > a, .editormd-dialog-info .hover-link:hover { - color: #2196F3; -} -.editormd-dialog-info .hover-link { - color: #666; -} -.editormd-dialog-info a .fa-external-link { - display: none; -} -.editormd-dialog-info a:hover { - color: #2196F3; -} -.editormd-dialog-info a:hover .fa-external-link { - display: inline-block; -} - -.editormd-mask, -.editormd-container-mask, -.editormd-dialog-mask { - display: none; - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; -} - -.editormd-mask, -.editormd-dialog-mask-bg { - background: #fff; - opacity: 0.5; - filter: alpha(opacity=50); -} - -.editormd-mask { - position: fixed; - background: #000; - opacity: 0.2; - /* W3C */ - filter: alpha(opacity=20); - /* IE */ - z-index: 99998; -} - -.editormd-container-mask, -.editormd-dialog-mask-con { - background: url(../images/loading.gif) no-repeat center center; - -webkit-background-size: 32px 32px; - /* Chrome, iOS, Safari */ - -moz-background-size: 32px 32px; - /* Firefox 3.6~4.0 */ - -o-background-size: 32px 32px; - /* Opera 9.5 */ - background-size: 32px 32px; - /* IE9+, New */ -} - -.editormd-container-mask { - z-index: 20; - display: block; - background-color: #fff; -} - -@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2) { - .editormd-container-mask, - .editormd-dialog-mask-con { - background-image: url(../images/loading@2x.gif); - } -} -@media only screen and (-webkit-min-device-pixel-ratio: 3), only screen and (min-device-pixel-ratio: 3) { - .editormd-container-mask, - .editormd-dialog-mask-con { - background-image: url(../images/loading@3x.gif); - } -} -.editormd-code-block-dialog textarea, -.editormd-preformatted-text-dialog textarea { - width: 100%; - height: 400px; - margin-bottom: 6px; - overflow: auto; - border: 1px solid #eee; - background: #fff; - padding: 15px; - resize: none; -} - -.editormd-code-toolbar { - color: #999; - font-size: 14px; - margin: -5px 0 10px; -} - -.editormd-grid-table { - width: 99%; - display: table; - border: 1px solid #ddd; - border-collapse: collapse; -} - -.editormd-grid-table-row { - width: 100%; - display: table-row; -} -.editormd-grid-table-row a { - font-size: 1.4em; - width: 5%; - height: 36px; - color: #999; - text-align: center; - display: table-cell; - vertical-align: middle; - border: 1px solid #ddd; - text-decoration: none; - -webkit-transition: background-color 300ms ease-out, color 100ms ease-in; - /* Safari, Chrome */ - -moz-transition: background-color 300ms ease-out, color 100ms ease-in; - /* Firefox 4.0~16.0 */ - transition: background-color 300ms ease-out, color 100ms ease-in; - /* IE >9, FF >15, Opera >12.0 */ -} -.editormd-grid-table-row a.selected { - color: #666; - background-color: #eee; -} -.editormd-grid-table-row a:hover { - color: #777; - background-color: #f6f6f6; -} - -.editormd-tab-head { - list-style: none; - border-bottom: 1px solid #ddd; -} -.editormd-tab-head li { - display: inline-block; -} -.editormd-tab-head li a { - color: #999; - display: block; - padding: 6px 12px 5px; - text-align: center; - text-decoration: none; - margin-bottom: -1px; - border: 1px solid #ddd; - -webkit-border-top-left-radius: 3px; - -moz-border-top-left-radius: 3px; - -ms-border-top-left-radius: 3px; - -o-border-top-left-radius: 3px; - border-top-left-radius: 3px; - -webkit-border-top-right-radius: 3px; - -moz-border-top-right-radius: 3px; - -ms-border-top-right-radius: 3px; - -o-border-top-right-radius: 3px; - border-top-right-radius: 3px; - background: #f6f6f6; - -webkit-transition: all 300ms ease-out; - /* Safari, Chrome */ - -moz-transition: all 300ms ease-out; - /* Firefox 4.0~16.0 */ - transition: all 300ms ease-out; - /* IE >9, FF >15, Opera >12.0 */ -} -.editormd-tab-head li a:hover { - color: #666; - background: #eee; -} -.editormd-tab-head li.active a { - color: #666; - background: #fff; - border-bottom-color: #fff; -} -.editormd-tab-head li + li { - margin-left: 3px; -} - -.editormd-tab-box { - padding: 20px 0; -} - -.editormd-form { - color: #666; -} -.editormd-form label { - float: left; - display: block; - width: 75px; - text-align: left; - padding: 7px 0 15px 5px; - margin: 0 0 2px; - font-weight: normal; -} -.editormd-form br { - clear: both; -} -.editormd-form iframe { - display: none; -} -.editormd-form input:focus { - outline: 0; -} -.editormd-form input[type="text"], .editormd-form input[type="number"] { - color: #999; - padding: 8px; - border: 1px solid #ddd; -} -.editormd-form input[type="number"] { - width: 40px; - display: inline-block; - padding: 6px 8px; -} -.editormd-form input[type="text"] { - display: inline-block; - width: 264px; -} -.editormd-form .fa-btns { - display: inline-block; -} -.editormd-form .fa-btns a { - color: #999; - padding: 7px 10px 0 0; - display: inline-block; - text-decoration: none; - text-align: center; -} -.editormd-form .fa-btns .fa { - font-size: 1.3em; -} -.editormd-form .fa-btns label { - float: none; - display: inline-block; - width: auto; - text-align: left; - padding: 0 0 0 5px; - cursor: pointer; -} - -.editormd-form input[type="submit"], .editormd-form .editormd-btn, .editormd-form button, -.editormd-dialog-container input[type="submit"], -.editormd-dialog-container .editormd-btn, -.editormd-dialog-container button, -.editormd-dialog-footer input[type="submit"], -.editormd-dialog-footer .editormd-btn, -.editormd-dialog-footer button { - color: #666; - min-width: 75px; - cursor: pointer; - background: #fff; - padding: 7px 10px; - border: 1px solid #ddd; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - -ms-border-radius: 3px; - -o-border-radius: 3px; - border-radius: 3px; - -webkit-transition: background 300ms ease-out; - /* Safari, Chrome */ - -moz-transition: background 300ms ease-out; - /* Firefox 4.0~16.0 */ - transition: background 300ms ease-out; - /* IE >9, FF >15, Opera >12.0 */ -} -.editormd-form input[type="submit"]:hover, .editormd-form .editormd-btn:hover, .editormd-form button:hover, -.editormd-dialog-container input[type="submit"]:hover, -.editormd-dialog-container .editormd-btn:hover, -.editormd-dialog-container button:hover, -.editormd-dialog-footer input[type="submit"]:hover, -.editormd-dialog-footer .editormd-btn:hover, -.editormd-dialog-footer button:hover { - background: #eee; -} -.editormd-form .editormd-btn, -.editormd-dialog-container .editormd-btn, -.editormd-dialog-footer .editormd-btn { - padding: 5px 8px 4px\0; -} -.editormd-form .editormd-btn + .editormd-btn, -.editormd-dialog-container .editormd-btn + .editormd-btn, -.editormd-dialog-footer .editormd-btn + .editormd-btn { - margin-left: 8px; -} - -.editormd-file-input { - width: 75px; - height: 32px; - margin-left: 8px; - position: relative; - display: inline-block; -} -.editormd-file-input input[type="file"] { - width: 75px; - height: 32px; - opacity: 0; - cursor: pointer; - background: #000; - display: inline-block; - position: absolute; - top: 0; - right: 0; -} -.editormd-file-input input[type="file"]::-webkit-file-upload-button { - visibility: hidden; -} -.editormd-file-input:hover input[type="submit"] { - background: #eee; -} - -.editormd .CodeMirror, .editormd-preview { - display: inline-block; - width: 50%; - height: 100%; - vertical-align: top; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - margin: 0; -} - -.editormd-preview { - position: absolute; - top: 35px; - right: 0; - right: -1px\0; - overflow: auto; - line-height: 1.6; - display: none; - background: #fff; -} - -.editormd .CodeMirror { - z-index: 10; - float: left; - border-right: 1px solid #ddd; - font-size: 14px; - font-family: "YaHei Consolas Hybrid", Consolas, "微软雅黑", "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, "Monaco", courier, monospace; - line-height: 1.6; - margin-top: 35px; -} -.editormd .CodeMirror pre { - font-size: 14px; - padding: 0 12px; -} -.editormd .CodeMirror-linenumbers { - padding: 0 5px; -} -.editormd .CodeMirror-selected { - background: #70B7FF; -} -.editormd .CodeMirror-focused .CodeMirror-selected { - background: #70B7FF; -} -.editormd .CodeMirror, .editormd .CodeMirror-scroll, .editormd .editormd-preview { - -webkit-overflow-scrolling: touch; -} -.editormd .styled-background { - background-color: #ff7; -} -.editormd .CodeMirror-focused .cm-matchhighlight { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFklEQVQI12NgYGBgkKzc8x9CMDAwAAAmhwSbidEoSQAAAABJRU5ErkJggg==); - background-position: bottom; - background-repeat: repeat-x; -} -.editormd .CodeMirror-empty.CodeMirror-focused { - outline: none; -} -.editormd .CodeMirror pre.CodeMirror-placeholder { - color: #999; -} -.editormd .cm-trailingspace { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAYAAAB/qH1jAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QUXCToH00Y1UgAAACFJREFUCNdjPMDBUc/AwNDAAAFMTAwMDA0OP34wQgX/AQBYgwYEx4f9lQAAAABJRU5ErkJggg==); - background-position: bottom left; - background-repeat: repeat-x; -} -.editormd .cm-tab { - background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=); - background-position: right; - background-repeat: no-repeat; -} - -/*! prefixes.scss v0.1.0 | Author: Pandao | https://github.com/pandao/prefixes.scss | MIT license | Copyright (c) 2015 */ -/*! - * Font Awesome 4.3.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */ -/* FONT PATH - * -------------------------- */ -@font-face { - font-family: 'FontAwesome'; - src: url("../fonts/fontawesome-webfont.eot?v=4.3.0"); - src: url("../fonts/fontawesome-webfont.eot?#iefix&v=4.3.0") format("embedded-opentype"), url("../fonts/fontawesome-webfont.woff2?v=4.3.0") format("woff2"), url("../fonts/fontawesome-webfont.woff?v=4.3.0") format("woff"), url("../fonts/fontawesome-webfont.ttf?v=4.3.0") format("truetype"), url("../fonts/fontawesome-webfont.svg?v=4.3.0#fontawesomeregular") format("svg"); - font-weight: normal; - font-style: normal; -} -.fa { - display: inline-block; - font: normal normal normal 14px/1 FontAwesome; - font-size: inherit; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - transform: translate(0, 0); -} - -/* makes the font 33% larger relative to the icon container */ -.fa-lg { - font-size: 1.33333333em; - line-height: 0.75em; - vertical-align: -15%; -} - -.fa-2x { - font-size: 2em; -} - -.fa-3x { - font-size: 3em; -} - -.fa-4x { - font-size: 4em; -} - -.fa-5x { - font-size: 5em; -} - -.fa-fw { - width: 1.28571429em; - text-align: center; -} - -.fa-ul { - padding-left: 0; - margin-left: 2.14285714em; - list-style-type: none; -} - -.fa-ul > li { - position: relative; -} - -.fa-li { - position: absolute; - left: -2.14285714em; - width: 2.14285714em; - top: 0.14285714em; - text-align: center; -} - -.fa-li.fa-lg { - left: -1.85714286em; -} - -.fa-border { - padding: .2em .25em .15em; - border: solid 0.08em #eeeeee; - border-radius: .1em; -} - -.pull-right { - float: right; -} - -.pull-left { - float: left; -} - -.fa.pull-left { - margin-right: .3em; -} - -.fa.pull-right { - margin-left: .3em; -} - -.fa-spin { - -webkit-animation: fa-spin 2s infinite linear; - animation: fa-spin 2s infinite linear; -} - -.fa-pulse { - -webkit-animation: fa-spin 1s infinite steps(8); - animation: fa-spin 1s infinite steps(8); -} - -@-webkit-keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -@keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -.fa-rotate-90 { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); - -webkit-transform: rotate(90deg); - -ms-transform: rotate(90deg); - transform: rotate(90deg); -} - -.fa-rotate-180 { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); - -webkit-transform: rotate(180deg); - -ms-transform: rotate(180deg); - transform: rotate(180deg); -} - -.fa-rotate-270 { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); - -webkit-transform: rotate(270deg); - -ms-transform: rotate(270deg); - transform: rotate(270deg); -} - -.fa-flip-horizontal { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1); - -webkit-transform: scale(-1, 1); - -ms-transform: scale(-1, 1); - transform: scale(-1, 1); -} - -.fa-flip-vertical { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1); - -webkit-transform: scale(1, -1); - -ms-transform: scale(1, -1); - transform: scale(1, -1); -} - -:root .fa-rotate-90, -:root .fa-rotate-180, -:root .fa-rotate-270, -:root .fa-flip-horizontal, -:root .fa-flip-vertical { - filter: none; -} - -.fa-stack { - position: relative; - display: inline-block; - width: 2em; - height: 2em; - line-height: 2em; - vertical-align: middle; -} - -.fa-stack-1x, -.fa-stack-2x { - position: absolute; - left: 0; - width: 100%; - text-align: center; -} - -.fa-stack-1x { - line-height: inherit; -} - -.fa-stack-2x { - font-size: 2em; -} - -.fa-inverse { - color: #ffffff; -} - -/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen - readers do not read off random characters that represent icons */ -.fa-glass:before { - content: "\f000"; -} - -.fa-music:before { - content: "\f001"; -} - -.fa-search:before { - content: "\f002"; -} - -.fa-envelope-o:before { - content: "\f003"; -} - -.fa-heart:before { - content: "\f004"; -} - -.fa-star:before { - content: "\f005"; -} - -.fa-star-o:before { - content: "\f006"; -} - -.fa-user:before { - content: "\f007"; -} - -.fa-film:before { - content: "\f008"; -} - -.fa-th-large:before { - content: "\f009"; -} - -.fa-th:before { - content: "\f00a"; -} - -.fa-th-list:before { - content: "\f00b"; -} - -.fa-check:before { - content: "\f00c"; -} - -.fa-remove:before, -.fa-close:before, -.fa-times:before { - content: "\f00d"; -} - -.fa-search-plus:before { - content: "\f00e"; -} - -.fa-search-minus:before { - content: "\f010"; -} - -.fa-power-off:before { - content: "\f011"; -} - -.fa-signal:before { - content: "\f012"; -} - -.fa-gear:before, -.fa-cog:before { - content: "\f013"; -} - -.fa-trash-o:before { - content: "\f014"; -} - -.fa-home:before { - content: "\f015"; -} - -.fa-file-o:before { - content: "\f016"; -} - -.fa-clock-o:before { - content: "\f017"; -} - -.fa-road:before { - content: "\f018"; -} - -.fa-download:before { - content: "\f019"; -} - -.fa-arrow-circle-o-down:before { - content: "\f01a"; -} - -.fa-arrow-circle-o-up:before { - content: "\f01b"; -} - -.fa-inbox:before { - content: "\f01c"; -} - -.fa-play-circle-o:before { - content: "\f01d"; -} - -.fa-rotate-right:before, -.fa-repeat:before { - content: "\f01e"; -} - -.fa-refresh:before { - content: "\f021"; -} - -.fa-list-alt:before { - content: "\f022"; -} - -.fa-lock:before { - content: "\f023"; -} - -.fa-flag:before { - content: "\f024"; -} - -.fa-headphones:before { - content: "\f025"; -} - -.fa-volume-off:before { - content: "\f026"; -} - -.fa-volume-down:before { - content: "\f027"; -} - -.fa-volume-up:before { - content: "\f028"; -} - -.fa-qrcode:before { - content: "\f029"; -} - -.fa-barcode:before { - content: "\f02a"; -} - -.fa-tag:before { - content: "\f02b"; -} - -.fa-tags:before { - content: "\f02c"; -} - -.fa-book:before { - content: "\f02d"; -} - -.fa-bookmark:before { - content: "\f02e"; -} - -.fa-print:before { - content: "\f02f"; -} - -.fa-camera:before { - content: "\f030"; -} - -.fa-font:before { - content: "\f031"; -} - -.fa-bold:before { - content: "\f032"; -} - -.fa-italic:before { - content: "\f033"; -} - -.fa-text-height:before { - content: "\f034"; -} - -.fa-text-width:before { - content: "\f035"; -} - -.fa-align-left:before { - content: "\f036"; -} - -.fa-align-center:before { - content: "\f037"; -} - -.fa-align-right:before { - content: "\f038"; -} - -.fa-align-justify:before { - content: "\f039"; -} - -.fa-list:before { - content: "\f03a"; -} - -.fa-dedent:before, -.fa-outdent:before { - content: "\f03b"; -} - -.fa-indent:before { - content: "\f03c"; -} - -.fa-video-camera:before { - content: "\f03d"; -} - -.fa-photo:before, -.fa-image:before, -.fa-picture-o:before { - content: "\f03e"; -} - -.fa-pencil:before { - content: "\f040"; -} - -.fa-map-marker:before { - content: "\f041"; -} - -.fa-adjust:before { - content: "\f042"; -} - -.fa-tint:before { - content: "\f043"; -} - -.fa-edit:before, -.fa-pencil-square-o:before { - content: "\f044"; -} - -.fa-share-square-o:before { - content: "\f045"; -} - -.fa-check-square-o:before { - content: "\f046"; -} - -.fa-arrows:before { - content: "\f047"; -} - -.fa-step-backward:before { - content: "\f048"; -} - -.fa-fast-backward:before { - content: "\f049"; -} - -.fa-backward:before { - content: "\f04a"; -} - -.fa-play:before { - content: "\f04b"; -} - -.fa-pause:before { - content: "\f04c"; -} - -.fa-stop:before { - content: "\f04d"; -} - -.fa-forward:before { - content: "\f04e"; -} - -.fa-fast-forward:before { - content: "\f050"; -} - -.fa-step-forward:before { - content: "\f051"; -} - -.fa-eject:before { - content: "\f052"; -} - -.fa-chevron-left:before { - content: "\f053"; -} - -.fa-chevron-right:before { - content: "\f054"; -} - -.fa-plus-circle:before { - content: "\f055"; -} - -.fa-minus-circle:before { - content: "\f056"; -} - -.fa-times-circle:before { - content: "\f057"; -} - -.fa-check-circle:before { - content: "\f058"; -} - -.fa-question-circle:before { - content: "\f059"; -} - -.fa-info-circle:before { - content: "\f05a"; -} - -.fa-crosshairs:before { - content: "\f05b"; -} - -.fa-times-circle-o:before { - content: "\f05c"; -} - -.fa-check-circle-o:before { - content: "\f05d"; -} - -.fa-ban:before { - content: "\f05e"; -} - -.fa-arrow-left:before { - content: "\f060"; -} - -.fa-arrow-right:before { - content: "\f061"; -} - -.fa-arrow-up:before { - content: "\f062"; -} - -.fa-arrow-down:before { - content: "\f063"; -} - -.fa-mail-forward:before, -.fa-share:before { - content: "\f064"; -} - -.fa-expand:before { - content: "\f065"; -} - -.fa-compress:before { - content: "\f066"; -} - -.fa-plus:before { - content: "\f067"; -} - -.fa-minus:before { - content: "\f068"; -} - -.fa-asterisk:before { - content: "\f069"; -} - -.fa-exclamation-circle:before { - content: "\f06a"; -} - -.fa-gift:before { - content: "\f06b"; -} - -.fa-leaf:before { - content: "\f06c"; -} - -.fa-fire:before { - content: "\f06d"; -} - -.fa-eye:before { - content: "\f06e"; -} - -.fa-eye-slash:before { - content: "\f070"; -} - -.fa-warning:before, -.fa-exclamation-triangle:before { - content: "\f071"; -} - -.fa-plane:before { - content: "\f072"; -} - -.fa-calendar:before { - content: "\f073"; -} - -.fa-random:before { - content: "\f074"; -} - -.fa-comment:before { - content: "\f075"; -} - -.fa-magnet:before { - content: "\f076"; -} - -.fa-chevron-up:before { - content: "\f077"; -} - -.fa-chevron-down:before { - content: "\f078"; -} - -.fa-retweet:before { - content: "\f079"; -} - -.fa-shopping-cart:before { - content: "\f07a"; -} - -.fa-folder:before { - content: "\f07b"; -} - -.fa-folder-open:before { - content: "\f07c"; -} - -.fa-arrows-v:before { - content: "\f07d"; -} - -.fa-arrows-h:before { - content: "\f07e"; -} - -.fa-bar-chart-o:before, -.fa-bar-chart:before { - content: "\f080"; -} - -.fa-twitter-square:before { - content: "\f081"; -} - -.fa-facebook-square:before { - content: "\f082"; -} - -.fa-camera-retro:before { - content: "\f083"; -} - -.fa-key:before { - content: "\f084"; -} - -.fa-gears:before, -.fa-cogs:before { - content: "\f085"; -} - -.fa-comments:before { - content: "\f086"; -} - -.fa-thumbs-o-up:before { - content: "\f087"; -} - -.fa-thumbs-o-down:before { - content: "\f088"; -} - -.fa-star-half:before { - content: "\f089"; -} - -.fa-heart-o:before { - content: "\f08a"; -} - -.fa-sign-out:before { - content: "\f08b"; -} - -.fa-linkedin-square:before { - content: "\f08c"; -} - -.fa-thumb-tack:before { - content: "\f08d"; -} - -.fa-external-link:before { - content: "\f08e"; -} - -.fa-sign-in:before { - content: "\f090"; -} - -.fa-trophy:before { - content: "\f091"; -} - -.fa-github-square:before { - content: "\f092"; -} - -.fa-upload:before { - content: "\f093"; -} - -.fa-lemon-o:before { - content: "\f094"; -} - -.fa-phone:before { - content: "\f095"; -} - -.fa-square-o:before { - content: "\f096"; -} - -.fa-bookmark-o:before { - content: "\f097"; -} - -.fa-phone-square:before { - content: "\f098"; -} - -.fa-twitter:before { - content: "\f099"; -} - -.fa-facebook-f:before, -.fa-facebook:before { - content: "\f09a"; -} - -.fa-github:before { - content: "\f09b"; -} - -.fa-unlock:before { - content: "\f09c"; -} - -.fa-credit-card:before { - content: "\f09d"; -} - -.fa-rss:before { - content: "\f09e"; -} - -.fa-hdd-o:before { - content: "\f0a0"; -} - -.fa-bullhorn:before { - content: "\f0a1"; -} - -.fa-bell:before { - content: "\f0f3"; -} - -.fa-certificate:before { - content: "\f0a3"; -} - -.fa-hand-o-right:before { - content: "\f0a4"; -} - -.fa-hand-o-left:before { - content: "\f0a5"; -} - -.fa-hand-o-up:before { - content: "\f0a6"; -} - -.fa-hand-o-down:before { - content: "\f0a7"; -} - -.fa-arrow-circle-left:before { - content: "\f0a8"; -} - -.fa-arrow-circle-right:before { - content: "\f0a9"; -} - -.fa-arrow-circle-up:before { - content: "\f0aa"; -} - -.fa-arrow-circle-down:before { - content: "\f0ab"; -} - -.fa-globe:before { - content: "\f0ac"; -} - -.fa-wrench:before { - content: "\f0ad"; -} - -.fa-tasks:before { - content: "\f0ae"; -} - -.fa-filter:before { - content: "\f0b0"; -} - -.fa-briefcase:before { - content: "\f0b1"; -} - -.fa-arrows-alt:before { - content: "\f0b2"; -} - -.fa-group:before, -.fa-users:before { - content: "\f0c0"; -} - -.fa-chain:before, -.fa-link:before { - content: "\f0c1"; -} - -.fa-cloud:before { - content: "\f0c2"; -} - -.fa-flask:before { - content: "\f0c3"; -} - -.fa-cut:before, -.fa-scissors:before { - content: "\f0c4"; -} - -.fa-copy:before, -.fa-files-o:before { - content: "\f0c5"; -} - -.fa-paperclip:before { - content: "\f0c6"; -} - -.fa-save:before, -.fa-floppy-o:before { - content: "\f0c7"; -} - -.fa-square:before { - content: "\f0c8"; -} - -.fa-navicon:before, -.fa-reorder:before, -.fa-bars:before { - content: "\f0c9"; -} - -.fa-list-ul:before { - content: "\f0ca"; -} - -.fa-list-ol:before { - content: "\f0cb"; -} - -.fa-strikethrough:before { - content: "\f0cc"; -} - -.fa-underline:before { - content: "\f0cd"; -} - -.fa-table:before { - content: "\f0ce"; -} - -.fa-magic:before { - content: "\f0d0"; -} - -.fa-truck:before { - content: "\f0d1"; -} - -.fa-pinterest:before { - content: "\f0d2"; -} - -.fa-pinterest-square:before { - content: "\f0d3"; -} - -.fa-google-plus-square:before { - content: "\f0d4"; -} - -.fa-google-plus:before { - content: "\f0d5"; -} - -.fa-money:before { - content: "\f0d6"; -} - -.fa-caret-down:before { - content: "\f0d7"; -} - -.fa-caret-up:before { - content: "\f0d8"; -} - -.fa-caret-left:before { - content: "\f0d9"; -} - -.fa-caret-right:before { - content: "\f0da"; -} - -.fa-columns:before { - content: "\f0db"; -} - -.fa-unsorted:before, -.fa-sort:before { - content: "\f0dc"; -} - -.fa-sort-down:before, -.fa-sort-desc:before { - content: "\f0dd"; -} - -.fa-sort-up:before, -.fa-sort-asc:before { - content: "\f0de"; -} - -.fa-envelope:before { - content: "\f0e0"; -} - -.fa-linkedin:before { - content: "\f0e1"; -} - -.fa-rotate-left:before, -.fa-undo:before { - content: "\f0e2"; -} - -.fa-legal:before, -.fa-gavel:before { - content: "\f0e3"; -} - -.fa-dashboard:before, -.fa-tachometer:before { - content: "\f0e4"; -} - -.fa-comment-o:before { - content: "\f0e5"; -} - -.fa-comments-o:before { - content: "\f0e6"; -} - -.fa-flash:before, -.fa-bolt:before { - content: "\f0e7"; -} - -.fa-sitemap:before { - content: "\f0e8"; -} - -.fa-umbrella:before { - content: "\f0e9"; -} - -.fa-paste:before, -.fa-clipboard:before { - content: "\f0ea"; -} - -.fa-lightbulb-o:before { - content: "\f0eb"; -} - -.fa-exchange:before { - content: "\f0ec"; -} - -.fa-cloud-download:before { - content: "\f0ed"; -} - -.fa-cloud-upload:before { - content: "\f0ee"; -} - -.fa-user-md:before { - content: "\f0f0"; -} - -.fa-stethoscope:before { - content: "\f0f1"; -} - -.fa-suitcase:before { - content: "\f0f2"; -} - -.fa-bell-o:before { - content: "\f0a2"; -} - -.fa-coffee:before { - content: "\f0f4"; -} - -.fa-cutlery:before { - content: "\f0f5"; -} - -.fa-file-text-o:before { - content: "\f0f6"; -} - -.fa-building-o:before { - content: "\f0f7"; -} - -.fa-hospital-o:before { - content: "\f0f8"; -} - -.fa-ambulance:before { - content: "\f0f9"; -} - -.fa-medkit:before { - content: "\f0fa"; -} - -.fa-fighter-jet:before { - content: "\f0fb"; -} - -.fa-beer:before { - content: "\f0fc"; -} - -.fa-h-square:before { - content: "\f0fd"; -} - -.fa-plus-square:before { - content: "\f0fe"; -} - -.fa-angle-double-left:before { - content: "\f100"; -} - -.fa-angle-double-right:before { - content: "\f101"; -} - -.fa-angle-double-up:before { - content: "\f102"; -} - -.fa-angle-double-down:before { - content: "\f103"; -} - -.fa-angle-left:before { - content: "\f104"; -} - -.fa-angle-right:before { - content: "\f105"; -} - -.fa-angle-up:before { - content: "\f106"; -} - -.fa-angle-down:before { - content: "\f107"; -} - -.fa-desktop:before { - content: "\f108"; -} - -.fa-laptop:before { - content: "\f109"; -} - -.fa-tablet:before { - content: "\f10a"; -} - -.fa-mobile-phone:before, -.fa-mobile:before { - content: "\f10b"; -} - -.fa-circle-o:before { - content: "\f10c"; -} - -.fa-quote-left:before { - content: "\f10d"; -} - -.fa-quote-right:before { - content: "\f10e"; -} - -.fa-spinner:before { - content: "\f110"; -} - -.fa-circle:before { - content: "\f111"; -} - -.fa-mail-reply:before, -.fa-reply:before { - content: "\f112"; -} - -.fa-github-alt:before { - content: "\f113"; -} - -.fa-folder-o:before { - content: "\f114"; -} - -.fa-folder-open-o:before { - content: "\f115"; -} - -.fa-smile-o:before { - content: "\f118"; -} - -.fa-frown-o:before { - content: "\f119"; -} - -.fa-meh-o:before { - content: "\f11a"; -} - -.fa-gamepad:before { - content: "\f11b"; -} - -.fa-keyboard-o:before { - content: "\f11c"; -} - -.fa-flag-o:before { - content: "\f11d"; -} - -.fa-flag-checkered:before { - content: "\f11e"; -} - -.fa-terminal:before { - content: "\f120"; -} - -.fa-code:before { - content: "\f121"; -} - -.fa-mail-reply-all:before, -.fa-reply-all:before { - content: "\f122"; -} - -.fa-star-half-empty:before, -.fa-star-half-full:before, -.fa-star-half-o:before { - content: "\f123"; -} - -.fa-location-arrow:before { - content: "\f124"; -} - -.fa-crop:before { - content: "\f125"; -} - -.fa-code-fork:before { - content: "\f126"; -} - -.fa-unlink:before, -.fa-chain-broken:before { - content: "\f127"; -} - -.fa-question:before { - content: "\f128"; -} - -.fa-info:before { - content: "\f129"; -} - -.fa-exclamation:before { - content: "\f12a"; -} - -.fa-superscript:before { - content: "\f12b"; -} - -.fa-subscript:before { - content: "\f12c"; -} - -.fa-eraser:before { - content: "\f12d"; -} - -.fa-puzzle-piece:before { - content: "\f12e"; -} - -.fa-microphone:before { - content: "\f130"; -} - -.fa-microphone-slash:before { - content: "\f131"; -} - -.fa-shield:before { - content: "\f132"; -} - -.fa-calendar-o:before { - content: "\f133"; -} - -.fa-fire-extinguisher:before { - content: "\f134"; -} - -.fa-rocket:before { - content: "\f135"; -} - -.fa-maxcdn:before { - content: "\f136"; -} - -.fa-chevron-circle-left:before { - content: "\f137"; -} - -.fa-chevron-circle-right:before { - content: "\f138"; -} - -.fa-chevron-circle-up:before { - content: "\f139"; -} - -.fa-chevron-circle-down:before { - content: "\f13a"; -} - -.fa-html5:before { - content: "\f13b"; -} - -.fa-css3:before { - content: "\f13c"; -} - -.fa-anchor:before { - content: "\f13d"; -} - -.fa-unlock-alt:before { - content: "\f13e"; -} - -.fa-bullseye:before { - content: "\f140"; -} - -.fa-ellipsis-h:before { - content: "\f141"; -} - -.fa-ellipsis-v:before { - content: "\f142"; -} - -.fa-rss-square:before { - content: "\f143"; -} - -.fa-play-circle:before { - content: "\f144"; -} - -.fa-ticket:before { - content: "\f145"; -} - -.fa-minus-square:before { - content: "\f146"; -} - -.fa-minus-square-o:before { - content: "\f147"; -} - -.fa-level-up:before { - content: "\f148"; -} - -.fa-level-down:before { - content: "\f149"; -} - -.fa-check-square:before { - content: "\f14a"; -} - -.fa-pencil-square:before { - content: "\f14b"; -} - -.fa-external-link-square:before { - content: "\f14c"; -} - -.fa-share-square:before { - content: "\f14d"; -} - -.fa-compass:before { - content: "\f14e"; -} - -.fa-toggle-down:before, -.fa-caret-square-o-down:before { - content: "\f150"; -} - -.fa-toggle-up:before, -.fa-caret-square-o-up:before { - content: "\f151"; -} - -.fa-toggle-right:before, -.fa-caret-square-o-right:before { - content: "\f152"; -} - -.fa-euro:before, -.fa-eur:before { - content: "\f153"; -} - -.fa-gbp:before { - content: "\f154"; -} - -.fa-dollar:before, -.fa-usd:before { - content: "\f155"; -} - -.fa-rupee:before, -.fa-inr:before { - content: "\f156"; -} - -.fa-cny:before, -.fa-rmb:before, -.fa-yen:before, -.fa-jpy:before { - content: "\f157"; -} - -.fa-ruble:before, -.fa-rouble:before, -.fa-rub:before { - content: "\f158"; -} - -.fa-won:before, -.fa-krw:before { - content: "\f159"; -} - -.fa-bitcoin:before, -.fa-btc:before { - content: "\f15a"; -} - -.fa-file:before { - content: "\f15b"; -} - -.fa-file-text:before { - content: "\f15c"; -} - -.fa-sort-alpha-asc:before { - content: "\f15d"; -} - -.fa-sort-alpha-desc:before { - content: "\f15e"; -} - -.fa-sort-amount-asc:before { - content: "\f160"; -} - -.fa-sort-amount-desc:before { - content: "\f161"; -} - -.fa-sort-numeric-asc:before { - content: "\f162"; -} - -.fa-sort-numeric-desc:before { - content: "\f163"; -} - -.fa-thumbs-up:before { - content: "\f164"; -} - -.fa-thumbs-down:before { - content: "\f165"; -} - -.fa-youtube-square:before { - content: "\f166"; -} - -.fa-youtube:before { - content: "\f167"; -} - -.fa-xing:before { - content: "\f168"; -} - -.fa-xing-square:before { - content: "\f169"; -} - -.fa-youtube-play:before { - content: "\f16a"; -} - -.fa-dropbox:before { - content: "\f16b"; -} - -.fa-stack-overflow:before { - content: "\f16c"; -} - -.fa-instagram:before { - content: "\f16d"; -} - -.fa-flickr:before { - content: "\f16e"; -} - -.fa-adn:before { - content: "\f170"; -} - -.fa-bitbucket:before { - content: "\f171"; -} - -.fa-bitbucket-square:before { - content: "\f172"; -} - -.fa-tumblr:before { - content: "\f173"; -} - -.fa-tumblr-square:before { - content: "\f174"; -} - -.fa-long-arrow-down:before { - content: "\f175"; -} - -.fa-long-arrow-up:before { - content: "\f176"; -} - -.fa-long-arrow-left:before { - content: "\f177"; -} - -.fa-long-arrow-right:before { - content: "\f178"; -} - -.fa-apple:before { - content: "\f179"; -} - -.fa-windows:before { - content: "\f17a"; -} - -.fa-android:before { - content: "\f17b"; -} - -.fa-linux:before { - content: "\f17c"; -} - -.fa-dribbble:before { - content: "\f17d"; -} - -.fa-skype:before { - content: "\f17e"; -} - -.fa-foursquare:before { - content: "\f180"; -} - -.fa-trello:before { - content: "\f181"; -} - -.fa-female:before { - content: "\f182"; -} - -.fa-male:before { - content: "\f183"; -} - -.fa-gittip:before, -.fa-gratipay:before { - content: "\f184"; -} - -.fa-sun-o:before { - content: "\f185"; -} - -.fa-moon-o:before { - content: "\f186"; -} - -.fa-archive:before { - content: "\f187"; -} - -.fa-bug:before { - content: "\f188"; -} - -.fa-vk:before { - content: "\f189"; -} - -.fa-weibo:before { - content: "\f18a"; -} - -.fa-renren:before { - content: "\f18b"; -} - -.fa-pagelines:before { - content: "\f18c"; -} - -.fa-stack-exchange:before { - content: "\f18d"; -} - -.fa-arrow-circle-o-right:before { - content: "\f18e"; -} - -.fa-arrow-circle-o-left:before { - content: "\f190"; -} - -.fa-toggle-left:before, -.fa-caret-square-o-left:before { - content: "\f191"; -} - -.fa-dot-circle-o:before { - content: "\f192"; -} - -.fa-wheelchair:before { - content: "\f193"; -} - -.fa-vimeo-square:before { - content: "\f194"; -} - -.fa-turkish-lira:before, -.fa-try:before { - content: "\f195"; -} - -.fa-plus-square-o:before { - content: "\f196"; -} - -.fa-space-shuttle:before { - content: "\f197"; -} - -.fa-slack:before { - content: "\f198"; -} - -.fa-envelope-square:before { - content: "\f199"; -} - -.fa-wordpress:before { - content: "\f19a"; -} - -.fa-openid:before { - content: "\f19b"; -} - -.fa-institution:before, -.fa-bank:before, -.fa-university:before { - content: "\f19c"; -} - -.fa-mortar-board:before, -.fa-graduation-cap:before { - content: "\f19d"; -} - -.fa-yahoo:before { - content: "\f19e"; -} - -.fa-google:before { - content: "\f1a0"; -} - -.fa-reddit:before { - content: "\f1a1"; -} - -.fa-reddit-square:before { - content: "\f1a2"; -} - -.fa-stumbleupon-circle:before { - content: "\f1a3"; -} - -.fa-stumbleupon:before { - content: "\f1a4"; -} - -.fa-delicious:before { - content: "\f1a5"; -} - -.fa-digg:before { - content: "\f1a6"; -} - -.fa-pied-piper:before { - content: "\f1a7"; -} - -.fa-pied-piper-alt:before { - content: "\f1a8"; -} - -.fa-drupal:before { - content: "\f1a9"; -} - -.fa-joomla:before { - content: "\f1aa"; -} - -.fa-language:before { - content: "\f1ab"; -} - -.fa-fax:before { - content: "\f1ac"; -} - -.fa-building:before { - content: "\f1ad"; -} - -.fa-child:before { - content: "\f1ae"; -} - -.fa-paw:before { - content: "\f1b0"; -} - -.fa-spoon:before { - content: "\f1b1"; -} - -.fa-cube:before { - content: "\f1b2"; -} - -.fa-cubes:before { - content: "\f1b3"; -} - -.fa-behance:before { - content: "\f1b4"; -} - -.fa-behance-square:before { - content: "\f1b5"; -} - -.fa-steam:before { - content: "\f1b6"; -} - -.fa-steam-square:before { - content: "\f1b7"; -} - -.fa-recycle:before { - content: "\f1b8"; -} - -.fa-automobile:before, -.fa-car:before { - content: "\f1b9"; -} - -.fa-cab:before, -.fa-taxi:before { - content: "\f1ba"; -} - -.fa-tree:before { - content: "\f1bb"; -} - -.fa-spotify:before { - content: "\f1bc"; -} - -.fa-deviantart:before { - content: "\f1bd"; -} - -.fa-soundcloud:before { - content: "\f1be"; -} - -.fa-database:before { - content: "\f1c0"; -} - -.fa-file-pdf-o:before { - content: "\f1c1"; -} - -.fa-file-word-o:before { - content: "\f1c2"; -} - -.fa-file-excel-o:before { - content: "\f1c3"; -} - -.fa-file-powerpoint-o:before { - content: "\f1c4"; -} - -.fa-file-photo-o:before, -.fa-file-picture-o:before, -.fa-file-image-o:before { - content: "\f1c5"; -} - -.fa-file-zip-o:before, -.fa-file-archive-o:before { - content: "\f1c6"; -} - -.fa-file-sound-o:before, -.fa-file-audio-o:before { - content: "\f1c7"; -} - -.fa-file-movie-o:before, -.fa-file-video-o:before { - content: "\f1c8"; -} - -.fa-file-code-o:before { - content: "\f1c9"; -} - -.fa-vine:before { - content: "\f1ca"; -} - -.fa-codepen:before { - content: "\f1cb"; -} - -.fa-jsfiddle:before { - content: "\f1cc"; -} - -.fa-life-bouy:before, -.fa-life-buoy:before, -.fa-life-saver:before, -.fa-support:before, -.fa-life-ring:before { - content: "\f1cd"; -} - -.fa-circle-o-notch:before { - content: "\f1ce"; -} - -.fa-ra:before, -.fa-rebel:before { - content: "\f1d0"; -} - -.fa-ge:before, -.fa-empire:before { - content: "\f1d1"; -} - -.fa-git-square:before { - content: "\f1d2"; -} - -.fa-git:before { - content: "\f1d3"; -} - -.fa-hacker-news:before { - content: "\f1d4"; -} - -.fa-tencent-weibo:before { - content: "\f1d5"; -} - -.fa-qq:before { - content: "\f1d6"; -} - -.fa-wechat:before, -.fa-weixin:before { - content: "\f1d7"; -} - -.fa-send:before, -.fa-paper-plane:before { - content: "\f1d8"; -} - -.fa-send-o:before, -.fa-paper-plane-o:before { - content: "\f1d9"; -} - -.fa-history:before { - content: "\f1da"; -} - -.fa-genderless:before, -.fa-circle-thin:before { - content: "\f1db"; -} - -.fa-header:before { - content: "\f1dc"; -} - -.fa-paragraph:before { - content: "\f1dd"; -} - -.fa-sliders:before { - content: "\f1de"; -} - -.fa-share-alt:before { - content: "\f1e0"; -} - -.fa-share-alt-square:before { - content: "\f1e1"; -} - -.fa-bomb:before { - content: "\f1e2"; -} - -.fa-soccer-ball-o:before, -.fa-futbol-o:before { - content: "\f1e3"; -} - -.fa-tty:before { - content: "\f1e4"; -} - -.fa-binoculars:before { - content: "\f1e5"; -} - -.fa-plug:before { - content: "\f1e6"; -} - -.fa-slideshare:before { - content: "\f1e7"; -} - -.fa-twitch:before { - content: "\f1e8"; -} - -.fa-yelp:before { - content: "\f1e9"; -} - -.fa-newspaper-o:before { - content: "\f1ea"; -} - -.fa-wifi:before { - content: "\f1eb"; -} - -.fa-calculator:before { - content: "\f1ec"; -} - -.fa-paypal:before { - content: "\f1ed"; -} - -.fa-google-wallet:before { - content: "\f1ee"; -} - -.fa-cc-visa:before { - content: "\f1f0"; -} - -.fa-cc-mastercard:before { - content: "\f1f1"; -} - -.fa-cc-discover:before { - content: "\f1f2"; -} - -.fa-cc-amex:before { - content: "\f1f3"; -} - -.fa-cc-paypal:before { - content: "\f1f4"; -} - -.fa-cc-stripe:before { - content: "\f1f5"; -} - -.fa-bell-slash:before { - content: "\f1f6"; -} - -.fa-bell-slash-o:before { - content: "\f1f7"; -} - -.fa-trash:before { - content: "\f1f8"; -} - -.fa-copyright:before { - content: "\f1f9"; -} - -.fa-at:before { - content: "\f1fa"; -} - -.fa-eyedropper:before { - content: "\f1fb"; -} - -.fa-paint-brush:before { - content: "\f1fc"; -} - -.fa-birthday-cake:before { - content: "\f1fd"; -} - -.fa-area-chart:before { - content: "\f1fe"; -} - -.fa-pie-chart:before { - content: "\f200"; -} - -.fa-line-chart:before { - content: "\f201"; -} - -.fa-lastfm:before { - content: "\f202"; -} - -.fa-lastfm-square:before { - content: "\f203"; -} - -.fa-toggle-off:before { - content: "\f204"; -} - -.fa-toggle-on:before { - content: "\f205"; -} - -.fa-bicycle:before { - content: "\f206"; -} - -.fa-bus:before { - content: "\f207"; -} - -.fa-ioxhost:before { - content: "\f208"; -} - -.fa-angellist:before { - content: "\f209"; -} - -.fa-cc:before { - content: "\f20a"; -} - -.fa-shekel:before, -.fa-sheqel:before, -.fa-ils:before { - content: "\f20b"; -} - -.fa-meanpath:before { - content: "\f20c"; -} - -.fa-buysellads:before { - content: "\f20d"; -} - -.fa-connectdevelop:before { - content: "\f20e"; -} - -.fa-dashcube:before { - content: "\f210"; -} - -.fa-forumbee:before { - content: "\f211"; -} - -.fa-leanpub:before { - content: "\f212"; -} - -.fa-sellsy:before { - content: "\f213"; -} - -.fa-shirtsinbulk:before { - content: "\f214"; -} - -.fa-simplybuilt:before { - content: "\f215"; -} - -.fa-skyatlas:before { - content: "\f216"; -} - -.fa-cart-plus:before { - content: "\f217"; -} - -.fa-cart-arrow-down:before { - content: "\f218"; -} - -.fa-diamond:before { - content: "\f219"; -} - -.fa-ship:before { - content: "\f21a"; -} - -.fa-user-secret:before { - content: "\f21b"; -} - -.fa-motorcycle:before { - content: "\f21c"; -} - -.fa-street-view:before { - content: "\f21d"; -} - -.fa-heartbeat:before { - content: "\f21e"; -} - -.fa-venus:before { - content: "\f221"; -} - -.fa-mars:before { - content: "\f222"; -} - -.fa-mercury:before { - content: "\f223"; -} - -.fa-transgender:before { - content: "\f224"; -} - -.fa-transgender-alt:before { - content: "\f225"; -} - -.fa-venus-double:before { - content: "\f226"; -} - -.fa-mars-double:before { - content: "\f227"; -} - -.fa-venus-mars:before { - content: "\f228"; -} - -.fa-mars-stroke:before { - content: "\f229"; -} - -.fa-mars-stroke-v:before { - content: "\f22a"; -} - -.fa-mars-stroke-h:before { - content: "\f22b"; -} - -.fa-neuter:before { - content: "\f22c"; -} - -.fa-facebook-official:before { - content: "\f230"; -} - -.fa-pinterest-p:before { - content: "\f231"; -} - -.fa-whatsapp:before { - content: "\f232"; -} - -.fa-server:before { - content: "\f233"; -} - -.fa-user-plus:before { - content: "\f234"; -} - -.fa-user-times:before { - content: "\f235"; -} - -.fa-hotel:before, -.fa-bed:before { - content: "\f236"; -} - -.fa-viacoin:before { - content: "\f237"; -} - -.fa-train:before { - content: "\f238"; -} - -.fa-subway:before { - content: "\f239"; -} - -.fa-medium:before { - content: "\f23a"; -} - -/*! prefixes.scss v0.1.0 | Author: Pandao | https://github.com/pandao/prefixes.scss | MIT license | Copyright (c) 2015 */ -@font-face { - font-family: 'editormd-logo'; - src: url("../fonts/editormd-logo.eot?-5y8q6h"); - src: url("../fonts/editormd-logo.eot?#iefix-5y8q6h") format("embedded-opentype"), url("../fonts/editormd-logo.woff?-5y8q6h") format("woff"), url("../fonts/editormd-logo.ttf?-5y8q6h") format("truetype"), url("../fonts/editormd-logo.svg?-5y8q6h#icomoon") format("svg"); - font-weight: normal; - font-style: normal; -} -.editormd-logo, -.editormd-logo-1x, -.editormd-logo-2x, -.editormd-logo-3x, -.editormd-logo-4x, -.editormd-logo-5x, -.editormd-logo-6x, -.editormd-logo-7x, -.editormd-logo-8x { - font-family: 'editormd-logo'; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - font-size: inherit; - line-height: 1; - display: inline-block; - text-rendering: auto; - vertical-align: inherit; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -.editormd-logo:before, -.editormd-logo-1x:before, -.editormd-logo-2x:before, -.editormd-logo-3x:before, -.editormd-logo-4x:before, -.editormd-logo-5x:before, -.editormd-logo-6x:before, -.editormd-logo-7x:before, -.editormd-logo-8x:before { - content: "\e1987"; - /* - HTML Entity 󡦇 - example: - */ -} - -.editormd-logo-1x { - font-size: 1em; -} - -.editormd-logo-lg { - font-size: 1.2em; -} - -.editormd-logo-2x { - font-size: 2em; -} - -.editormd-logo-3x { - font-size: 3em; -} - -.editormd-logo-4x { - font-size: 4em; -} - -.editormd-logo-5x { - font-size: 5em; -} - -.editormd-logo-6x { - font-size: 6em; -} - -.editormd-logo-7x { - font-size: 7em; -} - -.editormd-logo-8x { - font-size: 8em; -} - -.editormd-logo-color { - color: #2196F3; -} - -/*! github-markdown-css | The MIT License (MIT) | Copyright (c) Sindre Sorhus (sindresorhus.com) | https://github.com/sindresorhus/github-markdown-css */ -@font-face { - font-family: octicons-anchor; - src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAYcAA0AAAAACjQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABMAAAABwAAAAca8vGTk9TLzIAAAFMAAAARAAAAFZG1VHVY21hcAAAAZAAAAA+AAABQgAP9AdjdnQgAAAB0AAAAAQAAAAEACICiGdhc3AAAAHUAAAACAAAAAj//wADZ2x5ZgAAAdwAAADRAAABEKyikaNoZWFkAAACsAAAAC0AAAA2AtXoA2hoZWEAAALgAAAAHAAAACQHngNFaG10eAAAAvwAAAAQAAAAEAwAACJsb2NhAAADDAAAAAoAAAAKALIAVG1heHAAAAMYAAAAHwAAACABEAB2bmFtZQAAAzgAAALBAAAFu3I9x/Nwb3N0AAAF/AAAAB0AAAAvaoFvbwAAAAEAAAAAzBdyYwAAAADP2IQvAAAAAM/bz7t4nGNgZGFgnMDAysDB1Ml0hoGBoR9CM75mMGLkYGBgYmBlZsAKAtJcUxgcPsR8iGF2+O/AEMPsznAYKMwIkgMA5REMOXicY2BgYGaAYBkGRgYQsAHyGMF8FgYFIM0ChED+h5j//yEk/3KoSgZGNgYYk4GRCUgwMaACRoZhDwCs7QgGAAAAIgKIAAAAAf//AAJ4nHWMMQrCQBBF/0zWrCCIKUQsTDCL2EXMohYGSSmorScInsRGL2DOYJe0Ntp7BK+gJ1BxF1stZvjz/v8DRghQzEc4kIgKwiAppcA9LtzKLSkdNhKFY3HF4lK69ExKslx7Xa+vPRVS43G98vG1DnkDMIBUgFN0MDXflU8tbaZOUkXUH0+U27RoRpOIyCKjbMCVejwypzJJG4jIwb43rfl6wbwanocrJm9XFYfskuVC5K/TPyczNU7b84CXcbxks1Un6H6tLH9vf2LRnn8Ax7A5WQAAAHicY2BkYGAA4teL1+yI57f5ysDNwgAC529f0kOmWRiYVgEpDgYmEA8AUzEKsQAAAHicY2BkYGB2+O/AEMPCAAJAkpEBFbAAADgKAe0EAAAiAAAAAAQAAAAEAAAAAAAAKgAqACoAiAAAeJxjYGRgYGBhsGFgYgABEMkFhAwM/xn0QAIAD6YBhwB4nI1Ty07cMBS9QwKlQapQW3VXySvEqDCZGbGaHULiIQ1FKgjWMxknMfLEke2A+IJu+wntrt/QbVf9gG75jK577Lg8K1qQPCfnnnt8fX1NRC/pmjrk/zprC+8D7tBy9DHgBXoWfQ44Av8t4Bj4Z8CLtBL9CniJluPXASf0Lm4CXqFX8Q84dOLnMB17N4c7tBo1AS/Qi+hTwBH4rwHHwN8DXqQ30XXAS7QaLwSc0Gn8NuAVWou/gFmnjLrEaEh9GmDdDGgL3B4JsrRPDU2hTOiMSuJUIdKQQayiAth69r6akSSFqIJuA19TrzCIaY8sIoxyrNIrL//pw7A2iMygkX5vDj+G+kuoLdX4GlGK/8Lnlz6/h9MpmoO9rafrz7ILXEHHaAx95s9lsI7AHNMBWEZHULnfAXwG9/ZqdzLI08iuwRloXE8kfhXYAvE23+23DU3t626rbs8/8adv+9DWknsHp3E17oCf+Z48rvEQNZ78paYM38qfk3v/u3l3u3GXN2Dmvmvpf1Srwk3pB/VSsp512bA/GG5i2WJ7wu430yQ5K3nFGiOqgtmSB5pJVSizwaacmUZzZhXLlZTq8qGGFY2YcSkqbth6aW1tRmlaCFs2016m5qn36SbJrqosG4uMV4aP2PHBmB3tjtmgN2izkGQyLWprekbIntJFing32a5rKWCN/SdSoga45EJykyQ7asZvHQ8PTm6cslIpwyeyjbVltNikc2HTR7YKh9LBl9DADC0U/jLcBZDKrMhUBfQBvXRzLtFtjU9eNHKin0x5InTqb8lNpfKv1s1xHzTXRqgKzek/mb7nB8RZTCDhGEX3kK/8Q75AmUM/eLkfA+0Hi908Kx4eNsMgudg5GLdRD7a84npi+YxNr5i5KIbW5izXas7cHXIMAau1OueZhfj+cOcP3P8MNIWLyYOBuxL6DRylJ4cAAAB4nGNgYoAALjDJyIAOWMCiTIxMLDmZedkABtIBygAAAA==) format("woff"); -} -.markdown-body { - -ms-text-size-adjust: 100%; - -webkit-text-size-adjust: 100%; - color: #333; - overflow: hidden; - font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", "Monaco", monospace, Tahoma, STXihei, "华文细黑", STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, "宋体", Heiti, "黑体", sans-serif; - font-size: 16px; - line-height: 1.6; - word-wrap: break-word; -} - -.markdown-body a { - background: transparent; -} - -.markdown-body a:active, -.markdown-body a:hover { - outline: 0; -} - -.markdown-body strong { - font-weight: bold; -} - -.markdown-body h1 { - font-size: 2em; - margin: 0.67em 0; -} - -.markdown-body img { - border: 0; -} - -.markdown-body hr { - -moz-box-sizing: content-box; - box-sizing: content-box; - height: 0; -} - -.markdown-body pre { - overflow: auto; -} - -.markdown-body code, -.markdown-body kbd, -.markdown-body pre { - font-family: "Meiryo UI", "YaHei Consolas Hybrid", Consolas, "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; - font-size: 1em; -} - -.markdown-body input { - color: inherit; - font: inherit; - margin: 0; -} - -.markdown-body html input[disabled] { - cursor: default; -} - -.markdown-body input { - line-height: normal; -} - -.markdown-body input[type="checkbox"] { - -moz-box-sizing: border-box; - box-sizing: border-box; - padding: 0; -} - -.markdown-body table { - border-collapse: collapse; - border-spacing: 0; -} - -.markdown-body td, -.markdown-body th { - padding: 0; -} - -.markdown-body * { - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.markdown-body input { - font: 13px/1.4 Helvetica, arial, freesans, clean, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol"; -} - -.markdown-body a { - color: #4183c4; - text-decoration: none; -} - -.markdown-body a:hover, -.markdown-body a:active { - text-decoration: underline; -} - -.markdown-body hr { - height: 0; - margin: 15px 0; - overflow: hidden; - background: transparent; - border: 0; - border-bottom: 1px solid #ddd; -} - -.markdown-body hr:before { - display: table; - content: ""; -} - -.markdown-body hr:after { - display: table; - clear: both; - content: ""; -} - -.markdown-body h1, -.markdown-body h2, -.markdown-body h3, -.markdown-body h4, -.markdown-body h5, -.markdown-body h6 { - margin-top: 15px; - margin-bottom: 15px; - line-height: 1.1; -} - -.markdown-body h1 { - font-size: 30px; -} - -.markdown-body h2 { - font-size: 21px; -} - -.markdown-body h3 { - font-size: 16px; -} - -.markdown-body h4 { - font-size: 14px; -} - -.markdown-body h5 { - font-size: 12px; -} - -.markdown-body h6 { - font-size: 11px; -} - -.markdown-body blockquote { - margin: 0; -} - -.markdown-body ul, -.markdown-body ol { - padding: 0; - margin-top: 0; - margin-bottom: 0; -} - -.markdown-body ol ol, -.markdown-body ul ol { - list-style-type: lower-roman; -} - -.markdown-body ul ul ol, -.markdown-body ul ol ol, -.markdown-body ol ul ol, -.markdown-body ol ol ol { - list-style-type: lower-alpha; -} - -.markdown-body dd { - margin-left: 0; -} - -.markdown-body code { - font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; - font-size: 12px; -} - -.markdown-body pre { - margin-top: 0; - margin-bottom: 0; - font: 12px Consolas, "Liberation Mono", Menlo, Courier, monospace; -} - -.markdown-body .octicon { - font: normal normal 16px octicons-anchor; - line-height: 1; - display: inline-block; - text-decoration: none; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.markdown-body .octicon-link:before { - content: '\f05c'; -} - -.markdown-body > *:first-child { - margin-top: 0 !important; -} - -.markdown-body > *:last-child { - margin-bottom: 0 !important; -} - -.markdown-body .anchor { - position: absolute; - top: 0; - left: 0; - display: block; - padding-right: 6px; - padding-left: 30px; - margin-left: -30px; -} - -.markdown-body .anchor:focus { - outline: none; -} - -.markdown-body h1, -.markdown-body h2, -.markdown-body h3, -.markdown-body h4, -.markdown-body h5, -.markdown-body h6 { - position: relative; - margin-top: 1em; - margin-bottom: 16px; - font-weight: bold; - line-height: 1.4; -} - -.markdown-body h1 .octicon-link, -.markdown-body h2 .octicon-link, -.markdown-body h3 .octicon-link, -.markdown-body h4 .octicon-link, -.markdown-body h5 .octicon-link, -.markdown-body h6 .octicon-link { - display: none; - color: #000; - vertical-align: middle; -} - -.markdown-body h1:hover .anchor, -.markdown-body h2:hover .anchor, -.markdown-body h3:hover .anchor, -.markdown-body h4:hover .anchor, -.markdown-body h5:hover .anchor, -.markdown-body h6:hover .anchor { - padding-left: 8px; - margin-left: -30px; - text-decoration: none; -} - -.markdown-body h1:hover .anchor .octicon-link, -.markdown-body h2:hover .anchor .octicon-link, -.markdown-body h3:hover .anchor .octicon-link, -.markdown-body h4:hover .anchor .octicon-link, -.markdown-body h5:hover .anchor .octicon-link, -.markdown-body h6:hover .anchor .octicon-link { - display: inline-block; -} - -.markdown-body h1 { - padding-bottom: 0.3em; - font-size: 2.25em; - line-height: 1.2; - border-bottom: 1px solid #eee; -} - -.markdown-body h1 .anchor { - line-height: 1; -} - -.markdown-body h2 { - padding-bottom: 0.3em; - font-size: 1.75em; - line-height: 1.225; - border-bottom: 1px solid #eee; -} - -.markdown-body h2 .anchor { - line-height: 1; -} - -.markdown-body h3 { - font-size: 1.5em; - line-height: 1.43; -} - -.markdown-body h3 .anchor { - line-height: 1.2; -} - -.markdown-body h4 { - font-size: 1.25em; -} - -.markdown-body h4 .anchor { - line-height: 1.2; -} - -.markdown-body h5 { - font-size: 1em; -} - -.markdown-body h5 .anchor { - line-height: 1.1; -} - -.markdown-body h6 { - font-size: 1em; - color: #777; -} - -.markdown-body h6 .anchor { - line-height: 1.1; -} - -.markdown-body p, -.markdown-body blockquote, -.markdown-body ul, -.markdown-body ol, -.markdown-body dl, -.markdown-body table, -.markdown-body pre { - margin-top: 0; - margin-bottom: 16px; -} - -/* -.markdown-body hr { - height: 4px; - padding: 0; - margin: 16px 0; - background-color: #e7e7e7; - border: 0 none; -}*/ -.markdown-body ul, -.markdown-body ol { - padding-left: 2em; -} - -.markdown-body ul ul, -.markdown-body ul ol, -.markdown-body ol ol, -.markdown-body ol ul { - margin-top: 0; - margin-bottom: 0; -} - -.markdown-body li > p { - margin-top: 16px; -} - -.markdown-body dl { - padding: 0; -} - -.markdown-body dl dt { - padding: 0; - margin-top: 16px; - font-size: 1em; - font-style: italic; - font-weight: bold; -} - -.markdown-body dl dd { - padding: 0 16px; - margin-bottom: 16px; -} - -.markdown-body blockquote { - padding: 0 15px; - color: #777; - border-left: 4px solid #ddd; -} - -.markdown-body blockquote > :first-child { - margin-top: 0; -} - -.markdown-body blockquote > :last-child { - margin-bottom: 0; -} - -.markdown-body table { - display: block; - width: 100%; - overflow: auto; - word-break: normal; - word-break: keep-all; -} - -.markdown-body table th { - font-weight: bold; -} - -.markdown-body table th, -.markdown-body table td { - padding: 6px 13px; - border: 1px solid #ddd; -} - -.markdown-body table tr { - background-color: #fff; - border-top: 1px solid #ccc; -} - -.markdown-body table tr:nth-child(2n) { - background-color: #f8f8f8; -} - -.markdown-body img { - max-width: 100%; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.markdown-body code { - padding: 0; - padding-top: 0.2em; - padding-bottom: 0.2em; - margin: 0; - font-size: 85%; - background-color: rgba(0, 0, 0, 0.04); - border-radius: 3px; -} - -.markdown-body code:before, -.markdown-body code:after { - letter-spacing: -0.2em; - content: "\00a0"; -} - -.markdown-body pre > code { - padding: 0; - margin: 0; - font-size: 100%; - word-break: normal; - white-space: pre; - background: transparent; - border: 0; -} - -.markdown-body .highlight { - margin-bottom: 16px; -} - -.markdown-body .highlight pre, -.markdown-body pre { - padding: 16px; - overflow: auto; - font-size: 85%; - line-height: 1.45; - background-color: #f7f7f7; - border-radius: 3px; -} - -.markdown-body .highlight pre { - margin-bottom: 0; - word-break: normal; -} - -.markdown-body pre { - word-wrap: normal; -} - -.markdown-body pre code { - display: inline; - max-width: initial; - padding: 0; - margin: 0; - overflow: initial; - line-height: inherit; - word-wrap: normal; - background-color: transparent; - border: 0; -} - -.markdown-body pre code:before, -.markdown-body pre code:after { - content: normal; -} - -.markdown-body kbd { - display: inline-block; - padding: 3px 5px; - font-size: 11px; - line-height: 10px; - color: #555; - vertical-align: middle; - background-color: #fcfcfc; - border: solid 1px #ccc; - border-bottom-color: #bbb; - border-radius: 3px; - box-shadow: inset 0 -1px 0 #bbb; -} - -.markdown-body .pl-c { - color: #969896; -} - -.markdown-body .pl-c1, -.markdown-body .pl-mdh, -.markdown-body .pl-mm, -.markdown-body .pl-mp, -.markdown-body .pl-mr, -.markdown-body .pl-s1 .pl-v, -.markdown-body .pl-s3, -.markdown-body .pl-sc, -.markdown-body .pl-sv { - color: #0086b3; -} - -.markdown-body .pl-e, -.markdown-body .pl-en { - color: #795da3; -} - -.markdown-body .pl-s1 .pl-s2, -.markdown-body .pl-smi, -.markdown-body .pl-smp, -.markdown-body .pl-stj, -.markdown-body .pl-vo, -.markdown-body .pl-vpf { - color: #333; -} - -.markdown-body .pl-ent { - color: #63a35c; -} - -.markdown-body .pl-k, -.markdown-body .pl-s, -.markdown-body .pl-st { - color: #a71d5d; -} - -.markdown-body .pl-pds, -.markdown-body .pl-s1, -.markdown-body .pl-s1 .pl-pse .pl-s2, -.markdown-body .pl-sr, -.markdown-body .pl-sr .pl-cce, -.markdown-body .pl-sr .pl-sra, -.markdown-body .pl-sr .pl-sre, -.markdown-body .pl-src { - color: #df5000; -} - -.markdown-body .pl-mo, -.markdown-body .pl-v { - color: #1d3e81; -} - -.markdown-body .pl-id { - color: #b52a1d; -} - -.markdown-body .pl-ii { - background-color: #b52a1d; - color: #f8f8f8; -} - -.markdown-body .pl-sr .pl-cce { - color: #63a35c; - font-weight: bold; -} - -.markdown-body .pl-ml { - color: #693a17; -} - -.markdown-body .pl-mh, -.markdown-body .pl-mh .pl-en, -.markdown-body .pl-ms { - color: #1d3e81; - font-weight: bold; -} - -.markdown-body .pl-mq { - color: #008080; -} - -.markdown-body .pl-mi { - color: #333; - font-style: italic; -} - -.markdown-body .pl-mb { - color: #333; - font-weight: bold; -} - -.markdown-body .pl-md, -.markdown-body .pl-mdhf { - background-color: #ffecec; - color: #bd2c00; -} - -.markdown-body .pl-mdht, -.markdown-body .pl-mi1 { - background-color: #eaffea; - color: #55a532; -} - -.markdown-body .pl-mdr { - color: #795da3; - font-weight: bold; -} - -.markdown-body kbd { - display: inline-block; - padding: 3px 5px; - font: 11px Consolas, "Liberation Mono", Menlo, Courier, monospace; - line-height: 10px; - color: #555; - vertical-align: middle; - background-color: #fcfcfc; - border: solid 1px #ccc; - border-bottom-color: #bbb; - border-radius: 3px; - box-shadow: inset 0 -1px 0 #bbb; -} - -.markdown-body .task-list-item { - list-style-type: none; -} - -.markdown-body .task-list-item + .task-list-item { - margin-top: 3px; -} - -.markdown-body .task-list-item input { - float: left; - margin: 0.3em 0 0.25em -1.6em; - vertical-align: middle; -} - -.markdown-body :checked + .radio-label { - z-index: 1; - position: relative; - border-color: #4183c4; -} - -.editormd-preview-container, .editormd-html-preview { - text-align: left; - font-size: 14px; - line-height: 1.6; - padding: 20px; - overflow: auto; - width: 100%; - background-color: #fff; -} -.editormd-preview-container blockquote, .editormd-html-preview blockquote { - color: #666; - border-left: 4px solid #ddd; - padding-left: 20px; - margin-left: 0; - font-size: 14px; - font-style: italic; -} -.editormd-preview-container p code, .editormd-html-preview p code { - margin-left: 5px; - margin-right: 4px; -} -.editormd-preview-container abbr, .editormd-html-preview abbr { - background: #ffffdd; -} -.editormd-preview-container hr, .editormd-html-preview hr { - height: 1px; - border: none; - border-top: 1px solid #ddd; - background: none; -} -.editormd-preview-container code, .editormd-html-preview code { - border: 1px solid #ddd; - background: #f6f6f6; - padding: 3px; - border-radius: 3px; - font-size: 14px; -} -.editormd-preview-container pre, .editormd-html-preview pre { - border: 1px solid #ddd; - background: #f6f6f6; - padding: 10px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - -ms-border-radius: 3px; - -o-border-radius: 3px; - border-radius: 3px; -} -.editormd-preview-container pre code, .editormd-html-preview pre code { - padding: 0; -} -.editormd-preview-container pre, .editormd-preview-container code, .editormd-preview-container kbd, .editormd-html-preview pre, .editormd-html-preview code, .editormd-html-preview kbd { - font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; -} -.editormd-preview-container table thead tr, .editormd-html-preview table thead tr { - background-color: #F8F8F8; -} -.editormd-preview-container p.editormd-tex, .editormd-html-preview p.editormd-tex { - text-align: center; -} -.editormd-preview-container span.editormd-tex, .editormd-html-preview span.editormd-tex { - margin: 0 5px; -} -.editormd-preview-container .emoji, .editormd-html-preview .emoji { - width: 24px; - height: 24px; -} -.editormd-preview-container .katex, .editormd-html-preview .katex { - font-size: 1.4em; -} -.editormd-preview-container .sequence-diagram, .editormd-preview-container .flowchart, .editormd-html-preview .sequence-diagram, .editormd-html-preview .flowchart { - margin: 0 auto; - text-align: center; -} -.editormd-preview-container .sequence-diagram svg, .editormd-preview-container .flowchart svg, .editormd-html-preview .sequence-diagram svg, .editormd-html-preview .flowchart svg { - margin: 0 auto; -} -.editormd-preview-container .sequence-diagram text, .editormd-preview-container .flowchart text, .editormd-html-preview .sequence-diagram text, .editormd-html-preview .flowchart text { - font-size: 15px !important; - font-family: "YaHei Consolas Hybrid", Consolas, "Microsoft YaHei", "Malgun Gothic", "Segoe UI", Helvetica, Arial !important; -} - -/*! Pretty printing styles. Used with prettify.js. */ -/* SPAN elements with the classes below are added by prettyprint. */ -.pln { - color: #000; -} - -/* plain text */ -@media screen { - .str { - color: #080; - } - - /* string content */ - .kwd { - color: #008; - } - - /* a keyword */ - .com { - color: #800; - } - - /* a comment */ - .typ { - color: #606; - } - - /* a type name */ - .lit { - color: #066; - } - - /* a literal value */ - /* punctuation, lisp open bracket, lisp close bracket */ - .pun, .opn, .clo { - color: #660; - } - - .tag { - color: #008; - } - - /* a markup tag name */ - .atn { - color: #606; - } - - /* a markup attribute name */ - .atv { - color: #080; - } - - /* a markup attribute value */ - .dec, .var { - color: #606; - } - - /* a declaration; a variable name */ - .fun { - color: red; - } - - /* a function name */ -} -/* Use higher contrast and text-weight for printable form. */ -@media print, projection { - .str { - color: #060; - } - - .kwd { - color: #006; - font-weight: bold; - } - - .com { - color: #600; - font-style: italic; - } - - .typ { - color: #404; - font-weight: bold; - } - - .lit { - color: #044; - } - - .pun, .opn, .clo { - color: #440; - } - - .tag { - color: #006; - font-weight: bold; - } - - .atn { - color: #404; - } - - .atv { - color: #060; - } -} -/* Put a border around prettyprinted code snippets. */ -pre.prettyprint { - padding: 2px; - border: 1px solid #888; -} - -/* Specify class=linenums on a pre to get line numbering */ -ol.linenums { - margin-top: 0; - margin-bottom: 0; -} - -/* IE indents via margin-left */ -li.L0, -li.L1, -li.L2, -li.L3, -li.L5, -li.L6, -li.L7, -li.L8 { - list-style-type: none; -} - -/* Alternate shading for lines */ -li.L1, -li.L3, -li.L5, -li.L7, -li.L9 { - background: #eee; -} - -.editormd-preview-container pre.prettyprint, .editormd-html-preview pre.prettyprint { - padding: 10px; - border: 1px solid #ddd; - white-space: pre-wrap; - word-wrap: break-word; -} -.editormd-preview-container ol.linenums, .editormd-html-preview ol.linenums { - color: #999; - padding-left: 2.5em; -} -.editormd-preview-container ol.linenums li, .editormd-html-preview ol.linenums li { - list-style-type: decimal; -} -.editormd-preview-container ol.linenums li code, .editormd-html-preview ol.linenums li code { - border: none; - background: none; - padding: 0; -} - -.editormd-preview-container .editormd-toc-menu, .editormd-html-preview .editormd-toc-menu { - margin: 8px 0 12px 0; - display: inline-block; -} -.editormd-preview-container .editormd-toc-menu > .markdown-toc, .editormd-html-preview .editormd-toc-menu > .markdown-toc { - position: relative; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - -ms-border-radius: 4px; - -o-border-radius: 4px; - border-radius: 4px; - border: 1px solid #ddd; - display: inline-block; - font-size: 1em; -} -.editormd-preview-container .editormd-toc-menu > .markdown-toc > ul, .editormd-html-preview .editormd-toc-menu > .markdown-toc > ul { - width: 160%; - min-width: 180px; - position: absolute; - left: -1px; - top: -2px; - z-index: 100; - padding: 0 10px 10px; - display: none; - background: #fff; - border: 1px solid #ddd; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - -ms-border-radius: 4px; - -o-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); - /* Webkit browsers */ - -moz-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); - /* Firefox */ - -ms-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); - /* IE9 */ - -o-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); - /* Opera(Old) */ - box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); - /* IE9+, News */ -} -.editormd-preview-container .editormd-toc-menu > .markdown-toc > ul > li ul, .editormd-html-preview .editormd-toc-menu > .markdown-toc > ul > li ul { - width: 100%; - min-width: 180px; - border: 1px solid #ddd; - display: none; - background: #fff; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - -ms-border-radius: 4px; - -o-border-radius: 4px; - border-radius: 4px; -} -.editormd-preview-container .editormd-toc-menu > .markdown-toc > ul > li a, .editormd-html-preview .editormd-toc-menu > .markdown-toc > ul > li a { - color: #666; - padding: 6px 10px; - display: block; - -webkit-transition: background-color 500ms ease-out; - /* Safari, Chrome */ - -moz-transition: background-color 500ms ease-out; - /* Firefox 4.0~16.0 */ - transition: background-color 500ms ease-out; - /* IE >9, FF >15, Opera >12.0 */ -} -.editormd-preview-container .editormd-toc-menu > .markdown-toc > ul > li a:hover, .editormd-html-preview .editormd-toc-menu > .markdown-toc > ul > li a:hover { - background-color: #f6f6f6; -} -.editormd-preview-container .editormd-toc-menu > .markdown-toc li, .editormd-html-preview .editormd-toc-menu > .markdown-toc li { - position: relative; -} -.editormd-preview-container .editormd-toc-menu > .markdown-toc li > ul, .editormd-html-preview .editormd-toc-menu > .markdown-toc li > ul { - position: absolute; - top: 32px; - left: 10%; - display: none; - -webkit-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); - /* Webkit browsers */ - -moz-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); - /* Firefox */ - -ms-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); - /* IE9 */ - -o-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); - /* Opera(Old) */ - box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); - /* IE9+, News */ -} -.editormd-preview-container .editormd-toc-menu > .markdown-toc li > ul:before, .editormd-preview-container .editormd-toc-menu > .markdown-toc li > ul:after, .editormd-html-preview .editormd-toc-menu > .markdown-toc li > ul:before, .editormd-html-preview .editormd-toc-menu > .markdown-toc li > ul:after { - pointer-events: pointer-events; - position: absolute; - left: 15px; - top: -6px; - display: block; - content: ""; - width: 0; - height: 0; - border: 6px solid transparent; - border-width: 0 6px 6px; - z-index: 10; -} -.editormd-preview-container .editormd-toc-menu > .markdown-toc li > ul:before, .editormd-html-preview .editormd-toc-menu > .markdown-toc li > ul:before { - border-bottom-color: #ccc; -} -.editormd-preview-container .editormd-toc-menu > .markdown-toc li > ul:after, .editormd-html-preview .editormd-toc-menu > .markdown-toc li > ul:after { - border-bottom-color: #ffffff; - top: -5px; -} -.editormd-preview-container .editormd-toc-menu ul, .editormd-html-preview .editormd-toc-menu ul { - list-style: none; -} -.editormd-preview-container .editormd-toc-menu a, .editormd-html-preview .editormd-toc-menu a { - text-decoration: none; -} -.editormd-preview-container .editormd-toc-menu h1, .editormd-html-preview .editormd-toc-menu h1 { - font-size: 16px; - padding: 5px 0 10px 10px; - line-height: 1; - border-bottom: 1px solid #eee; -} -.editormd-preview-container .editormd-toc-menu h1 .fa, .editormd-html-preview .editormd-toc-menu h1 .fa { - padding-left: 10px; -} -.editormd-preview-container .editormd-toc-menu .toc-menu-btn, .editormd-html-preview .editormd-toc-menu .toc-menu-btn { - color: #666; - min-width: 180px; - padding: 5px 10px; - border-radius: 4px; - display: inline-block; - -webkit-transition: background-color 500ms ease-out; - /* Safari, Chrome */ - -moz-transition: background-color 500ms ease-out; - /* Firefox 4.0~16.0 */ - transition: background-color 500ms ease-out; - /* IE >9, FF >15, Opera >12.0 */ -} -.editormd-preview-container .editormd-toc-menu .toc-menu-btn:hover, .editormd-html-preview .editormd-toc-menu .toc-menu-btn:hover { - background-color: #f6f6f6; -} -.editormd-preview-container .editormd-toc-menu .toc-menu-btn .fa, .editormd-html-preview .editormd-toc-menu .toc-menu-btn .fa { - float: right; - padding: 3px 0 0 10px; - font-size: 1.3em; -} - -.markdown-body .editormd-toc-menu ul { - padding-left: 0; -} -.markdown-body .highlight pre, .markdown-body pre { - line-height: 1.6; -} - -hr.editormd-page-break { - border: 1px dotted #ccc; - font-size: 0; - height: 2px; -} - -@media only print { - hr.editormd-page-break { - background: none; - border: none; - height: 0; - } -} -.editormd-html-preview textarea { - display: none; -} -.editormd-html-preview hr.editormd-page-break { - background: none; - border: none; - height: 0; -} - -.editormd-preview-close-btn { - color: #fff; - padding: 4px 6px; - font-size: 18px; - -webkit-border-radius: 500px; - -moz-border-radius: 500px; - -ms-border-radius: 500px; - -o-border-radius: 500px; - border-radius: 500px; - display: none; - background-color: #ccc; - position: absolute; - top: 25px; - right: 35px; - z-index: 19; - -webkit-transition: background-color 300ms ease-out; - /* Safari, Chrome */ - -moz-transition: background-color 300ms ease-out; - /* Firefox 4.0~16.0 */ - transition: background-color 300ms ease-out; - /* IE >9, FF >15, Opera >12.0 */ -} -.editormd-preview-close-btn:hover { - background-color: #999; -} - -.editormd-preview-active { - width: 100%; - padding: 40px; -} - -/* Preview dark theme */ -.editormd-preview-theme-dark { - color: #777; - background: #2C2827; -} -.editormd-preview-theme-dark .editormd-preview-container { - color: #888; - background-color: #2C2827; -} -.editormd-preview-theme-dark .editormd-preview-container pre.prettyprint { - border: none; -} -.editormd-preview-theme-dark .editormd-preview-container blockquote { - color: #555; - padding: 0.5em; - background: #222; - border-color: #333; -} -.editormd-preview-theme-dark .editormd-preview-container abbr { - color: #fff; - padding: 1px 3px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - -ms-border-radius: 3px; - -o-border-radius: 3px; - border-radius: 3px; - background: #ff9900; -} -.editormd-preview-theme-dark .editormd-preview-container code { - color: #fff; - border: none; - padding: 1px 3px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - -ms-border-radius: 3px; - -o-border-radius: 3px; - border-radius: 3px; - background: #5A9600; -} -.editormd-preview-theme-dark .editormd-preview-container table { - border: none; -} -.editormd-preview-theme-dark .editormd-preview-container .fa-emoji { - color: #B4BF42; -} -.editormd-preview-theme-dark .editormd-preview-container .katex { - color: #FEC93F; -} -.editormd-preview-theme-dark .editormd-toc-menu > .markdown-toc { - background: #fff; - border: none; -} -.editormd-preview-theme-dark .editormd-toc-menu > .markdown-toc h1 { - border-color: #ddd; -} -.editormd-preview-theme-dark .markdown-body h1, .editormd-preview-theme-dark .markdown-body h2, .editormd-preview-theme-dark .markdown-body hr { - border-color: #222; -} -.editormd-preview-theme-dark pre { - color: #999; - background-color: #111; - background-color: rgba(0, 0, 0, 0.4); - /* plain text */ -} -.editormd-preview-theme-dark pre .pln { - color: #999; -} -.editormd-preview-theme-dark li.L1, .editormd-preview-theme-dark li.L3, .editormd-preview-theme-dark li.L5, .editormd-preview-theme-dark li.L7, .editormd-preview-theme-dark li.L9 { - background: none; -} -.editormd-preview-theme-dark [class*=editormd-logo] { - color: #2196F3; -} -.editormd-preview-theme-dark .sequence-diagram text { - fill: #fff; -} -.editormd-preview-theme-dark .sequence-diagram rect, .editormd-preview-theme-dark .sequence-diagram path { - color: #fff; - fill: #64D1CB; - stroke: #64D1CB; -} -.editormd-preview-theme-dark .flowchart rect, .editormd-preview-theme-dark .flowchart path { - stroke: #A6C6FF; -} -.editormd-preview-theme-dark .flowchart rect { - fill: #A6C6FF; -} -.editormd-preview-theme-dark .flowchart text { - fill: #5879B4; -} - -@media screen { - .editormd-preview-theme-dark { - /* string content */ - /* a keyword */ - /* a comment */ - /* a type name */ - /* a literal value */ - /* punctuation, lisp open bracket, lisp close bracket */ - /* a markup tag name */ - /* a markup attribute name */ - /* a markup attribute value */ - /* a declaration; a variable name */ - /* a function name */ - } - .editormd-preview-theme-dark .str { - color: #080; - } - .editormd-preview-theme-dark .kwd { - color: #ff9900; - } - .editormd-preview-theme-dark .com { - color: #444444; - } - .editormd-preview-theme-dark .typ { - color: #606; - } - .editormd-preview-theme-dark .lit { - color: #066; - } - .editormd-preview-theme-dark .pun, .editormd-preview-theme-dark .opn, .editormd-preview-theme-dark .clo { - color: #660; - } - .editormd-preview-theme-dark .tag { - color: #ff9900; - } - .editormd-preview-theme-dark .atn { - color: #6C95F5; - } - .editormd-preview-theme-dark .atv { - color: #080; - } - .editormd-preview-theme-dark .dec, .editormd-preview-theme-dark .var { - color: #008BA7; - } - .editormd-preview-theme-dark .fun { - color: red; - } -} -.editormd-onlyread .editormd-toolbar { - display: none; -} -.editormd-onlyread .CodeMirror { - margin-top: 0; -} -.editormd-onlyread .editormd-preview { - top: 0; -} - -.editormd-fullscreen { - position: fixed; - top: 0; - left: 0; - border: none; - margin: 0 auto; -} - -/* Editor.md Dark theme */ -.editormd-theme-dark { - border-color: #1a1a17; -} -.editormd-theme-dark .editormd-toolbar { - background: #1A1A17; - border-color: #1a1a17; -} -.editormd-theme-dark .editormd-menu > li > a { - color: #777; - border-color: #1a1a17; -} -.editormd-theme-dark .editormd-menu > li > a:hover, .editormd-theme-dark .editormd-menu > li > a.active { - border-color: #333; - background: #333; -} -.editormd-theme-dark .editormd-menu > li.divider { - border-right: 1px solid #111; -} -.editormd-theme-dark .CodeMirror { - border-right: 1px solid rgba(0, 0, 0, 0.1); -} diff --git a/src/main/resources/static/css/global.css b/src/main/resources/static/css/global.css deleted file mode 100644 index 112a25d..0000000 --- a/src/main/resources/static/css/global.css +++ /dev/null @@ -1,198 +0,0 @@ -html { - height: 100%; -} - -body { - background: #eee; - font-family: arial, STHeiti, 'Microsoft YaHei', \5b8b\4f53; - font-size: 14px; - height: 100%; -} - -.btn-primary { - color: #fff; - background-color: #ff6a46; - border-color: #ff6a46; -} - -.nk-container { - position: relative; - height: auto; - min-height: 100%; -} - - -.container { - width: 960px; - padding: 0; - border-radius: 20px; -} - -header .navbar-brand { - background: url('https://gitee.com/veal98/images/raw/master/img/greateCommunityLogo.png') no-repeat; - background-size: 147px 42px; - width: 147px; - height: 42px; - margin: 5px 15px 5px 0; -} - -header .navbar { - padding: 5px 0; - font-size: 16px; -} - -.nav-link { - color: rgb(113, 119, 145) !important; -} - -.nav-link:hover{ - color: rgb(119, 84, 223) !important; -} - -.dropdown-item { - color: rgb(119, 84, 223); -} -.text-secondary { - color: #6c757d !important; -} - -.pb-3, .py-3 { - border-radius: 10px; - border: 1px solid #dee2e6; - padding: 20px; -} - -.serach-btn { - color: #fff; - background: rgb(119, 84, 223); -} - -.page-link { - color: rgb(119, 84, 223); -} - -.page-item.active .page-link { - background-color: rgb(119, 84, 223); -} - -header .badge { - position: absolute; - top: -3px; - left: 60px; -} - -.navbar-dark .navbar-toggler { - background: rgb(119, 84, 223); - opacity: 80%; -} - - - -footer { - padding: 20px 0; - font-size: 12px; - position: absolute; - bottom: 0; - width: 100%; -} - -footer .qrcode { - text-align: center; -} - -footer .detail-info{ - border-left: 1px solid #888; -} - -footer .company-info li { - padding-left: 16px; - margin: 4px 0; -} - -.main { - padding: 20px 0; - padding-bottom: 200px; -} - -.main .container { - background: #fff; - padding: 20px; - box-shadow: 5px 16px 23px 5px #cfcccc; -} - -i { - font-style: normal; -} - -u { - text-decoration: none; -} - -b { - font-weight: normal; -} - -a { - color: #000; -} - -a:hover { - text-decoration: none; -} - -.font-size-12 { - font-size: 12px; -} -.font-size-14 { - font-size: 14px; -} -.font-size-16 { - font-size: 16px; -} -.font-size-18 { - font-size: 18px; -} -.font-size-20 { - font-size: 20px; -} -.font-size-22 { - font-size: 20px; -} -.font-size-24 { - font-size: 20px; -} - -.hidden { - display: none; -} - -.rt-0 { - right: 0; - top: 0; -} - -.square { - display: inline-block; - width: 7px; - height: 7px; - background: #ff6547; - margin-bottom: 2px; - margin-right: 3px; -} - -.bg-gray { - background: #eff0f2; -} -.bg-light { - background: #fff !important; -} - -.user-header { - width: 50px; - height: 50px; -} - -em { - font-style: normal; - color: red; -} \ No newline at end of file diff --git a/src/main/resources/static/css/letter.css b/src/main/resources/static/css/letter.css deleted file mode 100644 index 8556041..0000000 --- a/src/main/resources/static/css/letter.css +++ /dev/null @@ -1,17 +0,0 @@ -.main .nav .badge { - position: absolute; - top: -3px; - left: 90px; -} - -.main .media .badge { - position: absolute; - top: 12px; - left: 8px; -} - -.toast { - max-width: 100%; - width: 80%; -} - diff --git a/src/main/resources/static/css/login.css b/src/main/resources/static/css/login.css deleted file mode 100644 index 604e589..0000000 --- a/src/main/resources/static/css/login.css +++ /dev/null @@ -1,13 +0,0 @@ -.main .container { - width: 720px; -} - -.text-info { - color: #7754df!important; -} - -.btn-info { - color: #fff; - background-color: #9575f4 !important; - border-color: #9575f4 !important; -} diff --git a/src/main/resources/static/css/my-reply.css b/src/main/resources/static/css/my-reply.css deleted file mode 100644 index 9ad89a2..0000000 --- a/src/main/resources/static/css/my-reply.css +++ /dev/null @@ -1,5 +0,0 @@ -.mt-1, .my-1 { - margin-top: .25rem!important; - word-wrap: break-word; - word-break: normal; -} \ No newline at end of file diff --git a/src/main/resources/static/editor-md-upload/05ed9c9c900d475b86a66bee7c39642e.jpeg b/src/main/resources/static/editor-md-upload/05ed9c9c900d475b86a66bee7c39642e.jpeg deleted file mode 100644 index 580cd3023040a2c2f9fcc2bcd360d43052ba8014..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89202 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Μ*Gh?2<7>yUp`eB8YEVR1 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 fb*ZQM0r5BFz2J@cX8^~C=H^`kBU diff --git a/src/main/resources/static/editor-md-upload/323b95b3bc6e43f7a8824b43b1e8100c.jpg b/src/main/resources/static/editor-md-upload/323b95b3bc6e43f7a8824b43b1e8100c.jpg deleted file mode 100644 index 85e9127c975cc4ccb0138a839fcadbb7c7ad69f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14054 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 diff --git a/src/main/resources/static/editor-md-upload/ed84395548b045b386ec2f1ca6dde32d.jpeg b/src/main/resources/static/editor-md-upload/ed84395548b045b386ec2f1ca6dde32d.jpeg deleted file mode 100644 index 580cd3023040a2c2f9fcc2bcd360d43052ba8014..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89202 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Μ*Gh?2<7>yUp`eB8YEVR1 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 fb*ZQM0r5BFz2J@cX8^~C=H^`kBU diff --git a/src/main/resources/static/editor-md/.gitignore b/src/main/resources/static/editor-md/.gitignore deleted file mode 100644 index 9a85439..0000000 --- a/src/main/resources/static/editor-md/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -logs -*.log -*.pid -*.seed -node_modules/ -.sass-cache/ -research/ -test/ -backup/ -examples/uploads/**/* -*.bat -*.sh -.project -.url -css/*.map \ No newline at end of file diff --git a/src/main/resources/static/editor-md/.jshintrc b/src/main/resources/static/editor-md/.jshintrc deleted file mode 100644 index d689d8f..0000000 --- a/src/main/resources/static/editor-md/.jshintrc +++ /dev/null @@ -1,20 +0,0 @@ -{ - "esnext": true, - "bitwise": true, - "camelcase": true, - "curly": true, - "eqeqeq": true, - "immed": true, - "indent": 4, - "latedef": true, - "newcap": true, - "noarg": true, - "quotmark": "double", - "regexp": true, - "undef": true, - "unused": true, - "strict": true, - "trailing": true, - "smarttabs": true, - "white": true -} \ No newline at end of file diff --git a/src/main/resources/static/editor-md/BUGS.md b/src/main/resources/static/editor-md/BUGS.md deleted file mode 100644 index f16f9ad..0000000 --- a/src/main/resources/static/editor-md/BUGS.md +++ /dev/null @@ -1,22 +0,0 @@ -#Bugs - -> 说明:删除线表示已经解决。 - -####IE8 - -- ~~不能加载;~~ -- flowChart(流程图)、sequenceDiagram(序列图)不支持IE8; -- ~~不支持Markdown转HTML页面解析预览;~~ - -####IE8 & IE9 & IE10 - -- KaTeX会出现解析错误,但不影响程序运行; - -####Sea.js - -- ~~Raphael.js无法加载;~~ - -####Require.js - -- ~~CodeMirror编辑器的代码无法高亮;~~ -- ~~sequenceDiagram不支持: `Uncaught TypeError: Cannot call method 'isArray' of undefined.`~~ diff --git a/src/main/resources/static/editor-md/CHANGE.md b/src/main/resources/static/editor-md/CHANGE.md deleted file mode 100644 index 5198137..0000000 --- a/src/main/resources/static/editor-md/CHANGE.md +++ /dev/null @@ -1,534 +0,0 @@ -## 更新日志 - -### v1.0.x - -##### v1.0.0 beta - -预览版:基本功能完成; - -##### v1.0.0 releases - -发布 v1.0.0 正式版。 - -主要更新: - -- 新建分支 `mathjax-version`,但不打算继续对此分支进行开发; - -- 移除 MathJax,改用 KaTeX [#2](https://github.com/pandao/editor.md/issues/2),解析和预览响应速度大幅度提高 [#3](https://github.com/pandao/editor.md/issues/3); - - 移除 `mathjax` 配置项; - - 移除 `mathjaxURL` 属性; - - 移除 `setMathJaxConfig()` 方法; - - 移除 `loadMathJax()` 方法; - - 移除MathJax的所有示例; - - 新增 `tex` 配置项,表示是否开启支持科学公式 TeX ,基于 KaTeX; - - 新增 `katexURL` 属性; - - 新增 `loadKaTeX` 方法; - - 新增 KaTeX 的示例; - -- `setCodeEditor()` 方法更名为 `setCodeMirror()`; - -- 合并 CodeMirror 使用到的多个 JS 模块文件,大幅减少 HTTP 请求,加快下载速度; - - 新增合并后的两个模块文件:`./lib/codemirror/modes.min.js`、`./lib/codemirror/addons.min.js` ; - - `Gulpfile.js` 新增合并 CodeMirror 模块文件的任务方法 `codemirror-mode` 和 `codemirror-addon` ; - - 另外在使用 Require.js 时,因为 CodeMirror 的严格模块依赖的限制,不能使用上述合并的模块文件,仍然采用动态加载多个模块文件; - -- 更新 `README.md` 等相关文档和示例; - -- 解决 Sea.js 环境下 Raphael.js 无法运行导致不支持流程图和时序图的问题,即必须先加载 Raphael.js ,后加载 Sea.js ; - -### v1.1.x - -##### v1.1.0 - -主要更新: - -- 设计并更换了 Logo; -- 新增添加图片、链接、锚点链接、代码块、预格式文本等操作弹出对话框层及示例; -- 新增支持图片(跨域)上传; -- 改用 ` - - - - -``` - -If you using modular script loader: - -- [Using Require.js](https://github.com/pandao/editor.md/tree/master/examples/use-requirejs.html) -- [Using Sea.js](https://github.com/pandao/editor.md/tree/master/examples/use-seajs.html) - -##### Markdown to HTML - -```html - -
- - -
- - - - - -``` - -> See the full example: [http://editor.md.ipandao.com/examples/html-preview-markdown-to-html.html](http://editor.md.ipandao.com/examples/html-preview-markdown-to-html.html) - -##### HTML to Markdown? - -Sorry, Editor.md not support HTML to Markdown parsing, Maybe In the future. - -#### Examples - -[https://pandao.github.io/editor.md/examples/index.html](https://pandao.github.io/editor.md/examples/index.html) - -#### Options - -Editor.md options and default values: - -```javascript -{ - mode : "gfm", // gfm or markdown - name : "", // Form element name for post - value : "", // value for CodeMirror, if mode not gfm/markdown - theme : "", // Editor.md self themes, before v1.5.0 is CodeMirror theme, default empty - editorTheme : "default", // Editor area, this is CodeMirror theme at v1.5.0 - previewTheme : "", // Preview area theme, default empty - markdown : "", // Markdown source code - appendMarkdown : "", // if in init textarea value not empty, append markdown to textarea - width : "100%", - height : "100%", - path : "./lib/", // Dependents module file directory - pluginPath : "", // If this empty, default use settings.path + "../plugins/" - delay : 300, // Delay parse markdown to html, Uint : ms - autoLoadModules : true, // Automatic load dependent module files - watch : true, - placeholder : "Enjoy Markdown! coding now...", - gotoLine : true, // Enable / disable goto a line - codeFold : false, - autoHeight : false, - autoFocus : true, // Enable / disable auto focus editor left input area - autoCloseTags : true, - searchReplace : true, // Enable / disable (CodeMirror) search and replace function - syncScrolling : true, // options: true | false | "single", default true - readOnly : false, // Enable / disable readonly mode - tabSize : 4, - indentUnit : 4, - lineNumbers : true, // Display editor line numbers - lineWrapping : true, - autoCloseBrackets : true, - showTrailingSpace : true, - matchBrackets : true, - indentWithTabs : true, - styleSelectedText : true, - matchWordHighlight : true, // options: true, false, "onselected" - styleActiveLine : true, // Highlight the current line - dialogLockScreen : true, - dialogShowMask : true, - dialogDraggable : true, - dialogMaskBgColor : "#fff", - dialogMaskOpacity : 0.1, - fontSize : "13px", - saveHTMLToTextarea : false, // If enable, Editor will create a "); - markdownTextarea = this.markdownTextarea = editor.children("textarea"); - } - - markdownTextarea.addClass(classNames.textarea.markdown).attr("placeholder", settings.placeholder); - - if (typeof markdownTextarea.attr("name") === "undefined" || markdownTextarea.attr("name") === "") - { - markdownTextarea.attr("name", (settings.name !== "") ? settings.name : id + "-markdown-doc"); - } - - var appendElements = [ - (!settings.readOnly) ? "" : "", - ( (settings.saveHTMLToTextarea) ? "" : "" ), - "
", - "
", - "
" - ].join("\n"); - - editor.append(appendElements).addClass(classPrefix + "vertical"); - - if (settings.theme !== "") - { - editor.addClass(classPrefix + "theme-" + settings.theme); - } - - this.mask = editor.children("." + classPrefix + "mask"); - this.containerMask = editor.children("." + classPrefix + "container-mask"); - - if (settings.markdown !== "") - { - markdownTextarea.val(settings.markdown); - } - - if (settings.appendMarkdown !== "") - { - markdownTextarea.val(markdownTextarea.val() + settings.appendMarkdown); - } - - this.htmlTextarea = editor.children("." + classNames.textarea.html); - this.preview = editor.children("." + classPrefix + "preview"); - this.previewContainer = this.preview.children("." + classPrefix + "preview-container"); - - if (settings.previewTheme !== "") - { - this.preview.addClass(classPrefix + "preview-theme-" + settings.previewTheme); - } - - if (typeof define === "function" && define.amd) - { - if (typeof katex !== "undefined") - { - editormd.$katex = katex; - } - - if (settings.searchReplace && !settings.readOnly) - { - editormd.loadCSS(settings.path + "codemirror/addon/dialog/dialog"); - editormd.loadCSS(settings.path + "codemirror/addon/search/matchesonscrollbar"); - } - } - - if ((typeof define === "function" && define.amd) || !settings.autoLoadModules) - { - if (typeof CodeMirror !== "undefined") { - editormd.$CodeMirror = CodeMirror; - } - - if (typeof marked !== "undefined") { - editormd.$marked = marked; - } - - this.setCodeMirror().setToolbar().loadedDisplay(); - } - else - { - this.loadQueues(); - } - - return this; - }, - - /** - * 所需组件加载队列 - * Required components loading queue - * - * @returns {editormd} 返回editormd的实例对象 - */ - - loadQueues : function() { - var _this = this; - var settings = this.settings; - var loadPath = settings.path; - - var loadFlowChartOrSequenceDiagram = function() { - - if (editormd.isIE8) - { - _this.loadedDisplay(); - - return ; - } - - if (settings.flowChart || settings.sequenceDiagram) - { - editormd.loadScript(loadPath + "raphael.min", function() { - - editormd.loadScript(loadPath + "underscore.min", function() { - - if (!settings.flowChart && settings.sequenceDiagram) - { - editormd.loadScript(loadPath + "sequence-diagram.min", function() { - _this.loadedDisplay(); - }); - } - else if (settings.flowChart && !settings.sequenceDiagram) - { - editormd.loadScript(loadPath + "flowchart.min", function() { - editormd.loadScript(loadPath + "jquery.flowchart.min", function() { - _this.loadedDisplay(); - }); - }); - } - else if (settings.flowChart && settings.sequenceDiagram) - { - editormd.loadScript(loadPath + "flowchart.min", function() { - editormd.loadScript(loadPath + "jquery.flowchart.min", function() { - editormd.loadScript(loadPath + "sequence-diagram.min", function() { - _this.loadedDisplay(); - }); - }); - }); - } - }); - - }); - } - else - { - _this.loadedDisplay(); - } - }; - - editormd.loadCSS(loadPath + "codemirror/codemirror.min"); - - if (settings.searchReplace && !settings.readOnly) - { - editormd.loadCSS(loadPath + "codemirror/addon/dialog/dialog"); - editormd.loadCSS(loadPath + "codemirror/addon/search/matchesonscrollbar"); - } - - if (settings.codeFold) - { - editormd.loadCSS(loadPath + "codemirror/addon/fold/foldgutter"); - } - - editormd.loadScript(loadPath + "codemirror/codemirror.min", function() { - editormd.$CodeMirror = CodeMirror; - - editormd.loadScript(loadPath + "codemirror/modes.min", function() { - - editormd.loadScript(loadPath + "codemirror/addons.min", function() { - - _this.setCodeMirror(); - - if (settings.mode !== "gfm" && settings.mode !== "markdown") - { - _this.loadedDisplay(); - - return false; - } - - _this.setToolbar(); - - editormd.loadScript(loadPath + "marked.min", function() { - - editormd.$marked = marked; - - if (settings.previewCodeHighlight) - { - editormd.loadScript(loadPath + "prettify.min", function() { - loadFlowChartOrSequenceDiagram(); - }); - } - else - { - loadFlowChartOrSequenceDiagram(); - } - }); - - }); - - }); - - }); - - return this; - }, - - /** - * 设置 Editor.md 的整体主题,主要是工具栏 - * Setting Editor.md theme - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setTheme : function(theme) { - var editor = this.editor; - var oldTheme = this.settings.theme; - var themePrefix = this.classPrefix + "theme-"; - - editor.removeClass(themePrefix + oldTheme).addClass(themePrefix + theme); - - this.settings.theme = theme; - - return this; - }, - - /** - * 设置 CodeMirror(编辑区)的主题 - * Setting CodeMirror (Editor area) theme - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setEditorTheme : function(theme) { - var settings = this.settings; - settings.editorTheme = theme; - - if (theme !== "default") - { - editormd.loadCSS(settings.path + "codemirror/theme/" + settings.editorTheme); - } - - this.cm.setOption("theme", theme); - - return this; - }, - - /** - * setEditorTheme() 的别名 - * setEditorTheme() alias - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setCodeMirrorTheme : function (theme) { - this.setEditorTheme(theme); - - return this; - }, - - /** - * 设置 Editor.md 的主题 - * Setting Editor.md theme - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setPreviewTheme : function(theme) { - var preview = this.preview; - var oldTheme = this.settings.previewTheme; - var themePrefix = this.classPrefix + "preview-theme-"; - - preview.removeClass(themePrefix + oldTheme).addClass(themePrefix + theme); - - this.settings.previewTheme = theme; - - return this; - }, - - /** - * 配置和初始化CodeMirror组件 - * CodeMirror initialization - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setCodeMirror : function() { - var settings = this.settings; - var editor = this.editor; - - if (settings.editorTheme !== "default") - { - editormd.loadCSS(settings.path + "codemirror/theme/" + settings.editorTheme); - } - - var codeMirrorConfig = { - mode : settings.mode, - theme : settings.editorTheme, - tabSize : settings.tabSize, - dragDrop : false, - autofocus : settings.autoFocus, - autoCloseTags : settings.autoCloseTags, - readOnly : (settings.readOnly) ? "nocursor" : false, - indentUnit : settings.indentUnit, - lineNumbers : settings.lineNumbers, - lineWrapping : settings.lineWrapping, - extraKeys : { - "Ctrl-Q": function(cm) { - cm.foldCode(cm.getCursor()); - } - }, - foldGutter : settings.codeFold, - gutters : ["CodeMirror-linenumbers", "CodeMirror-foldgutter"], - matchBrackets : settings.matchBrackets, - indentWithTabs : settings.indentWithTabs, - styleActiveLine : settings.styleActiveLine, - styleSelectedText : settings.styleSelectedText, - autoCloseBrackets : settings.autoCloseBrackets, - showTrailingSpace : settings.showTrailingSpace, - highlightSelectionMatches : ( (!settings.matchWordHighlight) ? false : { showToken: (settings.matchWordHighlight === "onselected") ? false : /\w/ } ) - }; - - this.codeEditor = this.cm = editormd.$CodeMirror.fromTextArea(this.markdownTextarea[0], codeMirrorConfig); - this.codeMirror = this.cmElement = editor.children(".CodeMirror"); - - if (settings.value !== "") - { - this.cm.setValue(settings.value); - } - - this.codeMirror.css({ - fontSize : settings.fontSize, - width : (!settings.watch) ? "100%" : "50%" - }); - - if (settings.autoHeight) - { - this.codeMirror.css("height", "auto"); - this.cm.setOption("viewportMargin", Infinity); - } - - if (!settings.lineNumbers) - { - this.codeMirror.find(".CodeMirror-gutters").css("border-right", "none"); - } - - return this; - }, - - /** - * 获取CodeMirror的配置选项 - * Get CodeMirror setting options - * - * @returns {Mixed} return CodeMirror setting option value - */ - - getCodeMirrorOption : function(key) { - return this.cm.getOption(key); - }, - - /** - * 配置和重配置CodeMirror的选项 - * CodeMirror setting options / resettings - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setCodeMirrorOption : function(key, value) { - - this.cm.setOption(key, value); - - return this; - }, - - /** - * 添加 CodeMirror 键盘快捷键 - * Add CodeMirror keyboard shortcuts key map - * - * @returns {editormd} 返回editormd的实例对象 - */ - - addKeyMap : function(map, bottom) { - this.cm.addKeyMap(map, bottom); - - return this; - }, - - /** - * 移除 CodeMirror 键盘快捷键 - * Remove CodeMirror keyboard shortcuts key map - * - * @returns {editormd} 返回editormd的实例对象 - */ - - removeKeyMap : function(map) { - this.cm.removeKeyMap(map); - - return this; - }, - - /** - * 跳转到指定的行 - * Goto CodeMirror line - * - * @param {String|Intiger} line line number or "first"|"last" - * @returns {editormd} 返回editormd的实例对象 - */ - - gotoLine : function (line) { - - var settings = this.settings; - - if (!settings.gotoLine) - { - return this; - } - - var cm = this.cm; - var editor = this.editor; - var count = cm.lineCount(); - var preview = this.preview; - - if (typeof line === "string") - { - if(line === "last") - { - line = count; - } - - if (line === "first") - { - line = 1; - } - } - - if (typeof line !== "number") - { - alert("Error: The line number must be an integer."); - return this; - } - - line = parseInt(line) - 1; - - if (line > count) - { - alert("Error: The line number range 1-" + count); - - return this; - } - - cm.setCursor( {line : line, ch : 0} ); - - var scrollInfo = cm.getScrollInfo(); - var clientHeight = scrollInfo.clientHeight; - var coords = cm.charCoords({line : line, ch : 0}, "local"); - - cm.scrollTo(null, (coords.top + coords.bottom - clientHeight) / 2); - - if (settings.watch) - { - var cmScroll = this.codeMirror.find(".CodeMirror-scroll")[0]; - var height = $(cmScroll).height(); - var scrollTop = cmScroll.scrollTop; - var percent = (scrollTop / cmScroll.scrollHeight); - - if (scrollTop === 0) - { - preview.scrollTop(0); - } - else if (scrollTop + height >= cmScroll.scrollHeight - 16) - { - preview.scrollTop(preview[0].scrollHeight); - } - else - { - preview.scrollTop(preview[0].scrollHeight * percent); - } - } - - cm.focus(); - - return this; - }, - - /** - * 扩展当前实例对象,可同时设置多个或者只设置一个 - * Extend editormd instance object, can mutil setting. - * - * @returns {editormd} this(editormd instance object.) - */ - - extend : function() { - if (typeof arguments[1] !== "undefined") - { - if (typeof arguments[1] === "function") - { - arguments[1] = $.proxy(arguments[1], this); - } - - this[arguments[0]] = arguments[1]; - } - - if (typeof arguments[0] === "object" && typeof arguments[0].length === "undefined") - { - $.extend(true, this, arguments[0]); - } - - return this; - }, - - /** - * 设置或扩展当前实例对象,单个设置 - * Extend editormd instance object, one by one - * - * @param {String|Object} key option key - * @param {String|Object} value option value - * @returns {editormd} this(editormd instance object.) - */ - - set : function (key, value) { - - if (typeof value !== "undefined" && typeof value === "function") - { - value = $.proxy(value, this); - } - - this[key] = value; - - return this; - }, - - /** - * 重新配置 - * Resetting editor options - * - * @param {String|Object} key option key - * @param {String|Object} value option value - * @returns {editormd} this(editormd instance object.) - */ - - config : function(key, value) { - var settings = this.settings; - - if (typeof key === "object") - { - settings = $.extend(true, settings, key); - } - - if (typeof key === "string") - { - settings[key] = value; - } - - this.settings = settings; - this.recreate(); - - return this; - }, - - /** - * 注册事件处理方法 - * Bind editor event handle - * - * @param {String} eventType event type - * @param {Function} callback 回调函数 - * @returns {editormd} this(editormd instance object.) - */ - - on : function(eventType, callback) { - var settings = this.settings; - - if (typeof settings["on" + eventType] !== "undefined") - { - settings["on" + eventType] = $.proxy(callback, this); - } - - return this; - }, - - /** - * 解除事件处理方法 - * Unbind editor event handle - * - * @param {String} eventType event type - * @returns {editormd} this(editormd instance object.) - */ - - off : function(eventType) { - var settings = this.settings; - - if (typeof settings["on" + eventType] !== "undefined") - { - settings["on" + eventType] = function(){}; - } - - return this; - }, - - /** - * 显示工具栏 - * Display toolbar - * - * @param {Function} [callback=function(){}] 回调函数 - * @returns {editormd} 返回editormd的实例对象 - */ - - showToolbar : function(callback) { - var settings = this.settings; - - if(settings.readOnly) { - return this; - } - - if (settings.toolbar && (this.toolbar.length < 1 || this.toolbar.find("." + this.classPrefix + "menu").html() === "") ) - { - this.setToolbar(); - } - - settings.toolbar = true; - - this.toolbar.show(); - this.resize(); - - $.proxy(callback || function(){}, this)(); - - return this; - }, - - /** - * 隐藏工具栏 - * Hide toolbar - * - * @param {Function} [callback=function(){}] 回调函数 - * @returns {editormd} this(editormd instance object.) - */ - - hideToolbar : function(callback) { - var settings = this.settings; - - settings.toolbar = false; - this.toolbar.hide(); - this.resize(); - - $.proxy(callback || function(){}, this)(); - - return this; - }, - - /** - * 页面滚动时工具栏的固定定位 - * Set toolbar in window scroll auto fixed position - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setToolbarAutoFixed : function(fixed) { - - var state = this.state; - var editor = this.editor; - var toolbar = this.toolbar; - var settings = this.settings; - - if (typeof fixed !== "undefined") - { - settings.toolbarAutoFixed = fixed; - } - - var autoFixedHandle = function(){ - var $window = $(window); - var top = $window.scrollTop(); - - if (!settings.toolbarAutoFixed) - { - return false; - } - - if (top - editor.offset().top > 10 && top < editor.height()) - { - toolbar.css({ - position : "fixed", - width : editor.width() + "px", - left : ($window.width() - editor.width()) / 2 + "px" - }); - } - else - { - toolbar.css({ - position : "absolute", - width : "100%", - left : 0 - }); - } - }; - - if (!state.fullscreen && !state.preview && settings.toolbar && settings.toolbarAutoFixed) - { - $(window).bind("scroll", autoFixedHandle); - } - - return this; - }, - - /** - * 配置和初始化工具栏 - * Set toolbar and Initialization - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setToolbar : function() { - var settings = this.settings; - - if(settings.readOnly) { - return this; - } - - var editor = this.editor; - var preview = this.preview; - var classPrefix = this.classPrefix; - - var toolbar = this.toolbar = editor.children("." + classPrefix + "toolbar"); - - if (settings.toolbar && toolbar.length < 1) - { - var toolbarHTML = "
    "; - - editor.append(toolbarHTML); - toolbar = this.toolbar = editor.children("." + classPrefix + "toolbar"); - } - - if (!settings.toolbar) - { - toolbar.hide(); - - return this; - } - - toolbar.show(); - - var icons = (typeof settings.toolbarIcons === "function") ? settings.toolbarIcons() - : ((typeof settings.toolbarIcons === "string") ? editormd.toolbarModes[settings.toolbarIcons] : settings.toolbarIcons); - - var toolbarMenu = toolbar.find("." + this.classPrefix + "menu"), menu = ""; - var pullRight = false; - - for (var i = 0, len = icons.length; i < len; i++) - { - var name = icons[i]; - - if (name === "||") - { - pullRight = true; - } - else if (name === "|") - { - menu += "
  • |
  • "; - } - else - { - var isHeader = (/h(\d)/.test(name)); - var index = name; - - if (name === "watch" && !settings.watch) { - index = "unwatch"; - } - - var title = settings.lang.toolbar[index]; - var iconTexts = settings.toolbarIconTexts[index]; - var iconClass = settings.toolbarIconsClass[index]; - - title = (typeof title === "undefined") ? "" : title; - iconTexts = (typeof iconTexts === "undefined") ? "" : iconTexts; - iconClass = (typeof iconClass === "undefined") ? "" : iconClass; - - var menuItem = pullRight ? "
  • " : "
  • "; - - if (typeof settings.toolbarCustomIcons[name] !== "undefined" && typeof settings.toolbarCustomIcons[name] !== "function") - { - menuItem += settings.toolbarCustomIcons[name]; - } - else - { - menuItem += ""; - menuItem += ""+((isHeader) ? name.toUpperCase() : ( (iconClass === "") ? iconTexts : "") ) + ""; - menuItem += ""; - } - - menuItem += "
  • "; - - menu = pullRight ? menuItem + menu : menu + menuItem; - } - } - - toolbarMenu.html(menu); - - toolbarMenu.find("[title=\"Lowercase\"]").attr("title", settings.lang.toolbar.lowercase); - toolbarMenu.find("[title=\"ucwords\"]").attr("title", settings.lang.toolbar.ucwords); - - this.setToolbarHandler(); - this.setToolbarAutoFixed(); - - return this; - }, - - /** - * 工具栏图标事件处理对象序列 - * Get toolbar icons event handlers - * - * @param {Object} cm CodeMirror的实例对象 - * @param {String} name 要获取的事件处理器名称 - * @returns {Object} 返回处理对象序列 - */ - - dialogLockScreen : function() { - $.proxy(editormd.dialogLockScreen, this)(); - - return this; - }, - - dialogShowMask : function(dialog) { - $.proxy(editormd.dialogShowMask, this)(dialog); - - return this; - }, - - getToolbarHandles : function(name) { - var toolbarHandlers = this.toolbarHandlers = editormd.toolbarHandlers; - - return (name && typeof toolbarIconHandlers[name] !== "undefined") ? toolbarHandlers[name] : toolbarHandlers; - }, - - /** - * 工具栏图标事件处理器 - * Bind toolbar icons event handle - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setToolbarHandler : function() { - var _this = this; - var settings = this.settings; - - if (!settings.toolbar || settings.readOnly) { - return this; - } - - var toolbar = this.toolbar; - var cm = this.cm; - var classPrefix = this.classPrefix; - var toolbarIcons = this.toolbarIcons = toolbar.find("." + classPrefix + "menu > li > a"); - var toolbarIconHandlers = this.getToolbarHandles(); - - toolbarIcons.bind(editormd.mouseOrTouch("click", "touchend"), function(event) { - - var icon = $(this).children(".fa"); - var name = icon.attr("name"); - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (name === "") { - return ; - } - - _this.activeIcon = icon; - - if (typeof toolbarIconHandlers[name] !== "undefined") - { - $.proxy(toolbarIconHandlers[name], _this)(cm); - } - else - { - if (typeof settings.toolbarHandlers[name] !== "undefined") - { - $.proxy(settings.toolbarHandlers[name], _this)(cm, icon, cursor, selection); - } - } - - if (name !== "link" && name !== "reference-link" && name !== "image" && name !== "code-block" && - name !== "preformatted-text" && name !== "watch" && name !== "preview" && name !== "search" && name !== "fullscreen" && name !== "info") - { - cm.focus(); - } - - return false; - - }); - - return this; - }, - - /** - * 动态创建对话框 - * Creating custom dialogs - * - * @param {Object} options 配置项键值对 Key/Value - * @returns {dialog} 返回创建的dialog的jQuery实例对象 - */ - - createDialog : function(options) { - return $.proxy(editormd.createDialog, this)(options); - }, - - /** - * 创建关于Editor.md的对话框 - * Create about Editor.md dialog - * - * @returns {editormd} 返回editormd的实例对象 - */ - - createInfoDialog : function() { - var _this = this; - var editor = this.editor; - var classPrefix = this.classPrefix; - - var infoDialogHTML = [ - "
    ", - "
    ", - "

    " + editormd.title + "v" + editormd.version + "

    ", - "

    " + this.lang.description + "

    ", - "

    " + editormd.homePage + "

    ", - "

    Copyright © 2015 Pandao, The MIT License.

    ", - "
    ", - "", - "
    " - ].join("\n"); - - editor.append(infoDialogHTML); - - var infoDialog = this.infoDialog = editor.children("." + classPrefix + "dialog-info"); - - infoDialog.find("." + classPrefix + "dialog-close").bind(editormd.mouseOrTouch("click", "touchend"), function() { - _this.hideInfoDialog(); - }); - - infoDialog.css("border", (editormd.isIE8) ? "1px solid #ddd" : "").css("z-index", editormd.dialogZindex).show(); - - this.infoDialogPosition(); - - return this; - }, - - /** - * 关于Editor.md对话居中定位 - * Editor.md dialog position handle - * - * @returns {editormd} 返回editormd的实例对象 - */ - - infoDialogPosition : function() { - var infoDialog = this.infoDialog; - - var _infoDialogPosition = function() { - infoDialog.css({ - top : ($(window).height() - infoDialog.height()) / 2 + "px", - left : ($(window).width() - infoDialog.width()) / 2 + "px" - }); - }; - - _infoDialogPosition(); - - $(window).resize(_infoDialogPosition); - - return this; - }, - - /** - * 显示关于Editor.md - * Display about Editor.md dialog - * - * @returns {editormd} 返回editormd的实例对象 - */ - - showInfoDialog : function() { - - $("html,body").css("overflow-x", "hidden"); - - var _this = this; - var editor = this.editor; - var settings = this.settings; - var infoDialog = this.infoDialog = editor.children("." + this.classPrefix + "dialog-info"); - - if (infoDialog.length < 1) - { - this.createInfoDialog(); - } - - this.lockScreen(true); - - this.mask.css({ - opacity : settings.dialogMaskOpacity, - backgroundColor : settings.dialogMaskBgColor - }).show(); - - infoDialog.css("z-index", editormd.dialogZindex).show(); - - this.infoDialogPosition(); - - return this; - }, - - /** - * 隐藏关于Editor.md - * Hide about Editor.md dialog - * - * @returns {editormd} 返回editormd的实例对象 - */ - - hideInfoDialog : function() { - $("html,body").css("overflow-x", ""); - this.infoDialog.hide(); - this.mask.hide(); - this.lockScreen(false); - - return this; - }, - - /** - * 锁屏 - * lock screen - * - * @param {Boolean} lock Boolean 布尔值,是否锁屏 - * @returns {editormd} 返回editormd的实例对象 - */ - - lockScreen : function(lock) { - editormd.lockScreen(lock); - this.resize(); - - return this; - }, - - /** - * 编辑器界面重建,用于动态语言包或模块加载等 - * Recreate editor - * - * @returns {editormd} 返回editormd的实例对象 - */ - - recreate : function() { - var _this = this; - var editor = this.editor; - var settings = this.settings; - - this.codeMirror.remove(); - - this.setCodeMirror(); - - if (!settings.readOnly) - { - if (editor.find(".editormd-dialog").length > 0) { - editor.find(".editormd-dialog").remove(); - } - - if (settings.toolbar) - { - this.getToolbarHandles(); - this.setToolbar(); - } - } - - this.loadedDisplay(true); - - return this; - }, - - /** - * 高亮预览HTML的pre代码部分 - * highlight of preview codes - * - * @returns {editormd} 返回editormd的实例对象 - */ - - previewCodeHighlight : function() { - var settings = this.settings; - var previewContainer = this.previewContainer; - - if (settings.previewCodeHighlight) - { - previewContainer.find("pre").addClass("prettyprint linenums"); - - if (typeof prettyPrint !== "undefined") - { - prettyPrint(); - } - } - - return this; - }, - - /** - * 解析TeX(KaTeX)科学公式 - * TeX(KaTeX) Renderer - * - * @returns {editormd} 返回editormd的实例对象 - */ - - katexRender : function() { - - if (timer === null) - { - return this; - } - - this.previewContainer.find("." + editormd.classNames.tex).each(function(){ - var tex = $(this); - editormd.$katex.render(tex.text(), tex[0]); - - tex.find(".katex").css("font-size", "1.6em"); - }); - - return this; - }, - - /** - * 解析和渲染流程图及时序图 - * FlowChart and SequenceDiagram Renderer - * - * @returns {editormd} 返回editormd的实例对象 - */ - - flowChartAndSequenceDiagramRender : function() { - var $this = this; - var settings = this.settings; - var previewContainer = this.previewContainer; - - if (editormd.isIE8) { - return this; - } - - if (settings.flowChart) { - if (flowchartTimer === null) { - return this; - } - - previewContainer.find(".flowchart").flowChart(); - } - - if (settings.sequenceDiagram) { - previewContainer.find(".sequence-diagram").sequenceDiagram({theme: "simple"}); - } - - var preview = $this.preview; - var codeMirror = $this.codeMirror; - var codeView = codeMirror.find(".CodeMirror-scroll"); - - var height = codeView.height(); - var scrollTop = codeView.scrollTop(); - var percent = (scrollTop / codeView[0].scrollHeight); - var tocHeight = 0; - - preview.find(".markdown-toc-list").each(function(){ - tocHeight += $(this).height(); - }); - - var tocMenuHeight = preview.find(".editormd-toc-menu").height(); - tocMenuHeight = (!tocMenuHeight) ? 0 : tocMenuHeight; - - if (scrollTop === 0) - { - preview.scrollTop(0); - } - else if (scrollTop + height >= codeView[0].scrollHeight - 16) - { - preview.scrollTop(preview[0].scrollHeight); - } - else - { - preview.scrollTop((preview[0].scrollHeight + tocHeight + tocMenuHeight) * percent); - } - - return this; - }, - - /** - * 注册键盘快捷键处理 - * Register CodeMirror keyMaps (keyboard shortcuts). - * - * @param {Object} keyMap KeyMap key/value {"(Ctrl/Shift/Alt)-Key" : function(){}} - * @returns {editormd} return this - */ - - registerKeyMaps : function(keyMap) { - - var _this = this; - var cm = this.cm; - var settings = this.settings; - var toolbarHandlers = editormd.toolbarHandlers; - var disabledKeyMaps = settings.disabledKeyMaps; - - keyMap = keyMap || null; - - if (keyMap) - { - for (var i in keyMap) - { - if ($.inArray(i, disabledKeyMaps) < 0) - { - var map = {}; - map[i] = keyMap[i]; - - cm.addKeyMap(keyMap); - } - } - } - else - { - for (var k in editormd.keyMaps) - { - var _keyMap = editormd.keyMaps[k]; - var handle = (typeof _keyMap === "string") ? $.proxy(toolbarHandlers[_keyMap], _this) : $.proxy(_keyMap, _this); - - if ($.inArray(k, ["F9", "F10", "F11"]) < 0 && $.inArray(k, disabledKeyMaps) < 0) - { - var _map = {}; - _map[k] = handle; - - cm.addKeyMap(_map); - } - } - - $(window).keydown(function(event) { - - var keymaps = { - "120" : "F9", - "121" : "F10", - "122" : "F11" - }; - - if ( $.inArray(keymaps[event.keyCode], disabledKeyMaps) < 0 ) - { - switch (event.keyCode) - { - case 120: - $.proxy(toolbarHandlers["watch"], _this)(); - return false; - break; - - case 121: - $.proxy(toolbarHandlers["preview"], _this)(); - return false; - break; - - case 122: - $.proxy(toolbarHandlers["fullscreen"], _this)(); - return false; - break; - - default: - break; - } - } - }); - } - - return this; - }, - - /** - * 绑定同步滚动 - * - * @returns {editormd} return this - */ - - bindScrollEvent : function() { - - var _this = this; - var preview = this.preview; - var settings = this.settings; - var codeMirror = this.codeMirror; - var mouseOrTouch = editormd.mouseOrTouch; - - if (!settings.syncScrolling) { - return this; - } - - var cmBindScroll = function() { - codeMirror.find(".CodeMirror-scroll").bind(mouseOrTouch("scroll", "touchmove"), function(event) { - var height = $(this).height(); - var scrollTop = $(this).scrollTop(); - var percent = (scrollTop / $(this)[0].scrollHeight); - - var tocHeight = 0; - - preview.find(".markdown-toc-list").each(function(){ - tocHeight += $(this).height(); - }); - - var tocMenuHeight = preview.find(".editormd-toc-menu").height(); - tocMenuHeight = (!tocMenuHeight) ? 0 : tocMenuHeight; - - if (scrollTop === 0) - { - preview.scrollTop(0); - } - else if (scrollTop + height >= $(this)[0].scrollHeight - 16) - { - preview.scrollTop(preview[0].scrollHeight); - } - else - { - preview.scrollTop((preview[0].scrollHeight + tocHeight + tocMenuHeight) * percent); - } - - $.proxy(settings.onscroll, _this)(event); - }); - }; - - var cmUnbindScroll = function() { - codeMirror.find(".CodeMirror-scroll").unbind(mouseOrTouch("scroll", "touchmove")); - }; - - var previewBindScroll = function() { - - preview.bind(mouseOrTouch("scroll", "touchmove"), function(event) { - var height = $(this).height(); - var scrollTop = $(this).scrollTop(); - var percent = (scrollTop / $(this)[0].scrollHeight); - var codeView = codeMirror.find(".CodeMirror-scroll"); - - if(scrollTop === 0) - { - codeView.scrollTop(0); - } - else if (scrollTop + height >= $(this)[0].scrollHeight) - { - codeView.scrollTop(codeView[0].scrollHeight); - } - else - { - codeView.scrollTop(codeView[0].scrollHeight * percent); - } - - $.proxy(settings.onpreviewscroll, _this)(event); - }); - - }; - - var previewUnbindScroll = function() { - preview.unbind(mouseOrTouch("scroll", "touchmove")); - }; - - codeMirror.bind({ - mouseover : cmBindScroll, - mouseout : cmUnbindScroll, - touchstart : cmBindScroll, - touchend : cmUnbindScroll - }); - - if (settings.syncScrolling === "single") { - return this; - } - - preview.bind({ - mouseover : previewBindScroll, - mouseout : previewUnbindScroll, - touchstart : previewBindScroll, - touchend : previewUnbindScroll - }); - - return this; - }, - - bindChangeEvent : function() { - - var _this = this; - var cm = this.cm; - var settings = this.settings; - - if (!settings.syncScrolling) { - return this; - } - - cm.on("change", function(_cm, changeObj) { - - if (settings.watch) - { - _this.previewContainer.css("padding", settings.autoHeight ? "20px 20px 50px 40px" : "20px"); - } - - timer = setTimeout(function() { - clearTimeout(timer); - _this.save(); - timer = null; - }, settings.delay); - }); - - return this; - }, - - /** - * 加载队列完成之后的显示处理 - * Display handle of the module queues loaded after. - * - * @param {Boolean} recreate 是否为重建编辑器 - * @returns {editormd} 返回editormd的实例对象 - */ - - loadedDisplay : function(recreate) { - - recreate = recreate || false; - - var _this = this; - var editor = this.editor; - var preview = this.preview; - var settings = this.settings; - - this.containerMask.hide(); - - this.save(); - - if (settings.watch) { - preview.show(); - } - - editor.data("oldWidth", editor.width()).data("oldHeight", editor.height()); // 为了兼容Zepto - - this.resize(); - this.registerKeyMaps(); - - $(window).resize(function(){ - _this.resize(); - }); - - this.bindScrollEvent().bindChangeEvent(); - - if (!recreate) - { - $.proxy(settings.onload, this)(); - } - - this.state.loaded = true; - - return this; - }, - - /** - * 设置编辑器的宽度 - * Set editor width - * - * @param {Number|String} width 编辑器宽度值 - * @returns {editormd} 返回editormd的实例对象 - */ - - width : function(width) { - - this.editor.css("width", (typeof width === "number") ? width + "px" : width); - this.resize(); - - return this; - }, - - /** - * 设置编辑器的高度 - * Set editor height - * - * @param {Number|String} height 编辑器高度值 - * @returns {editormd} 返回editormd的实例对象 - */ - - height : function(height) { - - this.editor.css("height", (typeof height === "number") ? height + "px" : height); - this.resize(); - - return this; - }, - - /** - * 调整编辑器的尺寸和布局 - * Resize editor layout - * - * @param {Number|String} [width=null] 编辑器宽度值 - * @param {Number|String} [height=null] 编辑器高度值 - * @returns {editormd} 返回editormd的实例对象 - */ - - resize : function(width, height) { - - width = width || null; - height = height || null; - - var state = this.state; - var editor = this.editor; - var preview = this.preview; - var toolbar = this.toolbar; - var settings = this.settings; - var codeMirror = this.codeMirror; - - if (width) - { - editor.css("width", (typeof width === "number") ? width + "px" : width); - } - - if (settings.autoHeight && !state.fullscreen && !state.preview) - { - editor.css("height", "auto"); - codeMirror.css("height", "auto"); - } - else - { - if (height) - { - editor.css("height", (typeof height === "number") ? height + "px" : height); - } - - if (state.fullscreen) - { - editor.height($(window).height()); - } - - if (settings.toolbar && !settings.readOnly) - { - codeMirror.css("margin-top", toolbar.height() + 1).height(editor.height() - toolbar.height()); - } - else - { - codeMirror.css("margin-top", 0).height(editor.height()); - } - } - - if(settings.watch) - { - codeMirror.width(editor.width() / 2); - preview.width((!state.preview) ? editor.width() / 2 : editor.width()); - - this.previewContainer.css("padding", settings.autoHeight ? "20px 20px 50px 40px" : "20px"); - - if (settings.toolbar && !settings.readOnly) - { - preview.css("top", toolbar.height() + 1); - } - else - { - preview.css("top", 0); - } - - if (settings.autoHeight && !state.fullscreen && !state.preview) - { - preview.height(""); - } - else - { - var previewHeight = (settings.toolbar && !settings.readOnly) ? editor.height() - toolbar.height() : editor.height(); - - preview.height(previewHeight); - } - } - else - { - codeMirror.width(editor.width()); - preview.hide(); - } - - if (state.loaded) - { - $.proxy(settings.onresize, this)(); - } - - return this; - }, - - /** - * 解析和保存Markdown代码 - * Parse & Saving Markdown source code - * - * @returns {editormd} 返回editormd的实例对象 - */ - - save : function() { - - if (timer === null) - { - return this; - } - - var _this = this; - var state = this.state; - var settings = this.settings; - var cm = this.cm; - var cmValue = cm.getValue(); - var previewContainer = this.previewContainer; - - if (settings.mode !== "gfm" && settings.mode !== "markdown") - { - this.markdownTextarea.val(cmValue); - - return this; - } - - var marked = editormd.$marked; - var markdownToC = this.markdownToC = []; - var rendererOptions = this.markedRendererOptions = { - toc : settings.toc, - tocm : settings.tocm, - tocStartLevel : settings.tocStartLevel, - pageBreak : settings.pageBreak, - taskList : settings.taskList, - emoji : settings.emoji, - tex : settings.tex, - atLink : settings.atLink, // for @link - emailLink : settings.emailLink, // for mail address auto link - flowChart : settings.flowChart, - sequenceDiagram : settings.sequenceDiagram, - previewCodeHighlight : settings.previewCodeHighlight, - }; - - var markedOptions = this.markedOptions = { - renderer : editormd.markedRenderer(markdownToC, rendererOptions), - gfm : true, - tables : true, - breaks : true, - pedantic : false, - sanitize : (settings.htmlDecode) ? false : true, // 关闭忽略HTML标签,即开启识别HTML标签,默认为false - smartLists : true, - smartypants : true - }; - - marked.setOptions(markedOptions); - - var newMarkdownDoc = editormd.$marked(cmValue, markedOptions); - - //console.info("cmValue", cmValue, newMarkdownDoc); - - newMarkdownDoc = editormd.filterHTMLTags(newMarkdownDoc, settings.htmlDecode); - - //console.error("cmValue", cmValue, newMarkdownDoc); - - this.markdownTextarea.text(cmValue); - - cm.save(); - - if (settings.saveHTMLToTextarea) - { - this.htmlTextarea.text(newMarkdownDoc); - } - - if(settings.watch || (!settings.watch && state.preview)) - { - previewContainer.html(newMarkdownDoc); - - this.previewCodeHighlight(); - - if (settings.toc) - { - var tocContainer = (settings.tocContainer === "") ? previewContainer : $(settings.tocContainer); - var tocMenu = tocContainer.find("." + this.classPrefix + "toc-menu"); - - tocContainer.attr("previewContainer", (settings.tocContainer === "") ? "true" : "false"); - - if (settings.tocContainer !== "" && tocMenu.length > 0) - { - tocMenu.remove(); - } - - editormd.markdownToCRenderer(markdownToC, tocContainer, settings.tocDropdown, settings.tocStartLevel); - - if (settings.tocDropdown || tocContainer.find("." + this.classPrefix + "toc-menu").length > 0) - { - editormd.tocDropdownMenu(tocContainer, (settings.tocTitle !== "") ? settings.tocTitle : this.lang.tocTitle); - } - - if (settings.tocContainer !== "") - { - previewContainer.find(".markdown-toc").css("border", "none"); - } - } - - if (settings.tex) - { - if (!editormd.kaTeXLoaded && settings.autoLoadModules) - { - editormd.loadKaTeX(function() { - editormd.$katex = katex; - editormd.kaTeXLoaded = true; - _this.katexRender(); - }); - } - else - { - editormd.$katex = katex; - this.katexRender(); - } - } - - if (settings.flowChart || settings.sequenceDiagram) - { - flowchartTimer = setTimeout(function(){ - clearTimeout(flowchartTimer); - _this.flowChartAndSequenceDiagramRender(); - flowchartTimer = null; - }, 10); - } - - if (state.loaded) - { - $.proxy(settings.onchange, this)(); - } - } - - return this; - }, - - /** - * 聚焦光标位置 - * Focusing the cursor position - * - * @returns {editormd} 返回editormd的实例对象 - */ - - focus : function() { - this.cm.focus(); - - return this; - }, - - /** - * 设置光标的位置 - * Set cursor position - * - * @param {Object} cursor 要设置的光标位置键值对象,例:{line:1, ch:0} - * @returns {editormd} 返回editormd的实例对象 - */ - - setCursor : function(cursor) { - this.cm.setCursor(cursor); - - return this; - }, - - /** - * 获取当前光标的位置 - * Get the current position of the cursor - * - * @returns {Cursor} 返回一个光标Cursor对象 - */ - - getCursor : function() { - return this.cm.getCursor(); - }, - - /** - * 设置光标选中的范围 - * Set cursor selected ranges - * - * @param {Object} from 开始位置的光标键值对象,例:{line:1, ch:0} - * @param {Object} to 结束位置的光标键值对象,例:{line:1, ch:0} - * @returns {editormd} 返回editormd的实例对象 - */ - - setSelection : function(from, to) { - - this.cm.setSelection(from, to); - - return this; - }, - - /** - * 获取光标选中的文本 - * Get the texts from cursor selected - * - * @returns {String} 返回选中文本的字符串形式 - */ - - getSelection : function() { - return this.cm.getSelection(); - }, - - /** - * 设置光标选中的文本范围 - * Set the cursor selection ranges - * - * @param {Array} ranges cursor selection ranges array - * @returns {Array} return this - */ - - setSelections : function(ranges) { - this.cm.setSelections(ranges); - - return this; - }, - - /** - * 获取光标选中的文本范围 - * Get the cursor selection ranges - * - * @returns {Array} return selection ranges array - */ - - getSelections : function() { - return this.cm.getSelections(); - }, - - /** - * 替换当前光标选中的文本或在当前光标处插入新字符 - * Replace the text at the current cursor selected or insert a new character at the current cursor position - * - * @param {String} value 要插入的字符值 - * @returns {editormd} 返回editormd的实例对象 - */ - - replaceSelection : function(value) { - this.cm.replaceSelection(value); - - return this; - }, - - /** - * 在当前光标处插入新字符 - * Insert a new character at the current cursor position - * - * 同replaceSelection()方法 - * With the replaceSelection() method - * - * @param {String} value 要插入的字符值 - * @returns {editormd} 返回editormd的实例对象 - */ - - insertValue : function(value) { - this.replaceSelection(value); - - return this; - }, - - /** - * 追加markdown - * append Markdown to editor - * - * @param {String} md 要追加的markdown源文档 - * @returns {editormd} 返回editormd的实例对象 - */ - - appendMarkdown : function(md) { - var settings = this.settings; - var cm = this.cm; - - cm.setValue(cm.getValue() + md); - - return this; - }, - - /** - * 设置和传入编辑器的markdown源文档 - * Set Markdown source document - * - * @param {String} md 要传入的markdown源文档 - * @returns {editormd} 返回editormd的实例对象 - */ - - setMarkdown : function(md) { - this.cm.setValue(md || this.settings.markdown); - - return this; - }, - - /** - * 获取编辑器的markdown源文档 - * Set Editor.md markdown/CodeMirror value - * - * @returns {editormd} 返回editormd的实例对象 - */ - - getMarkdown : function() { - return this.cm.getValue(); - }, - - /** - * 获取编辑器的源文档 - * Get CodeMirror value - * - * @returns {editormd} 返回editormd的实例对象 - */ - - getValue : function() { - return this.cm.getValue(); - }, - - /** - * 设置编辑器的源文档 - * Set CodeMirror value - * - * @param {String} value set code/value/string/text - * @returns {editormd} 返回editormd的实例对象 - */ - - setValue : function(value) { - this.cm.setValue(value); - - return this; - }, - - /** - * 清空编辑器 - * Empty CodeMirror editor container - * - * @returns {editormd} 返回editormd的实例对象 - */ - - clear : function() { - this.cm.setValue(""); - - return this; - }, - - /** - * 获取解析后存放在Textarea的HTML源码 - * Get parsed html code from Textarea - * - * @returns {String} 返回HTML源码 - */ - - getHTML : function() { - if (!this.settings.saveHTMLToTextarea) - { - alert("Error: settings.saveHTMLToTextarea == false"); - - return false; - } - - return this.htmlTextarea.val(); - }, - - /** - * getHTML()的别名 - * getHTML (alias) - * - * @returns {String} Return html code 返回HTML源码 - */ - - getTextareaSavedHTML : function() { - return this.getHTML(); - }, - - /** - * 获取预览窗口的HTML源码 - * Get html from preview container - * - * @returns {editormd} 返回editormd的实例对象 - */ - - getPreviewedHTML : function() { - if (!this.settings.watch) - { - alert("Error: settings.watch == false"); - - return false; - } - - return this.previewContainer.html(); - }, - - /** - * 开启实时预览 - * Enable real-time watching - * - * @returns {editormd} 返回editormd的实例对象 - */ - - watch : function(callback) { - var settings = this.settings; - - if ($.inArray(settings.mode, ["gfm", "markdown"]) < 0) - { - return this; - } - - this.state.watching = settings.watch = true; - this.preview.show(); - - if (this.toolbar) - { - var watchIcon = settings.toolbarIconsClass.watch; - var unWatchIcon = settings.toolbarIconsClass.unwatch; - - var icon = this.toolbar.find(".fa[name=watch]"); - icon.parent().attr("title", settings.lang.toolbar.watch); - icon.removeClass(unWatchIcon).addClass(watchIcon); - } - - this.codeMirror.css("border-right", "1px solid #ddd").width(this.editor.width() / 2); - - timer = 0; - - this.save().resize(); - - if (!settings.onwatch) - { - settings.onwatch = callback || function() {}; - } - - $.proxy(settings.onwatch, this)(); - - return this; - }, - - /** - * 关闭实时预览 - * Disable real-time watching - * - * @returns {editormd} 返回editormd的实例对象 - */ - - unwatch : function(callback) { - var settings = this.settings; - this.state.watching = settings.watch = false; - this.preview.hide(); - - if (this.toolbar) - { - var watchIcon = settings.toolbarIconsClass.watch; - var unWatchIcon = settings.toolbarIconsClass.unwatch; - - var icon = this.toolbar.find(".fa[name=watch]"); - icon.parent().attr("title", settings.lang.toolbar.unwatch); - icon.removeClass(watchIcon).addClass(unWatchIcon); - } - - this.codeMirror.css("border-right", "none").width(this.editor.width()); - - this.resize(); - - if (!settings.onunwatch) - { - settings.onunwatch = callback || function() {}; - } - - $.proxy(settings.onunwatch, this)(); - - return this; - }, - - /** - * 显示编辑器 - * Show editor - * - * @param {Function} [callback=function()] 回调函数 - * @returns {editormd} 返回editormd的实例对象 - */ - - show : function(callback) { - callback = callback || function() {}; - - var _this = this; - this.editor.show(0, function() { - $.proxy(callback, _this)(); - }); - - return this; - }, - - /** - * 隐藏编辑器 - * Hide editor - * - * @param {Function} [callback=function()] 回调函数 - * @returns {editormd} 返回editormd的实例对象 - */ - - hide : function(callback) { - callback = callback || function() {}; - - var _this = this; - this.editor.hide(0, function() { - $.proxy(callback, _this)(); - }); - - return this; - }, - - /** - * 隐藏编辑器部分,只预览HTML - * Enter preview html state - * - * @returns {editormd} 返回editormd的实例对象 - */ - - previewing : function() { - - var _this = this; - var editor = this.editor; - var preview = this.preview; - var toolbar = this.toolbar; - var settings = this.settings; - var codeMirror = this.codeMirror; - var previewContainer = this.previewContainer; - - if ($.inArray(settings.mode, ["gfm", "markdown"]) < 0) { - return this; - } - - if (settings.toolbar && toolbar) { - toolbar.toggle(); - toolbar.find(".fa[name=preview]").toggleClass("active"); - } - - codeMirror.toggle(); - - var escHandle = function(event) { - if (event.shiftKey && event.keyCode === 27) { - _this.previewed(); - } - }; - - if (codeMirror.css("display") === "none") // 为了兼容Zepto,而不使用codeMirror.is(":hidden") - { - this.state.preview = true; - - if (this.state.fullscreen) { - preview.css("background", "#fff"); - } - - editor.find("." + this.classPrefix + "preview-close-btn").show().bind(editormd.mouseOrTouch("click", "touchend"), function(){ - _this.previewed(); - }); - - if (!settings.watch) - { - this.save(); - } - else - { - previewContainer.css("padding", ""); - } - - previewContainer.addClass(this.classPrefix + "preview-active"); - - preview.show().css({ - position : "", - top : 0, - width : editor.width(), - height : (settings.autoHeight && !this.state.fullscreen) ? "auto" : editor.height() - }); - - if (this.state.loaded) - { - $.proxy(settings.onpreviewing, this)(); - } - - $(window).bind("keyup", escHandle); - } - else - { - $(window).unbind("keyup", escHandle); - this.previewed(); - } - }, - - /** - * 显示编辑器部分,退出只预览HTML - * Exit preview html state - * - * @returns {editormd} 返回editormd的实例对象 - */ - - previewed : function() { - - var editor = this.editor; - var preview = this.preview; - var toolbar = this.toolbar; - var settings = this.settings; - var previewContainer = this.previewContainer; - var previewCloseBtn = editor.find("." + this.classPrefix + "preview-close-btn"); - - this.state.preview = false; - - this.codeMirror.show(); - - if (settings.toolbar) { - toolbar.show(); - } - - preview[(settings.watch) ? "show" : "hide"](); - - previewCloseBtn.hide().unbind(editormd.mouseOrTouch("click", "touchend")); - - previewContainer.removeClass(this.classPrefix + "preview-active"); - - if (settings.watch) - { - previewContainer.css("padding", "20px"); - } - - preview.css({ - background : null, - position : "absolute", - width : editor.width() / 2, - height : (settings.autoHeight && !this.state.fullscreen) ? "auto" : editor.height() - toolbar.height(), - top : (settings.toolbar) ? toolbar.height() : 0 - }); - - if (this.state.loaded) - { - $.proxy(settings.onpreviewed, this)(); - } - - return this; - }, - - /** - * 编辑器全屏显示 - * Fullscreen show - * - * @returns {editormd} 返回editormd的实例对象 - */ - - fullscreen : function() { - - var _this = this; - var state = this.state; - var editor = this.editor; - var preview = this.preview; - var toolbar = this.toolbar; - var settings = this.settings; - var fullscreenClass = this.classPrefix + "fullscreen"; - - if (toolbar) { - toolbar.find(".fa[name=fullscreen]").parent().toggleClass("active"); - } - - var escHandle = function(event) { - if (!event.shiftKey && event.keyCode === 27) - { - if (state.fullscreen) - { - _this.fullscreenExit(); - } - } - }; - - if (!editor.hasClass(fullscreenClass)) - { - state.fullscreen = true; - - $("html,body").css("overflow", "hidden"); - - editor.css({ - width : $(window).width(), - height : $(window).height() - }).addClass(fullscreenClass); - - this.resize(); - - $.proxy(settings.onfullscreen, this)(); - - $(window).bind("keyup", escHandle); - } - else - { - $(window).unbind("keyup", escHandle); - this.fullscreenExit(); - } - - return this; - }, - - /** - * 编辑器退出全屏显示 - * Exit fullscreen state - * - * @returns {editormd} 返回editormd的实例对象 - */ - - fullscreenExit : function() { - - var editor = this.editor; - var settings = this.settings; - var toolbar = this.toolbar; - var fullscreenClass = this.classPrefix + "fullscreen"; - - this.state.fullscreen = false; - - if (toolbar) { - toolbar.find(".fa[name=fullscreen]").parent().removeClass("active"); - } - - $("html,body").css("overflow", ""); - - editor.css({ - width : editor.data("oldWidth"), - height : editor.data("oldHeight") - }).removeClass(fullscreenClass); - - this.resize(); - - $.proxy(settings.onfullscreenExit, this)(); - - return this; - }, - - /** - * 加载并执行插件 - * Load and execute the plugin - * - * @param {String} name plugin name / function name - * @param {String} path plugin load path - * @returns {editormd} 返回editormd的实例对象 - */ - - executePlugin : function(name, path) { - - var _this = this; - var cm = this.cm; - var settings = this.settings; - - path = settings.pluginPath + path; - - if (typeof define === "function") - { - if (typeof this[name] === "undefined") - { - alert("Error: " + name + " plugin is not found, you are not load this plugin."); - - return this; - } - - this[name](cm); - - return this; - } - - if ($.inArray(path, editormd.loadFiles.plugin) < 0) - { - editormd.loadPlugin(path, function() { - editormd.loadPlugins[name] = _this[name]; - _this[name](cm); - }); - } - else - { - $.proxy(editormd.loadPlugins[name], this)(cm); - } - - return this; - }, - - /** - * 搜索替换 - * Search & replace - * - * @param {String} command CodeMirror serach commands, "find, fintNext, fintPrev, clearSearch, replace, replaceAll" - * @returns {editormd} return this - */ - - search : function(command) { - var settings = this.settings; - - if (!settings.searchReplace) - { - alert("Error: settings.searchReplace == false"); - return this; - } - - if (!settings.readOnly) - { - this.cm.execCommand(command || "find"); - } - - return this; - }, - - searchReplace : function() { - this.search("replace"); - - return this; - }, - - searchReplaceAll : function() { - this.search("replaceAll"); - - return this; - } - }; - - editormd.fn.init.prototype = editormd.fn; - - /** - * 锁屏 - * lock screen when dialog opening - * - * @returns {void} - */ - - editormd.dialogLockScreen = function() { - var settings = this.settings || {dialogLockScreen : true}; - - if (settings.dialogLockScreen) - { - $("html,body").css("overflow", "hidden"); - this.resize(); - } - }; - - /** - * 显示透明背景层 - * Display mask layer when dialog opening - * - * @param {Object} dialog dialog jQuery object - * @returns {void} - */ - - editormd.dialogShowMask = function(dialog) { - var editor = this.editor; - var settings = this.settings || {dialogShowMask : true}; - - dialog.css({ - top : ($(window).height() - dialog.height()) / 2 + "px", - left : ($(window).width() - dialog.width()) / 2 + "px" - }); - - if (settings.dialogShowMask) { - editor.children("." + this.classPrefix + "mask").css("z-index", parseInt(dialog.css("z-index")) - 1).show(); - } - }; - - editormd.toolbarHandlers = { - undo : function() { - this.cm.undo(); - }, - - redo : function() { - this.cm.redo(); - }, - - bold : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("**" + selection + "**"); - - if(selection === "") { - cm.setCursor(cursor.line, cursor.ch + 2); - } - }, - - del : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("~~" + selection + "~~"); - - if(selection === "") { - cm.setCursor(cursor.line, cursor.ch + 2); - } - }, - - italic : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("*" + selection + "*"); - - if(selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); - } - }, - - quote : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("> " + selection); - cm.setCursor(cursor.line, cursor.ch + 2); - } - else - { - cm.replaceSelection("> " + selection); - } - - //cm.replaceSelection("> " + selection); - //cm.setCursor(cursor.line, (selection === "") ? cursor.ch + 2 : cursor.ch + selection.length + 2); - }, - - ucfirst : function() { - var cm = this.cm; - var selection = cm.getSelection(); - var selections = cm.listSelections(); - - cm.replaceSelection(editormd.firstUpperCase(selection)); - cm.setSelections(selections); - }, - - ucwords : function() { - var cm = this.cm; - var selection = cm.getSelection(); - var selections = cm.listSelections(); - - cm.replaceSelection(editormd.wordsFirstUpperCase(selection)); - cm.setSelections(selections); - }, - - uppercase : function() { - var cm = this.cm; - var selection = cm.getSelection(); - var selections = cm.listSelections(); - - cm.replaceSelection(selection.toUpperCase()); - cm.setSelections(selections); - }, - - lowercase : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - var selections = cm.listSelections(); - - cm.replaceSelection(selection.toLowerCase()); - cm.setSelections(selections); - }, - - h1 : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("# " + selection); - cm.setCursor(cursor.line, cursor.ch + 2); - } - else - { - cm.replaceSelection("# " + selection); - } - }, - - h2 : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("## " + selection); - cm.setCursor(cursor.line, cursor.ch + 3); - } - else - { - cm.replaceSelection("## " + selection); - } - }, - - h3 : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("### " + selection); - cm.setCursor(cursor.line, cursor.ch + 4); - } - else - { - cm.replaceSelection("### " + selection); - } - }, - - h4 : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("#### " + selection); - cm.setCursor(cursor.line, cursor.ch + 5); - } - else - { - cm.replaceSelection("#### " + selection); - } - }, - - h5 : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("##### " + selection); - cm.setCursor(cursor.line, cursor.ch + 6); - } - else - { - cm.replaceSelection("##### " + selection); - } - }, - - h6 : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("###### " + selection); - cm.setCursor(cursor.line, cursor.ch + 7); - } - else - { - cm.replaceSelection("###### " + selection); - } - }, - - "list-ul" : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (selection === "") - { - cm.replaceSelection("- " + selection); - } - else - { - var selectionText = selection.split("\n"); - - for (var i = 0, len = selectionText.length; i < len; i++) - { - selectionText[i] = (selectionText[i] === "") ? "" : "- " + selectionText[i]; - } - - cm.replaceSelection(selectionText.join("\n")); - } - }, - - "list-ol" : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if(selection === "") - { - cm.replaceSelection("1. " + selection); - } - else - { - var selectionText = selection.split("\n"); - - for (var i = 0, len = selectionText.length; i < len; i++) - { - selectionText[i] = (selectionText[i] === "") ? "" : (i+1) + ". " + selectionText[i]; - } - - cm.replaceSelection(selectionText.join("\n")); - } - }, - - hr : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection(((cursor.ch !== 0) ? "\n\n" : "\n") + "------------\n\n"); - }, - - tex : function() { - if (!this.settings.tex) - { - alert("settings.tex === false"); - return this; - } - - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("$$" + selection + "$$"); - - if(selection === "") { - cm.setCursor(cursor.line, cursor.ch + 2); - } - }, - - link : function() { - this.executePlugin("linkDialog", "link-dialog/link-dialog"); - }, - - "reference-link" : function() { - this.executePlugin("referenceLinkDialog", "reference-link-dialog/reference-link-dialog"); - }, - - pagebreak : function() { - if (!this.settings.pageBreak) - { - alert("settings.pageBreak === false"); - return this; - } - - var cm = this.cm; - var selection = cm.getSelection(); - - cm.replaceSelection("\r\n[========]\r\n"); - }, - - image : function() { - this.executePlugin("imageDialog", "image-dialog/image-dialog"); - }, - - code : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("`" + selection + "`"); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); - } - }, - - "code-block" : function() { - this.executePlugin("codeBlockDialog", "code-block-dialog/code-block-dialog"); - }, - - "preformatted-text" : function() { - this.executePlugin("preformattedTextDialog", "preformatted-text-dialog/preformatted-text-dialog"); - }, - - table : function() { - this.executePlugin("tableDialog", "table-dialog/table-dialog"); - }, - - datetime : function() { - var cm = this.cm; - var selection = cm.getSelection(); - var date = new Date(); - var langName = this.settings.lang.name; - var datefmt = editormd.dateFormat() + " " + editormd.dateFormat((langName === "zh-cn" || langName === "zh-tw") ? "cn-week-day" : "week-day"); - - cm.replaceSelection(datefmt); - }, - - emoji : function() { - this.executePlugin("emojiDialog", "emoji-dialog/emoji-dialog"); - }, - - "html-entities" : function() { - this.executePlugin("htmlEntitiesDialog", "html-entities-dialog/html-entities-dialog"); - }, - - "goto-line" : function() { - this.executePlugin("gotoLineDialog", "goto-line-dialog/goto-line-dialog"); - }, - - watch : function() { - this[this.settings.watch ? "unwatch" : "watch"](); - }, - - preview : function() { - this.previewing(); - }, - - fullscreen : function() { - this.fullscreen(); - }, - - clear : function() { - this.clear(); - }, - - search : function() { - this.search(); - }, - - help : function() { - this.executePlugin("helpDialog", "help-dialog/help-dialog"); - }, - - info : function() { - this.showInfoDialog(); - } - }; - - editormd.keyMaps = { - "Ctrl-1" : "h1", - "Ctrl-2" : "h2", - "Ctrl-3" : "h3", - "Ctrl-4" : "h4", - "Ctrl-5" : "h5", - "Ctrl-6" : "h6", - "Ctrl-B" : "bold", // if this is string == editormd.toolbarHandlers.xxxx - "Ctrl-D" : "datetime", - - "Ctrl-E" : function() { // emoji - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (!this.settings.emoji) - { - alert("Error: settings.emoji == false"); - return ; - } - - cm.replaceSelection(":" + selection + ":"); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); - } - }, - "Ctrl-Alt-G" : "goto-line", - "Ctrl-H" : "hr", - "Ctrl-I" : "italic", - "Ctrl-K" : "code", - - "Ctrl-L" : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - var title = (selection === "") ? "" : " \""+selection+"\""; - - cm.replaceSelection("[" + selection + "]("+title+")"); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); - } - }, - "Ctrl-U" : "list-ul", - - "Shift-Ctrl-A" : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (!this.settings.atLink) - { - alert("Error: settings.atLink == false"); - return ; - } - - cm.replaceSelection("@" + selection); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); - } - }, - - "Shift-Ctrl-C" : "code", - "Shift-Ctrl-Q" : "quote", - "Shift-Ctrl-S" : "del", - "Shift-Ctrl-K" : "tex", // KaTeX - - "Shift-Alt-C" : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection(["```", selection, "```"].join("\n")); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 3); - } - }, - - "Shift-Ctrl-Alt-C" : "code-block", - "Shift-Ctrl-H" : "html-entities", - "Shift-Alt-H" : "help", - "Shift-Ctrl-E" : "emoji", - "Shift-Ctrl-U" : "uppercase", - "Shift-Alt-U" : "ucwords", - "Shift-Ctrl-Alt-U" : "ucfirst", - "Shift-Alt-L" : "lowercase", - - "Shift-Ctrl-I" : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - var title = (selection === "") ? "" : " \""+selection+"\""; - - cm.replaceSelection("![" + selection + "]("+title+")"); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 4); - } - }, - - "Shift-Ctrl-Alt-I" : "image", - "Shift-Ctrl-L" : "link", - "Shift-Ctrl-O" : "list-ol", - "Shift-Ctrl-P" : "preformatted-text", - "Shift-Ctrl-T" : "table", - "Shift-Alt-P" : "pagebreak", - "F9" : "watch", - "F10" : "preview", - "F11" : "fullscreen", - }; - - /** - * 清除字符串两边的空格 - * Clear the space of strings both sides. - * - * @param {String} str string - * @returns {String} trimed string - */ - - var trim = function(str) { - return (!String.prototype.trim) ? str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "") : str.trim(); - }; - - editormd.trim = trim; - - /** - * 所有单词首字母大写 - * Words first to uppercase - * - * @param {String} str string - * @returns {String} string - */ - - var ucwords = function (str) { - return str.toLowerCase().replace(/\b(\w)|\s(\w)/g, function($1) { - return $1.toUpperCase(); - }); - }; - - editormd.ucwords = editormd.wordsFirstUpperCase = ucwords; - - /** - * 字符串首字母大写 - * Only string first char to uppercase - * - * @param {String} str string - * @returns {String} string - */ - - var firstUpperCase = function(str) { - return str.toLowerCase().replace(/\b(\w)/, function($1){ - return $1.toUpperCase(); - }); - }; - - var ucfirst = firstUpperCase; - - editormd.firstUpperCase = editormd.ucfirst = firstUpperCase; - - editormd.urls = { - atLinkBase : "https://github.com/" - }; - - editormd.regexs = { - atLink : /@(\w+)/g, - email : /(\w+)@(\w+)\.(\w+)\.?(\w+)?/g, - emailLink : /(mailto:)?([\w\.\_]+)@(\w+)\.(\w+)\.?(\w+)?/g, - emoji : /:([\w\+-]+):/g, - emojiDatetime : /(\d{2}:\d{2}:\d{2})/g, - twemoji : /:(tw-([\w]+)-?(\w+)?):/g, - fontAwesome : /:(fa-([\w]+)(-(\w+)){0,}):/g, - editormdLogo : /:(editormd-logo-?(\w+)?):/g, - pageBreak : /^\[[=]{8,}\]$/ - }; - - // Emoji graphics files url path - editormd.emoji = { - path : "http://www.emoji-cheat-sheet.com/graphics/emojis/", - ext : ".png" - }; - - // Twitter Emoji (Twemoji) graphics files url path - editormd.twemoji = { - path : "http://twemoji.maxcdn.com/36x36/", - ext : ".png" - }; - - /** - * 自定义marked的解析器 - * Custom Marked renderer rules - * - * @param {Array} markdownToC 传入用于接收TOC的数组 - * @returns {Renderer} markedRenderer 返回marked的Renderer自定义对象 - */ - - editormd.markedRenderer = function(markdownToC, options) { - var defaults = { - toc : true, // Table of contents - tocm : false, - tocStartLevel : 1, // Said from H1 to create ToC - pageBreak : true, - atLink : true, // for @link - emailLink : true, // for mail address auto link - taskList : false, // Enable Github Flavored Markdown task lists - emoji : false, // :emoji: , Support Twemoji, fontAwesome, Editor.md logo emojis. - tex : false, // TeX(LaTeX), based on KaTeX - flowChart : false, // flowChart.js only support IE9+ - sequenceDiagram : false, // sequenceDiagram.js only support IE9+ - }; - - var settings = $.extend(defaults, options || {}); - var marked = editormd.$marked; - var markedRenderer = new marked.Renderer(); - markdownToC = markdownToC || []; - - var regexs = editormd.regexs; - var atLinkReg = regexs.atLink; - var emojiReg = regexs.emoji; - var emailReg = regexs.email; - var emailLinkReg = regexs.emailLink; - var twemojiReg = regexs.twemoji; - var faIconReg = regexs.fontAwesome; - var editormdLogoReg = regexs.editormdLogo; - var pageBreakReg = regexs.pageBreak; - - markedRenderer.emoji = function(text) { - - text = text.replace(editormd.regexs.emojiDatetime, function($1) { - return $1.replace(/:/g, ":"); - }); - - var matchs = text.match(emojiReg); - - if (!matchs || !settings.emoji) { - return text; - } - - for (var i = 0, len = matchs.length; i < len; i++) - { - if (matchs[i] === ":+1:") { - matchs[i] = ":\\+1:"; - } - - text = text.replace(new RegExp(matchs[i]), function($1, $2){ - var faMatchs = $1.match(faIconReg); - var name = $1.replace(/:/g, ""); - - if (faMatchs) - { - for (var fa = 0, len1 = faMatchs.length; fa < len1; fa++) - { - var faName = faMatchs[fa].replace(/:/g, ""); - - return ""; - } - } - else - { - var emdlogoMathcs = $1.match(editormdLogoReg); - var twemojiMatchs = $1.match(twemojiReg); - - if (emdlogoMathcs) - { - for (var x = 0, len2 = emdlogoMathcs.length; x < len2; x++) - { - var logoName = emdlogoMathcs[x].replace(/:/g, ""); - return ""; - } - } - else if (twemojiMatchs) - { - for (var t = 0, len3 = twemojiMatchs.length; t < len3; t++) - { - var twe = twemojiMatchs[t].replace(/:/g, "").replace("tw-", ""); - return "\"twemoji-""; - } - } - else - { - var src = (name === "+1") ? "plus1" : name; - src = (src === "black_large_square") ? "black_square" : src; - src = (src === "moon") ? "waxing_gibbous_moon" : src; - - return "\":""; - } - } - }); - } - - return text; - }; - - markedRenderer.atLink = function(text) { - - if (atLinkReg.test(text)) - { - if (settings.atLink) - { - text = text.replace(emailReg, function($1, $2, $3, $4) { - return $1.replace(/@/g, "_#_@_#_"); - }); - - text = text.replace(atLinkReg, function($1, $2) { - return "" + $1 + ""; - }).replace(/_#_@_#_/g, "@"); - } - - if (settings.emailLink) - { - text = text.replace(emailLinkReg, function($1, $2, $3, $4, $5) { - return (!$2 && $.inArray($5, "jpg|jpeg|png|gif|webp|ico|icon|pdf".split("|")) < 0) ? ""+$1+"" : $1; - }); - } - - return text; - } - - return text; - }; - - markedRenderer.link = function (href, title, text) { - - if (this.options.sanitize) { - try { - var prot = decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase(); - } catch(e) { - return ""; - } - - if (prot.indexOf("javascript:") === 0) { - return ""; - } - } - - var out = "" + text.replace(/@/g, "@") + ""; - } - - if (title) { - out += " title=\"" + title + "\""; - } - - out += ">" + text + ""; - - return out; - }; - - markedRenderer.heading = function(text, level, raw) { - - var linkText = text; - var hasLinkReg = /\s*\]*)\>(.*)\<\/a\>\s*/; - var getLinkTextReg = /\s*\]+)\>([^\>]*)\<\/a\>\s*/g; - - if (hasLinkReg.test(text)) - { - var tempText = []; - text = text.split(/\]+)\>([^\>]*)\<\/a\>/); - - for (var i = 0, len = text.length; i < len; i++) - { - tempText.push(text[i].replace(/\s*href\=\"(.*)\"\s*/g, "")); - } - - text = tempText.join(" "); - } - - text = trim(text); - - var escapedText = text.toLowerCase().replace(/[^\w]+/g, "-"); - var toc = { - text : text, - level : level, - slug : escapedText - }; - - var isChinese = /^[\u4e00-\u9fa5]+$/.test(text); - var id = (isChinese) ? escape(text).replace(/\%/g, "") : text.toLowerCase().replace(/[^\w]+/g, "-"); - - markdownToC.push(toc); - - var headingHTML = ""; - - headingHTML += ""; - headingHTML += ""; - headingHTML += (hasLinkReg) ? this.atLink(this.emoji(linkText)) : this.atLink(this.emoji(text)); - headingHTML += ""; - - return headingHTML; - }; - - markedRenderer.pageBreak = function(text) { - if (pageBreakReg.test(text) && settings.pageBreak) - { - text = "
    "; - } - - return text; - }; - - markedRenderer.paragraph = function(text) { - var isTeXInline = /\$\$(.*)\$\$/g.test(text); - var isTeXLine = /^\$\$(.*)\$\$$/.test(text); - var isTeXAddClass = (isTeXLine) ? " class=\"" + editormd.classNames.tex + "\"" : ""; - var isToC = (settings.tocm) ? /^(\[TOC\]|\[TOCM\])$/.test(text) : /^\[TOC\]$/.test(text); - var isToCMenu = /^\[TOCM\]$/.test(text); - - if (!isTeXLine && isTeXInline) - { - text = text.replace(/(\$\$([^\$]*)\$\$)+/g, function($1, $2) { - return "" + $2.replace(/\$/g, "") + ""; - }); - } - else - { - text = (isTeXLine) ? text.replace(/\$/g, "") : text; - } - - var tocHTML = "
    " + text + "
    "; - - return (isToC) ? ( (isToCMenu) ? "
    " + tocHTML + "

    " : tocHTML ) - : ( (pageBreakReg.test(text)) ? this.pageBreak(text) : "" + this.atLink(this.emoji(text)) + "

    \n" ); - }; - - markedRenderer.code = function (code, lang, escaped) { - - if (lang === "seq" || lang === "sequence") - { - return "
    " + code + "
    "; - } - else if ( lang === "flow") - { - return "
    " + code + "
    "; - } - else if ( lang === "math" || lang === "latex" || lang === "katex") - { - return "

    " + code + "

    "; - } - else - { - - return marked.Renderer.prototype.code.apply(this, arguments); - } - }; - - markedRenderer.tablecell = function(content, flags) { - var type = (flags.header) ? "th" : "td"; - var tag = (flags.align) ? "<" + type +" style=\"text-align:" + flags.align + "\">" : "<" + type + ">"; - - return tag + this.atLink(this.emoji(content)) + "\n"; - }; - - markedRenderer.listitem = function(text) { - if (settings.taskList && /^\s*\[[x\s]\]\s*/.test(text)) - { - text = text.replace(/^\s*\[\s\]\s*/, " ") - .replace(/^\s*\[x\]\s*/, " "); - - return "
  • " + this.atLink(this.emoji(text)) + "
  • "; - } - else - { - return "
  • " + this.atLink(this.emoji(text)) + "
  • "; - } - }; - - return markedRenderer; - }; - - /** - * - * 生成TOC(Table of Contents) - * Creating ToC (Table of Contents) - * - * @param {Array} toc 从marked获取的TOC数组列表 - * @param {Element} container 插入TOC的容器元素 - * @param {Integer} startLevel Hx 起始层级 - * @returns {Object} tocContainer 返回ToC列表容器层的jQuery对象元素 - */ - - editormd.markdownToCRenderer = function(toc, container, tocDropdown, startLevel) { - - var html = ""; - var lastLevel = 0; - var classPrefix = this.classPrefix; - - startLevel = startLevel || 1; - - for (var i = 0, len = toc.length; i < len; i++) - { - var text = toc[i].text; - var level = toc[i].level; - - if (level < startLevel) { - continue; - } - - if (level > lastLevel) - { - html += ""; - } - else if (level < lastLevel) - { - html += (new Array(lastLevel - level + 2)).join(""); - } - else - { - html += ""; - } - - html += "
  • " + text + "
      "; - lastLevel = level; - } - - var tocContainer = container.find(".markdown-toc"); - - if ((tocContainer.length < 1 && container.attr("previewContainer") === "false")) - { - var tocHTML = "
      "; - - tocHTML = (tocDropdown) ? "
      " + tocHTML + "
      " : tocHTML; - - container.html(tocHTML); - - tocContainer = container.find(".markdown-toc"); - } - - if (tocDropdown) - { - tocContainer.wrap("

      "); - } - - tocContainer.html("
        ").children(".markdown-toc-list").html(html.replace(/\r?\n?\\<\/ul\>/g, "")); - - return tocContainer; - }; - - /** - * - * 生成TOC下拉菜单 - * Creating ToC dropdown menu - * - * @param {Object} container 插入TOC的容器jQuery对象元素 - * @param {String} tocTitle ToC title - * @returns {Object} return toc-menu object - */ - - editormd.tocDropdownMenu = function(container, tocTitle) { - - tocTitle = tocTitle || "Table of Contents"; - - var zindex = 400; - var tocMenus = container.find("." + this.classPrefix + "toc-menu"); - - tocMenus.each(function() { - var $this = $(this); - var toc = $this.children(".markdown-toc"); - var icon = ""; - var btn = "" + icon + tocTitle + ""; - var menu = toc.children("ul"); - var list = menu.find("li"); - - toc.append(btn); - - list.first().before("
      • " + tocTitle + " " + icon + "

      • "); - - $this.mouseover(function(){ - menu.show(); - - list.each(function(){ - var li = $(this); - var ul = li.children("ul"); - - if (ul.html() === "") - { - ul.remove(); - } - - if (ul.length > 0 && ul.html() !== "") - { - var firstA = li.children("a").first(); - - if (firstA.children(".fa").length < 1) - { - firstA.append( $(icon).css({ float:"right", paddingTop:"4px" }) ); - } - } - - li.mouseover(function(){ - ul.css("z-index", zindex).show(); - zindex += 1; - }).mouseleave(function(){ - ul.hide(); - }); - }); - }).mouseleave(function(){ - menu.hide(); - }); - }); - - return tocMenus; - }; - - /** - * 简单地过滤指定的HTML标签 - * Filter custom html tags - * - * @param {String} html 要过滤HTML - * @param {String} filters 要过滤的标签 - * @returns {String} html 返回过滤的HTML - */ - - editormd.filterHTMLTags = function(html, filters) { - - if (typeof html !== "string") { - html = new String(html); - } - - if (typeof filters !== "string") { - return html; - } - - var expression = filters.split("|"); - var filterTags = expression[0].split(","); - var attrs = expression[1]; - - for (var i = 0, len = filterTags.length; i < len; i++) - { - var tag = filterTags[i]; - - html = html.replace(new RegExp("\<\s*" + tag + "\s*([^\>]*)\>([^\>]*)\<\s*\/" + tag + "\s*\>", "igm"), ""); - } - - //return html; - - if (typeof attrs !== "undefined") - { - var htmlTagRegex = /\<(\w+)\s*([^\>]*)\>([^\>]*)\<\/(\w+)\>/ig; - - if (attrs === "*") - { - html = html.replace(htmlTagRegex, function($1, $2, $3, $4, $5) { - return "<" + $2 + ">" + $4 + ""; - }); - } - else if (attrs === "on*") - { - html = html.replace(htmlTagRegex, function($1, $2, $3, $4, $5) { - var el = $("<" + $2 + ">" + $4 + ""); - var _attrs = $($1)[0].attributes; - var $attrs = {}; - - $.each(_attrs, function(i, e) { - if (e.nodeName !== '"') $attrs[e.nodeName] = e.nodeValue; - }); - - $.each($attrs, function(i) { - if (i.indexOf("on") === 0) { - delete $attrs[i]; - } - }); - - el.attr($attrs); - - var text = (typeof el[1] !== "undefined") ? $(el[1]).text() : ""; - - return el[0].outerHTML + text; - }); - } - else - { - html = html.replace(htmlTagRegex, function($1, $2, $3, $4) { - var filterAttrs = attrs.split(","); - var el = $($1); - el.html($4); - - $.each(filterAttrs, function(i) { - el.attr(filterAttrs[i], null); - }); - - return el[0].outerHTML; - }); - } - } - - return html; - }; - - /** - * 将Markdown文档解析为HTML用于前台显示 - * Parse Markdown to HTML for Font-end preview. - * - * @param {String} id 用于显示HTML的对象ID - * @param {Object} [options={}] 配置选项,可选 - * @returns {Object} div 返回jQuery对象元素 - */ - - editormd.markdownToHTML = function(id, options) { - var defaults = { - gfm : true, - toc : true, - tocm : false, - tocStartLevel : 1, - tocTitle : "目录", - tocDropdown : false, - tocContainer : "", - markdown : "", - markdownSourceCode : false, - htmlDecode : false, - autoLoadKaTeX : true, - pageBreak : true, - atLink : true, // for @link - emailLink : true, // for mail address auto link - tex : false, - taskList : false, // Github Flavored Markdown task lists - emoji : false, - flowChart : false, - sequenceDiagram : false, - previewCodeHighlight : true - }; - - editormd.$marked = marked; - - var div = $("#" + id); - var settings = div.settings = $.extend(true, defaults, options || {}); - var saveTo = div.find("textarea"); - - if (saveTo.length < 1) - { - div.append(""); - saveTo = div.find("textarea"); - } - - var markdownDoc = (settings.markdown === "") ? saveTo.val() : settings.markdown; - var markdownToC = []; - - var rendererOptions = { - toc : settings.toc, - tocm : settings.tocm, - tocStartLevel : settings.tocStartLevel, - taskList : settings.taskList, - emoji : settings.emoji, - tex : settings.tex, - pageBreak : settings.pageBreak, - atLink : settings.atLink, // for @link - emailLink : settings.emailLink, // for mail address auto link - flowChart : settings.flowChart, - sequenceDiagram : settings.sequenceDiagram, - previewCodeHighlight : settings.previewCodeHighlight, - }; - - var markedOptions = { - renderer : editormd.markedRenderer(markdownToC, rendererOptions), - gfm : settings.gfm, - tables : true, - breaks : true, - pedantic : false, - sanitize : (settings.htmlDecode) ? false : true, // 是否忽略HTML标签,即是否开启HTML标签解析,为了安全性,默认不开启 - smartLists : true, - smartypants : true - }; - - markdownDoc = new String(markdownDoc); - - var markdownParsed = marked(markdownDoc, markedOptions); - - markdownParsed = editormd.filterHTMLTags(markdownParsed, settings.htmlDecode); - - if (settings.markdownSourceCode) { - saveTo.text(markdownDoc); - } else { - saveTo.remove(); - } - - div.addClass("markdown-body " + this.classPrefix + "html-preview").append(markdownParsed); - - var tocContainer = (settings.tocContainer !== "") ? $(settings.tocContainer) : div; - - if (settings.tocContainer !== "") - { - tocContainer.attr("previewContainer", false); - } - - if (settings.toc) - { - div.tocContainer = this.markdownToCRenderer(markdownToC, tocContainer, settings.tocDropdown, settings.tocStartLevel); - - if (settings.tocDropdown || div.find("." + this.classPrefix + "toc-menu").length > 0) - { - this.tocDropdownMenu(div, settings.tocTitle); - } - - if (settings.tocContainer !== "") - { - div.find(".editormd-toc-menu, .editormd-markdown-toc").remove(); - } - } - - if (settings.previewCodeHighlight) - { - div.find("pre").addClass("prettyprint linenums"); - prettyPrint(); - } - - if (!editormd.isIE8) - { - if (settings.flowChart) { - div.find(".flowchart").flowChart(); - } - - if (settings.sequenceDiagram) { - div.find(".sequence-diagram").sequenceDiagram({theme: "simple"}); - } - } - - if (settings.tex) - { - var katexHandle = function() { - div.find("." + editormd.classNames.tex).each(function(){ - var tex = $(this); - katex.render(tex.html().replace(/</g, "<").replace(/>/g, ">"), tex[0]); - tex.find(".katex").css("font-size", "1.6em"); - }); - }; - - if (settings.autoLoadKaTeX && !editormd.$katex && !editormd.kaTeXLoaded) - { - this.loadKaTeX(function() { - editormd.$katex = katex; - editormd.kaTeXLoaded = true; - katexHandle(); - }); - } - else - { - katexHandle(); - } - } - - div.getMarkdown = function() { - return saveTo.val(); - }; - - return div; - }; - - // Editor.md themes, change toolbar themes etc. - // added @1.5.0 - editormd.themes = ["default", "dark"]; - - // Preview area themes - // added @1.5.0 - editormd.previewThemes = ["default", "dark"]; - - // CodeMirror / editor area themes - // @1.5.0 rename -> editorThemes, old version -> themes - editormd.editorThemes = [ - "default", "3024-day", "3024-night", - "ambiance", "ambiance-mobile", - "base16-dark", "base16-light", "blackboard", - "cobalt", - "eclipse", "elegant", "erlang-dark", - "lesser-dark", - "mbo", "mdn-like", "midnight", "monokai", - "neat", "neo", "night", - "paraiso-dark", "paraiso-light", "pastel-on-dark", - "rubyblue", - "solarized", - "the-matrix", "tomorrow-night-eighties", "twilight", - "vibrant-ink", - "xq-dark", "xq-light" - ]; - - editormd.loadPlugins = {}; - - editormd.loadFiles = { - js : [], - css : [], - plugin : [] - }; - - /** - * 动态加载Editor.md插件,但不立即执行 - * Load editor.md plugins - * - * @param {String} fileName 插件文件路径 - * @param {Function} [callback=function()] 加载成功后执行的回调函数 - * @param {String} [into="head"] 嵌入页面的位置 - */ - - editormd.loadPlugin = function(fileName, callback, into) { - callback = callback || function() {}; - - this.loadScript(fileName, function() { - editormd.loadFiles.plugin.push(fileName); - callback(); - }, into); - }; - - /** - * 动态加载CSS文件的方法 - * Load css file method - * - * @param {String} fileName CSS文件名 - * @param {Function} [callback=function()] 加载成功后执行的回调函数 - * @param {String} [into="head"] 嵌入页面的位置 - */ - - editormd.loadCSS = function(fileName, callback, into) { - into = into || "head"; - callback = callback || function() {}; - - var css = document.createElement("link"); - css.type = "text/css"; - css.rel = "stylesheet"; - css.onload = css.onreadystatechange = function() { - editormd.loadFiles.css.push(fileName); - callback(); - }; - - css.href = fileName + ".css"; - - if(into === "head") { - document.getElementsByTagName("head")[0].appendChild(css); - } else { - document.body.appendChild(css); - } - }; - - editormd.isIE = (navigator.appName == "Microsoft Internet Explorer"); - editormd.isIE8 = (editormd.isIE && navigator.appVersion.match(/8./i) == "8."); - - /** - * 动态加载JS文件的方法 - * Load javascript file method - * - * @param {String} fileName JS文件名 - * @param {Function} [callback=function()] 加载成功后执行的回调函数 - * @param {String} [into="head"] 嵌入页面的位置 - */ - - editormd.loadScript = function(fileName, callback, into) { - - into = into || "head"; - callback = callback || function() {}; - - var script = null; - script = document.createElement("script"); - script.id = fileName.replace(/[\./]+/g, "-"); - script.type = "text/javascript"; - script.src = fileName + ".js"; - - if (editormd.isIE8) - { - script.onreadystatechange = function() { - if(script.readyState) - { - if (script.readyState === "loaded" || script.readyState === "complete") - { - script.onreadystatechange = null; - editormd.loadFiles.js.push(fileName); - callback(); - } - } - }; - } - else - { - script.onload = function() { - editormd.loadFiles.js.push(fileName); - callback(); - }; - } - - if (into === "head") { - document.getElementsByTagName("head")[0].appendChild(script); - } else { - document.body.appendChild(script); - } - }; - - // 使用国外的CDN,加载速度有时会很慢,或者自定义URL - // You can custom KaTeX load url. - editormd.katexURL = { - css : "//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.3.0/katex.min", - js : "//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.3.0/katex.min" - }; - - editormd.kaTeXLoaded = false; - - /** - * 加载KaTeX文件 - * load KaTeX files - * - * @param {Function} [callback=function()] 加载成功后执行的回调函数 - */ - - editormd.loadKaTeX = function (callback) { - editormd.loadCSS(editormd.katexURL.css, function(){ - editormd.loadScript(editormd.katexURL.js, callback || function(){}); - }); - }; - - /** - * 锁屏 - * lock screen - * - * @param {Boolean} lock Boolean 布尔值,是否锁屏 - * @returns {void} - */ - - editormd.lockScreen = function(lock) { - $("html,body").css("overflow", (lock) ? "hidden" : ""); - }; - - /** - * 动态创建对话框 - * Creating custom dialogs - * - * @param {Object} options 配置项键值对 Key/Value - * @returns {dialog} 返回创建的dialog的jQuery实例对象 - */ - - editormd.createDialog = function(options) { - var defaults = { - name : "", - width : 420, - height: 240, - title : "", - drag : true, - closed : true, - content : "", - mask : true, - maskStyle : { - backgroundColor : "#fff", - opacity : 0.1 - }, - lockScreen : true, - footer : true, - buttons : false - }; - - options = $.extend(true, defaults, options); - - var $this = this; - var editor = this.editor; - var classPrefix = editormd.classPrefix; - var guid = (new Date()).getTime(); - var dialogName = ( (options.name === "") ? classPrefix + "dialog-" + guid : options.name); - var mouseOrTouch = editormd.mouseOrTouch; - - var html = "
        "; - - if (options.title !== "") - { - html += "
        "; - html += "" + options.title + ""; - html += "
        "; - } - - if (options.closed) - { - html += ""; - } - - html += "
        " + options.content; - - if (options.footer || typeof options.footer === "string") - { - html += "
        " + ( (typeof options.footer === "boolean") ? "" : options.footer) + "
        "; - } - - html += "
        "; - - html += "
        "; - html += "
        "; - html += "
        "; - - editor.append(html); - - var dialog = editor.find("." + dialogName); - - dialog.lockScreen = function(lock) { - if (options.lockScreen) - { - $("html,body").css("overflow", (lock) ? "hidden" : ""); - $this.resize(); - } - - return dialog; - }; - - dialog.showMask = function() { - if (options.mask) - { - editor.find("." + classPrefix + "mask").css(options.maskStyle).css("z-index", editormd.dialogZindex - 1).show(); - } - return dialog; - }; - - dialog.hideMask = function() { - if (options.mask) - { - editor.find("." + classPrefix + "mask").hide(); - } - - return dialog; - }; - - dialog.loading = function(show) { - var loading = dialog.find("." + classPrefix + "dialog-mask"); - loading[(show) ? "show" : "hide"](); - - return dialog; - }; - - dialog.lockScreen(true).showMask(); - - dialog.show().css({ - zIndex : editormd.dialogZindex, - border : (editormd.isIE8) ? "1px solid #ddd" : "", - width : (typeof options.width === "number") ? options.width + "px" : options.width, - height : (typeof options.height === "number") ? options.height + "px" : options.height - }); - - var dialogPosition = function(){ - dialog.css({ - top : ($(window).height() - dialog.height()) / 2 + "px", - left : ($(window).width() - dialog.width()) / 2 + "px" - }); - }; - - dialogPosition(); - - $(window).resize(dialogPosition); - - dialog.children("." + classPrefix + "dialog-close").bind(mouseOrTouch("click", "touchend"), function() { - dialog.hide().lockScreen(false).hideMask(); - }); - - if (typeof options.buttons === "object") - { - var footer = dialog.footer = dialog.find("." + classPrefix + "dialog-footer"); - - for (var key in options.buttons) - { - var btn = options.buttons[key]; - var btnClassName = classPrefix + key + "-btn"; - - footer.append(""); - btn[1] = $.proxy(btn[1], dialog); - footer.children("." + btnClassName).bind(mouseOrTouch("click", "touchend"), btn[1]); - } - } - - if (options.title !== "" && options.drag) - { - var posX, posY; - var dialogHeader = dialog.children("." + classPrefix + "dialog-header"); - - if (!options.mask) { - dialogHeader.bind(mouseOrTouch("click", "touchend"), function(){ - editormd.dialogZindex += 2; - dialog.css("z-index", editormd.dialogZindex); - }); - } - - dialogHeader.mousedown(function(e) { - e = e || window.event; //IE - posX = e.clientX - parseInt(dialog[0].style.left); - posY = e.clientY - parseInt(dialog[0].style.top); - - document.onmousemove = moveAction; - }); - - var userCanSelect = function (obj) { - obj.removeClass(classPrefix + "user-unselect").off("selectstart"); - }; - - var userUnselect = function (obj) { - obj.addClass(classPrefix + "user-unselect").on("selectstart", function(event) { // selectstart for IE - return false; - }); - }; - - var moveAction = function (e) { - e = e || window.event; //IE - - var left, top, nowLeft = parseInt(dialog[0].style.left), nowTop = parseInt(dialog[0].style.top); - - if( nowLeft >= 0 ) { - if( nowLeft + dialog.width() <= $(window).width()) { - left = e.clientX - posX; - } else { - left = $(window).width() - dialog.width(); - document.onmousemove = null; - } - } else { - left = 0; - document.onmousemove = null; - } - - if( nowTop >= 0 ) { - top = e.clientY - posY; - } else { - top = 0; - document.onmousemove = null; - } - - - document.onselectstart = function() { - return false; - }; - - userUnselect($("body")); - userUnselect(dialog); - dialog[0].style.left = left + "px"; - dialog[0].style.top = top + "px"; - }; - - document.onmouseup = function() { - userCanSelect($("body")); - userCanSelect(dialog); - - document.onselectstart = null; - document.onmousemove = null; - }; - - dialogHeader.touchDraggable = function() { - var offset = null; - var start = function(e) { - var orig = e.originalEvent; - var pos = $(this).parent().position(); - - offset = { - x : orig.changedTouches[0].pageX - pos.left, - y : orig.changedTouches[0].pageY - pos.top - }; - }; - - var move = function(e) { - e.preventDefault(); - var orig = e.originalEvent; - - $(this).parent().css({ - top : orig.changedTouches[0].pageY - offset.y, - left : orig.changedTouches[0].pageX - offset.x - }); - }; - - this.bind("touchstart", start).bind("touchmove", move); - }; - - dialogHeader.touchDraggable(); - } - - editormd.dialogZindex += 2; - - return dialog; - }; - - /** - * 鼠标和触摸事件的判断/选择方法 - * MouseEvent or TouchEvent type switch - * - * @param {String} [mouseEventType="click"] 供选择的鼠标事件 - * @param {String} [touchEventType="touchend"] 供选择的触摸事件 - * @returns {String} EventType 返回事件类型名称 - */ - - editormd.mouseOrTouch = function(mouseEventType, touchEventType) { - mouseEventType = mouseEventType || "click"; - touchEventType = touchEventType || "touchend"; - - var eventType = mouseEventType; - - try { - document.createEvent("TouchEvent"); - eventType = touchEventType; - } catch(e) {} - - return eventType; - }; - - /** - * 日期时间的格式化方法 - * Datetime format method - * - * @param {String} [format=""] 日期时间的格式,类似PHP的格式 - * @returns {String} datefmt 返回格式化后的日期时间字符串 - */ - - editormd.dateFormat = function(format) { - format = format || ""; - - var addZero = function(d) { - return (d < 10) ? "0" + d : d; - }; - - var date = new Date(); - var year = date.getFullYear(); - var year2 = year.toString().slice(2, 4); - var month = addZero(date.getMonth() + 1); - var day = addZero(date.getDate()); - var weekDay = date.getDay(); - var hour = addZero(date.getHours()); - var min = addZero(date.getMinutes()); - var second = addZero(date.getSeconds()); - var ms = addZero(date.getMilliseconds()); - var datefmt = ""; - - var ymd = year2 + "-" + month + "-" + day; - var fymd = year + "-" + month + "-" + day; - var hms = hour + ":" + min + ":" + second; - - switch (format) - { - case "UNIX Time" : - datefmt = date.getTime(); - break; - - case "UTC" : - datefmt = date.toUTCString(); - break; - - case "yy" : - datefmt = year2; - break; - - case "year" : - case "yyyy" : - datefmt = year; - break; - - case "month" : - case "mm" : - datefmt = month; - break; - - case "cn-week-day" : - case "cn-wd" : - var cnWeekDays = ["日", "一", "二", "三", "四", "五", "六"]; - datefmt = "星期" + cnWeekDays[weekDay]; - break; - - case "week-day" : - case "wd" : - var weekDays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; - datefmt = weekDays[weekDay]; - break; - - case "day" : - case "dd" : - datefmt = day; - break; - - case "hour" : - case "hh" : - datefmt = hour; - break; - - case "min" : - case "ii" : - datefmt = min; - break; - - case "second" : - case "ss" : - datefmt = second; - break; - - case "ms" : - datefmt = ms; - break; - - case "yy-mm-dd" : - datefmt = ymd; - break; - - case "yyyy-mm-dd" : - datefmt = fymd; - break; - - case "yyyy-mm-dd h:i:s ms" : - case "full + ms" : - datefmt = fymd + " " + hms + " " + ms; - break; - - case "full" : - case "yyyy-mm-dd h:i:s" : - default: - datefmt = fymd + " " + hms; - break; - } - - return datefmt; - }; - - return editormd; - -})); diff --git a/src/main/resources/static/editor-md/editormd.amd.min.js b/src/main/resources/static/editor-md/editormd.amd.min.js deleted file mode 100644 index 2301369..0000000 --- a/src/main/resources/static/editor-md/editormd.amd.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! Editor.md v1.5.0 | editormd.amd.min.js | Open source online markdown editor. | MIT License | By: Pandao | https://github.com/pandao/editor.md | 2015-06-09 */ -!function(e){"use strict";if("function"==typeof require&&"object"==typeof exports&&"object"==typeof module)module.exports=e;else if("function"==typeof define)if(define.amd){var t="codemirror/mode/",i="codemirror/addon/",o=["jquery","marked","prettify","katex","raphael","underscore","flowchart","jqueryflowchart","sequenceDiagram","codemirror/lib/codemirror",t+"css/css",t+"sass/sass",t+"shell/shell",t+"sql/sql",t+"clike/clike",t+"php/php",t+"xml/xml",t+"markdown/markdown",t+"javascript/javascript",t+"htmlmixed/htmlmixed",t+"gfm/gfm",t+"http/http",t+"go/go",t+"dart/dart",t+"coffeescript/coffeescript",t+"nginx/nginx",t+"python/python",t+"perl/perl",t+"lua/lua",t+"r/r",t+"ruby/ruby",t+"rst/rst",t+"smartymixed/smartymixed",t+"vb/vb",t+"vbscript/vbscript",t+"velocity/velocity",t+"xquery/xquery",t+"yaml/yaml",t+"erlang/erlang",t+"jade/jade",i+"edit/trailingspace",i+"dialog/dialog",i+"search/searchcursor",i+"search/search",i+"scroll/annotatescrollbar",i+"search/matchesonscrollbar",i+"display/placeholder",i+"edit/closetag",i+"fold/foldcode",i+"fold/foldgutter",i+"fold/indent-fold",i+"fold/brace-fold",i+"fold/xml-fold",i+"fold/markdown-fold",i+"fold/comment-fold",i+"mode/overlay",i+"selection/active-line",i+"edit/closebrackets",i+"display/fullscreen",i+"search/match-highlighter"];define(o,e)}else define(["jquery"],e);else window.editormd=e()}(function(){"function"==typeof define&&define.amd&&(e=arguments[0],marked=arguments[1],prettify=arguments[2],katex=arguments[3],Raphael=arguments[4],_=arguments[5],flowchart=arguments[6],CodeMirror=arguments[9]);var e="undefined"!=typeof jQuery?jQuery:Zepto;if("undefined"!=typeof e){var t=function(e,i){return new t.fn.init(e,i)};t.title=t.$name="Editor.md",t.version="1.5.0",t.homePage="https://pandao.github.io/editor.md/",t.classPrefix="editormd-",t.toolbarModes={full:["undo","redo","|","bold","del","italic","quote","ucwords","uppercase","lowercase","|","h1","h2","h3","h4","h5","h6","|","list-ul","list-ol","hr","|","link","reference-link","image","code","preformatted-text","code-block","table","datetime","emoji","html-entities","pagebreak","|","goto-line","watch","preview","fullscreen","clear","search","|","help","info"],simple:["undo","redo","|","bold","del","italic","quote","uppercase","lowercase","|","h1","h2","h3","h4","h5","h6","|","list-ul","list-ol","hr","|","watch","preview","fullscreen","|","help","info"],mini:["undo","redo","|","watch","preview","|","help","info"]},t.defaults={mode:"gfm",name:"",value:"",theme:"",editorTheme:"default",previewTheme:"",markdown:"",appendMarkdown:"",width:"100%",height:"100%",path:"./lib/",pluginPath:"",delay:300,autoLoadModules:!0,watch:!0,placeholder:"Enjoy Markdown! coding now...",gotoLine:!0,codeFold:!1,autoHeight:!1,autoFocus:!0,autoCloseTags:!0,searchReplace:!0,syncScrolling:!0,readOnly:!1,tabSize:4,indentUnit:4,lineNumbers:!0,lineWrapping:!0,autoCloseBrackets:!0,showTrailingSpace:!0,matchBrackets:!0,indentWithTabs:!0,styleSelectedText:!0,matchWordHighlight:!0,styleActiveLine:!0,dialogLockScreen:!0,dialogShowMask:!0,dialogDraggable:!0,dialogMaskBgColor:"#fff",dialogMaskOpacity:.1,fontSize:"13px",saveHTMLToTextarea:!1,disabledKeyMaps:[],onload:function(){},onresize:function(){},onchange:function(){},onwatch:null,onunwatch:null,onpreviewing:function(){},onpreviewed:function(){},onfullscreen:function(){},onfullscreenExit:function(){},onscroll:function(){},onpreviewscroll:function(){},imageUpload:!1,imageFormats:["jpg","jpeg","gif","png","bmp","webp"],imageUploadURL:"",crossDomainUpload:!1,uploadCallbackURL:"",toc:!0,tocm:!1,tocTitle:"",tocDropdown:!1,tocContainer:"",tocStartLevel:1,htmlDecode:!1,pageBreak:!0,atLink:!0,emailLink:!0,taskList:!1,emoji:!1,tex:!1,flowChart:!1,sequenceDiagram:!1,previewCodeHighlight:!0,toolbar:!0,toolbarAutoFixed:!0,toolbarIcons:"full",toolbarTitles:{},toolbarHandlers:{ucwords:function(){return t.toolbarHandlers.ucwords},lowercase:function(){return t.toolbarHandlers.lowercase}},toolbarCustomIcons:{lowercase:'a',ucwords:'Aa'},toolbarIconsClass:{undo:"fa-undo",redo:"fa-repeat",bold:"fa-bold",del:"fa-strikethrough",italic:"fa-italic",quote:"fa-quote-left",uppercase:"fa-font",h1:t.classPrefix+"bold",h2:t.classPrefix+"bold",h3:t.classPrefix+"bold",h4:t.classPrefix+"bold",h5:t.classPrefix+"bold",h6:t.classPrefix+"bold","list-ul":"fa-list-ul","list-ol":"fa-list-ol",hr:"fa-minus",link:"fa-link","reference-link":"fa-anchor",image:"fa-picture-o",code:"fa-code","preformatted-text":"fa-file-code-o","code-block":"fa-file-code-o",table:"fa-table",datetime:"fa-clock-o",emoji:"fa-smile-o","html-entities":"fa-copyright",pagebreak:"fa-newspaper-o","goto-line":"fa-terminal",watch:"fa-eye-slash",unwatch:"fa-eye",preview:"fa-desktop",search:"fa-search",fullscreen:"fa-arrows-alt",clear:"fa-eraser",help:"fa-question-circle",info:"fa-info-circle"},toolbarIconTexts:{},lang:{name:"zh-cn",description:"开源在线Markdown编辑器
        Open source online Markdown editor.",tocTitle:"目录",toolbar:{undo:"撤销(Ctrl+Z)",redo:"重做(Ctrl+Y)",bold:"粗体",del:"删除线",italic:"斜体",quote:"引用",ucwords:"将每个单词首字母转成大写",uppercase:"将所选转换成大写",lowercase:"将所选转换成小写",h1:"标题1",h2:"标题2",h3:"标题3",h4:"标题4",h5:"标题5",h6:"标题6","list-ul":"无序列表","list-ol":"有序列表",hr:"横线",link:"链接","reference-link":"引用链接",image:"添加图片",code:"行内代码","preformatted-text":"预格式文本 / 代码块(缩进风格)","code-block":"代码块(多语言风格)",table:"添加表格",datetime:"日期时间",emoji:"Emoji表情","html-entities":"HTML实体字符",pagebreak:"插入分页符","goto-line":"跳转到行",watch:"关闭实时预览",unwatch:"开启实时预览",preview:"全窗口预览HTML(按 Shift + ESC还原)",fullscreen:"全屏(按ESC还原)",clear:"清空",search:"搜索",help:"使用帮助",info:"关于"+t.title},buttons:{enter:"确定",cancel:"取消",close:"关闭"},dialog:{link:{title:"添加链接",url:"链接地址",urlTitle:"链接标题",urlEmpty:"错误:请填写链接地址。"},referenceLink:{title:"添加引用链接",name:"引用名称",url:"链接地址",urlId:"链接ID",urlTitle:"链接标题",nameEmpty:"错误:引用链接的名称不能为空。",idEmpty:"错误:请填写引用链接的ID。",urlEmpty:"错误:请填写引用链接的URL地址。"},image:{title:"添加图片",url:"图片地址",link:"图片链接",alt:"图片描述",uploadButton:"本地上传",imageURLEmpty:"错误:图片地址不能为空。",uploadFileEmpty:"错误:上传的图片不能为空。",formatNotAllowed:"错误:只允许上传图片文件,允许上传的图片文件格式有:"},preformattedText:{title:"添加预格式文本或代码块",emptyAlert:"错误:请填写预格式文本或代码的内容。"},codeBlock:{title:"添加代码块",selectLabel:"代码语言:",selectDefaultText:"请选择代码语言",otherLanguage:"其他语言",unselectedLanguageAlert:"错误:请选择代码所属的语言类型。",codeEmptyAlert:"错误:请填写代码内容。"},htmlEntities:{title:"HTML 实体字符"},help:{title:"使用帮助"}}}},t.classNames={tex:t.classPrefix+"tex"},t.dialogZindex=99999,t.$katex=null,t.$marked=null,t.$CodeMirror=null,t.$prettyPrint=null;var i,o;t.prototype=t.fn={state:{watching:!1,loaded:!1,preview:!1,fullscreen:!1},init:function(i,o){o=o||{},"object"==typeof i&&(o=i);var r=this.classPrefix=t.classPrefix,n=this.settings=e.extend(!0,t.defaults,o);i="object"==typeof i?n.id:i;var a=this.editor=e("#"+i);this.id=i,this.lang=n.lang;var s=this.classNames={textarea:{html:r+"html-textarea",markdown:r+"markdown-textarea"}};n.pluginPath=""===n.pluginPath?n.path+"../plugins/":n.pluginPath,this.state.watching=n.watch?!0:!1,a.hasClass("editormd")||a.addClass("editormd"),a.css({width:"number"==typeof n.width?n.width+"px":n.width,height:"number"==typeof n.height?n.height+"px":n.height}),n.autoHeight&&a.css("height","auto");var l=this.markdownTextarea=a.children("textarea");l.length<1&&(a.append(""),l=this.markdownTextarea=a.children("textarea")),l.addClass(s.textarea.markdown).attr("placeholder",n.placeholder),("undefined"==typeof l.attr("name")||""===l.attr("name"))&&l.attr("name",""!==n.name?n.name:i+"-markdown-doc");var c=[n.readOnly?"":'',n.saveHTMLToTextarea?'':"",'
        ','
        ','
        '].join("\n");return a.append(c).addClass(r+"vertical"),""!==n.theme&&a.addClass(r+"theme-"+n.theme),this.mask=a.children("."+r+"mask"),this.containerMask=a.children("."+r+"container-mask"),""!==n.markdown&&l.val(n.markdown),""!==n.appendMarkdown&&l.val(l.val()+n.appendMarkdown),this.htmlTextarea=a.children("."+s.textarea.html),this.preview=a.children("."+r+"preview"),this.previewContainer=this.preview.children("."+r+"preview-container"),""!==n.previewTheme&&this.preview.addClass(r+"preview-theme-"+n.previewTheme),"function"==typeof define&&define.amd&&("undefined"!=typeof katex&&(t.$katex=katex),n.searchReplace&&!n.readOnly&&(t.loadCSS(n.path+"codemirror/addon/dialog/dialog"),t.loadCSS(n.path+"codemirror/addon/search/matchesonscrollbar"))),"function"==typeof define&&define.amd||!n.autoLoadModules?("undefined"!=typeof CodeMirror&&(t.$CodeMirror=CodeMirror),"undefined"!=typeof marked&&(t.$marked=marked),this.setCodeMirror().setToolbar().loadedDisplay()):this.loadQueues(),this},loadQueues:function(){var e=this,i=this.settings,o=i.path,r=function(){return t.isIE8?void e.loadedDisplay():void(i.flowChart||i.sequenceDiagram?t.loadScript(o+"raphael.min",function(){t.loadScript(o+"underscore.min",function(){!i.flowChart&&i.sequenceDiagram?t.loadScript(o+"sequence-diagram.min",function(){e.loadedDisplay()}):i.flowChart&&!i.sequenceDiagram?t.loadScript(o+"flowchart.min",function(){t.loadScript(o+"jquery.flowchart.min",function(){e.loadedDisplay()})}):i.flowChart&&i.sequenceDiagram&&t.loadScript(o+"flowchart.min",function(){t.loadScript(o+"jquery.flowchart.min",function(){t.loadScript(o+"sequence-diagram.min",function(){e.loadedDisplay()})})})})}):e.loadedDisplay())};return t.loadCSS(o+"codemirror/codemirror.min"),i.searchReplace&&!i.readOnly&&(t.loadCSS(o+"codemirror/addon/dialog/dialog"),t.loadCSS(o+"codemirror/addon/search/matchesonscrollbar")),i.codeFold&&t.loadCSS(o+"codemirror/addon/fold/foldgutter"),t.loadScript(o+"codemirror/codemirror.min",function(){t.$CodeMirror=CodeMirror,t.loadScript(o+"codemirror/modes.min",function(){t.loadScript(o+"codemirror/addons.min",function(){return e.setCodeMirror(),"gfm"!==i.mode&&"markdown"!==i.mode?(e.loadedDisplay(),!1):(e.setToolbar(),void t.loadScript(o+"marked.min",function(){t.$marked=marked,i.previewCodeHighlight?t.loadScript(o+"prettify.min",function(){r()}):r()}))})})}),this},setTheme:function(e){var t=this.editor,i=this.settings.theme,o=this.classPrefix+"theme-";return t.removeClass(o+i).addClass(o+e),this.settings.theme=e,this},setEditorTheme:function(e){var i=this.settings;return i.editorTheme=e,"default"!==e&&t.loadCSS(i.path+"codemirror/theme/"+i.editorTheme),this.cm.setOption("theme",e),this},setCodeMirrorTheme:function(e){return this.setEditorTheme(e),this},setPreviewTheme:function(e){var t=this.preview,i=this.settings.previewTheme,o=this.classPrefix+"preview-theme-";return t.removeClass(o+i).addClass(o+e),this.settings.previewTheme=e,this},setCodeMirror:function(){var e=this.settings,i=this.editor;"default"!==e.editorTheme&&t.loadCSS(e.path+"codemirror/theme/"+e.editorTheme);var o={mode:e.mode,theme:e.editorTheme,tabSize:e.tabSize,dragDrop:!1,autofocus:e.autoFocus,autoCloseTags:e.autoCloseTags,readOnly:e.readOnly?"nocursor":!1,indentUnit:e.indentUnit,lineNumbers:e.lineNumbers,lineWrapping:e.lineWrapping,extraKeys:{"Ctrl-Q":function(e){e.foldCode(e.getCursor())}},foldGutter:e.codeFold,gutters:["CodeMirror-linenumbers","CodeMirror-foldgutter"],matchBrackets:e.matchBrackets,indentWithTabs:e.indentWithTabs,styleActiveLine:e.styleActiveLine,styleSelectedText:e.styleSelectedText,autoCloseBrackets:e.autoCloseBrackets,showTrailingSpace:e.showTrailingSpace,highlightSelectionMatches:e.matchWordHighlight?{showToken:"onselected"===e.matchWordHighlight?!1:/\w/}:!1};return this.codeEditor=this.cm=t.$CodeMirror.fromTextArea(this.markdownTextarea[0],o),this.codeMirror=this.cmElement=i.children(".CodeMirror"),""!==e.value&&this.cm.setValue(e.value),this.codeMirror.css({fontSize:e.fontSize,width:e.watch?"50%":"100%"}),e.autoHeight&&(this.codeMirror.css("height","auto"),this.cm.setOption("viewportMargin",1/0)),e.lineNumbers||this.codeMirror.find(".CodeMirror-gutters").css("border-right","none"),this},getCodeMirrorOption:function(e){return this.cm.getOption(e)},setCodeMirrorOption:function(e,t){return this.cm.setOption(e,t),this},addKeyMap:function(e,t){return this.cm.addKeyMap(e,t),this},removeKeyMap:function(e){return this.cm.removeKeyMap(e),this},gotoLine:function(t){var i=this.settings;if(!i.gotoLine)return this;var o=this.cm,r=(this.editor,o.lineCount()),n=this.preview;if("string"==typeof t&&("last"===t&&(t=r),"first"===t&&(t=1)),"number"!=typeof t)return alert("Error: The line number must be an integer."),this;if(t=parseInt(t)-1,t>r)return alert("Error: The line number range 1-"+r),this;o.setCursor({line:t,ch:0});var a=o.getScrollInfo(),s=a.clientHeight,l=o.charCoords({line:t,ch:0},"local");if(o.scrollTo(null,(l.top+l.bottom-s)/2),i.watch){var c=this.codeMirror.find(".CodeMirror-scroll")[0],h=e(c).height(),d=c.scrollTop,u=d/c.scrollHeight;n.scrollTop(0===d?0:d+h>=c.scrollHeight-16?n[0].scrollHeight:n[0].scrollHeight*u)}return o.focus(),this},extend:function(){return"undefined"!=typeof arguments[1]&&("function"==typeof arguments[1]&&(arguments[1]=e.proxy(arguments[1],this)),this[arguments[0]]=arguments[1]),"object"==typeof arguments[0]&&"undefined"==typeof arguments[0].length&&e.extend(!0,this,arguments[0]),this},set:function(t,i){return"undefined"!=typeof i&&"function"==typeof i&&(i=e.proxy(i,this)),this[t]=i,this},config:function(t,i){var o=this.settings;return"object"==typeof t&&(o=e.extend(!0,o,t)),"string"==typeof t&&(o[t]=i),this.settings=o,this.recreate(),this},on:function(t,i){var o=this.settings;return"undefined"!=typeof o["on"+t]&&(o["on"+t]=e.proxy(i,this)),this},off:function(e){var t=this.settings;return"undefined"!=typeof t["on"+e]&&(t["on"+e]=function(){}),this},showToolbar:function(t){var i=this.settings;return i.readOnly?this:(i.toolbar&&(this.toolbar.length<1||""===this.toolbar.find("."+this.classPrefix+"menu").html())&&this.setToolbar(),i.toolbar=!0,this.toolbar.show(),this.resize(),e.proxy(t||function(){},this)(),this)},hideToolbar:function(t){var i=this.settings;return i.toolbar=!1,this.toolbar.hide(),this.resize(),e.proxy(t||function(){},this)(),this},setToolbarAutoFixed:function(t){var i=this.state,o=this.editor,r=this.toolbar,n=this.settings;"undefined"!=typeof t&&(n.toolbarAutoFixed=t);var a=function(){var t=e(window),i=t.scrollTop();return n.toolbarAutoFixed?void r.css(i-o.offset().top>10&&i
          ';i.append(n),r=this.toolbar=i.children("."+o+"toolbar")}if(!e.toolbar)return r.hide(),this;r.show();for(var a="function"==typeof e.toolbarIcons?e.toolbarIcons():"string"==typeof e.toolbarIcons?t.toolbarModes[e.toolbarIcons]:e.toolbarIcons,s=r.find("."+this.classPrefix+"menu"),l="",c=!1,h=0,d=a.length;d>h;h++){var u=a[h];if("||"===u)c=!0;else if("|"===u)l+='
        • |
        • ';else{var f=/h(\d)/.test(u),g=u;"watch"!==u||e.watch||(g="unwatch");var p=e.lang.toolbar[g],m=e.toolbarIconTexts[g],w=e.toolbarIconsClass[g];p="undefined"==typeof p?"":p,m="undefined"==typeof m?"":m,w="undefined"==typeof w?"":w;var v=c?'
        • ':"
        • ";"undefined"!=typeof e.toolbarCustomIcons[u]&&"function"!=typeof e.toolbarCustomIcons[u]?v+=e.toolbarCustomIcons[u]:(v+='',v+=''+(f?u.toUpperCase():""===w?m:"")+"",v+=""),v+="
        • ",l=c?v+l:l+v}}return s.html(l),s.find('[title="Lowercase"]').attr("title",e.lang.toolbar.lowercase),s.find('[title="ucwords"]').attr("title",e.lang.toolbar.ucwords),this.setToolbarHandler(),this.setToolbarAutoFixed(),this},dialogLockScreen:function(){return e.proxy(t.dialogLockScreen,this)(),this},dialogShowMask:function(i){return e.proxy(t.dialogShowMask,this)(i),this},getToolbarHandles:function(e){var i=this.toolbarHandlers=t.toolbarHandlers;return e&&"undefined"!=typeof toolbarIconHandlers[e]?i[e]:i},setToolbarHandler:function(){var i=this,o=this.settings;if(!o.toolbar||o.readOnly)return this;var r=this.toolbar,n=this.cm,a=this.classPrefix,s=this.toolbarIcons=r.find("."+a+"menu > li > a"),l=this.getToolbarHandles();return s.bind(t.mouseOrTouch("click","touchend"),function(t){var r=e(this).children(".fa"),a=r.attr("name"),s=n.getCursor(),c=n.getSelection();return""!==a?(i.activeIcon=r,"undefined"!=typeof l[a]?e.proxy(l[a],i)(n):"undefined"!=typeof o.toolbarHandlers[a]&&e.proxy(o.toolbarHandlers[a],i)(n,r,s,c),"link"!==a&&"reference-link"!==a&&"image"!==a&&"code-block"!==a&&"preformatted-text"!==a&&"watch"!==a&&"preview"!==a&&"search"!==a&&"fullscreen"!==a&&"info"!==a&&n.focus(),!1):void 0}),this},createDialog:function(i){return e.proxy(t.createDialog,this)(i)},createInfoDialog:function(){var e=this,i=this.editor,o=this.classPrefix,r=['
          ','
          ','

          '+t.title+"v"+t.version+"

          ","

          "+this.lang.description+"

          ",'

          '+t.homePage+'

          ','

          Copyright © 2015 Pandao, The MIT License.

          ',"
          ",'',"
          "].join("\n");i.append(r);var n=this.infoDialog=i.children("."+o+"dialog-info");return n.find("."+o+"dialog-close").bind(t.mouseOrTouch("click","touchend"),function(){e.hideInfoDialog()}),n.css("border",t.isIE8?"1px solid #ddd":"").css("z-index",t.dialogZindex).show(),this.infoDialogPosition(),this},infoDialogPosition:function(){var t=this.infoDialog,i=function(){t.css({top:(e(window).height()-t.height())/2+"px",left:(e(window).width()-t.width())/2+"px"})};return i(),e(window).resize(i),this},showInfoDialog:function(){e("html,body").css("overflow-x","hidden");var i=this.editor,o=this.settings,r=this.infoDialog=i.children("."+this.classPrefix+"dialog-info");return r.length<1&&this.createInfoDialog(),this.lockScreen(!0),this.mask.css({opacity:o.dialogMaskOpacity,backgroundColor:o.dialogMaskBgColor}).show(),r.css("z-index",t.dialogZindex).show(),this.infoDialogPosition(),this},hideInfoDialog:function(){return e("html,body").css("overflow-x",""),this.infoDialog.hide(),this.mask.hide(),this.lockScreen(!1),this},lockScreen:function(e){return t.lockScreen(e),this.resize(),this},recreate:function(){var e=this.editor,t=this.settings;return this.codeMirror.remove(),this.setCodeMirror(),t.readOnly||(e.find(".editormd-dialog").length>0&&e.find(".editormd-dialog").remove(),t.toolbar&&(this.getToolbarHandles(),this.setToolbar())),this.loadedDisplay(!0),this},previewCodeHighlight:function(){var e=this.settings,t=this.previewContainer;return e.previewCodeHighlight&&(t.find("pre").addClass("prettyprint linenums"),"undefined"!=typeof prettyPrint&&prettyPrint()),this},katexRender:function(){return null===i?this:(this.previewContainer.find("."+t.classNames.tex).each(function(){var i=e(this);t.$katex.render(i.text(),i[0]),i.find(".katex").css("font-size","1.6em")}),this)},flowChartAndSequenceDiagramRender:function(){var i=this,r=this.settings,n=this.previewContainer;if(t.isIE8)return this;if(r.flowChart){if(null===o)return this;n.find(".flowchart").flowChart()}r.sequenceDiagram&&n.find(".sequence-diagram").sequenceDiagram({theme:"simple"});var a=i.preview,s=i.codeMirror,l=s.find(".CodeMirror-scroll"),c=l.height(),h=l.scrollTop(),d=h/l[0].scrollHeight,u=0;a.find(".markdown-toc-list").each(function(){u+=e(this).height()});var f=a.find(".editormd-toc-menu").height();return f=f?f:0,a.scrollTop(0===h?0:h+c>=l[0].scrollHeight-16?a[0].scrollHeight:(a[0].scrollHeight+u+f)*d),this},registerKeyMaps:function(i){var o=this,r=this.cm,n=this.settings,a=t.toolbarHandlers,s=n.disabledKeyMaps;if(i=i||null){for(var l in i)if(e.inArray(l,s)<0){var c={};c[l]=i[l],r.addKeyMap(i)}}else{for(var h in t.keyMaps){var d=t.keyMaps[h],u="string"==typeof d?e.proxy(a[d],o):e.proxy(d,o);if(e.inArray(h,["F9","F10","F11"])<0&&e.inArray(h,s)<0){var f={};f[h]=u,r.addKeyMap(f)}}e(window).keydown(function(t){var i={120:"F9",121:"F10",122:"F11"};if(e.inArray(i[t.keyCode],s)<0)switch(t.keyCode){case 120:return e.proxy(a.watch,o)(),!1;case 121:return e.proxy(a.preview,o)(),!1;case 122:return e.proxy(a.fullscreen,o)(),!1}})}return this},bindScrollEvent:function(){var i=this,o=this.preview,r=this.settings,n=this.codeMirror,a=t.mouseOrTouch;if(!r.syncScrolling)return this;var s=function(){n.find(".CodeMirror-scroll").bind(a("scroll","touchmove"),function(t){var n=e(this).height(),a=e(this).scrollTop(),s=a/e(this)[0].scrollHeight,l=0;o.find(".markdown-toc-list").each(function(){l+=e(this).height()});var c=o.find(".editormd-toc-menu").height();c=c?c:0,o.scrollTop(0===a?0:a+n>=e(this)[0].scrollHeight-16?o[0].scrollHeight:(o[0].scrollHeight+l+c)*s),e.proxy(r.onscroll,i)(t)})},l=function(){n.find(".CodeMirror-scroll").unbind(a("scroll","touchmove"))},c=function(){o.bind(a("scroll","touchmove"),function(t){var o=e(this).height(),a=e(this).scrollTop(),s=a/e(this)[0].scrollHeight,l=n.find(".CodeMirror-scroll");l.scrollTop(0===a?0:a+o>=e(this)[0].scrollHeight?l[0].scrollHeight:l[0].scrollHeight*s),e.proxy(r.onpreviewscroll,i)(t)})},h=function(){o.unbind(a("scroll","touchmove"))};return n.bind({mouseover:s,mouseout:l,touchstart:s,touchend:l}),"single"===r.syncScrolling?this:(o.bind({mouseover:c,mouseout:h,touchstart:c,touchend:h}),this)},bindChangeEvent:function(){var e=this,t=this.cm,o=this.settings;return o.syncScrolling?(t.on("change",function(t,r){o.watch&&e.previewContainer.css("padding",o.autoHeight?"20px 20px 50px 40px":"20px"),i=setTimeout(function(){clearTimeout(i),e.save(),i=null},o.delay)}),this):this},loadedDisplay:function(t){t=t||!1;var i=this,o=this.editor,r=this.preview,n=this.settings;return this.containerMask.hide(),this.save(),n.watch&&r.show(),o.data("oldWidth",o.width()).data("oldHeight",o.height()),this.resize(),this.registerKeyMaps(),e(window).resize(function(){i.resize()}),this.bindScrollEvent().bindChangeEvent(),t||e.proxy(n.onload,this)(),this.state.loaded=!0,this},width:function(e){return this.editor.css("width","number"==typeof e?e+"px":e),this.resize(),this},height:function(e){return this.editor.css("height","number"==typeof e?e+"px":e),this.resize(),this},resize:function(t,i){t=t||null,i=i||null;var o=this.state,r=this.editor,n=this.preview,a=this.toolbar,s=this.settings,l=this.codeMirror;if(t&&r.css("width","number"==typeof t?t+"px":t),!s.autoHeight||o.fullscreen||o.preview?(i&&r.css("height","number"==typeof i?i+"px":i),o.fullscreen&&r.height(e(window).height()),s.toolbar&&!s.readOnly?l.css("margin-top",a.height()+1).height(r.height()-a.height()):l.css("margin-top",0).height(r.height())):(r.css("height","auto"),l.css("height","auto")),s.watch)if(l.width(r.width()/2),n.width(o.preview?r.width():r.width()/2),this.previewContainer.css("padding",s.autoHeight?"20px 20px 50px 40px":"20px"),s.toolbar&&!s.readOnly?n.css("top",a.height()+1):n.css("top",0),!s.autoHeight||o.fullscreen||o.preview){var c=s.toolbar&&!s.readOnly?r.height()-a.height():r.height();n.height(c)}else n.height("");else l.width(r.width()),n.hide();return o.loaded&&e.proxy(s.onresize,this)(),this},save:function(){if(null===i)return this;var r=this,n=this.state,a=this.settings,s=this.cm,l=s.getValue(),c=this.previewContainer;if("gfm"!==a.mode&&"markdown"!==a.mode)return this.markdownTextarea.val(l),this;var h=t.$marked,d=this.markdownToC=[],u=this.markedRendererOptions={toc:a.toc,tocm:a.tocm,tocStartLevel:a.tocStartLevel,pageBreak:a.pageBreak,taskList:a.taskList,emoji:a.emoji,tex:a.tex,atLink:a.atLink,emailLink:a.emailLink,flowChart:a.flowChart,sequenceDiagram:a.sequenceDiagram,previewCodeHighlight:a.previewCodeHighlight},f=this.markedOptions={renderer:t.markedRenderer(d,u),gfm:!0,tables:!0,breaks:!0,pedantic:!1,sanitize:a.htmlDecode?!1:!0,smartLists:!0,smartypants:!0};h.setOptions(f);var g=t.$marked(l,f);if(g=t.filterHTMLTags(g,a.htmlDecode),this.markdownTextarea.text(l),s.save(),a.saveHTMLToTextarea&&this.htmlTextarea.text(g),a.watch||!a.watch&&n.preview){if(c.html(g),this.previewCodeHighlight(),a.toc){var p=""===a.tocContainer?c:e(a.tocContainer),m=p.find("."+this.classPrefix+"toc-menu");p.attr("previewContainer",""===a.tocContainer?"true":"false"),""!==a.tocContainer&&m.length>0&&m.remove(),t.markdownToCRenderer(d,p,a.tocDropdown,a.tocStartLevel),(a.tocDropdown||p.find("."+this.classPrefix+"toc-menu").length>0)&&t.tocDropdownMenu(p,""!==a.tocTitle?a.tocTitle:this.lang.tocTitle),""!==a.tocContainer&&c.find(".markdown-toc").css("border","none")}a.tex&&(!t.kaTeXLoaded&&a.autoLoadModules?t.loadKaTeX(function(){t.$katex=katex,t.kaTeXLoaded=!0,r.katexRender()}):(t.$katex=katex,this.katexRender())),(a.flowChart||a.sequenceDiagram)&&(o=setTimeout(function(){clearTimeout(o),r.flowChartAndSequenceDiagramRender(),o=null},10)),n.loaded&&e.proxy(a.onchange,this)()}return this},focus:function(){return this.cm.focus(),this},setCursor:function(e){return this.cm.setCursor(e),this},getCursor:function(){return this.cm.getCursor()},setSelection:function(e,t){return this.cm.setSelection(e,t),this},getSelection:function(){return this.cm.getSelection()},setSelections:function(e){return this.cm.setSelections(e),this},getSelections:function(){return this.cm.getSelections()},replaceSelection:function(e){return this.cm.replaceSelection(e),this},insertValue:function(e){return this.replaceSelection(e),this},appendMarkdown:function(e){var t=(this.settings,this.cm);return t.setValue(t.getValue()+e),this},setMarkdown:function(e){return this.cm.setValue(e||this.settings.markdown),this},getMarkdown:function(){return this.cm.getValue()},getValue:function(){return this.cm.getValue()},setValue:function(e){return this.cm.setValue(e),this},clear:function(){return this.cm.setValue(""),this},getHTML:function(){return this.settings.saveHTMLToTextarea?this.htmlTextarea.val():(alert("Error: settings.saveHTMLToTextarea == false"),!1)},getTextareaSavedHTML:function(){return this.getHTML()},getPreviewedHTML:function(){return this.settings.watch?this.previewContainer.html():(alert("Error: settings.watch == false"),!1)},watch:function(t){var o=this.settings;if(e.inArray(o.mode,["gfm","markdown"])<0)return this;if(this.state.watching=o.watch=!0,this.preview.show(),this.toolbar){var r=o.toolbarIconsClass.watch,n=o.toolbarIconsClass.unwatch,a=this.toolbar.find(".fa[name=watch]");a.parent().attr("title",o.lang.toolbar.watch),a.removeClass(n).addClass(r)}return this.codeMirror.css("border-right","1px solid #ddd").width(this.editor.width()/2),i=0,this.save().resize(),o.onwatch||(o.onwatch=t||function(){}),e.proxy(o.onwatch,this)(),this},unwatch:function(t){var i=this.settings;if(this.state.watching=i.watch=!1,this.preview.hide(),this.toolbar){var o=i.toolbarIconsClass.watch,r=i.toolbarIconsClass.unwatch,n=this.toolbar.find(".fa[name=watch]");n.parent().attr("title",i.lang.toolbar.unwatch),n.removeClass(o).addClass(r)}return this.codeMirror.css("border-right","none").width(this.editor.width()),this.resize(),i.onunwatch||(i.onunwatch=t||function(){}),e.proxy(i.onunwatch,this)(),this},show:function(t){t=t||function(){};var i=this;return this.editor.show(0,function(){e.proxy(t,i)()}),this},hide:function(t){t=t||function(){};var i=this;return this.editor.hide(0,function(){e.proxy(t,i)()}),this},previewing:function(){var i=this,o=this.editor,r=this.preview,n=this.toolbar,a=this.settings,s=this.codeMirror,l=this.previewContainer;if(e.inArray(a.mode,["gfm","markdown"])<0)return this;a.toolbar&&n&&(n.toggle(),n.find(".fa[name=preview]").toggleClass("active")),s.toggle();var c=function(e){e.shiftKey&&27===e.keyCode&&i.previewed()};"none"===s.css("display")?(this.state.preview=!0,this.state.fullscreen&&r.css("background","#fff"),o.find("."+this.classPrefix+"preview-close-btn").show().bind(t.mouseOrTouch("click","touchend"),function(){i.previewed()}),a.watch?l.css("padding",""):this.save(),l.addClass(this.classPrefix+"preview-active"),r.show().css({position:"",top:0,width:o.width(),height:a.autoHeight&&!this.state.fullscreen?"auto":o.height()}),this.state.loaded&&e.proxy(a.onpreviewing,this)(),e(window).bind("keyup",c)):(e(window).unbind("keyup",c),this.previewed())},previewed:function(){var i=this.editor,o=this.preview,r=this.toolbar,n=this.settings,a=this.previewContainer,s=i.find("."+this.classPrefix+"preview-close-btn");return this.state.preview=!1,this.codeMirror.show(),n.toolbar&&r.show(),o[n.watch?"show":"hide"](),s.hide().unbind(t.mouseOrTouch("click","touchend")),a.removeClass(this.classPrefix+"preview-active"),n.watch&&a.css("padding","20px"),o.css({background:null,position:"absolute",width:i.width()/2,height:n.autoHeight&&!this.state.fullscreen?"auto":i.height()-r.height(),top:n.toolbar?r.height():0}),this.state.loaded&&e.proxy(n.onpreviewed,this)(),this},fullscreen:function(){var t=this,i=this.state,o=this.editor,r=(this.preview,this.toolbar),n=this.settings,a=this.classPrefix+"fullscreen";r&&r.find(".fa[name=fullscreen]").parent().toggleClass("active");var s=function(e){e.shiftKey||27!==e.keyCode||i.fullscreen&&t.fullscreenExit()};return o.hasClass(a)?(e(window).unbind("keyup",s),this.fullscreenExit()):(i.fullscreen=!0,e("html,body").css("overflow","hidden"),o.css({width:e(window).width(),height:e(window).height()}).addClass(a),this.resize(),e.proxy(n.onfullscreen,this)(),e(window).bind("keyup",s)),this},fullscreenExit:function(){var t=this.editor,i=this.settings,o=this.toolbar,r=this.classPrefix+"fullscreen";return this.state.fullscreen=!1,o&&o.find(".fa[name=fullscreen]").parent().removeClass("active"),e("html,body").css("overflow",""),t.css({width:t.data("oldWidth"),height:t.data("oldHeight")}).removeClass(r),this.resize(),e.proxy(i.onfullscreenExit,this)(),this},executePlugin:function(i,o){var r=this,n=this.cm,a=this.settings;return o=a.pluginPath+o,"function"==typeof define?"undefined"==typeof this[i]?(alert("Error: "+i+" plugin is not found, you are not load this plugin."),this):(this[i](n),this):(e.inArray(o,t.loadFiles.plugin)<0?t.loadPlugin(o,function(){t.loadPlugins[i]=r[i],r[i](n)}):e.proxy(t.loadPlugins[i],this)(n),this)},search:function(e){var t=this.settings;return t.searchReplace?(t.readOnly||this.cm.execCommand(e||"find"),this):(alert("Error: settings.searchReplace == false"),this)},searchReplace:function(){return this.search("replace"),this},searchReplaceAll:function(){return this.search("replaceAll"),this}},t.fn.init.prototype=t.fn,t.dialogLockScreen=function(){var t=this.settings||{dialogLockScreen:!0};t.dialogLockScreen&&(e("html,body").css("overflow","hidden"),this.resize())},t.dialogShowMask=function(t){var i=this.editor,o=this.settings||{dialogShowMask:!0};t.css({top:(e(window).height()-t.height())/2+"px",left:(e(window).width()-t.width())/2+"px"}),o.dialogShowMask&&i.children("."+this.classPrefix+"mask").css("z-index",parseInt(t.css("z-index"))-1).show()},t.toolbarHandlers={undo:function(){this.cm.undo()},redo:function(){this.cm.redo()},bold:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection(); - -e.replaceSelection("**"+i+"**"),""===i&&e.setCursor(t.line,t.ch+2)},del:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("~~"+i+"~~"),""===i&&e.setCursor(t.line,t.ch+2)},italic:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("*"+i+"*"),""===i&&e.setCursor(t.line,t.ch+1)},quote:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();0!==t.ch?(e.setCursor(t.line,0),e.replaceSelection("> "+i),e.setCursor(t.line,t.ch+2)):e.replaceSelection("> "+i)},ucfirst:function(){var e=this.cm,i=e.getSelection(),o=e.listSelections();e.replaceSelection(t.firstUpperCase(i)),e.setSelections(o)},ucwords:function(){var e=this.cm,i=e.getSelection(),o=e.listSelections();e.replaceSelection(t.wordsFirstUpperCase(i)),e.setSelections(o)},uppercase:function(){var e=this.cm,t=e.getSelection(),i=e.listSelections();e.replaceSelection(t.toUpperCase()),e.setSelections(i)},lowercase:function(){var e=this.cm,t=(e.getCursor(),e.getSelection()),i=e.listSelections();e.replaceSelection(t.toLowerCase()),e.setSelections(i)},h1:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();0!==t.ch?(e.setCursor(t.line,0),e.replaceSelection("# "+i),e.setCursor(t.line,t.ch+2)):e.replaceSelection("# "+i)},h2:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();0!==t.ch?(e.setCursor(t.line,0),e.replaceSelection("## "+i),e.setCursor(t.line,t.ch+3)):e.replaceSelection("## "+i)},h3:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();0!==t.ch?(e.setCursor(t.line,0),e.replaceSelection("### "+i),e.setCursor(t.line,t.ch+4)):e.replaceSelection("### "+i)},h4:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();0!==t.ch?(e.setCursor(t.line,0),e.replaceSelection("#### "+i),e.setCursor(t.line,t.ch+5)):e.replaceSelection("#### "+i)},h5:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();0!==t.ch?(e.setCursor(t.line,0),e.replaceSelection("##### "+i),e.setCursor(t.line,t.ch+6)):e.replaceSelection("##### "+i)},h6:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();0!==t.ch?(e.setCursor(t.line,0),e.replaceSelection("###### "+i),e.setCursor(t.line,t.ch+7)):e.replaceSelection("###### "+i)},"list-ul":function(){var e=this.cm,t=(e.getCursor(),e.getSelection());if(""===t)e.replaceSelection("- "+t);else{for(var i=t.split("\n"),o=0,r=i.length;r>o;o++)i[o]=""===i[o]?"":"- "+i[o];e.replaceSelection(i.join("\n"))}},"list-ol":function(){var e=this.cm,t=(e.getCursor(),e.getSelection());if(""===t)e.replaceSelection("1. "+t);else{for(var i=t.split("\n"),o=0,r=i.length;r>o;o++)i[o]=""===i[o]?"":o+1+". "+i[o];e.replaceSelection(i.join("\n"))}},hr:function(){{var e=this.cm,t=e.getCursor();e.getSelection()}e.replaceSelection((0!==t.ch?"\n\n":"\n")+"------------\n\n")},tex:function(){if(!this.settings.tex)return alert("settings.tex === false"),this;var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("$$"+i+"$$"),""===i&&e.setCursor(t.line,t.ch+2)},link:function(){this.executePlugin("linkDialog","link-dialog/link-dialog")},"reference-link":function(){this.executePlugin("referenceLinkDialog","reference-link-dialog/reference-link-dialog")},pagebreak:function(){if(!this.settings.pageBreak)return alert("settings.pageBreak === false"),this;{var e=this.cm;e.getSelection()}e.replaceSelection("\r\n[========]\r\n")},image:function(){this.executePlugin("imageDialog","image-dialog/image-dialog")},code:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("`"+i+"`"),""===i&&e.setCursor(t.line,t.ch+1)},"code-block":function(){this.executePlugin("codeBlockDialog","code-block-dialog/code-block-dialog")},"preformatted-text":function(){this.executePlugin("preformattedTextDialog","preformatted-text-dialog/preformatted-text-dialog")},table:function(){this.executePlugin("tableDialog","table-dialog/table-dialog")},datetime:function(){var e=this.cm,i=(e.getSelection(),new Date,this.settings.lang.name),o=t.dateFormat()+" "+t.dateFormat("zh-cn"===i||"zh-tw"===i?"cn-week-day":"week-day");e.replaceSelection(o)},emoji:function(){this.executePlugin("emojiDialog","emoji-dialog/emoji-dialog")},"html-entities":function(){this.executePlugin("htmlEntitiesDialog","html-entities-dialog/html-entities-dialog")},"goto-line":function(){this.executePlugin("gotoLineDialog","goto-line-dialog/goto-line-dialog")},watch:function(){this[this.settings.watch?"unwatch":"watch"]()},preview:function(){this.previewing()},fullscreen:function(){this.fullscreen()},clear:function(){this.clear()},search:function(){this.search()},help:function(){this.executePlugin("helpDialog","help-dialog/help-dialog")},info:function(){this.showInfoDialog()}},t.keyMaps={"Ctrl-1":"h1","Ctrl-2":"h2","Ctrl-3":"h3","Ctrl-4":"h4","Ctrl-5":"h5","Ctrl-6":"h6","Ctrl-B":"bold","Ctrl-D":"datetime","Ctrl-E":function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();return this.settings.emoji?(e.replaceSelection(":"+i+":"),void(""===i&&e.setCursor(t.line,t.ch+1))):void alert("Error: settings.emoji == false")},"Ctrl-Alt-G":"goto-line","Ctrl-H":"hr","Ctrl-I":"italic","Ctrl-K":"code","Ctrl-L":function(){var e=this.cm,t=e.getCursor(),i=e.getSelection(),o=""===i?"":' "'+i+'"';e.replaceSelection("["+i+"]("+o+")"),""===i&&e.setCursor(t.line,t.ch+1)},"Ctrl-U":"list-ul","Shift-Ctrl-A":function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();return this.settings.atLink?(e.replaceSelection("@"+i),void(""===i&&e.setCursor(t.line,t.ch+1))):void alert("Error: settings.atLink == false")},"Shift-Ctrl-C":"code","Shift-Ctrl-Q":"quote","Shift-Ctrl-S":"del","Shift-Ctrl-K":"tex","Shift-Alt-C":function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection(["```",i,"```"].join("\n")),""===i&&e.setCursor(t.line,t.ch+3)},"Shift-Ctrl-Alt-C":"code-block","Shift-Ctrl-H":"html-entities","Shift-Alt-H":"help","Shift-Ctrl-E":"emoji","Shift-Ctrl-U":"uppercase","Shift-Alt-U":"ucwords","Shift-Ctrl-Alt-U":"ucfirst","Shift-Alt-L":"lowercase","Shift-Ctrl-I":function(){var e=this.cm,t=e.getCursor(),i=e.getSelection(),o=""===i?"":' "'+i+'"';e.replaceSelection("!["+i+"]("+o+")"),""===i&&e.setCursor(t.line,t.ch+4)},"Shift-Ctrl-Alt-I":"image","Shift-Ctrl-L":"link","Shift-Ctrl-O":"list-ol","Shift-Ctrl-P":"preformatted-text","Shift-Ctrl-T":"table","Shift-Alt-P":"pagebreak",F9:"watch",F10:"preview",F11:"fullscreen"};var r=function(e){return String.prototype.trim?e.trim():e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")};t.trim=r;var n=function(e){return e.toLowerCase().replace(/\b(\w)|\s(\w)/g,function(e){return e.toUpperCase()})};t.ucwords=t.wordsFirstUpperCase=n;var a=function(e){return e.toLowerCase().replace(/\b(\w)/,function(e){return e.toUpperCase()})};return t.firstUpperCase=t.ucfirst=a,t.urls={atLinkBase:"https://github.com/"},t.regexs={atLink:/@(\w+)/g,email:/(\w+)@(\w+)\.(\w+)\.?(\w+)?/g,emailLink:/(mailto:)?([\w\.\_]+)@(\w+)\.(\w+)\.?(\w+)?/g,emoji:/:([\w\+-]+):/g,emojiDatetime:/(\d{2}:\d{2}:\d{2})/g,twemoji:/:(tw-([\w]+)-?(\w+)?):/g,fontAwesome:/:(fa-([\w]+)(-(\w+)){0,}):/g,editormdLogo:/:(editormd-logo-?(\w+)?):/g,pageBreak:/^\[[=]{8,}\]$/},t.emoji={path:"http://www.emoji-cheat-sheet.com/graphics/emojis/",ext:".png"},t.twemoji={path:"http://twemoji.maxcdn.com/36x36/",ext:".png"},t.markedRenderer=function(i,o){var n={toc:!0,tocm:!1,tocStartLevel:1,pageBreak:!0,atLink:!0,emailLink:!0,taskList:!1,emoji:!1,tex:!1,flowChart:!1,sequenceDiagram:!1},a=e.extend(n,o||{}),s=t.$marked,l=new s.Renderer;i=i||[];var c=t.regexs,h=c.atLink,d=c.emoji,u=c.email,f=c.emailLink,g=c.twemoji,p=c.fontAwesome,m=c.editormdLogo,w=c.pageBreak;return l.emoji=function(e){e=e.replace(t.regexs.emojiDatetime,function(e){return e.replace(/:/g,":")});var i=e.match(d);if(!i||!a.emoji)return e;for(var o=0,r=i.length;r>o;o++)":+1:"===i[o]&&(i[o]=":\\+1:"),e=e.replace(new RegExp(i[o]),function(e,i){var o=e.match(p),r=e.replace(/:/g,"");if(o)for(var n=0,a=o.length;a>n;n++){var s=o[n].replace(/:/g,"");return''}else{var l=e.match(m),c=e.match(g);if(l)for(var h=0,d=l.length;d>h;h++){var u=l[h].replace(/:/g,"");return''}else{if(!c){var f="+1"===r?"plus1":r;return f="black_large_square"===f?"black_square":f,f="moon"===f?"waxing_gibbous_moon":f,':'+r+':'}for(var w=0,v=c.length;v>w;w++){var k=c[w].replace(/:/g,"").replace("tw-","");return'twemoji-'+k+''}}}});return e},l.atLink=function(i){return h.test(i)?(a.atLink&&(i=i.replace(u,function(e,t,i,o){return e.replace(/@/g,"_#_@_#_")}),i=i.replace(h,function(e,i){return''+e+""}).replace(/_#_@_#_/g,"@")),a.emailLink&&(i=i.replace(f,function(t,i,o,r,n){return!i&&e.inArray(n,"jpg|jpeg|png|gif|webp|ico|icon|pdf".split("|"))<0?''+t+"":t})),i):i},l.link=function(e,t,i){if(this.options.sanitize){try{var o=decodeURIComponent(unescape(e)).replace(/[^\w:]/g,"").toLowerCase()}catch(r){return""}if(0===o.indexOf("javascript:"))return""}var n=''+i.replace(/@/g,"@")+""):(t&&(n+=' title="'+t+'"'),n+=">"+i+"")},l.heading=function(e,t,o){var n=e,a=/\s*\]*)\>(.*)\<\/a\>\s*/;if(a.test(e)){var s=[];e=e.split(/\]+)\>([^\>]*)\<\/a\>/);for(var l=0,c=e.length;c>l;l++)s.push(e[l].replace(/\s*href\=\"(.*)\"\s*/g,""));e=s.join(" ")}e=r(e);var h=e.toLowerCase().replace(/[^\w]+/g,"-"),d={text:e,level:t,slug:h},u=/^[\u4e00-\u9fa5]+$/.test(e),f=u?escape(e).replace(/\%/g,""):e.toLowerCase().replace(/[^\w]+/g,"-");i.push(d);var g="';return g+='',g+='',g+=this.atLink(a?this.emoji(n):this.emoji(e)),g+=""},l.pageBreak=function(e){return w.test(e)&&a.pageBreak&&(e='
          '),e},l.paragraph=function(e){var i=/\$\$(.*)\$\$/g.test(e),o=/^\$\$(.*)\$\$$/.test(e),r=o?' class="'+t.classNames.tex+'"':"",n=a.tocm?/^(\[TOC\]|\[TOCM\])$/.test(e):/^\[TOC\]$/.test(e),s=/^\[TOCM\]$/.test(e);e=!o&&i?e.replace(/(\$\$([^\$]*)\$\$)+/g,function(e,i){return''+i.replace(/\$/g,"")+""}):o?e.replace(/\$/g,""):e;var l='
          '+e+"
          ";return n?s?'
          '+l+"

          ":l:w.test(e)?this.pageBreak(e):""+this.atLink(this.emoji(e))+"

          \n"},l.code=function(e,i,o){return"seq"===i||"sequence"===i?'
          '+e+"
          ":"flow"===i?'
          '+e+"
          ":"math"===i||"latex"===i||"katex"===i?'

          '+e+"

          ":s.Renderer.prototype.code.apply(this,arguments)},l.tablecell=function(e,t){var i=t.header?"th":"td",o=t.align?"<"+i+' style="text-align:'+t.align+'">':"<"+i+">";return o+this.atLink(this.emoji(e))+"\n"},l.listitem=function(e){return a.taskList&&/^\s*\[[x\s]\]\s*/.test(e)?(e=e.replace(/^\s*\[\s\]\s*/,' ').replace(/^\s*\[x\]\s*/,' '),'
        • '+this.atLink(this.emoji(e))+"
        • "):"
        • "+this.atLink(this.emoji(e))+"
        • "},l},t.markdownToCRenderer=function(e,t,i,o){var r="",n=0,a=this.classPrefix;o=o||1;for(var s=0,l=e.length;l>s;s++){var c=e[s].text,h=e[s].level;o>h||(r+=h>n?"":n>h?new Array(n-h+2).join("
      • "):"",r+='
      • '+c+"
          ",n=h)}var d=t.find(".markdown-toc");if(d.length<1&&"false"===t.attr("previewContainer")){var u='
          ';u=i?'
          '+u+"
          ":u,t.html(u),d=t.find(".markdown-toc")}return i&&d.wrap('

          '),d.html('
            ').children(".markdown-toc-list").html(r.replace(/\r?\n?\\<\/ul\>/g,"")),d},t.tocDropdownMenu=function(t,i){i=i||"Table of Contents";var o=400,r=t.find("."+this.classPrefix+"toc-menu");return r.each(function(){var t=e(this),r=t.children(".markdown-toc"),n='',a=''+n+i+"",s=r.children("ul"),l=s.find("li");r.append(a),l.first().before("
          • "+i+" "+n+"

          • "),t.mouseover(function(){s.show(),l.each(function(){var t=e(this),i=t.children("ul");if(""===i.html()&&i.remove(),i.length>0&&""!==i.html()){var r=t.children("a").first();r.children(".fa").length<1&&r.append(e(n).css({"float":"right",paddingTop:"4px"}))}t.mouseover(function(){i.css("z-index",o).show(),o+=1}).mouseleave(function(){i.hide()})})}).mouseleave(function(){s.hide()})}),r},t.filterHTMLTags=function(t,i){if("string"!=typeof t&&(t=new String(t)),"string"!=typeof i)return t;for(var o=i.split("|"),r=o[0].split(","),n=o[1],a=0,s=r.length;s>a;a++){var l=r[a];t=t.replace(new RegExp("]*)>([^>]*)","igm"),"")}if("undefined"!=typeof n){var c=/\<(\w+)\s*([^\>]*)\>([^\>]*)\<\/(\w+)\>/gi;t="*"===n?t.replace(c,function(e,t,i,o,r){return"<"+t+">"+o+""}):"on*"===n?t.replace(c,function(t,i,o,r,n){var a=e("<"+i+">"+r+""),s=e(t)[0].attributes,l={};e.each(s,function(e,t){'"'!==t.nodeName&&(l[t.nodeName]=t.nodeValue)}),e.each(l,function(e){0===e.indexOf("on")&&delete l[e]}),a.attr(l);var c="undefined"!=typeof a[1]?e(a[1]).text():"";return a[0].outerHTML+c}):t.replace(c,function(t,i,o,r){var a=n.split(","),s=e(t);return s.html(r),e.each(a,function(e){s.attr(a[e],null)}),s[0].outerHTML})}return t},t.markdownToHTML=function(i,o){var r={gfm:!0,toc:!0,tocm:!1,tocStartLevel:1,tocTitle:"目录",tocDropdown:!1,tocContainer:"",markdown:"",markdownSourceCode:!1,htmlDecode:!1,autoLoadKaTeX:!0,pageBreak:!0,atLink:!0,emailLink:!0,tex:!1,taskList:!1,emoji:!1,flowChart:!1,sequenceDiagram:!1,previewCodeHighlight:!0};t.$marked=marked;var n=e("#"+i),a=n.settings=e.extend(!0,r,o||{}),s=n.find("textarea");s.length<1&&(n.append(""),s=n.find("textarea"));var l=""===a.markdown?s.val():a.markdown,c=[],h={toc:a.toc,tocm:a.tocm,tocStartLevel:a.tocStartLevel,taskList:a.taskList,emoji:a.emoji,tex:a.tex,pageBreak:a.pageBreak,atLink:a.atLink,emailLink:a.emailLink,flowChart:a.flowChart,sequenceDiagram:a.sequenceDiagram,previewCodeHighlight:a.previewCodeHighlight},d={renderer:t.markedRenderer(c,h),gfm:a.gfm,tables:!0,breaks:!0,pedantic:!1,sanitize:a.htmlDecode?!1:!0,smartLists:!0,smartypants:!0};l=new String(l);var u=marked(l,d);u=t.filterHTMLTags(u,a.htmlDecode),a.markdownSourceCode?s.text(l):s.remove(),n.addClass("markdown-body "+this.classPrefix+"html-preview").append(u);var f=""!==a.tocContainer?e(a.tocContainer):n;if(""!==a.tocContainer&&f.attr("previewContainer",!1),a.toc&&(n.tocContainer=this.markdownToCRenderer(c,f,a.tocDropdown,a.tocStartLevel),(a.tocDropdown||n.find("."+this.classPrefix+"toc-menu").length>0)&&this.tocDropdownMenu(n,a.tocTitle),""!==a.tocContainer&&n.find(".editormd-toc-menu, .editormd-markdown-toc").remove()),a.previewCodeHighlight&&(n.find("pre").addClass("prettyprint linenums"),prettyPrint()),t.isIE8||(a.flowChart&&n.find(".flowchart").flowChart(),a.sequenceDiagram&&n.find(".sequence-diagram").sequenceDiagram({theme:"simple"})),a.tex){var g=function(){n.find("."+t.classNames.tex).each(function(){var t=e(this);katex.render(t.html().replace(/</g,"<").replace(/>/g,">"),t[0]),t.find(".katex").css("font-size","1.6em")})};!a.autoLoadKaTeX||t.$katex||t.kaTeXLoaded?g():this.loadKaTeX(function(){t.$katex=katex,t.kaTeXLoaded=!0,g()})}return n.getMarkdown=function(){return s.val()},n},t.themes=["default","dark"],t.previewThemes=["default","dark"],t.editorThemes=["default","3024-day","3024-night","ambiance","ambiance-mobile","base16-dark","base16-light","blackboard","cobalt","eclipse","elegant","erlang-dark","lesser-dark","mbo","mdn-like","midnight","monokai","neat","neo","night","paraiso-dark","paraiso-light","pastel-on-dark","rubyblue","solarized","the-matrix","tomorrow-night-eighties","twilight","vibrant-ink","xq-dark","xq-light"],t.loadPlugins={},t.loadFiles={js:[],css:[],plugin:[]},t.loadPlugin=function(e,i,o){i=i||function(){},this.loadScript(e,function(){t.loadFiles.plugin.push(e),i()},o)},t.loadCSS=function(e,i,o){o=o||"head",i=i||function(){};var r=document.createElement("link");r.type="text/css",r.rel="stylesheet",r.onload=r.onreadystatechange=function(){t.loadFiles.css.push(e),i()},r.href=e+".css","head"===o?document.getElementsByTagName("head")[0].appendChild(r):document.body.appendChild(r)},t.isIE="Microsoft Internet Explorer"==navigator.appName,t.isIE8=t.isIE&&"8."==navigator.appVersion.match(/8./i),t.loadScript=function(e,i,o){o=o||"head",i=i||function(){};var r=null;r=document.createElement("script"),r.id=e.replace(/[\./]+/g,"-"),r.type="text/javascript",r.src=e+".js",t.isIE8?r.onreadystatechange=function(){r.readyState&&("loaded"===r.readyState||"complete"===r.readyState)&&(r.onreadystatechange=null,t.loadFiles.js.push(e),i())}:r.onload=function(){t.loadFiles.js.push(e),i()},"head"===o?document.getElementsByTagName("head")[0].appendChild(r):document.body.appendChild(r)},t.katexURL={css:"//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.3.0/katex.min",js:"//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.3.0/katex.min"},t.kaTeXLoaded=!1,t.loadKaTeX=function(e){t.loadCSS(t.katexURL.css,function(){t.loadScript(t.katexURL.js,e||function(){})})},t.lockScreen=function(t){e("html,body").css("overflow",t?"hidden":"")},t.createDialog=function(i){var o={name:"",width:420,height:240,title:"",drag:!0,closed:!0,content:"",mask:!0,maskStyle:{backgroundColor:"#fff",opacity:.1},lockScreen:!0,footer:!0,buttons:!1};i=e.extend(!0,o,i);var r=this,n=this.editor,a=t.classPrefix,s=(new Date).getTime(),l=""===i.name?a+"dialog-"+s:i.name,c=t.mouseOrTouch,h='
            ';""!==i.title&&(h+='
            ",h+=''+i.title+"",h+="
            "),i.closed&&(h+=''),h+='
            '+i.content,(i.footer||"string"==typeof i.footer)&&(h+='"),h+="
            ",h+='
            ',h+='
            ',h+="
            ",n.append(h);var d=n.find("."+l);d.lockScreen=function(t){return i.lockScreen&&(e("html,body").css("overflow",t?"hidden":""),r.resize()),d},d.showMask=function(){return i.mask&&n.find("."+a+"mask").css(i.maskStyle).css("z-index",t.dialogZindex-1).show(),d},d.hideMask=function(){return i.mask&&n.find("."+a+"mask").hide(),d},d.loading=function(e){var t=d.find("."+a+"dialog-mask");return t[e?"show":"hide"](),d},d.lockScreen(!0).showMask(),d.show().css({zIndex:t.dialogZindex,border:t.isIE8?"1px solid #ddd":"",width:"number"==typeof i.width?i.width+"px":i.width,height:"number"==typeof i.height?i.height+"px":i.height});var u=function(){d.css({top:(e(window).height()-d.height())/2+"px",left:(e(window).width()-d.width())/2+"px"})};if(u(),e(window).resize(u),d.children("."+a+"dialog-close").bind(c("click","touchend"),function(){d.hide().lockScreen(!1).hideMask()}),"object"==typeof i.buttons){var f=d.footer=d.find("."+a+"dialog-footer");for(var g in i.buttons){var p=i.buttons[g],m=a+g+"-btn";f.append('"),p[1]=e.proxy(p[1],d),f.children("."+m).bind(c("click","touchend"),p[1])}}if(""!==i.title&&i.drag){var w,v,k=d.children("."+a+"dialog-header");i.mask||k.bind(c("click","touchend"),function(){t.dialogZindex+=2,d.css("z-index",t.dialogZindex)}),k.mousedown(function(e){e=e||window.event,w=e.clientX-parseInt(d[0].style.left),v=e.clientY-parseInt(d[0].style.top),document.onmousemove=y});var b=function(e){e.removeClass(a+"user-unselect").off("selectstart")},x=function(e){e.addClass(a+"user-unselect").on("selectstart",function(e){return!1})},y=function(t){t=t||window.event;var i,o,r=parseInt(d[0].style.left),n=parseInt(d[0].style.top);r>=0?r+d.width()<=e(window).width()?i=t.clientX-w:(i=e(window).width()-d.width(),document.onmousemove=null):(i=0,document.onmousemove=null),n>=0?o=t.clientY-v:(o=0,document.onmousemove=null),document.onselectstart=function(){return!1},x(e("body")),x(d),d[0].style.left=i+"px",d[0].style.top=o+"px"};document.onmouseup=function(){b(e("body")),b(d),document.onselectstart=null,document.onmousemove=null},k.touchDraggable=function(){var t=null,i=function(i){var o=i.originalEvent,r=e(this).parent().position();t={x:o.changedTouches[0].pageX-r.left,y:o.changedTouches[0].pageY-r.top}},o=function(i){i.preventDefault();var o=i.originalEvent;e(this).parent().css({top:o.changedTouches[0].pageY-t.y,left:o.changedTouches[0].pageX-t.x})};this.bind("touchstart",i).bind("touchmove",o)},k.touchDraggable()}return t.dialogZindex+=2,d},t.mouseOrTouch=function(e,t){e=e||"click",t=t||"touchend";var i=e;try{document.createEvent("TouchEvent"),i=t}catch(o){}return i},t.dateFormat=function(e){e=e||"";var t=function(e){return 10>e?"0"+e:e},i=new Date,o=i.getFullYear(),r=o.toString().slice(2,4),n=t(i.getMonth()+1),a=t(i.getDate()),s=i.getDay(),l=t(i.getHours()),c=t(i.getMinutes()),h=t(i.getSeconds()),d=t(i.getMilliseconds()),u="",f=r+"-"+n+"-"+a,g=o+"-"+n+"-"+a,p=l+":"+c+":"+h;switch(e){case"UNIX Time":u=i.getTime();break;case"UTC":u=i.toUTCString();break;case"yy":u=r;break;case"year":case"yyyy":u=o;break;case"month":case"mm":u=n;break;case"cn-week-day":case"cn-wd":var m=["日","一","二","三","四","五","六"];u="星期"+m[s];break;case"week-day":case"wd":var w=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];u=w[s];break;case"day":case"dd":u=a;break;case"hour":case"hh":u=l;break;case"min":case"ii":u=c;break;case"second":case"ss":u=h;break;case"ms":u=d;break;case"yy-mm-dd":u=f;break;case"yyyy-mm-dd":u=g;break;case"yyyy-mm-dd h:i:s ms":case"full + ms":u=g+" "+p+" "+d;break;case"full":case"yyyy-mm-dd h:i:s":default:u=g+" "+p}return u},t}}); \ No newline at end of file diff --git a/src/main/resources/static/editor-md/editormd.js b/src/main/resources/static/editor-md/editormd.js deleted file mode 100644 index 7b162f0..0000000 --- a/src/main/resources/static/editor-md/editormd.js +++ /dev/null @@ -1,4598 +0,0 @@ -/* - * Editor.md - * - * @file editormd.js - * @version v1.5.0 - * @description Open source online markdown editor. - * @license MIT License - * @author Pandao - * {@link https://github.com/pandao/editor.md} - * @updateTime 2015-06-09 - */ - -;(function(factory) { - "use strict"; - - // CommonJS/Node.js - if (typeof require === "function" && typeof exports === "object" && typeof module === "object") - { - module.exports = factory; - } - else if (typeof define === "function") // AMD/CMD/Sea.js - { - if (define.amd) // for Require.js - { - /* Require.js define replace */ - } - else - { - define(["jquery"], factory); // for Sea.js - } - } - else - { - window.editormd = factory(); - } - -}(function() { - - /* Require.js assignment replace */ - - "use strict"; - - var $ = (typeof (jQuery) !== "undefined") ? jQuery : Zepto; - - if (typeof ($) === "undefined") { - return ; - } - - /** - * editormd - * - * @param {String} id 编辑器的ID - * @param {Object} options 配置选项 Key/Value - * @returns {Object} editormd 返回editormd对象 - */ - - var editormd = function (id, options) { - return new editormd.fn.init(id, options); - }; - - editormd.title = editormd.$name = "Editor.md"; - editormd.version = "1.5.0"; - editormd.homePage = "https://pandao.github.io/editor.md/"; - editormd.classPrefix = "editormd-"; - - editormd.toolbarModes = { - full : [ - "undo", "redo", "|", - "bold", "del", "italic", "quote", "ucwords", "uppercase", "lowercase", "|", - "h1", "h2", "h3", "h4", "h5", "h6", "|", - "list-ul", "list-ol", "hr", "|", - "link", "reference-link", "image", "code", "preformatted-text", "code-block", "table", "datetime", "emoji", "html-entities", "pagebreak", "|", - "goto-line", "watch", "preview", "fullscreen", "clear", "search", "|", - "help", "info" - ], - simple : [ - "undo", "redo", "|", - "bold", "del", "italic", "quote", "uppercase", "lowercase", "|", - "h1", "h2", "h3", "h4", "h5", "h6", "|", - "list-ul", "list-ol", "hr", "|", - "watch", "preview", "fullscreen", "|", - "help", "info" - ], - mini : [ - "undo", "redo", "|", - "watch", "preview", "|", - "help", "info" - ] - }; - - editormd.defaults = { - mode : "gfm", //gfm or markdown - name : "", // Form element name - value : "", // value for CodeMirror, if mode not gfm/markdown - theme : "", // Editor.md self themes, before v1.5.0 is CodeMirror theme, default empty - editorTheme : "default", // Editor area, this is CodeMirror theme at v1.5.0 - previewTheme : "", // Preview area theme, default empty - markdown : "", // Markdown source code - appendMarkdown : "", // if in init textarea value not empty, append markdown to textarea - width : "100%", - height : "100%", - path : "./lib/", // Dependents module file directory - pluginPath : "", // If this empty, default use settings.path + "../plugins/" - delay : 300, // Delay parse markdown to html, Uint : ms - autoLoadModules : true, // Automatic load dependent module files - watch : true, - placeholder : "Enjoy Markdown! coding now...", - gotoLine : true, - codeFold : false, - autoHeight : false, - autoFocus : true, - autoCloseTags : true, - searchReplace : true, - syncScrolling : true, // true | false | "single", default true - readOnly : false, - tabSize : 4, - indentUnit : 4, - lineNumbers : true, - lineWrapping : true, - autoCloseBrackets : true, - showTrailingSpace : true, - matchBrackets : true, - indentWithTabs : true, - styleSelectedText : true, - matchWordHighlight : true, // options: true, false, "onselected" - styleActiveLine : true, // Highlight the current line - dialogLockScreen : true, - dialogShowMask : true, - dialogDraggable : true, - dialogMaskBgColor : "#fff", - dialogMaskOpacity : 0.1, - fontSize : "13px", - saveHTMLToTextarea : false, - disabledKeyMaps : [], - - onload : function() {}, - onresize : function() {}, - onchange : function() {}, - onwatch : null, - onunwatch : null, - onpreviewing : function() {}, - onpreviewed : function() {}, - onfullscreen : function() {}, - onfullscreenExit : function() {}, - onscroll : function() {}, - onpreviewscroll : function() {}, - - imageUpload : false, - imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"], - imageUploadURL : "", - crossDomainUpload : false, - uploadCallbackURL : "", - - toc : true, // Table of contents - tocm : false, // Using [TOCM], auto create ToC dropdown menu - tocTitle : "", // for ToC dropdown menu btn - tocDropdown : false, - tocContainer : "", - tocStartLevel : 1, // Said from H1 to create ToC - htmlDecode : false, // Open the HTML tag identification - pageBreak : true, // Enable parse page break [========] - atLink : true, // for @link - emailLink : true, // for email address auto link - taskList : false, // Enable Github Flavored Markdown task lists - emoji : false, // :emoji: , Support Github emoji, Twitter Emoji (Twemoji); - // Support FontAwesome icon emoji :fa-xxx: > Using fontAwesome icon web fonts; - // Support Editor.md logo icon emoji :editormd-logo: :editormd-logo-1x: > 1~8x; - tex : false, // TeX(LaTeX), based on KaTeX - flowChart : false, // flowChart.js only support IE9+ - sequenceDiagram : false, // sequenceDiagram.js only support IE9+ - previewCodeHighlight : true, - - toolbar : true, // show/hide toolbar - toolbarAutoFixed : true, // on window scroll auto fixed position - toolbarIcons : "full", - toolbarTitles : {}, - toolbarHandlers : { - ucwords : function() { - return editormd.toolbarHandlers.ucwords; - }, - lowercase : function() { - return editormd.toolbarHandlers.lowercase; - } - }, - toolbarCustomIcons : { // using html tag create toolbar icon, unused default tag. - lowercase : "a", - "ucwords" : "Aa" - }, - toolbarIconsClass : { - undo : "fa-undo", - redo : "fa-repeat", - bold : "fa-bold", - del : "fa-strikethrough", - italic : "fa-italic", - quote : "fa-quote-left", - uppercase : "fa-font", - h1 : editormd.classPrefix + "bold", - h2 : editormd.classPrefix + "bold", - h3 : editormd.classPrefix + "bold", - h4 : editormd.classPrefix + "bold", - h5 : editormd.classPrefix + "bold", - h6 : editormd.classPrefix + "bold", - "list-ul" : "fa-list-ul", - "list-ol" : "fa-list-ol", - hr : "fa-minus", - link : "fa-link", - "reference-link" : "fa-anchor", - image : "fa-picture-o", - code : "fa-code", - "preformatted-text" : "fa-file-code-o", - "code-block" : "fa-file-code-o", - table : "fa-table", - datetime : "fa-clock-o", - emoji : "fa-smile-o", - "html-entities" : "fa-copyright", - pagebreak : "fa-newspaper-o", - "goto-line" : "fa-terminal", // fa-crosshairs - watch : "fa-eye-slash", - unwatch : "fa-eye", - preview : "fa-desktop", - search : "fa-search", - fullscreen : "fa-arrows-alt", - clear : "fa-eraser", - help : "fa-question-circle", - info : "fa-info-circle" - }, - toolbarIconTexts : {}, - - lang : { - name : "zh-cn", - description : "开源在线Markdown编辑器
            Open source online Markdown editor.", - tocTitle : "目录", - toolbar : { - undo : "撤销(Ctrl+Z)", - redo : "重做(Ctrl+Y)", - bold : "粗体", - del : "删除线", - italic : "斜体", - quote : "引用", - ucwords : "将每个单词首字母转成大写", - uppercase : "将所选转换成大写", - lowercase : "将所选转换成小写", - h1 : "标题1", - h2 : "标题2", - h3 : "标题3", - h4 : "标题4", - h5 : "标题5", - h6 : "标题6", - "list-ul" : "无序列表", - "list-ol" : "有序列表", - hr : "横线", - link : "链接", - "reference-link" : "引用链接", - image : "添加图片", - code : "行内代码", - "preformatted-text" : "预格式文本 / 代码块(缩进风格)", - "code-block" : "代码块(多语言风格)", - table : "添加表格", - datetime : "日期时间", - emoji : "Emoji表情", - "html-entities" : "HTML实体字符", - pagebreak : "插入分页符", - "goto-line" : "跳转到行", - watch : "关闭实时预览", - unwatch : "开启实时预览", - preview : "全窗口预览HTML(按 Shift + ESC还原)", - fullscreen : "全屏(按ESC还原)", - clear : "清空", - search : "搜索", - help : "使用帮助", - info : "关于" + editormd.title - }, - buttons : { - enter : "确定", - cancel : "取消", - close : "关闭" - }, - dialog : { - link : { - title : "添加链接", - url : "链接地址", - urlTitle : "链接标题", - urlEmpty : "错误:请填写链接地址。" - }, - referenceLink : { - title : "添加引用链接", - name : "引用名称", - url : "链接地址", - urlId : "链接ID", - urlTitle : "链接标题", - nameEmpty: "错误:引用链接的名称不能为空。", - idEmpty : "错误:请填写引用链接的ID。", - urlEmpty : "错误:请填写引用链接的URL地址。" - }, - image : { - title : "添加图片", - url : "图片地址", - link : "图片链接", - alt : "图片描述", - uploadButton : "本地上传", - imageURLEmpty : "错误:图片地址不能为空。", - uploadFileEmpty : "错误:上传的图片不能为空。", - formatNotAllowed : "错误:只允许上传图片文件,允许上传的图片文件格式有:" - }, - preformattedText : { - title : "添加预格式文本或代码块", - emptyAlert : "错误:请填写预格式文本或代码的内容。" - }, - codeBlock : { - title : "添加代码块", - selectLabel : "代码语言:", - selectDefaultText : "请选择代码语言", - otherLanguage : "其他语言", - unselectedLanguageAlert : "错误:请选择代码所属的语言类型。", - codeEmptyAlert : "错误:请填写代码内容。" - }, - htmlEntities : { - title : "HTML 实体字符" - }, - help : { - title : "使用帮助" - } - } - } - }; - - editormd.classNames = { - tex : editormd.classPrefix + "tex" - }; - - editormd.dialogZindex = 99999; - - editormd.$katex = null; - editormd.$marked = null; - editormd.$CodeMirror = null; - editormd.$prettyPrint = null; - - var timer, flowchartTimer; - - editormd.prototype = editormd.fn = { - state : { - watching : false, - loaded : false, - preview : false, - fullscreen : false - }, - - /** - * 构造函数/实例初始化 - * Constructor / instance initialization - * - * @param {String} id 编辑器的ID - * @param {Object} [options={}] 配置选项 Key/Value - * @returns {editormd} 返回editormd的实例对象 - */ - - init : function (id, options) { - - options = options || {}; - - if (typeof id === "object") - { - options = id; - } - - var _this = this; - var classPrefix = this.classPrefix = editormd.classPrefix; - var settings = this.settings = $.extend(true, {}, editormd.defaults, options); - - id = (typeof id === "object") ? settings.id : id; - - var editor = this.editor = $("#" + id); - - this.id = id; - this.lang = settings.lang; - - var classNames = this.classNames = { - textarea : { - html : classPrefix + "html-textarea", - markdown : classPrefix + "markdown-textarea" - } - }; - - settings.pluginPath = (settings.pluginPath === "") ? settings.path + "../plugins/" : settings.pluginPath; - - this.state.watching = (settings.watch) ? true : false; - - if ( !editor.hasClass("editormd") ) { - editor.addClass("editormd"); - } - - editor.css({ - width : (typeof settings.width === "number") ? settings.width + "px" : settings.width, - height : (typeof settings.height === "number") ? settings.height + "px" : settings.height - }); - - if (settings.autoHeight) - { - editor.css("height", "auto"); - } - - var markdownTextarea = this.markdownTextarea = editor.children("textarea"); - - if (markdownTextarea.length < 1) - { - editor.append(""); - markdownTextarea = this.markdownTextarea = editor.children("textarea"); - } - - markdownTextarea.addClass(classNames.textarea.markdown).attr("placeholder", settings.placeholder); - - if (typeof markdownTextarea.attr("name") === "undefined" || markdownTextarea.attr("name") === "") - { - markdownTextarea.attr("name", (settings.name !== "") ? settings.name : id + "-markdown-doc"); - } - - var appendElements = [ - (!settings.readOnly) ? "" : "", - ( (settings.saveHTMLToTextarea) ? "" : "" ), - "
            ", - "
            ", - "
            " - ].join("\n"); - - editor.append(appendElements).addClass(classPrefix + "vertical"); - - if (settings.theme !== "") - { - editor.addClass(classPrefix + "theme-" + settings.theme); - } - - this.mask = editor.children("." + classPrefix + "mask"); - this.containerMask = editor.children("." + classPrefix + "container-mask"); - - if (settings.markdown !== "") - { - markdownTextarea.val(settings.markdown); - } - - if (settings.appendMarkdown !== "") - { - markdownTextarea.val(markdownTextarea.val() + settings.appendMarkdown); - } - - this.htmlTextarea = editor.children("." + classNames.textarea.html); - this.preview = editor.children("." + classPrefix + "preview"); - this.previewContainer = this.preview.children("." + classPrefix + "preview-container"); - - if (settings.previewTheme !== "") - { - this.preview.addClass(classPrefix + "preview-theme-" + settings.previewTheme); - } - - if (typeof define === "function" && define.amd) - { - if (typeof katex !== "undefined") - { - editormd.$katex = katex; - } - - if (settings.searchReplace && !settings.readOnly) - { - editormd.loadCSS(settings.path + "codemirror/addon/dialog/dialog"); - editormd.loadCSS(settings.path + "codemirror/addon/search/matchesonscrollbar"); - } - } - - if ((typeof define === "function" && define.amd) || !settings.autoLoadModules) - { - if (typeof CodeMirror !== "undefined") { - editormd.$CodeMirror = CodeMirror; - } - - if (typeof marked !== "undefined") { - editormd.$marked = marked; - } - - this.setCodeMirror().setToolbar().loadedDisplay(); - } - else - { - this.loadQueues(); - } - - return this; - }, - - /** - * 所需组件加载队列 - * Required components loading queue - * - * @returns {editormd} 返回editormd的实例对象 - */ - - loadQueues : function() { - var _this = this; - var settings = this.settings; - var loadPath = settings.path; - - var loadFlowChartOrSequenceDiagram = function() { - - if (editormd.isIE8) - { - _this.loadedDisplay(); - - return ; - } - - if (settings.flowChart || settings.sequenceDiagram) - { - editormd.loadScript(loadPath + "raphael.min", function() { - - editormd.loadScript(loadPath + "underscore.min", function() { - - if (!settings.flowChart && settings.sequenceDiagram) - { - editormd.loadScript(loadPath + "sequence-diagram.min", function() { - _this.loadedDisplay(); - }); - } - else if (settings.flowChart && !settings.sequenceDiagram) - { - editormd.loadScript(loadPath + "flowchart.min", function() { - editormd.loadScript(loadPath + "jquery.flowchart.min", function() { - _this.loadedDisplay(); - }); - }); - } - else if (settings.flowChart && settings.sequenceDiagram) - { - editormd.loadScript(loadPath + "flowchart.min", function() { - editormd.loadScript(loadPath + "jquery.flowchart.min", function() { - editormd.loadScript(loadPath + "sequence-diagram.min", function() { - _this.loadedDisplay(); - }); - }); - }); - } - }); - - }); - } - else - { - _this.loadedDisplay(); - } - }; - - editormd.loadCSS(loadPath + "codemirror/codemirror.min"); - - if (settings.searchReplace && !settings.readOnly) - { - editormd.loadCSS(loadPath + "codemirror/addon/dialog/dialog"); - editormd.loadCSS(loadPath + "codemirror/addon/search/matchesonscrollbar"); - } - - if (settings.codeFold) - { - editormd.loadCSS(loadPath + "codemirror/addon/fold/foldgutter"); - } - - editormd.loadScript(loadPath + "codemirror/codemirror.min", function() { - editormd.$CodeMirror = CodeMirror; - - editormd.loadScript(loadPath + "codemirror/modes.min", function() { - - editormd.loadScript(loadPath + "codemirror/addons.min", function() { - - _this.setCodeMirror(); - - if (settings.mode !== "gfm" && settings.mode !== "markdown") - { - _this.loadedDisplay(); - - return false; - } - - _this.setToolbar(); - - editormd.loadScript(loadPath + "marked.min", function() { - - editormd.$marked = marked; - - if (settings.previewCodeHighlight) - { - editormd.loadScript(loadPath + "prettify.min", function() { - loadFlowChartOrSequenceDiagram(); - }); - } - else - { - loadFlowChartOrSequenceDiagram(); - } - }); - - }); - - }); - - }); - - return this; - }, - - /** - * 设置 Editor.md 的整体主题,主要是工具栏 - * Setting Editor.md theme - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setTheme : function(theme) { - var editor = this.editor; - var oldTheme = this.settings.theme; - var themePrefix = this.classPrefix + "theme-"; - - editor.removeClass(themePrefix + oldTheme).addClass(themePrefix + theme); - - this.settings.theme = theme; - - return this; - }, - - /** - * 设置 CodeMirror(编辑区)的主题 - * Setting CodeMirror (Editor area) theme - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setEditorTheme : function(theme) { - var settings = this.settings; - settings.editorTheme = theme; - - if (theme !== "default") - { - editormd.loadCSS(settings.path + "codemirror/theme/" + settings.editorTheme); - } - - this.cm.setOption("theme", theme); - - return this; - }, - - /** - * setEditorTheme() 的别名 - * setEditorTheme() alias - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setCodeMirrorTheme : function (theme) { - this.setEditorTheme(theme); - - return this; - }, - - /** - * 设置 Editor.md 的主题 - * Setting Editor.md theme - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setPreviewTheme : function(theme) { - var preview = this.preview; - var oldTheme = this.settings.previewTheme; - var themePrefix = this.classPrefix + "preview-theme-"; - - preview.removeClass(themePrefix + oldTheme).addClass(themePrefix + theme); - - this.settings.previewTheme = theme; - - return this; - }, - - /** - * 配置和初始化CodeMirror组件 - * CodeMirror initialization - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setCodeMirror : function() { - var settings = this.settings; - var editor = this.editor; - - if (settings.editorTheme !== "default") - { - editormd.loadCSS(settings.path + "codemirror/theme/" + settings.editorTheme); - } - - var codeMirrorConfig = { - mode : settings.mode, - theme : settings.editorTheme, - tabSize : settings.tabSize, - dragDrop : false, - autofocus : settings.autoFocus, - autoCloseTags : settings.autoCloseTags, - readOnly : (settings.readOnly) ? "nocursor" : false, - indentUnit : settings.indentUnit, - lineNumbers : settings.lineNumbers, - lineWrapping : settings.lineWrapping, - extraKeys : { - "Ctrl-Q": function(cm) { - cm.foldCode(cm.getCursor()); - } - }, - foldGutter : settings.codeFold, - gutters : ["CodeMirror-linenumbers", "CodeMirror-foldgutter"], - matchBrackets : settings.matchBrackets, - indentWithTabs : settings.indentWithTabs, - styleActiveLine : settings.styleActiveLine, - styleSelectedText : settings.styleSelectedText, - autoCloseBrackets : settings.autoCloseBrackets, - showTrailingSpace : settings.showTrailingSpace, - highlightSelectionMatches : ( (!settings.matchWordHighlight) ? false : { showToken: (settings.matchWordHighlight === "onselected") ? false : /\w/ } ) - }; - - this.codeEditor = this.cm = editormd.$CodeMirror.fromTextArea(this.markdownTextarea[0], codeMirrorConfig); - this.codeMirror = this.cmElement = editor.children(".CodeMirror"); - - if (settings.value !== "") - { - this.cm.setValue(settings.value); - } - - this.codeMirror.css({ - fontSize : settings.fontSize, - width : (!settings.watch) ? "100%" : "50%" - }); - - if (settings.autoHeight) - { - this.codeMirror.css("height", "auto"); - this.cm.setOption("viewportMargin", Infinity); - } - - if (!settings.lineNumbers) - { - this.codeMirror.find(".CodeMirror-gutters").css("border-right", "none"); - } - - return this; - }, - - /** - * 获取CodeMirror的配置选项 - * Get CodeMirror setting options - * - * @returns {Mixed} return CodeMirror setting option value - */ - - getCodeMirrorOption : function(key) { - return this.cm.getOption(key); - }, - - /** - * 配置和重配置CodeMirror的选项 - * CodeMirror setting options / resettings - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setCodeMirrorOption : function(key, value) { - - this.cm.setOption(key, value); - - return this; - }, - - /** - * 添加 CodeMirror 键盘快捷键 - * Add CodeMirror keyboard shortcuts key map - * - * @returns {editormd} 返回editormd的实例对象 - */ - - addKeyMap : function(map, bottom) { - this.cm.addKeyMap(map, bottom); - - return this; - }, - - /** - * 移除 CodeMirror 键盘快捷键 - * Remove CodeMirror keyboard shortcuts key map - * - * @returns {editormd} 返回editormd的实例对象 - */ - - removeKeyMap : function(map) { - this.cm.removeKeyMap(map); - - return this; - }, - - /** - * 跳转到指定的行 - * Goto CodeMirror line - * - * @param {String|Intiger} line line number or "first"|"last" - * @returns {editormd} 返回editormd的实例对象 - */ - - gotoLine : function (line) { - - var settings = this.settings; - - if (!settings.gotoLine) - { - return this; - } - - var cm = this.cm; - var editor = this.editor; - var count = cm.lineCount(); - var preview = this.preview; - - if (typeof line === "string") - { - if(line === "last") - { - line = count; - } - - if (line === "first") - { - line = 1; - } - } - - if (typeof line !== "number") - { - alert("Error: The line number must be an integer."); - return this; - } - - line = parseInt(line) - 1; - - if (line > count) - { - alert("Error: The line number range 1-" + count); - - return this; - } - - cm.setCursor( {line : line, ch : 0} ); - - var scrollInfo = cm.getScrollInfo(); - var clientHeight = scrollInfo.clientHeight; - var coords = cm.charCoords({line : line, ch : 0}, "local"); - - cm.scrollTo(null, (coords.top + coords.bottom - clientHeight) / 2); - - if (settings.watch) - { - var cmScroll = this.codeMirror.find(".CodeMirror-scroll")[0]; - var height = $(cmScroll).height(); - var scrollTop = cmScroll.scrollTop; - var percent = (scrollTop / cmScroll.scrollHeight); - - if (scrollTop === 0) - { - preview.scrollTop(0); - } - else if (scrollTop + height >= cmScroll.scrollHeight - 16) - { - preview.scrollTop(preview[0].scrollHeight); - } - else - { - preview.scrollTop(preview[0].scrollHeight * percent); - } - } - - cm.focus(); - - return this; - }, - - /** - * 扩展当前实例对象,可同时设置多个或者只设置一个 - * Extend editormd instance object, can mutil setting. - * - * @returns {editormd} this(editormd instance object.) - */ - - extend : function() { - if (typeof arguments[1] !== "undefined") - { - if (typeof arguments[1] === "function") - { - arguments[1] = $.proxy(arguments[1], this); - } - - this[arguments[0]] = arguments[1]; - } - - if (typeof arguments[0] === "object" && typeof arguments[0].length === "undefined") - { - $.extend(true, this, arguments[0]); - } - - return this; - }, - - /** - * 设置或扩展当前实例对象,单个设置 - * Extend editormd instance object, one by one - * - * @param {String|Object} key option key - * @param {String|Object} value option value - * @returns {editormd} this(editormd instance object.) - */ - - set : function (key, value) { - - if (typeof value !== "undefined" && typeof value === "function") - { - value = $.proxy(value, this); - } - - this[key] = value; - - return this; - }, - - /** - * 重新配置 - * Resetting editor options - * - * @param {String|Object} key option key - * @param {String|Object} value option value - * @returns {editormd} this(editormd instance object.) - */ - - config : function(key, value) { - var settings = this.settings; - - if (typeof key === "object") - { - settings = $.extend(true, settings, key); - } - - if (typeof key === "string") - { - settings[key] = value; - } - - this.settings = settings; - this.recreate(); - - return this; - }, - - /** - * 注册事件处理方法 - * Bind editor event handle - * - * @param {String} eventType event type - * @param {Function} callback 回调函数 - * @returns {editormd} this(editormd instance object.) - */ - - on : function(eventType, callback) { - var settings = this.settings; - - if (typeof settings["on" + eventType] !== "undefined") - { - settings["on" + eventType] = $.proxy(callback, this); - } - - return this; - }, - - /** - * 解除事件处理方法 - * Unbind editor event handle - * - * @param {String} eventType event type - * @returns {editormd} this(editormd instance object.) - */ - - off : function(eventType) { - var settings = this.settings; - - if (typeof settings["on" + eventType] !== "undefined") - { - settings["on" + eventType] = function(){}; - } - - return this; - }, - - /** - * 显示工具栏 - * Display toolbar - * - * @param {Function} [callback=function(){}] 回调函数 - * @returns {editormd} 返回editormd的实例对象 - */ - - showToolbar : function(callback) { - var settings = this.settings; - - if(settings.readOnly) { - return this; - } - - if (settings.toolbar && (this.toolbar.length < 1 || this.toolbar.find("." + this.classPrefix + "menu").html() === "") ) - { - this.setToolbar(); - } - - settings.toolbar = true; - - this.toolbar.show(); - this.resize(); - - $.proxy(callback || function(){}, this)(); - - return this; - }, - - /** - * 隐藏工具栏 - * Hide toolbar - * - * @param {Function} [callback=function(){}] 回调函数 - * @returns {editormd} this(editormd instance object.) - */ - - hideToolbar : function(callback) { - var settings = this.settings; - - settings.toolbar = false; - this.toolbar.hide(); - this.resize(); - - $.proxy(callback || function(){}, this)(); - - return this; - }, - - /** - * 页面滚动时工具栏的固定定位 - * Set toolbar in window scroll auto fixed position - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setToolbarAutoFixed : function(fixed) { - - var state = this.state; - var editor = this.editor; - var toolbar = this.toolbar; - var settings = this.settings; - - if (typeof fixed !== "undefined") - { - settings.toolbarAutoFixed = fixed; - } - - var autoFixedHandle = function(){ - var $window = $(window); - var top = $window.scrollTop(); - - if (!settings.toolbarAutoFixed) - { - return false; - } - - if (top - editor.offset().top > 10 && top < editor.height()) - { - toolbar.css({ - position : "fixed", - width : editor.width() + "px", - left : ($window.width() - editor.width()) / 2 + "px" - }); - } - else - { - toolbar.css({ - position : "absolute", - width : "100%", - left : 0 - }); - } - }; - - if (!state.fullscreen && !state.preview && settings.toolbar && settings.toolbarAutoFixed) - { - $(window).bind("scroll", autoFixedHandle); - } - - return this; - }, - - /** - * 配置和初始化工具栏 - * Set toolbar and Initialization - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setToolbar : function() { - var settings = this.settings; - - if(settings.readOnly) { - return this; - } - - var editor = this.editor; - var preview = this.preview; - var classPrefix = this.classPrefix; - - var toolbar = this.toolbar = editor.children("." + classPrefix + "toolbar"); - - if (settings.toolbar && toolbar.length < 1) - { - var toolbarHTML = "
              "; - - editor.append(toolbarHTML); - toolbar = this.toolbar = editor.children("." + classPrefix + "toolbar"); - } - - if (!settings.toolbar) - { - toolbar.hide(); - - return this; - } - - toolbar.show(); - - var icons = (typeof settings.toolbarIcons === "function") ? settings.toolbarIcons() - : ((typeof settings.toolbarIcons === "string") ? editormd.toolbarModes[settings.toolbarIcons] : settings.toolbarIcons); - - var toolbarMenu = toolbar.find("." + this.classPrefix + "menu"), menu = ""; - var pullRight = false; - - for (var i = 0, len = icons.length; i < len; i++) - { - var name = icons[i]; - - if (name === "||") - { - pullRight = true; - } - else if (name === "|") - { - menu += "
            • |
            • "; - } - else - { - var isHeader = (/h(\d)/.test(name)); - var index = name; - - if (name === "watch" && !settings.watch) { - index = "unwatch"; - } - - var title = settings.lang.toolbar[index]; - var iconTexts = settings.toolbarIconTexts[index]; - var iconClass = settings.toolbarIconsClass[index]; - - title = (typeof title === "undefined") ? "" : title; - iconTexts = (typeof iconTexts === "undefined") ? "" : iconTexts; - iconClass = (typeof iconClass === "undefined") ? "" : iconClass; - - var menuItem = pullRight ? "
            • " : "
            • "; - - if (typeof settings.toolbarCustomIcons[name] !== "undefined" && typeof settings.toolbarCustomIcons[name] !== "function") - { - menuItem += settings.toolbarCustomIcons[name]; - } - else - { - menuItem += ""; - menuItem += ""+((isHeader) ? name.toUpperCase() : ( (iconClass === "") ? iconTexts : "") ) + ""; - menuItem += ""; - } - - menuItem += "
            • "; - - menu = pullRight ? menuItem + menu : menu + menuItem; - } - } - - toolbarMenu.html(menu); - - toolbarMenu.find("[title=\"Lowercase\"]").attr("title", settings.lang.toolbar.lowercase); - toolbarMenu.find("[title=\"ucwords\"]").attr("title", settings.lang.toolbar.ucwords); - - this.setToolbarHandler(); - this.setToolbarAutoFixed(); - - return this; - }, - - /** - * 工具栏图标事件处理对象序列 - * Get toolbar icons event handlers - * - * @param {Object} cm CodeMirror的实例对象 - * @param {String} name 要获取的事件处理器名称 - * @returns {Object} 返回处理对象序列 - */ - - dialogLockScreen : function() { - $.proxy(editormd.dialogLockScreen, this)(); - - return this; - }, - - dialogShowMask : function(dialog) { - $.proxy(editormd.dialogShowMask, this)(dialog); - - return this; - }, - - getToolbarHandles : function(name) { - var toolbarHandlers = this.toolbarHandlers = editormd.toolbarHandlers; - - return (name && typeof toolbarIconHandlers[name] !== "undefined") ? toolbarHandlers[name] : toolbarHandlers; - }, - - /** - * 工具栏图标事件处理器 - * Bind toolbar icons event handle - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setToolbarHandler : function() { - var _this = this; - var settings = this.settings; - - if (!settings.toolbar || settings.readOnly) { - return this; - } - - var toolbar = this.toolbar; - var cm = this.cm; - var classPrefix = this.classPrefix; - var toolbarIcons = this.toolbarIcons = toolbar.find("." + classPrefix + "menu > li > a"); - var toolbarIconHandlers = this.getToolbarHandles(); - - toolbarIcons.bind(editormd.mouseOrTouch("click", "touchend"), function(event) { - - var icon = $(this).children(".fa"); - var name = icon.attr("name"); - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (name === "") { - return ; - } - - _this.activeIcon = icon; - - if (typeof toolbarIconHandlers[name] !== "undefined") - { - $.proxy(toolbarIconHandlers[name], _this)(cm); - } - else - { - if (typeof settings.toolbarHandlers[name] !== "undefined") - { - $.proxy(settings.toolbarHandlers[name], _this)(cm, icon, cursor, selection); - } - } - - if (name !== "link" && name !== "reference-link" && name !== "image" && name !== "code-block" && - name !== "preformatted-text" && name !== "watch" && name !== "preview" && name !== "search" && name !== "fullscreen" && name !== "info") - { - cm.focus(); - } - - return false; - - }); - - return this; - }, - - /** - * 动态创建对话框 - * Creating custom dialogs - * - * @param {Object} options 配置项键值对 Key/Value - * @returns {dialog} 返回创建的dialog的jQuery实例对象 - */ - - createDialog : function(options) { - return $.proxy(editormd.createDialog, this)(options); - }, - - /** - * 创建关于Editor.md的对话框 - * Create about Editor.md dialog - * - * @returns {editormd} 返回editormd的实例对象 - */ - - createInfoDialog : function() { - var _this = this; - var editor = this.editor; - var classPrefix = this.classPrefix; - - var infoDialogHTML = [ - "
              ", - "
              ", - "

              " + editormd.title + "v" + editormd.version + "

              ", - "

              " + this.lang.description + "

              ", - "

              " + editormd.homePage + "

              ", - "

              Copyright © 2015 Pandao, The MIT License.

              ", - "
              ", - "", - "
              " - ].join("\n"); - - editor.append(infoDialogHTML); - - var infoDialog = this.infoDialog = editor.children("." + classPrefix + "dialog-info"); - - infoDialog.find("." + classPrefix + "dialog-close").bind(editormd.mouseOrTouch("click", "touchend"), function() { - _this.hideInfoDialog(); - }); - - infoDialog.css("border", (editormd.isIE8) ? "1px solid #ddd" : "").css("z-index", editormd.dialogZindex).show(); - - this.infoDialogPosition(); - - return this; - }, - - /** - * 关于Editor.md对话居中定位 - * Editor.md dialog position handle - * - * @returns {editormd} 返回editormd的实例对象 - */ - - infoDialogPosition : function() { - var infoDialog = this.infoDialog; - - var _infoDialogPosition = function() { - infoDialog.css({ - top : ($(window).height() - infoDialog.height()) / 2 + "px", - left : ($(window).width() - infoDialog.width()) / 2 + "px" - }); - }; - - _infoDialogPosition(); - - $(window).resize(_infoDialogPosition); - - return this; - }, - - /** - * 显示关于Editor.md - * Display about Editor.md dialog - * - * @returns {editormd} 返回editormd的实例对象 - */ - - showInfoDialog : function() { - - $("html,body").css("overflow-x", "hidden"); - - var _this = this; - var editor = this.editor; - var settings = this.settings; - var infoDialog = this.infoDialog = editor.children("." + this.classPrefix + "dialog-info"); - - if (infoDialog.length < 1) - { - this.createInfoDialog(); - } - - this.lockScreen(true); - - this.mask.css({ - opacity : settings.dialogMaskOpacity, - backgroundColor : settings.dialogMaskBgColor - }).show(); - - infoDialog.css("z-index", editormd.dialogZindex).show(); - - this.infoDialogPosition(); - - return this; - }, - - /** - * 隐藏关于Editor.md - * Hide about Editor.md dialog - * - * @returns {editormd} 返回editormd的实例对象 - */ - - hideInfoDialog : function() { - $("html,body").css("overflow-x", ""); - this.infoDialog.hide(); - this.mask.hide(); - this.lockScreen(false); - - return this; - }, - - /** - * 锁屏 - * lock screen - * - * @param {Boolean} lock Boolean 布尔值,是否锁屏 - * @returns {editormd} 返回editormd的实例对象 - */ - - lockScreen : function(lock) { - editormd.lockScreen(lock); - this.resize(); - - return this; - }, - - /** - * 编辑器界面重建,用于动态语言包或模块加载等 - * Recreate editor - * - * @returns {editormd} 返回editormd的实例对象 - */ - - recreate : function() { - var _this = this; - var editor = this.editor; - var settings = this.settings; - - this.codeMirror.remove(); - - this.setCodeMirror(); - - if (!settings.readOnly) - { - if (editor.find(".editormd-dialog").length > 0) { - editor.find(".editormd-dialog").remove(); - } - - if (settings.toolbar) - { - this.getToolbarHandles(); - this.setToolbar(); - } - } - - this.loadedDisplay(true); - - return this; - }, - - /** - * 高亮预览HTML的pre代码部分 - * highlight of preview codes - * - * @returns {editormd} 返回editormd的实例对象 - */ - - previewCodeHighlight : function() { - var settings = this.settings; - var previewContainer = this.previewContainer; - - if (settings.previewCodeHighlight) - { - previewContainer.find("pre").addClass("prettyprint linenums"); - - if (typeof prettyPrint !== "undefined") - { - prettyPrint(); - } - } - - return this; - }, - - /** - * 解析TeX(KaTeX)科学公式 - * TeX(KaTeX) Renderer - * - * @returns {editormd} 返回editormd的实例对象 - */ - - katexRender : function() { - - if (timer === null) - { - return this; - } - - this.previewContainer.find("." + editormd.classNames.tex).each(function(){ - var tex = $(this); - editormd.$katex.render(tex.text(), tex[0]); - - tex.find(".katex").css("font-size", "1.6em"); - }); - - return this; - }, - - /** - * 解析和渲染流程图及时序图 - * FlowChart and SequenceDiagram Renderer - * - * @returns {editormd} 返回editormd的实例对象 - */ - - flowChartAndSequenceDiagramRender : function() { - var $this = this; - var settings = this.settings; - var previewContainer = this.previewContainer; - - if (editormd.isIE8) { - return this; - } - - if (settings.flowChart) { - if (flowchartTimer === null) { - return this; - } - - previewContainer.find(".flowchart").flowChart(); - } - - if (settings.sequenceDiagram) { - previewContainer.find(".sequence-diagram").sequenceDiagram({theme: "simple"}); - } - - var preview = $this.preview; - var codeMirror = $this.codeMirror; - var codeView = codeMirror.find(".CodeMirror-scroll"); - - var height = codeView.height(); - var scrollTop = codeView.scrollTop(); - var percent = (scrollTop / codeView[0].scrollHeight); - var tocHeight = 0; - - preview.find(".markdown-toc-list").each(function(){ - tocHeight += $(this).height(); - }); - - var tocMenuHeight = preview.find(".editormd-toc-menu").height(); - tocMenuHeight = (!tocMenuHeight) ? 0 : tocMenuHeight; - - if (scrollTop === 0) - { - preview.scrollTop(0); - } - else if (scrollTop + height >= codeView[0].scrollHeight - 16) - { - preview.scrollTop(preview[0].scrollHeight); - } - else - { - preview.scrollTop((preview[0].scrollHeight + tocHeight + tocMenuHeight) * percent); - } - - return this; - }, - - /** - * 注册键盘快捷键处理 - * Register CodeMirror keyMaps (keyboard shortcuts). - * - * @param {Object} keyMap KeyMap key/value {"(Ctrl/Shift/Alt)-Key" : function(){}} - * @returns {editormd} return this - */ - - registerKeyMaps : function(keyMap) { - - var _this = this; - var cm = this.cm; - var settings = this.settings; - var toolbarHandlers = editormd.toolbarHandlers; - var disabledKeyMaps = settings.disabledKeyMaps; - - keyMap = keyMap || null; - - if (keyMap) - { - for (var i in keyMap) - { - if ($.inArray(i, disabledKeyMaps) < 0) - { - var map = {}; - map[i] = keyMap[i]; - - cm.addKeyMap(keyMap); - } - } - } - else - { - for (var k in editormd.keyMaps) - { - var _keyMap = editormd.keyMaps[k]; - var handle = (typeof _keyMap === "string") ? $.proxy(toolbarHandlers[_keyMap], _this) : $.proxy(_keyMap, _this); - - if ($.inArray(k, ["F9", "F10", "F11"]) < 0 && $.inArray(k, disabledKeyMaps) < 0) - { - var _map = {}; - _map[k] = handle; - - cm.addKeyMap(_map); - } - } - - $(window).keydown(function(event) { - - var keymaps = { - "120" : "F9", - "121" : "F10", - "122" : "F11" - }; - - if ( $.inArray(keymaps[event.keyCode], disabledKeyMaps) < 0 ) - { - switch (event.keyCode) - { - case 120: - $.proxy(toolbarHandlers["watch"], _this)(); - return false; - break; - - case 121: - $.proxy(toolbarHandlers["preview"], _this)(); - return false; - break; - - case 122: - $.proxy(toolbarHandlers["fullscreen"], _this)(); - return false; - break; - - default: - break; - } - } - }); - } - - return this; - }, - - /** - * 绑定同步滚动 - * - * @returns {editormd} return this - */ - - bindScrollEvent : function() { - - var _this = this; - var preview = this.preview; - var settings = this.settings; - var codeMirror = this.codeMirror; - var mouseOrTouch = editormd.mouseOrTouch; - - if (!settings.syncScrolling) { - return this; - } - - var cmBindScroll = function() { - codeMirror.find(".CodeMirror-scroll").bind(mouseOrTouch("scroll", "touchmove"), function(event) { - var height = $(this).height(); - var scrollTop = $(this).scrollTop(); - var percent = (scrollTop / $(this)[0].scrollHeight); - - var tocHeight = 0; - - preview.find(".markdown-toc-list").each(function(){ - tocHeight += $(this).height(); - }); - - var tocMenuHeight = preview.find(".editormd-toc-menu").height(); - tocMenuHeight = (!tocMenuHeight) ? 0 : tocMenuHeight; - - if (scrollTop === 0) - { - preview.scrollTop(0); - } - else if (scrollTop + height >= $(this)[0].scrollHeight - 16) - { - preview.scrollTop(preview[0].scrollHeight); - } - else - { - preview.scrollTop((preview[0].scrollHeight + tocHeight + tocMenuHeight) * percent); - } - - $.proxy(settings.onscroll, _this)(event); - }); - }; - - var cmUnbindScroll = function() { - codeMirror.find(".CodeMirror-scroll").unbind(mouseOrTouch("scroll", "touchmove")); - }; - - var previewBindScroll = function() { - - preview.bind(mouseOrTouch("scroll", "touchmove"), function(event) { - var height = $(this).height(); - var scrollTop = $(this).scrollTop(); - var percent = (scrollTop / $(this)[0].scrollHeight); - var codeView = codeMirror.find(".CodeMirror-scroll"); - - if(scrollTop === 0) - { - codeView.scrollTop(0); - } - else if (scrollTop + height >= $(this)[0].scrollHeight) - { - codeView.scrollTop(codeView[0].scrollHeight); - } - else - { - codeView.scrollTop(codeView[0].scrollHeight * percent); - } - - $.proxy(settings.onpreviewscroll, _this)(event); - }); - - }; - - var previewUnbindScroll = function() { - preview.unbind(mouseOrTouch("scroll", "touchmove")); - }; - - codeMirror.bind({ - mouseover : cmBindScroll, - mouseout : cmUnbindScroll, - touchstart : cmBindScroll, - touchend : cmUnbindScroll - }); - - if (settings.syncScrolling === "single") { - return this; - } - - preview.bind({ - mouseover : previewBindScroll, - mouseout : previewUnbindScroll, - touchstart : previewBindScroll, - touchend : previewUnbindScroll - }); - - return this; - }, - - bindChangeEvent : function() { - - var _this = this; - var cm = this.cm; - var settings = this.settings; - - if (!settings.syncScrolling) { - return this; - } - - cm.on("change", function(_cm, changeObj) { - - if (settings.watch) - { - _this.previewContainer.css("padding", settings.autoHeight ? "20px 20px 50px 40px" : "20px"); - } - - timer = setTimeout(function() { - clearTimeout(timer); - _this.save(); - timer = null; - }, settings.delay); - }); - - return this; - }, - - /** - * 加载队列完成之后的显示处理 - * Display handle of the module queues loaded after. - * - * @param {Boolean} recreate 是否为重建编辑器 - * @returns {editormd} 返回editormd的实例对象 - */ - - loadedDisplay : function(recreate) { - - recreate = recreate || false; - - var _this = this; - var editor = this.editor; - var preview = this.preview; - var settings = this.settings; - - this.containerMask.hide(); - - this.save(); - - if (settings.watch) { - preview.show(); - } - - editor.data("oldWidth", editor.width()).data("oldHeight", editor.height()); // 为了兼容Zepto - - this.resize(); - this.registerKeyMaps(); - - $(window).resize(function(){ - _this.resize(); - }); - - this.bindScrollEvent().bindChangeEvent(); - - if (!recreate) - { - $.proxy(settings.onload, this)(); - } - - this.state.loaded = true; - - return this; - }, - - /** - * 设置编辑器的宽度 - * Set editor width - * - * @param {Number|String} width 编辑器宽度值 - * @returns {editormd} 返回editormd的实例对象 - */ - - width : function(width) { - - this.editor.css("width", (typeof width === "number") ? width + "px" : width); - this.resize(); - - return this; - }, - - /** - * 设置编辑器的高度 - * Set editor height - * - * @param {Number|String} height 编辑器高度值 - * @returns {editormd} 返回editormd的实例对象 - */ - - height : function(height) { - - this.editor.css("height", (typeof height === "number") ? height + "px" : height); - this.resize(); - - return this; - }, - - /** - * 调整编辑器的尺寸和布局 - * Resize editor layout - * - * @param {Number|String} [width=null] 编辑器宽度值 - * @param {Number|String} [height=null] 编辑器高度值 - * @returns {editormd} 返回editormd的实例对象 - */ - - resize : function(width, height) { - - width = width || null; - height = height || null; - - var state = this.state; - var editor = this.editor; - var preview = this.preview; - var toolbar = this.toolbar; - var settings = this.settings; - var codeMirror = this.codeMirror; - - if (width) - { - editor.css("width", (typeof width === "number") ? width + "px" : width); - } - - if (settings.autoHeight && !state.fullscreen && !state.preview) - { - editor.css("height", "auto"); - codeMirror.css("height", "auto"); - } - else - { - if (height) - { - editor.css("height", (typeof height === "number") ? height + "px" : height); - } - - if (state.fullscreen) - { - editor.height($(window).height()); - } - - if (settings.toolbar && !settings.readOnly) - { - codeMirror.css("margin-top", toolbar.height() + 1).height(editor.height() - toolbar.height()); - } - else - { - codeMirror.css("margin-top", 0).height(editor.height()); - } - } - - if(settings.watch) - { - codeMirror.width(editor.width() / 2); - preview.width((!state.preview) ? editor.width() / 2 : editor.width()); - - this.previewContainer.css("padding", settings.autoHeight ? "20px 20px 50px 40px" : "20px"); - - if (settings.toolbar && !settings.readOnly) - { - preview.css("top", toolbar.height() + 1); - } - else - { - preview.css("top", 0); - } - - if (settings.autoHeight && !state.fullscreen && !state.preview) - { - preview.height(""); - } - else - { - var previewHeight = (settings.toolbar && !settings.readOnly) ? editor.height() - toolbar.height() : editor.height(); - - preview.height(previewHeight); - } - } - else - { - codeMirror.width(editor.width()); - preview.hide(); - } - - if (state.loaded) - { - $.proxy(settings.onresize, this)(); - } - - return this; - }, - - /** - * 解析和保存Markdown代码 - * Parse & Saving Markdown source code - * - * @returns {editormd} 返回editormd的实例对象 - */ - - save : function() { - - var _this = this; - var state = this.state; - var settings = this.settings; - - if (timer === null && !(!settings.watch && state.preview)) - { - return this; - } - - var cm = this.cm; - var cmValue = cm.getValue(); - var previewContainer = this.previewContainer; - - if (settings.mode !== "gfm" && settings.mode !== "markdown") - { - this.markdownTextarea.val(cmValue); - - return this; - } - - var marked = editormd.$marked; - var markdownToC = this.markdownToC = []; - var rendererOptions = this.markedRendererOptions = { - toc : settings.toc, - tocm : settings.tocm, - tocStartLevel : settings.tocStartLevel, - pageBreak : settings.pageBreak, - taskList : settings.taskList, - emoji : settings.emoji, - tex : settings.tex, - atLink : settings.atLink, // for @link - emailLink : settings.emailLink, // for mail address auto link - flowChart : settings.flowChart, - sequenceDiagram : settings.sequenceDiagram, - previewCodeHighlight : settings.previewCodeHighlight, - }; - - var markedOptions = this.markedOptions = { - renderer : editormd.markedRenderer(markdownToC, rendererOptions), - gfm : true, - tables : true, - breaks : true, - pedantic : false, - sanitize : (settings.htmlDecode) ? false : true, // 关闭忽略HTML标签,即开启识别HTML标签,默认为false - smartLists : true, - smartypants : true - }; - - marked.setOptions(markedOptions); - - var newMarkdownDoc = editormd.$marked(cmValue, markedOptions); - - //console.info("cmValue", cmValue, newMarkdownDoc); - - newMarkdownDoc = editormd.filterHTMLTags(newMarkdownDoc, settings.htmlDecode); - - //console.error("cmValue", cmValue, newMarkdownDoc); - - this.markdownTextarea.text(cmValue); - - cm.save(); - - if (settings.saveHTMLToTextarea) - { - this.htmlTextarea.text(newMarkdownDoc); - } - - if(settings.watch || (!settings.watch && state.preview)) - { - previewContainer.html(newMarkdownDoc); - - this.previewCodeHighlight(); - - if (settings.toc) - { - var tocContainer = (settings.tocContainer === "") ? previewContainer : $(settings.tocContainer); - var tocMenu = tocContainer.find("." + this.classPrefix + "toc-menu"); - - tocContainer.attr("previewContainer", (settings.tocContainer === "") ? "true" : "false"); - - if (settings.tocContainer !== "" && tocMenu.length > 0) - { - tocMenu.remove(); - } - - editormd.markdownToCRenderer(markdownToC, tocContainer, settings.tocDropdown, settings.tocStartLevel); - - if (settings.tocDropdown || tocContainer.find("." + this.classPrefix + "toc-menu").length > 0) - { - editormd.tocDropdownMenu(tocContainer, (settings.tocTitle !== "") ? settings.tocTitle : this.lang.tocTitle); - } - - if (settings.tocContainer !== "") - { - previewContainer.find(".markdown-toc").css("border", "none"); - } - } - - if (settings.tex) - { - if (!editormd.kaTeXLoaded && settings.autoLoadModules) - { - editormd.loadKaTeX(function() { - editormd.$katex = katex; - editormd.kaTeXLoaded = true; - _this.katexRender(); - }); - } - else - { - editormd.$katex = katex; - this.katexRender(); - } - } - - if (settings.flowChart || settings.sequenceDiagram) - { - flowchartTimer = setTimeout(function(){ - clearTimeout(flowchartTimer); - _this.flowChartAndSequenceDiagramRender(); - flowchartTimer = null; - }, 10); - } - - if (state.loaded) - { - $.proxy(settings.onchange, this)(); - } - } - - return this; - }, - - /** - * 聚焦光标位置 - * Focusing the cursor position - * - * @returns {editormd} 返回editormd的实例对象 - */ - - focus : function() { - this.cm.focus(); - - return this; - }, - - /** - * 设置光标的位置 - * Set cursor position - * - * @param {Object} cursor 要设置的光标位置键值对象,例:{line:1, ch:0} - * @returns {editormd} 返回editormd的实例对象 - */ - - setCursor : function(cursor) { - this.cm.setCursor(cursor); - - return this; - }, - - /** - * 获取当前光标的位置 - * Get the current position of the cursor - * - * @returns {Cursor} 返回一个光标Cursor对象 - */ - - getCursor : function() { - return this.cm.getCursor(); - }, - - /** - * 设置光标选中的范围 - * Set cursor selected ranges - * - * @param {Object} from 开始位置的光标键值对象,例:{line:1, ch:0} - * @param {Object} to 结束位置的光标键值对象,例:{line:1, ch:0} - * @returns {editormd} 返回editormd的实例对象 - */ - - setSelection : function(from, to) { - - this.cm.setSelection(from, to); - - return this; - }, - - /** - * 获取光标选中的文本 - * Get the texts from cursor selected - * - * @returns {String} 返回选中文本的字符串形式 - */ - - getSelection : function() { - return this.cm.getSelection(); - }, - - /** - * 设置光标选中的文本范围 - * Set the cursor selection ranges - * - * @param {Array} ranges cursor selection ranges array - * @returns {Array} return this - */ - - setSelections : function(ranges) { - this.cm.setSelections(ranges); - - return this; - }, - - /** - * 获取光标选中的文本范围 - * Get the cursor selection ranges - * - * @returns {Array} return selection ranges array - */ - - getSelections : function() { - return this.cm.getSelections(); - }, - - /** - * 替换当前光标选中的文本或在当前光标处插入新字符 - * Replace the text at the current cursor selected or insert a new character at the current cursor position - * - * @param {String} value 要插入的字符值 - * @returns {editormd} 返回editormd的实例对象 - */ - - replaceSelection : function(value) { - this.cm.replaceSelection(value); - - return this; - }, - - /** - * 在当前光标处插入新字符 - * Insert a new character at the current cursor position - * - * 同replaceSelection()方法 - * With the replaceSelection() method - * - * @param {String} value 要插入的字符值 - * @returns {editormd} 返回editormd的实例对象 - */ - - insertValue : function(value) { - this.replaceSelection(value); - - return this; - }, - - /** - * 追加markdown - * append Markdown to editor - * - * @param {String} md 要追加的markdown源文档 - * @returns {editormd} 返回editormd的实例对象 - */ - - appendMarkdown : function(md) { - var settings = this.settings; - var cm = this.cm; - - cm.setValue(cm.getValue() + md); - - return this; - }, - - /** - * 设置和传入编辑器的markdown源文档 - * Set Markdown source document - * - * @param {String} md 要传入的markdown源文档 - * @returns {editormd} 返回editormd的实例对象 - */ - - setMarkdown : function(md) { - this.cm.setValue(md || this.settings.markdown); - - return this; - }, - - /** - * 获取编辑器的markdown源文档 - * Set Editor.md markdown/CodeMirror value - * - * @returns {editormd} 返回editormd的实例对象 - */ - - getMarkdown : function() { - return this.cm.getValue(); - }, - - /** - * 获取编辑器的源文档 - * Get CodeMirror value - * - * @returns {editormd} 返回editormd的实例对象 - */ - - getValue : function() { - return this.cm.getValue(); - }, - - /** - * 设置编辑器的源文档 - * Set CodeMirror value - * - * @param {String} value set code/value/string/text - * @returns {editormd} 返回editormd的实例对象 - */ - - setValue : function(value) { - this.cm.setValue(value); - - return this; - }, - - /** - * 清空编辑器 - * Empty CodeMirror editor container - * - * @returns {editormd} 返回editormd的实例对象 - */ - - clear : function() { - this.cm.setValue(""); - - return this; - }, - - /** - * 获取解析后存放在Textarea的HTML源码 - * Get parsed html code from Textarea - * - * @returns {String} 返回HTML源码 - */ - - getHTML : function() { - if (!this.settings.saveHTMLToTextarea) - { - alert("Error: settings.saveHTMLToTextarea == false"); - - return false; - } - - return this.htmlTextarea.val(); - }, - - /** - * getHTML()的别名 - * getHTML (alias) - * - * @returns {String} Return html code 返回HTML源码 - */ - - getTextareaSavedHTML : function() { - return this.getHTML(); - }, - - /** - * 获取预览窗口的HTML源码 - * Get html from preview container - * - * @returns {editormd} 返回editormd的实例对象 - */ - - getPreviewedHTML : function() { - if (!this.settings.watch) - { - alert("Error: settings.watch == false"); - - return false; - } - - return this.previewContainer.html(); - }, - - /** - * 开启实时预览 - * Enable real-time watching - * - * @returns {editormd} 返回editormd的实例对象 - */ - - watch : function(callback) { - var settings = this.settings; - - if ($.inArray(settings.mode, ["gfm", "markdown"]) < 0) - { - return this; - } - - this.state.watching = settings.watch = true; - this.preview.show(); - - if (this.toolbar) - { - var watchIcon = settings.toolbarIconsClass.watch; - var unWatchIcon = settings.toolbarIconsClass.unwatch; - - var icon = this.toolbar.find(".fa[name=watch]"); - icon.parent().attr("title", settings.lang.toolbar.watch); - icon.removeClass(unWatchIcon).addClass(watchIcon); - } - - this.codeMirror.css("border-right", "1px solid #ddd").width(this.editor.width() / 2); - - timer = 0; - - this.save().resize(); - - if (!settings.onwatch) - { - settings.onwatch = callback || function() {}; - } - - $.proxy(settings.onwatch, this)(); - - return this; - }, - - /** - * 关闭实时预览 - * Disable real-time watching - * - * @returns {editormd} 返回editormd的实例对象 - */ - - unwatch : function(callback) { - var settings = this.settings; - this.state.watching = settings.watch = false; - this.preview.hide(); - - if (this.toolbar) - { - var watchIcon = settings.toolbarIconsClass.watch; - var unWatchIcon = settings.toolbarIconsClass.unwatch; - - var icon = this.toolbar.find(".fa[name=watch]"); - icon.parent().attr("title", settings.lang.toolbar.unwatch); - icon.removeClass(watchIcon).addClass(unWatchIcon); - } - - this.codeMirror.css("border-right", "none").width(this.editor.width()); - - this.resize(); - - if (!settings.onunwatch) - { - settings.onunwatch = callback || function() {}; - } - - $.proxy(settings.onunwatch, this)(); - - return this; - }, - - /** - * 显示编辑器 - * Show editor - * - * @param {Function} [callback=function()] 回调函数 - * @returns {editormd} 返回editormd的实例对象 - */ - - show : function(callback) { - callback = callback || function() {}; - - var _this = this; - this.editor.show(0, function() { - $.proxy(callback, _this)(); - }); - - return this; - }, - - /** - * 隐藏编辑器 - * Hide editor - * - * @param {Function} [callback=function()] 回调函数 - * @returns {editormd} 返回editormd的实例对象 - */ - - hide : function(callback) { - callback = callback || function() {}; - - var _this = this; - this.editor.hide(0, function() { - $.proxy(callback, _this)(); - }); - - return this; - }, - - /** - * 隐藏编辑器部分,只预览HTML - * Enter preview html state - * - * @returns {editormd} 返回editormd的实例对象 - */ - - previewing : function() { - - var _this = this; - var editor = this.editor; - var preview = this.preview; - var toolbar = this.toolbar; - var settings = this.settings; - var codeMirror = this.codeMirror; - var previewContainer = this.previewContainer; - - if ($.inArray(settings.mode, ["gfm", "markdown"]) < 0) { - return this; - } - - if (settings.toolbar && toolbar) { - toolbar.toggle(); - toolbar.find(".fa[name=preview]").toggleClass("active"); - } - - codeMirror.toggle(); - - var escHandle = function(event) { - if (event.shiftKey && event.keyCode === 27) { - _this.previewed(); - } - }; - - if (codeMirror.css("display") === "none") // 为了兼容Zepto,而不使用codeMirror.is(":hidden") - { - this.state.preview = true; - - if (this.state.fullscreen) { - preview.css("background", "#fff"); - } - - editor.find("." + this.classPrefix + "preview-close-btn").show().bind(editormd.mouseOrTouch("click", "touchend"), function(){ - _this.previewed(); - }); - - if (!settings.watch) - { - this.save(); - } - else - { - previewContainer.css("padding", ""); - } - - previewContainer.addClass(this.classPrefix + "preview-active"); - - preview.show().css({ - position : "", - top : 0, - width : editor.width(), - height : (settings.autoHeight && !this.state.fullscreen) ? "auto" : editor.height() - }); - - if (this.state.loaded) - { - $.proxy(settings.onpreviewing, this)(); - } - - $(window).bind("keyup", escHandle); - } - else - { - $(window).unbind("keyup", escHandle); - this.previewed(); - } - }, - - /** - * 显示编辑器部分,退出只预览HTML - * Exit preview html state - * - * @returns {editormd} 返回editormd的实例对象 - */ - - previewed : function() { - - var editor = this.editor; - var preview = this.preview; - var toolbar = this.toolbar; - var settings = this.settings; - var previewContainer = this.previewContainer; - var previewCloseBtn = editor.find("." + this.classPrefix + "preview-close-btn"); - - this.state.preview = false; - - this.codeMirror.show(); - - if (settings.toolbar) { - toolbar.show(); - } - - preview[(settings.watch) ? "show" : "hide"](); - - previewCloseBtn.hide().unbind(editormd.mouseOrTouch("click", "touchend")); - - previewContainer.removeClass(this.classPrefix + "preview-active"); - - if (settings.watch) - { - previewContainer.css("padding", "20px"); - } - - preview.css({ - background : null, - position : "absolute", - width : editor.width() / 2, - height : (settings.autoHeight && !this.state.fullscreen) ? "auto" : editor.height() - toolbar.height(), - top : (settings.toolbar) ? toolbar.height() : 0 - }); - - if (this.state.loaded) - { - $.proxy(settings.onpreviewed, this)(); - } - - return this; - }, - - /** - * 编辑器全屏显示 - * Fullscreen show - * - * @returns {editormd} 返回editormd的实例对象 - */ - - fullscreen : function() { - - var _this = this; - var state = this.state; - var editor = this.editor; - var preview = this.preview; - var toolbar = this.toolbar; - var settings = this.settings; - var fullscreenClass = this.classPrefix + "fullscreen"; - - if (toolbar) { - toolbar.find(".fa[name=fullscreen]").parent().toggleClass("active"); - } - - var escHandle = function(event) { - if (!event.shiftKey && event.keyCode === 27) - { - if (state.fullscreen) - { - _this.fullscreenExit(); - } - } - }; - - if (!editor.hasClass(fullscreenClass)) - { - state.fullscreen = true; - - $("html,body").css("overflow", "hidden"); - - editor.css({ - width : $(window).width(), - height : $(window).height() - }).addClass(fullscreenClass); - - this.resize(); - - $.proxy(settings.onfullscreen, this)(); - - $(window).bind("keyup", escHandle); - } - else - { - $(window).unbind("keyup", escHandle); - this.fullscreenExit(); - } - - return this; - }, - - /** - * 编辑器退出全屏显示 - * Exit fullscreen state - * - * @returns {editormd} 返回editormd的实例对象 - */ - - fullscreenExit : function() { - - var editor = this.editor; - var settings = this.settings; - var toolbar = this.toolbar; - var fullscreenClass = this.classPrefix + "fullscreen"; - - this.state.fullscreen = false; - - if (toolbar) { - toolbar.find(".fa[name=fullscreen]").parent().removeClass("active"); - } - - $("html,body").css("overflow", ""); - - editor.css({ - width : editor.data("oldWidth"), - height : editor.data("oldHeight") - }).removeClass(fullscreenClass); - - this.resize(); - - $.proxy(settings.onfullscreenExit, this)(); - - return this; - }, - - /** - * 加载并执行插件 - * Load and execute the plugin - * - * @param {String} name plugin name / function name - * @param {String} path plugin load path - * @returns {editormd} 返回editormd的实例对象 - */ - - executePlugin : function(name, path) { - - var _this = this; - var cm = this.cm; - var settings = this.settings; - - path = settings.pluginPath + path; - - if (typeof define === "function") - { - if (typeof this[name] === "undefined") - { - alert("Error: " + name + " plugin is not found, you are not load this plugin."); - - return this; - } - - this[name](cm); - - return this; - } - - if ($.inArray(path, editormd.loadFiles.plugin) < 0) - { - editormd.loadPlugin(path, function() { - editormd.loadPlugins[name] = _this[name]; - _this[name](cm); - }); - } - else - { - $.proxy(editormd.loadPlugins[name], this)(cm); - } - - return this; - }, - - /** - * 搜索替换 - * Search & replace - * - * @param {String} command CodeMirror serach commands, "find, fintNext, fintPrev, clearSearch, replace, replaceAll" - * @returns {editormd} return this - */ - - search : function(command) { - var settings = this.settings; - - if (!settings.searchReplace) - { - alert("Error: settings.searchReplace == false"); - return this; - } - - if (!settings.readOnly) - { - this.cm.execCommand(command || "find"); - } - - return this; - }, - - searchReplace : function() { - this.search("replace"); - - return this; - }, - - searchReplaceAll : function() { - this.search("replaceAll"); - - return this; - } - }; - - editormd.fn.init.prototype = editormd.fn; - - /** - * 锁屏 - * lock screen when dialog opening - * - * @returns {void} - */ - - editormd.dialogLockScreen = function() { - var settings = this.settings || {dialogLockScreen : true}; - - if (settings.dialogLockScreen) - { - $("html,body").css("overflow", "hidden"); - this.resize(); - } - }; - - /** - * 显示透明背景层 - * Display mask layer when dialog opening - * - * @param {Object} dialog dialog jQuery object - * @returns {void} - */ - - editormd.dialogShowMask = function(dialog) { - var editor = this.editor; - var settings = this.settings || {dialogShowMask : true}; - - dialog.css({ - top : ($(window).height() - dialog.height()) / 2 + "px", - left : ($(window).width() - dialog.width()) / 2 + "px" - }); - - if (settings.dialogShowMask) { - editor.children("." + this.classPrefix + "mask").css("z-index", parseInt(dialog.css("z-index")) - 1).show(); - } - }; - - editormd.toolbarHandlers = { - undo : function() { - this.cm.undo(); - }, - - redo : function() { - this.cm.redo(); - }, - - bold : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("**" + selection + "**"); - - if(selection === "") { - cm.setCursor(cursor.line, cursor.ch + 2); - } - }, - - del : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("~~" + selection + "~~"); - - if(selection === "") { - cm.setCursor(cursor.line, cursor.ch + 2); - } - }, - - italic : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("*" + selection + "*"); - - if(selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); - } - }, - - quote : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("> " + selection); - cm.setCursor(cursor.line, cursor.ch + 2); - } - else - { - cm.replaceSelection("> " + selection); - } - - //cm.replaceSelection("> " + selection); - //cm.setCursor(cursor.line, (selection === "") ? cursor.ch + 2 : cursor.ch + selection.length + 2); - }, - - ucfirst : function() { - var cm = this.cm; - var selection = cm.getSelection(); - var selections = cm.listSelections(); - - cm.replaceSelection(editormd.firstUpperCase(selection)); - cm.setSelections(selections); - }, - - ucwords : function() { - var cm = this.cm; - var selection = cm.getSelection(); - var selections = cm.listSelections(); - - cm.replaceSelection(editormd.wordsFirstUpperCase(selection)); - cm.setSelections(selections); - }, - - uppercase : function() { - var cm = this.cm; - var selection = cm.getSelection(); - var selections = cm.listSelections(); - - cm.replaceSelection(selection.toUpperCase()); - cm.setSelections(selections); - }, - - lowercase : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - var selections = cm.listSelections(); - - cm.replaceSelection(selection.toLowerCase()); - cm.setSelections(selections); - }, - - h1 : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("# " + selection); - cm.setCursor(cursor.line, cursor.ch + 2); - } - else - { - cm.replaceSelection("# " + selection); - } - }, - - h2 : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("## " + selection); - cm.setCursor(cursor.line, cursor.ch + 3); - } - else - { - cm.replaceSelection("## " + selection); - } - }, - - h3 : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("### " + selection); - cm.setCursor(cursor.line, cursor.ch + 4); - } - else - { - cm.replaceSelection("### " + selection); - } - }, - - h4 : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("#### " + selection); - cm.setCursor(cursor.line, cursor.ch + 5); - } - else - { - cm.replaceSelection("#### " + selection); - } - }, - - h5 : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("##### " + selection); - cm.setCursor(cursor.line, cursor.ch + 6); - } - else - { - cm.replaceSelection("##### " + selection); - } - }, - - h6 : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("###### " + selection); - cm.setCursor(cursor.line, cursor.ch + 7); - } - else - { - cm.replaceSelection("###### " + selection); - } - }, - - "list-ul" : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (selection === "") - { - cm.replaceSelection("- " + selection); - } - else - { - var selectionText = selection.split("\n"); - - for (var i = 0, len = selectionText.length; i < len; i++) - { - selectionText[i] = (selectionText[i] === "") ? "" : "- " + selectionText[i]; - } - - cm.replaceSelection(selectionText.join("\n")); - } - }, - - "list-ol" : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if(selection === "") - { - cm.replaceSelection("1. " + selection); - } - else - { - var selectionText = selection.split("\n"); - - for (var i = 0, len = selectionText.length; i < len; i++) - { - selectionText[i] = (selectionText[i] === "") ? "" : (i+1) + ". " + selectionText[i]; - } - - cm.replaceSelection(selectionText.join("\n")); - } - }, - - hr : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection(((cursor.ch !== 0) ? "\n\n" : "\n") + "------------\n\n"); - }, - - tex : function() { - if (!this.settings.tex) - { - alert("settings.tex === false"); - return this; - } - - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("$$" + selection + "$$"); - - if(selection === "") { - cm.setCursor(cursor.line, cursor.ch + 2); - } - }, - - link : function() { - this.executePlugin("linkDialog", "link-dialog/link-dialog"); - }, - - "reference-link" : function() { - this.executePlugin("referenceLinkDialog", "reference-link-dialog/reference-link-dialog"); - }, - - pagebreak : function() { - if (!this.settings.pageBreak) - { - alert("settings.pageBreak === false"); - return this; - } - - var cm = this.cm; - var selection = cm.getSelection(); - - cm.replaceSelection("\r\n[========]\r\n"); - }, - - image : function() { - this.executePlugin("imageDialog", "image-dialog/image-dialog"); - }, - - code : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("`" + selection + "`"); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); - } - }, - - "code-block" : function() { - this.executePlugin("codeBlockDialog", "code-block-dialog/code-block-dialog"); - }, - - "preformatted-text" : function() { - this.executePlugin("preformattedTextDialog", "preformatted-text-dialog/preformatted-text-dialog"); - }, - - table : function() { - this.executePlugin("tableDialog", "table-dialog/table-dialog"); - }, - - datetime : function() { - var cm = this.cm; - var selection = cm.getSelection(); - var date = new Date(); - var langName = this.settings.lang.name; - var datefmt = editormd.dateFormat() + " " + editormd.dateFormat((langName === "zh-cn" || langName === "zh-tw") ? "cn-week-day" : "week-day"); - - cm.replaceSelection(datefmt); - }, - - emoji : function() { - this.executePlugin("emojiDialog", "emoji-dialog/emoji-dialog"); - }, - - "html-entities" : function() { - this.executePlugin("htmlEntitiesDialog", "html-entities-dialog/html-entities-dialog"); - }, - - "goto-line" : function() { - this.executePlugin("gotoLineDialog", "goto-line-dialog/goto-line-dialog"); - }, - - watch : function() { - this[this.settings.watch ? "unwatch" : "watch"](); - }, - - preview : function() { - this.previewing(); - }, - - fullscreen : function() { - this.fullscreen(); - }, - - clear : function() { - this.clear(); - }, - - search : function() { - this.search(); - }, - - help : function() { - this.executePlugin("helpDialog", "help-dialog/help-dialog"); - }, - - info : function() { - this.showInfoDialog(); - } - }; - - editormd.keyMaps = { - "Ctrl-1" : "h1", - "Ctrl-2" : "h2", - "Ctrl-3" : "h3", - "Ctrl-4" : "h4", - "Ctrl-5" : "h5", - "Ctrl-6" : "h6", - "Ctrl-B" : "bold", // if this is string == editormd.toolbarHandlers.xxxx - "Ctrl-D" : "datetime", - - "Ctrl-E" : function() { // emoji - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (!this.settings.emoji) - { - alert("Error: settings.emoji == false"); - return ; - } - - cm.replaceSelection(":" + selection + ":"); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); - } - }, - "Ctrl-Alt-G" : "goto-line", - "Ctrl-H" : "hr", - "Ctrl-I" : "italic", - "Ctrl-K" : "code", - - "Ctrl-L" : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - var title = (selection === "") ? "" : " \""+selection+"\""; - - cm.replaceSelection("[" + selection + "]("+title+")"); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); - } - }, - "Ctrl-U" : "list-ul", - - "Shift-Ctrl-A" : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (!this.settings.atLink) - { - alert("Error: settings.atLink == false"); - return ; - } - - cm.replaceSelection("@" + selection); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); - } - }, - - "Shift-Ctrl-C" : "code", - "Shift-Ctrl-Q" : "quote", - "Shift-Ctrl-S" : "del", - "Shift-Ctrl-K" : "tex", // KaTeX - - "Shift-Alt-C" : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection(["```", selection, "```"].join("\n")); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 3); - } - }, - - "Shift-Ctrl-Alt-C" : "code-block", - "Shift-Ctrl-H" : "html-entities", - "Shift-Alt-H" : "help", - "Shift-Ctrl-E" : "emoji", - "Shift-Ctrl-U" : "uppercase", - "Shift-Alt-U" : "ucwords", - "Shift-Ctrl-Alt-U" : "ucfirst", - "Shift-Alt-L" : "lowercase", - - "Shift-Ctrl-I" : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - var title = (selection === "") ? "" : " \""+selection+"\""; - - cm.replaceSelection("![" + selection + "]("+title+")"); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 4); - } - }, - - "Shift-Ctrl-Alt-I" : "image", - "Shift-Ctrl-L" : "link", - "Shift-Ctrl-O" : "list-ol", - "Shift-Ctrl-P" : "preformatted-text", - "Shift-Ctrl-T" : "table", - "Shift-Alt-P" : "pagebreak", - "F9" : "watch", - "F10" : "preview", - "F11" : "fullscreen", - }; - - /** - * 清除字符串两边的空格 - * Clear the space of strings both sides. - * - * @param {String} str string - * @returns {String} trimed string - */ - - var trim = function(str) { - return (!String.prototype.trim) ? str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "") : str.trim(); - }; - - editormd.trim = trim; - - /** - * 所有单词首字母大写 - * Words first to uppercase - * - * @param {String} str string - * @returns {String} string - */ - - var ucwords = function (str) { - return str.toLowerCase().replace(/\b(\w)|\s(\w)/g, function($1) { - return $1.toUpperCase(); - }); - }; - - editormd.ucwords = editormd.wordsFirstUpperCase = ucwords; - - /** - * 字符串首字母大写 - * Only string first char to uppercase - * - * @param {String} str string - * @returns {String} string - */ - - var firstUpperCase = function(str) { - return str.toLowerCase().replace(/\b(\w)/, function($1){ - return $1.toUpperCase(); - }); - }; - - var ucfirst = firstUpperCase; - - editormd.firstUpperCase = editormd.ucfirst = firstUpperCase; - - editormd.urls = { - atLinkBase : "https://github.com/" - }; - - editormd.regexs = { - atLink : /@(\w+)/g, - email : /(\w+)@(\w+)\.(\w+)\.?(\w+)?/g, - emailLink : /(mailto:)?([\w\.\_]+)@(\w+)\.(\w+)\.?(\w+)?/g, - emoji : /:([\w\+-]+):/g, - emojiDatetime : /(\d{2}:\d{2}:\d{2})/g, - twemoji : /:(tw-([\w]+)-?(\w+)?):/g, - fontAwesome : /:(fa-([\w]+)(-(\w+)){0,}):/g, - editormdLogo : /:(editormd-logo-?(\w+)?):/g, - pageBreak : /^\[[=]{8,}\]$/ - }; - - // Emoji graphics files url path - editormd.emoji = { - path : "https://www.webpagefx.com/tools/emoji-cheat-sheet/graphics/emojis/", - ext : ".png" - }; - - // Twitter Emoji (Twemoji) graphics files url path - editormd.twemoji = { - path : "http://twemoji.maxcdn.com/36x36/", - ext : ".png" - }; - - /** - * 自定义marked的解析器 - * Custom Marked renderer rules - * - * @param {Array} markdownToC 传入用于接收TOC的数组 - * @returns {Renderer} markedRenderer 返回marked的Renderer自定义对象 - */ - - editormd.markedRenderer = function(markdownToC, options) { - var defaults = { - toc : true, // Table of contents - tocm : false, - tocStartLevel : 1, // Said from H1 to create ToC - pageBreak : true, - atLink : true, // for @link - emailLink : true, // for mail address auto link - taskList : false, // Enable Github Flavored Markdown task lists - emoji : false, // :emoji: , Support Twemoji, fontAwesome, Editor.md logo emojis. - tex : false, // TeX(LaTeX), based on KaTeX - flowChart : false, // flowChart.js only support IE9+ - sequenceDiagram : false, // sequenceDiagram.js only support IE9+ - }; - - var settings = $.extend(defaults, options || {}); - var marked = editormd.$marked; - var markedRenderer = new marked.Renderer(); - markdownToC = markdownToC || []; - - var regexs = editormd.regexs; - var atLinkReg = regexs.atLink; - var emojiReg = regexs.emoji; - var emailReg = regexs.email; - var emailLinkReg = regexs.emailLink; - var twemojiReg = regexs.twemoji; - var faIconReg = regexs.fontAwesome; - var editormdLogoReg = regexs.editormdLogo; - var pageBreakReg = regexs.pageBreak; - - markedRenderer.emoji = function(text) { - - text = text.replace(editormd.regexs.emojiDatetime, function($1) { - return $1.replace(/:/g, ":"); - }); - - var matchs = text.match(emojiReg); - - if (!matchs || !settings.emoji) { - return text; - } - - for (var i = 0, len = matchs.length; i < len; i++) - { - if (matchs[i] === ":+1:") { - matchs[i] = ":\\+1:"; - } - - text = text.replace(new RegExp(matchs[i]), function($1, $2){ - var faMatchs = $1.match(faIconReg); - var name = $1.replace(/:/g, ""); - - if (faMatchs) - { - for (var fa = 0, len1 = faMatchs.length; fa < len1; fa++) - { - var faName = faMatchs[fa].replace(/:/g, ""); - - return ""; - } - } - else - { - var emdlogoMathcs = $1.match(editormdLogoReg); - var twemojiMatchs = $1.match(twemojiReg); - - if (emdlogoMathcs) - { - for (var x = 0, len2 = emdlogoMathcs.length; x < len2; x++) - { - var logoName = emdlogoMathcs[x].replace(/:/g, ""); - return ""; - } - } - else if (twemojiMatchs) - { - for (var t = 0, len3 = twemojiMatchs.length; t < len3; t++) - { - var twe = twemojiMatchs[t].replace(/:/g, "").replace("tw-", ""); - return "\"twemoji-""; - } - } - else - { - var src = (name === "+1") ? "plus1" : name; - src = (src === "black_large_square") ? "black_square" : src; - src = (src === "moon") ? "waxing_gibbous_moon" : src; - - return "\":""; - } - } - }); - } - - return text; - }; - - markedRenderer.atLink = function(text) { - - if (atLinkReg.test(text)) - { - if (settings.atLink) - { - text = text.replace(emailReg, function($1, $2, $3, $4) { - return $1.replace(/@/g, "_#_@_#_"); - }); - - text = text.replace(atLinkReg, function($1, $2) { - return "" + $1 + ""; - }).replace(/_#_@_#_/g, "@"); - } - - if (settings.emailLink) - { - text = text.replace(emailLinkReg, function($1, $2, $3, $4, $5) { - return (!$2 && $.inArray($5, "jpg|jpeg|png|gif|webp|ico|icon|pdf".split("|")) < 0) ? ""+$1+"" : $1; - }); - } - - return text; - } - - return text; - }; - - markedRenderer.link = function (href, title, text) { - - if (this.options.sanitize) { - try { - var prot = decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase(); - } catch(e) { - return ""; - } - - if (prot.indexOf("javascript:") === 0) { - return ""; - } - } - - var out = "" + text.replace(/@/g, "@") + ""; - } - - if (title) { - out += " title=\"" + title + "\""; - } - - out += ">" + text + ""; - - return out; - }; - - markedRenderer.heading = function(text, level, raw) { - - var linkText = text; - var hasLinkReg = /\s*\]*)\>(.*)\<\/a\>\s*/; - var getLinkTextReg = /\s*\]+)\>([^\>]*)\<\/a\>\s*/g; - - if (hasLinkReg.test(text)) - { - var tempText = []; - text = text.split(/\]+)\>([^\>]*)\<\/a\>/); - - for (var i = 0, len = text.length; i < len; i++) - { - tempText.push(text[i].replace(/\s*href\=\"(.*)\"\s*/g, "")); - } - - text = tempText.join(" "); - } - - text = trim(text); - - var escapedText = text.toLowerCase().replace(/[^\w]+/g, "-"); - var toc = { - text : text, - level : level, - slug : escapedText - }; - - var isChinese = /^[\u4e00-\u9fa5]+$/.test(text); - var id = (isChinese) ? escape(text).replace(/\%/g, "") : text.toLowerCase().replace(/[^\w]+/g, "-"); - - markdownToC.push(toc); - - var headingHTML = ""; - - headingHTML += ""; - headingHTML += ""; - headingHTML += (hasLinkReg) ? this.atLink(this.emoji(linkText)) : this.atLink(this.emoji(text)); - headingHTML += ""; - - return headingHTML; - }; - - markedRenderer.pageBreak = function(text) { - if (pageBreakReg.test(text) && settings.pageBreak) - { - text = "
              "; - } - - return text; - }; - - markedRenderer.paragraph = function(text) { - var isTeXInline = /\$\$(.*)\$\$/g.test(text); - var isTeXLine = /^\$\$(.*)\$\$$/.test(text); - var isTeXAddClass = (isTeXLine) ? " class=\"" + editormd.classNames.tex + "\"" : ""; - var isToC = (settings.tocm) ? /^(\[TOC\]|\[TOCM\])$/.test(text) : /^\[TOC\]$/.test(text); - var isToCMenu = /^\[TOCM\]$/.test(text); - - if (!isTeXLine && isTeXInline) - { - text = text.replace(/(\$\$([^\$]*)\$\$)+/g, function($1, $2) { - return "" + $2.replace(/\$/g, "") + ""; - }); - } - else - { - text = (isTeXLine) ? text.replace(/\$/g, "") : text; - } - - var tocHTML = "
              " + text + "
              "; - - return (isToC) ? ( (isToCMenu) ? "
              " + tocHTML + "

              " : tocHTML ) - : ( (pageBreakReg.test(text)) ? this.pageBreak(text) : "" + this.atLink(this.emoji(text)) + "

              \n" ); - }; - - markedRenderer.code = function (code, lang, escaped) { - - if (lang === "seq" || lang === "sequence") - { - return "
              " + code + "
              "; - } - else if ( lang === "flow") - { - return "
              " + code + "
              "; - } - else if ( lang === "math" || lang === "latex" || lang === "katex") - { - return "

              " + code + "

              "; - } - else - { - - return marked.Renderer.prototype.code.apply(this, arguments); - } - }; - - markedRenderer.tablecell = function(content, flags) { - var type = (flags.header) ? "th" : "td"; - var tag = (flags.align) ? "<" + type +" style=\"text-align:" + flags.align + "\">" : "<" + type + ">"; - - return tag + this.atLink(this.emoji(content)) + "\n"; - }; - - markedRenderer.listitem = function(text) { - if (settings.taskList && /^\s*\[[x\s]\]\s*/.test(text)) - { - text = text.replace(/^\s*\[\s\]\s*/, " ") - .replace(/^\s*\[x\]\s*/, " "); - - return "
            • " + this.atLink(this.emoji(text)) + "
            • "; - } - else - { - return "
            • " + this.atLink(this.emoji(text)) + "
            • "; - } - }; - - return markedRenderer; - }; - - /** - * - * 生成TOC(Table of Contents) - * Creating ToC (Table of Contents) - * - * @param {Array} toc 从marked获取的TOC数组列表 - * @param {Element} container 插入TOC的容器元素 - * @param {Integer} startLevel Hx 起始层级 - * @returns {Object} tocContainer 返回ToC列表容器层的jQuery对象元素 - */ - - editormd.markdownToCRenderer = function(toc, container, tocDropdown, startLevel) { - - var html = ""; - var lastLevel = 0; - var classPrefix = this.classPrefix; - - startLevel = startLevel || 1; - - for (var i = 0, len = toc.length; i < len; i++) - { - var text = toc[i].text; - var level = toc[i].level; - - if (level < startLevel) { - continue; - } - - if (level > lastLevel) - { - html += ""; - } - else if (level < lastLevel) - { - html += (new Array(lastLevel - level + 2)).join("
          • "); - } - else - { - html += ""; - } - - html += "
          • " + text + "
              "; - lastLevel = level; - } - - var tocContainer = container.find(".markdown-toc"); - - if ((tocContainer.length < 1 && container.attr("previewContainer") === "false")) - { - var tocHTML = "
              "; - - tocHTML = (tocDropdown) ? "
              " + tocHTML + "
              " : tocHTML; - - container.html(tocHTML); - - tocContainer = container.find(".markdown-toc"); - } - - if (tocDropdown) - { - tocContainer.wrap("

              "); - } - - tocContainer.html("
                ").children(".markdown-toc-list").html(html.replace(/\r?\n?\\<\/ul\>/g, "")); - - return tocContainer; - }; - - /** - * - * 生成TOC下拉菜单 - * Creating ToC dropdown menu - * - * @param {Object} container 插入TOC的容器jQuery对象元素 - * @param {String} tocTitle ToC title - * @returns {Object} return toc-menu object - */ - - editormd.tocDropdownMenu = function(container, tocTitle) { - - tocTitle = tocTitle || "Table of Contents"; - - var zindex = 400; - var tocMenus = container.find("." + this.classPrefix + "toc-menu"); - - tocMenus.each(function() { - var $this = $(this); - var toc = $this.children(".markdown-toc"); - var icon = ""; - var btn = "" + icon + tocTitle + ""; - var menu = toc.children("ul"); - var list = menu.find("li"); - - toc.append(btn); - - list.first().before("
              • " + tocTitle + " " + icon + "

              • "); - - $this.mouseover(function(){ - menu.show(); - - list.each(function(){ - var li = $(this); - var ul = li.children("ul"); - - if (ul.html() === "") - { - ul.remove(); - } - - if (ul.length > 0 && ul.html() !== "") - { - var firstA = li.children("a").first(); - - if (firstA.children(".fa").length < 1) - { - firstA.append( $(icon).css({ float:"right", paddingTop:"4px" }) ); - } - } - - li.mouseover(function(){ - ul.css("z-index", zindex).show(); - zindex += 1; - }).mouseleave(function(){ - ul.hide(); - }); - }); - }).mouseleave(function(){ - menu.hide(); - }); - }); - - return tocMenus; - }; - - /** - * 简单地过滤指定的HTML标签 - * Filter custom html tags - * - * @param {String} html 要过滤HTML - * @param {String} filters 要过滤的标签 - * @returns {String} html 返回过滤的HTML - */ - - editormd.filterHTMLTags = function(html, filters) { - - if (typeof html !== "string") { - html = new String(html); - } - - if (typeof filters !== "string") { - return html; - } - - var expression = filters.split("|"); - var filterTags = expression[0].split(","); - var attrs = expression[1]; - - for (var i = 0, len = filterTags.length; i < len; i++) - { - var tag = filterTags[i]; - - html = html.replace(new RegExp("\<\s*" + tag + "\s*([^\>]*)\>([^\>]*)\<\s*\/" + tag + "\s*\>", "igm"), ""); - } - - //return html; - - if (typeof attrs !== "undefined") - { - var htmlTagRegex = /\<(\w+)\s*([^\>]*)\>([^\>]*)\<\/(\w+)\>/ig; - - if (attrs === "*") - { - html = html.replace(htmlTagRegex, function($1, $2, $3, $4, $5) { - return "<" + $2 + ">" + $4 + ""; - }); - } - else if (attrs === "on*") - { - html = html.replace(htmlTagRegex, function($1, $2, $3, $4, $5) { - var el = $("<" + $2 + ">" + $4 + ""); - var _attrs = $($1)[0].attributes; - var $attrs = {}; - - $.each(_attrs, function(i, e) { - if (e.nodeName !== '"') $attrs[e.nodeName] = e.nodeValue; - }); - - $.each($attrs, function(i) { - if (i.indexOf("on") === 0) { - delete $attrs[i]; - } - }); - - el.attr($attrs); - - var text = (typeof el[1] !== "undefined") ? $(el[1]).text() : ""; - - return el[0].outerHTML + text; - }); - } - else - { - html = html.replace(htmlTagRegex, function($1, $2, $3, $4) { - var filterAttrs = attrs.split(","); - var el = $($1); - el.html($4); - - $.each(filterAttrs, function(i) { - el.attr(filterAttrs[i], null); - }); - - return el[0].outerHTML; - }); - } - } - - return html; - }; - - /** - * 将Markdown文档解析为HTML用于前台显示 - * Parse Markdown to HTML for Font-end preview. - * - * @param {String} id 用于显示HTML的对象ID - * @param {Object} [options={}] 配置选项,可选 - * @returns {Object} div 返回jQuery对象元素 - */ - - editormd.markdownToHTML = function(id, options) { - var defaults = { - gfm : true, - toc : true, - tocm : false, - tocStartLevel : 1, - tocTitle : "目录", - tocDropdown : false, - tocContainer : "", - markdown : "", - markdownSourceCode : false, - htmlDecode : false, - autoLoadKaTeX : true, - pageBreak : true, - atLink : true, // for @link - emailLink : true, // for mail address auto link - tex : false, - taskList : false, // Github Flavored Markdown task lists - emoji : false, - flowChart : false, - sequenceDiagram : false, - previewCodeHighlight : true - }; - - editormd.$marked = marked; - - var div = $("#" + id); - var settings = div.settings = $.extend(true, defaults, options || {}); - var saveTo = div.find("textarea"); - - if (saveTo.length < 1) - { - div.append(""); - saveTo = div.find("textarea"); - } - - var markdownDoc = (settings.markdown === "") ? saveTo.val() : settings.markdown; - var markdownToC = []; - - var rendererOptions = { - toc : settings.toc, - tocm : settings.tocm, - tocStartLevel : settings.tocStartLevel, - taskList : settings.taskList, - emoji : settings.emoji, - tex : settings.tex, - pageBreak : settings.pageBreak, - atLink : settings.atLink, // for @link - emailLink : settings.emailLink, // for mail address auto link - flowChart : settings.flowChart, - sequenceDiagram : settings.sequenceDiagram, - previewCodeHighlight : settings.previewCodeHighlight, - }; - - var markedOptions = { - renderer : editormd.markedRenderer(markdownToC, rendererOptions), - gfm : settings.gfm, - tables : true, - breaks : true, - pedantic : false, - sanitize : (settings.htmlDecode) ? false : true, // 是否忽略HTML标签,即是否开启HTML标签解析,为了安全性,默认不开启 - smartLists : true, - smartypants : true - }; - - markdownDoc = new String(markdownDoc); - - var markdownParsed = marked(markdownDoc, markedOptions); - - markdownParsed = editormd.filterHTMLTags(markdownParsed, settings.htmlDecode); - - if (settings.markdownSourceCode) { - saveTo.text(markdownDoc); - } else { - saveTo.remove(); - } - - div.addClass("markdown-body " + this.classPrefix + "html-preview").append(markdownParsed); - - var tocContainer = (settings.tocContainer !== "") ? $(settings.tocContainer) : div; - - if (settings.tocContainer !== "") - { - tocContainer.attr("previewContainer", false); - } - - if (settings.toc) - { - div.tocContainer = this.markdownToCRenderer(markdownToC, tocContainer, settings.tocDropdown, settings.tocStartLevel); - - if (settings.tocDropdown || div.find("." + this.classPrefix + "toc-menu").length > 0) - { - this.tocDropdownMenu(div, settings.tocTitle); - } - - if (settings.tocContainer !== "") - { - div.find(".editormd-toc-menu, .editormd-markdown-toc").remove(); - } - } - - if (settings.previewCodeHighlight) - { - div.find("pre").addClass("prettyprint linenums"); - prettyPrint(); - } - - if (!editormd.isIE8) - { - if (settings.flowChart) { - div.find(".flowchart").flowChart(); - } - - if (settings.sequenceDiagram) { - div.find(".sequence-diagram").sequenceDiagram({theme: "simple"}); - } - } - - if (settings.tex) - { - var katexHandle = function() { - div.find("." + editormd.classNames.tex).each(function(){ - var tex = $(this); - katex.render(tex.html().replace(/</g, "<").replace(/>/g, ">"), tex[0]); - tex.find(".katex").css("font-size", "1.6em"); - }); - }; - - if (settings.autoLoadKaTeX && !editormd.$katex && !editormd.kaTeXLoaded) - { - this.loadKaTeX(function() { - editormd.$katex = katex; - editormd.kaTeXLoaded = true; - katexHandle(); - }); - } - else - { - katexHandle(); - } - } - - div.getMarkdown = function() { - return saveTo.val(); - }; - - return div; - }; - - // Editor.md themes, change toolbar themes etc. - // added @1.5.0 - editormd.themes = ["default", "dark"]; - - // Preview area themes - // added @1.5.0 - editormd.previewThemes = ["default", "dark"]; - - // CodeMirror / editor area themes - // @1.5.0 rename -> editorThemes, old version -> themes - editormd.editorThemes = [ - "default", "3024-day", "3024-night", - "ambiance", "ambiance-mobile", - "base16-dark", "base16-light", "blackboard", - "cobalt", - "eclipse", "elegant", "erlang-dark", - "lesser-dark", - "mbo", "mdn-like", "midnight", "monokai", - "neat", "neo", "night", - "paraiso-dark", "paraiso-light", "pastel-on-dark", - "rubyblue", - "solarized", - "the-matrix", "tomorrow-night-eighties", "twilight", - "vibrant-ink", - "xq-dark", "xq-light" - ]; - - editormd.loadPlugins = {}; - - editormd.loadFiles = { - js : [], - css : [], - plugin : [] - }; - - /** - * 动态加载Editor.md插件,但不立即执行 - * Load editor.md plugins - * - * @param {String} fileName 插件文件路径 - * @param {Function} [callback=function()] 加载成功后执行的回调函数 - * @param {String} [into="head"] 嵌入页面的位置 - */ - - editormd.loadPlugin = function(fileName, callback, into) { - callback = callback || function() {}; - - this.loadScript(fileName, function() { - editormd.loadFiles.plugin.push(fileName); - callback(); - }, into); - }; - - /** - * 动态加载CSS文件的方法 - * Load css file method - * - * @param {String} fileName CSS文件名 - * @param {Function} [callback=function()] 加载成功后执行的回调函数 - * @param {String} [into="head"] 嵌入页面的位置 - */ - - editormd.loadCSS = function(fileName, callback, into) { - into = into || "head"; - callback = callback || function() {}; - - var css = document.createElement("link"); - css.type = "text/css"; - css.rel = "stylesheet"; - css.onload = css.onreadystatechange = function() { - editormd.loadFiles.css.push(fileName); - callback(); - }; - - css.href = fileName + ".css"; - - if(into === "head") { - document.getElementsByTagName("head")[0].appendChild(css); - } else { - document.body.appendChild(css); - } - }; - - editormd.isIE = (navigator.appName == "Microsoft Internet Explorer"); - editormd.isIE8 = (editormd.isIE && navigator.appVersion.match(/8./i) == "8."); - - /** - * 动态加载JS文件的方法 - * Load javascript file method - * - * @param {String} fileName JS文件名 - * @param {Function} [callback=function()] 加载成功后执行的回调函数 - * @param {String} [into="head"] 嵌入页面的位置 - */ - - editormd.loadScript = function(fileName, callback, into) { - - into = into || "head"; - callback = callback || function() {}; - - var script = null; - script = document.createElement("script"); - script.id = fileName.replace(/[\./]+/g, "-"); - script.type = "text/javascript"; - script.src = fileName + ".js"; - - if (editormd.isIE8) - { - script.onreadystatechange = function() { - if(script.readyState) - { - if (script.readyState === "loaded" || script.readyState === "complete") - { - script.onreadystatechange = null; - editormd.loadFiles.js.push(fileName); - callback(); - } - } - }; - } - else - { - script.onload = function() { - editormd.loadFiles.js.push(fileName); - callback(); - }; - } - - if (into === "head") { - document.getElementsByTagName("head")[0].appendChild(script); - } else { - document.body.appendChild(script); - } - }; - - // 使用国外的CDN,加载速度有时会很慢,或者自定义URL - // You can custom KaTeX load url. - editormd.katexURL = { - css : "//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.3.0/katex.min", - js : "//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.3.0/katex.min" - }; - - editormd.kaTeXLoaded = false; - - /** - * 加载KaTeX文件 - * load KaTeX files - * - * @param {Function} [callback=function()] 加载成功后执行的回调函数 - */ - - editormd.loadKaTeX = function (callback) { - editormd.loadCSS(editormd.katexURL.css, function(){ - editormd.loadScript(editormd.katexURL.js, callback || function(){}); - }); - }; - - /** - * 锁屏 - * lock screen - * - * @param {Boolean} lock Boolean 布尔值,是否锁屏 - * @returns {void} - */ - - editormd.lockScreen = function(lock) { - $("html,body").css("overflow", (lock) ? "hidden" : ""); - }; - - /** - * 动态创建对话框 - * Creating custom dialogs - * - * @param {Object} options 配置项键值对 Key/Value - * @returns {dialog} 返回创建的dialog的jQuery实例对象 - */ - - editormd.createDialog = function(options) { - var defaults = { - name : "", - width : 420, - height: 240, - title : "", - drag : true, - closed : true, - content : "", - mask : true, - maskStyle : { - backgroundColor : "#fff", - opacity : 0.1 - }, - lockScreen : true, - footer : true, - buttons : false - }; - - options = $.extend(true, defaults, options); - - var $this = this; - var editor = this.editor; - var classPrefix = editormd.classPrefix; - var guid = (new Date()).getTime(); - var dialogName = ( (options.name === "") ? classPrefix + "dialog-" + guid : options.name); - var mouseOrTouch = editormd.mouseOrTouch; - - var html = "
                "; - - if (options.title !== "") - { - html += "
                "; - html += "" + options.title + ""; - html += "
                "; - } - - if (options.closed) - { - html += ""; - } - - html += "
                " + options.content; - - if (options.footer || typeof options.footer === "string") - { - html += "
                " + ( (typeof options.footer === "boolean") ? "" : options.footer) + "
                "; - } - - html += "
                "; - - html += "
                "; - html += "
                "; - html += "
                "; - - editor.append(html); - - var dialog = editor.find("." + dialogName); - - dialog.lockScreen = function(lock) { - if (options.lockScreen) - { - $("html,body").css("overflow", (lock) ? "hidden" : ""); - $this.resize(); - } - - return dialog; - }; - - dialog.showMask = function() { - if (options.mask) - { - editor.find("." + classPrefix + "mask").css(options.maskStyle).css("z-index", editormd.dialogZindex - 1).show(); - } - return dialog; - }; - - dialog.hideMask = function() { - if (options.mask) - { - editor.find("." + classPrefix + "mask").hide(); - } - - return dialog; - }; - - dialog.loading = function(show) { - var loading = dialog.find("." + classPrefix + "dialog-mask"); - loading[(show) ? "show" : "hide"](); - - return dialog; - }; - - dialog.lockScreen(true).showMask(); - - dialog.show().css({ - zIndex : editormd.dialogZindex, - border : (editormd.isIE8) ? "1px solid #ddd" : "", - width : (typeof options.width === "number") ? options.width + "px" : options.width, - height : (typeof options.height === "number") ? options.height + "px" : options.height - }); - - var dialogPosition = function(){ - dialog.css({ - top : ($(window).height() - dialog.height()) / 2 + "px", - left : ($(window).width() - dialog.width()) / 2 + "px" - }); - }; - - dialogPosition(); - - $(window).resize(dialogPosition); - - dialog.children("." + classPrefix + "dialog-close").bind(mouseOrTouch("click", "touchend"), function() { - dialog.hide().lockScreen(false).hideMask(); - }); - - if (typeof options.buttons === "object") - { - var footer = dialog.footer = dialog.find("." + classPrefix + "dialog-footer"); - - for (var key in options.buttons) - { - var btn = options.buttons[key]; - var btnClassName = classPrefix + key + "-btn"; - - footer.append(""); - btn[1] = $.proxy(btn[1], dialog); - footer.children("." + btnClassName).bind(mouseOrTouch("click", "touchend"), btn[1]); - } - } - - if (options.title !== "" && options.drag) - { - var posX, posY; - var dialogHeader = dialog.children("." + classPrefix + "dialog-header"); - - if (!options.mask) { - dialogHeader.bind(mouseOrTouch("click", "touchend"), function(){ - editormd.dialogZindex += 2; - dialog.css("z-index", editormd.dialogZindex); - }); - } - - dialogHeader.mousedown(function(e) { - e = e || window.event; //IE - posX = e.clientX - parseInt(dialog[0].style.left); - posY = e.clientY - parseInt(dialog[0].style.top); - - document.onmousemove = moveAction; - }); - - var userCanSelect = function (obj) { - obj.removeClass(classPrefix + "user-unselect").off("selectstart"); - }; - - var userUnselect = function (obj) { - obj.addClass(classPrefix + "user-unselect").on("selectstart", function(event) { // selectstart for IE - return false; - }); - }; - - var moveAction = function (e) { - e = e || window.event; //IE - - var left, top, nowLeft = parseInt(dialog[0].style.left), nowTop = parseInt(dialog[0].style.top); - - if( nowLeft >= 0 ) { - if( nowLeft + dialog.width() <= $(window).width()) { - left = e.clientX - posX; - } else { - left = $(window).width() - dialog.width(); - document.onmousemove = null; - } - } else { - left = 0; - document.onmousemove = null; - } - - if( nowTop >= 0 ) { - top = e.clientY - posY; - } else { - top = 0; - document.onmousemove = null; - } - - - document.onselectstart = function() { - return false; - }; - - userUnselect($("body")); - userUnselect(dialog); - dialog[0].style.left = left + "px"; - dialog[0].style.top = top + "px"; - }; - - document.onmouseup = function() { - userCanSelect($("body")); - userCanSelect(dialog); - - document.onselectstart = null; - document.onmousemove = null; - }; - - dialogHeader.touchDraggable = function() { - var offset = null; - var start = function(e) { - var orig = e.originalEvent; - var pos = $(this).parent().position(); - - offset = { - x : orig.changedTouches[0].pageX - pos.left, - y : orig.changedTouches[0].pageY - pos.top - }; - }; - - var move = function(e) { - e.preventDefault(); - var orig = e.originalEvent; - - $(this).parent().css({ - top : orig.changedTouches[0].pageY - offset.y, - left : orig.changedTouches[0].pageX - offset.x - }); - }; - - this.bind("touchstart", start).bind("touchmove", move); - }; - - dialogHeader.touchDraggable(); - } - - editormd.dialogZindex += 2; - - return dialog; - }; - - /** - * 鼠标和触摸事件的判断/选择方法 - * MouseEvent or TouchEvent type switch - * - * @param {String} [mouseEventType="click"] 供选择的鼠标事件 - * @param {String} [touchEventType="touchend"] 供选择的触摸事件 - * @returns {String} EventType 返回事件类型名称 - */ - - editormd.mouseOrTouch = function(mouseEventType, touchEventType) { - mouseEventType = mouseEventType || "click"; - touchEventType = touchEventType || "touchend"; - - var eventType = mouseEventType; - - try { - document.createEvent("TouchEvent"); - eventType = touchEventType; - } catch(e) {} - - return eventType; - }; - - /** - * 日期时间的格式化方法 - * Datetime format method - * - * @param {String} [format=""] 日期时间的格式,类似PHP的格式 - * @returns {String} datefmt 返回格式化后的日期时间字符串 - */ - - editormd.dateFormat = function(format) { - format = format || ""; - - var addZero = function(d) { - return (d < 10) ? "0" + d : d; - }; - - var date = new Date(); - var year = date.getFullYear(); - var year2 = year.toString().slice(2, 4); - var month = addZero(date.getMonth() + 1); - var day = addZero(date.getDate()); - var weekDay = date.getDay(); - var hour = addZero(date.getHours()); - var min = addZero(date.getMinutes()); - var second = addZero(date.getSeconds()); - var ms = addZero(date.getMilliseconds()); - var datefmt = ""; - - var ymd = year2 + "-" + month + "-" + day; - var fymd = year + "-" + month + "-" + day; - var hms = hour + ":" + min + ":" + second; - - switch (format) - { - case "UNIX Time" : - datefmt = date.getTime(); - break; - - case "UTC" : - datefmt = date.toUTCString(); - break; - - case "yy" : - datefmt = year2; - break; - - case "year" : - case "yyyy" : - datefmt = year; - break; - - case "month" : - case "mm" : - datefmt = month; - break; - - case "cn-week-day" : - case "cn-wd" : - var cnWeekDays = ["日", "一", "二", "三", "四", "五", "六"]; - datefmt = "星期" + cnWeekDays[weekDay]; - break; - - case "week-day" : - case "wd" : - var weekDays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; - datefmt = weekDays[weekDay]; - break; - - case "day" : - case "dd" : - datefmt = day; - break; - - case "hour" : - case "hh" : - datefmt = hour; - break; - - case "min" : - case "ii" : - datefmt = min; - break; - - case "second" : - case "ss" : - datefmt = second; - break; - - case "ms" : - datefmt = ms; - break; - - case "yy-mm-dd" : - datefmt = ymd; - break; - - case "yyyy-mm-dd" : - datefmt = fymd; - break; - - case "yyyy-mm-dd h:i:s ms" : - case "full + ms" : - datefmt = fymd + " " + hms + " " + ms; - break; - - case "full" : - case "yyyy-mm-dd h:i:s" : - default: - datefmt = fymd + " " + hms; - break; - } - - return datefmt; - }; - - return editormd; - -})); diff --git a/src/main/resources/static/editor-md/editormd.min.js b/src/main/resources/static/editor-md/editormd.min.js deleted file mode 100644 index f810e34..0000000 --- a/src/main/resources/static/editor-md/editormd.min.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! Editor.md v1.5.0 | editormd.min.js | Open source online markdown editor. | MIT License | By: Pandao | https://github.com/pandao/editor.md | 2015-06-09 */ -!function(e){"use strict";"function"==typeof require&&"object"==typeof exports&&"object"==typeof module?module.exports=e:"function"==typeof define?define.amd||define(["jquery"],e):window.editormd=e()}(function(){"use strict";var e="undefined"!=typeof jQuery?jQuery:Zepto;if("undefined"!=typeof e){var t=function(e,i){return new t.fn.init(e,i)};t.title=t.$name="Editor.md",t.version="1.5.0",t.homePage="https://pandao.github.io/editor.md/",t.classPrefix="editormd-",t.toolbarModes={full:["undo","redo","|","bold","del","italic","quote","ucwords","uppercase","lowercase","|","h1","h2","h3","h4","h5","h6","|","list-ul","list-ol","hr","|","link","reference-link","image","code","preformatted-text","code-block","table","datetime","emoji","html-entities","pagebreak","|","goto-line","watch","preview","fullscreen","clear","search","|","help","info"],simple:["undo","redo","|","bold","del","italic","quote","uppercase","lowercase","|","h1","h2","h3","h4","h5","h6","|","list-ul","list-ol","hr","|","watch","preview","fullscreen","|","help","info"],mini:["undo","redo","|","watch","preview","|","help","info"]},t.defaults={mode:"gfm",name:"",value:"",theme:"",editorTheme:"default",previewTheme:"",markdown:"",appendMarkdown:"",width:"100%",height:"100%",path:"./lib/",pluginPath:"",delay:300,autoLoadModules:!0,watch:!0,placeholder:"Enjoy Markdown! coding now...",gotoLine:!0,codeFold:!1,autoHeight:!1,autoFocus:!0,autoCloseTags:!0,searchReplace:!0,syncScrolling:!0,readOnly:!1,tabSize:4,indentUnit:4,lineNumbers:!0,lineWrapping:!0,autoCloseBrackets:!0,showTrailingSpace:!0,matchBrackets:!0,indentWithTabs:!0,styleSelectedText:!0,matchWordHighlight:!0,styleActiveLine:!0,dialogLockScreen:!0,dialogShowMask:!0,dialogDraggable:!0,dialogMaskBgColor:"#fff",dialogMaskOpacity:.1,fontSize:"13px",saveHTMLToTextarea:!1,disabledKeyMaps:[],onload:function(){},onresize:function(){},onchange:function(){},onwatch:null,onunwatch:null,onpreviewing:function(){},onpreviewed:function(){},onfullscreen:function(){},onfullscreenExit:function(){},onscroll:function(){},onpreviewscroll:function(){},imageUpload:!1,imageFormats:["jpg","jpeg","gif","png","bmp","webp"],imageUploadURL:"",crossDomainUpload:!1,uploadCallbackURL:"",toc:!0,tocm:!1,tocTitle:"",tocDropdown:!1,tocContainer:"",tocStartLevel:1,htmlDecode:!1,pageBreak:!0,atLink:!0,emailLink:!0,taskList:!1,emoji:!1,tex:!1,flowChart:!1,sequenceDiagram:!1,previewCodeHighlight:!0,toolbar:!0,toolbarAutoFixed:!0,toolbarIcons:"full",toolbarTitles:{},toolbarHandlers:{ucwords:function(){return t.toolbarHandlers.ucwords},lowercase:function(){return t.toolbarHandlers.lowercase}},toolbarCustomIcons:{lowercase:'a',ucwords:'Aa'},toolbarIconsClass:{undo:"fa-undo",redo:"fa-repeat",bold:"fa-bold",del:"fa-strikethrough",italic:"fa-italic",quote:"fa-quote-left",uppercase:"fa-font",h1:t.classPrefix+"bold",h2:t.classPrefix+"bold",h3:t.classPrefix+"bold",h4:t.classPrefix+"bold",h5:t.classPrefix+"bold",h6:t.classPrefix+"bold","list-ul":"fa-list-ul","list-ol":"fa-list-ol",hr:"fa-minus",link:"fa-link","reference-link":"fa-anchor",image:"fa-picture-o",code:"fa-code","preformatted-text":"fa-file-code-o","code-block":"fa-file-code-o",table:"fa-table",datetime:"fa-clock-o",emoji:"fa-smile-o","html-entities":"fa-copyright",pagebreak:"fa-newspaper-o","goto-line":"fa-terminal",watch:"fa-eye-slash",unwatch:"fa-eye",preview:"fa-desktop",search:"fa-search",fullscreen:"fa-arrows-alt",clear:"fa-eraser",help:"fa-question-circle",info:"fa-info-circle"},toolbarIconTexts:{},lang:{name:"zh-cn",description:"开源在线Markdown编辑器
                Open source online Markdown editor.",tocTitle:"目录",toolbar:{undo:"撤销(Ctrl+Z)",redo:"重做(Ctrl+Y)",bold:"粗体",del:"删除线",italic:"斜体",quote:"引用",ucwords:"将每个单词首字母转成大写",uppercase:"将所选转换成大写",lowercase:"将所选转换成小写",h1:"标题1",h2:"标题2",h3:"标题3",h4:"标题4",h5:"标题5",h6:"标题6","list-ul":"无序列表","list-ol":"有序列表",hr:"横线",link:"链接","reference-link":"引用链接",image:"添加图片",code:"行内代码","preformatted-text":"预格式文本 / 代码块(缩进风格)","code-block":"代码块(多语言风格)",table:"添加表格",datetime:"日期时间",emoji:"Emoji表情","html-entities":"HTML实体字符",pagebreak:"插入分页符","goto-line":"跳转到行",watch:"关闭实时预览",unwatch:"开启实时预览",preview:"全窗口预览HTML(按 Shift + ESC还原)",fullscreen:"全屏(按ESC还原)",clear:"清空",search:"搜索",help:"使用帮助",info:"关于"+t.title},buttons:{enter:"确定",cancel:"取消",close:"关闭"},dialog:{link:{title:"添加链接",url:"链接地址",urlTitle:"链接标题",urlEmpty:"错误:请填写链接地址。"},referenceLink:{title:"添加引用链接",name:"引用名称",url:"链接地址",urlId:"链接ID",urlTitle:"链接标题",nameEmpty:"错误:引用链接的名称不能为空。",idEmpty:"错误:请填写引用链接的ID。",urlEmpty:"错误:请填写引用链接的URL地址。"},image:{title:"添加图片",url:"图片地址",link:"图片链接",alt:"图片描述",uploadButton:"本地上传",imageURLEmpty:"错误:图片地址不能为空。",uploadFileEmpty:"错误:上传的图片不能为空。",formatNotAllowed:"错误:只允许上传图片文件,允许上传的图片文件格式有:"},preformattedText:{title:"添加预格式文本或代码块",emptyAlert:"错误:请填写预格式文本或代码的内容。"},codeBlock:{title:"添加代码块",selectLabel:"代码语言:",selectDefaultText:"请选择代码语言",otherLanguage:"其他语言",unselectedLanguageAlert:"错误:请选择代码所属的语言类型。",codeEmptyAlert:"错误:请填写代码内容。"},htmlEntities:{title:"HTML 实体字符"},help:{title:"使用帮助"}}}},t.classNames={tex:t.classPrefix+"tex"},t.dialogZindex=99999,t.$katex=null,t.$marked=null,t.$CodeMirror=null,t.$prettyPrint=null;var i,o;t.prototype=t.fn={state:{watching:!1,loaded:!1,preview:!1,fullscreen:!1},init:function(i,o){o=o||{},"object"==typeof i&&(o=i);var r=this.classPrefix=t.classPrefix,n=this.settings=e.extend(!0,t.defaults,o);i="object"==typeof i?n.id:i;var a=this.editor=e("#"+i);this.id=i,this.lang=n.lang;var s=this.classNames={textarea:{html:r+"html-textarea",markdown:r+"markdown-textarea"}};n.pluginPath=""===n.pluginPath?n.path+"../plugins/":n.pluginPath,this.state.watching=n.watch?!0:!1,a.hasClass("editormd")||a.addClass("editormd"),a.css({width:"number"==typeof n.width?n.width+"px":n.width,height:"number"==typeof n.height?n.height+"px":n.height}),n.autoHeight&&a.css("height","auto");var l=this.markdownTextarea=a.children("textarea");l.length<1&&(a.append(""),l=this.markdownTextarea=a.children("textarea")),l.addClass(s.textarea.markdown).attr("placeholder",n.placeholder),("undefined"==typeof l.attr("name")||""===l.attr("name"))&&l.attr("name",""!==n.name?n.name:i+"-markdown-doc");var c=[n.readOnly?"":'',n.saveHTMLToTextarea?'':"",'
                ','
                ','
                '].join("\n");return a.append(c).addClass(r+"vertical"),""!==n.theme&&a.addClass(r+"theme-"+n.theme),this.mask=a.children("."+r+"mask"),this.containerMask=a.children("."+r+"container-mask"),""!==n.markdown&&l.val(n.markdown),""!==n.appendMarkdown&&l.val(l.val()+n.appendMarkdown),this.htmlTextarea=a.children("."+s.textarea.html),this.preview=a.children("."+r+"preview"),this.previewContainer=this.preview.children("."+r+"preview-container"),""!==n.previewTheme&&this.preview.addClass(r+"preview-theme-"+n.previewTheme),"function"==typeof define&&define.amd&&("undefined"!=typeof katex&&(t.$katex=katex),n.searchReplace&&!n.readOnly&&(t.loadCSS(n.path+"codemirror/addon/dialog/dialog"),t.loadCSS(n.path+"codemirror/addon/search/matchesonscrollbar"))),"function"==typeof define&&define.amd||!n.autoLoadModules?("undefined"!=typeof CodeMirror&&(t.$CodeMirror=CodeMirror),"undefined"!=typeof marked&&(t.$marked=marked),this.setCodeMirror().setToolbar().loadedDisplay()):this.loadQueues(),this},loadQueues:function(){var e=this,i=this.settings,o=i.path,r=function(){return t.isIE8?void e.loadedDisplay():void(i.flowChart||i.sequenceDiagram?t.loadScript(o+"raphael.min",function(){t.loadScript(o+"underscore.min",function(){!i.flowChart&&i.sequenceDiagram?t.loadScript(o+"sequence-diagram.min",function(){e.loadedDisplay()}):i.flowChart&&!i.sequenceDiagram?t.loadScript(o+"flowchart.min",function(){t.loadScript(o+"jquery.flowchart.min",function(){e.loadedDisplay()})}):i.flowChart&&i.sequenceDiagram&&t.loadScript(o+"flowchart.min",function(){t.loadScript(o+"jquery.flowchart.min",function(){t.loadScript(o+"sequence-diagram.min",function(){e.loadedDisplay()})})})})}):e.loadedDisplay())};return t.loadCSS(o+"codemirror/codemirror.min"),i.searchReplace&&!i.readOnly&&(t.loadCSS(o+"codemirror/addon/dialog/dialog"),t.loadCSS(o+"codemirror/addon/search/matchesonscrollbar")),i.codeFold&&t.loadCSS(o+"codemirror/addon/fold/foldgutter"),t.loadScript(o+"codemirror/codemirror.min",function(){t.$CodeMirror=CodeMirror,t.loadScript(o+"codemirror/modes.min",function(){t.loadScript(o+"codemirror/addons.min",function(){return e.setCodeMirror(),"gfm"!==i.mode&&"markdown"!==i.mode?(e.loadedDisplay(),!1):(e.setToolbar(),void t.loadScript(o+"marked.min",function(){t.$marked=marked,i.previewCodeHighlight?t.loadScript(o+"prettify.min",function(){r()}):r()}))})})}),this},setTheme:function(e){var t=this.editor,i=this.settings.theme,o=this.classPrefix+"theme-";return t.removeClass(o+i).addClass(o+e),this.settings.theme=e,this},setEditorTheme:function(e){var i=this.settings;return i.editorTheme=e,"default"!==e&&t.loadCSS(i.path+"codemirror/theme/"+i.editorTheme),this.cm.setOption("theme",e),this},setCodeMirrorTheme:function(e){return this.setEditorTheme(e),this},setPreviewTheme:function(e){var t=this.preview,i=this.settings.previewTheme,o=this.classPrefix+"preview-theme-";return t.removeClass(o+i).addClass(o+e),this.settings.previewTheme=e,this},setCodeMirror:function(){var e=this.settings,i=this.editor;"default"!==e.editorTheme&&t.loadCSS(e.path+"codemirror/theme/"+e.editorTheme);var o={mode:e.mode,theme:e.editorTheme,tabSize:e.tabSize,dragDrop:!1,autofocus:e.autoFocus,autoCloseTags:e.autoCloseTags,readOnly:e.readOnly?"nocursor":!1,indentUnit:e.indentUnit,lineNumbers:e.lineNumbers,lineWrapping:e.lineWrapping,extraKeys:{"Ctrl-Q":function(e){e.foldCode(e.getCursor())}},foldGutter:e.codeFold,gutters:["CodeMirror-linenumbers","CodeMirror-foldgutter"],matchBrackets:e.matchBrackets,indentWithTabs:e.indentWithTabs,styleActiveLine:e.styleActiveLine,styleSelectedText:e.styleSelectedText,autoCloseBrackets:e.autoCloseBrackets,showTrailingSpace:e.showTrailingSpace,highlightSelectionMatches:e.matchWordHighlight?{showToken:"onselected"===e.matchWordHighlight?!1:/\w/}:!1};return this.codeEditor=this.cm=t.$CodeMirror.fromTextArea(this.markdownTextarea[0],o),this.codeMirror=this.cmElement=i.children(".CodeMirror"),""!==e.value&&this.cm.setValue(e.value),this.codeMirror.css({fontSize:e.fontSize,width:e.watch?"50%":"100%"}),e.autoHeight&&(this.codeMirror.css("height","auto"),this.cm.setOption("viewportMargin",1/0)),e.lineNumbers||this.codeMirror.find(".CodeMirror-gutters").css("border-right","none"),this},getCodeMirrorOption:function(e){return this.cm.getOption(e)},setCodeMirrorOption:function(e,t){return this.cm.setOption(e,t),this},addKeyMap:function(e,t){return this.cm.addKeyMap(e,t),this},removeKeyMap:function(e){return this.cm.removeKeyMap(e),this},gotoLine:function(t){var i=this.settings;if(!i.gotoLine)return this;var o=this.cm,r=(this.editor,o.lineCount()),n=this.preview;if("string"==typeof t&&("last"===t&&(t=r),"first"===t&&(t=1)),"number"!=typeof t)return alert("Error: The line number must be an integer."),this;if(t=parseInt(t)-1,t>r)return alert("Error: The line number range 1-"+r),this;o.setCursor({line:t,ch:0});var a=o.getScrollInfo(),s=a.clientHeight,l=o.charCoords({line:t,ch:0},"local");if(o.scrollTo(null,(l.top+l.bottom-s)/2),i.watch){var c=this.codeMirror.find(".CodeMirror-scroll")[0],h=e(c).height(),d=c.scrollTop,u=d/c.scrollHeight;n.scrollTop(0===d?0:d+h>=c.scrollHeight-16?n[0].scrollHeight:n[0].scrollHeight*u)}return o.focus(),this},extend:function(){return"undefined"!=typeof arguments[1]&&("function"==typeof arguments[1]&&(arguments[1]=e.proxy(arguments[1],this)),this[arguments[0]]=arguments[1]),"object"==typeof arguments[0]&&"undefined"==typeof arguments[0].length&&e.extend(!0,this,arguments[0]),this},set:function(t,i){return"undefined"!=typeof i&&"function"==typeof i&&(i=e.proxy(i,this)),this[t]=i,this},config:function(t,i){var o=this.settings;return"object"==typeof t&&(o=e.extend(!0,o,t)),"string"==typeof t&&(o[t]=i),this.settings=o,this.recreate(),this},on:function(t,i){var o=this.settings;return"undefined"!=typeof o["on"+t]&&(o["on"+t]=e.proxy(i,this)),this},off:function(e){var t=this.settings;return"undefined"!=typeof t["on"+e]&&(t["on"+e]=function(){}),this},showToolbar:function(t){var i=this.settings;return i.readOnly?this:(i.toolbar&&(this.toolbar.length<1||""===this.toolbar.find("."+this.classPrefix+"menu").html())&&this.setToolbar(),i.toolbar=!0,this.toolbar.show(),this.resize(),e.proxy(t||function(){},this)(),this)},hideToolbar:function(t){var i=this.settings;return i.toolbar=!1,this.toolbar.hide(),this.resize(),e.proxy(t||function(){},this)(),this},setToolbarAutoFixed:function(t){var i=this.state,o=this.editor,r=this.toolbar,n=this.settings;"undefined"!=typeof t&&(n.toolbarAutoFixed=t);var a=function(){var t=e(window),i=t.scrollTop();return n.toolbarAutoFixed?void r.css(i-o.offset().top>10&&i
                  ';i.append(n),r=this.toolbar=i.children("."+o+"toolbar")}if(!e.toolbar)return r.hide(),this;r.show();for(var a="function"==typeof e.toolbarIcons?e.toolbarIcons():"string"==typeof e.toolbarIcons?t.toolbarModes[e.toolbarIcons]:e.toolbarIcons,s=r.find("."+this.classPrefix+"menu"),l="",c=!1,h=0,d=a.length;d>h;h++){var u=a[h];if("||"===u)c=!0;else if("|"===u)l+='
                • |
                • ';else{var f=/h(\d)/.test(u),g=u;"watch"!==u||e.watch||(g="unwatch");var p=e.lang.toolbar[g],m=e.toolbarIconTexts[g],w=e.toolbarIconsClass[g];p="undefined"==typeof p?"":p,m="undefined"==typeof m?"":m,w="undefined"==typeof w?"":w;var v=c?'
                • ':"
                • ";"undefined"!=typeof e.toolbarCustomIcons[u]&&"function"!=typeof e.toolbarCustomIcons[u]?v+=e.toolbarCustomIcons[u]:(v+='',v+=''+(f?u.toUpperCase():""===w?m:"")+"",v+=""),v+="
                • ",l=c?v+l:l+v}}return s.html(l),s.find('[title="Lowercase"]').attr("title",e.lang.toolbar.lowercase),s.find('[title="ucwords"]').attr("title",e.lang.toolbar.ucwords),this.setToolbarHandler(),this.setToolbarAutoFixed(),this},dialogLockScreen:function(){return e.proxy(t.dialogLockScreen,this)(),this},dialogShowMask:function(i){return e.proxy(t.dialogShowMask,this)(i),this},getToolbarHandles:function(e){var i=this.toolbarHandlers=t.toolbarHandlers;return e&&"undefined"!=typeof toolbarIconHandlers[e]?i[e]:i},setToolbarHandler:function(){var i=this,o=this.settings;if(!o.toolbar||o.readOnly)return this;var r=this.toolbar,n=this.cm,a=this.classPrefix,s=this.toolbarIcons=r.find("."+a+"menu > li > a"),l=this.getToolbarHandles();return s.bind(t.mouseOrTouch("click","touchend"),function(t){var r=e(this).children(".fa"),a=r.attr("name"),s=n.getCursor(),c=n.getSelection();return""!==a?(i.activeIcon=r,"undefined"!=typeof l[a]?e.proxy(l[a],i)(n):"undefined"!=typeof o.toolbarHandlers[a]&&e.proxy(o.toolbarHandlers[a],i)(n,r,s,c),"link"!==a&&"reference-link"!==a&&"image"!==a&&"code-block"!==a&&"preformatted-text"!==a&&"watch"!==a&&"preview"!==a&&"search"!==a&&"fullscreen"!==a&&"info"!==a&&n.focus(),!1):void 0}),this},createDialog:function(i){return e.proxy(t.createDialog,this)(i)},createInfoDialog:function(){var e=this,i=this.editor,o=this.classPrefix,r=['
                  ','
                  ','

                  '+t.title+"v"+t.version+"

                  ","

                  "+this.lang.description+"

                  ",'

                  '+t.homePage+'

                  ','

                  Copyright © 2015 Pandao, The MIT License.

                  ',"
                  ",'',"
                  "].join("\n");i.append(r);var n=this.infoDialog=i.children("."+o+"dialog-info");return n.find("."+o+"dialog-close").bind(t.mouseOrTouch("click","touchend"),function(){e.hideInfoDialog()}),n.css("border",t.isIE8?"1px solid #ddd":"").css("z-index",t.dialogZindex).show(),this.infoDialogPosition(),this},infoDialogPosition:function(){var t=this.infoDialog,i=function(){t.css({top:(e(window).height()-t.height())/2+"px",left:(e(window).width()-t.width())/2+"px"})};return i(),e(window).resize(i),this},showInfoDialog:function(){e("html,body").css("overflow-x","hidden");var i=this.editor,o=this.settings,r=this.infoDialog=i.children("."+this.classPrefix+"dialog-info");return r.length<1&&this.createInfoDialog(),this.lockScreen(!0),this.mask.css({opacity:o.dialogMaskOpacity,backgroundColor:o.dialogMaskBgColor}).show(),r.css("z-index",t.dialogZindex).show(),this.infoDialogPosition(),this},hideInfoDialog:function(){return e("html,body").css("overflow-x",""),this.infoDialog.hide(),this.mask.hide(),this.lockScreen(!1),this},lockScreen:function(e){return t.lockScreen(e),this.resize(),this},recreate:function(){var e=this.editor,t=this.settings;return this.codeMirror.remove(),this.setCodeMirror(),t.readOnly||(e.find(".editormd-dialog").length>0&&e.find(".editormd-dialog").remove(),t.toolbar&&(this.getToolbarHandles(),this.setToolbar())),this.loadedDisplay(!0),this},previewCodeHighlight:function(){var e=this.settings,t=this.previewContainer;return e.previewCodeHighlight&&(t.find("pre").addClass("prettyprint linenums"),"undefined"!=typeof prettyPrint&&prettyPrint()),this},katexRender:function(){return null===i?this:(this.previewContainer.find("."+t.classNames.tex).each(function(){var i=e(this);t.$katex.render(i.text(),i[0]),i.find(".katex").css("font-size","1.6em")}),this)},flowChartAndSequenceDiagramRender:function(){var i=this,r=this.settings,n=this.previewContainer;if(t.isIE8)return this;if(r.flowChart){if(null===o)return this;n.find(".flowchart").flowChart()}r.sequenceDiagram&&n.find(".sequence-diagram").sequenceDiagram({theme:"simple"});var a=i.preview,s=i.codeMirror,l=s.find(".CodeMirror-scroll"),c=l.height(),h=l.scrollTop(),d=h/l[0].scrollHeight,u=0;a.find(".markdown-toc-list").each(function(){u+=e(this).height()});var f=a.find(".editormd-toc-menu").height();return f=f?f:0,a.scrollTop(0===h?0:h+c>=l[0].scrollHeight-16?a[0].scrollHeight:(a[0].scrollHeight+u+f)*d),this},registerKeyMaps:function(i){var o=this,r=this.cm,n=this.settings,a=t.toolbarHandlers,s=n.disabledKeyMaps;if(i=i||null){for(var l in i)if(e.inArray(l,s)<0){var c={};c[l]=i[l],r.addKeyMap(i)}}else{for(var h in t.keyMaps){var d=t.keyMaps[h],u="string"==typeof d?e.proxy(a[d],o):e.proxy(d,o);if(e.inArray(h,["F9","F10","F11"])<0&&e.inArray(h,s)<0){var f={};f[h]=u,r.addKeyMap(f)}}e(window).keydown(function(t){var i={120:"F9",121:"F10",122:"F11"};if(e.inArray(i[t.keyCode],s)<0)switch(t.keyCode){case 120:return e.proxy(a.watch,o)(),!1;case 121:return e.proxy(a.preview,o)(),!1;case 122:return e.proxy(a.fullscreen,o)(),!1}})}return this},bindScrollEvent:function(){var i=this,o=this.preview,r=this.settings,n=this.codeMirror,a=t.mouseOrTouch;if(!r.syncScrolling)return this;var s=function(){n.find(".CodeMirror-scroll").bind(a("scroll","touchmove"),function(t){var n=e(this).height(),a=e(this).scrollTop(),s=a/e(this)[0].scrollHeight,l=0;o.find(".markdown-toc-list").each(function(){l+=e(this).height()});var c=o.find(".editormd-toc-menu").height();c=c?c:0,o.scrollTop(0===a?0:a+n>=e(this)[0].scrollHeight-16?o[0].scrollHeight:(o[0].scrollHeight+l+c)*s),e.proxy(r.onscroll,i)(t)})},l=function(){n.find(".CodeMirror-scroll").unbind(a("scroll","touchmove"))},c=function(){o.bind(a("scroll","touchmove"),function(t){var o=e(this).height(),a=e(this).scrollTop(),s=a/e(this)[0].scrollHeight,l=n.find(".CodeMirror-scroll");l.scrollTop(0===a?0:a+o>=e(this)[0].scrollHeight?l[0].scrollHeight:l[0].scrollHeight*s),e.proxy(r.onpreviewscroll,i)(t)})},h=function(){o.unbind(a("scroll","touchmove"))};return n.bind({mouseover:s,mouseout:l,touchstart:s,touchend:l}),"single"===r.syncScrolling?this:(o.bind({mouseover:c,mouseout:h,touchstart:c,touchend:h}),this)},bindChangeEvent:function(){var e=this,t=this.cm,o=this.settings;return o.syncScrolling?(t.on("change",function(t,r){o.watch&&e.previewContainer.css("padding",o.autoHeight?"20px 20px 50px 40px":"20px"),i=setTimeout(function(){clearTimeout(i),e.save(),i=null},o.delay)}),this):this},loadedDisplay:function(t){t=t||!1;var i=this,o=this.editor,r=this.preview,n=this.settings;return this.containerMask.hide(),this.save(),n.watch&&r.show(),o.data("oldWidth",o.width()).data("oldHeight",o.height()),this.resize(),this.registerKeyMaps(),e(window).resize(function(){i.resize()}),this.bindScrollEvent().bindChangeEvent(),t||e.proxy(n.onload,this)(),this.state.loaded=!0,this},width:function(e){return this.editor.css("width","number"==typeof e?e+"px":e),this.resize(),this},height:function(e){return this.editor.css("height","number"==typeof e?e+"px":e),this.resize(),this},resize:function(t,i){t=t||null,i=i||null;var o=this.state,r=this.editor,n=this.preview,a=this.toolbar,s=this.settings,l=this.codeMirror;if(t&&r.css("width","number"==typeof t?t+"px":t),!s.autoHeight||o.fullscreen||o.preview?(i&&r.css("height","number"==typeof i?i+"px":i),o.fullscreen&&r.height(e(window).height()),s.toolbar&&!s.readOnly?l.css("margin-top",a.height()+1).height(r.height()-a.height()):l.css("margin-top",0).height(r.height())):(r.css("height","auto"),l.css("height","auto")),s.watch)if(l.width(r.width()/2),n.width(o.preview?r.width():r.width()/2),this.previewContainer.css("padding",s.autoHeight?"20px 20px 50px 40px":"20px"),s.toolbar&&!s.readOnly?n.css("top",a.height()+1):n.css("top",0),!s.autoHeight||o.fullscreen||o.preview){var c=s.toolbar&&!s.readOnly?r.height()-a.height():r.height();n.height(c)}else n.height("");else l.width(r.width()),n.hide();return o.loaded&&e.proxy(s.onresize,this)(),this},save:function(){if(null===i)return this;var r=this,n=this.state,a=this.settings,s=this.cm,l=s.getValue(),c=this.previewContainer;if("gfm"!==a.mode&&"markdown"!==a.mode)return this.markdownTextarea.val(l),this;var h=t.$marked,d=this.markdownToC=[],u=this.markedRendererOptions={toc:a.toc,tocm:a.tocm,tocStartLevel:a.tocStartLevel,pageBreak:a.pageBreak,taskList:a.taskList,emoji:a.emoji,tex:a.tex,atLink:a.atLink,emailLink:a.emailLink,flowChart:a.flowChart,sequenceDiagram:a.sequenceDiagram,previewCodeHighlight:a.previewCodeHighlight},f=this.markedOptions={renderer:t.markedRenderer(d,u),gfm:!0,tables:!0,breaks:!0,pedantic:!1,sanitize:a.htmlDecode?!1:!0,smartLists:!0,smartypants:!0};h.setOptions(f);var g=t.$marked(l,f);if(g=t.filterHTMLTags(g,a.htmlDecode),this.markdownTextarea.text(l),s.save(),a.saveHTMLToTextarea&&this.htmlTextarea.text(g),a.watch||!a.watch&&n.preview){if(c.html(g),this.previewCodeHighlight(),a.toc){var p=""===a.tocContainer?c:e(a.tocContainer),m=p.find("."+this.classPrefix+"toc-menu");p.attr("previewContainer",""===a.tocContainer?"true":"false"),""!==a.tocContainer&&m.length>0&&m.remove(),t.markdownToCRenderer(d,p,a.tocDropdown,a.tocStartLevel),(a.tocDropdown||p.find("."+this.classPrefix+"toc-menu").length>0)&&t.tocDropdownMenu(p,""!==a.tocTitle?a.tocTitle:this.lang.tocTitle),""!==a.tocContainer&&c.find(".markdown-toc").css("border","none")}a.tex&&(!t.kaTeXLoaded&&a.autoLoadModules?t.loadKaTeX(function(){t.$katex=katex,t.kaTeXLoaded=!0,r.katexRender()}):(t.$katex=katex,this.katexRender())),(a.flowChart||a.sequenceDiagram)&&(o=setTimeout(function(){clearTimeout(o),r.flowChartAndSequenceDiagramRender(),o=null},10)),n.loaded&&e.proxy(a.onchange,this)()}return this},focus:function(){return this.cm.focus(),this},setCursor:function(e){return this.cm.setCursor(e),this},getCursor:function(){return this.cm.getCursor()},setSelection:function(e,t){return this.cm.setSelection(e,t),this},getSelection:function(){return this.cm.getSelection()},setSelections:function(e){return this.cm.setSelections(e),this},getSelections:function(){return this.cm.getSelections()},replaceSelection:function(e){return this.cm.replaceSelection(e),this},insertValue:function(e){return this.replaceSelection(e),this},appendMarkdown:function(e){var t=(this.settings,this.cm);return t.setValue(t.getValue()+e),this},setMarkdown:function(e){return this.cm.setValue(e||this.settings.markdown),this},getMarkdown:function(){return this.cm.getValue()},getValue:function(){return this.cm.getValue()},setValue:function(e){return this.cm.setValue(e),this},clear:function(){return this.cm.setValue(""),this},getHTML:function(){return this.settings.saveHTMLToTextarea?this.htmlTextarea.val():(alert("Error: settings.saveHTMLToTextarea == false"),!1)},getTextareaSavedHTML:function(){return this.getHTML()},getPreviewedHTML:function(){return this.settings.watch?this.previewContainer.html():(alert("Error: settings.watch == false"),!1)},watch:function(t){var o=this.settings;if(e.inArray(o.mode,["gfm","markdown"])<0)return this;if(this.state.watching=o.watch=!0,this.preview.show(),this.toolbar){var r=o.toolbarIconsClass.watch,n=o.toolbarIconsClass.unwatch,a=this.toolbar.find(".fa[name=watch]");a.parent().attr("title",o.lang.toolbar.watch),a.removeClass(n).addClass(r)}return this.codeMirror.css("border-right","1px solid #ddd").width(this.editor.width()/2),i=0,this.save().resize(),o.onwatch||(o.onwatch=t||function(){}),e.proxy(o.onwatch,this)(),this},unwatch:function(t){var i=this.settings;if(this.state.watching=i.watch=!1,this.preview.hide(),this.toolbar){var o=i.toolbarIconsClass.watch,r=i.toolbarIconsClass.unwatch,n=this.toolbar.find(".fa[name=watch]");n.parent().attr("title",i.lang.toolbar.unwatch),n.removeClass(o).addClass(r)}return this.codeMirror.css("border-right","none").width(this.editor.width()),this.resize(),i.onunwatch||(i.onunwatch=t||function(){}),e.proxy(i.onunwatch,this)(),this},show:function(t){t=t||function(){};var i=this;return this.editor.show(0,function(){e.proxy(t,i)()}),this},hide:function(t){t=t||function(){};var i=this;return this.editor.hide(0,function(){e.proxy(t,i)()}),this},previewing:function(){var i=this,o=this.editor,r=this.preview,n=this.toolbar,a=this.settings,s=this.codeMirror,l=this.previewContainer;if(e.inArray(a.mode,["gfm","markdown"])<0)return this;a.toolbar&&n&&(n.toggle(),n.find(".fa[name=preview]").toggleClass("active")),s.toggle();var c=function(e){e.shiftKey&&27===e.keyCode&&i.previewed()};"none"===s.css("display")?(this.state.preview=!0,this.state.fullscreen&&r.css("background","#fff"),o.find("."+this.classPrefix+"preview-close-btn").show().bind(t.mouseOrTouch("click","touchend"),function(){i.previewed()}),a.watch?l.css("padding",""):this.save(),l.addClass(this.classPrefix+"preview-active"),r.show().css({position:"",top:0,width:o.width(),height:a.autoHeight&&!this.state.fullscreen?"auto":o.height()}),this.state.loaded&&e.proxy(a.onpreviewing,this)(),e(window).bind("keyup",c)):(e(window).unbind("keyup",c),this.previewed())},previewed:function(){var i=this.editor,o=this.preview,r=this.toolbar,n=this.settings,a=this.previewContainer,s=i.find("."+this.classPrefix+"preview-close-btn");return this.state.preview=!1,this.codeMirror.show(),n.toolbar&&r.show(),o[n.watch?"show":"hide"](),s.hide().unbind(t.mouseOrTouch("click","touchend")),a.removeClass(this.classPrefix+"preview-active"),n.watch&&a.css("padding","20px"),o.css({background:null,position:"absolute",width:i.width()/2,height:n.autoHeight&&!this.state.fullscreen?"auto":i.height()-r.height(),top:n.toolbar?r.height():0}),this.state.loaded&&e.proxy(n.onpreviewed,this)(),this},fullscreen:function(){var t=this,i=this.state,o=this.editor,r=(this.preview,this.toolbar),n=this.settings,a=this.classPrefix+"fullscreen";r&&r.find(".fa[name=fullscreen]").parent().toggleClass("active");var s=function(e){e.shiftKey||27!==e.keyCode||i.fullscreen&&t.fullscreenExit()};return o.hasClass(a)?(e(window).unbind("keyup",s),this.fullscreenExit()):(i.fullscreen=!0,e("html,body").css("overflow","hidden"),o.css({width:e(window).width(),height:e(window).height()}).addClass(a),this.resize(),e.proxy(n.onfullscreen,this)(),e(window).bind("keyup",s)),this},fullscreenExit:function(){var t=this.editor,i=this.settings,o=this.toolbar,r=this.classPrefix+"fullscreen";return this.state.fullscreen=!1,o&&o.find(".fa[name=fullscreen]").parent().removeClass("active"),e("html,body").css("overflow",""),t.css({width:t.data("oldWidth"),height:t.data("oldHeight")}).removeClass(r),this.resize(),e.proxy(i.onfullscreenExit,this)(),this},executePlugin:function(i,o){var r=this,n=this.cm,a=this.settings;return o=a.pluginPath+o,"function"==typeof define?"undefined"==typeof this[i]?(alert("Error: "+i+" plugin is not found, you are not load this plugin."),this):(this[i](n),this):(e.inArray(o,t.loadFiles.plugin)<0?t.loadPlugin(o,function(){t.loadPlugins[i]=r[i],r[i](n)}):e.proxy(t.loadPlugins[i],this)(n),this)},search:function(e){var t=this.settings;return t.searchReplace?(t.readOnly||this.cm.execCommand(e||"find"),this):(alert("Error: settings.searchReplace == false"),this)},searchReplace:function(){return this.search("replace"),this},searchReplaceAll:function(){return this.search("replaceAll"),this}},t.fn.init.prototype=t.fn,t.dialogLockScreen=function(){var t=this.settings||{dialogLockScreen:!0};t.dialogLockScreen&&(e("html,body").css("overflow","hidden"),this.resize())},t.dialogShowMask=function(t){var i=this.editor,o=this.settings||{dialogShowMask:!0};t.css({top:(e(window).height()-t.height())/2+"px",left:(e(window).width()-t.width())/2+"px"}),o.dialogShowMask&&i.children("."+this.classPrefix+"mask").css("z-index",parseInt(t.css("z-index"))-1).show()},t.toolbarHandlers={undo:function(){this.cm.undo()},redo:function(){this.cm.redo()},bold:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("**"+i+"**"),""===i&&e.setCursor(t.line,t.ch+2)},del:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("~~"+i+"~~"),""===i&&e.setCursor(t.line,t.ch+2)},italic:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("*"+i+"*"),""===i&&e.setCursor(t.line,t.ch+1)},quote:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();0!==t.ch?(e.setCursor(t.line,0),e.replaceSelection("> "+i),e.setCursor(t.line,t.ch+2)):e.replaceSelection("> "+i)},ucfirst:function(){var e=this.cm,i=e.getSelection(),o=e.listSelections();e.replaceSelection(t.firstUpperCase(i)),e.setSelections(o)},ucwords:function(){var e=this.cm,i=e.getSelection(),o=e.listSelections();e.replaceSelection(t.wordsFirstUpperCase(i)),e.setSelections(o)},uppercase:function(){var e=this.cm,t=e.getSelection(),i=e.listSelections();e.replaceSelection(t.toUpperCase()),e.setSelections(i)},lowercase:function(){var e=this.cm,t=(e.getCursor(),e.getSelection()),i=e.listSelections();e.replaceSelection(t.toLowerCase()),e.setSelections(i)},h1:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();0!==t.ch?(e.setCursor(t.line,0),e.replaceSelection("# "+i),e.setCursor(t.line,t.ch+2)):e.replaceSelection("# "+i)},h2:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();0!==t.ch?(e.setCursor(t.line,0), -e.replaceSelection("## "+i),e.setCursor(t.line,t.ch+3)):e.replaceSelection("## "+i)},h3:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();0!==t.ch?(e.setCursor(t.line,0),e.replaceSelection("### "+i),e.setCursor(t.line,t.ch+4)):e.replaceSelection("### "+i)},h4:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();0!==t.ch?(e.setCursor(t.line,0),e.replaceSelection("#### "+i),e.setCursor(t.line,t.ch+5)):e.replaceSelection("#### "+i)},h5:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();0!==t.ch?(e.setCursor(t.line,0),e.replaceSelection("##### "+i),e.setCursor(t.line,t.ch+6)):e.replaceSelection("##### "+i)},h6:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();0!==t.ch?(e.setCursor(t.line,0),e.replaceSelection("###### "+i),e.setCursor(t.line,t.ch+7)):e.replaceSelection("###### "+i)},"list-ul":function(){var e=this.cm,t=(e.getCursor(),e.getSelection());if(""===t)e.replaceSelection("- "+t);else{for(var i=t.split("\n"),o=0,r=i.length;r>o;o++)i[o]=""===i[o]?"":"- "+i[o];e.replaceSelection(i.join("\n"))}},"list-ol":function(){var e=this.cm,t=(e.getCursor(),e.getSelection());if(""===t)e.replaceSelection("1. "+t);else{for(var i=t.split("\n"),o=0,r=i.length;r>o;o++)i[o]=""===i[o]?"":o+1+". "+i[o];e.replaceSelection(i.join("\n"))}},hr:function(){{var e=this.cm,t=e.getCursor();e.getSelection()}e.replaceSelection((0!==t.ch?"\n\n":"\n")+"------------\n\n")},tex:function(){if(!this.settings.tex)return alert("settings.tex === false"),this;var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("$$"+i+"$$"),""===i&&e.setCursor(t.line,t.ch+2)},link:function(){this.executePlugin("linkDialog","link-dialog/link-dialog")},"reference-link":function(){this.executePlugin("referenceLinkDialog","reference-link-dialog/reference-link-dialog")},pagebreak:function(){if(!this.settings.pageBreak)return alert("settings.pageBreak === false"),this;{var e=this.cm;e.getSelection()}e.replaceSelection("\r\n[========]\r\n")},image:function(){this.executePlugin("imageDialog","image-dialog/image-dialog")},code:function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection("`"+i+"`"),""===i&&e.setCursor(t.line,t.ch+1)},"code-block":function(){this.executePlugin("codeBlockDialog","code-block-dialog/code-block-dialog")},"preformatted-text":function(){this.executePlugin("preformattedTextDialog","preformatted-text-dialog/preformatted-text-dialog")},table:function(){this.executePlugin("tableDialog","table-dialog/table-dialog")},datetime:function(){var e=this.cm,i=(e.getSelection(),new Date,this.settings.lang.name),o=t.dateFormat()+" "+t.dateFormat("zh-cn"===i||"zh-tw"===i?"cn-week-day":"week-day");e.replaceSelection(o)},emoji:function(){this.executePlugin("emojiDialog","emoji-dialog/emoji-dialog")},"html-entities":function(){this.executePlugin("htmlEntitiesDialog","html-entities-dialog/html-entities-dialog")},"goto-line":function(){this.executePlugin("gotoLineDialog","goto-line-dialog/goto-line-dialog")},watch:function(){this[this.settings.watch?"unwatch":"watch"]()},preview:function(){this.previewing()},fullscreen:function(){this.fullscreen()},clear:function(){this.clear()},search:function(){this.search()},help:function(){this.executePlugin("helpDialog","help-dialog/help-dialog")},info:function(){this.showInfoDialog()}},t.keyMaps={"Ctrl-1":"h1","Ctrl-2":"h2","Ctrl-3":"h3","Ctrl-4":"h4","Ctrl-5":"h5","Ctrl-6":"h6","Ctrl-B":"bold","Ctrl-D":"datetime","Ctrl-E":function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();return this.settings.emoji?(e.replaceSelection(":"+i+":"),void(""===i&&e.setCursor(t.line,t.ch+1))):void alert("Error: settings.emoji == false")},"Ctrl-Alt-G":"goto-line","Ctrl-H":"hr","Ctrl-I":"italic","Ctrl-K":"code","Ctrl-L":function(){var e=this.cm,t=e.getCursor(),i=e.getSelection(),o=""===i?"":' "'+i+'"';e.replaceSelection("["+i+"]("+o+")"),""===i&&e.setCursor(t.line,t.ch+1)},"Ctrl-U":"list-ul","Shift-Ctrl-A":function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();return this.settings.atLink?(e.replaceSelection("@"+i),void(""===i&&e.setCursor(t.line,t.ch+1))):void alert("Error: settings.atLink == false")},"Shift-Ctrl-C":"code","Shift-Ctrl-Q":"quote","Shift-Ctrl-S":"del","Shift-Ctrl-K":"tex","Shift-Alt-C":function(){var e=this.cm,t=e.getCursor(),i=e.getSelection();e.replaceSelection(["```",i,"```"].join("\n")),""===i&&e.setCursor(t.line,t.ch+3)},"Shift-Ctrl-Alt-C":"code-block","Shift-Ctrl-H":"html-entities","Shift-Alt-H":"help","Shift-Ctrl-E":"emoji","Shift-Ctrl-U":"uppercase","Shift-Alt-U":"ucwords","Shift-Ctrl-Alt-U":"ucfirst","Shift-Alt-L":"lowercase","Shift-Ctrl-I":function(){var e=this.cm,t=e.getCursor(),i=e.getSelection(),o=""===i?"":' "'+i+'"';e.replaceSelection("!["+i+"]("+o+")"),""===i&&e.setCursor(t.line,t.ch+4)},"Shift-Ctrl-Alt-I":"image","Shift-Ctrl-L":"link","Shift-Ctrl-O":"list-ol","Shift-Ctrl-P":"preformatted-text","Shift-Ctrl-T":"table","Shift-Alt-P":"pagebreak",F9:"watch",F10:"preview",F11:"fullscreen"};var r=function(e){return String.prototype.trim?e.trim():e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")};t.trim=r;var n=function(e){return e.toLowerCase().replace(/\b(\w)|\s(\w)/g,function(e){return e.toUpperCase()})};t.ucwords=t.wordsFirstUpperCase=n;var a=function(e){return e.toLowerCase().replace(/\b(\w)/,function(e){return e.toUpperCase()})};return t.firstUpperCase=t.ucfirst=a,t.urls={atLinkBase:"https://github.com/"},t.regexs={atLink:/@(\w+)/g,email:/(\w+)@(\w+)\.(\w+)\.?(\w+)?/g,emailLink:/(mailto:)?([\w\.\_]+)@(\w+)\.(\w+)\.?(\w+)?/g,emoji:/:([\w\+-]+):/g,emojiDatetime:/(\d{2}:\d{2}:\d{2})/g,twemoji:/:(tw-([\w]+)-?(\w+)?):/g,fontAwesome:/:(fa-([\w]+)(-(\w+)){0,}):/g,editormdLogo:/:(editormd-logo-?(\w+)?):/g,pageBreak:/^\[[=]{8,}\]$/},t.emoji={path:"http://www.emoji-cheat-sheet.com/graphics/emojis/",ext:".png"},t.twemoji={path:"http://twemoji.maxcdn.com/36x36/",ext:".png"},t.markedRenderer=function(i,o){var n={toc:!0,tocm:!1,tocStartLevel:1,pageBreak:!0,atLink:!0,emailLink:!0,taskList:!1,emoji:!1,tex:!1,flowChart:!1,sequenceDiagram:!1},a=e.extend(n,o||{}),s=t.$marked,l=new s.Renderer;i=i||[];var c=t.regexs,h=c.atLink,d=c.emoji,u=c.email,f=c.emailLink,g=c.twemoji,p=c.fontAwesome,m=c.editormdLogo,w=c.pageBreak;return l.emoji=function(e){e=e.replace(t.regexs.emojiDatetime,function(e){return e.replace(/:/g,":")});var i=e.match(d);if(!i||!a.emoji)return e;for(var o=0,r=i.length;r>o;o++)":+1:"===i[o]&&(i[o]=":\\+1:"),e=e.replace(new RegExp(i[o]),function(e,i){var o=e.match(p),r=e.replace(/:/g,"");if(o)for(var n=0,a=o.length;a>n;n++){var s=o[n].replace(/:/g,"");return''}else{var l=e.match(m),c=e.match(g);if(l)for(var h=0,d=l.length;d>h;h++){var u=l[h].replace(/:/g,"");return''}else{if(!c){var f="+1"===r?"plus1":r;return f="black_large_square"===f?"black_square":f,f="moon"===f?"waxing_gibbous_moon":f,':'+r+':'}for(var w=0,v=c.length;v>w;w++){var k=c[w].replace(/:/g,"").replace("tw-","");return'twemoji-'+k+''}}}});return e},l.atLink=function(i){return h.test(i)?(a.atLink&&(i=i.replace(u,function(e,t,i,o){return e.replace(/@/g,"_#_@_#_")}),i=i.replace(h,function(e,i){return''+e+""}).replace(/_#_@_#_/g,"@")),a.emailLink&&(i=i.replace(f,function(t,i,o,r,n){return!i&&e.inArray(n,"jpg|jpeg|png|gif|webp|ico|icon|pdf".split("|"))<0?''+t+"":t})),i):i},l.link=function(e,t,i){if(this.options.sanitize){try{var o=decodeURIComponent(unescape(e)).replace(/[^\w:]/g,"").toLowerCase()}catch(r){return""}if(0===o.indexOf("javascript:"))return""}var n=''+i.replace(/@/g,"@")+""):(t&&(n+=' title="'+t+'"'),n+=">"+i+"")},l.heading=function(e,t,o){var n=e,a=/\s*\]*)\>(.*)\<\/a\>\s*/;if(a.test(e)){var s=[];e=e.split(/\]+)\>([^\>]*)\<\/a\>/);for(var l=0,c=e.length;c>l;l++)s.push(e[l].replace(/\s*href\=\"(.*)\"\s*/g,""));e=s.join(" ")}e=r(e);var h=e.toLowerCase().replace(/[^\w]+/g,"-"),d={text:e,level:t,slug:h},u=/^[\u4e00-\u9fa5]+$/.test(e),f=u?escape(e).replace(/\%/g,""):e.toLowerCase().replace(/[^\w]+/g,"-");i.push(d);var g="';return g+='',g+='',g+=this.atLink(a?this.emoji(n):this.emoji(e)),g+=""},l.pageBreak=function(e){return w.test(e)&&a.pageBreak&&(e='
                  '),e},l.paragraph=function(e){var i=/\$\$(.*)\$\$/g.test(e),o=/^\$\$(.*)\$\$$/.test(e),r=o?' class="'+t.classNames.tex+'"':"",n=a.tocm?/^(\[TOC\]|\[TOCM\])$/.test(e):/^\[TOC\]$/.test(e),s=/^\[TOCM\]$/.test(e);e=!o&&i?e.replace(/(\$\$([^\$]*)\$\$)+/g,function(e,i){return''+i.replace(/\$/g,"")+""}):o?e.replace(/\$/g,""):e;var l='
                  '+e+"
                  ";return n?s?'
                  '+l+"

                  ":l:w.test(e)?this.pageBreak(e):""+this.atLink(this.emoji(e))+"

                  \n"},l.code=function(e,i,o){return"seq"===i||"sequence"===i?'
                  '+e+"
                  ":"flow"===i?'
                  '+e+"
                  ":"math"===i||"latex"===i||"katex"===i?'

                  '+e+"

                  ":s.Renderer.prototype.code.apply(this,arguments)},l.tablecell=function(e,t){var i=t.header?"th":"td",o=t.align?"<"+i+' style="text-align:'+t.align+'">':"<"+i+">";return o+this.atLink(this.emoji(e))+"\n"},l.listitem=function(e){return a.taskList&&/^\s*\[[x\s]\]\s*/.test(e)?(e=e.replace(/^\s*\[\s\]\s*/,' ').replace(/^\s*\[x\]\s*/,' '),'
                • '+this.atLink(this.emoji(e))+"
                • "):"
                • "+this.atLink(this.emoji(e))+"
                • "},l},t.markdownToCRenderer=function(e,t,i,o){var r="",n=0,a=this.classPrefix;o=o||1;for(var s=0,l=e.length;l>s;s++){var c=e[s].text,h=e[s].level;o>h||(r+=h>n?"":n>h?new Array(n-h+2).join("
              • "):"",r+='
              • '+c+"
                  ",n=h)}var d=t.find(".markdown-toc");if(d.length<1&&"false"===t.attr("previewContainer")){var u='
                  ';u=i?'
                  '+u+"
                  ":u,t.html(u),d=t.find(".markdown-toc")}return i&&d.wrap('

                  '),d.html('
                    ').children(".markdown-toc-list").html(r.replace(/\r?\n?\\<\/ul\>/g,"")),d},t.tocDropdownMenu=function(t,i){i=i||"Table of Contents";var o=400,r=t.find("."+this.classPrefix+"toc-menu");return r.each(function(){var t=e(this),r=t.children(".markdown-toc"),n='',a=''+n+i+"",s=r.children("ul"),l=s.find("li");r.append(a),l.first().before("
                  • "+i+" "+n+"

                  • "),t.mouseover(function(){s.show(),l.each(function(){var t=e(this),i=t.children("ul");if(""===i.html()&&i.remove(),i.length>0&&""!==i.html()){var r=t.children("a").first();r.children(".fa").length<1&&r.append(e(n).css({"float":"right",paddingTop:"4px"}))}t.mouseover(function(){i.css("z-index",o).show(),o+=1}).mouseleave(function(){i.hide()})})}).mouseleave(function(){s.hide()})}),r},t.filterHTMLTags=function(t,i){if("string"!=typeof t&&(t=new String(t)),"string"!=typeof i)return t;for(var o=i.split("|"),r=o[0].split(","),n=o[1],a=0,s=r.length;s>a;a++){var l=r[a];t=t.replace(new RegExp("]*)>([^>]*)","igm"),"")}if("undefined"!=typeof n){var c=/\<(\w+)\s*([^\>]*)\>([^\>]*)\<\/(\w+)\>/gi;t="*"===n?t.replace(c,function(e,t,i,o,r){return"<"+t+">"+o+""}):"on*"===n?t.replace(c,function(t,i,o,r,n){var a=e("<"+i+">"+r+""),s=e(t)[0].attributes,l={};e.each(s,function(e,t){'"'!==t.nodeName&&(l[t.nodeName]=t.nodeValue)}),e.each(l,function(e){0===e.indexOf("on")&&delete l[e]}),a.attr(l);var c="undefined"!=typeof a[1]?e(a[1]).text():"";return a[0].outerHTML+c}):t.replace(c,function(t,i,o,r){var a=n.split(","),s=e(t);return s.html(r),e.each(a,function(e){s.attr(a[e],null)}),s[0].outerHTML})}return t},t.markdownToHTML=function(i,o){var r={gfm:!0,toc:!0,tocm:!1,tocStartLevel:1,tocTitle:"目录",tocDropdown:!1,tocContainer:"",markdown:"",markdownSourceCode:!1,htmlDecode:!1,autoLoadKaTeX:!0,pageBreak:!0,atLink:!0,emailLink:!0,tex:!1,taskList:!1,emoji:!1,flowChart:!1,sequenceDiagram:!1,previewCodeHighlight:!0};t.$marked=marked;var n=e("#"+i),a=n.settings=e.extend(!0,r,o||{}),s=n.find("textarea");s.length<1&&(n.append(""),s=n.find("textarea"));var l=""===a.markdown?s.val():a.markdown,c=[],h={toc:a.toc,tocm:a.tocm,tocStartLevel:a.tocStartLevel,taskList:a.taskList,emoji:a.emoji,tex:a.tex,pageBreak:a.pageBreak,atLink:a.atLink,emailLink:a.emailLink,flowChart:a.flowChart,sequenceDiagram:a.sequenceDiagram,previewCodeHighlight:a.previewCodeHighlight},d={renderer:t.markedRenderer(c,h),gfm:a.gfm,tables:!0,breaks:!0,pedantic:!1,sanitize:a.htmlDecode?!1:!0,smartLists:!0,smartypants:!0};l=new String(l);var u=marked(l,d);u=t.filterHTMLTags(u,a.htmlDecode),a.markdownSourceCode?s.text(l):s.remove(),n.addClass("markdown-body "+this.classPrefix+"html-preview").append(u);var f=""!==a.tocContainer?e(a.tocContainer):n;if(""!==a.tocContainer&&f.attr("previewContainer",!1),a.toc&&(n.tocContainer=this.markdownToCRenderer(c,f,a.tocDropdown,a.tocStartLevel),(a.tocDropdown||n.find("."+this.classPrefix+"toc-menu").length>0)&&this.tocDropdownMenu(n,a.tocTitle),""!==a.tocContainer&&n.find(".editormd-toc-menu, .editormd-markdown-toc").remove()),a.previewCodeHighlight&&(n.find("pre").addClass("prettyprint linenums"),prettyPrint()),t.isIE8||(a.flowChart&&n.find(".flowchart").flowChart(),a.sequenceDiagram&&n.find(".sequence-diagram").sequenceDiagram({theme:"simple"})),a.tex){var g=function(){n.find("."+t.classNames.tex).each(function(){var t=e(this);katex.render(t.html().replace(/</g,"<").replace(/>/g,">"),t[0]),t.find(".katex").css("font-size","1.6em")})};!a.autoLoadKaTeX||t.$katex||t.kaTeXLoaded?g():this.loadKaTeX(function(){t.$katex=katex,t.kaTeXLoaded=!0,g()})}return n.getMarkdown=function(){return s.val()},n},t.themes=["default","dark"],t.previewThemes=["default","dark"],t.editorThemes=["default","3024-day","3024-night","ambiance","ambiance-mobile","base16-dark","base16-light","blackboard","cobalt","eclipse","elegant","erlang-dark","lesser-dark","mbo","mdn-like","midnight","monokai","neat","neo","night","paraiso-dark","paraiso-light","pastel-on-dark","rubyblue","solarized","the-matrix","tomorrow-night-eighties","twilight","vibrant-ink","xq-dark","xq-light"],t.loadPlugins={},t.loadFiles={js:[],css:[],plugin:[]},t.loadPlugin=function(e,i,o){i=i||function(){},this.loadScript(e,function(){t.loadFiles.plugin.push(e),i()},o)},t.loadCSS=function(e,i,o){o=o||"head",i=i||function(){};var r=document.createElement("link");r.type="text/css",r.rel="stylesheet",r.onload=r.onreadystatechange=function(){t.loadFiles.css.push(e),i()},r.href=e+".css","head"===o?document.getElementsByTagName("head")[0].appendChild(r):document.body.appendChild(r)},t.isIE="Microsoft Internet Explorer"==navigator.appName,t.isIE8=t.isIE&&"8."==navigator.appVersion.match(/8./i),t.loadScript=function(e,i,o){o=o||"head",i=i||function(){};var r=null;r=document.createElement("script"),r.id=e.replace(/[\./]+/g,"-"),r.type="text/javascript",r.src=e+".js",t.isIE8?r.onreadystatechange=function(){r.readyState&&("loaded"===r.readyState||"complete"===r.readyState)&&(r.onreadystatechange=null,t.loadFiles.js.push(e),i())}:r.onload=function(){t.loadFiles.js.push(e),i()},"head"===o?document.getElementsByTagName("head")[0].appendChild(r):document.body.appendChild(r)},t.katexURL={css:"//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.3.0/katex.min",js:"//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.3.0/katex.min"},t.kaTeXLoaded=!1,t.loadKaTeX=function(e){t.loadCSS(t.katexURL.css,function(){t.loadScript(t.katexURL.js,e||function(){})})},t.lockScreen=function(t){e("html,body").css("overflow",t?"hidden":"")},t.createDialog=function(i){var o={name:"",width:420,height:240,title:"",drag:!0,closed:!0,content:"",mask:!0,maskStyle:{backgroundColor:"#fff",opacity:.1},lockScreen:!0,footer:!0,buttons:!1};i=e.extend(!0,o,i);var r=this,n=this.editor,a=t.classPrefix,s=(new Date).getTime(),l=""===i.name?a+"dialog-"+s:i.name,c=t.mouseOrTouch,h='
                    ';""!==i.title&&(h+='
                    ",h+=''+i.title+"",h+="
                    "),i.closed&&(h+=''),h+='
                    '+i.content,(i.footer||"string"==typeof i.footer)&&(h+='"),h+="
                    ",h+='
                    ',h+='
                    ',h+="
                    ",n.append(h);var d=n.find("."+l);d.lockScreen=function(t){return i.lockScreen&&(e("html,body").css("overflow",t?"hidden":""),r.resize()),d},d.showMask=function(){return i.mask&&n.find("."+a+"mask").css(i.maskStyle).css("z-index",t.dialogZindex-1).show(),d},d.hideMask=function(){return i.mask&&n.find("."+a+"mask").hide(),d},d.loading=function(e){var t=d.find("."+a+"dialog-mask");return t[e?"show":"hide"](),d},d.lockScreen(!0).showMask(),d.show().css({zIndex:t.dialogZindex,border:t.isIE8?"1px solid #ddd":"",width:"number"==typeof i.width?i.width+"px":i.width,height:"number"==typeof i.height?i.height+"px":i.height});var u=function(){d.css({top:(e(window).height()-d.height())/2+"px",left:(e(window).width()-d.width())/2+"px"})};if(u(),e(window).resize(u),d.children("."+a+"dialog-close").bind(c("click","touchend"),function(){d.hide().lockScreen(!1).hideMask()}),"object"==typeof i.buttons){var f=d.footer=d.find("."+a+"dialog-footer");for(var g in i.buttons){var p=i.buttons[g],m=a+g+"-btn";f.append('"),p[1]=e.proxy(p[1],d),f.children("."+m).bind(c("click","touchend"),p[1])}}if(""!==i.title&&i.drag){var w,v,k=d.children("."+a+"dialog-header");i.mask||k.bind(c("click","touchend"),function(){t.dialogZindex+=2,d.css("z-index",t.dialogZindex)}),k.mousedown(function(e){e=e||window.event,w=e.clientX-parseInt(d[0].style.left),v=e.clientY-parseInt(d[0].style.top),document.onmousemove=y});var b=function(e){e.removeClass(a+"user-unselect").off("selectstart")},x=function(e){e.addClass(a+"user-unselect").on("selectstart",function(e){return!1})},y=function(t){t=t||window.event;var i,o,r=parseInt(d[0].style.left),n=parseInt(d[0].style.top);r>=0?r+d.width()<=e(window).width()?i=t.clientX-w:(i=e(window).width()-d.width(),document.onmousemove=null):(i=0,document.onmousemove=null),n>=0?o=t.clientY-v:(o=0,document.onmousemove=null),document.onselectstart=function(){return!1},x(e("body")),x(d),d[0].style.left=i+"px",d[0].style.top=o+"px"};document.onmouseup=function(){b(e("body")),b(d),document.onselectstart=null,document.onmousemove=null},k.touchDraggable=function(){var t=null,i=function(i){var o=i.originalEvent,r=e(this).parent().position();t={x:o.changedTouches[0].pageX-r.left,y:o.changedTouches[0].pageY-r.top}},o=function(i){i.preventDefault();var o=i.originalEvent;e(this).parent().css({top:o.changedTouches[0].pageY-t.y,left:o.changedTouches[0].pageX-t.x})};this.bind("touchstart",i).bind("touchmove",o)},k.touchDraggable()}return t.dialogZindex+=2,d},t.mouseOrTouch=function(e,t){e=e||"click",t=t||"touchend";var i=e;try{document.createEvent("TouchEvent"),i=t}catch(o){}return i},t.dateFormat=function(e){e=e||"";var t=function(e){return 10>e?"0"+e:e},i=new Date,o=i.getFullYear(),r=o.toString().slice(2,4),n=t(i.getMonth()+1),a=t(i.getDate()),s=i.getDay(),l=t(i.getHours()),c=t(i.getMinutes()),h=t(i.getSeconds()),d=t(i.getMilliseconds()),u="",f=r+"-"+n+"-"+a,g=o+"-"+n+"-"+a,p=l+":"+c+":"+h;switch(e){case"UNIX Time":u=i.getTime();break;case"UTC":u=i.toUTCString();break;case"yy":u=r;break;case"year":case"yyyy":u=o;break;case"month":case"mm":u=n;break;case"cn-week-day":case"cn-wd":var m=["日","一","二","三","四","五","六"];u="星期"+m[s];break;case"week-day":case"wd":var w=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];u=w[s];break;case"day":case"dd":u=a;break;case"hour":case"hh":u=l;break;case"min":case"ii":u=c;break;case"second":case"ss":u=h;break;case"ms":u=d;break;case"yy-mm-dd":u=f;break;case"yyyy-mm-dd":u=g;break;case"yyyy-mm-dd h:i:s ms":case"full + ms":u=g+" "+p+" "+d;break;case"full":case"yyyy-mm-dd h:i:s":default:u=g+" "+p}return u},t}}); \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/@links.html b/src/main/resources/static/editor-md/examples/@links.html deleted file mode 100644 index 2cc6a10..0000000 --- a/src/main/resources/static/editor-md/examples/@links.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - @links - Editor.md examples - - - - - -
                    -
                    -

                    @links

                    -

                    Github Flavored Markdown extras syntax

                    -
                    -
                    - -
                    -
                    - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/auto-height.html b/src/main/resources/static/editor-md/examples/auto-height.html deleted file mode 100644 index 4a37c43..0000000 --- a/src/main/resources/static/editor-md/examples/auto-height.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - Auto height - Editor.md examples - - - - - -
                    -
                    -

                    Auto height test

                    -
                    -
                    - -
                    -
                    - -
                    -
                    - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/change-mode.html b/src/main/resources/static/editor-md/examples/change-mode.html deleted file mode 100644 index e25798a..0000000 --- a/src/main/resources/static/editor-md/examples/change-mode.html +++ /dev/null @@ -1,508 +0,0 @@ - - - - - Chnage mode - Editor.md examples - - - - - - -
                    -
                    -

                    Chnage mode

                    -

                    Become to the code editor

                    -

                    Modes :   Themes : - -

                    -
                    -
                    - - -
                    -
                    - - - - - - - - - - -
                    -
                    - -
                    -
                    - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/code-fold.html b/src/main/resources/static/editor-md/examples/code-fold.html deleted file mode 100644 index e2774bc..0000000 --- a/src/main/resources/static/editor-md/examples/code-fold.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - - Code folding - Editor.md examples - - - - - -
                    -
                    -

                    Code folding

                    -

                    Switch code folding : Press Ctrl + Q / Command + Q

                    -
                    -
                    - -
                    -
                    - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/css/style.css b/src/main/resources/static/editor-md/examples/css/style.css deleted file mode 100644 index 0150e3b..0000000 --- a/src/main/resources/static/editor-md/examples/css/style.css +++ /dev/null @@ -1,94 +0,0 @@ -* { - padding: 0; - margin: 0; -} - -*, *:before, *:after { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td,hr,button,article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{ - margin: 0; - padding: 0; -} - -article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary { - display: block; -} - -audio, canvas, video { - display: inline-block; -} - -img { - border: none; - vertical-align: middle; -} - -ul, ol { - /*list-style: none;*/ -} - -.clear { - *zoom: 1; /* for IE 6/7 */ -} - -.clear:before, .clear:after { - height: 0; - content: ""; - font-size: 0; - display: table; - line-height: 0; /* for Opera */ - visibility: hidden; -} - -.clear:after { - clear: both; -} - -body { - font-size: 14px; - color: #666; - font-family: "Microsoft YaHei", "微软雅黑", Helvetica, Tahoma, STXihei, "华文细黑", STHeiti, "Helvetica Neue", Helvetica, Tahoma, "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, "宋体", Heiti, "黑体", sans-serif; - background: #fff; - text-align: center; -} - -#layout { - text-align: left; -} - -#layout > header, .btns { - padding: 15px 0; - width: 90%; - margin: 0 auto; -} - -.btns { - padding-top: 0; -} - -.btns button { - padding: 2px 8px; -} - -#layout > header > h1 { - font-size: 20px; - margin-bottom: 10px; -} - -.btns button, .btn { - padding: 8px 10px; - background: #fff; - border: 1px solid #ddd; - -webkit-border-radius: 3px; - border-radius: 3px; - cursor: pointer; - -webkit-transition: background 300ms ease-out; - transition: background 300ms ease-out; -} - -.btns button:hover, .btn:hover { - background: #f6f6f6; -} \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/custom-keyboard-shortcuts.html b/src/main/resources/static/editor-md/examples/custom-keyboard-shortcuts.html deleted file mode 100644 index 3afc27b..0000000 --- a/src/main/resources/static/editor-md/examples/custom-keyboard-shortcuts.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - - Custom keyboard shortcuts - Editor.md examples - - - - - -
                    -
                    -

                    Custom keyboard shortcuts

                    -
                    -
                    - -
                    -
                    - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/custom-toolbar.html b/src/main/resources/static/editor-md/examples/custom-toolbar.html deleted file mode 100644 index 89177da..0000000 --- a/src/main/resources/static/editor-md/examples/custom-toolbar.html +++ /dev/null @@ -1,178 +0,0 @@ - - - - - 自定义工具栏 - Editor.md examples - - - - - -
                    -
                    -

                    自定义工具栏

                    -

                    Custom toolbar (icons handler)

                    -
                    -
                    - -
                    -
                    - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/define-plugin.html b/src/main/resources/static/editor-md/examples/define-plugin.html deleted file mode 100644 index 8c867e7..0000000 --- a/src/main/resources/static/editor-md/examples/define-plugin.html +++ /dev/null @@ -1,151 +0,0 @@ - - - - - Define extention plugins for Editor.md - Editor.md examples - - - - - -
                    -
                    -

                    Define extention plugins for Editor.md

                    -
                    -
                    - -
                    -
                    - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/delay-renderer-preview.html b/src/main/resources/static/editor-md/examples/delay-renderer-preview.html deleted file mode 100644 index ad343a2..0000000 --- a/src/main/resources/static/editor-md/examples/delay-renderer-preview.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - Delay Rerender & Preview - Editor.md examples - - - - - -
                    -
                    -

                    Delay Rerender & Preview

                    -

                    P.S. If you input the content too much and too fast, You can setting the delay value.

                    -

                    P.S. 适用于输入内容太多太快的情形,但要是一个合理的值,不然会显得预览太慢。打字慢会相对显得慢,打字快时则相对显得快。

                    -
                    -
                    - -
                    -
                    - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/dynamic-create-editormd.html b/src/main/resources/static/editor-md/examples/dynamic-create-editormd.html deleted file mode 100644 index 5644e09..0000000 --- a/src/main/resources/static/editor-md/examples/dynamic-create-editormd.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - 动态创建 Editor.md - Editor.md examples - - - - - -
                    -
                    -

                    动态创建 Editor.md

                    -

                    Dynamic create Editor.md

                    -
                    -
                    - - -
                    -
                    -
                    - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/emoji.html b/src/main/resources/static/editor-md/examples/emoji.html deleted file mode 100644 index a5a6ea6..0000000 --- a/src/main/resources/static/editor-md/examples/emoji.html +++ /dev/null @@ -1,191 +0,0 @@ - - - - - Emoji - Editor.md examples - - - - - - -
                    -
                    -

                    Emoji 表情

                    -

                    Supports:

                    - -
                    -
                    - -
                    -
                    - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/extends.html b/src/main/resources/static/editor-md/examples/extends.html deleted file mode 100644 index 9601860..0000000 --- a/src/main/resources/static/editor-md/examples/extends.html +++ /dev/null @@ -1,153 +0,0 @@ - - - - - Expanded Editor.md - Editor.md examples - - - - - -
                    -
                    -

                    Expanded Editor.md

                    -

                    Expanded of member methods and properties

                    -
                    -
                    - -
                    -
                    - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/external-use.html b/src/main/resources/static/editor-md/examples/external-use.html deleted file mode 100644 index 32e02e2..0000000 --- a/src/main/resources/static/editor-md/examples/external-use.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - External use - Editor.md examples - - - - - -
                    -
                    -

                    External use

                    -

                    External use of toolbar handlers / modal dialog

                    -
                    -
                    - - - - - - - - -
                    -
                    - -
                    -
                    - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/flowchart.html b/src/main/resources/static/editor-md/examples/flowchart.html deleted file mode 100644 index 5149cb7..0000000 --- a/src/main/resources/static/editor-md/examples/flowchart.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - - FlowChart - Editor.md examples - - - - - -
                    -
                    -

                    FlowChart 流程图

                    -

                    Based on flowchart.js:http://adrai.github.io/flowchart.js/

                    -
                    -
                    - -
                    -
                    - - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/form-get-value.html b/src/main/resources/static/editor-md/examples/form-get-value.html deleted file mode 100644 index 5433d45..0000000 --- a/src/main/resources/static/editor-md/examples/form-get-value.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - Form get textarea value - Editor.md examples - - - - - -
                    -
                    -

                    表单取值

                    -

                    Form get textarea value.

                    -
                    -
                    -
                    - - -
                    -
                    - -
                    -
                    -
                    - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/full.html b/src/main/resources/static/editor-md/examples/full.html deleted file mode 100644 index 6fe0818..0000000 --- a/src/main/resources/static/editor-md/examples/full.html +++ /dev/null @@ -1,231 +0,0 @@ - - - - - Full example - Editor.md examples - - - - - - -
                    -
                    -

                    完整示例

                    -

                    Full example

                    -
                      -
                    • Enable HTML tags decode
                    • -
                    • Enable TeX, Flowchart, Sequence Diagram, Emoji, FontAwesome, Task lists
                    • -
                    • Enable Image upload
                    • -
                    • Enable [TOCM], Search Replace, Code fold
                    • -
                    -
                    -
                    - - - - - - - - - - - - - -
                    -
                    -
                    - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/goto-line.html b/src/main/resources/static/editor-md/examples/goto-line.html deleted file mode 100644 index 7eba47b..0000000 --- a/src/main/resources/static/editor-md/examples/goto-line.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - - Goto line - Editor.md examples - - - - - -
                    -
                    -

                    Goto line

                    -
                    -
                    - - - - - - - -
                    -
                    -
                    - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/html-preview-markdown-to-html-custom-toc-container.html b/src/main/resources/static/editor-md/examples/html-preview-markdown-to-html-custom-toc-container.html deleted file mode 100644 index bdf1bd6..0000000 --- a/src/main/resources/static/editor-md/examples/html-preview-markdown-to-html-custom-toc-container.html +++ /dev/null @@ -1,180 +0,0 @@ - - - - - HTML Preview (markdown to html) - Editor.md examples - - - - - - -
                    -
                    -

                    Markdown转HTML的显示处理之自定义 ToC 容器

                    -

                    即:非编辑情况下的HTML预览

                    -

                    HTML Preview (markdown to html and custom ToC container)

                    -
                    -
                    - -
                    - -
                    - -
                    -
                    - -
                    -
                    - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/html-preview-markdown-to-html.html b/src/main/resources/static/editor-md/examples/html-preview-markdown-to-html.html deleted file mode 100644 index ad1cf59..0000000 --- a/src/main/resources/static/editor-md/examples/html-preview-markdown-to-html.html +++ /dev/null @@ -1,142 +0,0 @@ - - - - - HTML Preview(markdown to html) - Editor.md examples - - - - - - -
                    -
                    -

                    Markdown转HTML的显示处理

                    -

                    即:非编辑情况下的HTML预览

                    -

                    HTML Preview(markdown to html)

                    -
                    -
                    - -
                    -
                    - -
                    -
                    - -
                    -
                    - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/html-tags-decode.html b/src/main/resources/static/editor-md/examples/html-tags-decode.html deleted file mode 100644 index 34de0d3..0000000 --- a/src/main/resources/static/editor-md/examples/html-tags-decode.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - 识别和解析 HTML 标签 - Editor.md examples - - - - - -
                    -
                    -

                    识别和解析HTML标签

                    -

                    HTML tags (filter) decode, You can increase safety by filtering the danger label.

                    -

                    注:虽然此功能能极大地扩展 Markdown 语法,但也面临着安全上的风险,所以默认是不开启的。

                    -

                    Update: 可以通过设置 `settings.htmlDecode = "style,script,iframe|on*"`来实现过滤指定标签及属性的解析,提高安全性;

                    -
                    -
                    - - - - -
                    -
                    - -
                    -
                    - - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/image-cross-domain-upload.html b/src/main/resources/static/editor-md/examples/image-cross-domain-upload.html deleted file mode 100644 index 5a63545..0000000 --- a/src/main/resources/static/editor-md/examples/image-cross-domain-upload.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - 图片跨域上传示例 - Editor.md examples - - - - - -
                    -
                    -

                    图片跨域上传示例

                    -

                    Image cross-domain upload example.

                    -
                    -
                    - -
                    -
                    - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/image-upload.html b/src/main/resources/static/editor-md/examples/image-upload.html deleted file mode 100644 index e6fa69b..0000000 --- a/src/main/resources/static/editor-md/examples/image-upload.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - 图片上传示例 - Editor.md examples - - - - - -
                    -
                    -

                    图片上传示例

                    -

                    Image upload example

                    -
                    -
                    - -
                    -
                    - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/images/4.jpg b/src/main/resources/static/editor-md/examples/images/4.jpg deleted file mode 100644 index 948f88c0bdbbddcb17b6a55b071a4ce737067249..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 121969 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%0APzoN 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 diff --git a/src/main/resources/static/editor-md/examples/images/7.jpg b/src/main/resources/static/editor-md/examples/images/7.jpg deleted file mode 100644 index c1806731cffe82bc03e7ab41f6a45c03235335a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 95090 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

                    <7ZSq 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 diff --git a/src/main/resources/static/editor-md/examples/images/8.jpg b/src/main/resources/static/editor-md/examples/images/8.jpg deleted file mode 100644 index f56e66eb6f3aef5deb77b1f0f1fa951dd4a8c05f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17555 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 diff --git a/src/main/resources/static/editor-md/examples/images/editormd-screenshot.png b/src/main/resources/static/editor-md/examples/images/editormd-screenshot.png deleted file mode 100644 index f63f633baf6618a4a2889473aaf0c180b7fca292..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81096 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∈^G2B@W@O;sE zebnSe?J3p$fex1~y%eY=72Jl_m&KaTX>)>=Hy47KrmXoHl|%?;m5SKy`Z;#rld*vb z7{bZh6)S$QOys%oXthicY&?VAe{}p(*XlbRIWy<%{GjJOtH9<%#fru5YR#z+^nj$# z&Xe`;UGr{B%wSocF|v9l&H=NjAgtTBtEqi(V`A4*+LqzLb9VQKaKmN$KH?EbC(8>e zn{lw>BjdZ~Y-x8-`K?TX0w>V51I7Z5N?frAM*0v{nwpY8Y zCfmtMvT=9r#wB&Z7j+kRVIy|})EUp*U-6T9FF$VTH(I;dw-8#1P>&}IrO3aRshb#h za;7`TOB&%e25cZ0hYxg%%v6306((8tD)ZONeRHz4SmMU)RM*1P7ug|}HGA~Az`kB# zXJ+mw11LfEWUI1ocd{({#w?fFX5CBRJXUuC#Eo5l5~>q9Z-jlBgZ22raLZ$i#}KZs zlR!stp83RFeg@M6vI%Q*Rcq=q)$dQqCuV2^wP4R%f--Hbjm2}@B@2%-D_&31&(73( zuK%zI@^t9^1uR2#InvBIpUnU%&VJS+)LBR7R;YG&@NvClj&cc)79GxpR{DVXh)w6~ znM$+;TJub`$z5+`(w*ija+bmmxiitU+fK-i-4_!^a$Qz6><;KO`iArO+X3%2DZH(w z{5;!w9l7U!0fl{=nbw%%hZY0G1KjRORB8~-tqFPVO*mn+{UxL#)t3_Fb`h6Rv&;3! zR^qU;5O@Ao3+L2Tq${7lKQW&Te(F5+rp4j`;o9{U);GY)(`%nmO+o5QW&ei|oiM)B z;{Oov52Ew{kpAwDyMOYuw&iRJl-B|_pJ}fZ`r$_Fe4ZKmE2rqnAqlFfp=Zy|E5I5FAF)-31$cjg?aw> z*;U3-;+_AJUA7VZznE`HkkwM`7C^muo-+A5OZ?wJpPYy6GRwxnX*ri_QV;6Y{rfHA z@Q5b@e7HU=sAfulgEP<8e7>4GB#TKi6Iy4j+K;Ef!P&*Rh(Sw24kallDD;Stx!@!0 zDO~%YaakN3F~-x^?@KGO**l>YdyDx59d=80{+I#>N3*L5u)upC2WJMinv&&z^LQ3? zg3Jtq?a*BdgdG&>t-6J%H|jdhn-TeZTpXNJ?6%_UA4!Dq*m2D;7Ycj+?NSeb?GKC< zFkk^eOZy{uAqP8Kr7P;^7arw9$E|iQf!@*l%*!7MzzAIN#wgyE$2LzBD7qPOa7suo zQK*&G0&TBGn`6wtQGFqx`b>Y<;3yuFHMQVgLRd3@JV7FZrg5ijeyi1u^IRwnjud&J zFm|A5@74HDpbX~B?uZl8-kz>&F=_|n>h;zE8?<091CqW|J76w zJ!970$lO>0f6I2+Z_Du?&AQx5gaeU1r!r_HXVHXMHgtGK8uKF-J)yH`Xz=z)a29W* zl^-U9ATmcih;KPJKIrB%z;eRoM_L`^5lJE;4o(5~l~e4jM6Q{D9<-|~&cR=Vhk{W{ z-=(4LW&B~h{k&w7KWGgA0!-@pf`Eh88rYDd322z4TQw1HZsb4e$mI+A02S>bzR3Ec zmVD*heAV~kElhiVKp*Ti+$>QlQ_a6?fUm2qh4)%DKbrK0*^Nsbmj3ijp$8br%(&R+ z)U)wNo&%R3QZ=K4A&#vK8@-QOR82hgCdlIN$)^oOK4E{F-HKzMT%DEA!d?SguUdO| zr8Tx^`gmpF-bEJ#v)5WF)n+b zUDriD1?|hu& zX#g7KzNpV>?4l%MC&Zb5orUe;4dQxyr{mtmHvb_+JIM9jh;;4#^+~y=0Kv^w`&sjLv4pPe1zjX`44PT)2!MS7Tqj zroCKTSCZUI%s|`S+d>_FoC1)j{gBq5uRbeRs^;JFN#Gv^V2g%$*r8o%v>~OCFK>JP zBYo~v7|#6OiGwXSEY11}la!sPl`d%6JLuVpj8OcIrwPt<*m3guV-T=Jfi1|XpDc2L zLK|xyE;Z9!bK!~5xy!)wDCPT{xl&JH@>V;AUB0$GYmUc?p!Kx~#H8pD2FYW)q{Z z7K>PM$ws6?f*ykb581&lm*hnA<(F3Z)^wYX$cS)o;J2{W?C(hOPKEW${YVka--Lya zOI3fjl*}5Z5Z`$ia5iaU4?d4Ung@2~Dsbt2{H27Q;pv6sX8_rA>yV5FfDQ7Zb9)fZ)&K;?vJwUOtRD;kI1H-A_~ii6{rX=4n!RE?DE%Bae~ zi=a_k@g}Awgc&1qI!|uOi%0wQn2kZtZN;OdrUt8tdhmp>*4kl@k2gXZ`{LbLk(dQX}u=mEbKTv2G01#W@N`Q_>a=IXQ zMbU4;VePAiSiyHQbn~OPZuGqxc>9NS3A|)QH{vc}n#CQ_YIf2rxE+^fYtO{n3=U%W z3+yQb6W~*P)&xT=P=LLk!$F2@3RaQ>a2_)Lo4t=NZJir#e5c4C4Q0-ksdyf&=f9JY z3CwR@-Fcr*<)?6M{gEKktO0;*?HM4Sq&_R^8qOQucj^}OS6E7b4>-XGLCnbco#`3~ zq5*;^0ACa&2ISwTJH>5do9!fJsPv0kP>ENr`Kjii)k}O@a7}2A2NL+%_&SdBC#-uT zxK!ID^%NCf&5Ot3B>sTA6{ZcM=71Y;Z3ivl;_NNU=a-RPnN*Q8b?kIrI!%Ww!!k}_ z4#LH{EUe-9<7KDjc`uzY){9nOSsD|1|9mXMm!?SM%I(?(UAgf~xBAEQIP6{deyqLy z1-iBDNjZKZ(xX z9nT*FnsG!#h$wiT>uHGQN9fbAQi${7gD4I;n9+~_ZKG44e-l=&+#v1XLl;;@xK$f? z=f{tx0Y~^U3mxv;cei~3grFaVxt|GT6J0zQ)~IY?nJigNCSEFt6)ak7|Mttw7Ft|y zMd<0kJLLK4K7kY{J*d1+mN)v7K5wN@{!71n)b5t(kxA7wUGd3mJ84y-mPWKzzG%mc zFQnQxoLWg!ZughvDAg4OXPAe+LC^L%VZ4_v^k;2P+m^Zdn|i#QST4=Tb@t+tU3z2E8yJM^&iNcjirsj*A+HB4M!s{bxRM@rWl&^i z5JWtx+rCnzj?&ie+&WnZv^%9jQF@rq|0RL!e5~+5+SSK1o!x*ouy0U>PD*6|bLVKK z;gogjsy$)SjI=`?zXc1b@@p*Mo%$P1RzDGnFxGnAy2;y417shktm?<=Sg5KvF&kTY zP(#upf}+mKuP3YIUPpL;J*`jxaEUV$+-PQ(hJATxfb!|JQSm3_%MYu6zXu)&4Tw*L ztLw0&v$ ztmC;7k(!-QX3U20T=N6srk~%vgkH`)d|2})Fvh0WRMgRl(XrHGUf-KnpN+vGhxj< zn0^gNqt|rK{oE0qQGfi4r6Wm~p=XcFI@Xk~CgoanMbfBNICZvl4ye-_Axz8p%=em< zDS+KY$p`Uh1sco_oYf{p2xlLtmp5hjOujH~tnPVo8jso%&D#=^BOH9bG;KUo{dr(L zqNJ~%aK+!uH{elaBjRSeMdm-KDKUsr3etA_WquRQH92zi$Ngu7wzIX%G; zJsmIr`{w^;u(DM546w3R;ECKD#cogOd{otdT0^SrlU6+`oaUO(xSD!iR74mpz8Vpm z{@m^2zo~XkH))s92@}>J>ouOJV6(Izw~YSsjb2TLUG*f9-)=}H(I833%!nslXX>Fq zQC_^ryP?QOsyUOcMux^dap4>vff;RSo3_fmdzKDizVLF0X$al7mm@kJD+2-G(~H|X zDKtG4VU}sa56FI5mNnI#TiRz7`*CL+{gR2$_t;F>7^w|54R<(<<=C;N-AUQfO$_a} zdJYR6hWP;CgUUD)PL0qWGF3s_q(^f3KSq&JzIlbQYMv)#=#DORJ)pTS7e1CdQQG>iCTSd&!a@xwzW~< z^cREo(U_I!U3{|MXtAx1j2E_UZ2Rz$qLSus|U0P%I zr+v*Akh!EqZy6ioQ`vjK$C_We4pIh^N3}c6vjbM7UoTgZx)G`fZN3w#7g%%3iC5%5 z<(kcMom$~yGK&rl>Ap8DGz1+PnVs~)VT&^g^8FHDldTH)`TeeLVgON-d46%lv=Nke z;&}AYbb+wg`+KH$(~GxWTftS|S{HQW1%sSw>_MEpZcw?-#t=|`bajvJGU9;aa=QtV zlJqcm7R0!sDd)7M`!D-_CLLjiQudBDsXiChJ*4b;d?)j{9@AWu=|~qxprh^BHyI8q zmmMNg0@3Ec!-SyWd`koF=g^;hC3#O1xe~|3tz0=Qa{1?SD^mL!2}n8;#TUM9Ioa^# zav3}!UtA5j>DgMY8{D}n{n>w!ZXnsl-8|46Y>R&cuOxe~C*xsFL zl+tDWVbg1cf-eZm&nWrAj$0?xW-X=%*Bd=)6JDqU25+p-c=~e5zKC7>C z?~4I8;VV_zS5XhS|KL`=2w%l;eg6n+wbc~p>i_1dQ&TBW9gdM8oQ)ex8Z*DY5G{j! z)8aB)-~Y}NVS(w{iG~p++Oq`yc51$E99zfnYlFLp$BKtzZN4lfbdpFUqGIQRHQB}~ z-fRCJXn&sgitD71uE5BNRcB16RgCGPyJy2xq|EQkuRy!3C;Rp`dB0be1t7N{OqSEd z)4-O&?7`16D<3S~9Ga-lubxfRbfA3IV*-+tIZHe*$&X#rwu}p}{$8AQS~Ck;iY>h5 z4e2rJ;(4TM7Sef#F`bpMBkP;mNKjnUbLYO6Yz7Ye??6q}gVCX8mMIp6ihak)4X*wI z#gn|SgV`If5mmHn>4;Ih0FjTh)Uf~4!R4sHoS5->xPh^d?33eLl*|A-N3Yp;FFh+9 ziT+d|q{dH$PkwA23$PDxe;dxcvtd5p-pFQi{bd4+^Pmc`3Yj6sU?9!SABOy)+bb?s zx9@tc+m;96Nbfy?COqZZ_-$ZiW~Q?Xoajrt)8pwXxz&;A3Fr7C9p&%1qbzJMX>lMt zT?R^kHPc%)c=J=$g%8*~%qZ);OE^n=J`I2V$*ng4NzOxC-tySN-?47`Hvse}2j?aYdJFDu+%qvEdk$i+zKlDcB&sIG=6JBlUer>Jh;n+TT$OKZ`s zkU!r3GUTK&!)$&E&;a1Y66P^TcM}Mk6H{ef>-e>;;daVTr<0-T=)&RIH*m7^tBJYa z+?Z&dFiT3ja>^Ja9I4bR<5oYpJ8ILk5R_*TPx-T7$F41J5uO;GOnbvq(9DsJq*%p& z(!cFnoO#t1ikpjgos_`iTl$-UkaftZ1zp^=QoiJag@V>*HZipD1;LE1A~Qm zh7=wbi5E&dmi7rVV!lH+CkQdB`FH){PxY$y|8Cg)Cxx%7LzPy-&Ii5nZvQ$RM8!WA z4gD-3g5*|^Y+4yOI8gqe+iK)X*!QslP$c+{QDL>o5BsJ-8PlE#aLcXt%LPmBk541f zsqB@FUYAw1%Y3H%e{zOGZ8bMkbq@;5|YUoC4228n)k?xid$w7vkA*8!wXgCkQ|NmVl*1OI+AI|%JW37h|&+O;E_r3SEuj{%S z@X~vUie-d_1#bGL(J%l3;14yrdlFzKIC?F!IMgG=b3WFgX{&S`nsiJ}?{9Y7Uj2r> zcC0c7~sp2K6(bay93KZ-`mDo?!xwAN3OJI2iZ{xH6!@EQfmdb9fa z7B0KrFU7Phy@wr?v$3|B-mdo?lLG6XK8`)VWfrVv=rf)L)btxNK93Lgj20*nhr1-4 z;@1(}vz$il*OF`^)&HDkU|%e)dbUe-Zf1*Ww!?`B1+x97$=Bs(NwGLWs~{@mwy{w! zoEm?I{@h5--%XBc3#YmqGe>Y&R_(hIH*581J!L1Z0&^8ijCv|(kUZ0o#J0;e19>kn zE`d%-a52ccIYLjL&5T!8s=E-kt$@k?jLu9LS0($w#;>S=4sH0Vf>(nZf3-rHV1f1# zm!d7LyNx5MMm2MCU5uqrZFixmMDyBM9!4VA$f&_Ci+T7K{Y!RuNsn7SfhEb}M8FzU zs!}8@#E_LMt~>eZJ6&+voMsnQ9epggTiK;RBEjsLa}DmaZ!5MtoJn&pHnOi9hZbIU`=@uUho?EC1x}@UE*i$!N|-TzVMwm zVPT_nrY$~SRtBi<N`puo{ zhxjFk32U0>b6pPEX2=MXOvc&VXqFs=tqW=Y2R8BBhh<;uatP>o-6$r0^e&;2Gs@zN z#g<*2y5;wKmPjy=20clQugeb;JMUu%=Fc-7z=P**ELXJqwIwKk$F;ox^I6hG8i47-~=}JlO}wLiPsx z>&ezx64g;O)vY+uB&i58GJR+wJ9^&K^BnD{p)+kse~w}rN4fAhS~eHIw&G?oaxzd8+d#ko->s08BcQ2#Izy4#W@Nyq->fs7`$%R$d}F75amE{UcsPaU;@DjhIXO>2*LVOt>Tk_YKB`i@Kgi%hS?M~{^8 z`q<|hR|$QU7ZF~MqmGUl`qo_VwB$`O>ATn!S{5$$e(7vI*Jib(*cxYrn(6GRRuOqy z4R2*xchd1<$X;9}f8O(N1tB<=cD%5G_${_HmDH9$Pmppqvhn6wtN#Q+oQywfZqi1O#>tgr#%DY&;+w$qWcQk5}w7@bokbO!W7|hAXx~IcEraeYjo~-lU+* zx9At-!2Vz~RI;9ZEc2mp7~EA)YBf3-TT~aFaaA?cr*dLADe2I@5)w>FWL1^i#*+iK zJt@WrSOGsh6aL}1a(ph@pg=c4ntey#R(c3HXGHk!yV1zzyiThJ|6>QAI{VJBn#X?| z&Y5{^sh|CALZ#*)D&uRStIX7g_^jp-#{JC+rV@|kDBt?o^s(2s^|fC(y+8C5ZI27T zt>9N`)yAP|EUVTM3u?gS4R=$UfQZYEX!5ocac8#uT4@E5WDb4v+UW59JFBdS6E_LA zaHdd(XE3kF6Iis=&DzK@u}M7@@o0EU?aM~l=w+~a!8HU_Pgv&*d5ZIsf;YZfJW^62 zXZq`LDQ&B~R5^(A(P;mZ2JUgZv4@LTP$%=jKC#a}q)qU~K`N@H7%^OnUKY>709&Y1 zS=wpCcmk?$`H^RS^n`9EkI!acGR~y{u8N{pKbFQ6zcy@@e}kVjIgj%Fz{&6=__!Q7 zY|;8%>F=*T50^^f!m}#uT&J<$_&dbh`efkN$c5owpIbkew~uhIp!>lnDET%MtRUf&w z^A{>)Q$4b2U-=YBE|Cwbdg)zTFN$_(V=3)We`~Uu)ecjRFU(sjQrY8lNTt^4=S;_B z+0F|MJybpn+g$iL=yHg1mnY^{U=9#_MmCLIrKl{Tfd8GLl&$5-KJ)KYJrNFCarz2l zzssdWt?wn@xD(5=lds1j^1K_Gx-Rm6wf04`?!y%W@S>a?zZz_<*b3Fmdj%;3+P?75 zDF{g+-Y`yqVZ~znhT6z%6pzY=>)Y$>PfC_JD|}~Znq-5NJ9K66tUa8`3>8iwYEzyj z6qa1m8jlr@le&CX!RbY5x_IuV__@&4 z`=$U-Z<;^$`h_Wsj-Mws>s?Ei3_Z#-9Buw=#VYUiKfkC$ScEeM3M z+t(Vxm%zc$^)YpBGlj6Rjw4lgjGcnA+@*o$)>bSFCF5AR9)BKPgesV_MB)x1>q=L2 zEoHEz$E1?NI{)ELoh8{{TY{+qXM#7&)3l*xTn+l(F*DrogrAgo1`jlNx-j|HE(w-b76fCdby9R-tB}+!N!@;~zB^#=udF>kEdTGHHzJdc=J0*`mJ#W_JlJl_iBG=AFhuH(f2W{dew^h z@pn~)wN_vrdn-tJ)!F?{Y`E?f7pHEOPXu3QJsFAmiU)r57(Flz`@#f`$%eS@0|0H!)$uwLu(6l}MP}`lq zIUzLG_zFhOdn4>YraFA0xMFd{pVYKehQw|j-YS4ZsZA-~%)W)Zg11--B;P!rSRz&u zv#|AOXN;j_|Rav3q$Y2d6q#>vz}$vUTFpt3tfzEH z>T9$fwnJotE$b-YvUFjNNjj79zGnNnMC)PwN;$MB`RHk4Z}5CR2WiF0iU+^rd2>UL!== z5hi&&!%@Wz94%hIj_V-{%)YTj%#@qCk7(^~r#L74%(YQH`Qe+C8+m-(lS@8KhA&8^ zTDmV!ZjX&De~BHb_nC}|^Af*u+4 zIqo;eGpfh+QPxg~6Gy_*3{fnPS6baFHNXC$kn0)$J)h7Tay@(+ceQ76m^GQ_7$=uI zoA((v1t(}EM;swK6|S?nJelf#!6k)%-3uFWS0L#4kwf1;ysl1jQ8X{+)jmqy>SNcC zL8U@%zT2oUbKa8(PU{j^wA8!;$|V8@{i|2!hE|IH<-!+!h69m0WYGrc0ail@)%$~JBA zESG`+X5oxXQG0*uCT;iK4abZd-pyaH;mHjJ@i&v!E&s;a1;^JWGD6>As%MOVjM6O| zi%yM%ZVErA`>TwLA)RWy9VZ`Ay<6AzsIBgGDg3qh|D|*DKlVAs<`kir!c(mu3RA*k5 zQp3)5Ozo}R?{wYPqSNBQgsLW4-))(=vb9yD@@iNbWD=s^MOo0KFi?MAzId6>u6}8nQHc2y8Zo)Y@vI)tb#7^gP9S$bO~lUWuX7~`yRR~K z0eTlZ%Fjns=Nz~(lV?=eAo>uP1_B*cDU1GDoI%S*u+UIHFV7zmFPCjmQZ%m772&YE z{hLwOH!(E_V)4axHT|`WCb@{j&#xNr#Orm8RQsnzm8l4S+9iccy0<1^B$6`yW7v;R z=_E*}?ldXQ{Z^%qS<+3GILh-dYt1rVSio`hAP`c~=a>KV$QqkURIm4S3pSLJ>tLm? zARHPyweXjGNNlV{=><}CGRG~>Q|Zy~9(CHc}@h{yXMj=efFT`)bbm)QUR9I*ZuDeBbG{|{T~ z|1(@Qd#i)G_}jJx6Sz~EToljuxG-L*#^;CtcMIT8eevGs0&_`Sg<(y z+Fuu#-?nrma<+)a?cNd_?N{RJtDddU7@~QWFY;Uzp2n@KUK221KF2j<8%#s7kXcXe79!H##MKH z#SZb_iFPXl3MM_DRv)iFAqHm}23GE3*yCi6)OkWll<_rtfz6c}8IHeZA0=!-9MY@r zgVhZWav%G%kMZB+==%c}?gE7T9T&XV7V92P+K{zQ-p`=St47X-r;X z0eo2sT2&FR4_B|#zkNDRGw-$J)|V$AovZ63E_BH4=iJtFC^NAr3goDHAc6%FTGQI@ zFC7)vcZgEVNi&M&c>UNOvHDsj>APh)g*k&hBWQY<<~-0t_4XZa{?*XdFT#mDvo@at z&DP6-U0z%YEwbtbRH<2BI@X&8ZJR%K$IqAM+J1_F(Rl0qX6!k!&ggk%_WH#SSHe&^ zLEpVfJMj9CbOVeU zFbCN>kf*W86X$aekpZ92tu7U1l!9M|n~j-}@S}=v`hX48+jg6pu{<{AG_QbGJEj?U zYj66!F=%4ht%6f=B_fsg@x|pZ!~-fc%dMFBWR#OFtsI#N{su-q7TO^0Mb+SEzpm$I zh}pL-Xi;RbpKElC-?OiIlWcs%rN4Zng4xuL|Jxn|EaYBkKjo;M0!4Ks#%5Jbra1XQ z9g9TJkr#%e2A0NJpgGMq?zlzX53$kltdwgrn3^Mh#!IIDdUj>eEOL-u*)TXff5rCF zU3Bh@x6cvZZsjk;XId6?%H4Buz_84bIvVrG8($;|Ma<_Kcwe?fq(opBrCfzNS0Es3 zLpPk!`wNR4a)RN(?6WeB=;t~|=Jq)zyFqORJFbq>kUlLR)sP+HdS{YF6meA)9Yot# z+t~%pv8({Z$MP72jR+U$KYHEd1aDHDl1>OXA)UaazIdcxP0M2w&vfBy9Xp{w$2E^t zmXGWzZIH+UrF?0me-<9!7lG_@PETdj%U8cKLFu6~p#ZQ<=3r$~RGU&pmYDqsT__Oi zptGzERlqloWwdYa7+Xb}+4Jli)<}@eeiPIep1(Dj{N2tl_rtL{pTDcGjO_;qLS|RU zql%xWh#lTPJ|Rk@M`Yp^_-=5lj5np-b1s0J{{{D<)dqrg(q?+Tx{uk?x(NNqh3t<= zae>p@$?{5>P4`sn;0Sp+{5<~LY_#{{^a!W96 zze_l-URCqoE%^53TOXjQ6bAi?7wfB6`5N#&Q{-{p^MA_7_ z#D=bRs}BZCQBPJ2l~nJQRCX86FcL{f2~98h0d&7~^@798_m`V2=~6_gzE#THmp&g6 z($#MB-8R~{e#TLM3av8;3ZAC5oJD$sNTp>o%0IUV#$|wMj)&B zgE^kzV&Lwd<&w>5)7`yx0B=8g6S+ZZR|}1x>2x1xMJ&`qW>5-hHs=2icxc=G9v*Vk zt7W!bd}1>50+La~!|g64DGFVBg3j3~*w(k=b_NytxOV&3Vk=rxaJfPWxmswWonvV#)nhz|q17 ztAMtbq*oLR;5fNg1ZX_qP3>fppwYPPycJ7UR^n#r*J^ytg4AUp*vb!m6KRl0!c4VJjeW^qVcUGb$48S0UK_3?Zy!($_Q3ueE6AjDL~E zp9r%73rvRNn4|U77;v3oQt7JRhH-u<3x?AttLTlK#{dgkEmDHB?Gay3?YleMImj0Z z!Ft8Pg^0Fj0Lrm8&j{w+l`WtijMz!vcxM}dntg2#BUyaMj|!7)O#Z_!up>KjzvkSm zW?EQx9+89s{~dyw?4u@~(azvHQRmO&LQMz|okaz@Jq?Uk-_60uL63@%?Yt#*q&%lH zn^AIgn7a)5MJ5$$*!VOVQ}i(q#oCGhp&2O$9U;N_$zmv>7kux?loy)jGHJi%Zp<6q%Q|dNN^wjSmbt`q;PG6 zmiD0&|I7*3*Cx-R-CcBwwXdeayG+o{z$y8bLdUx}ZO8pgh|;{Fa54XtYIJei+-zYO zs>b0-NE>ZU=Bf3q&E`nGZ@bzMze>CD>Z|nKvqp@~16CRojk2$%4X>gCxJkmhZjSKr z8v%$79{TZ2eJTa_A_wK{3?Z~+6deNY)jLP{YwfHSw_%a>O)JhYp2x*(<7`q9URH8p z7W25$^)z$Yu0(_AV12WCu#(YkLzoN31;U@gP`_^};&_k>n$n0YS8w5bbop_S$o2&+ z%rqJ+(z%f*MC^s$bRV|lZr*=_c!JLn?Je}5dP|8o?$~~qig~1RGh9)`AbHIMKCIw3 zkZ+R9$PF(|d0fArgLwzaO~ejAHVCoe7%nOQljSR=$yS&6PN8u3 zGLN(%WOFjx>iYYLnuBlmd}f@K7ba4L+IyHFNFevPkncECVG!PsCm+1Me*lEf~bSf1|YVZC)cqtQPE%9@_}|IWd2pN9wSbZa3lb?QA`9?}cuUzFIhXOV&|Wn@!sKh2D$v`?|x@$ObPCH@2#T;gy2K zw49BsZT?WNm1SC?AS$CoaTC!>4U)!~lEZT3f!lA6DckU{IAJx&E0&d{=wQ>Xf6K>M zocAwh;b5&()0xwmPXIf*O+HWo9p61zYq&W0dZxRVH}~zkJg?_&ZQI;S|DZH$7Vlxg z{u(AbJ34`y^IvaSqJFfd3(sx%I?e@7N$fk7V=-gFLUmo6aWmBvqn5an znA-KRa!s7?x+mAcycyjH)J|MnY{oX-l>PTVBe!hc05T=HR)MVd9N$}-FW49rRp?-LMlSxa;Jh#=J_!jnVxTc6edoA@#n2;@N zn>st;oj0@Xi8YDe4%R;&m5u5q-JNK4Ux7C-Oe6F7^OEGH^s3&{wa~e1E}O;xYK*F3 z%Yq!zXhjntQg(3so2r1wg=#|9cpjv@rfnBM(6w7*m!BpUa(fQ4$+UD};qqZ-UH3o~ z?~JX0cUv=r3bI!=}o9KOTgm&uh17kGm&BxQmF;Uu{V6gxYBZ>9U;o zq(e^C=)2+6KxxY^imz25ifz%^a_rN$`6i4-ic6Y*5jrmV2qo%FL-m&9s$`Tl)-s1q z3huMz=#Ut{af?mAY3^#Cyn0EnjMA?${gint_)jLU-zG$nyC_9q&=zIyv;?to++Z-7 z87lT%60&)Fqsv$u@3P`VdQs`e(8UMvawB0kgWh0xByT*co}~O-977#)@0dPExV9-a zr!b2m)s-l<4L6ZVnZ)M3Sdn{5i5Y?oNh3RXXFA9pmsG^U=|scOIeavP-%s0J*N>lg zjsu)()U`6PcS$9DM$5*5z^c(dZeBUP235}i z$p#xsL~gn{k~i(Y+!~vC8)fNe?H!~0t3&XGm@&dE{zj2kM4RikSd)bO;&Dt!`e}li zPl|?3A6wJheB%cVSEDu(&*5Qhvdx$Ct&%N@47>z%>+@7TA@)&q$vHJ-h7~RJKH+rk z09Fw#>7Zib61#4;-WDXhBByL_vuh&ueSdEI@3QaCYU?2FL2UWGkwM^ zZ-UKT@~GHM`A@=_R_+erx>&Z0Mwq~Wd5#bb4}D8Wy`>-KjD3&7UF~nem{+$5elYb? z+W+&QG8A&9FvvL+WY8dIyqBoG&N2ziJ=x+pLP7~$L6vf>%gqLyonV_#Q0xHzW$$K0|(cY0o%en*I0fJGBEyc zH0?a`D`j_~*&))8XOdS9E()bA71optlBPN^AO+1=y7(`CfG zU^=8M;L%58Hr+`;_HuVP&up5;d|uIBSQibiV?AfNM^UogL{|Lu^^qtZ;t2GsFwB{eQ~y9Q)6YrHJb%i+eFiWgBz0uN3N$Q)YttrSD{3`#n#nlDxGq zo0zL;^pljaw~=?pFs9gUf&C_-JQjj+kCI&6p1T zX|Mh$|MO)}%jrJ*Bl3!Yn(w^+M;E{UmiiuJr3gydZpMiE4=(XN+jk+I}`bt?>3b~svvB>&v~Ffx6}q3z=I+TglfLb$E<79qE) z#v{WCy;>OV4mZ9z35=c>>yestI;#rROBL5gm5M|*uKcrMgPY$b>rrD~w7wW9V0^LL z!uc>zB(AHlyaBiHXWnl*WMK2EN@JaZlu;;_DfteU3GBJLWW=hi|2&IbFZL`+Q5;l$3&snE3_nFl;Qx% zh?WxOHnoiv3*?FN)yCVeOHum!QXlxk!s`oV@h-+F&hgHh$koeS*CiMke98;~4K&?RbqStk2;Q&#>O3Xz}fMVo*IU)q`u)PKnF% z(*Nv0a(}P@&}N8a{8BLM4J%3$3z(6zW;bqoYWqOn+^x^%%MI-xDz?+Lk;iU!jkRwb z-2mrvG!a^;;Yh4 zV3^hSeZ?Y*^~)LeF%7DP0C{mD<%9Xl@J-wLBPcXt=TWo<&^%Dhtj-!tgQL;TtaCB>3Z@&*p3jaMUIMl-kZt~Uhbn^rF3WB>acKCcpsug{f*gn(mx4} zBkeD@){idKXqli+CoPrD66psMFTsjiQ`y9vNrmMp_O|X%FUWr)er-PsJYzMWB+rzW zk|)HK>~48cZ3sa*8Fsi(WrpoBOly4;<>w5{MpOl4THx#Fh|z}~ycNkSH+VCG_PWAu zetNh2DP2%<+r&2E>89ofbF2KR0Cb%=C~;mo?x~0T=_d;7GxkQ0doIcltRgZ!lk+ss z!9GsXyb;v!HmA*V=9jtGv`jDllF5_mxlThme#*6>P-B8tUBFYdAGRPX&$FK8load{+wc2b$x_|E>x z^2Ev`hq#=SeLZ3W*Cd3PvNXayqa{DWTx&wBuY-~6A2IxE^qh#E($|WMjEhlcg)H+< z{>3r9=8t)&Esw%U9c_u|E6ON73|wrX?7>v!&JOl-`!T%r^2}!vGhuHco9k2)dn?FpL4ci4o1Ov$|A96Vy-z zRmtxTh#j<|gkJxxWH}tx0Ceq(Mk%`%cWJvmu&(kyt`9`iX3Fs|1uv_5)|^GYhqj=( zNsA4Id_QwOo3ZSgZ-Vp{c2kgv$zF4te#HY=H^zr1;4Bbp7H~9GR|dB{ov~zWYvYjs z*Ppe`%JiM;{}d83k}NOcG9)1+OKrC!G70h`>LH_{np)R;PnKxl_M^S6YWbA2?}-NY zXyIr=b-wvhU^L433`0_lV&q&)Qg^5P+xIT^)^Z>1tMn2w4Ew_}c5C~nNkdxIg z^3(Sj5Dp}S8#;kkKmA>J-33p7C5ds|pJMfXM2{R<#+E3$-Fn;kjmACBX9{8Ap;FnM z6gB&0W)--!3D`F~^3F5<=Jx68gZWh?RK?V=>g2Z_^gfEwr=#fns^tE6Q!kBB(J$&q zXX-1-X{H_njIUS6i}CY`-esyAs^H#w_8oAaheYITO65{sWz9|TpMtuRHpGCraaAJ+ zmZ!zvS5UeYVE`MlUo6LiVx^uO>4u&d4u$1F50zLW4Qzk3mn{NAq59vP$LcD`d=fD} zCHaxJ;%|i%K2>AKzr1kzoiv{yij?NDbShA9NbNC9o90UEehJG?MA4CziI3Fj+q?*@ zwJYuRh)wkhwlgE_m(07iefgCd^fFxftXL0nB{({NEZi`XKleI5y8-jKu~4|@$$Cm> zR8-qs)zL@%y`bY&*=+v>LKnu_4|pbjm0#p653GOKQx^&l!h1HDyHMMCB4zCntw-&5 zdp6CEz3KBlzKHp6BVfe#2uRx9?Y+@PIc1<0%-i}h^S{0G5GXzlE=F|`K*!7%xyQuD z%iF7xiCiKCElv=qOx)NIi#&d|^rU$clKVLR@nY3aR^-w6OZXR+qkdX( zvS7}p&I5}*)ymiyyFhnfK*aLnxA{nI;Xga|Um}pE$?J9Ag^9h<;>g2eO%dZeTg!Nj zhSyBRVfyiUPo7DqXH2{h)a1M}c=K^Btx$W{fQ4?ViMf5v4N6O?L9r(E$N5IRfD1Lg zgV$AKyBq`3T}0_h)haoicqy3$WcEK0u;9q( zPu|}|9?QK!O(P0HZr<97As3)X%8o*p6@f0zNQshn@et8>MXWQR7Z;=C-r?eTevq;|; z=ffw&mgZKqQ~W-)isWw7yC~7IGhS#Fz>!~-%J5xDC|Au12_w6>YW@A5ENG3v(3W{D zEZ0|ua12i%IducTGAbIwBha{P*1Xl*x;)NmOmY=^;;ZH^pQ)UH_H^ne#^BMw=RwoU zm*tUV(RMnv(;$Gfp)zOA;4iv)kQ$m|>9ShUX) z^}K$5Caj++dRjhxKpwF_+N*3ZFC&(_7wZ^nHm-W7Zhj~8ZQkcj=3`}OOp*2Pd2H1) z5VoaGIvId5Onm?*tn-oV$BV~J8?Hd&2Cy}lfTcMuG9z5K>aBedz-o$gNeHw$*_be>SHrh(^-D>qpGi1zbACEPtmH7{s%Q5jcd{ zE(XDpD$^9Yod(SN_pOYrYRpL1#)Jm_+Ka4SQ>w6(*7|EAIUg1_^!7I}o@;!_sJIDU z@^eW~452L~wwtPV!}(oZbvG@AR!?R)LGs$d`~*j5x>I_X?XCAon}lFdBuciC5j6)E z`@J!S_+uaBpkaZ`ZkSVcoVe0Bp=`}u;{{(z&LQCz=1g6me2}=cNu$h|NLj-mG+GRf z5P1uLjUk5Rol2r%&RW*y+H4Uu(X-|Em6PMa>Hb@mL5V6CY>m%?Hey%XJ1cK<>H_!0f0WD#T*O|stYo!cn-YhUJ2sCNYKF?&jZKQqSM4A zqq5V-=`)WSkj1)+XcV}0Du!#0&DDehMn^N1dJ8O!T9a zIW9fTMcmZ6ZIh8Gy4qxrREE_4EJS-jo#o`=)<`9nv?%vpb!g~YQ~kU%&m{Gq{nF`N z>&3^u&$kPAsrDFFnq@9~yDNG&6MOG9%OyPi`)9YefA6mDrO6NM|Et>tWbVF4{Y>}j z`;wt=(f>YU`}7}8FYxSMBHxeee-PN<^!HvOzo!~-sd+DBc~Jk~Df9hhP>%ont8x2( zk^cVAx=&z6{eKZs?46wMmy+Ca4nGdqP`>l`X1g`B+NTm*=$QF)C$o}!!W1+1w|@IJ zh620OSPA37zaqnbMF%>t8`#-pUYYo!?=R`r3f|8h2}+5*m`-3twg7M%7QwOX5|vRT zS_X1E%=j8mJ-=I%*CIO>_gVF!zT-3p%n{1&=N`AGoOl1MaipsJt#KOLz@7*0c0k-* zhI9k^*Nc65kyY>H`LVv0t=veq=V<1DPL$m?5XG}WP2f^ujykoxeLxhw{s8#$xeCi; zBo)^JS5nIf5O3AMquY})W&AY|_AymovQyE_kA076P~lcr>psl_=>BCU0pU0<5ua*YwDdA75=2DGd?D zx?}-D1nj9keLm@g(Bu53qlkpz!FQ19A39{X9!8v5v<-D%zm?d@n4tUiV;Y-HYY=_m z)aISH3q)_xdmH24fq%@Lw37?7|oiep22e9})#7gpLXun#A*3WG}bM5<}$E zYHpOT6sK9LCN+A9XyE1E9hO@{Q$<~`e@}&>NbO?GiynT|f$0}if!}x;Q0AuTPy%Ap z)vPzz!M;RXz}Iwp2nbQS6}k(rghuKU!Re}Y1vL9Y=B~|mqea7KJ9V`m>}f{L7kNDh zHN&$r4(;CmfiovQA-7w7ds~rP_+BDuM~5|%H~6eX=8L1O9Mju3t`8oJd}T7U$yexl zJ;@dB_~608_&vJWh=}P0hSRQvMy%Kat*4Y9)Aky?JB;+LSe`uB{~*}XG-UTp%{O%$ zbNFg5LODi)51|2l)3H)UKGJ%nFS|-QCi3QXN=FGF(JB@9XW6#<;e#wX085EUvWcd6 z+UyP(=rk$8VT1_B}gf3j`u)Vl6LP0#Cz#;_4#_YMW#KQ-T5XXAN zhm$z+9?NvH7smQvz#_Pj=N^MguLwwf-Qg#ZdczxC@i>tPL%$&9=qI+oYLHstTXEs{ ziY$;1joD?UO6r&o8m%06SsjdDC~?#{$wba>Q~_VY`S(3Wbo;ND0iWX?YgsAwj>R;U z(Aze^zGUy-gW%shVdu7NY_nb<2|U5uBLJSf{6C)z8rxh6=QLP%Lk}6~3ORt(Hp>MJ zQ~veb`QKrOP#K`!vRF#8S7AMp!MVEl{!(OiI2#EKAZfjQzYka=RA()I|E_u|wY&^m z4Jq1s@08H`qGOxyQd~G|GRBk`5w~SbvF~9&pZ?hqS%G3-H*;yIi@SRyvMU_s1~#My2|LLk&mvGdLgJXY7A{9lXCLg5O}c^5^w4>*eph!KP*A_mbal zuSc?*9N#9$IdG=4Vt*z+=p-j8k0Y4{ZxgPnsDIzxiXngPuyS;z=(z$=G(xN-Wz`*h zkhjTBGZ>t>S#4pp{CB*Ff69NLPu#@rdN-{k{1$GcCg9U2%~C0TafM-*+-n(b{^0*= z#V-KcliL;8(C_R!X(e)?icv>=dp4jO7j9huAZ06N=C}v@FY|Xg7*!J3Wsed(F9b+IEiRw@~uY>gsTm$32uZYxnEO@KNiV$ZX%+L!VDM|9Tfp zqbNYmaP;o%ApIXcx33yfw5q&Htq+wBG7K-qePO};T_0^?5?Tac{b@?VO1d+FWENXV z%jIf;wIMub3H>r|V7RYdQmXqo$pkMHrY00K3#Hhm?y^2;in3^aQ> z-n2p^6as2ihipcwZmeX#FF0IQ#Th5nx!NpA;B2N3`L+2Pb~zNtwxms%neZ*Ysd-1% zEls{UktQ5&G@$}g2(-30bp9wGjCrzMCD&}ZNzfBw;v^3qtC|k17RUwt#2V@NWSM&6 zDA{?DF=m^-?0U63H5(g!QYRGIN=GS^)RqVaB^|xZuN0;)({nNf$Xe~>i5UJR!4`8e z?txyh6pP}(#RN{@1NE%*15q_7?iQqEAzH)S^J!%8zDF~Q@-;0^^;t%sY-S0j1yzo% z?_oi^vI4j!kMRRFJ?Cpsn|*_<*wa4@EM$b5y* zGW|iyik5S-w3FWY=aGl9!lh-H(@vsGaiQi)`kB8f63S58;lZ$H4mAKQCNK!75AN|_ zz|3cPM120DTeCDVWH_`n?UCfz=cLyo*2f_kKN6BJ3R#PCvM(2fLYc#KRNMvsNwY$S zWxVGV>(3Fwd|B6(Si(-o1Ew$cI5TI4ax5ja`3>C+V~_fsn<6r{$c;k zPXSlCD<|e7@Zn-5BPFDq7^1pl;fck1+GWw8WAJAVmMT4)@tWKPcQ)Z*hiwi5+=?`d z@$;4up{6=3N!>g#kI9t4LFug+8xp)HVK}qGJc|d%-p%_q2jOkBlT`txI*#$0Jn=;< zM3!kLnY^dW@#*Uhr4hN*)B7okaeb6#R+#P4izNn$7ndc;l#PoYvgr(5-3ZdH>dwCz zHAh8V_tfJbOBp7M2sg}Ufk^?`O_0N1wviu*;>W#FX97^5;Yo%T1R&S!mj%SntuL`h zrIQ6-xKc(T;c=RnIJ$&iC>#KT5Ix^wevzUkgOG%EG6v`4%_X);JnBvQDN=M{1P}F> znas|}wvB5LWZn5$?JKeFP#rDH6VIoc zhYFIxoLd>uc?`-1rO2q$Q-zyqBeLd3)l*;8>N;nmMUCmEh3MKoRQx5H1RZrvU8 z3J9k?;nJ5{3RoP5yFz`fd(PIeM?#XUTy6!A&0(*4DAO(*7ofFchKMTYT5PI@J$HM8iQXBXx2p3 zB5v8NJNCI=fd`9C>7H~@?Pq{@_k)5$Xp?60pJnVqEC>1?c1h8J_8r;Y`si*E*H9bi zyA615WNOWlV}NsKZ;N1WOsFj3F74wlvTJ|*BcG%p_=v0)2j_SBy`lRy)-DnSfa6pW zn&RwIN8=v|fmZR9rD%Uszx~m>Y+);2_TpM^j8#I>itp0!#Gg`EZN0qcU!}FLvPo0S zONU=$+BT%Fr>&DZJS5pE{q!(IXz5d(Me|9O8l!@DPKPXCp?G)R`d^c%o2Nbz1hVzW zS%V|_3%ly=fQy$DU)t!Pn$@C5PK3kfREd>DIZYit)=RI=ERf^rfmiC%Eh_rv{f>F$ zEBrFac}2{3p@y5fM{cZx9}Mse>D4EZqWsGBH%r)MYC5ZlYp4MDleF@Tbe!?Uy^}3z zpL5c>Pzf;R-ePoo*6+*=r}2-y_&&F>o|{9mc8wF3P%U}%a*9U}j)+{9xtfvo zXVbxl?u>h{`$qVWexlUI0eEGOaij#%=VUAAQMK;b?b&`ikss=sP+VLr4w|5M=I6wJ z;vFc(gAq@gzw*PMPEUSwkk@d-l{3^Zu#l08q{jdZ`6iW;$iXtWxX3V}c&tJ!G%E?( zC93%`TYobRoJZZB(i}MNI=vgOqcy6vo|hIS3+Oh)P>I7@;s^eTno6a+nn8&cOQ!aL zo~%{>2<1H99W!iH4{JUO67CTw_D})zD}$+n`MVDZIKBv(`%S-zED*;tV+ltFz=@k` zOz=E?YV8kgvUTfzv)VLNa2Yz&Qu&Jk{G{s*S@BBz+Ju!IMEl$Xzo01bm(cFUg@D3%uVUJA?wDHqEtQ0g|&X~%-tY4O0MGuu93z2{C#w77X3v-SYhhiHIMhZH#835lgK?!=km8Lu}hjw_3+wUbC~GGxfM#ho?%jH2H)a#AJe^ zxtF#3;#L^SMFPzMu4HCkIb{=eRw*=QPhVnk_w=!)FctXzh z$w>txRlF<&Uw_|@Gi9l777+_ln|gs87%5rM?sJP$(db{try}8H!6vm(-L~&zkvc7) z$tWuJsOEeR{9RKvs8IiK{V^UO40^D8K=q=+x7vR<7mVvknS+dF*ezDu4{n1OLtX`K z2vGG_Z9k<<${7{Tc^30|(yvd8SLTw*Y$m9M9`U*NRshaZ%8LU)f)(a3FSDC#OO#Bn z$rt&sObiMYS9WsD**EVpTso*?nBIqLkwq~gU2FSg73FQiEJ^wBiDqg0X}6V{EMqFB zDIB|UXPmLpu(&T&)Zf*hbc|D}g=slJ0aDao_5Q-BvNTMTG2>+%pASRa2KywOf^di_oXYECBtLlS56nh6$K^!yXe|H&9One4$dNJ81 zt9fLax1n8;tf)m0O7P0@ie4_(9-R!NhPsoSzuepV}ur5~aehu0;<%cnV*m0v9V55uU=I;6D{Gj(c7)~=j z+B|6^#{3?u8w-D^b~9{pXJBi%2mgZ?R_A;4Rc!0)uAgH(8-EGHfI%*>y6g}-#2qbW zG#tpyr}(`r!YJvVa&hyY_9i5hid%#N zTAxQyOW*Pa7|!M;tpGJ!M9b_qak++fa}t3#V|xox<{{)GfXeltx4o8+EEco&c*0>^ zn>=RbWVExbN8!ry9togpz5S%c6ybVUq@r+HB*Y*jYFXGAo1)?9XPnr3wKNJR1>B9f z0@VK|KY!Gu%xyy)$4#(10^)FaM)0=VzT{?{|EAv!xld}BtVh7tG*Ld}^(y2_Vb__Y z<|Zol{_`Gj=738LU)dSj_dR4+)7K=PMg7uE^X@N0%2UM&=ssbxGXyp4FzZD?G#VxO z&~2XW@{{rYt%p{r@2CEyJqn z+IMdh6_FOCL%Km>(IudCNC?s$3s`h7LTRL1T4E8>EiK)(=nN7Dd9ccAb7KtVO0y8k5 z_V32xUXwz*xt4ts4rLXpEMB^O?bWc2iBlrk&JQx*S~H}G6UISh*e#q8J8zq~_xpp_ zGfe;4uCEz4!fWsxoN|4{^bI|q%q@=$_}Ba22wF<@l|fAfZX=TvrpG!@a4A4@NYffY z-Puxw;9od4*=CgIWj^&I#b=360U6{Ex^Ze|N>$zC743tHYFkv!D_J zdZ|pdos_Z@tcmD5-(qbQ5HLCa9Qp;U9K>P9cdg>u^B^exg*iSbqF;tfgz%n_V)MAP zTqK9`0i^5ydvfCczkK??;~Qn~ug(v)xI9-?^8}rb<#-!zx7v#C)`D190VeKmia*!* zfO(Yt4E}DrG`k(`DBW*%2;ukG2^!&qJSP_7o zFCg0i`kq9aSmj5cJ>!xD{klQieR#R2%1lP;6dBFsI(#1WGDb(%Ami)gIzVT1z`3T4 ziJ=N|aRNk{l$U^Cmag7ccbNop560DBwd1-TCuN!{{{+FA;lX_gH2$A$bEV#O=M`DN z4tHyvj#$KhVopf3z1xIEQeI-`N&&})>1SY~_6n{-qBOsK=XPWQ=)|&?#qb5g@vOQj z%i{%BZFt2!U+)c0{}WF8lK8jn7v4NX=$ z3&lKxw8Ay;9o7I_{(0sh34ENwof(dV;OzBq+|RHGrd6b*ZVk*`D50Xm2)PWX`0znj z`Xyv}Ab{4vy($~iZjxGGPL1%2kQG>+s}SCxi#L5f{@v=I>Tb{-utpMLI8aHD{b%-p#~ySjGqc0AeWvvAMJxzs!*wdvfWbEIkv4Nc?72+ zuY|3|H6AOk2Wwv~z`XDJyoX9;Qs;7*MRDCqh#>aeEG9hyniQfT)^ zwMe*_GAho*9{)%hE@4-OcEu;}3RUqf33Q#hULm>|nZHDWZ?t2aT&@=5IR!FH+!IlP zp}JgIKq#6eF7SVoPOrvQo>y-b$HfV^VcZ32Ap9O)J)0laO((80yp7(?_FPR>f3=dC z(y5ZTq#7o(Nq6|1`SlYLJvX*33AC#?!AK&WRkEd*1H3lrnyWDCR?>Y1-2t8@-jHSM zlx@UE2wdnu?Lf};R@zEsBGppLDmdwnB`|938DmH^hdfqe!s&XZ_M9ZX>QjzIRSYq{ zNP&EGbvy$r?<^fL`Q_YrkH9*axpuRnUPt4=21gqM!EWC32egxnRmsW_I}$LZKfJfc z+V@9R_BkJo5fI)jlFkh;+~~~L4(k72JK0fS#E#n0XdKBG98+h>pZ(S2tGTL!VpS(K ztuurPmc@48wGFWja6GO5pO$AngoS4h-+oFi5BT-$o<0wlgCrz+S+QRmeiMB^U72~r zb7|6<&U5z*zJL-K9rW#g?Et3pGxzba%pf;hFPsx*E;L^PBZmO&-Up7j_(pjtk$03OmM}w~>iY%<(t# z`HNAUM2|fla~Xe!@EiIt^Zq^Z|4Yv$vFq(MFqJmAhgUA=;gJcrF+*sqJ)B{lYelz= z#Od-n*+S1#?g(`atSGLFH?5vV4(#kZe|#63B;h$S^Q>ryu&TS(AA_)}Ba zn8Hpi_Ulf;vDV+pJ6J?$1@2krW6yRbf3Q9WkhmJK$=i%k#TL0PlhOCu|1bxExxs}s zMvT+8efZpr?LFEwb%eA&Euy)i5jIwzT%?p4%u!1(sr0)=KJqJ=X;|xPVT;Y<9z0F= zT$Pvf7|FqFpK@oZmu^W+uK4m~YGYGUn~kqNBjXKB(2MQb*XenvkxEdn_O(Z{^l1%V zJ8ucN3k{q#Xr!LmE+F3=L7+Q0nsKwa?dRqjmP+z9N*dJf6K>n$PHfHt)Be&zdHyQE z%mBX0bqx@JtChj8WzDHBpNq$jdvs$BhYQjV83qtmG8Te-5>zW7Au5WBiPj&dR|W}X z@dizJUL9AWMx7-x=VDp%H*UkJ>39G`SaUIlT+)OQyhC3@7P6VfdlCLD52cmp**LbPK2+{Gt9=?t?#09v-d> zMFjECHe{0vHAWjndJA*DKB-SYtw1KomCT;{nm|(H7-&2mdwTZO&NmWr;6=ohuqOda z8+?%{;~SX?R1(kIl1or}E*}L?O(uenQ1*-C;Q+JIVXRZ!>h^CHy7+)GE&&p8_ zG3}}%63)$a+iq{V#in95r1b@IRQaqOaA=H7`l^r7Ao&%>Fa>j9|8c>M+UC+~XJSnd-`C~0EzC3bF#3q3r9?r#5Et%*F z@%T}Pk{DsMVr4ZQlcR|qcXMg&XejcQF~(0rCZ^sUw*iGbaUhHzahA>J$ax2*6WQqg zEwOo^(_g3TGZe2^)OJmPn$qDA_rfuFkMG=)f4WDaTw+%*HX%DojkbXHqFnauOxvIK z-S^TCzx2hTxyn>~Y7r&yNmZ@f`zmMa%*!V;$%NJqO1@RQ)2aB72HC`j5n9HLkVp$&I>t)XoE9|@3jQVoSd~$@siKGsAuXB2R0A+}vljTdpJgxL zN}p5c4`Epkm?s@L@81j}c$zd(9Ylod_}YTcaCq?yNcphJH0taK58n=&MCGvM=07-d z35{tlG#LBm%^(PSbagw$d-%vp$EM* zQV%A4$Isx&l%Wi8T*j?Po0&R{4D{B9vdlr!QG*hsY6eG<2~6T{gbl8T-{Pq5WX@#P zi|*<&hq|2fXful~onO~`+awrSV%p6eFXugOp#q2YkLmBnH98^JdK?E|5>)5$4wK4$ z7AR-mr$<^u93W$bR>nmnzLMmMkw20>xs#0KS-BXlR5KAh#K4u;GR7rH>Gv_PJ+SW| zV^%q^IOf@ZsLi`-=?K?N^M9#jvH+-d7^^j_t9UbHhiyIkZtE=rW}(sg2NkH6#~2Ov z?cvp7yIO(m`Ot@Mh6V!1o$$~i9_Akn0qSB(wOH%tu@L{8CxMQjB>48gtA zFzw1!>dJ;K)tMkyTgyoAA#*#A_^LD4$wrGrD(@T@Kj&DEk*}L^@9ASCb2a)ImZE(L zSAdYb4!p>DuHn^%QIR-cK-N2f8AEJw6WS~?(dikpMLV~tYWv~7r_%5Y?156X8dNJa za%QV7Oau8Z)^P+=pMU>z`igZGQHNPB+2?syyk%878;Q*b*;ileM__q$MHF;xeu-`Jz|P zf=M*}YH0NY_DQi4H70^kxW8HLMv)gn6ezh+qY%G^E>N7!{QBY^<5$jh+ddmV*nxRQ zZUOZo(g*$^g?OM4E^+^8GzA#C$wi(g6wI6IQr=$t88l?F`s2pnJKJDn3f2Q^#-DNY zdEqk@M2Y2MW#7teqaxg{gze%_hg#0(L4g6YUOnvzv(#H%IBw4}M1LKgCRXtV(THkI zSdk@AkE(skPX5qOHI#HfM>*48;E$fR25ANije*9u{;8>^1kEd)FoNmnSyny)xsgw) zWGxG6kg%K?`fE%_#DRuvdaubT*udFi%l5DKzJ($=a7ZPsG0$0wpWh3=;ic2A=n#A| zUZBU5-Tug9^;3}exjiFV)_(G3N4$LL3)$>7i11_ahC<=sDas^yAw%ltB^zQg{20B0 zj>QCKaRmv-G;S2oIRT1JEp^p*-sfeXQ7TB_Z$sadnk*r9Pl#^FGpVhV+tF5;bCW1! ztV7S^#n^@u4&GM>8r~k14VYpcR(al9t$PNZkp>O@7TW{*CDLLWg77bgA8vFxB&4L$w-8X-J4 z6xwGm!yZ?h2bUP^W_9yOH+tR&k*dwZM(eK>F#zjbipQk0gU4StMeT4Jjk^@yNF3Zh zde?8?5mhE8c$jjOc}6)r?^*$J%H{!yPi3K$rmiU|ZpPv1Nj-J3RR&VjDj0ZW_-4gm z{w$_+3*IiW{NG%?N~dyK$kbxhv(=y?@XEmy2J-K zNNhQ28HpO5FUcdcdcLp3@Ih`2N8S;3aK{0)hvV3$VHgb!p95ebykgN`+P8KDTJ|8` z)_3v&Cg&;bj~wgoVpLskg%1Q3@K=)QhuLzUVbG$iK7oYaL=Ld7L}Py6=eWwRa<8|t zLy;vcwRPJrjt$|M)Q$^r0Gq2r%+u5oI*ldDI7-88bM@D$IUb#6J58Z}=QlF1^Qf|r zw_{?yB&{yllVRgy2q{Y;Q}+{~&OQroOb@$Rv9HRfc(jcJ&PQ&`j+kTIsGM&;r{GyX zAN$43*R7F<xa$kC>hy2D+v1E`gBEKk@x1us zZ+62#-F*07NKjw#9FWIJ2H9-^>O%+f#p8LRNw!j;V4W=)ACM4iq`9VCa#%saLixT1 zWvq149C+8)dS|b+P11T^l@<}3_X{T;pI#gb9h1H_l8n<|&eZxKaekE9&)ji<3;uNE zq0zm!nQ1$m9G>!H)AN$;lj&$hBUa!T;q_PfG@mDJqNB&x8?6fJdo385aQemm|q8o7{&82=oO=Rmu6#mxj#^Uv_-6K`bgzn74pldNc2f4qXQ1YlENF%i_qog923J?Qvw|R#HlrOrnsDkF& z+i_T1kxaNrC9o5t%8%67GUG_~>K;1Q9HodQD_i+QOG?g?9+ND-MsdJKgLkGCj68HS zg1_!)5p6WW5yrnK%VWw@mK0XG$v|Ge*-cZFJxgg+*GXv#0*DhYw9Xu-RZ0z-wWm0n z;{3W?qLmJ^(?oL~V0pZDwm*d&IiE`j?u{LOGQ(m^pHjlN<3m#D0iTe)a+1txbMzJS zW3o$1tS^Unv8EFLD@|fGz)7z+>HT!pXj#uP3Mb}F1R)Hg@3fYtSL7WfEpefeyFlOA zkJyGDHUe&1d%N~an9NjYH5mDme4)>UId$3UFlNGXL-wM;4FDjhBN|X4OZUB z%x~LVwB*oA2yAlIMd5J_TUklxT!d@nX~($u(A0&nX)^4amkxU@n{Czx1UBk3Zx4z1 z(>?+Ohd)sEKVa!&)hh)#%&-@1sfIr*quCEXBpHAw-gxkX_2#6x{R2JcVX>D?$6p1e z+R!>W_vGc}c!(_ID-(tXG~L3OmS1raTQ39FcpqGUdwebvRSE;^cTagA@8z!djh&sG zTnOG2<32mRfa{i2n*3B9OUh;-?;Ctyr#u@ytMzS&g5+t5ajW4*2zJnJshGK{$Z{0I zf41r~7k~^KpISFj%Tgcg-x?pbA{C$TW->TXqAP|#su0fRBewc(-}L$9tGBOA%#o{S zgbARP1ZG|sJd=v4@8XizWA+uEcfi-IG3VOczT8q`}FvEYgB1NYm4wBmGhd2pX zdwMze5Kh+`6e=pc4sy)I9Mut3kNWDG`HIB1{Kdmv>sxGH`aMTckp1l6yEa)=zDGU( zm$)^cKd%2>lGQ;LGkZ){hB=C*XU2s3aoOJG#g5i=R-?loYC?Nu{G5mdp{RfDV(V=6 z$3&#Ohadj?K~xl#pVag}K&e)>!44_<^|l_E?PRhEaZ%yh0y`uQzdfHGvILwChNkc? z7S4iA6L$rUwNapR)Y&_s@`2&obWD7hwvg~p`lYLphX|iPzPSJL*#7S#@&A$W6R3TE zlZx5zsXn3hDP`cY599b9b=C zfm6^mB6-lfh>$`Cp<~D4V}w1#zpVQQMK=Q;-aDP$%#k-n2#CZSd2*$Jzj_Mj)f2O( zr{29XykQ0zd|r$;`-*$HBz*~V^3XH8!S|C;+#%s6R;m+XKvWP#KImBo${)`lAYMOY z{sG2O@<5NS6r|kZzSG3I`O%je00f9?ug@N%$b-H6ZaAE~Ebc^$2FCo0P)uwnc%N0_11^GCP*T}KmuW|T2hY*E0nTjN*+lKRn@32Us2v_-+2iFg)DAjne^|8JXx8>nB`tGl?Kx zXg>p5jRnKk&$3UF`$ylzvyrGiRYn*T*C3Zjr1*YO8dOfNoyejX+kp;nP~$6>pCZg) z{Z%@Ekp_^hOzmu5WlwF=CeMAWxqlbvES0q$BeqL1HTR{jm(S?lg#fTVv4jPe%GK&> zV02n*Q+eiB2wz?ne!1(zrq%J63ByCMmInmthpm;ewg>rGb_c*)r%R**JX&1vI43YG zU{D4<%=_d5?H!i&&X5>*Aj1oHz8v59=!g&DW;5Qp|Nvu3;6<1Bcv$Xdc~6a zl(vU7(-avXtUzEWR($t%sqo>DN5Os!JF!OKxIQK z8Rpo?vX?Zx?87Ts2|>a3^n^w9TYp}B$V;2f1J&%GaK-q$#Qiwzrsvma96V_#P^(;C z$sM+ySC~zd6c19Uk@A*ZO3Gf=qj{<4_ubt+Yn#@pq1W*nCi;4OE3*d2=lI|Gz(`g7 zTU;P7@8ZoK`9Qsk?m;XOW$WJ3G{pK&V&52~6+(NO<^DxlTmR?}cYJY84lO z5*`Pdbj64kPsuQg*uoUdyg{{UGRBwAub}-vouhO26CsZ|XLaRQJCm;9KHmyE&c0=( zTCtz18QhK*4R6jYDiFnmnYuLbek-fK$P3wu#cNVEMg~Vu9e+r+e3RrqBH?IXtb*`c z;9+Sk;$^k&f~l+@^QTAjQu#_&CPku=wvUFD3HM30 ztMzGKq0-CMI%{XEeb3iq!m&=+8)h?%)$9dbzYJpWxO7J0;6_*g+d^ZWHM!WdXSK?T z$!13LXjPph>5kvjIBty6_5buV#&3N|2$`W3@#dfDXHN^SP*;=t7RJ= z;t;iLrggwda!EPyW&STMQ=PKS!>7#e&*pU|kYUz>Fry`Hdba#aXbAIRa0x>pLAVYq+c zsBIvRNd1|}5kw3)b_ekPH7-MSz;apyr zH2PHm%%{lzo}<4G*qp*$M>B)z0*C|vri=gjmuL(j)6|gn=0R&D-^$*lJ^Ee$pA0-; zVKT#(D3k)!3(5bpg8Da_t}ks|=#FumT&MoPbIEndtpikhcNKDzY-?8T37RGAZ^^qc z=|_a8au#{|)m`%~5nK-MFm6QtlFgIyL=!--MJEl0`dY?9%SEKmk@i0hF_Z!A%3(y~d|W{c*T9Bj>;0-ZgB;y0CS#t_+WGB^HF%f0{cJjef4yt`?I zaF=mWiaa-`p|X~QQc5N+^%&x9MPs*4!(`eKc5$HWa!EUqvs|-zMpKEDCa1Sb%?gw& zPm{Q;q7nw5@sy>BZ5LVY>X%xuMTbgM4N`rotT~7gD?|hR*#CLh=*Gt*Ku#x8c%fVF zKQkKJYCGs@sWM&@ z7|O+*^#`R5{F3f}^QY9Z7iRJa{4qIg^=X9=kVI?ycD?l+WZ`JaHa;==4n5UlFsl=z zNYMSTn|gIlVmMxgF`JSoFqC{SraO6vu*yG}OtW(yL&YIr{;dxY;UpOO3I2y68C zZH(B9$PPz()gvxp(_};Bs7kq}x0NXPFXzo`hue@ccvkGo*1`t+epGL6w8EiMjI=Hk zLFbl1mBcXd9`}UIz%ijmzS3mhO$oeQF2qp`E|f%B;Oh#i$}+}k|C2rS6MoUPP8N5h zFP>&okeXr!H_f}FPK_!{NT*gzzihwde*f*}>eKO@S65qLv{+TF3=vNhf6K^Xxr@2& zOlnLY)Xhp0oM}p<#uOvg{Vf4z*8e^PXY9#Pq0Diig!6mmMD%7bh8VOHM+HwFLZH8= z%K-!!hK+}oYB*-M8ce=?X0r8YirJYfxh=VvtyElTfJR+Y-j7)1T2O@{q%>F#7>T7w z#)^obRAIi2xc9inuSuT%_301%giCY|$TQz>;FMfkakPf;W}vk^k;cwidzz93 zJv8crJ(r`m=#O^)MISEzS^2`p8<)M)sy`vljn3uv2Tf_gmcp;{EIG(gX1Q+z{Kry< z(Yi4=hvEdM#Fmt_Lr_|$PAnOE+Bb?CS;y77YPE&z#n zQX)qsPTqfd)3P8%z`>pVg6E=MV~43*cgty?O2Sn?tdRDuZel=kADndk`~863DoVa3lN|tZD5yl}R0|Q-)zpq#U`J^$a8yUXFQefC zDM+bUbWc-d#78RzFRLof86RJFOCBpmo`9v$=)L99xZ-5fxRIqhHZZ=OZsif*q)~Om zm*2gKW1ciotK?DKWypib`Nb)_6W_)Xd5OyL)vPrAAn-0cYabGWIDn zrCf_x*Zpkn_$VffBFTZ~m>bElyrH-yWnJ#=QMF;Ld8=V(18HlMfoN-n0ovpPRvUF1oPv?b*g3_X!Q%>!Cb$sxR*eso%7MIjEMC>kCxZfz3Fii)e z!}Gd^PXIPw+9DHeim}q^oyMN^aVwn7x%TKLx<~ti<0D#O!HWpb#3en&SA5qRBAM$_8n9N!VGUo4j{n}a zvBq0w37oV2(pGHvz>t7KSp&z)NFgIMG{P$UT{!{t8F4eK3qVKl%X;4~QS7})y?;JV zF4jV;x2^?%J1CE47($N3{2*2($EU3ICr3e`dUf&Kcef43$F`)j(Fp|X94_#ZnF|0a zS`jwv8(H7`l(K0%M?P8@ey6z+1}1D%Fz!ob07fS0)!=9eu* zn{vlib6d6)d!sr$oGQP6_k}l1*T5|74xfid(mV(x2}C(r@P8rU`&Oo(efDCho#Ux2e%XY@yus-bsfwn` ziVW!E4!IH0!P;(?hVH*1D2#LWo+Pg28RTTD%rp25R`&Wy9&$B!8KF_p7W1q~9BUiF zvDk8Ij+oEuS^u9_c`-+0wr+~Cub!sL#l~Rj-EsG(JNs+s6*_hjx^-o}8gYoTD!)MW42aHY!Z2X;^o%8G13C09cH3o`b zX^<&vA?s}cH9nMRNvqhUzQz|oa2CX|?b?;ScU(zk`jee`mMkN%$@YP9Opv#I#m-8{ zNh^`Sti~!mKg07xX)%nTH?i&ZjtFnVQFJ3n*$c8vyU1h?XuBKNE5(0VAddILe=@}^ z9V3Ne9g)6&Gbu>Ek#aimoSG+(G}pm2<=(^0K+=Jp)nVQBB?!Pdc`c!m$_a`=`JPXy zo+s_(fcjl^r)X#L@_CY1kgOV{*5eIovU?unU|T$~yKVkiDep}vm(J9>XwL4(TF6Su zvt7j#wsX}h7R!gE1A5&w#xJkXXOmrhL^_tH3BMc4E+CnnAy&w7)yc z!NIoc0!di(N2&#CWt zW5S_5YZVJYq@TSp=vBbcIGp9_SX+hdD#}~Z)iM?KXouGP z(i39qPqjf8s0Nbjmx-=&QgR0`(nDtpLC$F8JH~nj6AoVl`%U3kOA%PZ2!BJ0*6Lr> z{%K3cH7C2I>(^sbVa;tifHmXpz0l)A0fNSw&(u=~=Xp*f=1IjeT%jp?2A_hNxF)dI{}K&9(Iv4p)G#W4jsctK>Y8{0kDBgJ)rp~@W9hR9G6e6y)~=ebm9r(=n~;v08{?PzrhByNF2eTr6d#d!*DvyPfVb9eD4p%YP`!8)4YmHz#Spdbb` zeJc%e15>BqcB!5>-#Al^>YYYt9A)1IVwWy8TB=Hujq#kP++rHTWCvGimTHKjBq=Gc zsjYiSH(4HVBA!qF-Q9)&?y&LAuDptEc#p?(HL-dVt^d4f8PR7)aH)(<2qT(&pp@)w zXYiDd_E|`ZWZcWEe4@aoGq_H2;Q-em zvoD!5bn4gN+PSwe>-bbN$@lX)Kgqv4;W8cY=Bud&i9fVMfO~Sx9rd;MhRw%)N1TQ@ z?}3>vM05L?Mp|9xrn^B*FwMQFtm4n#_NRysU^cRSWUkCJ8QI=pS$lF?B62PVyao{%`0=dkXPo9 zdi60%@UVhMUF`Rt*Z`&T%QeD(J_6Rc zpR2#i!9`S7uUl&r+lglMj{$n}et2Vk zc;Q?T9)6-Cc{fC_zbt_EZKm!M;JoH~@n;Vt1Po2~pCIk^;QRb@kapwMNgLzss{>{5 z#(!jz{;OQ#V!cn;#eYhfg`^upnM zIJ7gxzuLv_Hrc&;4`*+X?e#B_E<6BKwTwGa5OL^jK; zFh-sn0|Dw}s9$}31XHl4)ezJ#mUPoRqT%h*xND8H-z?4p=Vq{hps$2&oc}SxzzbmP z^fH9(S()OOKOZV3znvHjQau7Pod-T@6~QGMv)?lL0H^QxYf{R<>jB)@1emG_np&7G zP;2q0VY?BHc8(I_4?BdmlFc77{1rh&{dOLb;cXOSolzShE`z9tJrmLpJ~D(9c0h6> zP$jIk#izcic;00sDtVR5dC(S^3)%`3As{INb(38Hj#r{}z?&;6xA}twfCvU5hmhBY zRRmLnYt;hOkg4Q>o5<$|p^yFgyE9d5e=YLwQdclrEV77&#LhLZV9EL@Xh^oye4Ro7 zKqe1K2a*EsDw+TW0>`_bZ*z3teDM105p}=KVAjd%1*8QtWW`Qsfh|VJ0ri(1@HR(a zcS1(uiF_&;EdYvD$ixXU$xKJeV4-OA3Toqcnag=o0RvAJTGdYL$Lw2~x9 z^aAd_BUy;RZvYHGyTm``QvsVq9k6(Odf9Z3b!W{Go9#ySHjwS`JURZ7x`d$2D)>9M z^*CL0J#j^hRzIrKPzP3j2rKgVQ-s(5&aME-m9iDsaaGI`Z7#pq;vrljKFNS!Ru+WY zEU^Pvw;+R+cW19gCOJ?SXRtwV{?`s#!*IB(=#x*;c^91G~E3@P-^7QUiPvE z&Mi&YzaBAJ*&!B-Yt1Rxu{ACaB05&kOB(z?PwJSFIonUhGj~FIyv;|9;whm$&zhxP z5&IUbLTQ?u#QZJPktaB*tN+ge2uOtN?IgE1F7M%JCf^qG+R0$~Z-T|K+uZQS5s8q& zCN`(%P;pVYs-b&4D6>oMw%lbCkA5I`c(r=T*(AUoMt4tXS_F(2h2v%MbVFigRLw}#P znZ_nFuonbS9((_#Nf+&d2Vv^JWDktO980EYc4Qt(lrufQdQz%ILjiZT*JmUHTE`&5 z>ZV`P6em04xxNojBz%47@$>zi;3;D$#`()iwBN^%0Ob{`{V;9Q-L6_yOL>k$uT*Oq z-L4rMuQtu^0b|T&QKY|Ta2;97{gpHKatq_7^vYuwkCTH6O+)zSTcVYyMse*LvnQob zYG2=eW`%3_Fs7FCQ(yPua-Qp52d@1C@$R_Y=&WCIia`2&ke1&FuFcctq7py~LMPR@zW z9K7Wt)qgaP+7kP-#l!>W4V{EVp%|nqiYkow699EJqg{pJdY)z)7GjWwBi2M8@=n}V zj>vBE-qt5lWmU=R5WR_dp*OXfA)CbdJG$d87kWB4Qqlz%(p^J78IhvA(_|SkE742U zD|^!<#Qc+yxTpT_w@;Xf3i#$CY9AT!PRmU1xZMs%Q(v)cf?5hi>1+;>zbSoRgCCrQ zpk&FqmLgJnjl#vGg=O$Ag@Ea_e59%7-=$M!5B3pUcJh``iI3N>C{d* zkzzBiP33uBwbQCxg-Id~vxhh9{IgH<;r9Dy7ycG1gm-TPsFBi#niYtPS!(Ou7o+&! zVPDzrSdpEub;yK0Qk$7QaVns>S`9QCzZq&VKhBi>L7VMS7$1XK{o?8b@x?R~P4c^g zP2?BB@CX9x^30t6?x|Hue2o3i6#wY#T&zIS=tjSvw!;~12$o(*1$&*A{ zp{OH|&DC`tVRO@{yDNOAS@eV{ZbtD^`rT8lqm_&QBBz+T2*lG z#!GIPp+C51nOl}~Ue_c{1)f=HNq|vwa)X%8(F0*~y&lZ(BewdwgpVZ05+!xuhJAcS z{R6)(M49tbhuDB5!exwe;W|_rTLf}0gjV)~WhaRc=zS6$kjN;?n5m(o5Gn z!}uHlF4s)E-)<;J?|~K#cjQ5?vA#iDsol=M>JBg;@W&IAF*q znq^jT$rXUocQTbyeWUY@7-geT!JTx6O9YT_N%O;|WnwQZZSz;uTt|62(&k>ja)b+v zMZ4y&y?Y62+o0>+k=4kZm(I$a?mU*FL?e#lI@<`=5CD4Qu`x@2dKv64X8wUl!tOv0%e_Ix%}=T+&&H0s{3Q!-F$L}yCpL1V zlUBfpd-}P6Ly>8Yo%yqQn#`03Z%)|MJX{54mp5%?sZ)nqD_%xg^R!DRYkE)|V?NdM zWeL?ncKOBlKKx84lQsnR<66aeebO_}X5M)A`24|H*^hrvMduyIKS2y{ruC6c=}yF^TN4t^FGc(U8ZJl8I1K<~kR{gO{n&oy>OFKfM#$DjYFnq8A1k?~|k z?M&AGB#_mF{YJm#>lmgR>8d>L&pZd0Tm?bz9q{x;!R$Ou%}AgHpEiQ-KjRKC-z%Fi z-HTi_oP!!XjyXN;q7&%xE*Cz9pSQ-x7Cho#e)3^hhkyn7V^xaSCx07HBgWO3oUqAaE?47j9O5Jmba)Pa|sVOfreEO~-S>bka<#yCd zZd?FiM8j@)OwIsOxX*%Zyd`2+8~52mo>D>e`yTjBv6#7~tR1?;WYaF?2LAR)+a#os z*rA5+>NOgUOhofpZN_Q1LR@x;y|;FqSt{Dx5D=+uKji>f+02s0tx8GPee|XJR?6Tm zZv0C72F7W0g0#bl0rBuV{ut|0WHkQxtkfxDy&v5&Waw64yJ5cb_&A>d?RGI&;J#xw zMT(Nv?W%7msnm^tDmg>OJc+5D;AL8xl;}}rr0ZJiP*&%#REF^iJq&s+a@5lR|EPE~ z&e8`%Ws+CDrCtWr7E6}~@9ge0NlisZ6I&#?z=Zp6yViHgwB*Y;dDh(?yIXJV8qj2j zNmQ5e<9AtB4hK6Bb#08q;Pll-P$qYoF4r=IyjMr2?!ILTq*1Tuvz?Ex+1b*S4AZp9 zs-$m87%uMF zl6>V>^+xKWR6-&fyJNT{48BlKe;R5c*|S`d@Dg@IPc2`;I7AZw!ulXx5Bo_Ut)De% z+&$+kF+^v=!LGiuvxi{hSlg#ovq@)yFY?wQdH1a?LsFE2`ABYJ-&)MNhSGg|`lNB7 zCZ}opSV(4Kq*KE3U}NHSMbJ4QZgzuvtfnS(g6UDyBRsX_bT5+osD*I+Oq>z9isCLxc0aAxMjuCvS++YwYp`!-j?X zl(tFX-b@8i#!+Lr6U79dy@23!cfK71G$IU_Bnsa@Zx^R z*jWJrrq}q2jNp-eS>HJW>B}Z?)Yf8{3e-t@Kkh+h zOrazz)o86DDXT@9ETyezq~4k`sg=M`pS3$eC9TaXaS(S5w>ky(g}Yj)#W`ai4Uis(7LHw@I8KaCL5<^EyO^9ugMFAIMJp>44xU6sUxL0&M=)HEipx+KWY4GRs?*Pf;R}0kQo6xz|0@rk z@lW6vsX=KP=hw(O|2r&f2PHvYTrglL+lI$2j3Fp z#ggt;goGmkk^?g(^t~q@oH^j7MLKuYnPE&%WrnswkSL7~vRv>IS9Hl74-KpF@Y}YR zTV}Z9?CM>i4)Ag~ueYE&z9(q2=9sRT5@@IWr^lakk&$^6|HM}Mqo@qZNzq`vZ|B!@ zKqbfK>VkHDy@n~+Wxoj`T>B`zRUV;`T#X<=0Qn4XfXfU}Yq1I;tkCi}qA`~dF$GP~YbkNR@UuBl><*%$m4Nv}(1TdTc6x6+t90)8-S`-xr#9`5 zheZhNO;7p_^&aBJ(fYJH2bAh*hh`<5p&=2EM-ESa@}utBXIwDzs&ocX)kHWRjoclq z_QYH`kSw2eCc(k9Kf@~sm<-Yb3}eQgTA#?aLisnpxvv~QWTyIQ-``C(-r#z@e$J~9 z3fTNZZ%=SqipHYGcVgmh`~;UJar-Sm`)Mci_x*+1UEx!TOEQc|8W$+a9td^;zDAZdCL&vc8!qBt2_-rN?#T|bJ zxSg?VoTssAV9kwO(%j^?Wyrgkwtbe~rx&?_)@Os0P`EBwRx*mo*-vm=Okc34n~?O; zf1M;z5$J*gdeprOWO$Iiq<;HeGEr)dl4hDy@{=egbFHr=_n@4j-rYhu0CCtCRS|2o-m5?!BEDUVP z0E~jbJB0Z}IJ@V;#b2*Ht!n-cyhCL|6u*MRJ+6#N+t1OQ7>!DET08W)`^@LRzZddP zaMnSL>YWEoZ_ha3sU$hg?$!4LA;x5YOBN8B|2`d!JkZ5zd^ix-+fxtU;%~ds)>*cC zBIt7f5)%Vge1>v&10^zw5pHpJ*Y%jiSdflbp++X_xfEkUM8vkaH4vUz-*JG$5TZ0* zZQDpASjaeg_cWgt1Bkh4o|5}p(RlsbOD=BNczzgRA*EU!MlRH4Uw-3Kua&6{dLtT>tSV30vNmh`{T}HF@D;aRh+e_0#F3JUT@d~ z{SgmF>BAjh;fTy|jNb7q2lVGm|LF!F$bokPH7g;ZPqkV9+${9J?qa}m($Wx;W(8sT zUk_zd6eH$w-~9U12L^%fZK+8>0_i_*KtAY7$bM9VI1#;DZy@HAZ&MdHkZl2YFt|ht zQ2?4Z!2F;+zfEc9`JYb!0O~X2iR~dV2n|q#%=)EWp9w_e0_c7JKw5+awf`Oz*D=q4 zhBPb(p8q7xkc(9DEX4uj7c0GyIW7Rr3#8Tl_w%Mxy}PeE=ai15?s1>zN3vmUb@~OZ zYx~^zNF{_C*G%e*J$W%*`iCzgTd`msV*^einR5}v#F$AYy5h{QU!!Xh&AiBdJ;@Qy z81l-&K%|PoRoy#WTqIreSTa;e$?sLVPxW;WcXs{-ZRLsS5GWG_eIQ&JEc_TgX;dMT z&CWvb3Y0-b*QhP?%BYlMV^Q(YPzzN&;tvQVah7i!E(?@2$j zq_1KOkssmQ5=D%%&4ve1nS&l7$YU!L+I|jKlu_sC&zxJoe>V zm?Rqr?ryYss&yMZ`mXoqG^FZ1NgyTA%})>lxPiJ7Fn)pDmnLL9^Y*Uzl;HuL+^ zCudPGO%t(THEb3mN9jxAbyu(?l6IMST!FJ;lfRXv8+{Am3WP&ki4RWz6wc>hQBli9 z{IS_!;IcG&mf3SbmJZpX`bGqYVQDmF#GFk7!-d&H;#JI;4WbhbP4;dfX7{r~TA|ca=C3Ac2ym%+Qmob7YJk%T!iIN@-h|cj(e=Gt>myhkL z;VNXR%cWz*C1RP*9aPj(Dd`O8pi=#mGu7so`YS~<=|9&6yasdHeP+1K;XCwj!y|AZ z3SBxR-6jF$nzhEtu8C+lfeP6g0MYaqV66hy`?I@f9&vclEwg9^J$gt6(5Wf@kOk!= zj+DpXTtnbNJ&h2eKte0?2I3Y#0fD)T5D@xS^e6ENHHRWNYN5^vmR829B~>91$zv(> z+0i^Arv;Kke5tC}!z7~wLOV^Q&Y&WHFhH~b^orh^ui$zV{mmBfZ#KFv|SNKB#CF$yMPdA_d zA@s*efOb$;jAqYh%S1<%p3}JOqW5^WG<7DYAvMx~6e$)GSIwDaP}Gbf1r{SPNWCt7 zS1KUCFr@j6-sg#=1TY!gzmH4=~8M?aNs z8A-KfxnlnWT5tX}QZZ|a0XeIZ~vK1>gDA0R10m|KBCPKc>Fc`5daO+1SlBe#KC5%yF_$k1HH_-F;Cm;X}QXqcKets$|27Um0sx@b(PUDFJd}%S&V!r5`F5}^QTJM*qrt5L(#bWWPb53Vhjn`WH zgLnlYV}JxdL0dW;S2a7TBosqE-1{kc4Gys0pE6@vQ>WU}@@1dFVcAfMl}s;Q&5 zRLx(<<+Efw7KX*#fvO1^%b&aEn`;PWZM@1HK98Inb`^ z{-xHgm_#1as_4dK8vt1sIr-hN!I1Gob<^C=9yD!8;IqD!D5)G;Q4Nu1ZUXvrAF!+F~URV zd&_$8xspU`1Uuj9O*p26y5}1YV&a~ap(F!6Gh;#dGI-~=bdW*LP#Ao($a#CzoOxWe z_1CoJ-sobMF|F6wi+%26%>-7EYvz8Gyrv!s$$~Uec4F)dKC6-}z&e?YXTS2sQ;|ev zXMNvM16nu#?RP4{gTpAI7NV$?KPp?JkpowzUST~CZU+#VZtK3OtIkCm=T-Ko6^0ne zF+JmJf@emfqX%e`cRMeS?<;-;9T$v*1*?CfG_T86x`?=u!vBkfvi#FYU!@rTQ8d{! z0uMO%*uMvX(EVl@@#h!12s|J^_4N6K-Lf} zagjD2)D2%2IcQ0Z&I)apPtnmL!*9D4|0L*Y&|=J%n9USjkPl0$O5b9Cmvq2R9l8q3 zMus&)Mi(4NC1lz%-Y6xV?Q7chQBX+D7vrCIfmzSuYFa1bV)ZlH?wc6i8ejIin~v_n zIi_-4^4@O7BQ(~TMi3-^AX~gx3W#C6?>L`%yI4V}(F#UQ zWAajgMKkZvg)?FlxP>HMmWoBD>CP*`&eC>4bH}Q?n}+t}4000oR1UrxiA70aw~eZY zlUv-DIs`pQR$S;4IR!moIi>LEdH38CgAGLm&7?j_EK#c6a3^W87C`r$KOxMcK=eo+=Cn{WPqI?{BedO4#TYQo&`VCCyOR zvHIJ&b!0t&DXGwfD`0 z01#NA&`We398^{jdK3&iMbmZH~?9=Nha#qLGbHgw?Ly z1r>U&zkVs<+*=E>63 z-$}vCf>oX%8{{miw)KIO@J7gNU4QXDQQljlaR=9+S_YKfJsP4eVekimuU;-rkHsUi z+M6U%37zRs9PI6JzL-CC$Ji(yE+Q1apTMQ(be#=RM|2HBs^Y5oPbIW2lR1@I)m}jw>Suf=}u3V_u<{{Ecg@9p7I@IIK(A8WS(Cto;_6#_!S%s za{}9#ckxMzJQSdMvwdoB@!8HpzKuR&$70jL+P9q26m4bk~wV)=lfQce4ZHTxT z;a16xm<|^Km9{yYUHLbpuNJzo7#_}u* z;_qNvz6@NrF5uG1Az$`%O69wNG-2WCUJ~3qRNMZrbt??IOdaMn`o8ngjfz`x9i7_9 zS1f5aUhrYM0F-Vo2I`T!wVFfiHF6drWtZ@?2}EnWW1Wqp?>LjYtPfL(1hwueY8-gZ zU%Ga;?mEuI39hZqL_6}%`STO?Ny@SHU>dve9ZpK=C1vLFr;$GzetS0^3Du!#F#BxB z@VRR_a%s@M_(;mcVC_8*E`wD9^j&UmX`tjf5-5L(@Nt`*{#mSU{y^dH+-W<+H$R3t zvX02I)bHhjG;N(Z4&RV?8Z7UYzT$qFz-1z_hDsG5?IPTRyzF27&A^2$oSu+DDGhIk z);Rg>OgX<#TITKidwi1zJS%}q!gR)=nzt5fzCT!GZu??x7Vr+=Z^fx7So^DN&;s<% z^a+umA`|he*qxSc$w?e5f%olqTAC{AjjwemB?;&Cq)g@_lzQkOU5cn*5;+X`C8`N- zR)F%$_?;O1uoMu_>pvi$S;5a}ITV;qmwzd4UX8 z8x&@G)D~HR=KJG)mZD(OqztlPEM?qeOFhFqrP<#$7K~(?ay6FMuatCOwkT;;iYFhw zKd#1UaabB{~x`IqOjnK>XLLHz!!-9?>=vQZg51N=#r@r*#V8 zGFFVCJk8O*yGRBM6T~z3nSzi)#22wTba<;P0>X`#l3B?{M$@D0PA@MLI?Ei$gv;DV%sa; znyV%JOOfiMbGW1JYD|5Wrsx5A_mksj6vz8nPq#Y^4=A(~43DixysTj7KO#mntmke*l zBYrq7Kk}N~M`v+{IFE*sDOVV+W-f;-b2OB5zrfPMP1%Br-NiftgF=!}h4Gu6 zUZ3?@RTl$~CCD@);pZdSFCY%K<3WAbLTR;J#H?LQtNqrg?4-O-b9E`UQ9+Upk9f1P zi{($6_XmQ(<9%&b7XH2iVI3$H))gyU{zAS2;GF=-0DuF()4^k0-!uHaezb4Ja92fx zM*sZs&rVkVMk1J?|9J3};C67k&qFM^ZabYPFz9alADE}S2JHTbN)8VJ(fdzic|;vC zQITn9gbjoOfS%sJB6B$v3m`>nl3*8w{Zl4F20Bjw_z&>-DNX?Lvi&_&jW(PphLvuA zJ9bB9)G~l1u2VUNWEJyXeJRBw8!t|nh#KMD?rl^REykGdW%rC1Eo6g$NCc)N{%d{XiWbV` zvGHnIl8=x^ceU|BWe9V(&uB)3KS=2zmqZ!@{ zvB6W7Q1rqrJI}j<#@LD%WWru9>WJGnUxKABNc*N$aq~6RF;Yv6rO*IwA?1I?cS0H1 zyC^i7es>K`?35>qse!phiWc79S4UyXNG6pTcWxYK(syyRrUI_>;>MbSzNWXAn|mX6 za&>jk&?^qZ3-4j=V#7FtIjY^KZAXJ7Z+CDn=p5e87qSu#7XhOsTD`bZE0Q~kG(b&N znw)NVQ_iG(Gk6eRq>cZCcz(CDZUXkQQ)=kES0@cQyrw>RRovofYPjM%-df~EHBvcT zK7MZZ!Hh33)`|84oEtWaw%a54ZX@X+aoK8l2cYgxIIKZ~5WB6_KinBlr;5uRq`+Ck zifK6gy}h#52_RqNyFMjDF{$D@K%!oKk=pKw@SShXLxGEjl3YqX9s1Bgni>p(12IfV z3c0E5q&WVxW})G{tvla~C^a!ij9SvMDu`Spwl*At`7Q^WaSJlzqQ)qI$$8&m9`a%1 zuDX;*>#vjU>B+cuSXq`b9qzPxDh6zU zR$wNQEeomIZ4^Iplh~a98gqKml7xRaP2ed_VS1&u_=Qj@U#5ujd-+HwWn5d(`Vgi{ zibDmXJxzo|+5T5`XKNGJsIPp$jfBWh&5QX7U-4FBt2G`fXHEYjq@+|_oqVPgceh1s z68H^mV}6=gfq0G&oy;$XTO-$1FxxzB$ZDlZ8l-OdEeZF>q_~FJIyyHbZM9!tW{Y=? znAXAl7bD%6TCF=hV__|+&C`KM$ja_ixkILsR=kRJR$$sUoSSS*fuyyjA4Ru_7!i{1R04O`tWro&%NeiC#m?EsD1 zBg0mj{L0WLHU88VR&f`*#X=xoyRyON;fN`C-vClJlpbl__CivBnc zpFCwea>X>}IR~lNIXhy3D#*HcL$WEYSbgNXW_<94)!SW3n|h~lC5xmLy)3l{++gweS(HNxp#E)r+H^Mrt$Lvt^8mZOM4N@<*& zSq-`WlWEy-c)UMqC>23xGw)E{dLEBWS-^3MFlt>-H=+EG<*;6B|9$cy>+C(JuU1_x zGQFWj7FKnRCy&y@)*2Grw9ZNs{;+m^rq84*i5a|mVb$)m{f)F1@WDpt*Xd#@*4pt* zVut08X5zLrlP^=yBycBUG6@q7OL)R(G*pR&r7`uD!`oL5hGB@Cl8)t40aXvpHQl*S z+Q@^jDg@XxB=gdX)#f3<{7L=%DlW*O6uv*#6vsbpZhey+G^YGMwY0WW2oz6mMfF)s z(UFbg>I2V5VN@mVFGWAUS*;uE8|@iaCOe!EVcxpGUDfqA5tvWgwOlhHvBr*x@kTeT zr-x44K7ZXFRMhm<}l1kSe+HS zed0?Oj(fAg%(}A$=G+9E*P=3q5ZBR<0YAgd)?qF5;1;76T}JYFYYY~)Va^>}u*4T9 z*mUM$&zMnkuwzil z#jvg&rF1y1)tafZ>*hTA6b_lXE8X?M9=l8J^D=Yr)Xr94m_Ya#-?xJIe+S}!l1JVj z;2$FX)i@q*4?PjFan272!iQmGL|j-!b_!-#QjU+CFZG%m*P_n(<$+WDf+2|##&mEh z`Z5hx@ziDTUf~o5!0RjqtT=hfrKdwi4!a%2bqOEEGpm72C(zZLu8-`VcNvl(d(b)793Dn^@}g8-&)!DZp4GT^^%vsG$`%e+q`%kycdE<&6?KuR#fOm{Ql6`p5bAT_^lY?zsBpdA zNPNV?-ddymxfC1(#3SIv@OfW5F|A`)uJHDMwb@@*=L5r%vIWKr1ELPT)V|=y_fOM4 z{nySaQ|)*ZemQa|0n_#g6Ra6zf9IY+O%gG~?{~@S|JwF=QKsLMTH3UpN=pj^NO~7Y zpWnT>UT#;hk002T6I?Vb)W2NWP{7}$aBU#w#%jD&!$zJm*ZGIX2X~} z>8!oKzmA!>9fWHbEq*lkNz<}7Le1H1f^~MLxlka`nNzWc%g)vg^Pe+qtK!n_Z)op) zk*A;}_q^Scneao~XH45BH-N?~a)+aOQzo9M$X#}RF@2=ed@Utx6PvZ^d;%l9n(**! zANjAtLt?SIY&^b)u0EV?ZPYUP(>?X4cq2m{k-!PgNk<)iy0uBz;ctk8iV?z@TPdL` z7K4&eg>@>ZP=U(F_w8cyB3Qa&IDXUQ1|{LS5|)PP-M+VbQEh=#&~#_QHM<{_ ztZz@eHWkuN^O<*cXXov9bS#HnVp|W!SIL_+LCh9)ci@z}`Z4%qRJZVkqsq^Hi9`^j za78(`6c`~5uFf$DSPy5fOBIP4mM7J?5*=Y82a(F=mo91vI>uZKn~d5cj&DVFx=}HS z<;c23XY>Zi4&O=>x4D&znhg10fNZ;G(zM7MX`1!Jdo#|H|MZ~!etOepGc6`_(h0%8 zBpHybJ-;Ouw0mBu(BxWw%3Dn*kW5kpe`W#grPT7r#}&4rjKHb9?8672*G}G-l`@g6 z4`;`>1bzeAk5=nN)UOl8U=<`ZxKm3ifqc2!>Md7%cj%Q8SxM{HH|kush4s7Yv>h+PF?mY0a9eX*x>#bEfIV!iz#NizTwd%qNC5S=N^8%xTpt z)pFOUhu;rTR7G@gK5~=(&-=gI)_Lptp)2Yr!DSI&nmH>0^+pn#Z}n<&sY-a9jO>k# zG;8iUC}c2_NEb^n+DGm#X*Q#6GRw6qx6ZItAXJK>;xS?ietXE7=|G##MYY)o4C1); zR<{|PkXXpfx+f@#!N)Fc_J-EPw!m@2tfmh-Dm2zhFcf}W|WipvvCX4m(FHr@=Sdulwxi*NqXKsm5 z`QtdQZL8qY+O_vaMouHHo;OERJ{-hWVu&rp$(c0kTT^fEsD~VU&*sG1G8mOCjxP4j z;|ZGgz1W(qd1(m(Y5QD-BvuUt(*HGYi)pC^(ppF24hTd!us9V7v-_@eaS}JtbSILgw0_nYZKZswoGM()8Dno-wBDhDy|^Z zv|=`Wm3a@7i@C5It|ru{MS0C`4gVxmpQ8iLlSzaMxS@#%Q?aDDwd97U0sUq^PjOrV z1#~lP`TQ&9ogXx-OfDf@4`OY@tL!XW992h49$EA!%B!Z3HX0so^{Vr~=#MY?$74Qa zUD5Q&wcidCUYcMuB~>}oZi;I2AN627(Nw#aG*(5ldvBZl(WyBGChj^#ma-~B>DTay z<$V$BdJMV@#{oNbfTL-@qJ@=C+^VFF+rOW9&y~ynpl2BOrYZ?fUJ z23mb{!@kQxb44QjgFS~ zF~>GnGG4No)@go-2-+D;bLAQ>zmtt@ExDOMi-f4|#mhal+erqR`99=Uel!*~v23zE zlBF6&-{6+-V$)Iq_Bsr&Da>^u9h}!)$T=6AGWCDv_x`arfE?>%#L=XtY!)}pZRBMy ze7VYi(Y1KS)&$5>PpY`v2Y@`BO4hb?QZhNa&JlpXt4v&5XjOrPFUObg9zQO({=Y?zsFSU~Feu|1UJ%FD;7RRRNN`f|3dvOHu z`>mPeqhEeVt@`@}2JXBDrs4XVzd&nG)*e21bdRXDO1FkjT499N&KgF|6|pN*12v}5 z`hfE2zsM~s^AIKeRje$NS@yzoL1M}MUfp)0ZO{R+KUjV(35UnPfrLKQ|J z4GJL>76yg4*(rzF;QWQpD2~`Jfp+5JsS$sT;0>|K7U5K1Ua~C;45}^KCtG+bKn$BN z(o5F{uI$s(Ix+W}ROVa`+*?O)P zL+j?niUtf=Y2MZN?BZa+ZFwveEsVwRst zsA`+{h&0lr$}FhyNc;^pd4`145=F;FCMMYW=wR0-B(QJRQup)NgH_HsE14TFRc%aU zYr+dgO>XIgs!ek8FVsMK$ChH8JSr>QA(NolcvaDs1LUZFU*;6C08WH(q6EyJl54y; z9hN_Khg6*2%>B)g`VEq>w1RzKpYJ+AKjctk2b)B*$;rP-TFwj(FEd6v;pX(pj_vUE zeD0Bk6(iLJ8&)X{4Te5uP43Li7w?koVqEJblj6-7N#{5om&lxVTtRqlyZFDzhjD#N z4KNv561p7Hb}HOXw&lMN)P_Aj&9d0b zrfo?30%G5QmNMx+{R~xhoqcFm9BYp$zKsZ9I=m!1+8~d^bVZ1q;0~NUGIh6uq>4V7 zrWw}rFg@l#^T?uY zo;#Xa)`V$CpjPg?+&OV0%&&C-p!Fv<>;P0)Es*3?CUh*Kt0M&(S{|jPTBc!;x>`GO zK4-RRAS#?}J+F>E&KU5oct1qonz|}lOgbQFjhvT{g-nfo#CpCJMkzP7@4Zt5iEzvo z6U>BC0^_+#B}D|4rEv!QIHyE2*WtxGU6*|4{V+1iz>F>J&h#x{iQ3j26K0vD`9c3r z?eqxXND5Zbwr|^{!;>OEkF(w83`34tBbd(i9y)B zSY*+o$=7R!q8Pwt&QBQkQMRqlq$UoUBq~QsZa~;V5CxBTcj-Y zJ!;lCwGnL`IoWjBGIfitn5y+oI{}_e?aGIG^D=MH58ATp*^kG*!WiTYVhr;qVLl4VO?Y20Ddb{;8iiK%;IcpN9@ut#l* zQpZ41Y8kx6VK&+-0@<&jpSY>vyd%PV>B}k?{#YGj|IJc-&%QZu>MQpBw@0G~`>U;& zpIRD*0d_@N{IF{+?vfYATvn7RlVQWB3N6wardB48w!B@w1aQ6YBCRAS1=?Rfu?w^x zQb(v_Oc%3a*g5Ij_wHMh-{N0_hVrhr)xrn1`bWEr*({H;#U0t5kCSW0^owz7GaXr* z_>d_ey2LJnbBhqA41bKLOxxealiegpVEW6Z2e2sPLU%WPAGZK=?&B1vKALnUf0sG` zK^wKRB*#!;=pW48RGho(@NL+GErIn2moH0vSO%0JXdVnbCRe-i=@M0^J{Jo5LD6%? zhFen;TC;p+kXWOf3Pl4{ zvndJbGouOt`M?kFoG^uaGQ}pj1S;%@1Z>xa zCxb9pkOm|F=?G2GKtwJ84-!(q-jfz#F~v}{xzHww)V%f zPjNq8HxziwfflqDuTF<}-{3OV8Tyo6^HjtDQe7*+_NqF=dH2soFh-|aC>_$5M&rCs zTVN;;y|upGc0~6D9h30fRXT1c8~aUG3C6Wh$xIu>VYB^9YJ`szSb+%>$jq^Ru@>V3 z>VpC*+GfSRWE4`Cy{sOIP%7jMLm?zH(s76pN{lKiGAS`4CcZUh`UO$!n&m(0*i`3c zp98!@S`kC@C?R4}Yrw9cAg0BY#hA{mw_~B;?j_1rLJazxYxn-+AA%Vl%}Sah7SveO zo!#X;hOl#5mqqSoV}eck!!pY5S%!1e<+IKUMN@^Wg~d)vli4>v#-+dr?!<;ck^s?< z0}XFG9UrGD@12_s5K3o6kOD4F7ztDuBZ_czYY$+G$@>xl~G zLsI!-Kk1FLT#u9#C+^%_;C3Qqi>_y&57|uCx<Z|`}r&w{sBYw zP<+`L8{ffN)o{XKHcva$Z|tPN5O_@LKKWiJixcS*TQyY(F&YfW! zIGMHzYev-qBl}#pbQqe5dqw)bOda?E)V`HIQcLN}?Qve6F(zxH$_z%P!R3=?^e;b1 zaoRggctQ?XpR}rU-us9W2I~B-TtdJD!6E>s5Ze`=shAOvH$8u%5|VvSNsPw!qQXo5 z&b%t083Z zBv}PA#~|v;BP;ku5+Mw;78%zNe&jYdt{%pW;vzeUd4E;@^Tw2v=L{kx3*^Wy^VE@f z@}4(Zl7BoU+yzAt@QsON@FXLOsNiwR*Kx3Avo@)uov4hVZP2?EhVVy|^xwTC7dtrF zDa@WOoEt7nA{%2C=fr<`_y;^G@p`$j>s8z{V9tQs?(V@mh)M);@o9Gj(59U%G2|_+H(=Z8|@Py0_Ulbw`qUBsAW%9&oXlHxZ^kru0Wr zFaION{`W63_Vs{)nq=ScrrQxd`jJYZ5Owy@0b1JQ9i4ykM*fv${f8Lz|9d-S#4B%C z;F#~p!tP~c82Y8{48!k(cWei-oLFYZi#AZoJ*WJqC`m#Su|JWy4EqH(LXdsCiaG+H z&JvjGYxGZmJyHtj4*3>ILrAUawfnA8M?ArZi%L!l1u^@mh#5aK>wA#UgyEUg&cM)4 zVLE2EltyoP(}c;`#Ow{L-vLtW0E+x?s;v+WLOGf5tY48+0NX`?JiTyt^5M=UKnI%XUqgp z@Va+Zak)kqGRb;X1f?%TNlDSD56_O?{ze7fz|w+JeME4Qf=_Vl+WsoQ^n7|as7sXY}Gg**8MvS26?@#Y@G7nNF~UFQnm_4 zbxpC<2s(I6S@C_=Ie{pjIT6rDe$u-GIsrhh@RDQ$Q8W>}lnIIoT{3}7GfrPIu>022Tx3$MmIyUWZc#C{1pFOMs%v7Ap6Zce&eLefgVxC zEqLu(^=eE`%le{fQqt3yl#Jk8@*|6Rk{rpcorbFI`M7s;!#oY;1n zoBLN7gr4c1JoJzWqd*87o&t7;JecR?Te?tP$E$< zaFCMwb(Kp}MCqqfWd8BbUV3hi3U=oHeyh-&L1}TNoD46{RVbxI6GK_AVjnsq?XxyT zRAaTJLw`25spc7J=^Pc8jD7~ay(rj~b9Ckjf~grqPcujqwSr{Re7$|K?(Tb5X4L`? zrTIoHpMV58@t_#egpqH$_?%XTN4q}iW4`Hy7TM&hhB&IEQ}o=|-1BQHRX~sDYJdtqwB34yXil1yzUtPH|?aa&^qT+VS!WiRa zmc|FxNYZuvEgxSF+8S46|$yU0wn)Q5ymlMk0n0&VQ($yL`Wg5u-*QKK4m1Gt0% zrm7e{cA=7p^g{TsKG8h@I1TAMbV-d~%Wp!!Cxj<`YeF+l~QwnCPOV z>rc(UQp`gZMkVZ3*2b0(YO-MQj`N?@=`#rY@&(hH!1sH5vTE#CYT9-YiY6m~Dt2OG?^`D&Rr`<0M0MB0 zWUX4<)?vVhe9r{-?xRWzt-thz`iW^vtxg( zUbLz2sWT#5Yl>M^)9Y|(ptaKC)rBys#kY(}qGPZoUb=KoZR#I*KVR-L{*B%_EGzgr zILzGVVhJ-!G4htODmjep(?~>jGXsLjTq~|I{@GmjJ;u>v8?vj0MI{Vz(RYA4pz@u0 zG5jZn?65jPj5xh#lg5rAtD?88z$L2PH&5E_z_%0T(xL;J72V){(JD9DE51%BW6L4U zsw~-f_bnAxVYF*I-TO-$%s36C`uI`2oIZsUGlWxQlkCvGPl6+fIxI^HwY{EOMobaei#R^+3r4W4%)%Tw(?C0_)v4fnz4h(CzbpLQDnP&xo0K73`&|Aj^D2d z7>=~`3TK*Hiil@9it7S%SMV{wx>9$>wO~joz|6xvFz2Qa>DKV z;wM&;{297a9BRE>5mJeQQ0yL$N9tl}Mu$$*=X*t3N@5ag=$5mNur0yB2Hs6$H4gcVG9? z2Lh0fxc6P$5G*bm%3y8G4hr~?so54hNoQlpP1v$<0)C&Ig>h9DvAek zZa4LVG+FOA0!XV-Q|fYi#t%J%F-*cjtMag#V&A*irvRHrM50ZBY^&glV!cIM3a=pB z#_QZvc#EWRVk`kxu^qmm#d%GuDcN=SK5O8P54it;HcPq{+%m&Wd;sE=#QL=pRSghb zJybu8EhEJhl0R+@dR{XR#@R`ZIH0zkFTy<&JQru2_PWN4F~;A**p&DZSk!F9LiUl*d=ZE(hb|X!W~T&$GBe?(9;w zUonc)2l~}hyc>PYT>;g~;eWMk=*FjfsB35P73H0hA{{GzR?qQzai9mWV5H(ENC}%! zND8Xq+LTE;U)N-^1pH<|=XW^ecu|08rHKs`k%vq}$50iEIa;qNyM}_tvy++=-!PlR z*$_^j^{q0*+`6B0*nNI->}K}`N}vmGAC9l74F~$5&=#)|HH^?!!s}Xp?J;TX{Un!G zoYw6|)7P`2iHILqNLaqQCe?08Fn}pjoQmW|IO}I`KMwrSM%Hn~hf7LmRsM0xh615Q zEgn|{NSiyn-WgIRz^4{?OXvNu$lQ%!Qzrt&&)?pK(?6~RPVkCSRHVU(B7{z2ALK! z;{zOS4~z0Wm!J1@r2vMP^oOI*G;Wd^JACQd2ukqA)JRI*A|+C=CVZ}9sJcR8xz@H z47F4<@&T3x;7o}6ovWXTW`pQRauOAk0esNVgu&&=?0dX-6I1{jtSj%^$635XuY6|c zr=hU^bLeE>6 zaku`YVs(8%QgIe*4+88D}3MuQe7w9O8k~L(V*0@zS;kgs2`Z!g*@UF7rD(^wPne@JXKX? zf`P~69)(CI>5mrn))&wWhpjC|4L7=AbBv! zqE@u$J;5&Gw;=BlgKwDQO3R3ohQ##1TMj+Su4ZQ^rrOg1}y>D@UWMF*eV zEm6quzdOJFklEbGwY~D*l*5!;wjZ~r!|=ZUuj2gwK5X=_ezgAyJMpIh$WSKE^mDL% zTDp=4^gLua5BBe-zrX44e{iO|WruUU*E06VUrJ-pU4HXTo>R{*_kK(F_B^ANp?}#} z%iZX22S3B?Nu=%s+x`5s?lJEtW42jkzF%u#MQCgA^~Md(?(@Puq4}Djcvn@alQFxK zgm$pg!8ikexBXja!8Fex<0maAEd#fa<&Ue@8!o**q-%Q~nU2tYlR=gx1TVg0Z$zHS zf1kr^Zp7o@65WEWIKfvZq z=q?!@zOq*$;|hwPm?BBI3I=1ANIARE^>>K|niQ&J=q5oDhUA_PQ7Qrq4$r8D++OI= zI5sS`J=tLSnn*WSQbF9;zk)w75BQRVvVgJNH%I2P$>AjVov61y%FJC$4wl3EOm0OP zv=K|yB^CY}2qu73LV*L)#M)Fx{Vt5y&!@9`&xaNHuP`+yi1pLr{mU2{weM7^!NR9+ zG*lBCe>u`N=@q0igd(;vc9ob_Q86jhNm2(V*NTqy7TLl7{N)ea7Ygr}wvKH9RPE&& zj(m~Ej_18SpF=gE`pN~%_M2@bA7@p>3L-Okb0Rn)jC1&vIVM5b39#v$GA;(2YVot_ zj7Yq)XGCKKP_5##m|G~ih#stxi599}3Gs5*6w=R$WFshG!dhT|R78}>s3R>{k=O?b{7grT1C9NXsm{vQHJy+^fI-17?&1d-Wsu;B9#`>* z^G?6EvDOJywfyQz7``ZWKmsK@hTKJr_)r|Jxut;wulX;m-$2soRTOLpgYJqSEopwN zdwf4S07HMF7zV($lSNzbcflC5tHv=_4KdSFD#DPA`sGJTb?Dj1qr0D$_~|Pg9o>k6 zN(}4ye&9(FMN{bk^-4;wkmA)ckbzy9UZ%Qw+FR|z+UUHeipBJt#fpR%A!*#opl5>v_LPrH6-&g0?($e@NpoR4C zU95G4RZ{k%pCfZ8QR=8Oz!BbR9F^)JN&Yf~=gt_dqQ(4)Fa3LMZ+HHOkL#0G&9y=U z34NX>Kb`EpC|L6*qZ4>65{VWiRyw)o1y zcyICbpe@F-W45!9S$aoQN8M*(ERTfhzKgP#na76PW=CD!wE+KuQ46Wc){CrJh-qQD z%=Y2+E7O-fmP!V+m>ic%qK{=seX8-v$K9MiNvUef7+sx*02l*6Whqnlo42r(spF8C z6nFK>08vRFi0)mfnppJ0(dZ~~K%xf1br{1te@ZB2&5Q;6`d4WKvKLUqI?X*tZo2~d`Vjw8)xsx7o*hV$>fENScO zeIyZw{w&*D6`w;FOUJoQtG-r?!_#aGU`U6Ve#&wyzCT`PDX{Bq&C@;drc438b1U`# z>g_zkn%KHWk5U8?5fG#(C^dle-b6YC3B4CZq=eoC0!Tzaq}PB3L+`zJL8SNIOF+7S z6zK$Vhx32mbIyI9`{91McYmAbnM`J_y=L~FRep=Tu`COJuqT)v$ahjNt{E}VxI<1P zYqcGy!l$fs5{FD6n~*_iUS_}ATxpuQEuj+Pe$cF|q0gQdL;O_Lqb_4dAFlb;MKUy~ zojn=>A!a-h{-GmwDGiAVv%Md*R_VsmTA!M9;u26uB~H=QV*A9s^S14eqp79M(x=m# z+ab%`I5Z#qX^?tvQY6@O2NuVgGBgy1jbgVhMTF?SHqQa@l*H=3ge*2rYCC|=<~V9Xk`@GA5r^2Ra%tGSE0P5s*{`lO zb(#d;#^3}ULuKp(0i^is#w59+KbxX{UXqWBad?QLlZGH(S*q@MSIxaz)dMSL=V^-w zOSf?_vVbayfl2+`@|8m#J}s5{wzkL#qY{}gPQ|lNY6@|>`Q)VW71=qghd=%Pvan?x z+PtreyWU_HrSmVLIvg5os*xpvu_kwn4hQ{#dfVjMHE;mPP%b@-ej;!L$}w?2%H2Et zLLtHjpIi`DmP}CZgyHA}(_hIB<~{l*vpK1Yol>pSJr$<4K);Z85#KlHN<23$R%7Yz zee68b_7k!zL=xMypg#ZY!5zBoRa-7D%8M~EX8VFC%DK189ygKO-ZyZbFVpa02dgkA zOIF4~)WrBH7^M&CH>!WlOtzdyQdLtpbwsIc#<_$%&x=D z$#4_87v$dDl)rew(-WSBiKdQp2?gYvYjL8H?b_XoLwPARfIi;(gK^)_zn8@&1a=L0 zgVOo8jh@KtkUvvNJs?1v;p5aQ{_TDKpJn|2uirT=>$@c;aH?@Zu|Ts`cnFu2a~K_m-Ps9?Ti*hS`4(zQpTl=sTt&a%%J_* zb762-Zy*@4rJ@k*(PwT(dX8se(2{KR?6__Jq|G^hT)oMUsaw}$9@fuU?p%*z8WLu) z*Y}dS_QkFaHmkpE_BuMs;n$Eqh;#nxVps*W=d25){+=eUzmsRyuYNLky$S`4mPHr> zPJ$Mdk7^!}M6@%vOQ>ky>X}a~85&*9 zrQJLqt?MtKK(^qg9D29$xbI}oySjE3jqa8~c(fg>z0!_slAc_O$Lr7dCUUoKHU*s3 zV%WMhc_uZAdAQEzohCJnWvM+2l;K+SWzWmVJUEa&zl6X}-oBB-{7mlZr{}`J?T;r5fwrE8c z{d2mkpcDirm9_bZAgInrMyFS$rS3Lf!_yxgmWCS&l+$b`5`l1|rm^6+rdh97&UzEq z07z{GgeF>294|4m2MQyjD))Aj5PhMZ&CGAAcvhb-^M)VxZB-AIYk=xKf^iBR z73Z=vP7?YOZr;GE!RGkvjm)LxoTI4U6sdny+gn{r#tn8mX%cnWB6mRCPd?(Fp04TU zF>Y7w{l1Nw9}%9P&AvCM6E%43d9m__k$bC+O7$iMN3-wzd}2#D8_;;gnvb+!pz+Se zFeKicsi^xMY^6f>3-?TVw9ky|3d;xGHZK{;;ED9;NWauuhAPwXM4akUR3Sn< z_75roUaWNGR?CFemef{Qec#BHsl+ehF;@?={a$VRy}p@6;_5{J;9)lLi*NCs0E&8f zVsr+7gqXsXOQn)ku)oa~jI3bV1yR_{(FJP<7)}j*IzY% zGYMf5hyr7Pv>Zi)q8a@KbT8dHBv!=UKRP;-Df*4KNw09oscby^jv&|JV9_W;f9$|P zU0s^61c%phuQB2Yib^sMx;s)5U2Y#tS($fX{Em=)(L;}Ec|nONM%Z=Jv%w!#t?tvo z;#g_%D$wV#EV2ERRcjLXMpq2dSRb{MRL0CpKmJXoAc4uHzub9=n)D|>keH)Gs&1LA zw(KbTaSU2O=e{l)RE~IiP(U<@l89APHNHepKAfw zM4}>{i{T$;O?RMfUk_gz%30;=M;xuqyKcy|dk-KgEA7CSykmq}@ zBe5dF^TrY(qWsJ}JhyEaG)8D#9b=wjxf7i90B{>9P>Y2<)7rUW&&UW6clPz!Z3v(e3oN zU`Vtx1=BDefkhnzq1CCV9HacYZO9(N4k826UMjldr@|Yj%-u!t9Wu8FJ6<`P01cw* ziPJV#&gZDA_4>I}=t|1zDm{MbQonoKsa1OGHQ;-lP_^qVXcS+S*B;Z-{$dvgq%=Ju<;H_Q!Z8GFh4oYgDiWYkAF;udMeJLX_;sg{XZ(cx71Cx!?xjFa_lfkD&Mn zHA9`EH#5pyAOh2d8}D8O?sjSReI}xOVM@bYSeh(e^xpPM-#&J=`Hj>qW8D5qO;ekj z?6Oouh1@-j$)NKN=# zC>X0uua(kPKUc6y#YN!wT4UXyT$o>L)gmLAMxfBpMU8quK{YB2Y0rWdlsz z4R)DS-X{dhwMj`*Hy)Tl-J|>zM4q%BbR}Ymz5N6?ZYP$?Sm82$Dva?}Q~vEbm{w66 zk;^tP^7ELfg43Bl`+E$fNI3qZ7pC{P1Vvp8+W4W_DXR!gKF9gW7&8#J{FEjTQYl-5 zm7Q;I-n*=OWXJm4X~+`sAw6Np2@!Z>fXl$ zAx=g~eD%DMA-UhlhXN7Yt@rAg8%WgB@2#87SgC1?9+4%z&e4uskvkAkrPUIb?U}X+ zjkpOKRy31O-ni>ec>RK4+K;lEUIXm*@!8KhOWBIv^@-GP&Q>bKsDgX#diuKC{-5uR zbh9?_+T@xrXh7Y4*nW)i($%dre3KwyZ4``QVj(4!kM5$IZ%55d(Ui^AQP*Tpog+SO zIXVKi>75nxai^@0^gwbkS#m6C>fH((owvCvLnwHKC7n2SQHa9MTp6li6^j}W&Uowo zekPY*v&13Ii>^pgmR-H9-<7JK?Y%>?~_n z;HCAorfLA`U#Sy6L!ZuNlSKX;bRSw#NK!(ycYnKTBpPjLtbwm+zIuzcZDyT8I<1pU zL@IwaDgMx=L@Yt&K9ws^Oa;WReydYb0?{Yu^Wegttbn&EV&;`+NwO|601y&O zAx8NGd?K9_P-R=A5ep3~5&U$x$Nky*v^ViEin2z@Zv+%Ab(HILT*)vQ#&1m>P=KH;Pkhh{(;ksjgb3DIxX!eBO8E)1I*1QyVAmtQuZBowi`%G>z9g zF&ExYR_x8ur%uGG_nzMU3aXm|6MMz?sj!(VmNS}8TbXqm>!{i8Y<(FRXdTor&h4V@ z_-ZBlrRG@@k`~|Z*8WB?%e+<!br^|&=@o$X?vsg$9GqLJ+cSh)7{h8 z@XMw5fYNtY8}6>O^pS2d+N-~d1GUxZABMT-x6G1q39VGV5874lTsKS(4cY{8o znZrWs4GO4U0TnPOvuIO|JiYA*>HhIL$As)euuqZu*m3=Peq&{Mkc$fchWsqPVs6#W z^V7MJs$73AQ!>kz<}zqzbK8tU9SpnFQKolo^}CUKeX;0;t9=u*tTJ*0zJ1U7B#($H z{=h9Z>Ep^`$Cnbd_i}nTqpJTHSl34Jq;pLjT>Bqjjq53Dtl#-05dxWoWx7H+8DFHJ zkWCj;{a-r6W+#`hnTETF4*rX-nB1WatKvJR9iNwC2=J7Z|Ly+CKD0;F|> zIpw&?08a*--D3_MS$B7C-Co2GLrwTTnxwl|HH9*JCK@$ z@v&`~yN{y|z{=e`E-)8>5A6zngJOSk>%nGJ%sUtW9a$WSwmU>)4qw38oxJr;Cehot z#x8j!l^C|~K>=9MK^^wJC>DP`_;Pg(^g5P@E}2_$=EK6+7$E>hsf`6Mdtw=NX{Dtz zM^2X-O8gXkFN(vlyPoI+gW+r{!wZZLJaHuNZ*CY+c)Z-<=ALEVD7egkZp?@8iSE@t zfAy!Okav|~#;VYzW*oX<$9(p!ytzda6m@%fqYJ!zRV_iq4ULtzrJJuEP=P1->>-+5 zQ@*i}v=pxPdG>1mBr2Q7}VKJo(1l3lhihXTUDLKXs8T1uUW=>sf*v;;4!t zhaRIX^~cM!(m4A!aJ)o;I0|M5e%kEnjBUrpazwxlN3gnqhz?mI{_^S(=W>sv4Z%m? z5THoJ`tgA&OU&0rk>s#OG4Q$NuM_yrWPvP}s&-%niAoX?Ut`t(vN12EuVI+X6%D}p zRn5xxA-{e4Vzi4{k=^=lMqegB4&oDjzz49aO(|M5?~8H0Xx%sv5{h-te&}f}88J}) zxgX^y%=3j_A(paZ$|Na+7k_Ud0)8jeMJH=`{Yik)c+<1k1?T(n^E?Tbz4#7oes%UsOMO~67JYTP_VV%wjgii} z`I&<9{w?2BnL;42OvS%KB0S88=ny&JV!`aNaIT0`XrXcBLc#{z=b1xR#O^q-6}{b7 z?K4UvRfMIPPiLI?)m59E9kS2rFyJW&_aFEzL+qJ4#_D(Ql*|Xk8h!Qpg)EDQ4b_?I z6=TqwnuJD%o!L^iBQrKe?%WXU3KQ#Icsg7HR#h${a`R%IY%yj+wgkDI#cOkj9f)bL zHGv+xxgZE~3SDA*3=5NsX689)jwjBK!gn=QW*G}+6vf$VHYms7XTq0poyac!qu8Z$ zI4jGa^wQcrFJf=)8D!4WKSY)farOu??btJ{)-MPV1^^dhJJDA>SSfwl<`Wf;h{@fn zd>tG&40t(}RPfUg04Iq(l~V0)wNJO;AVJ}53J%1%k!QF`#IBnsp4@?Iq#<{yZw%63E~|r)3Mi7IyahFuGT)xpIr>YIoZM%?oOSt{>6r3TWeZ*gto}P@m+b(}ovAA%g zl&0uSt2n!rSD&I*&#c8AUNu#T1fUTomujWvuJoYp8wJ;~2|LE#F^g7?kAa#7MyEJ` ziJtM0?iP;Z&E_-o6|6weZx{IfyOPQ|Nz{d6GMd2v+`Abg0YC4B@1ilMHQ4qPtP|Wc z^gWT8T1z?Zv!TbpZrM_jr6_NA=B|c!%qUsXM&u^X8(v`!@`4#G6GzAl=a17L5W(4fLgKqnugNa= zyHcTG>ZD_kff7nB1WlUC7mtTB{NZ<_nuS@NyGy?u=AN}=`fPRVA#n*y)so=zrJulD zpoM=q86(1LG%7C?g#H{w;5&Qwjp4T|SGAwQs*kk$;?oRca*#I^-hA=4SGmGvH#Hq*%2=^FPSy&?28k*D|Vj``kQJl+TT(9d`^Kg!$Vt5qE=y_|arzOh+j zGDcpvAnll{LIcIUt3Jfruws+&kX^1q*8Szp*?-x-t#-$MZQuFX)k*Ui)^EA_3P^%n zXBbJvONO`a>|U-a=+SN}2_2NA*)SJOO~9SoNv@WV@>-fss8XO8UGX-gDFe#{@TuIAU>uZUX-qGloVz-`Od1 zXqQE>>}=~MR=$fVLm&nl4D9kr#KH3715K!gDnjv+faA)nrd+9;NDeRL{yOcKmX-T^%+{|SN>EZ`!zm6@npT~VKh*_t`%dEyDQJ&yBeZ?D z?pJA<>p(Q2l~F>cIYPE&`)*gl`OOzRFahi|wvVOL>D&78=)a|3w_(R!zZpR83hreW zYd)LAKoz+K4%BVBZqWiW*VRe8S*uwcr*4qR)zLfL0+2m_g8vA%@tO%B{8;~70F3z4AWu`Mv$rIT7w!;4ej=i`68~}G5L{NUe`?@{wrzCs(s^|H8Ish zS|$X|15+qa6HS-3(#7ROMDq98!4ze$im6J!jfgSMU+^CV4JGSvQYr#Gh<`~zWCUCw_unT$ zhQL7pRMY?C-^1gB9!EF;cmXd3!Dk&yYnyrr14cAhKvD9F`ns)hIz*d*hqC_vxUl0NsnE(I) diff --git a/src/main/resources/static/editor-md/examples/index.html b/src/main/resources/static/editor-md/examples/index.html deleted file mode 100644 index 1d717e9..0000000 --- a/src/main/resources/static/editor-md/examples/index.html +++ /dev/null @@ -1,356 +0,0 @@ - - - - - Editor.md examples - - - - - - - -

                    - -

                    Basic

                    - -

                    - TOP - 自定义 Customs -

                    - -

                    - TOP - Markdown Extras -

                    - -

                    - TOP - Image Upload -

                    - -

                    - TOP - 事件处理 Events handle -

                    - -
                    - -
                    - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/examples/js/jquery.min.js b/src/main/resources/static/editor-md/examples/js/jquery.min.js deleted file mode 100644 index b36821b..0000000 --- a/src/main/resources/static/editor-md/examples/js/jquery.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="
                    ",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h; -if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
                    a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/\s*$/g,rb={option:[1,""],legend:[1,"
                    ","
                    "],area:[1,"",""],param:[1,"",""],thead:[1,"","
                    "],tr:[2,"","
                    "],col:[2,"","
                    "],td:[3,"","
                    "],_default:k.htmlSerialize?[0,"",""]:[1,"X
                    ","
                    "]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?""!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("" : "" ) + - "" + - "" + (function(){ - return (settings.imageUpload) ? "
                    " + - "" + - "" + - "
                    " : ""; - })() + - "
                    " + - "" + - "" + - "
                    " + - "" + - "" + - "
                    " + - ( (settings.imageUpload) ? "" : ""); - - //var imageFooterHTML = ""; - - dialog = this.createDialog({ - title : imageLang.title, - width : (settings.imageUpload) ? 465 : 380, - height : 254, - name : dialogName, - content : dialogContent, - mask : settings.dialogShowMask, - drag : settings.dialogDraggable, - lockScreen : settings.dialogLockScreen, - maskStyle : { - opacity : settings.dialogMaskOpacity, - backgroundColor : settings.dialogMaskBgColor - }, - buttons : { - enter : [lang.buttons.enter, function() { - var url = this.find("[data-url]").val(); - var alt = this.find("[data-alt]").val(); - var link = this.find("[data-link]").val(); - - if (url === "") - { - alert(imageLang.imageURLEmpty); - return false; - } - - var altAttr = (alt !== "") ? " \"" + alt + "\"" : ""; - - if (link === "" || link === "http://") - { - cm.replaceSelection("![" + alt + "](" + url + altAttr + ")"); - } - else - { - cm.replaceSelection("[![" + alt + "](" + url + altAttr + ")](" + link + altAttr + ")"); - } - - if (alt === "") { - cm.setCursor(cursor.line, cursor.ch + 2); - } - - this.hide().lockScreen(false).hideMask(); - - //删除对话框 - this.remove(); - - return false; - }], - - cancel : [lang.buttons.cancel, function() { - this.hide().lockScreen(false).hideMask(); - - //删除对话框 - this.remove(); - - return false; - }] - } - }); - - dialog.attr("id", classPrefix + "image-dialog-" + guid); - - if (!settings.imageUpload) { - return ; - } - - var fileInput = dialog.find("[name=\"" + classPrefix + "image-file\"]"); - - fileInput.bind("change", function() { - var fileName = fileInput.val(); - var isImage = new RegExp("(\\.(" + settings.imageFormats.join("|") + "))$", "i"); // /(\.(webp|jpg|jpeg|gif|bmp|png))$/ - - if (fileName === "") - { - alert(imageLang.uploadFileEmpty); - - return false; - } - - if (!isImage.test(fileName)) - { - alert(imageLang.formatNotAllowed + settings.imageFormats.join(", ")); - - return false; - } - - loading(true); - - var submitHandler = function() { - - var uploadIframe = document.getElementById(iframeName); - - uploadIframe.onload = function() { - - loading(false); - - var body = (uploadIframe.contentWindow ? uploadIframe.contentWindow : uploadIframe.contentDocument).document.body; - var json = (body.innerText) ? body.innerText : ( (body.textContent) ? body.textContent : null); - - json = (typeof JSON.parse !== "undefined") ? JSON.parse(json) : eval("(" + json + ")"); - - if(!settings.crossDomainUpload) - { - if (json.success === 1) - { - dialog.find("[data-url]").val(json.url); - } - else - { - alert(json.message); - } - } - - return false; - }; - }; - - dialog.find("[type=\"submit\"]").bind("click", submitHandler).trigger("click"); - }); - } - - dialog = editor.find("." + dialogName); - dialog.find("[type=\"text\"]").val(""); - dialog.find("[type=\"file\"]").val(""); - dialog.find("[data-link]").val("http://"); - - this.dialogShowMask(dialog); - this.dialogLockScreen(); - dialog.show(); - - }; - - }; - - // CommonJS/Node.js - if (typeof require === "function" && typeof exports === "object" && typeof module === "object") - { - module.exports = factory; - } - else if (typeof define === "function") // AMD/CMD/Sea.js - { - if (define.amd) { // for Require.js - - define(["editormd"], function(editormd) { - factory(editormd); - }); - - } else { // for Sea.js - define(function(require) { - var editormd = require("./../../editormd"); - factory(editormd); - }); - } - } - else - { - factory(window.editormd); - } - -})(); diff --git a/src/main/resources/static/editor-md/plugins/link-dialog/link-dialog.js b/src/main/resources/static/editor-md/plugins/link-dialog/link-dialog.js deleted file mode 100644 index 3e1d0bf..0000000 --- a/src/main/resources/static/editor-md/plugins/link-dialog/link-dialog.js +++ /dev/null @@ -1,133 +0,0 @@ -/*! - * Link dialog plugin for Editor.md - * - * @file link-dialog.js - * @author pandao - * @version 1.2.1 - * @updateTime 2015-06-09 - * {@link https://github.com/pandao/editor.md} - * @license MIT - */ - -(function() { - - var factory = function (exports) { - - var pluginName = "link-dialog"; - - exports.fn.linkDialog = function() { - - var _this = this; - var cm = this.cm; - var editor = this.editor; - var settings = this.settings; - var selection = cm.getSelection(); - var lang = this.lang; - var linkLang = lang.dialog.link; - var classPrefix = this.classPrefix; - var dialogName = classPrefix + pluginName, dialog; - - cm.focus(); - - if (editor.find("." + dialogName).length > 0) - { - dialog = editor.find("." + dialogName); - dialog.find("[data-url]").val("http://"); - dialog.find("[data-title]").val(selection); - - this.dialogShowMask(dialog); - this.dialogLockScreen(); - dialog.show(); - } - else - { - var dialogHTML = "
                    " + - "" + - "" + - "
                    " + - "" + - "" + - "
                    " + - "
                    "; - - dialog = this.createDialog({ - title : linkLang.title, - width : 380, - height : 211, - content : dialogHTML, - mask : settings.dialogShowMask, - drag : settings.dialogDraggable, - lockScreen : settings.dialogLockScreen, - maskStyle : { - opacity : settings.dialogMaskOpacity, - backgroundColor : settings.dialogMaskBgColor - }, - buttons : { - enter : [lang.buttons.enter, function() { - var url = this.find("[data-url]").val(); - var title = this.find("[data-title]").val(); - - if (url === "http://" || url === "") - { - alert(linkLang.urlEmpty); - return false; - } - - /*if (title === "") - { - alert(linkLang.titleEmpty); - return false; - }*/ - - var str = "[" + title + "](" + url + " \"" + title + "\")"; - - if (title == "") - { - str = "[" + url + "](" + url + ")"; - } - - cm.replaceSelection(str); - - this.hide().lockScreen(false).hideMask(); - - return false; - }], - - cancel : [lang.buttons.cancel, function() { - this.hide().lockScreen(false).hideMask(); - - return false; - }] - } - }); - } - }; - - }; - - // CommonJS/Node.js - if (typeof require === "function" && typeof exports === "object" && typeof module === "object") - { - module.exports = factory; - } - else if (typeof define === "function") // AMD/CMD/Sea.js - { - if (define.amd) { // for Require.js - - define(["editormd"], function(editormd) { - factory(editormd); - }); - - } else { // for Sea.js - define(function(require) { - var editormd = require("./../../editormd"); - factory(editormd); - }); - } - } - else - { - factory(window.editormd); - } - -})(); diff --git a/src/main/resources/static/editor-md/plugins/plugin-template.js b/src/main/resources/static/editor-md/plugins/plugin-template.js deleted file mode 100644 index 8e30169..0000000 --- a/src/main/resources/static/editor-md/plugins/plugin-template.js +++ /dev/null @@ -1,111 +0,0 @@ -/*! - * Link dialog plugin for Editor.md - * - * @file link-dialog.js - * @author pandao - * @version 1.2.0 - * @updateTime 2015-03-07 - * {@link https://github.com/pandao/editor.md} - * @license MIT - */ - -(function() { - - var factory = function (exports) { - - var $ = jQuery; // if using module loader(Require.js/Sea.js). - - var langs = { - "zh-cn" : { - toolbar : { - table : "表格" - }, - dialog : { - table : { - title : "添加表格", - cellsLabel : "单元格数", - alignLabel : "对齐方式", - rows : "行数", - cols : "列数", - aligns : ["默认", "左对齐", "居中对齐", "右对齐"] - } - } - }, - "zh-tw" : { - toolbar : { - table : "添加表格" - }, - dialog : { - table : { - title : "添加表格", - cellsLabel : "單元格數", - alignLabel : "對齊方式", - rows : "行數", - cols : "列數", - aligns : ["默認", "左對齊", "居中對齊", "右對齊"] - } - } - }, - "en" : { - toolbar : { - table : "Tables" - }, - dialog : { - table : { - title : "Tables", - cellsLabel : "Cells", - alignLabel : "Align", - rows : "Rows", - cols : "Cols", - aligns : ["Default", "Left align", "Center align", "Right align"] - } - } - } - }; - - exports.fn.htmlEntities = function() { - /* - var _this = this; // this == the current instance object of Editor.md - var lang = _this.lang; - var settings = _this.settings; - var editor = this.editor; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - var classPrefix = this.classPrefix; - - $.extend(true, this.lang, langs[this.lang.name]); // l18n - this.setToolbar(); - - cm.focus(); - */ - //.... - }; - - }; - - // CommonJS/Node.js - if (typeof require === "function" && typeof exports === "object" && typeof module === "object") - { - module.exports = factory; - } - else if (typeof define === "function") // AMD/CMD/Sea.js - { - if (define.amd) { // for Require.js - - define(["editormd"], function(editormd) { - factory(editormd); - }); - - } else { // for Sea.js - define(function(require) { - var editormd = require("./../../editormd"); - factory(editormd); - }); - } - } - else - { - factory(window.editormd); - } - -})(); diff --git a/src/main/resources/static/editor-md/plugins/preformatted-text-dialog/preformatted-text-dialog.js b/src/main/resources/static/editor-md/plugins/preformatted-text-dialog/preformatted-text-dialog.js deleted file mode 100644 index 9a30860..0000000 --- a/src/main/resources/static/editor-md/plugins/preformatted-text-dialog/preformatted-text-dialog.js +++ /dev/null @@ -1,172 +0,0 @@ -/*! - * Preformatted text dialog plugin for Editor.md - * - * @file preformatted-text-dialog.js - * @author pandao - * @version 1.2.0 - * @updateTime 2015-03-07 - * {@link https://github.com/pandao/editor.md} - * @license MIT - */ - -(function() { - - var factory = function (exports) { - var cmEditor; - var pluginName = "preformatted-text-dialog"; - - exports.fn.preformattedTextDialog = function() { - - var _this = this; - var cm = this.cm; - var lang = this.lang; - var editor = this.editor; - var settings = this.settings; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - var classPrefix = this.classPrefix; - var dialogLang = lang.dialog.preformattedText; - var dialogName = classPrefix + pluginName, dialog; - - cm.focus(); - - if (editor.find("." + dialogName).length > 0) - { - dialog = editor.find("." + dialogName); - dialog.find("textarea").val(selection); - - this.dialogShowMask(dialog); - this.dialogLockScreen(); - dialog.show(); - } - else - { - var dialogContent = ""; - - dialog = this.createDialog({ - name : dialogName, - title : dialogLang.title, - width : 780, - height : 540, - mask : settings.dialogShowMask, - drag : settings.dialogDraggable, - content : dialogContent, - lockScreen : settings.dialogLockScreen, - maskStyle : { - opacity : settings.dialogMaskOpacity, - backgroundColor : settings.dialogMaskBgColor - }, - buttons : { - enter : [lang.buttons.enter, function() { - var codeTexts = this.find("textarea").val(); - - if (codeTexts === "") - { - alert(dialogLang.emptyAlert); - return false; - } - - codeTexts = codeTexts.split("\n"); - - for (var i in codeTexts) - { - codeTexts[i] = " " + codeTexts[i]; - } - - codeTexts = codeTexts.join("\n"); - - if (cursor.ch !== 0) { - codeTexts = "\r\n\r\n" + codeTexts; - } - - cm.replaceSelection(codeTexts); - - this.hide().lockScreen(false).hideMask(); - - return false; - }], - cancel : [lang.buttons.cancel, function() { - this.hide().lockScreen(false).hideMask(); - - return false; - }] - } - }); - } - - var cmConfig = { - mode : "text/html", - theme : settings.theme, - tabSize : 4, - autofocus : true, - autoCloseTags : true, - indentUnit : 4, - lineNumbers : true, - lineWrapping : true, - extraKeys : {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }}, - foldGutter : true, - gutters : ["CodeMirror-linenumbers", "CodeMirror-foldgutter"], - matchBrackets : true, - indentWithTabs : true, - styleActiveLine : true, - styleSelectedText : true, - autoCloseBrackets : true, - showTrailingSpace : true, - highlightSelectionMatches : true - }; - - var textarea = dialog.find("textarea"); - var cmObj = dialog.find(".CodeMirror"); - - if (dialog.find(".CodeMirror").length < 1) - { - cmEditor = exports.$CodeMirror.fromTextArea(textarea[0], cmConfig); - cmObj = dialog.find(".CodeMirror"); - - cmObj.css({ - "float" : "none", - margin : "0 0 5px", - border : "1px solid #ddd", - fontSize : settings.fontSize, - width : "100%", - height : "410px" - }); - - cmEditor.on("change", function(cm) { - textarea.val(cm.getValue()); - }); - } - else - { - cmEditor.setValue(cm.getSelection()); - } - }; - - }; - - // CommonJS/Node.js - if (typeof require === "function" && typeof exports === "object" && typeof module === "object") - { - module.exports = factory; - } - else if (typeof define === "function") // AMD/CMD/Sea.js - { - if (define.amd) { // for Require.js - - define(["editormd"], function(editormd) { - factory(editormd); - }); - - } else { // for Sea.js - define(function(require) { - var editormd = require("./../../editormd"); - factory(editormd); - }); - } - } - else - { - factory(window.editormd); - } - -})(); diff --git a/src/main/resources/static/editor-md/plugins/reference-link-dialog/reference-link-dialog.js b/src/main/resources/static/editor-md/plugins/reference-link-dialog/reference-link-dialog.js deleted file mode 100644 index f1ad086..0000000 --- a/src/main/resources/static/editor-md/plugins/reference-link-dialog/reference-link-dialog.js +++ /dev/null @@ -1,153 +0,0 @@ -/*! - * Reference link dialog plugin for Editor.md - * - * @file reference-link-dialog.js - * @author pandao - * @version 1.2.1 - * @updateTime 2015-06-09 - * {@link https://github.com/pandao/editor.md} - * @license MIT - */ - -(function() { - - var factory = function (exports) { - - var pluginName = "reference-link-dialog"; - var ReLinkId = 1; - - exports.fn.referenceLinkDialog = function() { - - var _this = this; - var cm = this.cm; - var lang = this.lang; - var editor = this.editor; - var settings = this.settings; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - var dialogLang = lang.dialog.referenceLink; - var classPrefix = this.classPrefix; - var dialogName = classPrefix + pluginName, dialog; - - cm.focus(); - - if (editor.find("." + dialogName).length < 1) - { - var dialogHTML = "
                    " + - "" + - "" + - "
                    " + - "" + - "" + - "
                    " + - "" + - "" + - "
                    " + - "" + - "" + - "
                    " + - "
                    "; - - dialog = this.createDialog({ - name : dialogName, - title : dialogLang.title, - width : 380, - height : 296, - content : dialogHTML, - mask : settings.dialogShowMask, - drag : settings.dialogDraggable, - lockScreen : settings.dialogLockScreen, - maskStyle : { - opacity : settings.dialogMaskOpacity, - backgroundColor : settings.dialogMaskBgColor - }, - buttons : { - enter : [lang.buttons.enter, function() { - var name = this.find("[data-name]").val(); - var url = this.find("[data-url]").val(); - var rid = this.find("[data-url-id]").val(); - var title = this.find("[data-title]").val(); - - if (name === "") - { - alert(dialogLang.nameEmpty); - return false; - } - - if (rid === "") - { - alert(dialogLang.idEmpty); - return false; - } - - if (url === "http://" || url === "") - { - alert(dialogLang.urlEmpty); - return false; - } - - //cm.replaceSelection("[" + title + "][" + name + "]\n[" + name + "]: " + url + ""); - cm.replaceSelection("[" + name + "][" + rid + "]"); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); - } - - title = (title === "") ? "" : " \"" + title + "\""; - - cm.setValue(cm.getValue() + "\n[" + rid + "]: " + url + title + ""); - - this.hide().lockScreen(false).hideMask(); - - return false; - }], - cancel : [lang.buttons.cancel, function() { - this.hide().lockScreen(false).hideMask(); - - return false; - }] - } - }); - } - - dialog = editor.find("." + dialogName); - dialog.find("[data-name]").val("[" + ReLinkId + "]"); - dialog.find("[data-url-id]").val(""); - dialog.find("[data-url]").val("http://"); - dialog.find("[data-title]").val(selection); - - this.dialogShowMask(dialog); - this.dialogLockScreen(); - dialog.show(); - - ReLinkId++; - }; - - }; - - // CommonJS/Node.js - if (typeof require === "function" && typeof exports === "object" && typeof module === "object") - { - module.exports = factory; - } - else if (typeof define === "function") // AMD/CMD/Sea.js - { - if (define.amd) { // for Require.js - - define(["editormd"], function(editormd) { - factory(editormd); - }); - - } else { // for Sea.js - define(function(require) { - var editormd = require("./../../editormd"); - factory(editormd); - }); - } - } - else - { - factory(window.editormd); - } - -})(); diff --git a/src/main/resources/static/editor-md/plugins/table-dialog/table-dialog.js b/src/main/resources/static/editor-md/plugins/table-dialog/table-dialog.js deleted file mode 100644 index 578adf2..0000000 --- a/src/main/resources/static/editor-md/plugins/table-dialog/table-dialog.js +++ /dev/null @@ -1,218 +0,0 @@ -/*! - * Table dialog plugin for Editor.md - * - * @file table-dialog.js - * @author pandao - * @version 1.2.1 - * @updateTime 2015-06-09 - * {@link https://github.com/pandao/editor.md} - * @license MIT - */ - -(function() { - - var factory = function (exports) { - - var $ = jQuery; - var pluginName = "table-dialog"; - - var langs = { - "zh-cn" : { - toolbar : { - table : "表格" - }, - dialog : { - table : { - title : "添加表格", - cellsLabel : "单元格数", - alignLabel : "对齐方式", - rows : "行数", - cols : "列数", - aligns : ["默认", "左对齐", "居中对齐", "右对齐"] - } - } - }, - "zh-tw" : { - toolbar : { - table : "添加表格" - }, - dialog : { - table : { - title : "添加表格", - cellsLabel : "單元格數", - alignLabel : "對齊方式", - rows : "行數", - cols : "列數", - aligns : ["默認", "左對齊", "居中對齊", "右對齊"] - } - } - }, - "en" : { - toolbar : { - table : "Tables" - }, - dialog : { - table : { - title : "Tables", - cellsLabel : "Cells", - alignLabel : "Align", - rows : "Rows", - cols : "Cols", - aligns : ["Default", "Left align", "Center align", "Right align"] - } - } - } - }; - - exports.fn.tableDialog = function() { - var _this = this; - var cm = this.cm; - var editor = this.editor; - var settings = this.settings; - var path = settings.path + "../plugins/" + pluginName +"/"; - var classPrefix = this.classPrefix; - var dialogName = classPrefix + pluginName, dialog; - - $.extend(true, this.lang, langs[this.lang.name]); - this.setToolbar(); - - var lang = this.lang; - var dialogLang = lang.dialog.table; - - var dialogContent = [ - "
                    ", - "", - dialogLang.rows + "   ", - dialogLang.cols + "
                    ", - "", - "
                    ", - "
                    " - ].join("\n"); - - if (editor.find("." + dialogName).length > 0) - { - dialog = editor.find("." + dialogName); - - this.dialogShowMask(dialog); - this.dialogLockScreen(); - dialog.show(); - } - else - { - dialog = this.createDialog({ - name : dialogName, - title : dialogLang.title, - width : 360, - height : 226, - mask : settings.dialogShowMask, - drag : settings.dialogDraggable, - content : dialogContent, - lockScreen : settings.dialogLockScreen, - maskStyle : { - opacity : settings.dialogMaskOpacity, - backgroundColor : settings.dialogMaskBgColor - }, - buttons : { - enter : [lang.buttons.enter, function() { - var rows = parseInt(this.find("[data-rows]").val()); - var cols = parseInt(this.find("[data-cols]").val()); - var align = this.find("[name=\"table-align\"]:checked").val(); - var table = ""; - var hrLine = "------------"; - - var alignSign = { - _default : hrLine, - left : ":" + hrLine, - center : ":" + hrLine + ":", - right : hrLine + ":" - }; - - if ( rows > 1 && cols > 0) - { - for (var r = 0, len = rows; r < len; r++) - { - var row = []; - var head = []; - - for (var c = 0, len2 = cols; c < len2; c++) - { - if (r === 1) { - head.push(alignSign[align]); - } - - row.push(" "); - } - - if (r === 1) { - table += "| " + head.join(" | ") + " |" + "\n"; - } - - table += "| " + row.join( (cols === 1) ? "" : " | " ) + " |" + "\n"; - } - } - - cm.replaceSelection(table); - - this.hide().lockScreen(false).hideMask(); - - return false; - }], - - cancel : [lang.buttons.cancel, function() { - this.hide().lockScreen(false).hideMask(); - - return false; - }] - } - }); - } - - var faBtns = dialog.find(".fa-btns"); - - if (faBtns.html() === "") - { - var icons = ["align-justify", "align-left", "align-center", "align-right"]; - var _lang = dialogLang.aligns; - var values = ["_default", "left", "center", "right"]; - - for (var i = 0, len = icons.length; i < len; i++) - { - var checked = (i === 0) ? " checked=\"checked\"" : ""; - var btn = ""; - - faBtns.append(btn); - } - } - }; - - }; - - // CommonJS/Node.js - if (typeof require === "function" && typeof exports === "object" && typeof module === "object") - { - module.exports = factory; - } - else if (typeof define === "function") // AMD/CMD/Sea.js - { - if (define.amd) { // for Require.js - - define(["editormd"], function(editormd) { - factory(editormd); - }); - - } else { // for Sea.js - define(function(require) { - var editormd = require("./../../editormd"); - factory(editormd); - }); - } - } - else - { - factory(window.editormd); - } - -})(); diff --git a/src/main/resources/static/editor-md/plugins/test-plugin/test-plugin.js b/src/main/resources/static/editor-md/plugins/test-plugin/test-plugin.js deleted file mode 100644 index bc4da31..0000000 --- a/src/main/resources/static/editor-md/plugins/test-plugin/test-plugin.js +++ /dev/null @@ -1,66 +0,0 @@ -/*! - * Test plugin for Editor.md - * - * @file test-plugin.js - * @author pandao - * @version 1.2.0 - * @updateTime 2015-03-07 - * {@link https://github.com/pandao/editor.md} - * @license MIT - */ - -(function() { - - var factory = function (exports) { - - var $ = jQuery; // if using module loader(Require.js/Sea.js). - - exports.testPlugin = function(){ - alert("testPlugin"); - }; - - exports.fn.testPluginMethodA = function() { - /* - var _this = this; // this == the current instance object of Editor.md - var lang = _this.lang; - var settings = _this.settings; - var editor = this.editor; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - var classPrefix = this.classPrefix; - - cm.focus(); - */ - //.... - - alert("testPluginMethodA"); - }; - - }; - - // CommonJS/Node.js - if (typeof require === "function" && typeof exports === "object" && typeof module === "object") - { - module.exports = factory; - } - else if (typeof define === "function") // AMD/CMD/Sea.js - { - if (define.amd) { // for Require.js - - define(["editormd"], function(editormd) { - factory(editormd); - }); - - } else { // for Sea.js - define(function(require) { - var editormd = require("./../../editormd"); - factory(editormd); - }); - } - } - else - { - factory(window.editormd); - } - -})(); diff --git a/src/main/resources/static/editor-md/scss/editormd.codemirror.scss b/src/main/resources/static/editor-md/scss/editormd.codemirror.scss deleted file mode 100644 index 3996bad..0000000 --- a/src/main/resources/static/editor-md/scss/editormd.codemirror.scss +++ /dev/null @@ -1,90 +0,0 @@ -@charset "UTF-8"; - -.editormd .CodeMirror, #{$prefix}preview { - display: inline-block; - width: 50%; - height: 100%; - vertical-align: top; - @include box-sizing(border-box); - margin: 0; -} - -#{$prefix}preview { - position: absolute; - top: 35px; - right: 0; - right: -1px\0; - overflow: auto; - line-height: 1.6; - display: none; - background: #fff; - z-index:10; -} - -.editormd { - - .CodeMirror { - z-index: 10; - float: left; - border-right: 1px solid $borderColor; - font-size: 14px; - font-family: "YaHei Consolas Hybrid", Consolas, "微软雅黑", "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, "Monaco", courier, monospace; - line-height: 1.6; - margin-top: 35px; - - pre { - font-size: 14px; - padding: 0 12px; - } - } - - .CodeMirror-linenumbers { - padding: 0 5px; - } - - .CodeMirror-selected { - background: #70B7FF; - } - - .CodeMirror-focused .CodeMirror-selected { - background: #70B7FF; - } - - .CodeMirror, .CodeMirror-scroll, #{$prefix}preview { - -webkit-overflow-scrolling : touch; - } - - .styled-background { - background-color: #ff7; - } - - .CodeMirror-focused .cm-matchhighlight { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFklEQVQI12NgYGBgkKzc8x9CMDAwAAAmhwSbidEoSQAAAABJRU5ErkJggg==); - background-position: bottom; - background-repeat: repeat-x; - } - - .CodeMirror-empty { - //outline: 1px solid #c22; - - &.CodeMirror-focused { - outline: none; - } - } - - .CodeMirror pre.CodeMirror-placeholder { - color: #999; - } - - .cm-trailingspace { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAYAAAB/qH1jAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QUXCToH00Y1UgAAACFJREFUCNdjPMDBUc/AwNDAAAFMTAwMDA0OP34wQgX/AQBYgwYEx4f9lQAAAABJRU5ErkJggg==); - background-position: bottom left; - background-repeat: repeat-x; - } - - .cm-tab { - background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=); - background-position: right; - background-repeat: no-repeat; - } -} diff --git a/src/main/resources/static/editor-md/scss/editormd.dialog.scss b/src/main/resources/static/editor-md/scss/editormd.dialog.scss deleted file mode 100644 index 609f6a9..0000000 --- a/src/main/resources/static/editor-md/scss/editormd.dialog.scss +++ /dev/null @@ -1,184 +0,0 @@ -@charset "UTF-8"; - -#{$prefix}dialog { - color: $color; - position: fixed; - z-index: 99999; - display: none; - @include border-radius(3px); - @include box-shadow(0 0 10px rgba(0, 0, 0, 0.3)); - //@include user-select(none); - background: #fff; - font-size: 14px; -} - -#{$prefix}dialog-container { - position: relative; - padding: 20px; - line-height: 1.4; - - h1 { - font-size: 24px; - margin-bottom: 10px; - - .fa { - color: #2C7EEA; - padding-right: 5px; - } - - small { - padding-left: 5px; - font-weight: normal; - font-size: 12px; - color: #999; - } - } - - select { - color: #999; - padding: 3px 8px; - border: 1px solid $borderColor; - } -} - -#{$prefix}dialog-close { - position: absolute; - top: 12px; - right: 15px; - font-size: 18px; - color: #ccc; - @include transition(color 300ms ease-out); - - &:hover { - color: #999; - } -} - -#{$prefix}dialog-header { - padding: 11px 20px; - border-bottom: 1px solid #eee; - @include transition(background 300ms ease-out); - - &:hover { - background: #f6f6f6; - } -} - -#{$prefix}dialog-title { - font-size: 14px; -} - -#{$prefix}dialog-footer { - padding: 10px 0 0 0; - text-align: right; -} - -#{$prefix}dialog-info { - width: 420px; - - h1 { - font-weight: normal; - } - - #{$prefix}dialog-container { - padding: 20px 25px 25px; - } - - #{$prefix}dialog-close { - top: 10px; - right: 10px; - } - - p > a, .hover-link:hover { - color: #2196F3; - } - - .hover-link { - color: #666; - } - - a { - .fa-external-link { - display: none; - } - - &:hover { - color: #2196F3; - - .fa-external-link { - display: inline-block; - } - } - } -} - -#{$prefix}mask, -#{$prefix}container-mask, -#{$prefix}dialog-mask { - display: none; - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; -} - -#{$prefix}mask, -#{$prefix}dialog-mask-bg { - background: #fff; - opacity: 0.5; - filter: alpha(opacity=50); -} - -#{$prefix}mask { - position: fixed; - background: #000; - @include opacity(0.2); - z-index: 99998; -} - -#{$prefix}container-mask, -#{$prefix}dialog-mask-con { - background: url(../images/loading.gif) no-repeat center center; - @include background-size(32px 32px); -} - -#{$prefix}container-mask { - z-index: 20; - display: block; - background-color: #fff; -} - -@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2) { - #{$prefix}container-mask, - #{$prefix}dialog-mask-con { - background-image: url(../images/loading@2x.gif); - } -} - -@media only screen and (-webkit-min-device-pixel-ratio: 3), only screen and (min-device-pixel-ratio: 3) { - #{$prefix}container-mask, - #{$prefix}dialog-mask-con { - background-image: url(../images/loading@3x.gif); - } -} - -#{$prefix}code-block-dialog, -#{$prefix}preformatted-text-dialog { - textarea { - width: 100%; - height: 400px; - margin-bottom: 6px; - overflow: auto; - border: 1px solid #eee; - background: #fff; - padding: 15px; - resize: none; - } -} - -#{$prefix}code-toolbar { - color: #999; - font-size: 14px; - margin: -5px 0 10px; -} \ No newline at end of file diff --git a/src/main/resources/static/editor-md/scss/editormd.form.scss b/src/main/resources/static/editor-md/scss/editormd.form.scss deleted file mode 100644 index e91456d..0000000 --- a/src/main/resources/static/editor-md/scss/editormd.form.scss +++ /dev/null @@ -1,130 +0,0 @@ -@charset "UTF-8"; - -// Form - -#{$prefix}form { - color: $color; - - label { - float: left; - display: block; - width: 75px; - text-align: left; - padding: 7px 0 15px 5px; - margin: 0 0 2px; - font-weight: normal; - } - - br { - clear: both; - } - - iframe { - display: none; - } - - input:focus { - outline: 0; - } - - input[type="text"], input[type="number"] { - color: #999; - padding: 8px; - border: 1px solid $borderColor; - } - - input[type="number"] { - width: 40px; - display: inline-block; - padding: 6px 8px; - } - - input[type="text"] { - display: inline-block; - width: 264px; - } - - .fa-btns { - display: inline-block; - - a { - color: #999; - padding: 7px 10px 0 0; - display: inline-block; - text-decoration: none; - text-align: center; - } - - .fa { - font-size: 1.3em; - } - - label { - float: none; - display: inline-block; - width: auto; - text-align: left; - padding: 0 0 0 5px; - cursor: pointer; - } - } -} - -#{$prefix}form, -#{$prefix}dialog-container, -#{$prefix}dialog-footer { - - input[type="submit"], #{$prefix}btn, button { - color: $color; - min-width: 75px; - cursor: pointer; - background: #fff; - padding: 7px 10px; - border: 1px solid #ddd; - @include border-radius(3px); - @include transition(background 300ms ease-out); - - &:hover { - background: #eee; - } - } - - #{$prefix}btn { - padding: 5px 8px 4px\0; - } - - #{$prefix}btn + #{$prefix}btn { - margin-left: 8px; - } -} - -#{$prefix}file-input { - width: 75px; - height: 32px; - margin-left: 8px; - position: relative; - display: inline-block; - - input[type="file"] { - width: 75px; - height: 32px; - opacity: 0; - cursor: pointer; - background: #000; - display: inline-block; - position: absolute; - top: 0; - right: 0; - - &::-webkit-file-upload-button { - visibility: hidden; - } - } - - input[type="submit"] { - } - - &:hover input[type="submit"] { - background: #eee; - } -} \ No newline at end of file diff --git a/src/main/resources/static/editor-md/scss/editormd.grid.scss b/src/main/resources/static/editor-md/scss/editormd.grid.scss deleted file mode 100644 index d7b6558..0000000 --- a/src/main/resources/static/editor-md/scss/editormd.grid.scss +++ /dev/null @@ -1,36 +0,0 @@ -@charset "utf-8"; - -.editormd-grid-table { - width: 99%; - display: table; - border: 1px solid #ddd; - border-collapse: collapse; -} - -.editormd-grid-table-row { - width: 100%; - display: table-row; - - a { - font-size: 1.4em; - width: 5%; - height: 36px; - color: #999; - text-align: center; - display: table-cell; - vertical-align: middle; - border: 1px solid #ddd; - text-decoration: none; - @include transition(background-color 300ms ease-out, color 100ms ease-in); - - &.selected { - color: #666; - background-color: #eee; - } - - &:hover { - color: #777; - background-color: #f6f6f6; - } - } -} \ No newline at end of file diff --git a/src/main/resources/static/editor-md/scss/editormd.logo.scss b/src/main/resources/static/editor-md/scss/editormd.logo.scss deleted file mode 100644 index 15ae537..0000000 --- a/src/main/resources/static/editor-md/scss/editormd.logo.scss +++ /dev/null @@ -1,89 +0,0 @@ -@charset "UTF-8"; - -@import "lib/variables"; -@import "lib/prefixes"; - -@font-face { - font-family: 'editormd-logo'; - src:url('../fonts/editormd-logo.eot?-5y8q6h'); - src:url('../fonts/editormd-logo.eot?#iefix-5y8q6h') format('embedded-opentype'), - url('../fonts/editormd-logo.woff?-5y8q6h') format('woff'), - url('../fonts/editormd-logo.ttf?-5y8q6h') format('truetype'), - url('../fonts/editormd-logo.svg?-5y8q6h#icomoon') format('svg'); - font-weight: normal; - font-style: normal; -} - -#{$prefix}logo, -#{$prefix}logo-1x, -#{$prefix}logo-2x, -#{$prefix}logo-3x, -#{$prefix}logo-4x, -#{$prefix}logo-5x, -#{$prefix}logo-6x, -#{$prefix}logo-7x, -#{$prefix}logo-8x { - font-family: 'editormd-logo'; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - font-size: inherit; - line-height: 1; - display: inline-block; - text-rendering: auto; - vertical-align: inherit; - - //Better Font Rendering - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - - &:before { - content: "\e1987"; - /* - HTML Entity 󡦇 - example: - */ - } -} - -#{$prefix}logo-1x { - font-size: 1em; -} - -#{$prefix}logo-lg { - font-size: 1.2em; -} - -#{$prefix}logo-2x { - font-size: 2em; -} - -#{$prefix}logo-3x { - font-size: 3em; -} - -#{$prefix}logo-4x { - font-size: 4em; -} - -#{$prefix}logo-5x { - font-size: 5em; -} - -#{$prefix}logo-6x { - font-size: 6em; -} - -#{$prefix}logo-7x { - font-size: 7em; -} - -#{$prefix}logo-8x { - font-size: 8em; -} - -#{$prefix}logo-color { - color: $mainColor; -} diff --git a/src/main/resources/static/editor-md/scss/editormd.menu.scss b/src/main/resources/static/editor-md/scss/editormd.menu.scss deleted file mode 100644 index 766903f..0000000 --- a/src/main/resources/static/editor-md/scss/editormd.menu.scss +++ /dev/null @@ -1,113 +0,0 @@ -@charset "UTF-8"; - -#{$prefix}menu { - margin: 0; - padding: 0; - list-style: none; - - > li { - margin: 0; - padding: 5px 1px; - display: inline-block; - position: relative; - - &.divider { - display: inline-block; - text-indent: -9999px; - margin: 0 5px; - height: 65%; - border-right: 1px solid $borderColor; - } - - > a { - outline: 0; - color: $color; - display: inline-block; - min-width: 24px; - font-size: 16px; - text-decoration: none; - text-align: center; - @include border-radius(2px); - border: 1px solid #fff; - @include transition(all 300ms ease-out); - - &:hover, &.active { - border: 1px solid $borderColor; - background: #eee; - } - - > .fa { - text-align: center; - display: block; - padding: 5px; - } - - > #{$prefix}bold { - padding: 5px 2px; - display: inline-block; - font-weight: bold; - } - } - - &:hover #{$prefix}dropdown-menu { - display: block; - } - } - - > li + li > a { - margin-left: 3px; - } -} - -#{$prefix}dropdown-menu { - display: none; - background: #fff; - border: 1px solid $borderColor; - width: 148px; - list-style: none; - position: absolute; - top: 33px; - left: 0; - z-index: 100; - @include box-shadow(1px 2px 6px rgba(0, 0, 0, 0.15)); - - &:before, &:after { - width: 0; - height: 0; - display: block; - content: ""; - position: absolute; - top: -11px; - left: 8px; - border: 5px solid transparent; - } - - &:before { - border-bottom-color: #ccc; - } - - &:after { - border-bottom-color: #ffffff; - top: -10px; - } - - - > li { - - > a { - color: $color; - display: block; - text-decoration: none; - padding: 8px 10px; - - &:hover { - background: #f6f6f6; - @include transition(all 300ms ease-out); - } - } - } - - > li + li { - border-top: 1px solid $borderColor; - } -} \ No newline at end of file diff --git a/src/main/resources/static/editor-md/scss/editormd.preview.scss b/src/main/resources/static/editor-md/scss/editormd.preview.scss deleted file mode 100644 index 5f9ce90..0000000 --- a/src/main/resources/static/editor-md/scss/editormd.preview.scss +++ /dev/null @@ -1,322 +0,0 @@ -@charset "UTF-8"; - -@import "lib/variables"; -@import "lib/prefixes"; -@import "font-awesome"; - -@import "editormd.logo"; - -// github-markdown.css -@import "github-markdown"; - -#{$prefix}preview-container, #{$prefix}html-preview { - text-align: left; - font-size: 14px; - line-height: 1.6; - padding: 20px; - overflow: auto; - width: 100%; - background-color: #fff; - - blockquote { - color: $color; - border-left: 4px solid $borderColor; - padding-left: 20px; - margin-left: 0; - font-size: 14px; - font-style: italic; - } - - p code { - margin-left: 5px; - margin-right: 4px; - } - - abbr { - background: #ffffdd; - } - - hr { - height: 1px; - border: none; - border-top: 1px solid $borderColor; - background: none; - } - - code { - border: 1px solid $borderColor; - background: #f6f6f6; - padding: 3px; - border-radius: 3px; - font-size: 14px; - } - - pre { - border: 1px solid $borderColor; - background: #f6f6f6; - padding: 10px; - @include border-radius(3px); - - code { - padding: 0; - } - } - - pre, code, kbd { - font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; - } - - table thead tr { - background-color: #F8F8F8; - } - - .markdown-toc { - } - - .markdown-toc-list { - } - - p#{$prefix}tex { - text-align: center; - } - - span#{$prefix}tex { - margin: 0 5px; - } - - .emoji { - width: 24px; - height: 24px; - } - - .katex { - font-size: 1.4em; - } - - .sequence-diagram, .flowchart { - margin: 0 auto; - text-align: center; - - svg { - margin: 0 auto; - } - - text { - font-size : 15px !important; - font-family: "YaHei Consolas Hybrid", Consolas, "Microsoft YaHei", "Malgun Gothic", "Segoe UI", Helvetica, Arial !important; - } - } -} - -//Pretty printing styles. Used with prettify.js. - -@import "prettify"; - -#{$prefix}preview-container, #{$prefix}html-preview { - pre.prettyprint { - padding: 10px; - border: 1px solid $borderColor; - white-space: pre-wrap; - word-wrap: break-word; - } - - ol.linenums { - color: #999; - padding-left: 2.5em; - - li { - list-style-type: decimal; - - code { - border: none; - background:none; - padding: 0; - } - } - } -} - -#{$prefix}preview-container, #{$prefix}html-preview { - - #{$prefix}toc-menu { - margin: 8px 0 12px 0; - display: inline-block; - - > .markdown-toc { - position: relative; - @include border-radius(4px); - border: 1px solid #ddd; - display: inline-block; - font-size: 1em; - - > ul { - width : 160%; - min-width: 180px; - position: absolute; - left: -1px; - top: -2px; - z-index: 100; - padding: 0 10px 10px; - display: none; - background: #fff; - border: 1px solid #ddd; - @include border-radius(4px); - @include box-shadow(0 3px 5px rgba(0, 0, 0, 0.2)); - - > li ul { - width: 100%; - min-width: 180px; - border: 1px solid #ddd; - display: none; - background: #fff; - @include border-radius(4px); - } - - > li a { - color: #666; - padding: 6px 10px; - display: block; - @include transition(background-color 500ms ease-out); - - &:hover { - background-color: #f6f6f6; - } - } - } - - li { - position: relative; - - > ul { - position: absolute; - top: 32px; - left: 10%; - display: none; - @include box-shadow(0 3px 5px rgba(0, 0, 0, 0.2)); - - &:before, &:after { - pointer-events: pointer-events; - position: absolute; - left: 15px; - top: -6px; - display: block; - content: ""; - width: 0; - height: 0; - border: 6px solid transparent; - border-width: 0 6px 6px; - z-index: 10; - } - - &:before { - border-bottom-color: #ccc; - } - - &:after { - border-bottom-color: #ffffff; - top: -5px; - } - } - } - } - - ul { - list-style: none; - } - - a { - text-decoration: none; - } - - h1 { - font-size: 16px; - padding: 5px 0 10px 10px; - line-height: 1; - border-bottom: 1px solid #eee; - - .fa { - padding-left: 10px; - } - } - - .toc-menu-btn { - color: #666; - min-width: 180px; - padding: 5px 10px; - border-radius: 4px; - display: inline-block; - @include transition(background-color 500ms ease-out); - - &:hover { - background-color: #f6f6f6; - } - - .fa { - float: right; - padding: 3px 0 0 10px; - font-size: 1.3em; - } - } - } -} - -.markdown-body { - #{$prefix}toc-menu { - ul { - padding-left: 0; - } - } - - .highlight pre, pre { - line-height: 1.6; - } -} - -hr.editormd-page-break { - border: 1px dotted #ccc; - font-size: 0; - height: 2px; -} - -@media only print { - hr.editormd-page-break { - background: none; - border: none; - height: 0; - } -} - -#{$prefix}html-preview { - textarea { - display : none; - } - - hr.editormd-page-break { - background: none; - border: none; - height: 0; - } -} - -#{$prefix}preview-close-btn { - color: #fff; - padding: 4px 6px; - font-size: 18px; - @include border-radius(500px); - display: none; - background-color: #ccc; - position: absolute; - top: 25px; - right: 35px; - z-index: 19; - @include transition(background-color 300ms ease-out); - - &:hover { - background-color: #999; - } -} - -.editormd-preview-active { - width: 100%; - padding: 40px; -} \ No newline at end of file diff --git a/src/main/resources/static/editor-md/scss/editormd.preview.themes.scss b/src/main/resources/static/editor-md/scss/editormd.preview.themes.scss deleted file mode 100644 index 6553c1e..0000000 --- a/src/main/resources/static/editor-md/scss/editormd.preview.themes.scss +++ /dev/null @@ -1,131 +0,0 @@ -/* Preview dark theme */ - -#{$prefix}preview-theme-dark { - color: #777; - background:#2C2827; - - #{$prefix}preview-container { - color: #888; - background-color: #2C2827; - //font-family: "Meiryo UI", "Helvetica Neue", "Microsoft YaHei"; - - pre.prettyprint { - border: none; - } - - blockquote { - color: #555; - padding: 0.5em; - background: #222; - border-color: #333; - } - - abbr { - color: #fff; - padding: 1px 3px; - @include border-radius(3px); - background:#ff9900; - } - - code { - color: #fff; - border: none; - padding: 1px 3px; - @include border-radius(3px); - background: #5A9600; - } - - table { - border: none; - } - - .fa-emoji { - color: #B4BF42; - } - - .katex { - color: #FEC93F; - } - } - - .editormd-toc-menu { - > .markdown-toc { - background:#fff; - border:none; - - h1 { - border-color:#ddd; - } - } - } - - .markdown-body { - h1, h2, hr { - border-color: #222; - } - } - - pre { - color: #999; - background-color: #111; - background-color: rgba(0,0,0,.4); - - /* plain text */ - .pln { - color: #999; - } - } - - li.L1, li.L3, li.L5, li.L7, li.L9 { - background: none; - } - - [class*=editormd-logo] { - color: #2196F3; - } - - .sequence-diagram { - text { - fill: #fff; - } - - rect, path { - color:#fff; - fill : #64D1CB; - stroke : #64D1CB; - } - } - - .flowchart { - rect, path { - stroke : #A6C6FF; - } - - rect { - fill: #A6C6FF; - } - - text { - fill: #5879B4; - } - } -} - -@media screen { - - #{$prefix}preview-theme-dark { - .str { color: #080 } /* string content */ - .kwd { color: #ff9900; } /* a keyword */ - .com { color: #444444; } /* a comment */ - .typ { color: #606 } /* a type name */ - .lit { color: #066 } /* a literal value */ - /* punctuation, lisp open bracket, lisp close bracket */ - .pun, .opn, .clo { color: #660 } - .tag { color: #ff9900; } /* a markup tag name */ - .atn { color: #6C95F5; } /* a markup attribute name */ - .atv { color: #080 } /* a markup attribute value */ - .dec, .var { color: #008BA7; } /* a declaration; a variable name */ - .fun { color: red } /* a function name */ - } - -} \ No newline at end of file diff --git a/src/main/resources/static/editor-md/scss/editormd.scss b/src/main/resources/static/editor-md/scss/editormd.scss deleted file mode 100644 index 30abf38..0000000 --- a/src/main/resources/static/editor-md/scss/editormd.scss +++ /dev/null @@ -1,137 +0,0 @@ -@charset "UTF-8"; - -@import "lib/variables"; -@import "lib/prefixes"; - -.editormd { - width: 90%; - height: 640px; - margin: 0 auto; - text-align: left; - overflow: hidden; - position: relative; - margin-bottom: 15px; - border: 1px solid $borderColor; - font-family: "Meiryo UI", "Microsoft YaHei", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, "Monaco", monospace, Tahoma, STXihei, "华文细黑", STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, "宋体", Heiti, "黑体", sans-serif; - - *, *:before, *:after { - @include box-sizing(border-box); - } - - a { - text-decoration: none; - } - - img { - border: none; - vertical-align: middle; - } - - > textarea, - #{$prefix}html-textarea, - #{$prefix}markdown-textarea { - width: 0; - height: 0; - outline: 0; - resize:none; - } - - #{$prefix}html-textarea, - #{$prefix}markdown-textarea { - display : none; - } - - input[type="text"], - input[type="button"], - input[type="submit"], - select, textarea, button { - @include appearance(none); - } - - ::-webkit-scrollbar { - height: 10px; - width: 7px; - background: rgba(0, 0, 0, .1); - - &:hover { - background: rgba(0, 0, 0, .2); - } - } - - ::-webkit-scrollbar-thumb { - background: rgba(0,0,0,0.3); - @include border-radius(6px); - - &:hover { - @include box-shadow(inset 1px 1px 1px rgba(0, 0, 0, .25)); - background-color: rgba(0, 0, 0, .4); - } - } -} - -#{$prefix}user-unselect { - @include user-select(none); -} - -#{$prefix}toolbar { - width: 100%; - min-height: 37px; - background: #fff; - display: none; - position: absolute; - top: 0; - left: 0; - z-index: 10; - border-bottom: 1px solid $borderColor; -} - -#{$prefix}toolbar-container { - padding: 0 8px; - min-height: 35px; - @include user-select(none); -} - -@import "editormd.menu"; - -#{$prefix}container { - margin: 0; - width: 100%; - height: 100%; - overflow: hidden; - padding: 35px 0 0; - position: relative; - background: #fff; - @include box-sizing(border-box); -} - -@import "editormd.dialog"; -@import "editormd.grid"; -@import "editormd.tab"; -@import "editormd.form"; -@import "editormd.codemirror"; -@import "editormd.preview"; -@import "editormd.preview.themes"; - -#{$prefix}onlyread { - #{$prefix}toolbar { - display: none; - } - - .CodeMirror { - margin-top: 0; - } - - #{$prefix}preview { - top: 0; - } -} - -#{$prefix}fullscreen { - position: fixed; - top : 0; - left : 0; - border: none; - margin: 0 auto; -} - -@import "editormd.themes"; \ No newline at end of file diff --git a/src/main/resources/static/editor-md/scss/editormd.tab.scss b/src/main/resources/static/editor-md/scss/editormd.tab.scss deleted file mode 100644 index 483b420..0000000 --- a/src/main/resources/static/editor-md/scss/editormd.tab.scss +++ /dev/null @@ -1,49 +0,0 @@ -@charset "utf-8"; - -.editormd-tab { -} - -.editormd-tab-head { - list-style: none; - border-bottom: 1px solid #ddd; - - li { - display: inline-block; - - a { - color: #999; - display: block; - padding: 6px 12px 5px; - text-align: center; - text-decoration: none; - margin-bottom: -1px; - border: 1px solid #ddd; - @include border-top-left-radius(3px); - @include border-top-right-radius(3px); - background: #f6f6f6; - @include transition(all 300ms ease-out); - - &:hover { - color: #666; - background: #eee; - } - } - - &.active a { - color: #666; - background: #fff; - border-bottom-color: #fff; - } - } - - li + li { - margin-left: 3px; - } -} - -.editormd-tab-container { -} - -.editormd-tab-box { - padding: 20px 0; -} \ No newline at end of file diff --git a/src/main/resources/static/editor-md/scss/editormd.themes.scss b/src/main/resources/static/editor-md/scss/editormd.themes.scss deleted file mode 100644 index 257766a..0000000 --- a/src/main/resources/static/editor-md/scss/editormd.themes.scss +++ /dev/null @@ -1,28 +0,0 @@ -/* Editor.md Dark theme */ - -#{$prefix}theme-dark { - border-color: #1a1a17; - - #{$prefix}toolbar { - background: #1A1A17; - border-color: #1a1a17; - } - - #{$prefix}menu > li > a { - color: #777; - border-color: #1a1a17; - - &:hover, &.active { - border-color: #333; - background: #333; - } - } - - #{$prefix}menu > li.divider { - border-right: 1px solid #111; - } - - .CodeMirror { - border-right: 1px solid rgba(0,0,0,0.1); - } -} \ No newline at end of file diff --git a/src/main/resources/static/editor-md/scss/font-awesome.scss b/src/main/resources/static/editor-md/scss/font-awesome.scss deleted file mode 100644 index 2dcdc22..0000000 --- a/src/main/resources/static/editor-md/scss/font-awesome.scss +++ /dev/null @@ -1,1801 +0,0 @@ -/*! - * Font Awesome 4.3.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */ -/* FONT PATH - * -------------------------- */ -@font-face { - font-family: 'FontAwesome'; - src: url('../fonts/fontawesome-webfont.eot?v=4.3.0'); - src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.3.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.3.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.3.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.3.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.3.0#fontawesomeregular') format('svg'); - font-weight: normal; - font-style: normal; -} -.fa { - display: inline-block; - font: normal normal normal 14px/1 FontAwesome; - font-size: inherit; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - transform: translate(0, 0); -} -/* makes the font 33% larger relative to the icon container */ -.fa-lg { - font-size: 1.33333333em; - line-height: 0.75em; - vertical-align: -15%; -} -.fa-2x { - font-size: 2em; -} -.fa-3x { - font-size: 3em; -} -.fa-4x { - font-size: 4em; -} -.fa-5x { - font-size: 5em; -} -.fa-fw { - width: 1.28571429em; - text-align: center; -} -.fa-ul { - padding-left: 0; - margin-left: 2.14285714em; - list-style-type: none; -} -.fa-ul > li { - position: relative; -} -.fa-li { - position: absolute; - left: -2.14285714em; - width: 2.14285714em; - top: 0.14285714em; - text-align: center; -} -.fa-li.fa-lg { - left: -1.85714286em; -} -.fa-border { - padding: .2em .25em .15em; - border: solid 0.08em #eeeeee; - border-radius: .1em; -} -.pull-right { - float: right; -} -.pull-left { - float: left; -} -.fa.pull-left { - margin-right: .3em; -} -.fa.pull-right { - margin-left: .3em; -} -.fa-spin { - -webkit-animation: fa-spin 2s infinite linear; - animation: fa-spin 2s infinite linear; -} -.fa-pulse { - -webkit-animation: fa-spin 1s infinite steps(8); - animation: fa-spin 1s infinite steps(8); -} -@-webkit-keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -@keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -.fa-rotate-90 { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); - -webkit-transform: rotate(90deg); - -ms-transform: rotate(90deg); - transform: rotate(90deg); -} -.fa-rotate-180 { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); - -webkit-transform: rotate(180deg); - -ms-transform: rotate(180deg); - transform: rotate(180deg); -} -.fa-rotate-270 { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); - -webkit-transform: rotate(270deg); - -ms-transform: rotate(270deg); - transform: rotate(270deg); -} -.fa-flip-horizontal { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1); - -webkit-transform: scale(-1, 1); - -ms-transform: scale(-1, 1); - transform: scale(-1, 1); -} -.fa-flip-vertical { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1); - -webkit-transform: scale(1, -1); - -ms-transform: scale(1, -1); - transform: scale(1, -1); -} -:root .fa-rotate-90, -:root .fa-rotate-180, -:root .fa-rotate-270, -:root .fa-flip-horizontal, -:root .fa-flip-vertical { - filter: none; -} -.fa-stack { - position: relative; - display: inline-block; - width: 2em; - height: 2em; - line-height: 2em; - vertical-align: middle; -} -.fa-stack-1x, -.fa-stack-2x { - position: absolute; - left: 0; - width: 100%; - text-align: center; -} -.fa-stack-1x { - line-height: inherit; -} -.fa-stack-2x { - font-size: 2em; -} -.fa-inverse { - color: #ffffff; -} -/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen - readers do not read off random characters that represent icons */ -.fa-glass:before { - content: "\f000"; -} -.fa-music:before { - content: "\f001"; -} -.fa-search:before { - content: "\f002"; -} -.fa-envelope-o:before { - content: "\f003"; -} -.fa-heart:before { - content: "\f004"; -} -.fa-star:before { - content: "\f005"; -} -.fa-star-o:before { - content: "\f006"; -} -.fa-user:before { - content: "\f007"; -} -.fa-film:before { - content: "\f008"; -} -.fa-th-large:before { - content: "\f009"; -} -.fa-th:before { - content: "\f00a"; -} -.fa-th-list:before { - content: "\f00b"; -} -.fa-check:before { - content: "\f00c"; -} -.fa-remove:before, -.fa-close:before, -.fa-times:before { - content: "\f00d"; -} -.fa-search-plus:before { - content: "\f00e"; -} -.fa-search-minus:before { - content: "\f010"; -} -.fa-power-off:before { - content: "\f011"; -} -.fa-signal:before { - content: "\f012"; -} -.fa-gear:before, -.fa-cog:before { - content: "\f013"; -} -.fa-trash-o:before { - content: "\f014"; -} -.fa-home:before { - content: "\f015"; -} -.fa-file-o:before { - content: "\f016"; -} -.fa-clock-o:before { - content: "\f017"; -} -.fa-road:before { - content: "\f018"; -} -.fa-download:before { - content: "\f019"; -} -.fa-arrow-circle-o-down:before { - content: "\f01a"; -} -.fa-arrow-circle-o-up:before { - content: "\f01b"; -} -.fa-inbox:before { - content: "\f01c"; -} -.fa-play-circle-o:before { - content: "\f01d"; -} -.fa-rotate-right:before, -.fa-repeat:before { - content: "\f01e"; -} -.fa-refresh:before { - content: "\f021"; -} -.fa-list-alt:before { - content: "\f022"; -} -.fa-lock:before { - content: "\f023"; -} -.fa-flag:before { - content: "\f024"; -} -.fa-headphones:before { - content: "\f025"; -} -.fa-volume-off:before { - content: "\f026"; -} -.fa-volume-down:before { - content: "\f027"; -} -.fa-volume-up:before { - content: "\f028"; -} -.fa-qrcode:before { - content: "\f029"; -} -.fa-barcode:before { - content: "\f02a"; -} -.fa-tag:before { - content: "\f02b"; -} -.fa-tags:before { - content: "\f02c"; -} -.fa-book:before { - content: "\f02d"; -} -.fa-bookmark:before { - content: "\f02e"; -} -.fa-print:before { - content: "\f02f"; -} -.fa-camera:before { - content: "\f030"; -} -.fa-font:before { - content: "\f031"; -} -.fa-bold:before { - content: "\f032"; -} -.fa-italic:before { - content: "\f033"; -} -.fa-text-height:before { - content: "\f034"; -} -.fa-text-width:before { - content: "\f035"; -} -.fa-align-left:before { - content: "\f036"; -} -.fa-align-center:before { - content: "\f037"; -} -.fa-align-right:before { - content: "\f038"; -} -.fa-align-justify:before { - content: "\f039"; -} -.fa-list:before { - content: "\f03a"; -} -.fa-dedent:before, -.fa-outdent:before { - content: "\f03b"; -} -.fa-indent:before { - content: "\f03c"; -} -.fa-video-camera:before { - content: "\f03d"; -} -.fa-photo:before, -.fa-image:before, -.fa-picture-o:before { - content: "\f03e"; -} -.fa-pencil:before { - content: "\f040"; -} -.fa-map-marker:before { - content: "\f041"; -} -.fa-adjust:before { - content: "\f042"; -} -.fa-tint:before { - content: "\f043"; -} -.fa-edit:before, -.fa-pencil-square-o:before { - content: "\f044"; -} -.fa-share-square-o:before { - content: "\f045"; -} -.fa-check-square-o:before { - content: "\f046"; -} -.fa-arrows:before { - content: "\f047"; -} -.fa-step-backward:before { - content: "\f048"; -} -.fa-fast-backward:before { - content: "\f049"; -} -.fa-backward:before { - content: "\f04a"; -} -.fa-play:before { - content: "\f04b"; -} -.fa-pause:before { - content: "\f04c"; -} -.fa-stop:before { - content: "\f04d"; -} -.fa-forward:before { - content: "\f04e"; -} -.fa-fast-forward:before { - content: "\f050"; -} -.fa-step-forward:before { - content: "\f051"; -} -.fa-eject:before { - content: "\f052"; -} -.fa-chevron-left:before { - content: "\f053"; -} -.fa-chevron-right:before { - content: "\f054"; -} -.fa-plus-circle:before { - content: "\f055"; -} -.fa-minus-circle:before { - content: "\f056"; -} -.fa-times-circle:before { - content: "\f057"; -} -.fa-check-circle:before { - content: "\f058"; -} -.fa-question-circle:before { - content: "\f059"; -} -.fa-info-circle:before { - content: "\f05a"; -} -.fa-crosshairs:before { - content: "\f05b"; -} -.fa-times-circle-o:before { - content: "\f05c"; -} -.fa-check-circle-o:before { - content: "\f05d"; -} -.fa-ban:before { - content: "\f05e"; -} -.fa-arrow-left:before { - content: "\f060"; -} -.fa-arrow-right:before { - content: "\f061"; -} -.fa-arrow-up:before { - content: "\f062"; -} -.fa-arrow-down:before { - content: "\f063"; -} -.fa-mail-forward:before, -.fa-share:before { - content: "\f064"; -} -.fa-expand:before { - content: "\f065"; -} -.fa-compress:before { - content: "\f066"; -} -.fa-plus:before { - content: "\f067"; -} -.fa-minus:before { - content: "\f068"; -} -.fa-asterisk:before { - content: "\f069"; -} -.fa-exclamation-circle:before { - content: "\f06a"; -} -.fa-gift:before { - content: "\f06b"; -} -.fa-leaf:before { - content: "\f06c"; -} -.fa-fire:before { - content: "\f06d"; -} -.fa-eye:before { - content: "\f06e"; -} -.fa-eye-slash:before { - content: "\f070"; -} -.fa-warning:before, -.fa-exclamation-triangle:before { - content: "\f071"; -} -.fa-plane:before { - content: "\f072"; -} -.fa-calendar:before { - content: "\f073"; -} -.fa-random:before { - content: "\f074"; -} -.fa-comment:before { - content: "\f075"; -} -.fa-magnet:before { - content: "\f076"; -} -.fa-chevron-up:before { - content: "\f077"; -} -.fa-chevron-down:before { - content: "\f078"; -} -.fa-retweet:before { - content: "\f079"; -} -.fa-shopping-cart:before { - content: "\f07a"; -} -.fa-folder:before { - content: "\f07b"; -} -.fa-folder-open:before { - content: "\f07c"; -} -.fa-arrows-v:before { - content: "\f07d"; -} -.fa-arrows-h:before { - content: "\f07e"; -} -.fa-bar-chart-o:before, -.fa-bar-chart:before { - content: "\f080"; -} -.fa-twitter-square:before { - content: "\f081"; -} -.fa-facebook-square:before { - content: "\f082"; -} -.fa-camera-retro:before { - content: "\f083"; -} -.fa-key:before { - content: "\f084"; -} -.fa-gears:before, -.fa-cogs:before { - content: "\f085"; -} -.fa-comments:before { - content: "\f086"; -} -.fa-thumbs-o-up:before { - content: "\f087"; -} -.fa-thumbs-o-down:before { - content: "\f088"; -} -.fa-star-half:before { - content: "\f089"; -} -.fa-heart-o:before { - content: "\f08a"; -} -.fa-sign-out:before { - content: "\f08b"; -} -.fa-linkedin-square:before { - content: "\f08c"; -} -.fa-thumb-tack:before { - content: "\f08d"; -} -.fa-external-link:before { - content: "\f08e"; -} -.fa-sign-in:before { - content: "\f090"; -} -.fa-trophy:before { - content: "\f091"; -} -.fa-github-square:before { - content: "\f092"; -} -.fa-upload:before { - content: "\f093"; -} -.fa-lemon-o:before { - content: "\f094"; -} -.fa-phone:before { - content: "\f095"; -} -.fa-square-o:before { - content: "\f096"; -} -.fa-bookmark-o:before { - content: "\f097"; -} -.fa-phone-square:before { - content: "\f098"; -} -.fa-twitter:before { - content: "\f099"; -} -.fa-facebook-f:before, -.fa-facebook:before { - content: "\f09a"; -} -.fa-github:before { - content: "\f09b"; -} -.fa-unlock:before { - content: "\f09c"; -} -.fa-credit-card:before { - content: "\f09d"; -} -.fa-rss:before { - content: "\f09e"; -} -.fa-hdd-o:before { - content: "\f0a0"; -} -.fa-bullhorn:before { - content: "\f0a1"; -} -.fa-bell:before { - content: "\f0f3"; -} -.fa-certificate:before { - content: "\f0a3"; -} -.fa-hand-o-right:before { - content: "\f0a4"; -} -.fa-hand-o-left:before { - content: "\f0a5"; -} -.fa-hand-o-up:before { - content: "\f0a6"; -} -.fa-hand-o-down:before { - content: "\f0a7"; -} -.fa-arrow-circle-left:before { - content: "\f0a8"; -} -.fa-arrow-circle-right:before { - content: "\f0a9"; -} -.fa-arrow-circle-up:before { - content: "\f0aa"; -} -.fa-arrow-circle-down:before { - content: "\f0ab"; -} -.fa-globe:before { - content: "\f0ac"; -} -.fa-wrench:before { - content: "\f0ad"; -} -.fa-tasks:before { - content: "\f0ae"; -} -.fa-filter:before { - content: "\f0b0"; -} -.fa-briefcase:before { - content: "\f0b1"; -} -.fa-arrows-alt:before { - content: "\f0b2"; -} -.fa-group:before, -.fa-users:before { - content: "\f0c0"; -} -.fa-chain:before, -.fa-link:before { - content: "\f0c1"; -} -.fa-cloud:before { - content: "\f0c2"; -} -.fa-flask:before { - content: "\f0c3"; -} -.fa-cut:before, -.fa-scissors:before { - content: "\f0c4"; -} -.fa-copy:before, -.fa-files-o:before { - content: "\f0c5"; -} -.fa-paperclip:before { - content: "\f0c6"; -} -.fa-save:before, -.fa-floppy-o:before { - content: "\f0c7"; -} -.fa-square:before { - content: "\f0c8"; -} -.fa-navicon:before, -.fa-reorder:before, -.fa-bars:before { - content: "\f0c9"; -} -.fa-list-ul:before { - content: "\f0ca"; -} -.fa-list-ol:before { - content: "\f0cb"; -} -.fa-strikethrough:before { - content: "\f0cc"; -} -.fa-underline:before { - content: "\f0cd"; -} -.fa-table:before { - content: "\f0ce"; -} -.fa-magic:before { - content: "\f0d0"; -} -.fa-truck:before { - content: "\f0d1"; -} -.fa-pinterest:before { - content: "\f0d2"; -} -.fa-pinterest-square:before { - content: "\f0d3"; -} -.fa-google-plus-square:before { - content: "\f0d4"; -} -.fa-google-plus:before { - content: "\f0d5"; -} -.fa-money:before { - content: "\f0d6"; -} -.fa-caret-down:before { - content: "\f0d7"; -} -.fa-caret-up:before { - content: "\f0d8"; -} -.fa-caret-left:before { - content: "\f0d9"; -} -.fa-caret-right:before { - content: "\f0da"; -} -.fa-columns:before { - content: "\f0db"; -} -.fa-unsorted:before, -.fa-sort:before { - content: "\f0dc"; -} -.fa-sort-down:before, -.fa-sort-desc:before { - content: "\f0dd"; -} -.fa-sort-up:before, -.fa-sort-asc:before { - content: "\f0de"; -} -.fa-envelope:before { - content: "\f0e0"; -} -.fa-linkedin:before { - content: "\f0e1"; -} -.fa-rotate-left:before, -.fa-undo:before { - content: "\f0e2"; -} -.fa-legal:before, -.fa-gavel:before { - content: "\f0e3"; -} -.fa-dashboard:before, -.fa-tachometer:before { - content: "\f0e4"; -} -.fa-comment-o:before { - content: "\f0e5"; -} -.fa-comments-o:before { - content: "\f0e6"; -} -.fa-flash:before, -.fa-bolt:before { - content: "\f0e7"; -} -.fa-sitemap:before { - content: "\f0e8"; -} -.fa-umbrella:before { - content: "\f0e9"; -} -.fa-paste:before, -.fa-clipboard:before { - content: "\f0ea"; -} -.fa-lightbulb-o:before { - content: "\f0eb"; -} -.fa-exchange:before { - content: "\f0ec"; -} -.fa-cloud-download:before { - content: "\f0ed"; -} -.fa-cloud-upload:before { - content: "\f0ee"; -} -.fa-user-md:before { - content: "\f0f0"; -} -.fa-stethoscope:before { - content: "\f0f1"; -} -.fa-suitcase:before { - content: "\f0f2"; -} -.fa-bell-o:before { - content: "\f0a2"; -} -.fa-coffee:before { - content: "\f0f4"; -} -.fa-cutlery:before { - content: "\f0f5"; -} -.fa-file-text-o:before { - content: "\f0f6"; -} -.fa-building-o:before { - content: "\f0f7"; -} -.fa-hospital-o:before { - content: "\f0f8"; -} -.fa-ambulance:before { - content: "\f0f9"; -} -.fa-medkit:before { - content: "\f0fa"; -} -.fa-fighter-jet:before { - content: "\f0fb"; -} -.fa-beer:before { - content: "\f0fc"; -} -.fa-h-square:before { - content: "\f0fd"; -} -.fa-plus-square:before { - content: "\f0fe"; -} -.fa-angle-double-left:before { - content: "\f100"; -} -.fa-angle-double-right:before { - content: "\f101"; -} -.fa-angle-double-up:before { - content: "\f102"; -} -.fa-angle-double-down:before { - content: "\f103"; -} -.fa-angle-left:before { - content: "\f104"; -} -.fa-angle-right:before { - content: "\f105"; -} -.fa-angle-up:before { - content: "\f106"; -} -.fa-angle-down:before { - content: "\f107"; -} -.fa-desktop:before { - content: "\f108"; -} -.fa-laptop:before { - content: "\f109"; -} -.fa-tablet:before { - content: "\f10a"; -} -.fa-mobile-phone:before, -.fa-mobile:before { - content: "\f10b"; -} -.fa-circle-o:before { - content: "\f10c"; -} -.fa-quote-left:before { - content: "\f10d"; -} -.fa-quote-right:before { - content: "\f10e"; -} -.fa-spinner:before { - content: "\f110"; -} -.fa-circle:before { - content: "\f111"; -} -.fa-mail-reply:before, -.fa-reply:before { - content: "\f112"; -} -.fa-github-alt:before { - content: "\f113"; -} -.fa-folder-o:before { - content: "\f114"; -} -.fa-folder-open-o:before { - content: "\f115"; -} -.fa-smile-o:before { - content: "\f118"; -} -.fa-frown-o:before { - content: "\f119"; -} -.fa-meh-o:before { - content: "\f11a"; -} -.fa-gamepad:before { - content: "\f11b"; -} -.fa-keyboard-o:before { - content: "\f11c"; -} -.fa-flag-o:before { - content: "\f11d"; -} -.fa-flag-checkered:before { - content: "\f11e"; -} -.fa-terminal:before { - content: "\f120"; -} -.fa-code:before { - content: "\f121"; -} -.fa-mail-reply-all:before, -.fa-reply-all:before { - content: "\f122"; -} -.fa-star-half-empty:before, -.fa-star-half-full:before, -.fa-star-half-o:before { - content: "\f123"; -} -.fa-location-arrow:before { - content: "\f124"; -} -.fa-crop:before { - content: "\f125"; -} -.fa-code-fork:before { - content: "\f126"; -} -.fa-unlink:before, -.fa-chain-broken:before { - content: "\f127"; -} -.fa-question:before { - content: "\f128"; -} -.fa-info:before { - content: "\f129"; -} -.fa-exclamation:before { - content: "\f12a"; -} -.fa-superscript:before { - content: "\f12b"; -} -.fa-subscript:before { - content: "\f12c"; -} -.fa-eraser:before { - content: "\f12d"; -} -.fa-puzzle-piece:before { - content: "\f12e"; -} -.fa-microphone:before { - content: "\f130"; -} -.fa-microphone-slash:before { - content: "\f131"; -} -.fa-shield:before { - content: "\f132"; -} -.fa-calendar-o:before { - content: "\f133"; -} -.fa-fire-extinguisher:before { - content: "\f134"; -} -.fa-rocket:before { - content: "\f135"; -} -.fa-maxcdn:before { - content: "\f136"; -} -.fa-chevron-circle-left:before { - content: "\f137"; -} -.fa-chevron-circle-right:before { - content: "\f138"; -} -.fa-chevron-circle-up:before { - content: "\f139"; -} -.fa-chevron-circle-down:before { - content: "\f13a"; -} -.fa-html5:before { - content: "\f13b"; -} -.fa-css3:before { - content: "\f13c"; -} -.fa-anchor:before { - content: "\f13d"; -} -.fa-unlock-alt:before { - content: "\f13e"; -} -.fa-bullseye:before { - content: "\f140"; -} -.fa-ellipsis-h:before { - content: "\f141"; -} -.fa-ellipsis-v:before { - content: "\f142"; -} -.fa-rss-square:before { - content: "\f143"; -} -.fa-play-circle:before { - content: "\f144"; -} -.fa-ticket:before { - content: "\f145"; -} -.fa-minus-square:before { - content: "\f146"; -} -.fa-minus-square-o:before { - content: "\f147"; -} -.fa-level-up:before { - content: "\f148"; -} -.fa-level-down:before { - content: "\f149"; -} -.fa-check-square:before { - content: "\f14a"; -} -.fa-pencil-square:before { - content: "\f14b"; -} -.fa-external-link-square:before { - content: "\f14c"; -} -.fa-share-square:before { - content: "\f14d"; -} -.fa-compass:before { - content: "\f14e"; -} -.fa-toggle-down:before, -.fa-caret-square-o-down:before { - content: "\f150"; -} -.fa-toggle-up:before, -.fa-caret-square-o-up:before { - content: "\f151"; -} -.fa-toggle-right:before, -.fa-caret-square-o-right:before { - content: "\f152"; -} -.fa-euro:before, -.fa-eur:before { - content: "\f153"; -} -.fa-gbp:before { - content: "\f154"; -} -.fa-dollar:before, -.fa-usd:before { - content: "\f155"; -} -.fa-rupee:before, -.fa-inr:before { - content: "\f156"; -} -.fa-cny:before, -.fa-rmb:before, -.fa-yen:before, -.fa-jpy:before { - content: "\f157"; -} -.fa-ruble:before, -.fa-rouble:before, -.fa-rub:before { - content: "\f158"; -} -.fa-won:before, -.fa-krw:before { - content: "\f159"; -} -.fa-bitcoin:before, -.fa-btc:before { - content: "\f15a"; -} -.fa-file:before { - content: "\f15b"; -} -.fa-file-text:before { - content: "\f15c"; -} -.fa-sort-alpha-asc:before { - content: "\f15d"; -} -.fa-sort-alpha-desc:before { - content: "\f15e"; -} -.fa-sort-amount-asc:before { - content: "\f160"; -} -.fa-sort-amount-desc:before { - content: "\f161"; -} -.fa-sort-numeric-asc:before { - content: "\f162"; -} -.fa-sort-numeric-desc:before { - content: "\f163"; -} -.fa-thumbs-up:before { - content: "\f164"; -} -.fa-thumbs-down:before { - content: "\f165"; -} -.fa-youtube-square:before { - content: "\f166"; -} -.fa-youtube:before { - content: "\f167"; -} -.fa-xing:before { - content: "\f168"; -} -.fa-xing-square:before { - content: "\f169"; -} -.fa-youtube-play:before { - content: "\f16a"; -} -.fa-dropbox:before { - content: "\f16b"; -} -.fa-stack-overflow:before { - content: "\f16c"; -} -.fa-instagram:before { - content: "\f16d"; -} -.fa-flickr:before { - content: "\f16e"; -} -.fa-adn:before { - content: "\f170"; -} -.fa-bitbucket:before { - content: "\f171"; -} -.fa-bitbucket-square:before { - content: "\f172"; -} -.fa-tumblr:before { - content: "\f173"; -} -.fa-tumblr-square:before { - content: "\f174"; -} -.fa-long-arrow-down:before { - content: "\f175"; -} -.fa-long-arrow-up:before { - content: "\f176"; -} -.fa-long-arrow-left:before { - content: "\f177"; -} -.fa-long-arrow-right:before { - content: "\f178"; -} -.fa-apple:before { - content: "\f179"; -} -.fa-windows:before { - content: "\f17a"; -} -.fa-android:before { - content: "\f17b"; -} -.fa-linux:before { - content: "\f17c"; -} -.fa-dribbble:before { - content: "\f17d"; -} -.fa-skype:before { - content: "\f17e"; -} -.fa-foursquare:before { - content: "\f180"; -} -.fa-trello:before { - content: "\f181"; -} -.fa-female:before { - content: "\f182"; -} -.fa-male:before { - content: "\f183"; -} -.fa-gittip:before, -.fa-gratipay:before { - content: "\f184"; -} -.fa-sun-o:before { - content: "\f185"; -} -.fa-moon-o:before { - content: "\f186"; -} -.fa-archive:before { - content: "\f187"; -} -.fa-bug:before { - content: "\f188"; -} -.fa-vk:before { - content: "\f189"; -} -.fa-weibo:before { - content: "\f18a"; -} -.fa-renren:before { - content: "\f18b"; -} -.fa-pagelines:before { - content: "\f18c"; -} -.fa-stack-exchange:before { - content: "\f18d"; -} -.fa-arrow-circle-o-right:before { - content: "\f18e"; -} -.fa-arrow-circle-o-left:before { - content: "\f190"; -} -.fa-toggle-left:before, -.fa-caret-square-o-left:before { - content: "\f191"; -} -.fa-dot-circle-o:before { - content: "\f192"; -} -.fa-wheelchair:before { - content: "\f193"; -} -.fa-vimeo-square:before { - content: "\f194"; -} -.fa-turkish-lira:before, -.fa-try:before { - content: "\f195"; -} -.fa-plus-square-o:before { - content: "\f196"; -} -.fa-space-shuttle:before { - content: "\f197"; -} -.fa-slack:before { - content: "\f198"; -} -.fa-envelope-square:before { - content: "\f199"; -} -.fa-wordpress:before { - content: "\f19a"; -} -.fa-openid:before { - content: "\f19b"; -} -.fa-institution:before, -.fa-bank:before, -.fa-university:before { - content: "\f19c"; -} -.fa-mortar-board:before, -.fa-graduation-cap:before { - content: "\f19d"; -} -.fa-yahoo:before { - content: "\f19e"; -} -.fa-google:before { - content: "\f1a0"; -} -.fa-reddit:before { - content: "\f1a1"; -} -.fa-reddit-square:before { - content: "\f1a2"; -} -.fa-stumbleupon-circle:before { - content: "\f1a3"; -} -.fa-stumbleupon:before { - content: "\f1a4"; -} -.fa-delicious:before { - content: "\f1a5"; -} -.fa-digg:before { - content: "\f1a6"; -} -.fa-pied-piper:before { - content: "\f1a7"; -} -.fa-pied-piper-alt:before { - content: "\f1a8"; -} -.fa-drupal:before { - content: "\f1a9"; -} -.fa-joomla:before { - content: "\f1aa"; -} -.fa-language:before { - content: "\f1ab"; -} -.fa-fax:before { - content: "\f1ac"; -} -.fa-building:before { - content: "\f1ad"; -} -.fa-child:before { - content: "\f1ae"; -} -.fa-paw:before { - content: "\f1b0"; -} -.fa-spoon:before { - content: "\f1b1"; -} -.fa-cube:before { - content: "\f1b2"; -} -.fa-cubes:before { - content: "\f1b3"; -} -.fa-behance:before { - content: "\f1b4"; -} -.fa-behance-square:before { - content: "\f1b5"; -} -.fa-steam:before { - content: "\f1b6"; -} -.fa-steam-square:before { - content: "\f1b7"; -} -.fa-recycle:before { - content: "\f1b8"; -} -.fa-automobile:before, -.fa-car:before { - content: "\f1b9"; -} -.fa-cab:before, -.fa-taxi:before { - content: "\f1ba"; -} -.fa-tree:before { - content: "\f1bb"; -} -.fa-spotify:before { - content: "\f1bc"; -} -.fa-deviantart:before { - content: "\f1bd"; -} -.fa-soundcloud:before { - content: "\f1be"; -} -.fa-database:before { - content: "\f1c0"; -} -.fa-file-pdf-o:before { - content: "\f1c1"; -} -.fa-file-word-o:before { - content: "\f1c2"; -} -.fa-file-excel-o:before { - content: "\f1c3"; -} -.fa-file-powerpoint-o:before { - content: "\f1c4"; -} -.fa-file-photo-o:before, -.fa-file-picture-o:before, -.fa-file-image-o:before { - content: "\f1c5"; -} -.fa-file-zip-o:before, -.fa-file-archive-o:before { - content: "\f1c6"; -} -.fa-file-sound-o:before, -.fa-file-audio-o:before { - content: "\f1c7"; -} -.fa-file-movie-o:before, -.fa-file-video-o:before { - content: "\f1c8"; -} -.fa-file-code-o:before { - content: "\f1c9"; -} -.fa-vine:before { - content: "\f1ca"; -} -.fa-codepen:before { - content: "\f1cb"; -} -.fa-jsfiddle:before { - content: "\f1cc"; -} -.fa-life-bouy:before, -.fa-life-buoy:before, -.fa-life-saver:before, -.fa-support:before, -.fa-life-ring:before { - content: "\f1cd"; -} -.fa-circle-o-notch:before { - content: "\f1ce"; -} -.fa-ra:before, -.fa-rebel:before { - content: "\f1d0"; -} -.fa-ge:before, -.fa-empire:before { - content: "\f1d1"; -} -.fa-git-square:before { - content: "\f1d2"; -} -.fa-git:before { - content: "\f1d3"; -} -.fa-hacker-news:before { - content: "\f1d4"; -} -.fa-tencent-weibo:before { - content: "\f1d5"; -} -.fa-qq:before { - content: "\f1d6"; -} -.fa-wechat:before, -.fa-weixin:before { - content: "\f1d7"; -} -.fa-send:before, -.fa-paper-plane:before { - content: "\f1d8"; -} -.fa-send-o:before, -.fa-paper-plane-o:before { - content: "\f1d9"; -} -.fa-history:before { - content: "\f1da"; -} -.fa-genderless:before, -.fa-circle-thin:before { - content: "\f1db"; -} -.fa-header:before { - content: "\f1dc"; -} -.fa-paragraph:before { - content: "\f1dd"; -} -.fa-sliders:before { - content: "\f1de"; -} -.fa-share-alt:before { - content: "\f1e0"; -} -.fa-share-alt-square:before { - content: "\f1e1"; -} -.fa-bomb:before { - content: "\f1e2"; -} -.fa-soccer-ball-o:before, -.fa-futbol-o:before { - content: "\f1e3"; -} -.fa-tty:before { - content: "\f1e4"; -} -.fa-binoculars:before { - content: "\f1e5"; -} -.fa-plug:before { - content: "\f1e6"; -} -.fa-slideshare:before { - content: "\f1e7"; -} -.fa-twitch:before { - content: "\f1e8"; -} -.fa-yelp:before { - content: "\f1e9"; -} -.fa-newspaper-o:before { - content: "\f1ea"; -} -.fa-wifi:before { - content: "\f1eb"; -} -.fa-calculator:before { - content: "\f1ec"; -} -.fa-paypal:before { - content: "\f1ed"; -} -.fa-google-wallet:before { - content: "\f1ee"; -} -.fa-cc-visa:before { - content: "\f1f0"; -} -.fa-cc-mastercard:before { - content: "\f1f1"; -} -.fa-cc-discover:before { - content: "\f1f2"; -} -.fa-cc-amex:before { - content: "\f1f3"; -} -.fa-cc-paypal:before { - content: "\f1f4"; -} -.fa-cc-stripe:before { - content: "\f1f5"; -} -.fa-bell-slash:before { - content: "\f1f6"; -} -.fa-bell-slash-o:before { - content: "\f1f7"; -} -.fa-trash:before { - content: "\f1f8"; -} -.fa-copyright:before { - content: "\f1f9"; -} -.fa-at:before { - content: "\f1fa"; -} -.fa-eyedropper:before { - content: "\f1fb"; -} -.fa-paint-brush:before { - content: "\f1fc"; -} -.fa-birthday-cake:before { - content: "\f1fd"; -} -.fa-area-chart:before { - content: "\f1fe"; -} -.fa-pie-chart:before { - content: "\f200"; -} -.fa-line-chart:before { - content: "\f201"; -} -.fa-lastfm:before { - content: "\f202"; -} -.fa-lastfm-square:before { - content: "\f203"; -} -.fa-toggle-off:before { - content: "\f204"; -} -.fa-toggle-on:before { - content: "\f205"; -} -.fa-bicycle:before { - content: "\f206"; -} -.fa-bus:before { - content: "\f207"; -} -.fa-ioxhost:before { - content: "\f208"; -} -.fa-angellist:before { - content: "\f209"; -} -.fa-cc:before { - content: "\f20a"; -} -.fa-shekel:before, -.fa-sheqel:before, -.fa-ils:before { - content: "\f20b"; -} -.fa-meanpath:before { - content: "\f20c"; -} -.fa-buysellads:before { - content: "\f20d"; -} -.fa-connectdevelop:before { - content: "\f20e"; -} -.fa-dashcube:before { - content: "\f210"; -} -.fa-forumbee:before { - content: "\f211"; -} -.fa-leanpub:before { - content: "\f212"; -} -.fa-sellsy:before { - content: "\f213"; -} -.fa-shirtsinbulk:before { - content: "\f214"; -} -.fa-simplybuilt:before { - content: "\f215"; -} -.fa-skyatlas:before { - content: "\f216"; -} -.fa-cart-plus:before { - content: "\f217"; -} -.fa-cart-arrow-down:before { - content: "\f218"; -} -.fa-diamond:before { - content: "\f219"; -} -.fa-ship:before { - content: "\f21a"; -} -.fa-user-secret:before { - content: "\f21b"; -} -.fa-motorcycle:before { - content: "\f21c"; -} -.fa-street-view:before { - content: "\f21d"; -} -.fa-heartbeat:before { - content: "\f21e"; -} -.fa-venus:before { - content: "\f221"; -} -.fa-mars:before { - content: "\f222"; -} -.fa-mercury:before { - content: "\f223"; -} -.fa-transgender:before { - content: "\f224"; -} -.fa-transgender-alt:before { - content: "\f225"; -} -.fa-venus-double:before { - content: "\f226"; -} -.fa-mars-double:before { - content: "\f227"; -} -.fa-venus-mars:before { - content: "\f228"; -} -.fa-mars-stroke:before { - content: "\f229"; -} -.fa-mars-stroke-v:before { - content: "\f22a"; -} -.fa-mars-stroke-h:before { - content: "\f22b"; -} -.fa-neuter:before { - content: "\f22c"; -} -.fa-facebook-official:before { - content: "\f230"; -} -.fa-pinterest-p:before { - content: "\f231"; -} -.fa-whatsapp:before { - content: "\f232"; -} -.fa-server:before { - content: "\f233"; -} -.fa-user-plus:before { - content: "\f234"; -} -.fa-user-times:before { - content: "\f235"; -} -.fa-hotel:before, -.fa-bed:before { - content: "\f236"; -} -.fa-viacoin:before { - content: "\f237"; -} -.fa-train:before { - content: "\f238"; -} -.fa-subway:before { - content: "\f239"; -} -.fa-medium:before { - content: "\f23a"; -} diff --git a/src/main/resources/static/editor-md/scss/github-markdown.scss b/src/main/resources/static/editor-md/scss/github-markdown.scss deleted file mode 100644 index 0d42686..0000000 --- a/src/main/resources/static/editor-md/scss/github-markdown.scss +++ /dev/null @@ -1,665 +0,0 @@ -@charset "UTF-8"; - -/*! github-markdown-css | The MIT License (MIT) | Copyright (c) Sindre Sorhus (sindresorhus.com) | https://github.com/sindresorhus/github-markdown-css */ -@font-face { - font-family: octicons-anchor; - src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAYcAA0AAAAACjQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABMAAAABwAAAAca8vGTk9TLzIAAAFMAAAARAAAAFZG1VHVY21hcAAAAZAAAAA+AAABQgAP9AdjdnQgAAAB0AAAAAQAAAAEACICiGdhc3AAAAHUAAAACAAAAAj//wADZ2x5ZgAAAdwAAADRAAABEKyikaNoZWFkAAACsAAAAC0AAAA2AtXoA2hoZWEAAALgAAAAHAAAACQHngNFaG10eAAAAvwAAAAQAAAAEAwAACJsb2NhAAADDAAAAAoAAAAKALIAVG1heHAAAAMYAAAAHwAAACABEAB2bmFtZQAAAzgAAALBAAAFu3I9x/Nwb3N0AAAF/AAAAB0AAAAvaoFvbwAAAAEAAAAAzBdyYwAAAADP2IQvAAAAAM/bz7t4nGNgZGFgnMDAysDB1Ml0hoGBoR9CM75mMGLkYGBgYmBlZsAKAtJcUxgcPsR8iGF2+O/AEMPsznAYKMwIkgMA5REMOXicY2BgYGaAYBkGRgYQsAHyGMF8FgYFIM0ChED+h5j//yEk/3KoSgZGNgYYk4GRCUgwMaACRoZhDwCs7QgGAAAAIgKIAAAAAf//AAJ4nHWMMQrCQBBF/0zWrCCIKUQsTDCL2EXMohYGSSmorScInsRGL2DOYJe0Ntp7BK+gJ1BxF1stZvjz/v8DRghQzEc4kIgKwiAppcA9LtzKLSkdNhKFY3HF4lK69ExKslx7Xa+vPRVS43G98vG1DnkDMIBUgFN0MDXflU8tbaZOUkXUH0+U27RoRpOIyCKjbMCVejwypzJJG4jIwb43rfl6wbwanocrJm9XFYfskuVC5K/TPyczNU7b84CXcbxks1Un6H6tLH9vf2LRnn8Ax7A5WQAAAHicY2BkYGAA4teL1+yI57f5ysDNwgAC529f0kOmWRiYVgEpDgYmEA8AUzEKsQAAAHicY2BkYGB2+O/AEMPCAAJAkpEBFbAAADgKAe0EAAAiAAAAAAQAAAAEAAAAAAAAKgAqACoAiAAAeJxjYGRgYGBhsGFgYgABEMkFhAwM/xn0QAIAD6YBhwB4nI1Ty07cMBS9QwKlQapQW3VXySvEqDCZGbGaHULiIQ1FKgjWMxknMfLEke2A+IJu+wntrt/QbVf9gG75jK577Lg8K1qQPCfnnnt8fX1NRC/pmjrk/zprC+8D7tBy9DHgBXoWfQ44Av8t4Bj4Z8CLtBL9CniJluPXASf0Lm4CXqFX8Q84dOLnMB17N4c7tBo1AS/Qi+hTwBH4rwHHwN8DXqQ30XXAS7QaLwSc0Gn8NuAVWou/gFmnjLrEaEh9GmDdDGgL3B4JsrRPDU2hTOiMSuJUIdKQQayiAth69r6akSSFqIJuA19TrzCIaY8sIoxyrNIrL//pw7A2iMygkX5vDj+G+kuoLdX4GlGK/8Lnlz6/h9MpmoO9rafrz7ILXEHHaAx95s9lsI7AHNMBWEZHULnfAXwG9/ZqdzLI08iuwRloXE8kfhXYAvE23+23DU3t626rbs8/8adv+9DWknsHp3E17oCf+Z48rvEQNZ78paYM38qfk3v/u3l3u3GXN2Dmvmvpf1Srwk3pB/VSsp512bA/GG5i2WJ7wu430yQ5K3nFGiOqgtmSB5pJVSizwaacmUZzZhXLlZTq8qGGFY2YcSkqbth6aW1tRmlaCFs2016m5qn36SbJrqosG4uMV4aP2PHBmB3tjtmgN2izkGQyLWprekbIntJFing32a5rKWCN/SdSoga45EJykyQ7asZvHQ8PTm6cslIpwyeyjbVltNikc2HTR7YKh9LBl9DADC0U/jLcBZDKrMhUBfQBvXRzLtFtjU9eNHKin0x5InTqb8lNpfKv1s1xHzTXRqgKzek/mb7nB8RZTCDhGEX3kK/8Q75AmUM/eLkfA+0Hi908Kx4eNsMgudg5GLdRD7a84npi+YxNr5i5KIbW5izXas7cHXIMAau1OueZhfj+cOcP3P8MNIWLyYOBuxL6DRylJ4cAAAB4nGNgYoAALjDJyIAOWMCiTIxMLDmZedkABtIBygAAAA==) format('woff'); -} - -.markdown-body { - -ms-text-size-adjust: 100%; - -webkit-text-size-adjust: 100%; - color: #333; - overflow: hidden; - //font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif; - font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", "Monaco", monospace, Tahoma, STXihei, "华文细黑", STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, "宋体", Heiti, "黑体", sans-serif; - font-size: 16px; - line-height: 1.6; - word-wrap: break-word; -} - -.markdown-body a { - background: transparent; -} - -.markdown-body a:active, -.markdown-body a:hover { - outline: 0; -} - -.markdown-body strong { - font-weight: bold; -} - -.markdown-body h1 { - font-size: 2em; - margin: 0.67em 0; -} - -.markdown-body img { - border: 0; -} - -.markdown-body hr { - -moz-box-sizing: content-box; - box-sizing: content-box; - height: 0; -} - -.markdown-body pre { - overflow: auto; -} - -.markdown-body code, -.markdown-body kbd, -.markdown-body pre { - font-family: "Meiryo UI", "YaHei Consolas Hybrid", Consolas, "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; - font-size: 1em; -} - -.markdown-body input { - color: inherit; - font: inherit; - margin: 0; -} - -.markdown-body html input[disabled] { - cursor: default; -} - -.markdown-body input { - line-height: normal; -} - -.markdown-body input[type="checkbox"] { - -moz-box-sizing: border-box; - box-sizing: border-box; - padding: 0; -} - -.markdown-body table { - border-collapse: collapse; - border-spacing: 0; -} - -.markdown-body td, -.markdown-body th { - padding: 0; -} - -.markdown-body * { - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.markdown-body input { - font: 13px/1.4 Helvetica, arial, freesans, clean, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol"; -} - -.markdown-body a { - color: #4183c4; - text-decoration: none; -} - -.markdown-body a:hover, -.markdown-body a:active { - text-decoration: underline; -} - -.markdown-body hr { - height: 0; - margin: 15px 0; - overflow: hidden; - background: transparent; - border: 0; - border-bottom: 1px solid #ddd; -} - -.markdown-body hr:before { - display: table; - content: ""; -} - -.markdown-body hr:after { - display: table; - clear: both; - content: ""; -} - -.markdown-body h1, -.markdown-body h2, -.markdown-body h3, -.markdown-body h4, -.markdown-body h5, -.markdown-body h6 { - margin-top: 15px; - margin-bottom: 15px; - line-height: 1.1; -} - -.markdown-body h1 { - font-size: 30px; -} - -.markdown-body h2 { - font-size: 21px; -} - -.markdown-body h3 { - font-size: 16px; -} - -.markdown-body h4 { - font-size: 14px; -} - -.markdown-body h5 { - font-size: 12px; -} - -.markdown-body h6 { - font-size: 11px; -} - -.markdown-body blockquote { - margin: 0; -} - -.markdown-body ul, -.markdown-body ol { - padding: 0; - margin-top: 0; - margin-bottom: 0; -} - -.markdown-body ol ol, -.markdown-body ul ol { - list-style-type: lower-roman; -} - -.markdown-body ul ul ol, -.markdown-body ul ol ol, -.markdown-body ol ul ol, -.markdown-body ol ol ol { - list-style-type: lower-alpha; -} - -.markdown-body dd { - margin-left: 0; -} - -.markdown-body code { - font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; - font-size: 12px; -} - -.markdown-body pre { - margin-top: 0; - margin-bottom: 0; - font: 12px Consolas, "Liberation Mono", Menlo, Courier, monospace; -} - -.markdown-body .octicon { - font: normal normal 16px octicons-anchor; - line-height: 1; - display: inline-block; - text-decoration: none; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.markdown-body .octicon-link:before { - content: '\f05c'; -} - -.markdown-body>*:first-child { - margin-top: 0 !important; -} - -.markdown-body>*:last-child { - margin-bottom: 0 !important; -} - -.markdown-body .anchor { - position: absolute; - top: 0; - left: 0; - display: block; - padding-right: 6px; - padding-left: 30px; - margin-left: -30px; -} - -.markdown-body .anchor:focus { - outline: none; -} - -.markdown-body h1, -.markdown-body h2, -.markdown-body h3, -.markdown-body h4, -.markdown-body h5, -.markdown-body h6 { - position: relative; - margin-top: 1em; - margin-bottom: 16px; - font-weight: bold; - line-height: 1.4; -} - -.markdown-body h1 .octicon-link, -.markdown-body h2 .octicon-link, -.markdown-body h3 .octicon-link, -.markdown-body h4 .octicon-link, -.markdown-body h5 .octicon-link, -.markdown-body h6 .octicon-link { - display: none; - color: #000; - vertical-align: middle; -} - -.markdown-body h1:hover .anchor, -.markdown-body h2:hover .anchor, -.markdown-body h3:hover .anchor, -.markdown-body h4:hover .anchor, -.markdown-body h5:hover .anchor, -.markdown-body h6:hover .anchor { - padding-left: 8px; - margin-left: -30px; - text-decoration: none; -} - -.markdown-body h1:hover .anchor .octicon-link, -.markdown-body h2:hover .anchor .octicon-link, -.markdown-body h3:hover .anchor .octicon-link, -.markdown-body h4:hover .anchor .octicon-link, -.markdown-body h5:hover .anchor .octicon-link, -.markdown-body h6:hover .anchor .octicon-link { - display: inline-block; -} - -.markdown-body h1 { - padding-bottom: 0.3em; - font-size: 2.25em; - line-height: 1.2; - border-bottom: 1px solid #eee; -} - -.markdown-body h1 .anchor { - line-height: 1; -} - -.markdown-body h2 { - padding-bottom: 0.3em; - font-size: 1.75em; - line-height: 1.225; - border-bottom: 1px solid #eee; -} - -.markdown-body h2 .anchor { - line-height: 1; -} - -.markdown-body h3 { - font-size: 1.5em; - line-height: 1.43; -} - -.markdown-body h3 .anchor { - line-height: 1.2; -} - -.markdown-body h4 { - font-size: 1.25em; -} - -.markdown-body h4 .anchor { - line-height: 1.2; -} - -.markdown-body h5 { - font-size: 1em; -} - -.markdown-body h5 .anchor { - line-height: 1.1; -} - -.markdown-body h6 { - font-size: 1em; - color: #777; -} - -.markdown-body h6 .anchor { - line-height: 1.1; -} - -.markdown-body p, -.markdown-body blockquote, -.markdown-body ul, -.markdown-body ol, -.markdown-body dl, -.markdown-body table, -.markdown-body pre { - margin-top: 0; - margin-bottom: 16px; -} -/* -.markdown-body hr { - height: 4px; - padding: 0; - margin: 16px 0; - background-color: #e7e7e7; - border: 0 none; -}*/ - -.markdown-body ul, -.markdown-body ol { - padding-left: 2em; -} - -.markdown-body ul ul, -.markdown-body ul ol, -.markdown-body ol ol, -.markdown-body ol ul { - margin-top: 0; - margin-bottom: 0; -} - -.markdown-body li>p { - margin-top: 16px; -} - -.markdown-body dl { - padding: 0; -} - -.markdown-body dl dt { - padding: 0; - margin-top: 16px; - font-size: 1em; - font-style: italic; - font-weight: bold; -} - -.markdown-body dl dd { - padding: 0 16px; - margin-bottom: 16px; -} - -.markdown-body blockquote { - padding: 0 15px; - color: #777; - border-left: 4px solid #ddd; -} - -.markdown-body blockquote>:first-child { - margin-top: 0; -} - -.markdown-body blockquote>:last-child { - margin-bottom: 0; -} - -.markdown-body table { - display: block; - width: 100%; - overflow: auto; - word-break: normal; - word-break: keep-all; -} - -.markdown-body table th { - font-weight: bold; -} - -.markdown-body table th, -.markdown-body table td { - padding: 6px 13px; - border: 1px solid #ddd; -} - -.markdown-body table tr { - background-color: #fff; - border-top: 1px solid #ccc; -} - -.markdown-body table tr:nth-child(2n) { - background-color: #f8f8f8; -} - -.markdown-body img { - max-width: 100%; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.markdown-body code { - padding: 0; - padding-top: 0.2em; - padding-bottom: 0.2em; - margin: 0; - font-size: 85%; - background-color: rgba(0,0,0,0.04); - border-radius: 3px; -} - -.markdown-body code:before, -.markdown-body code:after { - letter-spacing: -0.2em; - content: "\00a0"; -} - -.markdown-body pre>code { - padding: 0; - margin: 0; - font-size: 100%; - word-break: normal; - white-space: pre; - background: transparent; - border: 0; -} - -.markdown-body .highlight { - margin-bottom: 16px; -} - -.markdown-body .highlight pre, -.markdown-body pre { - padding: 16px; - overflow: auto; - font-size: 85%; - line-height: 1.45; - background-color: #f7f7f7; - border-radius: 3px; -} - -.markdown-body .highlight pre { - margin-bottom: 0; - word-break: normal; -} - -.markdown-body pre { - word-wrap: normal; -} - -.markdown-body pre code { - display: inline; - max-width: initial; - padding: 0; - margin: 0; - overflow: initial; - line-height: inherit; - word-wrap: normal; - background-color: transparent; - border: 0; -} - -.markdown-body pre code:before, -.markdown-body pre code:after { - content: normal; -} - -.markdown-body kbd { - display: inline-block; - padding: 3px 5px; - font-size: 11px; - line-height: 10px; - color: #555; - vertical-align: middle; - background-color: #fcfcfc; - border: solid 1px #ccc; - border-bottom-color: #bbb; - border-radius: 3px; - box-shadow: inset 0 -1px 0 #bbb; -} - -.markdown-body .pl-c { - color: #969896; -} - -.markdown-body .pl-c1, -.markdown-body .pl-mdh, -.markdown-body .pl-mm, -.markdown-body .pl-mp, -.markdown-body .pl-mr, -.markdown-body .pl-s1 .pl-v, -.markdown-body .pl-s3, -.markdown-body .pl-sc, -.markdown-body .pl-sv { - color: #0086b3; -} - -.markdown-body .pl-e, -.markdown-body .pl-en { - color: #795da3; -} - -.markdown-body .pl-s1 .pl-s2, -.markdown-body .pl-smi, -.markdown-body .pl-smp, -.markdown-body .pl-stj, -.markdown-body .pl-vo, -.markdown-body .pl-vpf { - color: #333; -} - -.markdown-body .pl-ent { - color: #63a35c; -} - -.markdown-body .pl-k, -.markdown-body .pl-s, -.markdown-body .pl-st { - color: #a71d5d; -} - -.markdown-body .pl-pds, -.markdown-body .pl-s1, -.markdown-body .pl-s1 .pl-pse .pl-s2, -.markdown-body .pl-sr, -.markdown-body .pl-sr .pl-cce, -.markdown-body .pl-sr .pl-sra, -.markdown-body .pl-sr .pl-sre, -.markdown-body .pl-src { - color: #df5000; -} - -.markdown-body .pl-mo, -.markdown-body .pl-v { - color: #1d3e81; -} - -.markdown-body .pl-id { - color: #b52a1d; -} - -.markdown-body .pl-ii { - background-color: #b52a1d; - color: #f8f8f8; -} - -.markdown-body .pl-sr .pl-cce { - color: #63a35c; - font-weight: bold; -} - -.markdown-body .pl-ml { - color: #693a17; -} - -.markdown-body .pl-mh, -.markdown-body .pl-mh .pl-en, -.markdown-body .pl-ms { - color: #1d3e81; - font-weight: bold; -} - -.markdown-body .pl-mq { - color: #008080; -} - -.markdown-body .pl-mi { - color: #333; - font-style: italic; -} - -.markdown-body .pl-mb { - color: #333; - font-weight: bold; -} - -.markdown-body .pl-md, -.markdown-body .pl-mdhf { - background-color: #ffecec; - color: #bd2c00; -} - -.markdown-body .pl-mdht, -.markdown-body .pl-mi1 { - background-color: #eaffea; - color: #55a532; -} - -.markdown-body .pl-mdr { - color: #795da3; - font-weight: bold; -} - -.markdown-body kbd { - display: inline-block; - padding: 3px 5px; - font: 11px Consolas, "Liberation Mono", Menlo, Courier, monospace; - line-height: 10px; - color: #555; - vertical-align: middle; - background-color: #fcfcfc; - border: solid 1px #ccc; - border-bottom-color: #bbb; - border-radius: 3px; - box-shadow: inset 0 -1px 0 #bbb; -} - -.markdown-body .task-list-item { - list-style-type: none; -} - -.markdown-body .task-list-item+.task-list-item { - margin-top: 3px; -} - -.markdown-body .task-list-item input { - float: left; - margin: 0.3em 0 0.25em -1.6em; - vertical-align: middle; -} - -.markdown-body :checked+.radio-label { - z-index: 1; - position: relative; - border-color: #4183c4; -} diff --git a/src/main/resources/static/editor-md/scss/lib/prefixes.scss b/src/main/resources/static/editor-md/scss/lib/prefixes.scss deleted file mode 100644 index 70a785d..0000000 --- a/src/main/resources/static/editor-md/scss/lib/prefixes.scss +++ /dev/null @@ -1,784 +0,0 @@ -@charset "UTF-8"; - -/*! prefixes.scss v0.1.0 | Author: Pandao | https://github.com/pandao/prefixes.scss | MIT license | Copyright (c) 2015 */ - -// appearance - -@mixin appearance($value) { - -webkit-appearance: $value; - -moz-appearance: $value; - -ms-appearance: $value; - appearance: $value; -} - -// clearfix - -@mixin clearfix() { - &:before, &:after { - content: " "; - display: table; - } - - &:after { - clear: both; - } -} - -// viewport - -@mixin viewport-device-width() { - width: device-width; - user-zoom: fixed; -} - -@mixin viewport() { - @-webkit-viewport { - @include viewport-device-width(); - } - @-moz-viewport { - @include viewport-device-width(); - } - - @-ms-viewport { - @include viewport-device-width(); - } - - @-o-viewport { - @include viewport-device-width(); - } - - @viewport { - @include viewport-device-width(); - } -} - -// Transform - -@mixin transform($transform) { - -webkit-transform: $transform; /* Safari, Chrome */ - -moz-transform: $transform; /* Firefox 3.5~16.0 */ - -ms-transform: $transform; /* IE9~10 */ - -o-transform: $transform; /* Opera 10.5~12.10 */ - transform: $transform; -} - -@mixin transform-origin($origin) { - -webkit-transform-origin: $origin; - -moz-transform-origin: $origin; /* Firefox 3.5~16.0 */ - -ms-transform-origin: $origin; /* IE9~10 */ - -o-transform-origin: $origin; /* Opera 10.5~12.10 */ - transform-origin: $origin; -} - -@mixin transform-origin-x($origin) { - -webkit-transform-origin-x: $origin; /* Blink, Webkit */ - transform-origin-x: $origin; /* IE11+ */ -} - -@mixin transform-origin-y($origin) { - -webkit-transform-origin-y: $origin; /* Blink, Webkit */ - transform-origin-y: $origin; /* IE11+ */ -} - -@mixin transform-origin-z($origin) { - -webkit-transform-origin-z: $origin; /* Blink, Webkit */ - transform-origin-z: $origin; /* IE11+ */ -} - -@mixin transform-style($style) { - -webkit-transform-style: $style; - -moz-transform-style: $style; /* Firefox 10~16.0 */ - -ms-transform-style: $style; /* IE9~10 */ - transform-style: $style; /* Firefox, Blink, IE11+ */ -} - -// perspective - -@mixin perspective($value) { - -webkit-perspective: $value; /* Safari, Chrome */ - perspective: $value; /* None yet / Non-standard */ -} - -@mixin perspective-origin($value) { - -webkit-perspective-origin: $value; /* Safari, Chrome 12+ */ - -moz-perspective-origin: $value; /* Firefox 10~16 */ - perspective-origin: $value; /* Opera 15+, IE10+ */ -} - -@mixin perspective-origin-x($value) { - -webkit-perspective-origin-x: $value; /* Safari, Chrome 12+ */ - perspective-origin-x: $value; /* IE10+ */ -} - -@mixin perspective-origin-y($value) { - -webkit-perspective-origin-y: $value; /* Safari, Chrome 12+ */ - perspective-origin-y: $value; /* IE10+ */ -} - -@mixin backface-visibility($value : hidden) { - -webkit-backface-visibility: $value; /* Chrome, Safari, Opera 15+ */ - -moz-backface-visibility: $value; /* Firefox */ - -ms-backface-visibility: $value; /* IE10 */ - backface-visibility: $value; -} - -// Transitions IE10+ - -@mixin transition($transition...) { - -webkit-transition: $transition; /* Safari, Chrome */ - -moz-transition: $transition; /* Firefox 4.0~16.0 */ - transition: $transition; /* IE >9, FF >15, Opera >12.0 */ -} - -@mixin transition-property($property) { - -webkit-transition-property: $property; - -moz-transition-property: $property; /* Firefox 4.0~16.0 */ - transition-property: $property; -} - -@mixin transition-duration($duration) { - -webkit-transition-duration: $duration; - -moz-transition-duration: $duration; /* Firefox 4.0~16.0 */ - transition-duration: $duration; -} - -@mixin transition-timing-function($easing) { - -webkit-transition-timing-function: $easing; - -moz-transition-timing-function: $easing; /* Firefox 4.0~16.0 */ - transition-timing-function: $easing; -} - -@mixin transition-delay($delay) { - -webkit-transition-delay: $delay; - -moz-transition-delay: $delay; /* Firefox 4.0~16.0 */ - transition-delay: $delay; -} - -// Flex align - -@mixin align-content($value) { - -webkit-align-content: $value; /* Chrome 21.0+, Safari Not supported. */ - align-content: $value; /* Firefox 28+, Opera 12.10, IE Not supported. */ -} - -@mixin align-items($value) { - -webkit-align-items: $value; /* Safari 7.0+, Chrome 21.0+ */ - align-items: $value; /* Firefox 20.0+, IE11+, Opera 12.10 */ -} - -@mixin align-self($value) { - -webkit-align-self: $value; /* Chrome 21~36, Safari Not supported. */ - align-self: $value; /* Firefox 28+, Opera 12.10, IE Not supported. */ -} - -// Animations IE10+ - -@mixin keyframes($name) { - @-webkit-keyframes #{$name} { - @content; - } - - @-moz-keyframes #{$name} { - @content; - } - - @keyframes #{$name} { - @content; - } -} - -@mixin animation($animation...) { - -webkit-animation: $animation; - -moz-animation: $animation; /* Firefox 5.0~16.0 */ - animation: $animation; /* IE10+ */ -} - -@mixin animation-name($name) { - -webkit-animation-name: $name; - -moz-animation-name: $name; /* Firefox 5.0~16.0 */ - animation-name: $name; -} - -@mixin animation-duration($time : 1s) { - -webkit-animation-duration: $time; - -moz-animation-duration: $time; /* Firefox 5.0~16.0 */ - animation-duration: $time; -} - -@mixin animation-timing-function($easing : ease) { - -webkit-animation-timing-function: $easing; - -moz-animation-timing-function: $easing; /* Firefox 5.0~16.0 */ - animation-timing-function: $easing; -} - -@mixin animation-delay($delay : 1s) { - -webkit-animation-delay: $delay; - -moz-animation-delay: $delay; /* Firefox 5.0~16.0 */ - animation-delay: $delay; -} - -@mixin animation-iteration-count($count : infinite) { - -webkit-animation-iteration-count: $count; - -moz-animation-iteration-count: $count; /* Firefox 5.0~16.0 */ - animation-iteration-count: $count; -} - -// normal or alternate -@mixin animation-direction($direction : normal) { - -webkit-animation-direction: $direction; - -moz-animation-direction: $direction; /* Firefox 5.0~16.0 */ - animation-direction: $direction; -} - -// paused or running - -@mixin animation-play-state($state) { - -webkit-animation-play-state: $state; - -moz-animation-play-state: $state; /* Firefox 5.0~16.0 */ - animation-play-state: $state; -} - -// animation-fill-mode - -@mixin animation-fill-mode($mode) { - -webkit-animation-fill-mode: $mode; - -moz-animation-fill-mode: $mode; - animation-fill-mode: $mode; -} - -// user-select - -@mixin user-select($type) { - -webkit-user-select: $type; - -moz-user-select: $type; - -ms-user-select: $type; - -o-user-select: $type; - user-select: $type; -} - -// border-radius - -@mixin border-radius($radius: 4px) { - -webkit-border-radius: $radius; - -moz-border-radius: $radius; - -ms-border-radius: $radius; - -o-border-radius: $radius; - border-radius: $radius; -} - -@mixin border-top-left-radius($radius: 4px) { - -webkit-border-top-left-radius: $radius; - -moz-border-top-left-radius: $radius; - -ms-border-top-left-radius: $radius; - -o-border-top-left-radius: $radius; - border-top-left-radius: $radius; -} - -@mixin border-top-right-radius($radius: 4px) { - -webkit-border-top-right-radius: $radius; - -moz-border-top-right-radius: $radius; - -ms-border-top-right-radius: $radius; - -o-border-top-right-radius: $radius; - border-top-right-radius: $radius; -} - -@mixin border-bottom-left-radius($radius: 4px) { - -webkit-border-bottom-left-radius: $radius; - -moz-border-bottom-left-radius: $radius; - -ms-border-bottom-left-radius: $radius; - -o-border-bottom-left-radius: $radius; - border-bottom-left-radius: $radius; -} - -@mixin border-bottom-right-radius($radius: 4px) { - -webkit-border-bottom-right-radius: $radius; - -moz-border-bottom-right-radius: $radius; - -ms-border-bottom-right-radius: $radius; - -o-border-bottom-right-radius: $radius; - border-bottom-right-radius: $radius; -} - -// border-image - -@mixin border-image($value) { - -webkit-border-image: $value; /* Safari 5, Chrome */ - -moz-border-image: $value; /* Firefox 3.5~15.0 */ - -o-border-image: $value; /* Opera */ - border-image: $value; /* Safari 6+, Chrome, New */ -} - -@mixin border-image-source($value) { - -webkit-border-image-source: $value; /* Safari 5, Chrome */ - border-image-source: $value; /* Safari 6+, Chrome, IE11+, Opera 15+ */ -} - -@mixin border-image-slice($value) { - -webkit-border-image-slice: $value; /* Safari 5, Chrome */ - border-image-slice: $value; /* Safari 6+, Chrome, IE11+, Opera 15+ */ -} - -@mixin border-image-width($value) { - -webkit-border-image-width: $value; /* Safari 5, Chrome */ - border-image-width: $value; /* Safari 6+, Chrome, IE11+, Opera 15+ */ -} - -@mixin border-image-outset($value) { - -webkit-border-image-outset: $value; /* Safari 5, Chrome */ - border-image-outset: $value; /* Safari 6+, Chrome, IE11+, Opera 15+ */ -} - -@mixin border-image-repeat($value) { - -webkit-border-image-repeat: $value; /* Safari 5, Chrome */ - border-image-repeat: $value; /* Safari 6+, Chrome, IE11+, Opera 15+ */ -} - -// box-shadow - -@mixin box-shadow($value) { - -webkit-box-shadow: $value; /* Webkit browsers */ - -moz-box-shadow: $value; /* Firefox */ - -ms-box-shadow: $value; /* IE9 */ - -o-box-shadow: $value; /* Opera(Old) */ - box-shadow: $value; /* IE9+, News */ -} - -//box-sizing - -@mixin box-sizing($value) { - -webkit-box-sizing: $value; - -moz-box-sizing: $value; - box-sizing: $value; -} - -// box-reflect - -@mixin box-reflect($value) { - -webkit-box-reflect: $value; /* Chrome, Safari, iOS, Blackberry */ - box-reflect: $value; /* None yet / Non-standard */ -} - -// background - -@mixin linear-gradient($start-color, $end-color, $position : top, $perStart : 0%, $perEnd : 100%) { - background: -webkit-linear-gradient($position, $start-color, $end-color); /* Webkit browsers */ - background: -moz-linear-gradient( $position, $start-color, $end-color); /* Firefox(old) */ - background: -o-linear-gradient( $position, $start-color, $end-color); /* Opera(old) */ - background: -ms-linear-gradient( $position, $start-color $perStart, $end-color $perEnd); /* IE10 */ - filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, start-colorstr=#{$start-color}, end-colorstr=#{$end-color}); /* IE9 */ - ms-filter: "progid:DXImageTransform.Microsoft.gradient (GradientType=0, start-colorstr=#{$start-color}, end-colorstr=#{$end-color})"; /* IE8 */ - background: linear-gradient( $position, $start-color $perStart, $end-color $perEnd); /* W3C */ -} - -@mixin background-clip($value) { - -webkit-background-clip: $value; - background-clip: $value; /* Firefox 4.0, IE9+, Opera 10.5+, Chrome, Safari 3.0+ */ -} - -@mixin background-origin($value) { - -webkit-background-origin: $value; - background-origin: $value; /* IE9+, Other */ -} - -@mixin background-size($value) { - -webkit-background-size: $value; /* Chrome, iOS, Safari */ - -moz-background-size: $value; /* Firefox 3.6~4.0 */ - -o-background-size: $value; /* Opera 9.5 */ - background-size: $value; /* IE9+, New */ -} - -// Column - -@mixin column-count($value) { - -webkit-column-count: $value; /* Chrome, Safari, Android, Blackberry */ - -moz-column-count: $value; /* Firefox 34+ */ - column-count: $value; /* IE 10+, Opera 11.1+, New */ -} - -@mixin column-gap($value) { - -webkit-column-gap: $value; /* Chrome, Safari, Android, Blackberry */ - -moz-column-gap: $value; /* Firefox 34+ */ - column-gap: $value; /* IE 10+, Opera 11.1+, New */ -} - -@mixin column-rule($value) { - -webkit-column-rule: $value; /* Chrome, Safari, Android, Blackberry */ - -moz-column-rule: $value; /* Firefox 34+ */ - column-rule: $value; /* IE 10+, Opera 11.1+, New */ -} - -@mixin column-rule-color($value) { - -webkit-column-rule-color: $value; /* Chrome, Safari, Android, Blackberry */ - -moz-column-rule-color: $value; /* Firefox 34+ */ - column-rule-color: $value; /* IE 10+, Opera 11.1+, New */ -} - -@mixin column-rule-style($value) { - -webkit-column-rule-style: $value; /* Chrome, Safari, Android, Blackberry */ - -moz-column-rule-style: $value; /* Firefox 34+ */ - column-rule-style: $value; /* IE 10+, Opera 11.1+, New */ -} - -@mixin column-rule-width($value) { - -webkit-column-rule-width: $value; /* Chrome, Safari, Android, Blackberry */ - -moz-column-rule-width: $value; /* Firefox 34+ */ - column-rule-width: $value; /* IE 10+, Opera 11.1+, New */ -} - -@mixin column-fill($value) { - -webkit-column-fill: $value; /* None yet */ - -moz-column-fill: $value; /* Firefox 13.0+ */ - column-fill: $value; /* None yet / Non-standard */ -} - -@mixin column-span($value) { - -webkit-column-span: $value; /* Safari, Chrome, iOS 7.0+, Android, Opera 26+ */ - -moz-column-span: $value; /* Firefox 34+ */ - column-span: $value; /* IE10+, Opera Mini */ -} - -@mixin column-width($value) { - -webkit-column-width: $value; /* Safari, Chrome, iOS 7.0+, Android, Opera 26+ */ - -moz-column-width: $value; /* Firefox */ - column-width: $value; /* IE10+, Opera */ -} - -// columns: column-width column-count; - -@mixin columns($value) { - -webkit-columns: $value; /* Safari, Chrome, iOS 7.0+, Android, Opera 26+ */ - -moz-columns: $value; /* Firefox */ - columns: $value; /* IE10+, Opera */ -} - -// clip-path - -@mixin clip-path($value) { - -webkit-clip-path: $value; /* Chrome, iOS, Safari */ - clip-path: $value; -} - -// display - -@mixin display-grid() { - display: -ms-grid; /* IE 10 */ - display: grid; /* None yet */ -} - -@mixin display-flex() { - display: -webkit-box; /* Old - iOS 6-, Safari 3.1~6, Blackberry 7 */ - display: -ms-flexbox; /* TWEENER - IE 10 */ - display: -webkit-flex; /* New - Safari 6.1+. iOS 7.1+, Blackberry 10 */ - display: flex; /* New, Spec - Firefox, Chrome, Opera */ -} - -@mixin inline-flex($value) { - -webkit-inline-flex: $value; /* Chrome 21.0+ */ - inline-flex: $value; /* Firefox 20+, Opera 12.5 */ -} - -@mixin flex($value) { - -webkit-box-flex: $value; /* Old - iOS 6-, Safari 3.1~6 */ - -webkit-flex: $value; /* Safari 6.1+. iOS 7.1+, Blackberry 10 */ - -ms-flex: $value; /* IE 10 */ - flex: $value; /* New, Spec - Firefox, Chrome, Opera */ -} - -@mixin flex-direction($value) { - -webkit-flex-direction: $value; /* Chrome 21.0+, But Safari & Android & iOS Not supported. */ - flex-direction: $value; /* Firefox 28+, IE11, Opera 12.10 */ -} - -@mixin flex-basis($value) { - -webkit-flex-basis: $value; /* Chrome 21.0+, But Safari & Android & iOS Not supported. */ - flex-basis: $value; /* Firefox 22+, IE11, Opera 12.10 */ -} - -@mixin flex-flow($value) { - -webkit-flex-flow: $value; /* Chrome 21.0+, But Safari & Android & iOS Not supported. */ - flex-flow: $value; /* Firefox 28+, IE11, Opera 12.10 */ -} - -@mixin flex-grow($value) { - -webkit-flex-grow: $value; /* Chrome 21.0+, But Safari & Android & iOS Not supported. */ - flex-grow: $value; /* Firefox 20+, Opera 12.10, IE Not supported. */ -} - -@mixin flex-shrink($value) { - -webkit-flex-shrink: $value; /* Chrome 21.0+, But Safari & Android & iOS Not supported. */ - flex-shrink: $value; /* Firefox 20+, Opera 12.10, IE Not supported. */ -} - -@mixin flex-wrap($value) { - -webkit-flex-wrap: $value; /* Safari 6.1+, Chrome 21.0+, Android 4.4+, iOS 7.0+ */ - flex-wrap: $value; /* Firefox 28+, IE11, Opera 12.10 */ -} - -@mixin order($value) { - -webkit-order: $value; /* Chrome 21+, Safari Not supported. */ - -ms-flex-order: $value; /* IE 10.0 */ - order: $value; /* Firefox 20+, Opera 12.10 */ -} - -// flow - -@mixin flow-into($value) { - -webkit-flow-into: $value; /* Safari 7.1+, iOS Safari 7.1+ */ - -ms-flow-into: $value; /* IE10+ */ - flow-into: $value; /* None yet */ -} - -@mixin flow-from($value) { - -webkit-flow-from: $value; /* Safari 7.1+, iOS Safari 7.1+ */ - -ms-flow-from: $value; /* IE10+ */ - flow-from: $value; /* None yet */ -} - -// filter - -@mixin filter($value) { - -webkit-filter: $value; /* Chrome 23+, Safari 6.0+, Blackberry 10.0+ */ - filter: $value; /* None yet */ -} - -// filter blur - -@mixin filter-blur($value : 10px, $ie-value : 10) { - filter: progid:DXImageTransform.Microsoft.Blur(PixelRadius=#{$ie-value}, MakeShadow=false); /* IE6~IE9 */ - -webkit-filter: blur($value); /* Chrome, Opera, iOS, Safari */ - -moz-filter: blur($value); /* Firefox(Old) */ - -ms-filter: blur($value); - filter: blur($value); -} - -@mixin font-kerning($value) { - -webkit-font-kerning: $value; - font-kerning: $value; -} - -// font-feature-settings - -@mixin font-feature-settings($value) { - -webkit-font-feature-settings: $value; /* Chrome 16-26, Blackberry 10 */ - -moz-font-feature-settings: $value; /* Firefox 4-21 */ - font-feature-settings: $value; /* IE 10, Safari 4.0-6.0 */ -} - -@mixin font-variant-ligatures($value) { - -webkit-font-variant-ligatures: $value; - font-variant-ligatures: $value; -} - -// hyphens - -@mixin hyphens($value : auto) { - // Chrome 29- and Android 4.0 Browser support "-webkit-hyphens: none", but not the "auto" property. - -webkit-hyphens: $value; /* Safari 5.1+, Chrome */ - -moz-hyphens: $value; /* Firefox 6.0+ */ - -ms-hyphens: $value; /* IE 10+ */ - hyphens: $value; /* None yet */ -} - -@mixin justify-content($value) { - -webkit-justify-content: $value; /* Chrome 21+, Safari Not supported. */ - justify-content: $value; /* Firefox 20+, Opera 12.10, IE Not supported. */ -} - -// line - -@mixin line-break($value) { - -webkit-line-break: $value; - line-break: $value; -} - -// margin - -@mixin margin-start($value) { - -webkit-margin-start: $value; /* Safari 3.0+, Chrome */ - -moz-margin-start: $value; /* Firefox 1.0+ */ - margin-start: $value; /* None yet / Non-standard */ -} - -@mixin margin-end($value) { - -webkit-margin-end: $value; /* Safari 3.0+, Chrome */ - -moz-margin-end: $value; /* Firefox 1.0+ */ - margin-end: $value; /* None yet / Non-standard */ -} - -// mask - -@mixin mask-image($value) { - -webkit-mask-image: $value; /* Chrome, iOS, Safari */ - mask-image: $value; /* None yet / Non-standard */ -} - -@mixin mask-size($value) { - -webkit-mask-size: $value; /* Chrome, iOS, Safari */ - mask-size: $value; /* None yet / Non-standard */ -} - -@mixin mask-clip($value) { - -webkit-mask-clip: $value; /* Chrome, iOS, Safari */ - mask-clip: $value; /* None yet / Non-standard */ -} - -@mixin mask-position($value) { - -webkit-mask-position: $value; /* Chrome, iOS, Safari */ - mask-position: $value; /* None yet / Non-standard */ -} - -@mixin mask-position-x($value) { - -webkit-mask-position-x: $value; /* Chrome, iOS, Safari */ - mask-position-x: $value; /* None yet / Non-standard */ -} - -@mixin mask-position-y($value) { - -webkit-mask-position-y: $value; /* Chrome, iOS, Safari */ - mask-position-y: $value; /* None yet / Non-standard */ -} - -@mixin mask-origin($value) { - -webkit-mask-origin: $value; /* Chrome, iOS, Safari */ - mask-origin: $value; /* None yet / Non-standard */ -} - -@mixin mask-repeat($value) { - -webkit-mask-repeat: $value; /* Chrome, iOS, Safari */ - mask-repeat: $value; /* None yet / Non-standard */ -} - -@mixin mask-attachment($value) { - -webkit-mask-attachment: $value; /* Chrome, iOS, Safari */ - mask-attachment: $value; /* None yet / Non-standard */ -} - -@mixin mask-composite($value) { - -webkit-mask-composite: $value; /* Chrome, iOS, Safari */ - mask-composite: $value; /* None yet / Non-standard */ -} - -@mixin mask-box-image($value) { - -webkit-mask-box-image: $value; /* Chrome, iOS, Safari */ - mask-box-image: $value; /* None yet / Non-standard */ -} - -// opacity - -@mixin opacity($opacity) { - opacity: $opacity; /* W3C */ - filter: alpha(opacity=($opacity * 100)); /* IE */ -} - -// padding - -@mixin padding-start($value) { - -webkit-padding-start: $value; /* Safari, Chrome, WebKit */ - -moz-padding-start: $value; /* Firefox 3+ */ - padding-start: $value; -} - -@mixin padding-end($value) { - -webkit-padding-end: $value; /* Safari, Chrome, WebKit */ - -moz-padding-end: $value; /* Firefox 3+ */ - padding-end: $value; -} - -// ruby-position - -@mixin ruby-position($value) { - -webkit-ruby-position: $value; /* Blink, Webkit */ - ruby-position: $value; /* Firefox, IE */ -} - -// Text - -@mixin text-size-adjust($value) { - -webkit-text-size-adjust: $value; /* Chrome 27+ */ - -moz-text-size-adjust: $value; /* Firefox */ - text-size-adjust: $value; /* None yet */ -} - -@mixin text-align-last($value) { - -webkit-text-align-last: $value; /* Chrome 35+, Safari Not supported. */ - -moz-text-align-last: $value; /* Firefox 12.0 */ - text-align-last: $value; /* IE 5.5+ */ -} - -@mixin text-justify($value) { - -webkit-text-justify: $value; - text-justify: $value; -} - -@mixin text-decoration-color($value) { - -webkit-text-decoration-color: $value; - text-decoration-color: $value; -} - -@mixin text-decoration-line($value) { - -webkit-text-decoration-line: $value; - text-decoration-line: $value; -} - -@mixin text-decoration-style($value) { - -webkit-text-decoration-style: $value; - text-decoration-style: $value; -} - -@mixin text-orientation($value) { - -webkit-text-orientation: $value; - text-orientation: $value; -} - -@mixin text-underline-position($value) { - -webkit-text-underline-position: $value; /* Chrome 33 not fully supported. */ - text-underline-position: $value; /* IE 5 not fully supported. */ -} - -@mixin text-emphasis($value) { - -webkit-text-emphasis: $value; /* Blink */ - text-emphasis: $value; /* WebKit */ -} - -@mixin text-emphasis-color($value) { - -webkit-text-emphasis-color: $value; /* Blink */ - text-emphasis-color: $value; /* WebKit */ -} - -@mixin text-emphasis-style($value) { - -webkit-text-emphasis-style: $value; /* Blink */ - text-emphasis-style: $value; /* WebKit */ -} - -@mixin text-emphasis-position($value) { - -webkit-text-emphasis-position: $value; /* Blink */ - text-emphasis-position: $value; /* WebKit */ -} - -// tab - -@mixin tab-size($value) { - -webkit-tab-size: $value; /* Chrome 21+, Safari 6.1+ */ - -moz-tab-size: $value; /* Firefox 4.0 */ - -o-tab-size: $value; /* Opera 10.6~15 */ - tab-size: $value; /* Blink & Webkit */ -} - -// input-placeholder - -@mixin input-placeholder($seletor) { - - #{$seletor}::-webkit-input-placeholder { - @content; - } - - #{$seletor}:-moz-placeholder { /* Firefox 4~18 */ - @content; - } - - #{$seletor}::-moz-placeholder { /* Firefox 19+ */ - @content; - } - - #{$seletor}:-ms-input-placeholder { /* IE10+ */ - @content; - } -} \ No newline at end of file diff --git a/src/main/resources/static/editor-md/scss/lib/variables.scss b/src/main/resources/static/editor-md/scss/lib/variables.scss deleted file mode 100644 index 4e21a7b..0000000 --- a/src/main/resources/static/editor-md/scss/lib/variables.scss +++ /dev/null @@ -1,11 +0,0 @@ -@charset "UTF-8"; - -// Global Variables - -$prefix : ".editormd-"; -$color : #666; -$mainColor : #2196F3; -$primaryColor : $mainColor; -$secondColor : #33CC66; -$thirdColor : #999999; -$borderColor : #ddd; \ No newline at end of file diff --git a/src/main/resources/static/editor-md/scss/prettify.scss b/src/main/resources/static/editor-md/scss/prettify.scss deleted file mode 100644 index c50bbe0..0000000 --- a/src/main/resources/static/editor-md/scss/prettify.scss +++ /dev/null @@ -1,53 +0,0 @@ -@charset "UTF-8"; - -/*! Pretty printing styles. Used with prettify.js. */ -/* SPAN elements with the classes below are added by prettyprint. */ -.pln { color: #000 } /* plain text */ - -@media screen { - .str { color: #080 } /* string content */ - .kwd { color: #008 } /* a keyword */ - .com { color: #800 } /* a comment */ - .typ { color: #606 } /* a type name */ - .lit { color: #066 } /* a literal value */ - /* punctuation, lisp open bracket, lisp close bracket */ - .pun, .opn, .clo { color: #660 } - .tag { color: #008 } /* a markup tag name */ - .atn { color: #606 } /* a markup attribute name */ - .atv { color: #080 } /* a markup attribute value */ - .dec, .var { color: #606 } /* a declaration; a variable name */ - .fun { color: red } /* a function name */ -} - -/* Use higher contrast and text-weight for printable form. */ -@media print, projection { - .str { color: #060 } - .kwd { color: #006; font-weight: bold } - .com { color: #600; font-style: italic } - .typ { color: #404; font-weight: bold } - .lit { color: #044 } - .pun, .opn, .clo { color: #440 } - .tag { color: #006; font-weight: bold } - .atn { color: #404 } - .atv { color: #060 } -} - -/* Put a border around prettyprinted code snippets. */ -pre.prettyprint { padding: 2px; border: 1px solid #888 } - -/* Specify class=linenums on a pre to get line numbering */ -ol.linenums { margin-top: 0; margin-bottom: 0 } /* IE indents via margin-left */ -li.L0, -li.L1, -li.L2, -li.L3, -li.L5, -li.L6, -li.L7, -li.L8 { list-style-type: none } -/* Alternate shading for lines */ -li.L1, -li.L3, -li.L5, -li.L7, -li.L9 { background: #eee } \ No newline at end of file diff --git a/src/main/resources/static/editor-md/src/editormd.js b/src/main/resources/static/editor-md/src/editormd.js deleted file mode 100644 index 483a8c3..0000000 --- a/src/main/resources/static/editor-md/src/editormd.js +++ /dev/null @@ -1,4588 +0,0 @@ -;(function(factory) { - "use strict"; - - // CommonJS/Node.js - if (typeof require === "function" && typeof exports === "object" && typeof module === "object") - { - module.exports = factory; - } - else if (typeof define === "function") // AMD/CMD/Sea.js - { - if (define.amd) // for Require.js - { - /* Require.js define replace */ - } - else - { - define(["jquery"], factory); // for Sea.js - } - } - else - { - window.editormd = factory(); - } - -}(function() { - - /* Require.js assignment replace */ - - "use strict"; - - var $ = (typeof (jQuery) !== "undefined") ? jQuery : Zepto; - - if (typeof ($) === "undefined") { - return ; - } - - /** - * editormd - * - * @param {String} id 编辑器的ID - * @param {Object} options 配置选项 Key/Value - * @returns {Object} editormd 返回editormd对象 - */ - - var editormd = function (id, options) { - return new editormd.fn.init(id, options); - }; - - editormd.title = editormd.$name = "Editor.md"; - editormd.version = "1.5.0"; - editormd.homePage = "https://pandao.github.io/editor.md/"; - editormd.classPrefix = "editormd-"; - - editormd.toolbarModes = { - full : [ - "undo", "redo", "|", - "bold", "del", "italic", "quote", "ucwords", "uppercase", "lowercase", "|", - "h1", "h2", "h3", "h4", "h5", "h6", "|", - "list-ul", "list-ol", "hr", "|", - "link", "reference-link", "image", "code", "preformatted-text", "code-block", "table", "datetime", "emoji", "html-entities", "pagebreak", "|", - "goto-line", "watch", "preview", "fullscreen", "clear", "search", "|", - "help", "info" - ], - simple : [ - "undo", "redo", "|", - "bold", "del", "italic", "quote", "uppercase", "lowercase", "|", - "h1", "h2", "h3", "h4", "h5", "h6", "|", - "list-ul", "list-ol", "hr", "|", - "watch", "preview", "fullscreen", "|", - "help", "info" - ], - mini : [ - "undo", "redo", "|", - "watch", "preview", "|", - "help", "info" - ] - }; - - editormd.defaults = { - mode : "gfm", //gfm or markdown - name : "", // Form element name - value : "", // value for CodeMirror, if mode not gfm/markdown - theme : "", // Editor.md self themes, before v1.5.0 is CodeMirror theme, default empty - editorTheme : "default", // Editor area, this is CodeMirror theme at v1.5.0 - previewTheme : "", // Preview area theme, default empty - markdown : "", // Markdown source code - appendMarkdown : "", // if in init textarea value not empty, append markdown to textarea - width : "100%", - height : "100%", - path : "./lib/", // Dependents module file directory - pluginPath : "", // If this empty, default use settings.path + "../plugins/" - delay : 300, // Delay parse markdown to html, Uint : ms - autoLoadModules : true, // Automatic load dependent module files - watch : true, - placeholder : "Enjoy Markdown! coding now...", - gotoLine : true, - codeFold : false, - autoHeight : false, - autoFocus : true, - autoCloseTags : true, - searchReplace : true, - syncScrolling : true, // true | false | "single", default true - readOnly : false, - tabSize : 4, - indentUnit : 4, - lineNumbers : true, - lineWrapping : true, - autoCloseBrackets : true, - showTrailingSpace : true, - matchBrackets : true, - indentWithTabs : true, - styleSelectedText : true, - matchWordHighlight : true, // options: true, false, "onselected" - styleActiveLine : true, // Highlight the current line - dialogLockScreen : true, - dialogShowMask : true, - dialogDraggable : true, - dialogMaskBgColor : "#fff", - dialogMaskOpacity : 0.1, - fontSize : "13px", - saveHTMLToTextarea : false, - disabledKeyMaps : [], - - onload : function() {}, - onresize : function() {}, - onchange : function() {}, - onwatch : null, - onunwatch : null, - onpreviewing : function() {}, - onpreviewed : function() {}, - onfullscreen : function() {}, - onfullscreenExit : function() {}, - onscroll : function() {}, - onpreviewscroll : function() {}, - - imageUpload : false, - imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"], - imageUploadURL : "", - crossDomainUpload : false, - uploadCallbackURL : "", - - toc : true, // Table of contents - tocm : false, // Using [TOCM], auto create ToC dropdown menu - tocTitle : "", // for ToC dropdown menu btn - tocDropdown : false, - tocContainer : "", - tocStartLevel : 1, // Said from H1 to create ToC - htmlDecode : false, // Open the HTML tag identification - pageBreak : true, // Enable parse page break [========] - atLink : true, // for @link - emailLink : true, // for email address auto link - taskList : false, // Enable Github Flavored Markdown task lists - emoji : false, // :emoji: , Support Github emoji, Twitter Emoji (Twemoji); - // Support FontAwesome icon emoji :fa-xxx: > Using fontAwesome icon web fonts; - // Support Editor.md logo icon emoji :editormd-logo: :editormd-logo-1x: > 1~8x; - tex : false, // TeX(LaTeX), based on KaTeX - flowChart : false, // flowChart.js only support IE9+ - sequenceDiagram : false, // sequenceDiagram.js only support IE9+ - previewCodeHighlight : true, - - toolbar : true, // show/hide toolbar - toolbarAutoFixed : true, // on window scroll auto fixed position - toolbarIcons : "full", - toolbarTitles : {}, - toolbarHandlers : { - ucwords : function() { - return editormd.toolbarHandlers.ucwords; - }, - lowercase : function() { - return editormd.toolbarHandlers.lowercase; - } - }, - toolbarCustomIcons : { // using html tag create toolbar icon, unused default tag. - lowercase : "a", - "ucwords" : "Aa" - }, - toolbarIconsClass : { - undo : "fa-undo", - redo : "fa-repeat", - bold : "fa-bold", - del : "fa-strikethrough", - italic : "fa-italic", - quote : "fa-quote-left", - uppercase : "fa-font", - h1 : editormd.classPrefix + "bold", - h2 : editormd.classPrefix + "bold", - h3 : editormd.classPrefix + "bold", - h4 : editormd.classPrefix + "bold", - h5 : editormd.classPrefix + "bold", - h6 : editormd.classPrefix + "bold", - "list-ul" : "fa-list-ul", - "list-ol" : "fa-list-ol", - hr : "fa-minus", - link : "fa-link", - "reference-link" : "fa-anchor", - image : "fa-picture-o", - code : "fa-code", - "preformatted-text" : "fa-file-code-o", - "code-block" : "fa-file-code-o", - table : "fa-table", - datetime : "fa-clock-o", - emoji : "fa-smile-o", - "html-entities" : "fa-copyright", - pagebreak : "fa-newspaper-o", - "goto-line" : "fa-terminal", // fa-crosshairs - watch : "fa-eye-slash", - unwatch : "fa-eye", - preview : "fa-desktop", - search : "fa-search", - fullscreen : "fa-arrows-alt", - clear : "fa-eraser", - help : "fa-question-circle", - info : "fa-info-circle" - }, - toolbarIconTexts : {}, - - lang : { - name : "zh-cn", - description : "开源在线Markdown编辑器
                    Open source online Markdown editor.", - tocTitle : "目录", - toolbar : { - undo : "撤销(Ctrl+Z)", - redo : "重做(Ctrl+Y)", - bold : "粗体", - del : "删除线", - italic : "斜体", - quote : "引用", - ucwords : "将每个单词首字母转成大写", - uppercase : "将所选转换成大写", - lowercase : "将所选转换成小写", - h1 : "标题1", - h2 : "标题2", - h3 : "标题3", - h4 : "标题4", - h5 : "标题5", - h6 : "标题6", - "list-ul" : "无序列表", - "list-ol" : "有序列表", - hr : "横线", - link : "链接", - "reference-link" : "引用链接", - image : "添加图片", - code : "行内代码", - "preformatted-text" : "预格式文本 / 代码块(缩进风格)", - "code-block" : "代码块(多语言风格)", - table : "添加表格", - datetime : "日期时间", - emoji : "Emoji表情", - "html-entities" : "HTML实体字符", - pagebreak : "插入分页符", - "goto-line" : "跳转到行", - watch : "关闭实时预览", - unwatch : "开启实时预览", - preview : "全窗口预览HTML(按 Shift + ESC还原)", - fullscreen : "全屏(按ESC还原)", - clear : "清空", - search : "搜索", - help : "使用帮助", - info : "关于" + editormd.title - }, - buttons : { - enter : "确定", - cancel : "取消", - close : "关闭" - }, - dialog : { - link : { - title : "添加链接", - url : "链接地址", - urlTitle : "链接标题", - urlEmpty : "错误:请填写链接地址。" - }, - referenceLink : { - title : "添加引用链接", - name : "引用名称", - url : "链接地址", - urlId : "链接ID", - urlTitle : "链接标题", - nameEmpty: "错误:引用链接的名称不能为空。", - idEmpty : "错误:请填写引用链接的ID。", - urlEmpty : "错误:请填写引用链接的URL地址。" - }, - image : { - title : "添加图片", - url : "图片地址", - link : "图片链接", - alt : "图片描述", - uploadButton : "本地上传", - imageURLEmpty : "错误:图片地址不能为空。", - uploadFileEmpty : "错误:上传的图片不能为空。", - formatNotAllowed : "错误:只允许上传图片文件,允许上传的图片文件格式有:" - }, - preformattedText : { - title : "添加预格式文本或代码块", - emptyAlert : "错误:请填写预格式文本或代码的内容。" - }, - codeBlock : { - title : "添加代码块", - selectLabel : "代码语言:", - selectDefaultText : "请选择代码语言", - otherLanguage : "其他语言", - unselectedLanguageAlert : "错误:请选择代码所属的语言类型。", - codeEmptyAlert : "错误:请填写代码内容。" - }, - htmlEntities : { - title : "HTML 实体字符" - }, - help : { - title : "使用帮助" - } - } - } - }; - - editormd.classNames = { - tex : editormd.classPrefix + "tex" - }; - - editormd.dialogZindex = 99999; - - editormd.$katex = null; - editormd.$marked = null; - editormd.$CodeMirror = null; - editormd.$prettyPrint = null; - - var timer, flowchartTimer; - - editormd.prototype = editormd.fn = { - state : { - watching : false, - loaded : false, - preview : false, - fullscreen : false - }, - - /** - * 构造函数/实例初始化 - * Constructor / instance initialization - * - * @param {String} id 编辑器的ID - * @param {Object} [options={}] 配置选项 Key/Value - * @returns {editormd} 返回editormd的实例对象 - */ - - init : function (id, options) { - - options = options || {}; - - if (typeof id === "object") - { - options = id; - } - - var _this = this; - var classPrefix = this.classPrefix = editormd.classPrefix; - var settings = this.settings = $.extend(true, editormd.defaults, options); - - id = (typeof id === "object") ? settings.id : id; - - var editor = this.editor = $("#" + id); - - this.id = id; - this.lang = settings.lang; - - var classNames = this.classNames = { - textarea : { - html : classPrefix + "html-textarea", - markdown : classPrefix + "markdown-textarea" - } - }; - - settings.pluginPath = (settings.pluginPath === "") ? settings.path + "../plugins/" : settings.pluginPath; - - this.state.watching = (settings.watch) ? true : false; - - if ( !editor.hasClass("editormd") ) { - editor.addClass("editormd"); - } - - editor.css({ - width : (typeof settings.width === "number") ? settings.width + "px" : settings.width, - height : (typeof settings.height === "number") ? settings.height + "px" : settings.height - }); - - if (settings.autoHeight) - { - editor.css("height", "auto"); - } - - var markdownTextarea = this.markdownTextarea = editor.children("textarea"); - - if (markdownTextarea.length < 1) - { - editor.append(""); - markdownTextarea = this.markdownTextarea = editor.children("textarea"); - } - - markdownTextarea.addClass(classNames.textarea.markdown).attr("placeholder", settings.placeholder); - - if (typeof markdownTextarea.attr("name") === "undefined" || markdownTextarea.attr("name") === "") - { - markdownTextarea.attr("name", (settings.name !== "") ? settings.name : id + "-markdown-doc"); - } - - var appendElements = [ - (!settings.readOnly) ? "" : "", - ( (settings.saveHTMLToTextarea) ? "" : "" ), - "
                    ", - "
                    ", - "
                    " - ].join("\n"); - - editor.append(appendElements).addClass(classPrefix + "vertical"); - - if (settings.theme !== "") - { - editor.addClass(classPrefix + "theme-" + settings.theme); - } - - this.mask = editor.children("." + classPrefix + "mask"); - this.containerMask = editor.children("." + classPrefix + "container-mask"); - - if (settings.markdown !== "") - { - markdownTextarea.val(settings.markdown); - } - - if (settings.appendMarkdown !== "") - { - markdownTextarea.val(markdownTextarea.val() + settings.appendMarkdown); - } - - this.htmlTextarea = editor.children("." + classNames.textarea.html); - this.preview = editor.children("." + classPrefix + "preview"); - this.previewContainer = this.preview.children("." + classPrefix + "preview-container"); - - if (settings.previewTheme !== "") - { - this.preview.addClass(classPrefix + "preview-theme-" + settings.previewTheme); - } - - if (typeof define === "function" && define.amd) - { - if (typeof katex !== "undefined") - { - editormd.$katex = katex; - } - - if (settings.searchReplace && !settings.readOnly) - { - editormd.loadCSS(settings.path + "codemirror/addon/dialog/dialog"); - editormd.loadCSS(settings.path + "codemirror/addon/search/matchesonscrollbar"); - } - } - - if ((typeof define === "function" && define.amd) || !settings.autoLoadModules) - { - if (typeof CodeMirror !== "undefined") { - editormd.$CodeMirror = CodeMirror; - } - - if (typeof marked !== "undefined") { - editormd.$marked = marked; - } - - this.setCodeMirror().setToolbar().loadedDisplay(); - } - else - { - this.loadQueues(); - } - - return this; - }, - - /** - * 所需组件加载队列 - * Required components loading queue - * - * @returns {editormd} 返回editormd的实例对象 - */ - - loadQueues : function() { - var _this = this; - var settings = this.settings; - var loadPath = settings.path; - - var loadFlowChartOrSequenceDiagram = function() { - - if (editormd.isIE8) - { - _this.loadedDisplay(); - - return ; - } - - if (settings.flowChart || settings.sequenceDiagram) - { - editormd.loadScript(loadPath + "raphael.min", function() { - - editormd.loadScript(loadPath + "underscore.min", function() { - - if (!settings.flowChart && settings.sequenceDiagram) - { - editormd.loadScript(loadPath + "sequence-diagram.min", function() { - _this.loadedDisplay(); - }); - } - else if (settings.flowChart && !settings.sequenceDiagram) - { - editormd.loadScript(loadPath + "flowchart.min", function() { - editormd.loadScript(loadPath + "jquery.flowchart.min", function() { - _this.loadedDisplay(); - }); - }); - } - else if (settings.flowChart && settings.sequenceDiagram) - { - editormd.loadScript(loadPath + "flowchart.min", function() { - editormd.loadScript(loadPath + "jquery.flowchart.min", function() { - editormd.loadScript(loadPath + "sequence-diagram.min", function() { - _this.loadedDisplay(); - }); - }); - }); - } - }); - - }); - } - else - { - _this.loadedDisplay(); - } - }; - - editormd.loadCSS(loadPath + "codemirror/codemirror.min"); - - if (settings.searchReplace && !settings.readOnly) - { - editormd.loadCSS(loadPath + "codemirror/addon/dialog/dialog"); - editormd.loadCSS(loadPath + "codemirror/addon/search/matchesonscrollbar"); - } - - if (settings.codeFold) - { - editormd.loadCSS(loadPath + "codemirror/addon/fold/foldgutter"); - } - - editormd.loadScript(loadPath + "codemirror/codemirror.min", function() { - editormd.$CodeMirror = CodeMirror; - - editormd.loadScript(loadPath + "codemirror/modes.min", function() { - - editormd.loadScript(loadPath + "codemirror/addons.min", function() { - - _this.setCodeMirror(); - - if (settings.mode !== "gfm" && settings.mode !== "markdown") - { - _this.loadedDisplay(); - - return false; - } - - _this.setToolbar(); - - editormd.loadScript(loadPath + "marked.min", function() { - - editormd.$marked = marked; - - if (settings.previewCodeHighlight) - { - editormd.loadScript(loadPath + "prettify.min", function() { - loadFlowChartOrSequenceDiagram(); - }); - } - else - { - loadFlowChartOrSequenceDiagram(); - } - }); - - }); - - }); - - }); - - return this; - }, - - /** - * 设置 Editor.md 的整体主题,主要是工具栏 - * Setting Editor.md theme - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setTheme : function(theme) { - var editor = this.editor; - var oldTheme = this.settings.theme; - var themePrefix = this.classPrefix + "theme-"; - - editor.removeClass(themePrefix + oldTheme).addClass(themePrefix + theme); - - this.settings.theme = theme; - - return this; - }, - - /** - * 设置 CodeMirror(编辑区)的主题 - * Setting CodeMirror (Editor area) theme - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setEditorTheme : function(theme) { - var settings = this.settings; - settings.editorTheme = theme; - - if (theme !== "default") - { - editormd.loadCSS(settings.path + "codemirror/theme/" + settings.editorTheme); - } - - this.cm.setOption("theme", theme); - - return this; - }, - - /** - * setEditorTheme() 的别名 - * setEditorTheme() alias - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setCodeMirrorTheme : function (theme) { - this.setEditorTheme(theme); - - return this; - }, - - /** - * 设置 Editor.md 的主题 - * Setting Editor.md theme - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setPreviewTheme : function(theme) { - var preview = this.preview; - var oldTheme = this.settings.previewTheme; - var themePrefix = this.classPrefix + "preview-theme-"; - - preview.removeClass(themePrefix + oldTheme).addClass(themePrefix + theme); - - this.settings.previewTheme = theme; - - return this; - }, - - /** - * 配置和初始化CodeMirror组件 - * CodeMirror initialization - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setCodeMirror : function() { - var settings = this.settings; - var editor = this.editor; - - if (settings.editorTheme !== "default") - { - editormd.loadCSS(settings.path + "codemirror/theme/" + settings.editorTheme); - } - - var codeMirrorConfig = { - mode : settings.mode, - theme : settings.editorTheme, - tabSize : settings.tabSize, - dragDrop : false, - autofocus : settings.autoFocus, - autoCloseTags : settings.autoCloseTags, - readOnly : (settings.readOnly) ? "nocursor" : false, - indentUnit : settings.indentUnit, - lineNumbers : settings.lineNumbers, - lineWrapping : settings.lineWrapping, - extraKeys : { - "Ctrl-Q": function(cm) { - cm.foldCode(cm.getCursor()); - } - }, - foldGutter : settings.codeFold, - gutters : ["CodeMirror-linenumbers", "CodeMirror-foldgutter"], - matchBrackets : settings.matchBrackets, - indentWithTabs : settings.indentWithTabs, - styleActiveLine : settings.styleActiveLine, - styleSelectedText : settings.styleSelectedText, - autoCloseBrackets : settings.autoCloseBrackets, - showTrailingSpace : settings.showTrailingSpace, - highlightSelectionMatches : ( (!settings.matchWordHighlight) ? false : { showToken: (settings.matchWordHighlight === "onselected") ? false : /\w/ } ) - }; - - this.codeEditor = this.cm = editormd.$CodeMirror.fromTextArea(this.markdownTextarea[0], codeMirrorConfig); - this.codeMirror = this.cmElement = editor.children(".CodeMirror"); - - if (settings.value !== "") - { - this.cm.setValue(settings.value); - } - - this.codeMirror.css({ - fontSize : settings.fontSize, - width : (!settings.watch) ? "100%" : "50%" - }); - - if (settings.autoHeight) - { - this.codeMirror.css("height", "auto"); - this.cm.setOption("viewportMargin", Infinity); - } - - if (!settings.lineNumbers) - { - this.codeMirror.find(".CodeMirror-gutters").css("border-right", "none"); - } - - return this; - }, - - /** - * 获取CodeMirror的配置选项 - * Get CodeMirror setting options - * - * @returns {Mixed} return CodeMirror setting option value - */ - - getCodeMirrorOption : function(key) { - return this.cm.getOption(key); - }, - - /** - * 配置和重配置CodeMirror的选项 - * CodeMirror setting options / resettings - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setCodeMirrorOption : function(key, value) { - - this.cm.setOption(key, value); - - return this; - }, - - /** - * 添加 CodeMirror 键盘快捷键 - * Add CodeMirror keyboard shortcuts key map - * - * @returns {editormd} 返回editormd的实例对象 - */ - - addKeyMap : function(map, bottom) { - this.cm.addKeyMap(map, bottom); - - return this; - }, - - /** - * 移除 CodeMirror 键盘快捷键 - * Remove CodeMirror keyboard shortcuts key map - * - * @returns {editormd} 返回editormd的实例对象 - */ - - removeKeyMap : function(map) { - this.cm.removeKeyMap(map); - - return this; - }, - - /** - * 跳转到指定的行 - * Goto CodeMirror line - * - * @param {String|Intiger} line line number or "first"|"last" - * @returns {editormd} 返回editormd的实例对象 - */ - - gotoLine : function (line) { - - var settings = this.settings; - - if (!settings.gotoLine) - { - return this; - } - - var cm = this.cm; - var editor = this.editor; - var count = cm.lineCount(); - var preview = this.preview; - - if (typeof line === "string") - { - if(line === "last") - { - line = count; - } - - if (line === "first") - { - line = 1; - } - } - - if (typeof line !== "number") - { - alert("Error: The line number must be an integer."); - return this; - } - - line = parseInt(line) - 1; - - if (line > count) - { - alert("Error: The line number range 1-" + count); - - return this; - } - - cm.setCursor( {line : line, ch : 0} ); - - var scrollInfo = cm.getScrollInfo(); - var clientHeight = scrollInfo.clientHeight; - var coords = cm.charCoords({line : line, ch : 0}, "local"); - - cm.scrollTo(null, (coords.top + coords.bottom - clientHeight) / 2); - - if (settings.watch) - { - var cmScroll = this.codeMirror.find(".CodeMirror-scroll")[0]; - var height = $(cmScroll).height(); - var scrollTop = cmScroll.scrollTop; - var percent = (scrollTop / cmScroll.scrollHeight); - - if (scrollTop === 0) - { - preview.scrollTop(0); - } - else if (scrollTop + height >= cmScroll.scrollHeight - 16) - { - preview.scrollTop(preview[0].scrollHeight); - } - else - { - preview.scrollTop(preview[0].scrollHeight * percent); - } - } - - cm.focus(); - - return this; - }, - - /** - * 扩展当前实例对象,可同时设置多个或者只设置一个 - * Extend editormd instance object, can mutil setting. - * - * @returns {editormd} this(editormd instance object.) - */ - - extend : function() { - if (typeof arguments[1] !== "undefined") - { - if (typeof arguments[1] === "function") - { - arguments[1] = $.proxy(arguments[1], this); - } - - this[arguments[0]] = arguments[1]; - } - - if (typeof arguments[0] === "object" && typeof arguments[0].length === "undefined") - { - $.extend(true, this, arguments[0]); - } - - return this; - }, - - /** - * 设置或扩展当前实例对象,单个设置 - * Extend editormd instance object, one by one - * - * @param {String|Object} key option key - * @param {String|Object} value option value - * @returns {editormd} this(editormd instance object.) - */ - - set : function (key, value) { - - if (typeof value !== "undefined" && typeof value === "function") - { - value = $.proxy(value, this); - } - - this[key] = value; - - return this; - }, - - /** - * 重新配置 - * Resetting editor options - * - * @param {String|Object} key option key - * @param {String|Object} value option value - * @returns {editormd} this(editormd instance object.) - */ - - config : function(key, value) { - var settings = this.settings; - - if (typeof key === "object") - { - settings = $.extend(true, settings, key); - } - - if (typeof key === "string") - { - settings[key] = value; - } - - this.settings = settings; - this.recreate(); - - return this; - }, - - /** - * 注册事件处理方法 - * Bind editor event handle - * - * @param {String} eventType event type - * @param {Function} callback 回调函数 - * @returns {editormd} this(editormd instance object.) - */ - - on : function(eventType, callback) { - var settings = this.settings; - - if (typeof settings["on" + eventType] !== "undefined") - { - settings["on" + eventType] = $.proxy(callback, this); - } - - return this; - }, - - /** - * 解除事件处理方法 - * Unbind editor event handle - * - * @param {String} eventType event type - * @returns {editormd} this(editormd instance object.) - */ - - off : function(eventType) { - var settings = this.settings; - - if (typeof settings["on" + eventType] !== "undefined") - { - settings["on" + eventType] = function(){}; - } - - return this; - }, - - /** - * 显示工具栏 - * Display toolbar - * - * @param {Function} [callback=function(){}] 回调函数 - * @returns {editormd} 返回editormd的实例对象 - */ - - showToolbar : function(callback) { - var settings = this.settings; - - if(settings.readOnly) { - return this; - } - - if (settings.toolbar && (this.toolbar.length < 1 || this.toolbar.find("." + this.classPrefix + "menu").html() === "") ) - { - this.setToolbar(); - } - - settings.toolbar = true; - - this.toolbar.show(); - this.resize(); - - $.proxy(callback || function(){}, this)(); - - return this; - }, - - /** - * 隐藏工具栏 - * Hide toolbar - * - * @param {Function} [callback=function(){}] 回调函数 - * @returns {editormd} this(editormd instance object.) - */ - - hideToolbar : function(callback) { - var settings = this.settings; - - settings.toolbar = false; - this.toolbar.hide(); - this.resize(); - - $.proxy(callback || function(){}, this)(); - - return this; - }, - - /** - * 页面滚动时工具栏的固定定位 - * Set toolbar in window scroll auto fixed position - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setToolbarAutoFixed : function(fixed) { - - var state = this.state; - var editor = this.editor; - var toolbar = this.toolbar; - var settings = this.settings; - - if (typeof fixed !== "undefined") - { - settings.toolbarAutoFixed = fixed; - } - - var autoFixedHandle = function(){ - var $window = $(window); - var top = $window.scrollTop(); - - if (!settings.toolbarAutoFixed) - { - return false; - } - - if (top - editor.offset().top > 10 && top < editor.height()) - { - toolbar.css({ - position : "fixed", - width : editor.width() + "px", - left : ($window.width() - editor.width()) / 2 + "px" - }); - } - else - { - toolbar.css({ - position : "absolute", - width : "100%", - left : 0 - }); - } - }; - - if (!state.fullscreen && !state.preview && settings.toolbar && settings.toolbarAutoFixed) - { - $(window).bind("scroll", autoFixedHandle); - } - - return this; - }, - - /** - * 配置和初始化工具栏 - * Set toolbar and Initialization - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setToolbar : function() { - var settings = this.settings; - - if(settings.readOnly) { - return this; - } - - var editor = this.editor; - var preview = this.preview; - var classPrefix = this.classPrefix; - - var toolbar = this.toolbar = editor.children("." + classPrefix + "toolbar"); - - if (settings.toolbar && toolbar.length < 1) - { - var toolbarHTML = "
                      "; - - editor.append(toolbarHTML); - toolbar = this.toolbar = editor.children("." + classPrefix + "toolbar"); - } - - if (!settings.toolbar) - { - toolbar.hide(); - - return this; - } - - toolbar.show(); - - var icons = (typeof settings.toolbarIcons === "function") ? settings.toolbarIcons() - : ((typeof settings.toolbarIcons === "string") ? editormd.toolbarModes[settings.toolbarIcons] : settings.toolbarIcons); - - var toolbarMenu = toolbar.find("." + this.classPrefix + "menu"), menu = ""; - var pullRight = false; - - for (var i = 0, len = icons.length; i < len; i++) - { - var name = icons[i]; - - if (name === "||") - { - pullRight = true; - } - else if (name === "|") - { - menu += "
                    • |
                    • "; - } - else - { - var isHeader = (/h(\d)/.test(name)); - var index = name; - - if (name === "watch" && !settings.watch) { - index = "unwatch"; - } - - var title = settings.lang.toolbar[index]; - var iconTexts = settings.toolbarIconTexts[index]; - var iconClass = settings.toolbarIconsClass[index]; - - title = (typeof title === "undefined") ? "" : title; - iconTexts = (typeof iconTexts === "undefined") ? "" : iconTexts; - iconClass = (typeof iconClass === "undefined") ? "" : iconClass; - - var menuItem = pullRight ? "
                    • " : "
                    • "; - - if (typeof settings.toolbarCustomIcons[name] !== "undefined" && typeof settings.toolbarCustomIcons[name] !== "function") - { - menuItem += settings.toolbarCustomIcons[name]; - } - else - { - menuItem += ""; - menuItem += ""+((isHeader) ? name.toUpperCase() : ( (iconClass === "") ? iconTexts : "") ) + ""; - menuItem += ""; - } - - menuItem += "
                    • "; - - menu = pullRight ? menuItem + menu : menu + menuItem; - } - } - - toolbarMenu.html(menu); - - toolbarMenu.find("[title=\"Lowercase\"]").attr("title", settings.lang.toolbar.lowercase); - toolbarMenu.find("[title=\"ucwords\"]").attr("title", settings.lang.toolbar.ucwords); - - this.setToolbarHandler(); - this.setToolbarAutoFixed(); - - return this; - }, - - /** - * 工具栏图标事件处理对象序列 - * Get toolbar icons event handlers - * - * @param {Object} cm CodeMirror的实例对象 - * @param {String} name 要获取的事件处理器名称 - * @returns {Object} 返回处理对象序列 - */ - - dialogLockScreen : function() { - $.proxy(editormd.dialogLockScreen, this)(); - - return this; - }, - - dialogShowMask : function(dialog) { - $.proxy(editormd.dialogShowMask, this)(dialog); - - return this; - }, - - getToolbarHandles : function(name) { - var toolbarHandlers = this.toolbarHandlers = editormd.toolbarHandlers; - - return (name && typeof toolbarIconHandlers[name] !== "undefined") ? toolbarHandlers[name] : toolbarHandlers; - }, - - /** - * 工具栏图标事件处理器 - * Bind toolbar icons event handle - * - * @returns {editormd} 返回editormd的实例对象 - */ - - setToolbarHandler : function() { - var _this = this; - var settings = this.settings; - - if (!settings.toolbar || settings.readOnly) { - return this; - } - - var toolbar = this.toolbar; - var cm = this.cm; - var classPrefix = this.classPrefix; - var toolbarIcons = this.toolbarIcons = toolbar.find("." + classPrefix + "menu > li > a"); - var toolbarIconHandlers = this.getToolbarHandles(); - - toolbarIcons.bind(editormd.mouseOrTouch("click", "touchend"), function(event) { - - var icon = $(this).children(".fa"); - var name = icon.attr("name"); - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (name === "") { - return ; - } - - _this.activeIcon = icon; - - if (typeof toolbarIconHandlers[name] !== "undefined") - { - $.proxy(toolbarIconHandlers[name], _this)(cm); - } - else - { - if (typeof settings.toolbarHandlers[name] !== "undefined") - { - $.proxy(settings.toolbarHandlers[name], _this)(cm, icon, cursor, selection); - } - } - - if (name !== "link" && name !== "reference-link" && name !== "image" && name !== "code-block" && - name !== "preformatted-text" && name !== "watch" && name !== "preview" && name !== "search" && name !== "fullscreen" && name !== "info") - { - cm.focus(); - } - - return false; - - }); - - return this; - }, - - /** - * 动态创建对话框 - * Creating custom dialogs - * - * @param {Object} options 配置项键值对 Key/Value - * @returns {dialog} 返回创建的dialog的jQuery实例对象 - */ - - createDialog : function(options) { - return $.proxy(editormd.createDialog, this)(options); - }, - - /** - * 创建关于Editor.md的对话框 - * Create about Editor.md dialog - * - * @returns {editormd} 返回editormd的实例对象 - */ - - createInfoDialog : function() { - var _this = this; - var editor = this.editor; - var classPrefix = this.classPrefix; - - var infoDialogHTML = [ - "
                      ", - "
                      ", - "

                      " + editormd.title + "v" + editormd.version + "

                      ", - "

                      " + this.lang.description + "

                      ", - "

                      " + editormd.homePage + "

                      ", - "

                      Copyright © 2015 Pandao, The MIT License.

                      ", - "
                      ", - "", - "
                      " - ].join("\n"); - - editor.append(infoDialogHTML); - - var infoDialog = this.infoDialog = editor.children("." + classPrefix + "dialog-info"); - - infoDialog.find("." + classPrefix + "dialog-close").bind(editormd.mouseOrTouch("click", "touchend"), function() { - _this.hideInfoDialog(); - }); - - infoDialog.css("border", (editormd.isIE8) ? "1px solid #ddd" : "").css("z-index", editormd.dialogZindex).show(); - - this.infoDialogPosition(); - - return this; - }, - - /** - * 关于Editor.md对话居中定位 - * Editor.md dialog position handle - * - * @returns {editormd} 返回editormd的实例对象 - */ - - infoDialogPosition : function() { - var infoDialog = this.infoDialog; - - var _infoDialogPosition = function() { - infoDialog.css({ - top : ($(window).height() - infoDialog.height()) / 2 + "px", - left : ($(window).width() - infoDialog.width()) / 2 + "px" - }); - }; - - _infoDialogPosition(); - - $(window).resize(_infoDialogPosition); - - return this; - }, - - /** - * 显示关于Editor.md - * Display about Editor.md dialog - * - * @returns {editormd} 返回editormd的实例对象 - */ - - showInfoDialog : function() { - - $("html,body").css("overflow-x", "hidden"); - - var _this = this; - var editor = this.editor; - var settings = this.settings; - var infoDialog = this.infoDialog = editor.children("." + this.classPrefix + "dialog-info"); - - if (infoDialog.length < 1) - { - this.createInfoDialog(); - } - - this.lockScreen(true); - - this.mask.css({ - opacity : settings.dialogMaskOpacity, - backgroundColor : settings.dialogMaskBgColor - }).show(); - - infoDialog.css("z-index", editormd.dialogZindex).show(); - - this.infoDialogPosition(); - - return this; - }, - - /** - * 隐藏关于Editor.md - * Hide about Editor.md dialog - * - * @returns {editormd} 返回editormd的实例对象 - */ - - hideInfoDialog : function() { - $("html,body").css("overflow-x", ""); - this.infoDialog.hide(); - this.mask.hide(); - this.lockScreen(false); - - return this; - }, - - /** - * 锁屏 - * lock screen - * - * @param {Boolean} lock Boolean 布尔值,是否锁屏 - * @returns {editormd} 返回editormd的实例对象 - */ - - lockScreen : function(lock) { - editormd.lockScreen(lock); - this.resize(); - - return this; - }, - - /** - * 编辑器界面重建,用于动态语言包或模块加载等 - * Recreate editor - * - * @returns {editormd} 返回editormd的实例对象 - */ - - recreate : function() { - var _this = this; - var editor = this.editor; - var settings = this.settings; - - this.codeMirror.remove(); - - this.setCodeMirror(); - - if (!settings.readOnly) - { - if (editor.find(".editormd-dialog").length > 0) { - editor.find(".editormd-dialog").remove(); - } - - if (settings.toolbar) - { - this.getToolbarHandles(); - this.setToolbar(); - } - } - - this.loadedDisplay(true); - - return this; - }, - - /** - * 高亮预览HTML的pre代码部分 - * highlight of preview codes - * - * @returns {editormd} 返回editormd的实例对象 - */ - - previewCodeHighlight : function() { - var settings = this.settings; - var previewContainer = this.previewContainer; - - if (settings.previewCodeHighlight) - { - previewContainer.find("pre").addClass("prettyprint linenums"); - - if (typeof prettyPrint !== "undefined") - { - prettyPrint(); - } - } - - return this; - }, - - /** - * 解析TeX(KaTeX)科学公式 - * TeX(KaTeX) Renderer - * - * @returns {editormd} 返回editormd的实例对象 - */ - - katexRender : function() { - - if (timer === null) - { - return this; - } - - this.previewContainer.find("." + editormd.classNames.tex).each(function(){ - var tex = $(this); - editormd.$katex.render(tex.text(), tex[0]); - - tex.find(".katex").css("font-size", "1.6em"); - }); - - return this; - }, - - /** - * 解析和渲染流程图及时序图 - * FlowChart and SequenceDiagram Renderer - * - * @returns {editormd} 返回editormd的实例对象 - */ - - flowChartAndSequenceDiagramRender : function() { - var $this = this; - var settings = this.settings; - var previewContainer = this.previewContainer; - - if (editormd.isIE8) { - return this; - } - - if (settings.flowChart) { - if (flowchartTimer === null) { - return this; - } - - previewContainer.find(".flowchart").flowChart(); - } - - if (settings.sequenceDiagram) { - previewContainer.find(".sequence-diagram").sequenceDiagram({theme: "simple"}); - } - - var preview = $this.preview; - var codeMirror = $this.codeMirror; - var codeView = codeMirror.find(".CodeMirror-scroll"); - - var height = codeView.height(); - var scrollTop = codeView.scrollTop(); - var percent = (scrollTop / codeView[0].scrollHeight); - var tocHeight = 0; - - preview.find(".markdown-toc-list").each(function(){ - tocHeight += $(this).height(); - }); - - var tocMenuHeight = preview.find(".editormd-toc-menu").height(); - tocMenuHeight = (!tocMenuHeight) ? 0 : tocMenuHeight; - - if (scrollTop === 0) - { - preview.scrollTop(0); - } - else if (scrollTop + height >= codeView[0].scrollHeight - 16) - { - preview.scrollTop(preview[0].scrollHeight); - } - else - { - preview.scrollTop((preview[0].scrollHeight + tocHeight + tocMenuHeight) * percent); - } - - return this; - }, - - /** - * 注册键盘快捷键处理 - * Register CodeMirror keyMaps (keyboard shortcuts). - * - * @param {Object} keyMap KeyMap key/value {"(Ctrl/Shift/Alt)-Key" : function(){}} - * @returns {editormd} return this - */ - - registerKeyMaps : function(keyMap) { - - var _this = this; - var cm = this.cm; - var settings = this.settings; - var toolbarHandlers = editormd.toolbarHandlers; - var disabledKeyMaps = settings.disabledKeyMaps; - - keyMap = keyMap || null; - - if (keyMap) - { - for (var i in keyMap) - { - if ($.inArray(i, disabledKeyMaps) < 0) - { - var map = {}; - map[i] = keyMap[i]; - - cm.addKeyMap(keyMap); - } - } - } - else - { - for (var k in editormd.keyMaps) - { - var _keyMap = editormd.keyMaps[k]; - var handle = (typeof _keyMap === "string") ? $.proxy(toolbarHandlers[_keyMap], _this) : $.proxy(_keyMap, _this); - - if ($.inArray(k, ["F9", "F10", "F11"]) < 0 && $.inArray(k, disabledKeyMaps) < 0) - { - var _map = {}; - _map[k] = handle; - - cm.addKeyMap(_map); - } - } - - $(window).keydown(function(event) { - - var keymaps = { - "120" : "F9", - "121" : "F10", - "122" : "F11" - }; - - if ( $.inArray(keymaps[event.keyCode], disabledKeyMaps) < 0 ) - { - switch (event.keyCode) - { - case 120: - $.proxy(toolbarHandlers["watch"], _this)(); - return false; - break; - - case 121: - $.proxy(toolbarHandlers["preview"], _this)(); - return false; - break; - - case 122: - $.proxy(toolbarHandlers["fullscreen"], _this)(); - return false; - break; - - default: - break; - } - } - }); - } - - return this; - }, - - /** - * 绑定同步滚动 - * - * @returns {editormd} return this - */ - - bindScrollEvent : function() { - - var _this = this; - var preview = this.preview; - var settings = this.settings; - var codeMirror = this.codeMirror; - var mouseOrTouch = editormd.mouseOrTouch; - - if (!settings.syncScrolling) { - return this; - } - - var cmBindScroll = function() { - codeMirror.find(".CodeMirror-scroll").bind(mouseOrTouch("scroll", "touchmove"), function(event) { - var height = $(this).height(); - var scrollTop = $(this).scrollTop(); - var percent = (scrollTop / $(this)[0].scrollHeight); - - var tocHeight = 0; - - preview.find(".markdown-toc-list").each(function(){ - tocHeight += $(this).height(); - }); - - var tocMenuHeight = preview.find(".editormd-toc-menu").height(); - tocMenuHeight = (!tocMenuHeight) ? 0 : tocMenuHeight; - - if (scrollTop === 0) - { - preview.scrollTop(0); - } - else if (scrollTop + height >= $(this)[0].scrollHeight - 16) - { - preview.scrollTop(preview[0].scrollHeight); - } - else - { - preview.scrollTop((preview[0].scrollHeight + tocHeight + tocMenuHeight) * percent); - } - - $.proxy(settings.onscroll, _this)(event); - }); - }; - - var cmUnbindScroll = function() { - codeMirror.find(".CodeMirror-scroll").unbind(mouseOrTouch("scroll", "touchmove")); - }; - - var previewBindScroll = function() { - - preview.bind(mouseOrTouch("scroll", "touchmove"), function(event) { - var height = $(this).height(); - var scrollTop = $(this).scrollTop(); - var percent = (scrollTop / $(this)[0].scrollHeight); - var codeView = codeMirror.find(".CodeMirror-scroll"); - - if(scrollTop === 0) - { - codeView.scrollTop(0); - } - else if (scrollTop + height >= $(this)[0].scrollHeight) - { - codeView.scrollTop(codeView[0].scrollHeight); - } - else - { - codeView.scrollTop(codeView[0].scrollHeight * percent); - } - - $.proxy(settings.onpreviewscroll, _this)(event); - }); - - }; - - var previewUnbindScroll = function() { - preview.unbind(mouseOrTouch("scroll", "touchmove")); - }; - - codeMirror.bind({ - mouseover : cmBindScroll, - mouseout : cmUnbindScroll, - touchstart : cmBindScroll, - touchend : cmUnbindScroll - }); - - if (settings.syncScrolling === "single") { - return this; - } - - preview.bind({ - mouseover : previewBindScroll, - mouseout : previewUnbindScroll, - touchstart : previewBindScroll, - touchend : previewUnbindScroll - }); - - return this; - }, - - bindChangeEvent : function() { - - var _this = this; - var cm = this.cm; - var settings = this.settings; - - if (!settings.syncScrolling) { - return this; - } - - cm.on("change", function(_cm, changeObj) { - - if (settings.watch) - { - _this.previewContainer.css("padding", settings.autoHeight ? "20px 20px 50px 40px" : "20px"); - } - - timer = setTimeout(function() { - clearTimeout(timer); - _this.save(); - timer = null; - }, settings.delay); - }); - - return this; - }, - - /** - * 加载队列完成之后的显示处理 - * Display handle of the module queues loaded after. - * - * @param {Boolean} recreate 是否为重建编辑器 - * @returns {editormd} 返回editormd的实例对象 - */ - - loadedDisplay : function(recreate) { - - recreate = recreate || false; - - var _this = this; - var editor = this.editor; - var preview = this.preview; - var settings = this.settings; - - this.containerMask.hide(); - - this.save(); - - if (settings.watch) { - preview.show(); - } - - editor.data("oldWidth", editor.width()).data("oldHeight", editor.height()); // 为了兼容Zepto - - this.resize(); - this.registerKeyMaps(); - - $(window).resize(function(){ - _this.resize(); - }); - - this.bindScrollEvent().bindChangeEvent(); - - if (!recreate) - { - $.proxy(settings.onload, this)(); - } - - this.state.loaded = true; - - return this; - }, - - /** - * 设置编辑器的宽度 - * Set editor width - * - * @param {Number|String} width 编辑器宽度值 - * @returns {editormd} 返回editormd的实例对象 - */ - - width : function(width) { - - this.editor.css("width", (typeof width === "number") ? width + "px" : width); - this.resize(); - - return this; - }, - - /** - * 设置编辑器的高度 - * Set editor height - * - * @param {Number|String} height 编辑器高度值 - * @returns {editormd} 返回editormd的实例对象 - */ - - height : function(height) { - - this.editor.css("height", (typeof height === "number") ? height + "px" : height); - this.resize(); - - return this; - }, - - /** - * 调整编辑器的尺寸和布局 - * Resize editor layout - * - * @param {Number|String} [width=null] 编辑器宽度值 - * @param {Number|String} [height=null] 编辑器高度值 - * @returns {editormd} 返回editormd的实例对象 - */ - - resize : function(width, height) { - - width = width || null; - height = height || null; - - var state = this.state; - var editor = this.editor; - var preview = this.preview; - var toolbar = this.toolbar; - var settings = this.settings; - var codeMirror = this.codeMirror; - - if (width) - { - editor.css("width", (typeof width === "number") ? width + "px" : width); - } - - if (settings.autoHeight && !state.fullscreen && !state.preview) - { - editor.css("height", "auto"); - codeMirror.css("height", "auto"); - } - else - { - if (height) - { - editor.css("height", (typeof height === "number") ? height + "px" : height); - } - - if (state.fullscreen) - { - editor.height($(window).height()); - } - - if (settings.toolbar && !settings.readOnly) - { - codeMirror.css("margin-top", toolbar.height() + 1).height(editor.height() - toolbar.height()); - } - else - { - codeMirror.css("margin-top", 0).height(editor.height()); - } - } - - if(settings.watch) - { - codeMirror.width(editor.width() / 2); - preview.width((!state.preview) ? editor.width() / 2 : editor.width()); - - this.previewContainer.css("padding", settings.autoHeight ? "20px 20px 50px 40px" : "20px"); - - if (settings.toolbar && !settings.readOnly) - { - preview.css("top", toolbar.height() + 1); - } - else - { - preview.css("top", 0); - } - - if (settings.autoHeight && !state.fullscreen && !state.preview) - { - preview.height(""); - } - else - { - var previewHeight = (settings.toolbar && !settings.readOnly) ? editor.height() - toolbar.height() : editor.height(); - - preview.height(previewHeight); - } - } - else - { - codeMirror.width(editor.width()); - preview.hide(); - } - - if (state.loaded) - { - $.proxy(settings.onresize, this)(); - } - - return this; - }, - - /** - * 解析和保存Markdown代码 - * Parse & Saving Markdown source code - * - * @returns {editormd} 返回editormd的实例对象 - */ - - save : function() { - - if (timer === null) - { - return this; - } - - var _this = this; - var state = this.state; - var settings = this.settings; - var cm = this.cm; - var cmValue = cm.getValue(); - var previewContainer = this.previewContainer; - - if (settings.mode !== "gfm" && settings.mode !== "markdown") - { - this.markdownTextarea.val(cmValue); - - return this; - } - - var marked = editormd.$marked; - var markdownToC = this.markdownToC = []; - var rendererOptions = this.markedRendererOptions = { - toc : settings.toc, - tocm : settings.tocm, - tocStartLevel : settings.tocStartLevel, - pageBreak : settings.pageBreak, - taskList : settings.taskList, - emoji : settings.emoji, - tex : settings.tex, - atLink : settings.atLink, // for @link - emailLink : settings.emailLink, // for mail address auto link - flowChart : settings.flowChart, - sequenceDiagram : settings.sequenceDiagram, - previewCodeHighlight : settings.previewCodeHighlight, - }; - - var markedOptions = this.markedOptions = { - renderer : editormd.markedRenderer(markdownToC, rendererOptions), - gfm : true, - tables : true, - breaks : true, - pedantic : false, - sanitize : (settings.htmlDecode) ? false : true, // 关闭忽略HTML标签,即开启识别HTML标签,默认为false - smartLists : true, - smartypants : true - }; - - marked.setOptions(markedOptions); - - var newMarkdownDoc = editormd.$marked(cmValue, markedOptions); - - //console.info("cmValue", cmValue, newMarkdownDoc); - - newMarkdownDoc = editormd.filterHTMLTags(newMarkdownDoc, settings.htmlDecode); - - //console.error("cmValue", cmValue, newMarkdownDoc); - - this.markdownTextarea.text(cmValue); - - cm.save(); - - if (settings.saveHTMLToTextarea) - { - this.htmlTextarea.text(newMarkdownDoc); - } - - if(settings.watch || (!settings.watch && state.preview)) - { - previewContainer.html(newMarkdownDoc); - - this.previewCodeHighlight(); - - if (settings.toc) - { - var tocContainer = (settings.tocContainer === "") ? previewContainer : $(settings.tocContainer); - var tocMenu = tocContainer.find("." + this.classPrefix + "toc-menu"); - - tocContainer.attr("previewContainer", (settings.tocContainer === "") ? "true" : "false"); - - if (settings.tocContainer !== "" && tocMenu.length > 0) - { - tocMenu.remove(); - } - - editormd.markdownToCRenderer(markdownToC, tocContainer, settings.tocDropdown, settings.tocStartLevel); - - if (settings.tocDropdown || tocContainer.find("." + this.classPrefix + "toc-menu").length > 0) - { - editormd.tocDropdownMenu(tocContainer, (settings.tocTitle !== "") ? settings.tocTitle : this.lang.tocTitle); - } - - if (settings.tocContainer !== "") - { - previewContainer.find(".markdown-toc").css("border", "none"); - } - } - - if (settings.tex) - { - if (!editormd.kaTeXLoaded && settings.autoLoadModules) - { - editormd.loadKaTeX(function() { - editormd.$katex = katex; - editormd.kaTeXLoaded = true; - _this.katexRender(); - }); - } - else - { - editormd.$katex = katex; - this.katexRender(); - } - } - - if (settings.flowChart || settings.sequenceDiagram) - { - flowchartTimer = setTimeout(function(){ - clearTimeout(flowchartTimer); - _this.flowChartAndSequenceDiagramRender(); - flowchartTimer = null; - }, 10); - } - - if (state.loaded) - { - $.proxy(settings.onchange, this)(); - } - } - - return this; - }, - - /** - * 聚焦光标位置 - * Focusing the cursor position - * - * @returns {editormd} 返回editormd的实例对象 - */ - - focus : function() { - this.cm.focus(); - - return this; - }, - - /** - * 设置光标的位置 - * Set cursor position - * - * @param {Object} cursor 要设置的光标位置键值对象,例:{line:1, ch:0} - * @returns {editormd} 返回editormd的实例对象 - */ - - setCursor : function(cursor) { - this.cm.setCursor(cursor); - - return this; - }, - - /** - * 获取当前光标的位置 - * Get the current position of the cursor - * - * @returns {Cursor} 返回一个光标Cursor对象 - */ - - getCursor : function() { - return this.cm.getCursor(); - }, - - /** - * 设置光标选中的范围 - * Set cursor selected ranges - * - * @param {Object} from 开始位置的光标键值对象,例:{line:1, ch:0} - * @param {Object} to 结束位置的光标键值对象,例:{line:1, ch:0} - * @returns {editormd} 返回editormd的实例对象 - */ - - setSelection : function(from, to) { - - this.cm.setSelection(from, to); - - return this; - }, - - /** - * 获取光标选中的文本 - * Get the texts from cursor selected - * - * @returns {String} 返回选中文本的字符串形式 - */ - - getSelection : function() { - return this.cm.getSelection(); - }, - - /** - * 设置光标选中的文本范围 - * Set the cursor selection ranges - * - * @param {Array} ranges cursor selection ranges array - * @returns {Array} return this - */ - - setSelections : function(ranges) { - this.cm.setSelections(ranges); - - return this; - }, - - /** - * 获取光标选中的文本范围 - * Get the cursor selection ranges - * - * @returns {Array} return selection ranges array - */ - - getSelections : function() { - return this.cm.getSelections(); - }, - - /** - * 替换当前光标选中的文本或在当前光标处插入新字符 - * Replace the text at the current cursor selected or insert a new character at the current cursor position - * - * @param {String} value 要插入的字符值 - * @returns {editormd} 返回editormd的实例对象 - */ - - replaceSelection : function(value) { - this.cm.replaceSelection(value); - - return this; - }, - - /** - * 在当前光标处插入新字符 - * Insert a new character at the current cursor position - * - * 同replaceSelection()方法 - * With the replaceSelection() method - * - * @param {String} value 要插入的字符值 - * @returns {editormd} 返回editormd的实例对象 - */ - - insertValue : function(value) { - this.replaceSelection(value); - - return this; - }, - - /** - * 追加markdown - * append Markdown to editor - * - * @param {String} md 要追加的markdown源文档 - * @returns {editormd} 返回editormd的实例对象 - */ - - appendMarkdown : function(md) { - var settings = this.settings; - var cm = this.cm; - - cm.setValue(cm.getValue() + md); - - return this; - }, - - /** - * 设置和传入编辑器的markdown源文档 - * Set Markdown source document - * - * @param {String} md 要传入的markdown源文档 - * @returns {editormd} 返回editormd的实例对象 - */ - - setMarkdown : function(md) { - this.cm.setValue(md || this.settings.markdown); - - return this; - }, - - /** - * 获取编辑器的markdown源文档 - * Set Editor.md markdown/CodeMirror value - * - * @returns {editormd} 返回editormd的实例对象 - */ - - getMarkdown : function() { - return this.cm.getValue(); - }, - - /** - * 获取编辑器的源文档 - * Get CodeMirror value - * - * @returns {editormd} 返回editormd的实例对象 - */ - - getValue : function() { - return this.cm.getValue(); - }, - - /** - * 设置编辑器的源文档 - * Set CodeMirror value - * - * @param {String} value set code/value/string/text - * @returns {editormd} 返回editormd的实例对象 - */ - - setValue : function(value) { - this.cm.setValue(value); - - return this; - }, - - /** - * 清空编辑器 - * Empty CodeMirror editor container - * - * @returns {editormd} 返回editormd的实例对象 - */ - - clear : function() { - this.cm.setValue(""); - - return this; - }, - - /** - * 获取解析后存放在Textarea的HTML源码 - * Get parsed html code from Textarea - * - * @returns {String} 返回HTML源码 - */ - - getHTML : function() { - if (!this.settings.saveHTMLToTextarea) - { - alert("Error: settings.saveHTMLToTextarea == false"); - - return false; - } - - return this.htmlTextarea.val(); - }, - - /** - * getHTML()的别名 - * getHTML (alias) - * - * @returns {String} Return html code 返回HTML源码 - */ - - getTextareaSavedHTML : function() { - return this.getHTML(); - }, - - /** - * 获取预览窗口的HTML源码 - * Get html from preview container - * - * @returns {editormd} 返回editormd的实例对象 - */ - - getPreviewedHTML : function() { - if (!this.settings.watch) - { - alert("Error: settings.watch == false"); - - return false; - } - - return this.previewContainer.html(); - }, - - /** - * 开启实时预览 - * Enable real-time watching - * - * @returns {editormd} 返回editormd的实例对象 - */ - - watch : function(callback) { - var settings = this.settings; - - if ($.inArray(settings.mode, ["gfm", "markdown"]) < 0) - { - return this; - } - - this.state.watching = settings.watch = true; - this.preview.show(); - - if (this.toolbar) - { - var watchIcon = settings.toolbarIconsClass.watch; - var unWatchIcon = settings.toolbarIconsClass.unwatch; - - var icon = this.toolbar.find(".fa[name=watch]"); - icon.parent().attr("title", settings.lang.toolbar.watch); - icon.removeClass(unWatchIcon).addClass(watchIcon); - } - - this.codeMirror.css("border-right", "1px solid #ddd").width(this.editor.width() / 2); - - timer = 0; - - this.save().resize(); - - if (!settings.onwatch) - { - settings.onwatch = callback || function() {}; - } - - $.proxy(settings.onwatch, this)(); - - return this; - }, - - /** - * 关闭实时预览 - * Disable real-time watching - * - * @returns {editormd} 返回editormd的实例对象 - */ - - unwatch : function(callback) { - var settings = this.settings; - this.state.watching = settings.watch = false; - this.preview.hide(); - - if (this.toolbar) - { - var watchIcon = settings.toolbarIconsClass.watch; - var unWatchIcon = settings.toolbarIconsClass.unwatch; - - var icon = this.toolbar.find(".fa[name=watch]"); - icon.parent().attr("title", settings.lang.toolbar.unwatch); - icon.removeClass(watchIcon).addClass(unWatchIcon); - } - - this.codeMirror.css("border-right", "none").width(this.editor.width()); - - this.resize(); - - if (!settings.onunwatch) - { - settings.onunwatch = callback || function() {}; - } - - $.proxy(settings.onunwatch, this)(); - - return this; - }, - - /** - * 显示编辑器 - * Show editor - * - * @param {Function} [callback=function()] 回调函数 - * @returns {editormd} 返回editormd的实例对象 - */ - - show : function(callback) { - callback = callback || function() {}; - - var _this = this; - this.editor.show(0, function() { - $.proxy(callback, _this)(); - }); - - return this; - }, - - /** - * 隐藏编辑器 - * Hide editor - * - * @param {Function} [callback=function()] 回调函数 - * @returns {editormd} 返回editormd的实例对象 - */ - - hide : function(callback) { - callback = callback || function() {}; - - var _this = this; - this.editor.hide(0, function() { - $.proxy(callback, _this)(); - }); - - return this; - }, - - /** - * 隐藏编辑器部分,只预览HTML - * Enter preview html state - * - * @returns {editormd} 返回editormd的实例对象 - */ - - previewing : function() { - - var _this = this; - var editor = this.editor; - var preview = this.preview; - var toolbar = this.toolbar; - var settings = this.settings; - var codeMirror = this.codeMirror; - var previewContainer = this.previewContainer; - - if ($.inArray(settings.mode, ["gfm", "markdown"]) < 0) { - return this; - } - - if (settings.toolbar && toolbar) { - toolbar.toggle(); - toolbar.find(".fa[name=preview]").toggleClass("active"); - } - - codeMirror.toggle(); - - var escHandle = function(event) { - if (event.shiftKey && event.keyCode === 27) { - _this.previewed(); - } - }; - - if (codeMirror.css("display") === "none") // 为了兼容Zepto,而不使用codeMirror.is(":hidden") - { - this.state.preview = true; - - if (this.state.fullscreen) { - preview.css("background", "#fff"); - } - - editor.find("." + this.classPrefix + "preview-close-btn").show().bind(editormd.mouseOrTouch("click", "touchend"), function(){ - _this.previewed(); - }); - - if (!settings.watch) - { - this.save(); - } - else - { - previewContainer.css("padding", ""); - } - - previewContainer.addClass(this.classPrefix + "preview-active"); - - preview.show().css({ - position : "", - top : 0, - width : editor.width(), - height : (settings.autoHeight && !this.state.fullscreen) ? "auto" : editor.height() - }); - - if (this.state.loaded) - { - $.proxy(settings.onpreviewing, this)(); - } - - $(window).bind("keyup", escHandle); - } - else - { - $(window).unbind("keyup", escHandle); - this.previewed(); - } - }, - - /** - * 显示编辑器部分,退出只预览HTML - * Exit preview html state - * - * @returns {editormd} 返回editormd的实例对象 - */ - - previewed : function() { - - var editor = this.editor; - var preview = this.preview; - var toolbar = this.toolbar; - var settings = this.settings; - var previewContainer = this.previewContainer; - var previewCloseBtn = editor.find("." + this.classPrefix + "preview-close-btn"); - - this.state.preview = false; - - this.codeMirror.show(); - - if (settings.toolbar) { - toolbar.show(); - } - - preview[(settings.watch) ? "show" : "hide"](); - - previewCloseBtn.hide().unbind(editormd.mouseOrTouch("click", "touchend")); - - previewContainer.removeClass(this.classPrefix + "preview-active"); - - if (settings.watch) - { - previewContainer.css("padding", "20px"); - } - - preview.css({ - background : null, - position : "absolute", - width : editor.width() / 2, - height : (settings.autoHeight && !this.state.fullscreen) ? "auto" : editor.height() - toolbar.height(), - top : (settings.toolbar) ? toolbar.height() : 0 - }); - - if (this.state.loaded) - { - $.proxy(settings.onpreviewed, this)(); - } - - return this; - }, - - /** - * 编辑器全屏显示 - * Fullscreen show - * - * @returns {editormd} 返回editormd的实例对象 - */ - - fullscreen : function() { - - var _this = this; - var state = this.state; - var editor = this.editor; - var preview = this.preview; - var toolbar = this.toolbar; - var settings = this.settings; - var fullscreenClass = this.classPrefix + "fullscreen"; - - if (toolbar) { - toolbar.find(".fa[name=fullscreen]").parent().toggleClass("active"); - } - - var escHandle = function(event) { - if (!event.shiftKey && event.keyCode === 27) - { - if (state.fullscreen) - { - _this.fullscreenExit(); - } - } - }; - - if (!editor.hasClass(fullscreenClass)) - { - state.fullscreen = true; - - $("html,body").css("overflow", "hidden"); - - editor.css({ - width : $(window).width(), - height : $(window).height() - }).addClass(fullscreenClass); - - this.resize(); - - $.proxy(settings.onfullscreen, this)(); - - $(window).bind("keyup", escHandle); - } - else - { - $(window).unbind("keyup", escHandle); - this.fullscreenExit(); - } - - return this; - }, - - /** - * 编辑器退出全屏显示 - * Exit fullscreen state - * - * @returns {editormd} 返回editormd的实例对象 - */ - - fullscreenExit : function() { - - var editor = this.editor; - var settings = this.settings; - var toolbar = this.toolbar; - var fullscreenClass = this.classPrefix + "fullscreen"; - - this.state.fullscreen = false; - - if (toolbar) { - toolbar.find(".fa[name=fullscreen]").parent().removeClass("active"); - } - - $("html,body").css("overflow", ""); - - editor.css({ - width : editor.data("oldWidth"), - height : editor.data("oldHeight") - }).removeClass(fullscreenClass); - - this.resize(); - - $.proxy(settings.onfullscreenExit, this)(); - - return this; - }, - - /** - * 加载并执行插件 - * Load and execute the plugin - * - * @param {String} name plugin name / function name - * @param {String} path plugin load path - * @returns {editormd} 返回editormd的实例对象 - */ - - executePlugin : function(name, path) { - - var _this = this; - var cm = this.cm; - var settings = this.settings; - - path = settings.pluginPath + path; - - if (typeof define === "function") - { - if (typeof this[name] === "undefined") - { - alert("Error: " + name + " plugin is not found, you are not load this plugin."); - - return this; - } - - this[name](cm); - - return this; - } - - if ($.inArray(path, editormd.loadFiles.plugin) < 0) - { - editormd.loadPlugin(path, function() { - editormd.loadPlugins[name] = _this[name]; - _this[name](cm); - }); - } - else - { - $.proxy(editormd.loadPlugins[name], this)(cm); - } - - return this; - }, - - /** - * 搜索替换 - * Search & replace - * - * @param {String} command CodeMirror serach commands, "find, fintNext, fintPrev, clearSearch, replace, replaceAll" - * @returns {editormd} return this - */ - - search : function(command) { - var settings = this.settings; - - if (!settings.searchReplace) - { - alert("Error: settings.searchReplace == false"); - return this; - } - - if (!settings.readOnly) - { - this.cm.execCommand(command || "find"); - } - - return this; - }, - - searchReplace : function() { - this.search("replace"); - - return this; - }, - - searchReplaceAll : function() { - this.search("replaceAll"); - - return this; - } - }; - - editormd.fn.init.prototype = editormd.fn; - - /** - * 锁屏 - * lock screen when dialog opening - * - * @returns {void} - */ - - editormd.dialogLockScreen = function() { - var settings = this.settings || {dialogLockScreen : true}; - - if (settings.dialogLockScreen) - { - $("html,body").css("overflow", "hidden"); - this.resize(); - } - }; - - /** - * 显示透明背景层 - * Display mask layer when dialog opening - * - * @param {Object} dialog dialog jQuery object - * @returns {void} - */ - - editormd.dialogShowMask = function(dialog) { - var editor = this.editor; - var settings = this.settings || {dialogShowMask : true}; - - dialog.css({ - top : ($(window).height() - dialog.height()) / 2 + "px", - left : ($(window).width() - dialog.width()) / 2 + "px" - }); - - if (settings.dialogShowMask) { - editor.children("." + this.classPrefix + "mask").css("z-index", parseInt(dialog.css("z-index")) - 1).show(); - } - }; - - editormd.toolbarHandlers = { - undo : function() { - this.cm.undo(); - }, - - redo : function() { - this.cm.redo(); - }, - - bold : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("**" + selection + "**"); - - if(selection === "") { - cm.setCursor(cursor.line, cursor.ch + 2); - } - }, - - del : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("~~" + selection + "~~"); - - if(selection === "") { - cm.setCursor(cursor.line, cursor.ch + 2); - } - }, - - italic : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("*" + selection + "*"); - - if(selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); - } - }, - - quote : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("> " + selection); - cm.setCursor(cursor.line, cursor.ch + 2); - } - else - { - cm.replaceSelection("> " + selection); - } - - //cm.replaceSelection("> " + selection); - //cm.setCursor(cursor.line, (selection === "") ? cursor.ch + 2 : cursor.ch + selection.length + 2); - }, - - ucfirst : function() { - var cm = this.cm; - var selection = cm.getSelection(); - var selections = cm.listSelections(); - - cm.replaceSelection(editormd.firstUpperCase(selection)); - cm.setSelections(selections); - }, - - ucwords : function() { - var cm = this.cm; - var selection = cm.getSelection(); - var selections = cm.listSelections(); - - cm.replaceSelection(editormd.wordsFirstUpperCase(selection)); - cm.setSelections(selections); - }, - - uppercase : function() { - var cm = this.cm; - var selection = cm.getSelection(); - var selections = cm.listSelections(); - - cm.replaceSelection(selection.toUpperCase()); - cm.setSelections(selections); - }, - - lowercase : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - var selections = cm.listSelections(); - - cm.replaceSelection(selection.toLowerCase()); - cm.setSelections(selections); - }, - - h1 : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("# " + selection); - cm.setCursor(cursor.line, cursor.ch + 2); - } - else - { - cm.replaceSelection("# " + selection); - } - }, - - h2 : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("## " + selection); - cm.setCursor(cursor.line, cursor.ch + 3); - } - else - { - cm.replaceSelection("## " + selection); - } - }, - - h3 : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("### " + selection); - cm.setCursor(cursor.line, cursor.ch + 4); - } - else - { - cm.replaceSelection("### " + selection); - } - }, - - h4 : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("#### " + selection); - cm.setCursor(cursor.line, cursor.ch + 5); - } - else - { - cm.replaceSelection("#### " + selection); - } - }, - - h5 : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("##### " + selection); - cm.setCursor(cursor.line, cursor.ch + 6); - } - else - { - cm.replaceSelection("##### " + selection); - } - }, - - h6 : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (cursor.ch !== 0) - { - cm.setCursor(cursor.line, 0); - cm.replaceSelection("###### " + selection); - cm.setCursor(cursor.line, cursor.ch + 7); - } - else - { - cm.replaceSelection("###### " + selection); - } - }, - - "list-ul" : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (selection === "") - { - cm.replaceSelection("- " + selection); - } - else - { - var selectionText = selection.split("\n"); - - for (var i = 0, len = selectionText.length; i < len; i++) - { - selectionText[i] = (selectionText[i] === "") ? "" : "- " + selectionText[i]; - } - - cm.replaceSelection(selectionText.join("\n")); - } - }, - - "list-ol" : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if(selection === "") - { - cm.replaceSelection("1. " + selection); - } - else - { - var selectionText = selection.split("\n"); - - for (var i = 0, len = selectionText.length; i < len; i++) - { - selectionText[i] = (selectionText[i] === "") ? "" : (i+1) + ". " + selectionText[i]; - } - - cm.replaceSelection(selectionText.join("\n")); - } - }, - - hr : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection(((cursor.ch !== 0) ? "\n\n" : "\n") + "------------\n\n"); - }, - - tex : function() { - if (!this.settings.tex) - { - alert("settings.tex === false"); - return this; - } - - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("$$" + selection + "$$"); - - if(selection === "") { - cm.setCursor(cursor.line, cursor.ch + 2); - } - }, - - link : function() { - this.executePlugin("linkDialog", "link-dialog/link-dialog"); - }, - - "reference-link" : function() { - this.executePlugin("referenceLinkDialog", "reference-link-dialog/reference-link-dialog"); - }, - - pagebreak : function() { - if (!this.settings.pageBreak) - { - alert("settings.pageBreak === false"); - return this; - } - - var cm = this.cm; - var selection = cm.getSelection(); - - cm.replaceSelection("\r\n[========]\r\n"); - }, - - image : function() { - this.executePlugin("imageDialog", "image-dialog/image-dialog"); - }, - - code : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection("`" + selection + "`"); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); - } - }, - - "code-block" : function() { - this.executePlugin("codeBlockDialog", "code-block-dialog/code-block-dialog"); - }, - - "preformatted-text" : function() { - this.executePlugin("preformattedTextDialog", "preformatted-text-dialog/preformatted-text-dialog"); - }, - - table : function() { - this.executePlugin("tableDialog", "table-dialog/table-dialog"); - }, - - datetime : function() { - var cm = this.cm; - var selection = cm.getSelection(); - var date = new Date(); - var langName = this.settings.lang.name; - var datefmt = editormd.dateFormat() + " " + editormd.dateFormat((langName === "zh-cn" || langName === "zh-tw") ? "cn-week-day" : "week-day"); - - cm.replaceSelection(datefmt); - }, - - emoji : function() { - this.executePlugin("emojiDialog", "emoji-dialog/emoji-dialog"); - }, - - "html-entities" : function() { - this.executePlugin("htmlEntitiesDialog", "html-entities-dialog/html-entities-dialog"); - }, - - "goto-line" : function() { - this.executePlugin("gotoLineDialog", "goto-line-dialog/goto-line-dialog"); - }, - - watch : function() { - this[this.settings.watch ? "unwatch" : "watch"](); - }, - - preview : function() { - this.previewing(); - }, - - fullscreen : function() { - this.fullscreen(); - }, - - clear : function() { - this.clear(); - }, - - search : function() { - this.search(); - }, - - help : function() { - this.executePlugin("helpDialog", "help-dialog/help-dialog"); - }, - - info : function() { - this.showInfoDialog(); - } - }; - - var isMac = navigator.platform.toUpperCase().indexOf('MAC')>=0; - var key = isMac ? "Cmd" : "Ctrl"; - - editormd.keyMaps = { - [key + "-1"] : "h1", - [key + "-2"] : "h2", - [key + "-3"] : "h3", - [key + "-4"] : "h4", - [key + "-5"] : "h5", - [key + "-6"] : "h6", - [key + "-B"] : "bold", // if this is string == editormd.toolbarHandlers.xxxx - [key + "-D"] : "datetime", - - [key + "Ctrl-E"] : function() { // emoji - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (!this.settings.emoji) - { - alert("Error: settings.emoji == false"); - return ; - } - - cm.replaceSelection(":" + selection + ":"); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); - } - }, - [key + "-Alt-G"] : "goto-line", - [key + "-H"] : "hr", - [key + "-I"] : "italic", - [key + "-K"] : "code", - - "Ctrl-L" : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - var title = (selection === "") ? "" : " \""+selection+"\""; - - cm.replaceSelection("[" + selection + "]("+title+")"); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); - } - }, - [key + "-U"] : "list-ul", - - "Shift-Ctrl-A" : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - if (!this.settings.atLink) - { - alert("Error: settings.atLink == false"); - return ; - } - - cm.replaceSelection("@" + selection); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 1); - } - }, - - ["Shift" + key + "-C"] : "code", - ["Shift" + key + "Q"] : "quote", - ["Shift" + key + "S"] : "del", - ["Shift" + key + "K"] : "tex", // KaTeX - - "Shift-Alt-C" : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - cm.replaceSelection(["```", selection, "```"].join("\n")); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 3); - } - }, - - ["Shift-" + key + "-Alt-C"] : "code-block", - ["Shift-" + key + "-H"] : "html-entities", - "Shift-Alt-H" : "help", - ["Shift-" + key + "-E"] : "emoji", - ["Shift-" + key + "-U"] : "uppercase", - "Shift-Alt-U" : "ucwords", - ["Shift-" + key + "-Alt-U"] : "ucfirst", - "Shift-Alt-L" : "lowercase", - - ["Shift-" + key + "-I"] : function() { - var cm = this.cm; - var cursor = cm.getCursor(); - var selection = cm.getSelection(); - - var title = (selection === "") ? "" : " \""+selection+"\""; - - cm.replaceSelection("![" + selection + "]("+title+")"); - - if (selection === "") { - cm.setCursor(cursor.line, cursor.ch + 4); - } - }, - - ["Shift-" + key + "-Alt-I"] : "image", - ["Shift-" + key + "-L"] : "link", - ["Shift-" + key + "-O"] : "list-ol", - ["Shift-" + key + "-P"] : "preformatted-text", - ["Shift-" + key + "-T"] : "table", - "Shift-Alt-P" : "pagebreak", - "F9" : "watch", - "F10" : "preview", - "F11" : "fullscreen", - }; - - /** - * 清除字符串两边的空格 - * Clear the space of strings both sides. - * - * @param {String} str string - * @returns {String} trimed string - */ - - var trim = function(str) { - return (!String.prototype.trim) ? str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "") : str.trim(); - }; - - editormd.trim = trim; - - /** - * 所有单词首字母大写 - * Words first to uppercase - * - * @param {String} str string - * @returns {String} string - */ - - var ucwords = function (str) { - return str.toLowerCase().replace(/\b(\w)|\s(\w)/g, function($1) { - return $1.toUpperCase(); - }); - }; - - editormd.ucwords = editormd.wordsFirstUpperCase = ucwords; - - /** - * 字符串首字母大写 - * Only string first char to uppercase - * - * @param {String} str string - * @returns {String} string - */ - - var firstUpperCase = function(str) { - return str.toLowerCase().replace(/\b(\w)/, function($1){ - return $1.toUpperCase(); - }); - }; - - var ucfirst = firstUpperCase; - - editormd.firstUpperCase = editormd.ucfirst = firstUpperCase; - - editormd.urls = { - atLinkBase : "https://github.com/" - }; - - editormd.regexs = { - atLink : /@(\w+)/g, - email : /(\w+)@(\w+)\.(\w+)\.?(\w+)?/g, - emailLink : /(mailto:)?([\w\.\_]+)@(\w+)\.(\w+)\.?(\w+)?/g, - emoji : /:([\w\+-]+):/g, - emojiDatetime : /(\d{1,2}:\d{1,2}:\d{1,2})/g, - twemoji : /:(tw-([\w]+)-?(\w+)?):/g, - fontAwesome : /:(fa-([\w]+)(-(\w+)){0,}):/g, - editormdLogo : /:(editormd-logo-?(\w+)?):/g, - pageBreak : /^\[[=]{8,}\]$/ - }; - - // Emoji graphics files url path - editormd.emoji = { - path : "http://www.emoji-cheat-sheet.com/graphics/emojis/", - ext : ".png" - }; - - // Twitter Emoji (Twemoji) graphics files url path - editormd.twemoji = { - path : "http://twemoji.maxcdn.com/36x36/", - ext : ".png" - }; - - /** - * 自定义marked的解析器 - * Custom Marked renderer rules - * - * @param {Array} markdownToC 传入用于接收TOC的数组 - * @returns {Renderer} markedRenderer 返回marked的Renderer自定义对象 - */ - - editormd.markedRenderer = function(markdownToC, options) { - var defaults = { - toc : true, // Table of contents - tocm : false, - tocStartLevel : 1, // Said from H1 to create ToC - pageBreak : true, - atLink : true, // for @link - emailLink : true, // for mail address auto link - taskList : false, // Enable Github Flavored Markdown task lists - emoji : false, // :emoji: , Support Twemoji, fontAwesome, Editor.md logo emojis. - tex : false, // TeX(LaTeX), based on KaTeX - flowChart : false, // flowChart.js only support IE9+ - sequenceDiagram : false, // sequenceDiagram.js only support IE9+ - }; - - var settings = $.extend(defaults, options || {}); - var marked = editormd.$marked; - var markedRenderer = new marked.Renderer(); - markdownToC = markdownToC || []; - - var regexs = editormd.regexs; - var atLinkReg = regexs.atLink; - var emojiReg = regexs.emoji; - var emailReg = regexs.email; - var emailLinkReg = regexs.emailLink; - var twemojiReg = regexs.twemoji; - var faIconReg = regexs.fontAwesome; - var editormdLogoReg = regexs.editormdLogo; - var pageBreakReg = regexs.pageBreak; - - markedRenderer.emoji = function(text) { - - text = text.replace(editormd.regexs.emojiDatetime, function($1) { - return $1.replace(/:/g, ":"); - }); - - var matchs = text.match(emojiReg); - - if (!matchs || !settings.emoji) { - return text; - } - - for (var i = 0, len = matchs.length; i < len; i++) - { - if (matchs[i] === ":+1:") { - matchs[i] = ":\\+1:"; - } - - text = text.replace(new RegExp(matchs[i]), function($1, $2){ - var faMatchs = $1.match(faIconReg); - var name = $1.replace(/:/g, ""); - - if (faMatchs) - { - for (var fa = 0, len1 = faMatchs.length; fa < len1; fa++) - { - var faName = faMatchs[fa].replace(/:/g, ""); - - return ""; - } - } - else - { - var emdlogoMathcs = $1.match(editormdLogoReg); - var twemojiMatchs = $1.match(twemojiReg); - - if (emdlogoMathcs) - { - for (var x = 0, len2 = emdlogoMathcs.length; x < len2; x++) - { - var logoName = emdlogoMathcs[x].replace(/:/g, ""); - return ""; - } - } - else if (twemojiMatchs) - { - for (var t = 0, len3 = twemojiMatchs.length; t < len3; t++) - { - var twe = twemojiMatchs[t].replace(/:/g, "").replace("tw-", ""); - return "\"twemoji-""; - } - } - else - { - var src = (name === "+1") ? "plus1" : name; - src = (src === "black_large_square") ? "black_square" : src; - src = (src === "moon") ? "waxing_gibbous_moon" : src; - - return "\":""; - } - } - }); - } - - return text; - }; - - markedRenderer.atLink = function(text) { - - if (atLinkReg.test(text)) - { - if (settings.atLink) - { - text = text.replace(emailReg, function($1, $2, $3, $4) { - return $1.replace(/@/g, "_#_@_#_"); - }); - - text = text.replace(atLinkReg, function($1, $2) { - return "" + $1 + ""; - }).replace(/_#_@_#_/g, "@"); - } - - if (settings.emailLink) - { - text = text.replace(emailLinkReg, function($1, $2, $3, $4, $5) { - return (!$2 && $.inArray($5, "jpg|jpeg|png|gif|webp|ico|icon|pdf".split("|")) < 0) ? ""+$1+"" : $1; - }); - } - - return text; - } - - return text; - }; - - markedRenderer.link = function (href, title, text) { - - if (this.options.sanitize) { - try { - var prot = decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase(); - } catch(e) { - return ""; - } - - if (prot.indexOf("javascript:") === 0) { - return ""; - } - } - - var out = "" + text.replace(/@/g, "@") + ""; - } - - if (title) { - out += " title=\"" + title + "\""; - } - - out += ">" + text + ""; - - return out; - }; - - markedRenderer.heading = function(text, level, raw) { - - var linkText = text; - var hasLinkReg = /\s*\]*)\>(.*)\<\/a\>\s*/; - var getLinkTextReg = /\s*\]+)\>([^\>]*)\<\/a\>\s*/g; - - if (hasLinkReg.test(text)) - { - var tempText = []; - text = text.split(/\]+)\>([^\>]*)\<\/a\>/); - - for (var i = 0, len = text.length; i < len; i++) - { - tempText.push(text[i].replace(/\s*href\=\"(.*)\"\s*/g, "")); - } - - text = tempText.join(" "); - } - - text = trim(text); - - var escapedText = text.toLowerCase().replace(/[^\w]+/g, "-"); - var toc = { - text : text, - level : level, - slug : escapedText - }; - - var isChinese = /^[\u4e00-\u9fa5]+$/.test(text); - var id = (isChinese) ? escape(text).replace(/\%/g, "") : text.toLowerCase().replace(/[^\w]+/g, "-"); - - markdownToC.push(toc); - - var headingHTML = ""; - - headingHTML += ""; - headingHTML += ""; - headingHTML += (hasLinkReg) ? this.atLink(this.emoji(linkText)) : this.atLink(this.emoji(text)); - headingHTML += ""; - - return headingHTML; - }; - - markedRenderer.pageBreak = function(text) { - if (pageBreakReg.test(text) && settings.pageBreak) - { - text = "
                      "; - } - - return text; - }; - - markedRenderer.paragraph = function(text) { - var isTeXInline = /\$\$(.*)\$\$/g.test(text); - var isTeXLine = /^\$\$(.*)\$\$$/.test(text); - var isTeXAddClass = (isTeXLine) ? " class=\"" + editormd.classNames.tex + "\"" : ""; - var isToC = (settings.tocm) ? /^(\[TOC\]|\[TOCM\])$/.test(text) : /^\[TOC\]$/.test(text); - var isToCMenu = /^\[TOCM\]$/.test(text); - - if (!isTeXLine && isTeXInline) - { - text = text.replace(/(\$\$([^\$]*)\$\$)+/g, function($1, $2) { - return "" + $2.replace(/\$/g, "") + ""; - }); - } - else - { - text = (isTeXLine) ? text.replace(/\$/g, "") : text; - } - - var tocHTML = "
                      " + text + "
                      "; - - return (isToC) ? ( (isToCMenu) ? "
                      " + tocHTML + "

                      " : tocHTML ) - : ( (pageBreakReg.test(text)) ? this.pageBreak(text) : "" + this.atLink(this.emoji(text)) + "

                      \n" ); - }; - - markedRenderer.code = function (code, lang, escaped) { - - if (lang === "seq" || lang === "sequence") - { - return "
                      " + code + "
                      "; - } - else if ( lang === "flow") - { - return "
                      " + code + "
                      "; - } - else if ( lang === "math" || lang === "latex" || lang === "katex") - { - return "

                      " + code + "

                      "; - } - else - { - - return marked.Renderer.prototype.code.apply(this, arguments); - } - }; - - markedRenderer.tablecell = function(content, flags) { - var type = (flags.header) ? "th" : "td"; - var tag = (flags.align) ? "<" + type +" style=\"text-align:" + flags.align + "\">" : "<" + type + ">"; - - return tag + this.atLink(this.emoji(content)) + "\n"; - }; - - markedRenderer.listitem = function(text) { - if (settings.taskList && /^\s*\[[x\s]\]\s*/.test(text)) - { - text = text.replace(/^\s*\[\s\]\s*/, " ") - .replace(/^\s*\[x\]\s*/, " "); - - return "
                    • " + this.atLink(this.emoji(text)) + "
                    • "; - } - else - { - return "
                    • " + this.atLink(this.emoji(text)) + "
                    • "; - } - }; - - return markedRenderer; - }; - - /** - * - * 生成TOC(Table of Contents) - * Creating ToC (Table of Contents) - * - * @param {Array} toc 从marked获取的TOC数组列表 - * @param {Element} container 插入TOC的容器元素 - * @param {Integer} startLevel Hx 起始层级 - * @returns {Object} tocContainer 返回ToC列表容器层的jQuery对象元素 - */ - - editormd.markdownToCRenderer = function(toc, container, tocDropdown, startLevel) { - - var html = ""; - var lastLevel = 0; - var classPrefix = this.classPrefix; - - startLevel = startLevel || 1; - - for (var i = 0, len = toc.length; i < len; i++) - { - var text = toc[i].text; - var level = toc[i].level; - - if (level < startLevel) { - continue; - } - - if (level > lastLevel) - { - html += ""; - } - else if (level < lastLevel) - { - html += (new Array(lastLevel - level + 2)).join(""); - } - else - { - html += ""; - } - - html += "
                    • " + text + "
                        "; - lastLevel = level; - } - - var tocContainer = container.find(".markdown-toc"); - - if ((tocContainer.length < 1 && container.attr("previewContainer") === "false")) - { - var tocHTML = "
                        "; - - tocHTML = (tocDropdown) ? "
                        " + tocHTML + "
                        " : tocHTML; - - container.html(tocHTML); - - tocContainer = container.find(".markdown-toc"); - } - - if (tocDropdown) - { - tocContainer.wrap("

                        "); - } - - tocContainer.html("
                          ").children(".markdown-toc-list").html(html.replace(/\r?\n?\\<\/ul\>/g, "")); - - return tocContainer; - }; - - /** - * - * 生成TOC下拉菜单 - * Creating ToC dropdown menu - * - * @param {Object} container 插入TOC的容器jQuery对象元素 - * @param {String} tocTitle ToC title - * @returns {Object} return toc-menu object - */ - - editormd.tocDropdownMenu = function(container, tocTitle) { - - tocTitle = tocTitle || "Table of Contents"; - - var zindex = 400; - var tocMenus = container.find("." + this.classPrefix + "toc-menu"); - - tocMenus.each(function() { - var $this = $(this); - var toc = $this.children(".markdown-toc"); - var icon = ""; - var btn = "" + icon + tocTitle + ""; - var menu = toc.children("ul"); - var list = menu.find("li"); - - toc.append(btn); - - list.first().before("
                        • " + tocTitle + " " + icon + "

                        • "); - - $this.mouseover(function(){ - menu.show(); - - list.each(function(){ - var li = $(this); - var ul = li.children("ul"); - - if (ul.html() === "") - { - ul.remove(); - } - - if (ul.length > 0 && ul.html() !== "") - { - var firstA = li.children("a").first(); - - if (firstA.children(".fa").length < 1) - { - firstA.append( $(icon).css({ float:"right", paddingTop:"4px" }) ); - } - } - - li.mouseover(function(){ - ul.css("z-index", zindex).show(); - zindex += 1; - }).mouseleave(function(){ - ul.hide(); - }); - }); - }).mouseleave(function(){ - menu.hide(); - }); - }); - - return tocMenus; - }; - - /** - * 简单地过滤指定的HTML标签 - * Filter custom html tags - * - * @param {String} html 要过滤HTML - * @param {String} filters 要过滤的标签 - * @returns {String} html 返回过滤的HTML - */ - - editormd.filterHTMLTags = function(html, filters) { - - if (typeof html !== "string") { - html = new String(html); - } - - if (typeof filters !== "string") { - return html; - } - - var expression = filters.split("|"); - var filterTags = expression[0].split(","); - var attrs = expression[1]; - - for (var i = 0, len = filterTags.length; i < len; i++) - { - var tag = filterTags[i]; - - html = html.replace(new RegExp("\<\s*" + tag + "\s*([^\>]*)\>([^\>]*)\<\s*\/" + tag + "\s*\>", "igm"), ""); - } - - //return html; - - if (typeof attrs !== "undefined") - { - var htmlTagRegex = /\<(\w+)\s*([^\>]*)\>([^\>]*)\<\/(\w+)\>/ig; - - if (attrs === "*") - { - html = html.replace(htmlTagRegex, function($1, $2, $3, $4, $5) { - return "<" + $2 + ">" + $4 + ""; - }); - } - else if (attrs === "on*") - { - html = html.replace(htmlTagRegex, function($1, $2, $3, $4, $5) { - var el = $("<" + $2 + ">" + $4 + ""); - var _attrs = $($1)[0].attributes; - var $attrs = {}; - - $.each(_attrs, function(i, e) { - if (e.nodeName !== '"') $attrs[e.nodeName] = e.nodeValue; - }); - - $.each($attrs, function(i) { - if (i.indexOf("on") === 0) { - delete $attrs[i]; - } - }); - - el.attr($attrs); - - var text = (typeof el[1] !== "undefined") ? $(el[1]).text() : ""; - - return el[0].outerHTML + text; - }); - } - else - { - html = html.replace(htmlTagRegex, function($1, $2, $3, $4) { - var filterAttrs = attrs.split(","); - var el = $($1); - el.html($4); - - $.each(filterAttrs, function(i) { - el.attr(filterAttrs[i], null); - }); - - return el[0].outerHTML; - }); - } - } - - return html; - }; - - /** - * 将Markdown文档解析为HTML用于前台显示 - * Parse Markdown to HTML for Font-end preview. - * - * @param {String} id 用于显示HTML的对象ID - * @param {Object} [options={}] 配置选项,可选 - * @returns {Object} div 返回jQuery对象元素 - */ - - editormd.markdownToHTML = function(id, options) { - var defaults = { - gfm : true, - toc : true, - tocm : false, - tocStartLevel : 1, - tocTitle : "目录", - tocDropdown : false, - tocContainer : "", - markdown : "", - markdownSourceCode : false, - htmlDecode : false, - autoLoadKaTeX : true, - pageBreak : true, - atLink : true, // for @link - emailLink : true, // for mail address auto link - tex : false, - taskList : false, // Github Flavored Markdown task lists - emoji : false, - flowChart : false, - sequenceDiagram : false, - previewCodeHighlight : true - }; - - editormd.$marked = marked; - - var div = $("#" + id); - var settings = div.settings = $.extend(true, defaults, options || {}); - var saveTo = div.find("textarea"); - - if (saveTo.length < 1) - { - div.append(""); - saveTo = div.find("textarea"); - } - - var markdownDoc = (settings.markdown === "") ? saveTo.val() : settings.markdown; - var markdownToC = []; - - var rendererOptions = { - toc : settings.toc, - tocm : settings.tocm, - tocStartLevel : settings.tocStartLevel, - taskList : settings.taskList, - emoji : settings.emoji, - tex : settings.tex, - pageBreak : settings.pageBreak, - atLink : settings.atLink, // for @link - emailLink : settings.emailLink, // for mail address auto link - flowChart : settings.flowChart, - sequenceDiagram : settings.sequenceDiagram, - previewCodeHighlight : settings.previewCodeHighlight, - }; - - var markedOptions = { - renderer : editormd.markedRenderer(markdownToC, rendererOptions), - gfm : settings.gfm, - tables : true, - breaks : true, - pedantic : false, - sanitize : (settings.htmlDecode) ? false : true, // 是否忽略HTML标签,即是否开启HTML标签解析,为了安全性,默认不开启 - smartLists : true, - smartypants : true - }; - - markdownDoc = new String(markdownDoc); - - var markdownParsed = marked(markdownDoc, markedOptions); - - markdownParsed = editormd.filterHTMLTags(markdownParsed, settings.htmlDecode); - - if (settings.markdownSourceCode) { - saveTo.text(markdownDoc); - } else { - saveTo.remove(); - } - - div.addClass("markdown-body " + this.classPrefix + "html-preview").append(markdownParsed); - - var tocContainer = (settings.tocContainer !== "") ? $(settings.tocContainer) : div; - - if (settings.tocContainer !== "") - { - tocContainer.attr("previewContainer", false); - } - - if (settings.toc) - { - div.tocContainer = this.markdownToCRenderer(markdownToC, tocContainer, settings.tocDropdown, settings.tocStartLevel); - - if (settings.tocDropdown || div.find("." + this.classPrefix + "toc-menu").length > 0) - { - this.tocDropdownMenu(div, settings.tocTitle); - } - - if (settings.tocContainer !== "") - { - div.find(".editormd-toc-menu, .editormd-markdown-toc").remove(); - } - } - - if (settings.previewCodeHighlight) - { - div.find("pre").addClass("prettyprint linenums"); - prettyPrint(); - } - - if (!editormd.isIE8) - { - if (settings.flowChart) { - div.find(".flowchart").flowChart(); - } - - if (settings.sequenceDiagram) { - div.find(".sequence-diagram").sequenceDiagram({theme: "simple"}); - } - } - - if (settings.tex) - { - var katexHandle = function() { - div.find("." + editormd.classNames.tex).each(function(){ - var tex = $(this); - katex.render(tex.html().replace(/</g, "<").replace(/>/g, ">"), tex[0]); - tex.find(".katex").css("font-size", "1.6em"); - }); - }; - - if (settings.autoLoadKaTeX && !editormd.$katex && !editormd.kaTeXLoaded) - { - this.loadKaTeX(function() { - editormd.$katex = katex; - editormd.kaTeXLoaded = true; - katexHandle(); - }); - } - else - { - katexHandle(); - } - } - - div.getMarkdown = function() { - return saveTo.val(); - }; - - return div; - }; - - // Editor.md themes, change toolbar themes etc. - // added @1.5.0 - editormd.themes = ["default", "dark"]; - - // Preview area themes - // added @1.5.0 - editormd.previewThemes = ["default", "dark"]; - - // CodeMirror / editor area themes - // @1.5.0 rename -> editorThemes, old version -> themes - editormd.editorThemes = [ - "default", "3024-day", "3024-night", - "ambiance", "ambiance-mobile", - "base16-dark", "base16-light", "blackboard", - "cobalt", - "eclipse", "elegant", "erlang-dark", - "lesser-dark", - "mbo", "mdn-like", "midnight", "monokai", - "neat", "neo", "night", - "paraiso-dark", "paraiso-light", "pastel-on-dark", - "rubyblue", - "solarized", - "the-matrix", "tomorrow-night-eighties", "twilight", - "vibrant-ink", - "xq-dark", "xq-light" - ]; - - editormd.loadPlugins = {}; - - editormd.loadFiles = { - js : [], - css : [], - plugin : [] - }; - - /** - * 动态加载Editor.md插件,但不立即执行 - * Load editor.md plugins - * - * @param {String} fileName 插件文件路径 - * @param {Function} [callback=function()] 加载成功后执行的回调函数 - * @param {String} [into="head"] 嵌入页面的位置 - */ - - editormd.loadPlugin = function(fileName, callback, into) { - callback = callback || function() {}; - - this.loadScript(fileName, function() { - editormd.loadFiles.plugin.push(fileName); - callback(); - }, into); - }; - - /** - * 动态加载CSS文件的方法 - * Load css file method - * - * @param {String} fileName CSS文件名 - * @param {Function} [callback=function()] 加载成功后执行的回调函数 - * @param {String} [into="head"] 嵌入页面的位置 - */ - - editormd.loadCSS = function(fileName, callback, into) { - into = into || "head"; - callback = callback || function() {}; - - var css = document.createElement("link"); - css.type = "text/css"; - css.rel = "stylesheet"; - css.onload = css.onreadystatechange = function() { - editormd.loadFiles.css.push(fileName); - callback(); - }; - - css.href = fileName + ".css"; - - if(into === "head") { - document.getElementsByTagName("head")[0].appendChild(css); - } else { - document.body.appendChild(css); - } - }; - - editormd.isIE = (navigator.appName == "Microsoft Internet Explorer"); - editormd.isIE8 = (editormd.isIE && navigator.appVersion.match(/8./i) == "8."); - - /** - * 动态加载JS文件的方法 - * Load javascript file method - * - * @param {String} fileName JS文件名 - * @param {Function} [callback=function()] 加载成功后执行的回调函数 - * @param {String} [into="head"] 嵌入页面的位置 - */ - - editormd.loadScript = function(fileName, callback, into) { - - into = into || "head"; - callback = callback || function() {}; - - var script = null; - script = document.createElement("script"); - script.id = fileName.replace(/[\./]+/g, "-"); - script.type = "text/javascript"; - script.src = fileName + ".js"; - - if (editormd.isIE8) - { - script.onreadystatechange = function() { - if(script.readyState) - { - if (script.readyState === "loaded" || script.readyState === "complete") - { - script.onreadystatechange = null; - editormd.loadFiles.js.push(fileName); - callback(); - } - } - }; - } - else - { - script.onload = function() { - editormd.loadFiles.js.push(fileName); - callback(); - }; - } - - if (into === "head") { - document.getElementsByTagName("head")[0].appendChild(script); - } else { - document.body.appendChild(script); - } - }; - - // 使用国外的CDN,加载速度有时会很慢,或者自定义URL - // You can custom KaTeX load url. - editormd.katexURL = { - css : "//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.3.0/katex.min", - js : "//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.3.0/katex.min" - }; - - editormd.kaTeXLoaded = false; - - /** - * 加载KaTeX文件 - * load KaTeX files - * - * @param {Function} [callback=function()] 加载成功后执行的回调函数 - */ - - editormd.loadKaTeX = function (callback) { - editormd.loadCSS(editormd.katexURL.css, function(){ - editormd.loadScript(editormd.katexURL.js, callback || function(){}); - }); - }; - - /** - * 锁屏 - * lock screen - * - * @param {Boolean} lock Boolean 布尔值,是否锁屏 - * @returns {void} - */ - - editormd.lockScreen = function(lock) { - $("html,body").css("overflow", (lock) ? "hidden" : ""); - }; - - /** - * 动态创建对话框 - * Creating custom dialogs - * - * @param {Object} options 配置项键值对 Key/Value - * @returns {dialog} 返回创建的dialog的jQuery实例对象 - */ - - editormd.createDialog = function(options) { - var defaults = { - name : "", - width : 420, - height: 240, - title : "", - drag : true, - closed : true, - content : "", - mask : true, - maskStyle : { - backgroundColor : "#fff", - opacity : 0.1 - }, - lockScreen : true, - footer : true, - buttons : false - }; - - options = $.extend(true, defaults, options); - - var $this = this; - var editor = this.editor; - var classPrefix = editormd.classPrefix; - var guid = (new Date()).getTime(); - var dialogName = ( (options.name === "") ? classPrefix + "dialog-" + guid : options.name); - var mouseOrTouch = editormd.mouseOrTouch; - - var html = "
                          "; - - if (options.title !== "") - { - html += "
                          "; - html += "" + options.title + ""; - html += "
                          "; - } - - if (options.closed) - { - html += ""; - } - - html += "
                          " + options.content; - - if (options.footer || typeof options.footer === "string") - { - html += "
                          " + ( (typeof options.footer === "boolean") ? "" : options.footer) + "
                          "; - } - - html += "
                          "; - - html += "
                          "; - html += "
                          "; - html += "
                          "; - - editor.append(html); - - var dialog = editor.find("." + dialogName); - - dialog.lockScreen = function(lock) { - if (options.lockScreen) - { - $("html,body").css("overflow", (lock) ? "hidden" : ""); - $this.resize(); - } - - return dialog; - }; - - dialog.showMask = function() { - if (options.mask) - { - editor.find("." + classPrefix + "mask").css(options.maskStyle).css("z-index", editormd.dialogZindex - 1).show(); - } - return dialog; - }; - - dialog.hideMask = function() { - if (options.mask) - { - editor.find("." + classPrefix + "mask").hide(); - } - - return dialog; - }; - - dialog.loading = function(show) { - var loading = dialog.find("." + classPrefix + "dialog-mask"); - loading[(show) ? "show" : "hide"](); - - return dialog; - }; - - dialog.lockScreen(true).showMask(); - - dialog.show().css({ - zIndex : editormd.dialogZindex, - border : (editormd.isIE8) ? "1px solid #ddd" : "", - width : (typeof options.width === "number") ? options.width + "px" : options.width, - height : (typeof options.height === "number") ? options.height + "px" : options.height - }); - - var dialogPosition = function(){ - dialog.css({ - top : ($(window).height() - dialog.height()) / 2 + "px", - left : ($(window).width() - dialog.width()) / 2 + "px" - }); - }; - - dialogPosition(); - - $(window).resize(dialogPosition); - - dialog.children("." + classPrefix + "dialog-close").bind(mouseOrTouch("click", "touchend"), function() { - dialog.hide().lockScreen(false).hideMask(); - }); - - if (typeof options.buttons === "object") - { - var footer = dialog.footer = dialog.find("." + classPrefix + "dialog-footer"); - - for (var key in options.buttons) - { - var btn = options.buttons[key]; - var btnClassName = classPrefix + key + "-btn"; - - footer.append(""); - btn[1] = $.proxy(btn[1], dialog); - footer.children("." + btnClassName).bind(mouseOrTouch("click", "touchend"), btn[1]); - } - } - - if (options.title !== "" && options.drag) - { - var posX, posY; - var dialogHeader = dialog.children("." + classPrefix + "dialog-header"); - - if (!options.mask) { - dialogHeader.bind(mouseOrTouch("click", "touchend"), function(){ - editormd.dialogZindex += 2; - dialog.css("z-index", editormd.dialogZindex); - }); - } - - dialogHeader.mousedown(function(e) { - e = e || window.event; //IE - posX = e.clientX - parseInt(dialog[0].style.left); - posY = e.clientY - parseInt(dialog[0].style.top); - - document.onmousemove = moveAction; - }); - - var userCanSelect = function (obj) { - obj.removeClass(classPrefix + "user-unselect").off("selectstart"); - }; - - var userUnselect = function (obj) { - obj.addClass(classPrefix + "user-unselect").on("selectstart", function(event) { // selectstart for IE - return false; - }); - }; - - var moveAction = function (e) { - e = e || window.event; //IE - - var left, top, nowLeft = parseInt(dialog[0].style.left), nowTop = parseInt(dialog[0].style.top); - - if( nowLeft >= 0 ) { - if( nowLeft + dialog.width() <= $(window).width()) { - left = e.clientX - posX; - } else { - left = $(window).width() - dialog.width(); - document.onmousemove = null; - } - } else { - left = 0; - document.onmousemove = null; - } - - if( nowTop >= 0 ) { - top = e.clientY - posY; - } else { - top = 0; - document.onmousemove = null; - } - - - document.onselectstart = function() { - return false; - }; - - userUnselect($("body")); - userUnselect(dialog); - dialog[0].style.left = left + "px"; - dialog[0].style.top = top + "px"; - }; - - document.onmouseup = function() { - userCanSelect($("body")); - userCanSelect(dialog); - - document.onselectstart = null; - document.onmousemove = null; - }; - - dialogHeader.touchDraggable = function() { - var offset = null; - var start = function(e) { - var orig = e.originalEvent; - var pos = $(this).parent().position(); - - offset = { - x : orig.changedTouches[0].pageX - pos.left, - y : orig.changedTouches[0].pageY - pos.top - }; - }; - - var move = function(e) { - e.preventDefault(); - var orig = e.originalEvent; - - $(this).parent().css({ - top : orig.changedTouches[0].pageY - offset.y, - left : orig.changedTouches[0].pageX - offset.x - }); - }; - - this.bind("touchstart", start).bind("touchmove", move); - }; - - dialogHeader.touchDraggable(); - } - - editormd.dialogZindex += 2; - - return dialog; - }; - - /** - * 鼠标和触摸事件的判断/选择方法 - * MouseEvent or TouchEvent type switch - * - * @param {String} [mouseEventType="click"] 供选择的鼠标事件 - * @param {String} [touchEventType="touchend"] 供选择的触摸事件 - * @returns {String} EventType 返回事件类型名称 - */ - - editormd.mouseOrTouch = function(mouseEventType, touchEventType) { - mouseEventType = mouseEventType || "click"; - touchEventType = touchEventType || "touchend"; - - var eventType = mouseEventType; - - try { - document.createEvent("TouchEvent"); - eventType = touchEventType; - } catch(e) {} - - return eventType; - }; - - /** - * 日期时间的格式化方法 - * Datetime format method - * - * @param {String} [format=""] 日期时间的格式,类似PHP的格式 - * @returns {String} datefmt 返回格式化后的日期时间字符串 - */ - - editormd.dateFormat = function(format) { - format = format || ""; - - var addZero = function(d) { - return (d < 10) ? "0" + d : d; - }; - - var date = new Date(); - var year = date.getFullYear(); - var year2 = year.toString().slice(2, 4); - var month = addZero(date.getMonth() + 1); - var day = addZero(date.getDate()); - var weekDay = date.getDay(); - var hour = addZero(date.getHours()); - var min = addZero(date.getMinutes()); - var second = addZero(date.getSeconds()); - var ms = addZero(date.getMilliseconds()); - var datefmt = ""; - - var ymd = year2 + "-" + month + "-" + day; - var fymd = year + "-" + month + "-" + day; - var hms = hour + ":" + min + ":" + second; - - switch (format) - { - case "UNIX Time" : - datefmt = date.getTime(); - break; - - case "UTC" : - datefmt = date.toUTCString(); - break; - - case "yy" : - datefmt = year2; - break; - - case "year" : - case "yyyy" : - datefmt = year; - break; - - case "month" : - case "mm" : - datefmt = month; - break; - - case "cn-week-day" : - case "cn-wd" : - var cnWeekDays = ["日", "一", "二", "三", "四", "五", "六"]; - datefmt = "星期" + cnWeekDays[weekDay]; - break; - - case "week-day" : - case "wd" : - var weekDays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; - datefmt = weekDays[weekDay]; - break; - - case "day" : - case "dd" : - datefmt = day; - break; - - case "hour" : - case "hh" : - datefmt = hour; - break; - - case "min" : - case "ii" : - datefmt = min; - break; - - case "second" : - case "ss" : - datefmt = second; - break; - - case "ms" : - datefmt = ms; - break; - - case "yy-mm-dd" : - datefmt = ymd; - break; - - case "yyyy-mm-dd" : - datefmt = fymd; - break; - - case "yyyy-mm-dd h:i:s ms" : - case "full + ms" : - datefmt = fymd + " " + hms + " " + ms; - break; - - case "full" : - case "yyyy-mm-dd h:i:s" : - default: - datefmt = fymd + " " + hms; - break; - } - - return datefmt; - }; - - return editormd; - -})); diff --git a/src/main/resources/static/editor-md/tests/bootstrap-test.html b/src/main/resources/static/editor-md/tests/bootstrap-test.html deleted file mode 100644 index e5e0f68..0000000 --- a/src/main/resources/static/editor-md/tests/bootstrap-test.html +++ /dev/null @@ -1,63 +0,0 @@ - - - - - Bootstrap 兼容测试 - Editor.md tests - - - - - - - - - - -
                          -
                          -

                          Bootstrap 兼容测试

                          -
                          -
                          - -
                          -
                          - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/tests/codemirror-searchbox-test.html b/src/main/resources/static/editor-md/tests/codemirror-searchbox-test.html deleted file mode 100644 index 60102e6..0000000 --- a/src/main/resources/static/editor-md/tests/codemirror-searchbox-test.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - CodeMirror searchbox Test - - - - - - -
                          - -
                          - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/tests/codemirror-test.html b/src/main/resources/static/editor-md/tests/codemirror-test.html deleted file mode 100644 index 382993d..0000000 --- a/src/main/resources/static/editor-md/tests/codemirror-test.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - CodeMirror Test - - - - - - -
                          - -
                          - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/tests/css/bootstrap-theme.min.css b/src/main/resources/static/editor-md/tests/css/bootstrap-theme.min.css deleted file mode 100644 index cefa3d1..0000000 --- a/src/main/resources/static/editor-md/tests/css/bootstrap-theme.min.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! - * Bootstrap v3.3.4 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default:disabled,.btn-default[disabled]{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary:disabled,.btn-primary[disabled]{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success:disabled,.btn-success[disabled]{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info:disabled,.btn-info[disabled]{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning:disabled,.btn-warning[disabled]{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger:disabled,.btn-danger[disabled]{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} \ No newline at end of file diff --git a/src/main/resources/static/editor-md/tests/css/bootstrap.min.css b/src/main/resources/static/editor-md/tests/css/bootstrap.min.css deleted file mode 100644 index cd1c616..0000000 --- a/src/main/resources/static/editor-md/tests/css/bootstrap.min.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! - * Bootstrap v3.3.4 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - *//*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date],input[type=time],input[type=datetime-local],input[type=month]{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px \9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.form-group-sm .form-control{height:30px;line-height:30px}select[multiple].form-group-sm .form-control,textarea.form-group-sm .form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:5px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.form-group-lg .form-control{height:46px;line-height:46px}select[multiple].form-group-lg .form-control,textarea.form-group-lg .form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:10px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.33px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.active,.btn-default.focus,.btn-default:active,.btn-default:focus,.btn-default:hover,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.active,.btn-primary.focus,.btn-primary:active,.btn-primary:focus,.btn-primary:hover,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.active,.btn-success.focus,.btn-success:active,.btn-success:focus,.btn-success:hover,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.active,.btn-info.focus,.btn-info:active,.btn-info:focus,.btn-info:hover,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.active,.btn-warning.focus,.btn-warning:active,.btn-warning:focus,.btn-warning:hover,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.active,.btn-danger.focus,.btn-danger:active,.btn-danger:focus,.btn-danger:hover,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px solid}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px)and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px 15px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding:48px 0}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-weight:400;line-height:1.4;filter:alpha(opacity=0);opacity:0}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-weight:400;line-height:1.42857143;text-align:left;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000;perspective:1000}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;margin-top:-10px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px)and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px)and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px)and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px)and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px)and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px)and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px)and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px)and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px)and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px)and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} \ No newline at end of file diff --git a/src/main/resources/static/editor-md/tests/js/bootstrap.min.js b/src/main/resources/static/editor-md/tests/js/bootstrap.min.js deleted file mode 100644 index c8f82e5..0000000 --- a/src/main/resources/static/editor-md/tests/js/bootstrap.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Bootstrap v3.3.4 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ -if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.4",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.4",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active"));a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.4",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.4",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=c(d),f={relatedTarget:this};e.hasClass("open")&&(e.trigger(b=a.Event("hide.bs.dropdown",f)),b.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger("hidden.bs.dropdown",f)))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.4",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(this.options.viewport.selector||this.options.viewport),this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c&&c.$tip&&c.$tip.is(":visible")?void(c.hoverState="in"):(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.options.container?a(this.options.container):this.$element.parent(),p=this.getPosition(o);h="bottom"==h&&k.bottom+m>p.bottom?"top":"top"==h&&k.top-mp.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.width&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type)})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.4",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.4",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.4",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=a(document.body).height();"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/src/main/resources/static/editor-md/tests/js/searchbox.js b/src/main/resources/static/editor-md/tests/js/searchbox.js deleted file mode 100644 index ff95f56..0000000 --- a/src/main/resources/static/editor-md/tests/js/searchbox.js +++ /dev/null @@ -1,674 +0,0 @@ -/* global CodeMirror */ -/* global define */ - -(function(mod) { - 'use strict'; - - if (typeof exports === 'object' && typeof module === 'object') // CommonJS - mod(require('../../lib/codemirror')); - else if (typeof define === 'function' && define.amd) // AMD - define(['../../lib/codemirror'], mod); - else - mod(CodeMirror); -})(function(CodeMirror) { - 'use strict'; - - var Search; - - CodeMirror.defineOption('searchbox', false, function(cm) { - cm.addKeyMap({ - 'Ctrl-F': function() { - if (!Search) - Search = new SearchBox(cm); - - Search.show(); - }, - - 'Esc': function() { - if (Search && Search.isVisible()) { - Search.hide(); - - if (typeof event !== 'undefined') - event.stopPropagation(); - } - - return false; - }, - - 'Cmd-F': function() { - if (!Search) - Search = new SearchBox(cm); - - Search.show(); - } - }); - }); - - function SearchBox(cm) { - var self = this; - - init(); - - function initElements(el) { - self.searchBox = el.querySelector('.ace_search_form'); - self.replaceBox = el.querySelector('.ace_replace_form'); - self.searchOptions = el.querySelector('.ace_search_options'); - - self.regExpOption = el.querySelector('[action=toggleRegexpMode]'); - self.caseSensitiveOption = el.querySelector('[action=toggleCaseSensitive]'); - self.wholeWordOption = el.querySelector('[action=toggleWholeWords]'); - - self.searchInput = self.searchBox.querySelector('.ace_search_field'); - self.replaceInput = self.replaceBox.querySelector('.ace_search_field'); - } - - function init() { - var el = self.element = addHtml(); - - addStyle(); - - initElements(el); - bindKeys(); - - el.addEventListener('mousedown', function(e) { - setTimeout(function(){ - self.activeInput.focus(); - }, 0); - - e.stopPropagation(); - }); - - el.addEventListener('click', function(e) { - var t = e.target || e.srcElement; - var action = t.getAttribute('action'); - if (action && self[action]) - self[action](); - else if (self.commands[action]) - self.commands[action](); - - e.stopPropagation(); - }); - - self.searchInput.addEventListener('input', function() { - self.$onChange.schedule(20); - }); - - self.searchInput.addEventListener('focus', function() { - self.activeInput = self.searchInput; - }); - - self.replaceInput.addEventListener('focus', function() { - self.activeInput = self.replaceInput; - }); - - self.$onChange = delayedCall(function() { - self.find(false, false); - }); - } - - function bindKeys() { - var sb = self, - obj = { - 'Ctrl-F|Cmd-F|Ctrl-H|Command-Alt-F': function() { - var isReplace = sb.isReplace = !sb.isReplace; - sb.replaceBox.style.display = isReplace ? '' : 'none'; - sb[isReplace ? 'replaceInput' : 'searchInput'].focus(); - }, - 'Ctrl-G|Cmd-G': function() { - sb.findNext(); - }, - 'Ctrl-Shift-G|Cmd-Shift-G': function() { - sb.findPrev(); - }, - 'Esc': function() { - setTimeout(function() { sb.hide();}); - }, - 'Enter': function() { - if (sb.activeInput === sb.replaceInput) - sb.replace(); - sb.findNext(); - }, - 'Shift-Enter': function() { - if (sb.activeInput === sb.replaceInput) - sb.replace(); - sb.findPrev(); - }, - 'Alt-Enter': function() { - if (sb.activeInput === sb.replaceInput) - sb.replaceAll(); - sb.findAll(); - }, - 'Tab': function() { - if (self.activeInput === self.replaceInput) - self.searchInput.focus(); - else - self.replaceInput.focus(); - } - }; - - self.element.addEventListener('keydown', function(event) { - Object.keys(obj).some(function(name) { - var is = key(name, event); - - if (is) { - event.stopPropagation(); - event.preventDefault(); - obj[name](event); - } - - return is; - }); - }); - } - - this.commands = { - toggleRegexpMode: function() { - self.regExpOption.checked = !self.regExpOption.checked; - self.$syncOptions(); - }, - - toggleCaseSensitive: function() { - self.caseSensitiveOption.checked = !self.caseSensitiveOption.checked; - self.$syncOptions(); - }, - - toggleWholeWords: function() { - self.wholeWordOption.checked = !self.wholeWordOption.checked; - self.$syncOptions(); - } - }; - - this.$syncOptions = function() { - setCssClass(this.regExpOption, 'checked', this.regExpOption.checked); - setCssClass(this.wholeWordOption, 'checked', this.wholeWordOption.checked); - setCssClass(this.caseSensitiveOption, 'checked', this.caseSensitiveOption.checked); - - this.find(false, false); - }; - - this.find = function(skipCurrent, backwards) { - var value = this.searchInput.value, - options = { - skipCurrent: skipCurrent, - backwards: backwards, - regExp: this.regExpOption.checked, - caseSensitive: this.caseSensitiveOption.checked, - wholeWord: this.wholeWordOption.checked - }; - - find(value, options, function(searchCursor) { - var current = searchCursor.matches(false, searchCursor.from()); - cm.setSelection(current.from, current.to); - }); - }; - - function find(value, options, callback) { - var done, - noMatch, searchCursor, next, prev, matches, cursor, - position, - o = options, - is = true, - caseSensitive = o.caseSensitive, - regExp = o.regExp, - wholeWord = o.wholeWord; - - if (regExp || wholeWord) { - if (options.wholeWord) - value = '\\b' + value + '\\b'; - - value = RegExp(value); - } - - if (o.backwards) - position = o.skipCurrent ? 'from': 'to'; - else - position = o.skipCurrent ? 'to' : 'from'; - - cursor = cm.getCursor(position); - searchCursor = cm.getSearchCursor(value, cursor, !caseSensitive); - - next = searchCursor.findNext.bind(searchCursor), - prev = searchCursor.findPrevious.bind(searchCursor), - matches = searchCursor.matches.bind(searchCursor); - - if (o.backwards && !prev()) { - is = next(); - - if (is) { - cm.setCursor(cm.doc.size - 1, 0); - find(true, true, callback); - done = true; - } - } else if (!o.backwards && !next()) { - is = prev(); - - if (is) { - cm.setCursor(0, 0); - find(true, false, callback); - done = true; - } - } - - noMatch = !is && self.searchInput.value; - setCssClass(self.searchBox, 'ace_nomatch', noMatch); - - if (!done && is) - callback(searchCursor); - } - - this.findNext = function() { - this.find(true, false); - }; - - this.findPrev = function() { - this.find(true, true); - }; - - this.findAll = function(){ - /* - var range = this.editor.findAll(this.searchInput.value, { - regExp: this.regExpOption.checked, - caseSensitive: this.caseSensitiveOption.checked, - wholeWord: this.wholeWordOption.checked - }); - */ - - var value = this.searchInput.value, - range, - noMatch = !range && this.searchInput.value; - - setCssClass(this.searchBox, 'ace_nomatch', noMatch); - - if (cm.showMatchesOnScrollbar) - cm.showMatchesOnScrollbar(value); - - this.hide(); - }; - - this.replace = function() { - if (!cm.getOption('readOnly')) - cm.replaceSelection(this.replaceInput.value, 'start'); - }; - - this.replaceAndFindNext = function() { - if (!cm.getOption('readOnly')) { - this.editor.replace(this.replaceInput.value); - this.findNext(); - } - }; - - this.replaceAll = function() { - var value, - cursor, - from = this.searchInput.value, - to = this.replaceInput.value, - reg = RegExp(from, 'g'); - - if (!cm.getOption('readOnly')) { - cursor = cm.getCursor(); - value = cm.getValue(); - value = value.replace(reg, to); - - cm.setValue(value); - cm.setCursor(cursor); - } - }; - - this.hide = function() { - this.element.style.display = 'none'; - cm.focus(); - }; - - this.isVisible = function() { - var is = this.element.style.display === ''; - - return is; - }; - - this.show = function(value, isReplace) { - this.element.style.display = ''; - this.replaceBox.style.display = isReplace ? '' : 'none'; - - this.isReplace = isReplace; - - if (value) - this.searchInput.value = value; - - this.searchInput.focus(); - this.searchInput.select(); - }; - - this.isFocused = function() { - var el = document.activeElement; - return el === this.searchInput || el === this.replaceInput; - }; - - function addStyle() { - var style = document.createElement('style'), - css = [ - '.ace_search {', - 'background-color: #ddd;', - 'border: 1px solid #cbcbcb;', - 'border-top: 0 none;', - 'max-width: 325px;', - 'overflow: hidden;', - 'margin: 0;', - 'padding: 4px;', - 'padding-right: 6px;', - 'padding-bottom: 0;', - 'position: absolute;', - 'top: 0px;', - 'z-index: 99;', - 'white-space: normal;', - '}', - '.ace_search.left {', - 'border-left: 0 none;', - 'border-radius: 0px 0px 5px 0px;', - 'left: 0;', - '}', - '.ace_search.right {', - 'border-radius: 0px 0px 0px 5px;', - 'border-right: 0 none;', - 'right: 0;', - '}', - '.ace_search_form, .ace_replace_form {', - 'border-radius: 3px;', - 'border: 1px solid #cbcbcb;', - 'float: left;', - 'margin-bottom: 4px;', - 'overflow: hidden;', - '}', - '.ace_search_form.ace_nomatch {', - 'outline: 1px solid red;', - '}', - '.ace_search_field {', - 'background-color: white;', - 'border-right: 1px solid #cbcbcb;', - 'border: 0 none;', - '-webkit-box-sizing: border-box;', - '-moz-box-sizing: border-box;', - 'box-sizing: border-box;', - 'float: left;', - 'height: 22px;', - 'outline: 0;', - 'padding: 0 7px;', - 'width: 214px;', - 'margin: 0;', - '}', - '.ace_searchbtn,', - '.ace_replacebtn {', - 'background: #fff;', - 'border: 0 none;', - 'border-left: 1px solid #dcdcdc;', - 'cursor: pointer;', - 'float: left;', - 'height: 22px;', - 'margin: 0;', - 'padding: 0;', - 'position: relative;', - '}', - '.ace_searchbtn:last-child,', - '.ace_replacebtn:last-child {', - 'border-top-right-radius: 3px;', - 'border-bottom-right-radius: 3px;', - '}', - '.ace_searchbtn:disabled {', - 'background: none;', - 'cursor: default;', - '}', - '.ace_searchbtn {', - 'background-position: 50% 50%;', - 'background-repeat: no-repeat;', - 'width: 27px;', - '}', - '.ace_searchbtn.prev {', - 'background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiSU1NZUAC/6E0I0yACYskCpsJiySKIiY0SUZk40FyTEgCjGgKwTRAgAEAQJUIPCE+qfkAAAAASUVORK5CYII=); ', - '}', - '.ace_searchbtn.next {', - 'background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNpiTE1NZQCC/0DMyIAKwGJMUAYDEo3M/s+EpvM/mkKwCQxYjIeLMaELoLMBAgwAU7UJObTKsvAAAAAASUVORK5CYII=); ', - '}', - '.ace_searchbtn_close {', - 'background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;', - 'border-radius: 50%;', - 'border: 0 none;', - 'color: #656565;', - 'cursor: pointer;', - 'float: right;', - 'font: 16px/16px Arial;', - 'height: 14px;', - 'margin: 5px 1px 9px 5px;', - 'padding: 0;', - 'text-align: center;', - 'width: 14px;', - '}', - '.ace_searchbtn_close:hover {', - 'background-color: #656565;', - 'background-position: 50% 100%;', - 'color: white;', - '}', - '.ace_replacebtn.prev {', - 'width: 54px', - '}', - '.ace_replacebtn.next {', - 'width: 27px', - '}', - '.ace_button {', - 'margin-left: 2px;', - 'cursor: pointer;', - '-webkit-user-select: none;', - '-moz-user-select: none;', - '-o-user-select: none;', - '-ms-user-select: none;', - 'user-select: none;', - 'overflow: hidden;', - 'opacity: 0.7;', - 'border: 1px solid rgba(100,100,100,0.23);', - 'padding: 1px;', - '-moz-box-sizing: border-box;', - 'box-sizing: border-box;', - 'color: black;', - '}', - '.ace_button:hover {', - 'background-color: #eee;', - 'opacity:1;', - '}', - '.ace_button:active {', - 'background-color: #ddd;', - '}', - '.ace_button.checked {', - 'border-color: #3399ff;', - 'opacity:1;', - '}', - '.ace_search_options{', - 'margin-bottom: 3px;', - 'text-align: right;', - '-webkit-user-select: none;', - '-moz-user-select: none;', - '-o-user-select: none;', - '-ms-user-select: none;', - 'user-select: none;', - '}' - ].join(''); - - style.setAttribute('data-name', 'js-searchbox'); - - style.textContent = css; - - document.head.appendChild(style); - } - - function addHtml() { - var elSearch, - el = document.querySelector('.CodeMirror'), - div = document.createElement('div'), - html = [ - '' - ].join(''); - - div.innerHTML = html; - - elSearch = div.firstChild; - - el.parentElement.appendChild(elSearch); - - return elSearch; - } - } - - function setCssClass(el, className, condition) { - var list = el.classList; - - list[condition ? 'add' : 'remove'](className); - } - - function delayedCall(fcn, defaultTimeout) { - var timer, - callback = function() { - timer = null; - fcn(); - }, - - _self = function(timeout) { - if (!timer) - timer = setTimeout(callback, timeout || defaultTimeout); - }; - - _self.delay = function(timeout) { - timer && clearTimeout(timer); - timer = setTimeout(callback, timeout || defaultTimeout); - }; - _self.schedule = _self; - - _self.call = function() { - this.cancel(); - fcn(); - }; - - _self.cancel = function() { - timer && clearTimeout(timer); - timer = null; - }; - - _self.isPending = function() { - return timer; - }; - - return _self; - } - - /* https://github.com/coderaiser/key */ - function key(str, event) { - var right, - KEY = { - BACKSPACE : 8, - TAB : 9, - ENTER : 13, - ESC : 27, - - SPACE : 32, - PAGE_UP : 33, - PAGE_DOWN : 34, - END : 35, - HOME : 36, - UP : 38, - DOWN : 40, - - INSERT : 45, - DELETE : 46, - - INSERT_MAC : 96, - - ASTERISK : 106, - PLUS : 107, - MINUS : 109, - - F1 : 112, - F2 : 113, - F3 : 114, - F4 : 115, - F5 : 116, - F6 : 117, - F7 : 118, - F8 : 119, - F9 : 120, - F10 : 121, - - SLASH : 191, - TRA : 192, /* Typewritten Reverse Apostrophe (`) */ - BACKSLASH : 220 - }; - - keyCheck(str, event); - - right = str.split('|').some(function(combination) { - var wrong; - - wrong = combination.split('-').some(function(key) { - var right; - - switch(key) { - case 'Ctrl': - right = event.ctrlKey; - break; - - case 'Shift': - right = event.shiftKey; - break; - - case 'Alt': - right = event.altKey; - break; - - case 'Cmd': - right = event.metaKey; - break; - - default: - if (key.length === 1) - right = event.keyCode === key.charCodeAt(0); - else - Object.keys(KEY).some(function(name) { - var up = key.toUpperCase(); - - if (up === name) - right = event.keyCode === KEY[name]; - }); - break; - } - - return !right; - }); - - return !wrong; - }); - - return right; - } - - function keyCheck(str, event) { - if (typeof str !== 'string') - throw(Error('str should be string!')); - - if (typeof event !== 'object') - throw(Error('event should be object!')); - } - -}); diff --git a/src/main/resources/static/editor-md/tests/katex-tests.html b/src/main/resources/static/editor-md/tests/katex-tests.html deleted file mode 100644 index f6c4f40..0000000 --- a/src/main/resources/static/editor-md/tests/katex-tests.html +++ /dev/null @@ -1,132 +0,0 @@ - - - - KaTeX Tests - - - - - - - http://khan.github.io/KaTeX/

                          - http://meta.wikimedia.org/wiki/Help:Displaying_a_formula -

                          - a^2 - a^{2+2} - a_2 - {x_2}^3 - x_2^3 - 10^{10^{8}} - a_{i,j} - _nP_k - E=MC^2 - \left \{ \frac{a}{b} \right \} \quad \left \lbrace \frac{a}{b} \right \rbrace - \left [ \frac{a}{b} \right ] \quad \left \lbrack \frac{a}{b} \right \rbrack - \left ( \frac{a}{b} \right ) - \left \langle \frac{a}{b} \right \rangle - x > y = 100 - c = \pm\sqrt{a^2 + b^2} - \left . \frac{A}{B} \right \} \to X - \left / \frac{a}{b} \right \backslash - \left \lfloor \frac{a}{b} \right \rfloor \left \lceil \frac{c}{d} \right \rceil - \frac{1}{2}=0.5 - \dfrac{k}{k-1} = 0.5 - \dbinom{n}{k} \binom{n}{k} - \oint_C x^3\, dx + 4y^2\, dy - \bigcap_1^n p \bigcup_1^k p - \phi_n(\kappa) = - \frac{1}{4\pi^2\kappa^2} \int_0^\infty - \frac{\sin(\kappa R)}{\kappa R} - \frac{\partial}{\partial R} - \left[R^2\frac{\partial D_n(R)}{\partial R}\right]\,dR - \sum_{m=1}^\infty\sum_{n=1}^\infty\frac{m^2\,n} - {3^m\left(m\,3^n+n\,3^m\right)} - e^{i \pi} + 1 = 0 - \left ( \frac{1}{2} \right ) - x_{1,2}=\frac{-b\pm\sqrt{\color{Red}b^2-4ac}}{2a} - {\color{Blue}x^2}+{\color{YellowOrange}2x}-{\color{OliveGreen}1} - \textstyle \sum_{k=1}^N k^2 - \dfrac{ \tfrac{1}{2}[1-(\tfrac{1}{2})^n] }{ 1-\tfrac{1}{2} } = s_n - \binom{n}{k} - 0+1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+\cdots - f(x) = \int_{-\infty}^\infty - \hat f(\xi)\,e^{2 \pi i \xi x} - \,d\xi - \displaystyle \frac{1}{\Bigl(\sqrt{\phi \sqrt{5}}-\phi\Bigr) e^{\frac25 \pi}} = 1+\frac{e^{-2\pi}} {1+\frac{e^{-4\pi}} {1+\frac{e^{-6\pi}} {1+\frac{e^{-8\pi}} {1+\cdots} } } } - \displaystyle \left( \sum_{k=1}^n a_k b_k \right)^2 \leq \left( \sum_{k=1}^n a_k^2 \right) \left( \sum_{k=1}^n b_k^2 \right) - \displaystyle 1 + \frac{q^2}{(1-q)}+\frac{q^6}{(1-q)(1-q^2)}+\cdots = \prod_{j=0}^{\infty}\frac{1}{(1-q^{5j+2})(1-q^{5j+3})}, \quad\quad \text{for }\lvert q\rvert<1. - 2 = \left( - \frac{\left(3-x\right) \times 2}{3-x} - \right) - S_{\text{new}} = S_{\text{old}} - \frac{ \left( 5-T \right) ^2} {2} - x=\frac{-b\pm\sqrt{b^2-4ac}}{2a} - ax^2 + bx + c = 0\, - \int_a^x \!\!\!\int_a^s f(y)\,dy\,ds - = \int_a^x f(y)(x-y)\,dy - \sum_{m=1}^\infty\sum_{n=1}^\infty\frac{m^2\,n} - {3^m\left(m\,3^n+n\,3^m\right)} - u'' + p(x)u' + q(x)u=f(x),\quad x>a - |\bar{z}| = |z|, - |(\bar{z})^n| = |z|^n, - \arg(z^n) = n \arg(z) - \lim_{z\rightarrow z_0} f(z)=f(z_0) - \phi_n(\kappa) = - 0.033C_n^2\kappa^{-11/3},\quad - \frac{1}{L_0}\ll\kappa\ll\frac{1}{l_0} - \sum_{k=1}^N k^2 - \textstyle \sum_{k=1}^N k^2 - \prod_{i=1}^N x_i - \textstyle \prod_{i=1}^N x_i - \coprod_{i=1}^N x_i - \textstyle \coprod_{i=1}^N x_i - \int_{1}^{3}\frac{e^3/x}{x^2}\, dx - \int_C x^3\, dx + 4y^2\, dy - {}_1^2\!\Omega_3^4 - x', y'', f', f'' - \dot{x}, \ddot{x} - \hat a \ \bar b \ \vec c - \lessapprox \lesssim \eqslantless \leqslant \leqq \geqq \geqslant \eqslantgtr \gtrsim \gtrapprox - \smile \frown \wr \triangleleft \triangleright \infty \bot \top - \leftarrow \gets \rightarrow \to \nleftarrow \nrightarrow \leftrightarrow \nleftrightarrow \longleftarrow \longrightarrow \longleftrightarrow - \uparrow \downarrow \updownarrow \Uparrow \Downarrow \Updownarrow \nearrow \searrow \swarrow \nwarrow - \rightharpoonup \rightharpoondown \leftharpoonup \leftharpoondown \upharpoonleft \upharpoonright \downharpoonleft \downharpoonright \rightleftharpoons \leftrightharpoons - \curvearrowleft \circlearrowleft \Lsh \upuparrows \rightrightarrows \rightleftarrows \Rrightarrow \rightarrowtail \looparrowright - \curvearrowright \circlearrowright \Rsh \downdownarrows \leftleftarrows \leftrightarrows \Lleftarrow \leftarrowtail \looparrowleft - \mapsto \longmapsto \hookrightarrow \hookleftarrow \multimap \leftrightsquigarrow \rightsquigarrow - \Diamond \Box \triangle \angle \perp \mid \nmid \| 45^\circ - -\sim \approx \simeq \cong \dot= \overset{\underset{\mathrm{def}}{}}{=} - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/tests/marked-@at-test.html b/src/main/resources/static/editor-md/tests/marked-@at-test.html deleted file mode 100644 index 821f308..0000000 --- a/src/main/resources/static/editor-md/tests/marked-@at-test.html +++ /dev/null @@ -1,221 +0,0 @@ - - - - Marked @ Test - - - - - - - -
                           ~~@mentions~~, #refs @tylerlong `inline code @tylerlong`, [links](), **formatting**, and tags supported @pandao;
                          -list syntax required (any unordered or ordered list supported) @pandao;
                          -this is @pandao a complete item @pandao;
                          -link [@pandao](https://github.com/pandao "@pandao") @
                          -link [@pandao](https://github.com/pandao "@pandao") 
                          -this is an incomplete item **@pandao**;
                          -*@pandao* this is an incomplete item ___@pandao___;
                          -# Github: @pandao
                          -## Github: @pandao
                          -### Github: @tylerlong
                          -#### Github: @tylerlong
                          -##### Github: @tylerlong
                          -###### Github: @tylerlong
                          - 
                          -- dafssdfsdaf@chjj dfsdfsdf
                          -- dafssdfsdaf@chjj dfsdfsdf     
                          -    - dafssdfsdaf@chjj dfsdfsdf
                          -    - dafss@pandao dfsdaf@chjj dfsdfsdf
                          -- dafssd:  @pandao fsdaf@chjj dfsdfsdf @codemirror  @pandao
                          -    + dafssdfsdaf@chjj dfsdfsdf
                          -    + dafss@pandaodfsdaf@chjj dfsdfsdf
                          -
                          -
                          -1. @chjj 第一行@pandao fsdaf@chjj dfsdfsdf :fa-save::  @pandao
                          -    - dafssdfsdaf@chjj dfsdfsdf
                          -    - dafss@pandao dfsdaf@chjj dfsdfsdf
                          -2. @chjj 第二行@pandao fsdaf@chjj dfsdfsdf @codemirror  @pandao
                          -3. 第三行@pandao fsdaf@chjj dfsdfsdf :fa-save::  @pandao
                          -
                          -> Blockquotes @pandao
                          -
                          -> dd@pandao引用文本(Blockquotes @pandao)fdasfad @_pandao fdasfad @xxx454xxx fdasfad @xx_x454xxx454
                          -
                          -|@pandao First Header  | Second@pandao Header@pandao |
                          -| ------------- | ------------- |
                          -| Content@pandao Cell  | @pandao Content Cell @pandao|
                          -| Con@pandao tent Cell@pandao  | Content@pan-dao Cell dfsdfsdf @pan_dao |
                          -
                          -dsfdf@pandao fasdfsdfsfddffd@pandao
                          -
                          -    dfasfasdfasdf:bangbang:
                          -
                          -This is an H1 @pandao
                          -=============
                          -
                          -This @pandao an H2 @pandao
                          --------------
                          -
                          - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/tests/marked-emoji-test.html b/src/main/resources/static/editor-md/tests/marked-emoji-test.html deleted file mode 100644 index 4b60c2e..0000000 --- a/src/main/resources/static/editor-md/tests/marked-emoji-test.html +++ /dev/null @@ -1,231 +0,0 @@ - - - - Marked Emoji Test - - - - - - - -
                          -
                          > Blockquotes
                          -dasfsadfasdf:fa-edit: :warning: :smiley:dsafsdfsad\:fdsfdf\:f dfdf:   :fa-save::fa-star:  :fa-truck:
                          -**fdfasd:smiley:dsfsdfsfd** ~~fsdfds:smiley:dfsdfsdf :fa-info:~~
                          -*dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf*
                          -___Emphasis :fa-gear: Italic:smiley:___  __Emphasis:smiley:__
                          -# H1 dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf
                          -## H2 dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf
                          -### H3 dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf:fa-edit: fdsfsdf:fa-save:dsfsdf
                          -#### H4 dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf:fa-edit: fdsfsdf:fa-save:dsfsdf
                          -##### H5 dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf:fa-edit: fdsfsdf:fa-save:dsfsdf
                          -###### H6 dsfdfsfd:smiley:dsfsfdsfd:smiley:dsfdf:fa-edit: fdsfsdf:fa-star:dsfsdf
                          -[:smiley:](http://www.emoji-cheat-sheet.com/ "link + emoji") link + emoji
                          -- dafssdfsdaf:smiley:dfsdfsdf
                          -- dafssdfsdaf:smiley:dfsdfsdf     
                          -    - dafssdfsdaf:smiley:dfsdfsdf
                          -    - dafss:fa-truck:dfsdaf:smiley:dfsdfsdf
                          -- dafssd:  :fa-truck:fsdaf:smiley:dfsdfsdf :fa-star::  :fa-truck:
                          -    + dafssdfsdaf:smiley:dfsdfsdf
                          -    + dafss:fa-truck:dfsdaf:smiley:dfsdfsdf
                          -
                          -
                          -1. :smiley:第一行:fa-truck:fsdaf:smiley:dfsdfsdf :fa-save::  :fa-truck:
                          -    - dafssdfsdaf:smiley:dfsdfsdf
                          -    - dafss:fa-truck:dfsdaf:smiley:dfsdfsdf
                          -2. :smiley:第二行:fa-truck:fsdaf:smiley:dfsdfsdf :fa-star::  :fa-truck:
                          -3. 第三行:fa-truck:fsdaf:smiley:dfsdfsdf :fa-save::  :fa-truck:
                          -
                          -> Blockquotes
                          -
                          -> dd:smiley:引用文本(Blockquotes:smiley:)fdasfad :fa-star:: dfd :fa-truck:
                          -
                          -|:100: First Header  | Second:smiley: Header:smiley: |
                          -| ------------- | ------------- |
                          -| Content:fa-truck: Cell  | :smiley:Content Cell :smiley: |
                          -| Con:fa-truck:tent Cell:bangbang:  | Content Cell dfsdfsdf :fa-star: :dfdf  :fa-truck: |
                          -
                          -:fa-heart:fasdfsdfsfddffd:editormd-logo: :editormd-logo: :editormd-logo-4x:
                          -
                          -    dfasfasdfasdf:bangbang:
                          -
                          -This is an H1 :editormd-logo-4x:
                          -=============
                          -
                          -This  :fa-save::  :fa-truck:is an H2 :100:
                          --------------
                          -
                          - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/tests/marked-heading-link-test.html b/src/main/resources/static/editor-md/tests/marked-heading-link-test.html deleted file mode 100644 index 108db87..0000000 --- a/src/main/resources/static/editor-md/tests/marked-heading-link-test.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - Marked heading link Test - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/tests/marked-todo-list-test.html b/src/main/resources/static/editor-md/tests/marked-todo-list-test.html deleted file mode 100644 index 50a465e..0000000 --- a/src/main/resources/static/editor-md/tests/marked-todo-list-test.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - Marked Emoji Test - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/static/editor-md/tests/qunit/qunit-1.16.0.css b/src/main/resources/static/editor-md/tests/qunit/qunit-1.16.0.css deleted file mode 100644 index 385a1ce..0000000 --- a/src/main/resources/static/editor-md/tests/qunit/qunit-1.16.0.css +++ /dev/null @@ -1,264 +0,0 @@ -/*! - * QUnit 1.16.0 - * http://qunitjs.com/ - * - * Copyright 2006, 2014 jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2014-12-03T16:32Z - */ - -/** Font Family and Sizes */ - -#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { - font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; -} - -#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } -#qunit-tests { font-size: smaller; } - - -/** Resets */ - -#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter { - margin: 0; - padding: 0; -} - - -/** Header */ - -#qunit-header { - padding: 0.5em 0 0.5em 1em; - - color: #8699A4; - background-color: #0D3349; - - font-size: 1.5em; - line-height: 1em; - font-weight: 400; - - border-radius: 5px 5px 0 0; -} - -#qunit-header a { - text-decoration: none; - color: #C2CCD1; -} - -#qunit-header a:hover, -#qunit-header a:focus { - color: #FFF; -} - -#qunit-testrunner-toolbar label { - display: inline-block; - padding: 0 0.5em 0 0.1em; -} - -#qunit-banner { - height: 5px; -} - -#qunit-testrunner-toolbar { - padding: 0.5em 1em 0.5em 1em; - color: #5E740B; - background-color: #EEE; - overflow: hidden; -} - -#qunit-userAgent { - padding: 0.5em 1em 0.5em 1em; - background-color: #2B81AF; - color: #FFF; - text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; -} - -#qunit-modulefilter-container { - float: right; -} - -/** Tests: Pass/Fail */ - -#qunit-tests { - list-style-position: inside; -} - -#qunit-tests li { - padding: 0.4em 1em 0.4em 1em; - border-bottom: 1px solid #FFF; - list-style-position: inside; -} - -#qunit-tests > li { - display: none; -} - -#qunit-tests li.pass, #qunit-tests li.running, #qunit-tests li.fail { - display: list-item; -} - -#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { - display: none; -} - -#qunit-tests li strong { - cursor: pointer; -} - -#qunit-tests li.skipped strong { - cursor: default; -} - -#qunit-tests li a { - padding: 0.5em; - color: #C2CCD1; - text-decoration: none; -} -#qunit-tests li a:hover, -#qunit-tests li a:focus { - color: #000; -} - -#qunit-tests li .runtime { - float: right; - font-size: smaller; -} - -.qunit-assert-list { - margin-top: 0.5em; - padding: 0.5em; - - background-color: #FFF; - - border-radius: 5px; -} - -.qunit-collapsed { - display: none; -} - -#qunit-tests table { - border-collapse: collapse; - margin-top: 0.2em; -} - -#qunit-tests th { - text-align: right; - vertical-align: top; - padding: 0 0.5em 0 0; -} - -#qunit-tests td { - vertical-align: top; -} - -#qunit-tests pre { - margin: 0; - white-space: pre-wrap; - word-wrap: break-word; -} - -#qunit-tests del { - background-color: #E0F2BE; - color: #374E0C; - text-decoration: none; -} - -#qunit-tests ins { - background-color: #FFCACA; - color: #500; - text-decoration: none; -} - -/*** Test Counts */ - -#qunit-tests b.counts { color: #000; } -#qunit-tests b.passed { color: #5E740B; } -#qunit-tests b.failed { color: #710909; } - -#qunit-tests li li { - padding: 5px; - background-color: #FFF; - border-bottom: none; - list-style-position: inside; -} - -/*** Passing Styles */ - -#qunit-tests li li.pass { - color: #3C510C; - background-color: #FFF; - border-left: 10px solid #C6E746; -} - -#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } -#qunit-tests .pass .test-name { color: #366097; } - -#qunit-tests .pass .test-actual, -#qunit-tests .pass .test-expected { color: #999; } - -#qunit-banner.qunit-pass { background-color: #C6E746; } - -/*** Failing Styles */ - -#qunit-tests li li.fail { - color: #710909; - background-color: #FFF; - border-left: 10px solid #EE5757; - white-space: pre; -} - -#qunit-tests > li:last-child { - border-radius: 0 0 5px 5px; -} - -#qunit-tests .fail { color: #000; background-color: #EE5757; } -#qunit-tests .fail .test-name, -#qunit-tests .fail .module-name { color: #000; } - -#qunit-tests .fail .test-actual { color: #EE5757; } -#qunit-tests .fail .test-expected { color: #008000; } - -#qunit-banner.qunit-fail { background-color: #EE5757; } - -/*** Skipped tests */ - -#qunit-tests .skipped { - background-color: #EBECE9; -} - -#qunit-tests .qunit-skipped-label { - background-color: #F4FF77; - display: inline-block; - font-style: normal; - color: #366097; - line-height: 1.8em; - padding: 0 0.5em; - margin: -0.4em 0.4em -0.4em 0; -} - -/** Result */ - -#qunit-testresult { - padding: 0.5em 1em 0.5em 1em; - - color: #2B81AF; - background-color: #D2E0E6; - - border-bottom: 1px solid #FFF; -} -#qunit-testresult .module-name { - font-weight: 700; -} - -/** Fixture */ - -#qunit-fixture { - position: absolute; - top: -10000px; - left: -10000px; - width: 1000px; - height: 1000px; -} diff --git a/src/main/resources/static/editor-md/tests/qunit/qunit-1.16.0.js b/src/main/resources/static/editor-md/tests/qunit/qunit-1.16.0.js deleted file mode 100644 index 82020d4..0000000 --- a/src/main/resources/static/editor-md/tests/qunit/qunit-1.16.0.js +++ /dev/null @@ -1,2819 +0,0 @@ -/*! - * QUnit 1.16.0 - * http://qunitjs.com/ - * - * Copyright 2006, 2014 jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2014-12-03T16:32Z - */ - -(function( window ) { - -var QUnit, - config, - onErrorFnPrev, - loggingCallbacks = {}, - fileName = ( sourceFromStacktrace( 0 ) || "" ).replace( /(:\d+)+\)?/, "" ).replace( /.+\//, "" ), - toString = Object.prototype.toString, - hasOwn = Object.prototype.hasOwnProperty, - // Keep a local reference to Date (GH-283) - Date = window.Date, - now = Date.now || function() { - return new Date().getTime(); - }, - globalStartCalled = false, - runStarted = false, - setTimeout = window.setTimeout, - clearTimeout = window.clearTimeout, - defined = { - document: window.document !== undefined, - setTimeout: window.setTimeout !== undefined, - sessionStorage: (function() { - var x = "qunit-test-string"; - try { - sessionStorage.setItem( x, x ); - sessionStorage.removeItem( x ); - return true; - } catch ( e ) { - return false; - } - }()) - }, - /** - * Provides a normalized error string, correcting an issue - * with IE 7 (and prior) where Error.prototype.toString is - * not properly implemented - * - * Based on http://es5.github.com/#x15.11.4.4 - * - * @param {String|Error} error - * @return {String} error message - */ - errorString = function( error ) { - var name, message, - errorString = error.toString(); - if ( errorString.substring( 0, 7 ) === "[object" ) { - name = error.name ? error.name.toString() : "Error"; - message = error.message ? error.message.toString() : ""; - if ( name && message ) { - return name + ": " + message; - } else if ( name ) { - return name; - } else if ( message ) { - return message; - } else { - return "Error"; - } - } else { - return errorString; - } - }, - /** - * Makes a clone of an object using only Array or Object as base, - * and copies over the own enumerable properties. - * - * @param {Object} obj - * @return {Object} New object with only the own properties (recursively). - */ - objectValues = function( obj ) { - var key, val, - vals = QUnit.is( "array", obj ) ? [] : {}; - for ( key in obj ) { - if ( hasOwn.call( obj, key ) ) { - val = obj[ key ]; - vals[ key ] = val === Object( val ) ? objectValues( val ) : val; - } - } - return vals; - }; - -QUnit = {}; - -/** - * Config object: Maintain internal state - * Later exposed as QUnit.config - * `config` initialized at top of scope - */ -config = { - // The queue of tests to run - queue: [], - - // block until document ready - blocking: true, - - // when enabled, show only failing tests - // gets persisted through sessionStorage and can be changed in UI via checkbox - hidepassed: false, - - // by default, run previously failed tests first - // very useful in combination with "Hide passed tests" checked - reorder: true, - - // by default, modify document.title when suite is done - altertitle: true, - - // by default, scroll to top of the page when suite is done - scrolltop: true, - - // when enabled, all tests must call expect() - requireExpects: false, - - // add checkboxes that are persisted in the query-string - // when enabled, the id is set to `true` as a `QUnit.config` property - urlConfig: [ - { - id: "hidepassed", - label: "Hide passed tests", - tooltip: "Only show tests and assertions that fail. Stored as query-strings." - }, - { - id: "noglobals", - label: "Check for Globals", - tooltip: "Enabling this will test if any test introduces new properties on the " + - "`window` object. Stored as query-strings." - }, - { - id: "notrycatch", - label: "No try-catch", - tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging " + - "exceptions in IE reasonable. Stored as query-strings." - } - ], - - // Set of all modules. - modules: [], - - // The first unnamed module - currentModule: { - name: "", - tests: [] - }, - - callbacks: {} -}; - -// Push a loose unnamed module to the modules collection -config.modules.push( config.currentModule ); - -// Initialize more QUnit.config and QUnit.urlParams -(function() { - var i, current, - location = window.location || { search: "", protocol: "file:" }, - params = location.search.slice( 1 ).split( "&" ), - length = params.length, - urlParams = {}; - - if ( params[ 0 ] ) { - for ( i = 0; i < length; i++ ) { - current = params[ i ].split( "=" ); - current[ 0 ] = decodeURIComponent( current[ 0 ] ); - - // allow just a key to turn on a flag, e.g., test.html?noglobals - current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true; - if ( urlParams[ current[ 0 ] ] ) { - urlParams[ current[ 0 ] ] = [].concat( urlParams[ current[ 0 ] ], current[ 1 ] ); - } else { - urlParams[ current[ 0 ] ] = current[ 1 ]; - } - } - } - - QUnit.urlParams = urlParams; - - // String search anywhere in moduleName+testName - config.filter = urlParams.filter; - - config.testId = []; - if ( urlParams.testId ) { - - // Ensure that urlParams.testId is an array - urlParams.testId = [].concat( urlParams.testId ); - for ( i = 0; i < urlParams.testId.length; i++ ) { - config.testId.push( urlParams.testId[ i ] ); - } - } - - // Figure out if we're running the tests from a server or not - QUnit.isLocal = location.protocol === "file:"; -}()); - -// Root QUnit object. -// `QUnit` initialized at top of scope -extend( QUnit, { - - // call on start of module test to prepend name to all tests - module: function( name, testEnvironment ) { - var currentModule = { - name: name, - testEnvironment: testEnvironment, - tests: [] - }; - - // DEPRECATED: handles setup/teardown functions, - // beforeEach and afterEach should be used instead - if ( testEnvironment && testEnvironment.setup ) { - testEnvironment.beforeEach = testEnvironment.setup; - delete testEnvironment.setup; - } - if ( testEnvironment && testEnvironment.teardown ) { - testEnvironment.afterEach = testEnvironment.teardown; - delete testEnvironment.teardown; - } - - config.modules.push( currentModule ); - config.currentModule = currentModule; - }, - - // DEPRECATED: QUnit.asyncTest() will be removed in QUnit 2.0. - asyncTest: function( testName, expected, callback ) { - if ( arguments.length === 2 ) { - callback = expected; - expected = null; - } - - QUnit.test( testName, expected, callback, true ); - }, - - test: function( testName, expected, callback, async ) { - var test; - - if ( arguments.length === 2 ) { - callback = expected; - expected = null; - } - - test = new Test({ - testName: testName, - expected: expected, - async: async, - callback: callback - }); - - test.queue(); - }, - - skip: function( testName ) { - var test = new Test({ - testName: testName, - skip: true - }); - - test.queue(); - }, - - // DEPRECATED: The functionality of QUnit.start() will be altered in QUnit 2.0. - // In QUnit 2.0, invoking it will ONLY affect the `QUnit.config.autostart` blocking behavior. - start: function( count ) { - var globalStartAlreadyCalled = globalStartCalled; - - if ( !config.current ) { - globalStartCalled = true; - - if ( runStarted ) { - throw new Error( "Called start() outside of a test context while already started" ); - } else if ( globalStartAlreadyCalled || count > 1 ) { - throw new Error( "Called start() outside of a test context too many times" ); - } else if ( config.autostart ) { - throw new Error( "Called start() outside of a test context when " + - "QUnit.config.autostart was true" ); - } else if ( !config.pageLoaded ) { - - // The page isn't completely loaded yet, so bail out and let `QUnit.load` handle it - config.autostart = true; - return; - } - } else { - - // If a test is running, adjust its semaphore - config.current.semaphore -= count || 1; - - // Don't start until equal number of stop-calls - if ( config.current.semaphore > 0 ) { - return; - } - - // throw an Error if start is called more often than stop - if ( config.current.semaphore < 0 ) { - config.current.semaphore = 0; - - QUnit.pushFailure( - "Called start() while already started (test's semaphore was 0 already)", - sourceFromStacktrace( 2 ) - ); - return; - } - } - - resumeProcessing(); - }, - - // DEPRECATED: QUnit.stop() will be removed in QUnit 2.0. - stop: function( count ) { - - // If there isn't a test running, don't allow QUnit.stop() to be called - if ( !config.current ) { - throw new Error( "Called stop() outside of a test context" ); - } - - // If a test is running, adjust its semaphore - config.current.semaphore += count || 1; - - pauseProcessing(); - }, - - config: config, - - // Safe object type checking - is: function( type, obj ) { - return QUnit.objectType( obj ) === type; - }, - - objectType: function( obj ) { - if ( typeof obj === "undefined" ) { - return "undefined"; - } - - // Consider: typeof null === object - if ( obj === null ) { - return "null"; - } - - var match = toString.call( obj ).match( /^\[object\s(.*)\]$/ ), - type = match && match[ 1 ] || ""; - - switch ( type ) { - case "Number": - if ( isNaN( obj ) ) { - return "nan"; - } - return "number"; - case "String": - case "Boolean": - case "Array": - case "Date": - case "RegExp": - case "Function": - return type.toLowerCase(); - } - if ( typeof obj === "object" ) { - return "object"; - } - return undefined; - }, - - url: function( params ) { - params = extend( extend( {}, QUnit.urlParams ), params ); - var key, - querystring = "?"; - - for ( key in params ) { - if ( hasOwn.call( params, key ) ) { - querystring += encodeURIComponent( key ); - if ( params[ key ] !== true ) { - querystring += "=" + encodeURIComponent( params[ key ] ); - } - querystring += "&"; - } - } - return location.protocol + "//" + location.host + - location.pathname + querystring.slice( 0, -1 ); - }, - - extend: extend, - - load: function() { - config.pageLoaded = true; - - // Initialize the configuration options - extend( config, { - stats: { all: 0, bad: 0 }, - moduleStats: { all: 0, bad: 0 }, - started: 0, - updateRate: 1000, - autostart: true, - filter: "" - }, true ); - - config.blocking = false; - - if ( config.autostart ) { - resumeProcessing(); - } - } -}); - -// Register logging callbacks -(function() { - var i, l, key, - callbacks = [ "begin", "done", "log", "testStart", "testDone", - "moduleStart", "moduleDone" ]; - - function registerLoggingCallback( key ) { - var loggingCallback = function( callback ) { - if ( QUnit.objectType( callback ) !== "function" ) { - throw new Error( - "QUnit logging methods require a callback function as their first parameters." - ); - } - - config.callbacks[ key ].push( callback ); - }; - - // DEPRECATED: This will be removed on QUnit 2.0.0+ - // Stores the registered functions allowing restoring - // at verifyLoggingCallbacks() if modified - loggingCallbacks[ key ] = loggingCallback; - - return loggingCallback; - } - - for ( i = 0, l = callbacks.length; i < l; i++ ) { - key = callbacks[ i ]; - - // Initialize key collection of logging callback - if ( QUnit.objectType( config.callbacks[ key ] ) === "undefined" ) { - config.callbacks[ key ] = []; - } - - QUnit[ key ] = registerLoggingCallback( key ); - } -})(); - -// `onErrorFnPrev` initialized at top of scope -// Preserve other handlers -onErrorFnPrev = window.onerror; - -// Cover uncaught exceptions -// Returning true will suppress the default browser handler, -// returning false will let it run. -window.onerror = function( error, filePath, linerNr ) { - var ret = false; - if ( onErrorFnPrev ) { - ret = onErrorFnPrev( error, filePath, linerNr ); - } - - // Treat return value as window.onerror itself does, - // Only do our handling if not suppressed. - if ( ret !== true ) { - if ( QUnit.config.current ) { - if ( QUnit.config.current.ignoreGlobalErrors ) { - return true; - } - QUnit.pushFailure( error, filePath + ":" + linerNr ); - } else { - QUnit.test( "global failure", extend(function() { - QUnit.pushFailure( error, filePath + ":" + linerNr ); - }, { validTest: true } ) ); - } - return false; - } - - return ret; -}; - -function done() { - var runtime, passed; - - config.autorun = true; - - // Log the last module results - if ( config.previousModule ) { - runLoggingCallbacks( "moduleDone", { - name: config.previousModule.name, - tests: config.previousModule.tests, - failed: config.moduleStats.bad, - passed: config.moduleStats.all - config.moduleStats.bad, - total: config.moduleStats.all, - runtime: now() - config.moduleStats.started - }); - } - delete config.previousModule; - - runtime = now() - config.started; - passed = config.stats.all - config.stats.bad; - - runLoggingCallbacks( "done", { - failed: config.stats.bad, - passed: passed, - total: config.stats.all, - runtime: runtime - }); -} - -// Doesn't support IE6 to IE9 -// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack -function extractStacktrace( e, offset ) { - offset = offset === undefined ? 4 : offset; - - var stack, include, i; - - if ( e.stacktrace ) { - - // Opera 12.x - return e.stacktrace.split( "\n" )[ offset + 3 ]; - } else if ( e.stack ) { - - // Firefox, Chrome, Safari 6+, IE10+, PhantomJS and Node - stack = e.stack.split( "\n" ); - if ( /^error$/i.test( stack[ 0 ] ) ) { - stack.shift(); - } - if ( fileName ) { - include = []; - for ( i = offset; i < stack.length; i++ ) { - if ( stack[ i ].indexOf( fileName ) !== -1 ) { - break; - } - include.push( stack[ i ] ); - } - if ( include.length ) { - return include.join( "\n" ); - } - } - return stack[ offset ]; - } else if ( e.sourceURL ) { - - // Safari < 6 - // exclude useless self-reference for generated Error objects - if ( /qunit.js$/.test( e.sourceURL ) ) { - return; - } - - // for actual exceptions, this is useful - return e.sourceURL + ":" + e.line; - } -} - -function sourceFromStacktrace( offset ) { - var e = new Error(); - if ( !e.stack ) { - try { - throw e; - } catch ( err ) { - // This should already be true in most browsers - e = err; - } - } - return extractStacktrace( e, offset ); -} - -function synchronize( callback, last ) { - if ( QUnit.objectType( callback ) === "array" ) { - while ( callback.length ) { - synchronize( callback.shift() ); - } - return; - } - config.queue.push( callback ); - - if ( config.autorun && !config.blocking ) { - process( last ); - } -} - -function process( last ) { - function next() { - process( last ); - } - var start = now(); - config.depth = config.depth ? config.depth + 1 : 1; - - while ( config.queue.length && !config.blocking ) { - if ( !defined.setTimeout || config.updateRate <= 0 || - ( ( now() - start ) < config.updateRate ) ) { - if ( config.current ) { - - // Reset async tracking for each phase of the Test lifecycle - config.current.usedAsync = false; - } - config.queue.shift()(); - } else { - setTimeout( next, 13 ); - break; - } - } - config.depth--; - if ( last && !config.blocking && !config.queue.length && config.depth === 0 ) { - done(); - } -} - -function begin() { - var i, l, - modulesLog = []; - - // If the test run hasn't officially begun yet - if ( !config.started ) { - - // Record the time of the test run's beginning - config.started = now(); - - verifyLoggingCallbacks(); - - // Delete the loose unnamed module if unused. - if ( config.modules[ 0 ].name === "" && config.modules[ 0 ].tests.length === 0 ) { - config.modules.shift(); - } - - // Avoid unnecessary information by not logging modules' test environments - for ( i = 0, l = config.modules.length; i < l; i++ ) { - modulesLog.push({ - name: config.modules[ i ].name, - tests: config.modules[ i ].tests - }); - } - - // The test run is officially beginning now - runLoggingCallbacks( "begin", { - totalTests: Test.count, - modules: modulesLog - }); - } - - config.blocking = false; - process( true ); -} - -function resumeProcessing() { - runStarted = true; - - // A slight delay to allow this iteration of the event loop to finish (more assertions, etc.) - if ( defined.setTimeout ) { - setTimeout(function() { - if ( config.current && config.current.semaphore > 0 ) { - return; - } - if ( config.timeout ) { - clearTimeout( config.timeout ); - } - - begin(); - }, 13 ); - } else { - begin(); - } -} - -function pauseProcessing() { - config.blocking = true; - - if ( config.testTimeout && defined.setTimeout ) { - clearTimeout( config.timeout ); - config.timeout = setTimeout(function() { - if ( config.current ) { - config.current.semaphore = 0; - QUnit.pushFailure( "Test timed out", sourceFromStacktrace( 2 ) ); - } else { - throw new Error( "Test timed out" ); - } - resumeProcessing(); - }, config.testTimeout ); - } -} - -function saveGlobal() { - config.pollution = []; - - if ( config.noglobals ) { - for ( var key in window ) { - if ( hasOwn.call( window, key ) ) { - // in Opera sometimes DOM element ids show up here, ignore them - if ( /^qunit-test-output/.test( key ) ) { - continue; - } - config.pollution.push( key ); - } - } - } -} - -function checkPollution() { - var newGlobals, - deletedGlobals, - old = config.pollution; - - saveGlobal(); - - newGlobals = diff( config.pollution, old ); - if ( newGlobals.length > 0 ) { - QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join( ", " ) ); - } - - deletedGlobals = diff( old, config.pollution ); - if ( deletedGlobals.length > 0 ) { - QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join( ", " ) ); - } -} - -// returns a new Array with the elements that are in a but not in b -function diff( a, b ) { - var i, j, - result = a.slice(); - - for ( i = 0; i < result.length; i++ ) { - for ( j = 0; j < b.length; j++ ) { - if ( result[ i ] === b[ j ] ) { - result.splice( i, 1 ); - i--; - break; - } - } - } - return result; -} - -function extend( a, b, undefOnly ) { - for ( var prop in b ) { - if ( hasOwn.call( b, prop ) ) { - - // Avoid "Member not found" error in IE8 caused by messing with window.constructor - if ( !( prop === "constructor" && a === window ) ) { - if ( b[ prop ] === undefined ) { - delete a[ prop ]; - } else if ( !( undefOnly && typeof a[ prop ] !== "undefined" ) ) { - a[ prop ] = b[ prop ]; - } - } - } - } - - return a; -} - -function runLoggingCallbacks( key, args ) { - var i, l, callbacks; - - callbacks = config.callbacks[ key ]; - for ( i = 0, l = callbacks.length; i < l; i++ ) { - callbacks[ i ]( args ); - } -} - -// DEPRECATED: This will be removed on 2.0.0+ -// This function verifies if the loggingCallbacks were modified by the user -// If so, it will restore it, assign the given callback and print a console warning -function verifyLoggingCallbacks() { - var loggingCallback, userCallback; - - for ( loggingCallback in loggingCallbacks ) { - if ( QUnit[ loggingCallback ] !== loggingCallbacks[ loggingCallback ] ) { - - userCallback = QUnit[ loggingCallback ]; - - // Restore the callback function - QUnit[ loggingCallback ] = loggingCallbacks[ loggingCallback ]; - - // Assign the deprecated given callback - QUnit[ loggingCallback ]( userCallback ); - - if ( window.console && window.console.warn ) { - window.console.warn( - "QUnit." + loggingCallback + " was replaced with a new value.\n" + - "Please, check out the documentation on how to apply logging callbacks.\n" + - "Reference: http://api.qunitjs.com/category/callbacks/" - ); - } - } - } -} - -// from jquery.js -function inArray( elem, array ) { - if ( array.indexOf ) { - return array.indexOf( elem ); - } - - for ( var i = 0, length = array.length; i < length; i++ ) { - if ( array[ i ] === elem ) { - return i; - } - } - - return -1; -} - -function Test( settings ) { - var i, l; - - ++Test.count; - - extend( this, settings ); - this.assertions = []; - this.semaphore = 0; - this.usedAsync = false; - this.module = config.currentModule; - this.stack = sourceFromStacktrace( 3 ); - - // Register unique strings - for ( i = 0, l = this.module.tests; i < l.length; i++ ) { - if ( this.module.tests[ i ].name === this.testName ) { - this.testName += " "; - } - } - - this.testId = generateHash( this.module.name, this.testName ); - - this.module.tests.push({ - name: this.testName, - testId: this.testId - }); - - if ( settings.skip ) { - - // Skipped tests will fully ignore any sent callback - this.callback = function() {}; - this.async = false; - this.expected = 0; - } else { - this.assert = new Assert( this ); - } -} - -Test.count = 0; - -Test.prototype = { - before: function() { - if ( - - // Emit moduleStart when we're switching from one module to another - this.module !== config.previousModule || - - // They could be equal (both undefined) but if the previousModule property doesn't - // yet exist it means this is the first test in a suite that isn't wrapped in a - // module, in which case we'll just emit a moduleStart event for 'undefined'. - // Without this, reporters can get testStart before moduleStart which is a problem. - !hasOwn.call( config, "previousModule" ) - ) { - if ( hasOwn.call( config, "previousModule" ) ) { - runLoggingCallbacks( "moduleDone", { - name: config.previousModule.name, - tests: config.previousModule.tests, - failed: config.moduleStats.bad, - passed: config.moduleStats.all - config.moduleStats.bad, - total: config.moduleStats.all, - runtime: now() - config.moduleStats.started - }); - } - config.previousModule = this.module; - config.moduleStats = { all: 0, bad: 0, started: now() }; - runLoggingCallbacks( "moduleStart", { - name: this.module.name, - tests: this.module.tests - }); - } - - config.current = this; - - this.testEnvironment = extend( {}, this.module.testEnvironment ); - delete this.testEnvironment.beforeEach; - delete this.testEnvironment.afterEach; - - this.started = now(); - runLoggingCallbacks( "testStart", { - name: this.testName, - module: this.module.name, - testId: this.testId - }); - - if ( !config.pollution ) { - saveGlobal(); - } - }, - - run: function() { - var promise; - - config.current = this; - - if ( this.async ) { - QUnit.stop(); - } - - this.callbackStarted = now(); - - if ( config.notrycatch ) { - promise = this.callback.call( this.testEnvironment, this.assert ); - this.resolvePromise( promise ); - return; - } - - try { - promise = this.callback.call( this.testEnvironment, this.assert ); - this.resolvePromise( promise ); - } catch ( e ) { - this.pushFailure( "Died on test #" + ( this.assertions.length + 1 ) + " " + - this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) ); - - // else next test will carry the responsibility - saveGlobal(); - - // Restart the tests if they're blocking - if ( config.blocking ) { - QUnit.start(); - } - } - }, - - after: function() { - checkPollution(); - }, - - queueHook: function( hook, hookName ) { - var promise, - test = this; - return function runHook() { - config.current = test; - if ( config.notrycatch ) { - promise = hook.call( test.testEnvironment, test.assert ); - test.resolvePromise( promise, hookName ); - return; - } - try { - promise = hook.call( test.testEnvironment, test.assert ); - test.resolvePromise( promise, hookName ); - } catch ( error ) { - test.pushFailure( hookName + " failed on " + test.testName + ": " + - ( error.message || error ), extractStacktrace( error, 0 ) ); - } - }; - }, - - // Currently only used for module level hooks, can be used to add global level ones - hooks: function( handler ) { - var hooks = []; - - // Hooks are ignored on skipped tests - if ( this.skip ) { - return hooks; - } - - if ( this.module.testEnvironment && - QUnit.objectType( this.module.testEnvironment[ handler ] ) === "function" ) { - hooks.push( this.queueHook( this.module.testEnvironment[ handler ], handler ) ); - } - - return hooks; - }, - - finish: function() { - config.current = this; - if ( config.requireExpects && this.expected === null ) { - this.pushFailure( "Expected number of assertions to be defined, but expect() was " + - "not called.", this.stack ); - } else if ( this.expected !== null && this.expected !== this.assertions.length ) { - this.pushFailure( "Expected " + this.expected + " assertions, but " + - this.assertions.length + " were run", this.stack ); - } else if ( this.expected === null && !this.assertions.length ) { - this.pushFailure( "Expected at least one assertion, but none were run - call " + - "expect(0) to accept zero assertions.", this.stack ); - } - - var i, - bad = 0; - - this.runtime = now() - this.started; - config.stats.all += this.assertions.length; - config.moduleStats.all += this.assertions.length; - - for ( i = 0; i < this.assertions.length; i++ ) { - if ( !this.assertions[ i ].result ) { - bad++; - config.stats.bad++; - config.moduleStats.bad++; - } - } - - runLoggingCallbacks( "testDone", { - name: this.testName, - module: this.module.name, - skipped: !!this.skip, - failed: bad, - passed: this.assertions.length - bad, - total: this.assertions.length, - runtime: this.runtime, - - // HTML Reporter use - assertions: this.assertions, - testId: this.testId, - - // DEPRECATED: this property will be removed in 2.0.0, use runtime instead - duration: this.runtime - }); - - // QUnit.reset() is deprecated and will be replaced for a new - // fixture reset function on QUnit 2.0/2.1. - // It's still called here for backwards compatibility handling - QUnit.reset(); - - config.current = undefined; - }, - - queue: function() { - var bad, - test = this; - - if ( !this.valid() ) { - return; - } - - function run() { - - // each of these can by async - synchronize([ - function() { - test.before(); - }, - - test.hooks( "beforeEach" ), - - function() { - test.run(); - }, - - test.hooks( "afterEach" ).reverse(), - - function() { - test.after(); - }, - function() { - test.finish(); - } - ]); - } - - // `bad` initialized at top of scope - // defer when previous test run passed, if storage is available - bad = QUnit.config.reorder && defined.sessionStorage && - +sessionStorage.getItem( "qunit-test-" + this.module.name + "-" + this.testName ); - - if ( bad ) { - run(); - } else { - synchronize( run, true ); - } - }, - - push: function( result, actual, expected, message ) { - var source, - details = { - module: this.module.name, - name: this.testName, - result: result, - message: message, - actual: actual, - expected: expected, - testId: this.testId, - runtime: now() - this.started - }; - - if ( !result ) { - source = sourceFromStacktrace(); - - if ( source ) { - details.source = source; - } - } - - runLoggingCallbacks( "log", details ); - - this.assertions.push({ - result: !!result, - message: message - }); - }, - - pushFailure: function( message, source, actual ) { - if ( !this instanceof Test ) { - throw new Error( "pushFailure() assertion outside test context, was " + - sourceFromStacktrace( 2 ) ); - } - - var details = { - module: this.module.name, - name: this.testName, - result: false, - message: message || "error", - actual: actual || null, - testId: this.testId, - runtime: now() - this.started - }; - - if ( source ) { - details.source = source; - } - - runLoggingCallbacks( "log", details ); - - this.assertions.push({ - result: false, - message: message - }); - }, - - resolvePromise: function( promise, phase ) { - var then, message, - test = this; - if ( promise != null ) { - then = promise.then; - if ( QUnit.objectType( then ) === "function" ) { - QUnit.stop(); - then.call( - promise, - QUnit.start, - function( error ) { - message = "Promise rejected " + - ( !phase ? "during" : phase.replace( /Each$/, "" ) ) + - " " + test.testName + ": " + ( error.message || error ); - test.pushFailure( message, extractStacktrace( error, 0 ) ); - - // else next test will carry the responsibility - saveGlobal(); - - // Unblock - QUnit.start(); - } - ); - } - } - }, - - valid: function() { - var include, - filter = config.filter && config.filter.toLowerCase(), - module = QUnit.urlParams.module && QUnit.urlParams.module.toLowerCase(), - fullName = ( this.module.name + ": " + this.testName ).toLowerCase(); - - // Internally-generated tests are always valid - if ( this.callback && this.callback.validTest ) { - return true; - } - - if ( config.testId.length > 0 && inArray( this.testId, config.testId ) < 0 ) { - return false; - } - - if ( module && ( !this.module.name || this.module.name.toLowerCase() !== module ) ) { - return false; - } - - if ( !filter ) { - return true; - } - - include = filter.charAt( 0 ) !== "!"; - if ( !include ) { - filter = filter.slice( 1 ); - } - - // If the filter matches, we need to honour include - if ( fullName.indexOf( filter ) !== -1 ) { - return include; - } - - // Otherwise, do the opposite - return !include; - } - -}; - -// Resets the test setup. Useful for tests that modify the DOM. -/* -DEPRECATED: Use multiple tests instead of resetting inside a test. -Use testStart or testDone for custom cleanup. -This method will throw an error in 2.0, and will be removed in 2.1 -*/ -QUnit.reset = function() { - - // Return on non-browser environments - // This is necessary to not break on node tests - if ( typeof window === "undefined" ) { - return; - } - - var fixture = defined.document && document.getElementById && - document.getElementById( "qunit-fixture" ); - - if ( fixture ) { - fixture.innerHTML = config.fixture; - } -}; - -QUnit.pushFailure = function() { - if ( !QUnit.config.current ) { - throw new Error( "pushFailure() assertion outside test context, in " + - sourceFromStacktrace( 2 ) ); - } - - // Gets current test obj - var currentTest = QUnit.config.current; - - return currentTest.pushFailure.apply( currentTest, arguments ); -}; - -// Based on Java's String.hashCode, a simple but not -// rigorously collision resistant hashing function -function generateHash( module, testName ) { - var hex, - i = 0, - hash = 0, - str = module + "\x1C" + testName, - len = str.length; - - for ( ; i < len; i++ ) { - hash = ( ( hash << 5 ) - hash ) + str.charCodeAt( i ); - hash |= 0; - } - - // Convert the possibly negative integer hash code into an 8 character hex string, which isn't - // strictly necessary but increases user understanding that the id is a SHA-like hash - hex = ( 0x100000000 + hash ).toString( 16 ); - if ( hex.length < 8 ) { - hex = "0000000" + hex; - } - - return hex.slice( -8 ); -} - -function Assert( testContext ) { - this.test = testContext; -} - -// Assert helpers -QUnit.assert = Assert.prototype = { - - // Specify the number of expected assertions to guarantee that failed test - // (no assertions are run at all) don't slip through. - expect: function( asserts ) { - if ( arguments.length === 1 ) { - this.test.expected = asserts; - } else { - return this.test.expected; - } - }, - - // Increment this Test's semaphore counter, then return a single-use function that - // decrements that counter a maximum of once. - async: function() { - var test = this.test, - popped = false; - - test.semaphore += 1; - test.usedAsync = true; - pauseProcessing(); - - return function done() { - if ( !popped ) { - test.semaphore -= 1; - popped = true; - resumeProcessing(); - } else { - test.pushFailure( "Called the callback returned from `assert.async` more than once", - sourceFromStacktrace( 2 ) ); - } - }; - }, - - // Exports test.push() to the user API - push: function( /* result, actual, expected, message */ ) { - var assert = this, - currentTest = ( assert instanceof Assert && assert.test ) || QUnit.config.current; - - // Backwards compatibility fix. - // Allows the direct use of global exported assertions and QUnit.assert.* - // Although, it's use is not recommended as it can leak assertions - // to other tests from async tests, because we only get a reference to the current test, - // not exactly the test where assertion were intended to be called. - if ( !currentTest ) { - throw new Error( "assertion outside test context, in " + sourceFromStacktrace( 2 ) ); - } - - if ( currentTest.usedAsync === true && currentTest.semaphore === 0 ) { - currentTest.pushFailure( "Assertion after the final `assert.async` was resolved", - sourceFromStacktrace( 2 ) ); - - // Allow this assertion to continue running anyway... - } - - if ( !( assert instanceof Assert ) ) { - assert = currentTest.assert; - } - return assert.test.push.apply( assert.test, arguments ); - }, - - /** - * Asserts rough true-ish result. - * @name ok - * @function - * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" ); - */ - ok: function( result, message ) { - message = message || ( result ? "okay" : "failed, expected argument to be truthy, was: " + - QUnit.dump.parse( result ) ); - this.push( !!result, result, true, message ); - }, - - /** - * Assert that the first two arguments are equal, with an optional message. - * Prints out both actual and expected values. - * @name equal - * @function - * @example equal( format( "{0} bytes.", 2), "2 bytes.", "replaces {0} with next argument" ); - */ - equal: function( actual, expected, message ) { - /*jshint eqeqeq:false */ - this.push( expected == actual, actual, expected, message ); - }, - - /** - * @name notEqual - * @function - */ - notEqual: function( actual, expected, message ) { - /*jshint eqeqeq:false */ - this.push( expected != actual, actual, expected, message ); - }, - - /** - * @name propEqual - * @function - */ - propEqual: function( actual, expected, message ) { - actual = objectValues( actual ); - expected = objectValues( expected ); - this.push( QUnit.equiv( actual, expected ), actual, expected, message ); - }, - - /** - * @name notPropEqual - * @function - */ - notPropEqual: function( actual, expected, message ) { - actual = objectValues( actual ); - expected = objectValues( expected ); - this.push( !QUnit.equiv( actual, expected ), actual, expected, message ); - }, - - /** - * @name deepEqual - * @function - */ - deepEqual: function( actual, expected, message ) { - this.push( QUnit.equiv( actual, expected ), actual, expected, message ); - }, - - /** - * @name notDeepEqual - * @function - */ - notDeepEqual: function( actual, expected, message ) { - this.push( !QUnit.equiv( actual, expected ), actual, expected, message ); - }, - - /** - * @name strictEqual - * @function - */ - strictEqual: function( actual, expected, message ) { - this.push( expected === actual, actual, expected, message ); - }, - - /** - * @name notStrictEqual - * @function - */ - notStrictEqual: function( actual, expected, message ) { - this.push( expected !== actual, actual, expected, message ); - }, - - "throws": function( block, expected, message ) { - var actual, expectedType, - expectedOutput = expected, - ok = false; - - // 'expected' is optional unless doing string comparison - if ( message == null && typeof expected === "string" ) { - message = expected; - expected = null; - } - - this.test.ignoreGlobalErrors = true; - try { - block.call( this.test.testEnvironment ); - } catch (e) { - actual = e; - } - this.test.ignoreGlobalErrors = false; - - if ( actual ) { - expectedType = QUnit.objectType( expected ); - - // we don't want to validate thrown error - if ( !expected ) { - ok = true; - expectedOutput = null; - - // expected is a regexp - } else if ( expectedType === "regexp" ) { - ok = expected.test( errorString( actual ) ); - - // expected is a string - } else if ( expectedType === "string" ) { - ok = expected === errorString( actual ); - - // expected is a constructor, maybe an Error constructor - } else if ( expectedType === "function" && actual instanceof expected ) { - ok = true; - - // expected is an Error object - } else if ( expectedType === "object" ) { - ok = actual instanceof expected.constructor && - actual.name === expected.name && - actual.message === expected.message; - - // expected is a validation function which returns true if validation passed - } else if ( expectedType === "function" && expected.call( {}, actual ) === true ) { - expectedOutput = null; - ok = true; - } - - this.push( ok, actual, expectedOutput, message ); - } else { - this.test.pushFailure( message, null, "No exception was thrown." ); - } - } -}; - -// Provide an alternative to assert.throws(), for enviroments that consider throws a reserved word -// Known to us are: Closure Compiler, Narwhal -(function() { - /*jshint sub:true */ - Assert.prototype.raises = Assert.prototype[ "throws" ]; -}()); - -// Test for equality any JavaScript type. -// Author: Philippe Rathé -QUnit.equiv = (function() { - - // Call the o related callback with the given arguments. - function bindCallbacks( o, callbacks, args ) { - var prop = QUnit.objectType( o ); - if ( prop ) { - if ( QUnit.objectType( callbacks[ prop ] ) === "function" ) { - return callbacks[ prop ].apply( callbacks, args ); - } else { - return callbacks[ prop ]; // or undefined - } - } - } - - // the real equiv function - var innerEquiv, - - // stack to decide between skip/abort functions - callers = [], - - // stack to avoiding loops from circular referencing - parents = [], - parentsB = [], - - getProto = Object.getPrototypeOf || function( obj ) { - /* jshint camelcase: false, proto: true */ - return obj.__proto__; - }, - callbacks = (function() { - - // for string, boolean, number and null - function useStrictEquality( b, a ) { - - /*jshint eqeqeq:false */ - if ( b instanceof a.constructor || a instanceof b.constructor ) { - - // to catch short annotation VS 'new' annotation of a - // declaration - // e.g. var i = 1; - // var j = new Number(1); - return a == b; - } else { - return a === b; - } - } - - return { - "string": useStrictEquality, - "boolean": useStrictEquality, - "number": useStrictEquality, - "null": useStrictEquality, - "undefined": useStrictEquality, - - "nan": function( b ) { - return isNaN( b ); - }, - - "date": function( b, a ) { - return QUnit.objectType( b ) === "date" && a.valueOf() === b.valueOf(); - }, - - "regexp": function( b, a ) { - return QUnit.objectType( b ) === "regexp" && - - // the regex itself - a.source === b.source && - - // and its modifiers - a.global === b.global && - - // (gmi) ... - a.ignoreCase === b.ignoreCase && - a.multiline === b.multiline && - a.sticky === b.sticky; - }, - - // - skip when the property is a method of an instance (OOP) - // - abort otherwise, - // initial === would have catch identical references anyway - "function": function() { - var caller = callers[ callers.length - 1 ]; - return caller !== Object && typeof caller !== "undefined"; - }, - - "array": function( b, a ) { - var i, j, len, loop, aCircular, bCircular; - - // b could be an object literal here - if ( QUnit.objectType( b ) !== "array" ) { - return false; - } - - len = a.length; - if ( len !== b.length ) { - // safe and faster - return false; - } - - // track reference to avoid circular references - parents.push( a ); - parentsB.push( b ); - for ( i = 0; i < len; i++ ) { - loop = false; - for ( j = 0; j < parents.length; j++ ) { - aCircular = parents[ j ] === a[ i ]; - bCircular = parentsB[ j ] === b[ i ]; - if ( aCircular || bCircular ) { - if ( a[ i ] === b[ i ] || aCircular && bCircular ) { - loop = true; - } else { - parents.pop(); - parentsB.pop(); - return false; - } - } - } - if ( !loop && !innerEquiv( a[ i ], b[ i ] ) ) { - parents.pop(); - parentsB.pop(); - return false; - } - } - parents.pop(); - parentsB.pop(); - return true; - }, - - "object": function( b, a ) { - - /*jshint forin:false */ - var i, j, loop, aCircular, bCircular, - // Default to true - eq = true, - aProperties = [], - bProperties = []; - - // comparing constructors is more strict than using - // instanceof - if ( a.constructor !== b.constructor ) { - - // Allow objects with no prototype to be equivalent to - // objects with Object as their constructor. - if ( !( ( getProto( a ) === null && getProto( b ) === Object.prototype ) || - ( getProto( b ) === null && getProto( a ) === Object.prototype ) ) ) { - return false; - } - } - - // stack constructor before traversing properties - callers.push( a.constructor ); - - // track reference to avoid circular references - parents.push( a ); - parentsB.push( b ); - - // be strict: don't ensure hasOwnProperty and go deep - for ( i in a ) { - loop = false; - for ( j = 0; j < parents.length; j++ ) { - aCircular = parents[ j ] === a[ i ]; - bCircular = parentsB[ j ] === b[ i ]; - if ( aCircular || bCircular ) { - if ( a[ i ] === b[ i ] || aCircular && bCircular ) { - loop = true; - } else { - eq = false; - break; - } - } - } - aProperties.push( i ); - if ( !loop && !innerEquiv( a[ i ], b[ i ] ) ) { - eq = false; - break; - } - } - - parents.pop(); - parentsB.pop(); - callers.pop(); // unstack, we are done - - for ( i in b ) { - bProperties.push( i ); // collect b's properties - } - - // Ensures identical properties name - return eq && innerEquiv( aProperties.sort(), bProperties.sort() ); - } - }; - }()); - - innerEquiv = function() { // can take multiple arguments - var args = [].slice.apply( arguments ); - if ( args.length < 2 ) { - return true; // end transition - } - - return ( (function( a, b ) { - if ( a === b ) { - return true; // catch the most you can - } else if ( a === null || b === null || typeof a === "undefined" || - typeof b === "undefined" || - QUnit.objectType( a ) !== QUnit.objectType( b ) ) { - - // don't lose time with error prone cases - return false; - } else { - return bindCallbacks( a, callbacks, [ b, a ] ); - } - - // apply transition with (1..n) arguments - }( args[ 0 ], args[ 1 ] ) ) && - innerEquiv.apply( this, args.splice( 1, args.length - 1 ) ) ); - }; - - return innerEquiv; -}()); - -// Based on jsDump by Ariel Flesler -// http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html -QUnit.dump = (function() { - function quote( str ) { - return "\"" + str.toString().replace( /"/g, "\\\"" ) + "\""; - } - function literal( o ) { - return o + ""; - } - function join( pre, arr, post ) { - var s = dump.separator(), - base = dump.indent(), - inner = dump.indent( 1 ); - if ( arr.join ) { - arr = arr.join( "," + s + inner ); - } - if ( !arr ) { - return pre + post; - } - return [ pre, inner + arr, base + post ].join( s ); - } - function array( arr, stack ) { - var i = arr.length, - ret = new Array( i ); - - if ( dump.maxDepth && dump.depth > dump.maxDepth ) { - return "[object Array]"; - } - - this.up(); - while ( i-- ) { - ret[ i ] = this.parse( arr[ i ], undefined, stack ); - } - this.down(); - return join( "[", ret, "]" ); - } - - var reName = /^function (\w+)/, - dump = { - - // objType is used mostly internally, you can fix a (custom) type in advance - parse: function( obj, objType, stack ) { - stack = stack || []; - var res, parser, parserType, - inStack = inArray( obj, stack ); - - if ( inStack !== -1 ) { - return "recursion(" + ( inStack - stack.length ) + ")"; - } - - objType = objType || this.typeOf( obj ); - parser = this.parsers[ objType ]; - parserType = typeof parser; - - if ( parserType === "function" ) { - stack.push( obj ); - res = parser.call( this, obj, stack ); - stack.pop(); - return res; - } - return ( parserType === "string" ) ? parser : this.parsers.error; - }, - typeOf: function( obj ) { - var type; - if ( obj === null ) { - type = "null"; - } else if ( typeof obj === "undefined" ) { - type = "undefined"; - } else if ( QUnit.is( "regexp", obj ) ) { - type = "regexp"; - } else if ( QUnit.is( "date", obj ) ) { - type = "date"; - } else if ( QUnit.is( "function", obj ) ) { - type = "function"; - } else if ( obj.setInterval !== undefined && - obj.document !== undefined && - obj.nodeType === undefined ) { - type = "window"; - } else if ( obj.nodeType === 9 ) { - type = "document"; - } else if ( obj.nodeType ) { - type = "node"; - } else if ( - - // native arrays - toString.call( obj ) === "[object Array]" || - - // NodeList objects - ( typeof obj.length === "number" && obj.item !== undefined && - ( obj.length ? obj.item( 0 ) === obj[ 0 ] : ( obj.item( 0 ) === null && - obj[ 0 ] === undefined ) ) ) - ) { - type = "array"; - } else if ( obj.constructor === Error.prototype.constructor ) { - type = "error"; - } else { - type = typeof obj; - } - return type; - }, - separator: function() { - return this.multiline ? this.HTML ? "
                          " : "\n" : this.HTML ? " " : " "; - }, - // extra can be a number, shortcut for increasing-calling-decreasing - indent: function( extra ) { - if ( !this.multiline ) { - return ""; - } - var chr = this.indentChar; - if ( this.HTML ) { - chr = chr.replace( /\t/g, " " ).replace( / /g, " " ); - } - return new Array( this.depth + ( extra || 0 ) ).join( chr ); - }, - up: function( a ) { - this.depth += a || 1; - }, - down: function( a ) { - this.depth -= a || 1; - }, - setParser: function( name, parser ) { - this.parsers[ name ] = parser; - }, - // The next 3 are exposed so you can use them - quote: quote, - literal: literal, - join: join, - // - depth: 1, - maxDepth: 5, - - // This is the list of parsers, to modify them, use dump.setParser - parsers: { - window: "[Window]", - document: "[Document]", - error: function( error ) { - return "Error(\"" + error.message + "\")"; - }, - unknown: "[Unknown]", - "null": "null", - "undefined": "undefined", - "function": function( fn ) { - var ret = "function", - - // functions never have name in IE - name = "name" in fn ? fn.name : ( reName.exec( fn ) || [] )[ 1 ]; - - if ( name ) { - ret += " " + name; - } - ret += "( "; - - ret = [ ret, dump.parse( fn, "functionArgs" ), "){" ].join( "" ); - return join( ret, dump.parse( fn, "functionCode" ), "}" ); - }, - array: array, - nodelist: array, - "arguments": array, - object: function( map, stack ) { - var keys, key, val, i, nonEnumerableProperties, - ret = []; - - if ( dump.maxDepth && dump.depth > dump.maxDepth ) { - return "[object Object]"; - } - - dump.up(); - keys = []; - for ( key in map ) { - keys.push( key ); - } - - // Some properties are not always enumerable on Error objects. - nonEnumerableProperties = [ "message", "name" ]; - for ( i in nonEnumerableProperties ) { - key = nonEnumerableProperties[ i ]; - if ( key in map && !( key in keys ) ) { - keys.push( key ); - } - } - keys.sort(); - for ( i = 0; i < keys.length; i++ ) { - key = keys[ i ]; - val = map[ key ]; - ret.push( dump.parse( key, "key" ) + ": " + - dump.parse( val, undefined, stack ) ); - } - dump.down(); - return join( "{", ret, "}" ); - }, - node: function( node ) { - var len, i, val, - open = dump.HTML ? "<" : "<", - close = dump.HTML ? ">" : ">", - tag = node.nodeName.toLowerCase(), - ret = open + tag, - attrs = node.attributes; - - if ( attrs ) { - for ( i = 0, len = attrs.length; i < len; i++ ) { - val = attrs[ i ].nodeValue; - - // IE6 includes all attributes in .attributes, even ones not explicitly - // set. Those have values like undefined, null, 0, false, "" or - // "inherit". - if ( val && val !== "inherit" ) { - ret += " " + attrs[ i ].nodeName + "=" + - dump.parse( val, "attribute" ); - } - } - } - ret += close; - - // Show content of TextNode or CDATASection - if ( node.nodeType === 3 || node.nodeType === 4 ) { - ret += node.nodeValue; - } - - return ret + open + "/" + tag + close; - }, - - // function calls it internally, it's the arguments part of the function - functionArgs: function( fn ) { - var args, - l = fn.length; - - if ( !l ) { - return ""; - } - - args = new Array( l ); - while ( l-- ) { - - // 97 is 'a' - args[ l ] = String.fromCharCode( 97 + l ); - } - return " " + args.join( ", " ) + " "; - }, - // object calls it internally, the key part of an item in a map - key: quote, - // function calls it internally, it's the content of the function - functionCode: "[code]", - // node calls it internally, it's an html attribute value - attribute: quote, - string: quote, - date: quote, - regexp: literal, - number: literal, - "boolean": literal - }, - // if true, entities are escaped ( <, >, \t, space and \n ) - HTML: false, - // indentation unit - indentChar: " ", - // if true, items in a collection, are separated by a \n, else just a space. - multiline: true - }; - - return dump; -}()); - -// back compat -QUnit.jsDump = QUnit.dump; - -// For browser, export only select globals -if ( typeof window !== "undefined" ) { - - // Deprecated - // Extend assert methods to QUnit and Global scope through Backwards compatibility - (function() { - var i, - assertions = Assert.prototype; - - function applyCurrent( current ) { - return function() { - var assert = new Assert( QUnit.config.current ); - current.apply( assert, arguments ); - }; - } - - for ( i in assertions ) { - QUnit[ i ] = applyCurrent( assertions[ i ] ); - } - })(); - - (function() { - var i, l, - keys = [ - "test", - "module", - "expect", - "asyncTest", - "start", - "stop", - "ok", - "equal", - "notEqual", - "propEqual", - "notPropEqual", - "deepEqual", - "notDeepEqual", - "strictEqual", - "notStrictEqual", - "throws" - ]; - - for ( i = 0, l = keys.length; i < l; i++ ) { - window[ keys[ i ] ] = QUnit[ keys[ i ] ]; - } - })(); - - window.QUnit = QUnit; -} - -// For nodejs -if ( typeof module !== "undefined" && module.exports ) { - module.exports = QUnit; -} - -// For CommonJS with exports, but without module.exports, like Rhino -if ( typeof exports !== "undefined" ) { - exports.QUnit = QUnit; -} - -// Get a reference to the global object, like window in browsers -}( (function() { - return this; -})() )); - -/*istanbul ignore next */ -// jscs:disable maximumLineLength -/* - * Javascript Diff Algorithm - * By John Resig (http://ejohn.org/) - * Modified by Chu Alan "sprite" - * - * Released under the MIT license. - * - * More Info: - * http://ejohn.org/projects/javascript-diff-algorithm/ - * - * Usage: QUnit.diff(expected, actual) - * - * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the quick brown fox jumped jumps over" - */ -QUnit.diff = (function() { - var hasOwn = Object.prototype.hasOwnProperty; - - /*jshint eqeqeq:false, eqnull:true */ - function diff( o, n ) { - var i, - ns = {}, - os = {}; - - for ( i = 0; i < n.length; i++ ) { - if ( !hasOwn.call( ns, n[ i ] ) ) { - ns[ n[ i ] ] = { - rows: [], - o: null - }; - } - ns[ n[ i ] ].rows.push( i ); - } - - for ( i = 0; i < o.length; i++ ) { - if ( !hasOwn.call( os, o[ i ] ) ) { - os[ o[ i ] ] = { - rows: [], - n: null - }; - } - os[ o[ i ] ].rows.push( i ); - } - - for ( i in ns ) { - if ( hasOwn.call( ns, i ) ) { - if ( ns[ i ].rows.length === 1 && hasOwn.call( os, i ) && os[ i ].rows.length === 1 ) { - n[ ns[ i ].rows[ 0 ] ] = { - text: n[ ns[ i ].rows[ 0 ] ], - row: os[ i ].rows[ 0 ] - }; - o[ os[ i ].rows[ 0 ] ] = { - text: o[ os[ i ].rows[ 0 ] ], - row: ns[ i ].rows[ 0 ] - }; - } - } - } - - for ( i = 0; i < n.length - 1; i++ ) { - if ( n[ i ].text != null && n[ i + 1 ].text == null && n[ i ].row + 1 < o.length && o[ n[ i ].row + 1 ].text == null && - n[ i + 1 ] == o[ n[ i ].row + 1 ] ) { - - n[ i + 1 ] = { - text: n[ i + 1 ], - row: n[ i ].row + 1 - }; - o[ n[ i ].row + 1 ] = { - text: o[ n[ i ].row + 1 ], - row: i + 1 - }; - } - } - - for ( i = n.length - 1; i > 0; i-- ) { - if ( n[ i ].text != null && n[ i - 1 ].text == null && n[ i ].row > 0 && o[ n[ i ].row - 1 ].text == null && - n[ i - 1 ] == o[ n[ i ].row - 1 ] ) { - - n[ i - 1 ] = { - text: n[ i - 1 ], - row: n[ i ].row - 1 - }; - o[ n[ i ].row - 1 ] = { - text: o[ n[ i ].row - 1 ], - row: i - 1 - }; - } - } - - return { - o: o, - n: n - }; - } - - return function( o, n ) { - o = o.replace( /\s+$/, "" ); - n = n.replace( /\s+$/, "" ); - - var i, pre, - str = "", - out = diff( o === "" ? [] : o.split( /\s+/ ), n === "" ? [] : n.split( /\s+/ ) ), - oSpace = o.match( /\s+/g ), - nSpace = n.match( /\s+/g ); - - if ( oSpace == null ) { - oSpace = [ " " ]; - } else { - oSpace.push( " " ); - } - - if ( nSpace == null ) { - nSpace = [ " " ]; - } else { - nSpace.push( " " ); - } - - if ( out.n.length === 0 ) { - for ( i = 0; i < out.o.length; i++ ) { - str += "" + out.o[ i ] + oSpace[ i ] + ""; - } - } else { - if ( out.n[ 0 ].text == null ) { - for ( n = 0; n < out.o.length && out.o[ n ].text == null; n++ ) { - str += "" + out.o[ n ] + oSpace[ n ] + ""; - } - } - - for ( i = 0; i < out.n.length; i++ ) { - if ( out.n[ i ].text == null ) { - str += "" + out.n[ i ] + nSpace[ i ] + ""; - } else { - - // `pre` initialized at top of scope - pre = ""; - - for ( n = out.n[ i ].row + 1; n < out.o.length && out.o[ n ].text == null; n++ ) { - pre += "" + out.o[ n ] + oSpace[ n ] + ""; - } - str += " " + out.n[ i ].text + nSpace[ i ] + pre; - } - } - } - - return str; - }; -}()); -// jscs:enable - -(function() { - -// Deprecated QUnit.init - Ref #530 -// Re-initialize the configuration options -QUnit.init = function() { - var tests, banner, result, qunit, - config = QUnit.config; - - config.stats = { all: 0, bad: 0 }; - config.moduleStats = { all: 0, bad: 0 }; - config.started = 0; - config.updateRate = 1000; - config.blocking = false; - config.autostart = true; - config.autorun = false; - config.filter = ""; - config.queue = []; - - // Return on non-browser environments - // This is necessary to not break on node tests - if ( typeof window === "undefined" ) { - return; - } - - qunit = id( "qunit" ); - if ( qunit ) { - qunit.innerHTML = - "

                          " + escapeText( document.title ) + "

                          " + - "

                          " + - "
                          " + - "

                          " + - "
                            "; - } - - tests = id( "qunit-tests" ); - banner = id( "qunit-banner" ); - result = id( "qunit-testresult" ); - - if ( tests ) { - tests.innerHTML = ""; - } - - if ( banner ) { - banner.className = ""; - } - - if ( result ) { - result.parentNode.removeChild( result ); - } - - if ( tests ) { - result = document.createElement( "p" ); - result.id = "qunit-testresult"; - result.className = "result"; - tests.parentNode.insertBefore( result, tests ); - result.innerHTML = "Running...
                             "; - } -}; - -// Don't load the HTML Reporter on non-Browser environments -if ( typeof window === "undefined" ) { - return; -} - -var config = QUnit.config, - hasOwn = Object.prototype.hasOwnProperty, - defined = { - document: window.document !== undefined, - sessionStorage: (function() { - var x = "qunit-test-string"; - try { - sessionStorage.setItem( x, x ); - sessionStorage.removeItem( x ); - return true; - } catch ( e ) { - return false; - } - }()) - }, - modulesList = []; - -/** -* Escape text for attribute or text content. -*/ -function escapeText( s ) { - if ( !s ) { - return ""; - } - s = s + ""; - - // Both single quotes and double quotes (for attributes) - return s.replace( /['"<>&]/g, function( s ) { - switch ( s ) { - case "'": - return "'"; - case "\"": - return """; - case "<": - return "<"; - case ">": - return ">"; - case "&": - return "&"; - } - }); -} - -/** - * @param {HTMLElement} elem - * @param {string} type - * @param {Function} fn - */ -function addEvent( elem, type, fn ) { - if ( elem.addEventListener ) { - - // Standards-based browsers - elem.addEventListener( type, fn, false ); - } else if ( elem.attachEvent ) { - - // support: IE <9 - elem.attachEvent( "on" + type, fn ); - } -} - -/** - * @param {Array|NodeList} elems - * @param {string} type - * @param {Function} fn - */ -function addEvents( elems, type, fn ) { - var i = elems.length; - while ( i-- ) { - addEvent( elems[ i ], type, fn ); - } -} - -function hasClass( elem, name ) { - return ( " " + elem.className + " " ).indexOf( " " + name + " " ) >= 0; -} - -function addClass( elem, name ) { - if ( !hasClass( elem, name ) ) { - elem.className += ( elem.className ? " " : "" ) + name; - } -} - -function toggleClass( elem, name ) { - if ( hasClass( elem, name ) ) { - removeClass( elem, name ); - } else { - addClass( elem, name ); - } -} - -function removeClass( elem, name ) { - var set = " " + elem.className + " "; - - // Class name may appear multiple times - while ( set.indexOf( " " + name + " " ) >= 0 ) { - set = set.replace( " " + name + " ", " " ); - } - - // trim for prettiness - elem.className = typeof set.trim === "function" ? set.trim() : set.replace( /^\s+|\s+$/g, "" ); -} - -function id( name ) { - return defined.document && document.getElementById && document.getElementById( name ); -} - -function getUrlConfigHtml() { - var i, j, val, - escaped, escapedTooltip, - selection = false, - len = config.urlConfig.length, - urlConfigHtml = ""; - - for ( i = 0; i < len; i++ ) { - val = config.urlConfig[ i ]; - if ( typeof val === "string" ) { - val = { - id: val, - label: val - }; - } - - escaped = escapeText( val.id ); - escapedTooltip = escapeText( val.tooltip ); - - config[ val.id ] = QUnit.urlParams[ val.id ]; - if ( !val.value || typeof val.value === "string" ) { - urlConfigHtml += ""; - } else { - urlConfigHtml += ""; - } - } - - return urlConfigHtml; -} - -// Handle "click" events on toolbar checkboxes and "change" for select menus. -// Updates the URL with the new state of `config.urlConfig` values. -function toolbarChanged() { - var updatedUrl, value, - field = this, - params = {}; - - // Detect if field is a select menu or a checkbox - if ( "selectedIndex" in field ) { - value = field.options[ field.selectedIndex ].value || undefined; - } else { - value = field.checked ? ( field.defaultValue || true ) : undefined; - } - - params[ field.name ] = value; - updatedUrl = QUnit.url( params ); - - if ( "hidepassed" === field.name && "replaceState" in window.history ) { - config[ field.name ] = value || false; - if ( value ) { - addClass( id( "qunit-tests" ), "hidepass" ); - } else { - removeClass( id( "qunit-tests" ), "hidepass" ); - } - - // It is not necessary to refresh the whole page - window.history.replaceState( null, "", updatedUrl ); - } else { - window.location = updatedUrl; - } -} - -function toolbarUrlConfigContainer() { - var urlConfigContainer = document.createElement( "span" ); - - urlConfigContainer.innerHTML = getUrlConfigHtml(); - - // For oldIE support: - // * Add handlers to the individual elements instead of the container - // * Use "click" instead of "change" for checkboxes - addEvents( urlConfigContainer.getElementsByTagName( "input" ), "click", toolbarChanged ); - addEvents( urlConfigContainer.getElementsByTagName( "select" ), "change", toolbarChanged ); - - return urlConfigContainer; -} - -function toolbarModuleFilterHtml() { - var i, - moduleFilterHtml = ""; - - if ( !modulesList.length ) { - return false; - } - - modulesList.sort(function( a, b ) { - return a.localeCompare( b ); - }); - - moduleFilterHtml += "" + - ""; - - return moduleFilterHtml; -} - -function toolbarModuleFilter() { - var toolbar = id( "qunit-testrunner-toolbar" ), - moduleFilter = document.createElement( "span" ), - moduleFilterHtml = toolbarModuleFilterHtml(); - - if ( !moduleFilterHtml ) { - return false; - } - - moduleFilter.setAttribute( "id", "qunit-modulefilter-container" ); - moduleFilter.innerHTML = moduleFilterHtml; - - addEvent( moduleFilter.lastChild, "change", function() { - var selectBox = moduleFilter.getElementsByTagName( "select" )[ 0 ], - selection = decodeURIComponent( selectBox.options[ selectBox.selectedIndex ].value ); - - window.location = QUnit.url({ - module: ( selection === "" ) ? undefined : selection, - - // Remove any existing filters - filter: undefined, - testId: undefined - }); - }); - - toolbar.appendChild( moduleFilter ); -} - -function appendToolbar() { - var toolbar = id( "qunit-testrunner-toolbar" ); - - if ( toolbar ) { - toolbar.appendChild( toolbarUrlConfigContainer() ); - } -} - -function appendBanner() { - var banner = id( "qunit-banner" ); - - if ( banner ) { - banner.className = ""; - banner.innerHTML = "" + banner.innerHTML + " "; - } -} - -function appendTestResults() { - var tests = id( "qunit-tests" ), - result = id( "qunit-testresult" ); - - if ( result ) { - result.parentNode.removeChild( result ); - } - - if ( tests ) { - tests.innerHTML = ""; - result = document.createElement( "p" ); - result.id = "qunit-testresult"; - result.className = "result"; - tests.parentNode.insertBefore( result, tests ); - result.innerHTML = "Running...
                             "; - } -} - -function storeFixture() { - var fixture = id( "qunit-fixture" ); - if ( fixture ) { - config.fixture = fixture.innerHTML; - } -} - -function appendUserAgent() { - var userAgent = id( "qunit-userAgent" ); - if ( userAgent ) { - userAgent.innerHTML = navigator.userAgent; - } -} - -function appendTestsList( modules ) { - var i, l, x, z, test, moduleObj; - - for ( i = 0, l = modules.length; i < l; i++ ) { - moduleObj = modules[ i ]; - - if ( moduleObj.name ) { - modulesList.push( moduleObj.name ); - } - - for ( x = 0, z = moduleObj.tests.length; x < z; x++ ) { - test = moduleObj.tests[ x ]; - - appendTest( test.name, test.testId, moduleObj.name ); - } - } -} - -function appendTest( name, testId, moduleName ) { - var title, rerunTrigger, testBlock, assertList, - tests = id( "qunit-tests" ); - - if ( !tests ) { - return; - } - - title = document.createElement( "strong" ); - title.innerHTML = getNameHtml( name, moduleName ); - - rerunTrigger = document.createElement( "a" ); - rerunTrigger.innerHTML = "Rerun"; - rerunTrigger.href = QUnit.url({ testId: testId }); - - testBlock = document.createElement( "li" ); - testBlock.appendChild( title ); - testBlock.appendChild( rerunTrigger ); - testBlock.id = "qunit-test-output-" + testId; - - assertList = document.createElement( "ol" ); - assertList.className = "qunit-assert-list"; - - testBlock.appendChild( assertList ); - - tests.appendChild( testBlock ); -} - -// HTML Reporter initialization and load -QUnit.begin(function( details ) { - var qunit = id( "qunit" ); - - // Fixture is the only one necessary to run without the #qunit element - storeFixture(); - - if ( !qunit ) { - return; - } - - qunit.innerHTML = - "

                            " + escapeText( document.title ) + "

                            " + - "

                            " + - "
                            " + - "

                            " + - "
                              "; - - appendBanner(); - appendTestResults(); - appendUserAgent(); - appendToolbar(); - appendTestsList( details.modules ); - toolbarModuleFilter(); - - if ( config.hidepassed ) { - addClass( qunit.lastChild, "hidepass" ); - } -}); - -QUnit.done(function( details ) { - var i, key, - banner = id( "qunit-banner" ), - tests = id( "qunit-tests" ), - html = [ - "Tests completed in ", - details.runtime, - " milliseconds.
                              ", - "", - details.passed, - " assertions of ", - details.total, - " passed, ", - details.failed, - " failed." - ].join( "" ); - - if ( banner ) { - banner.className = details.failed ? "qunit-fail" : "qunit-pass"; - } - - if ( tests ) { - id( "qunit-testresult" ).innerHTML = html; - } - - if ( config.altertitle && defined.document && document.title ) { - - // show ✖ for good, ✔ for bad suite result in title - // use escape sequences in case file gets loaded with non-utf-8-charset - document.title = [ - ( details.failed ? "\u2716" : "\u2714" ), - document.title.replace( /^[\u2714\u2716] /i, "" ) - ].join( " " ); - } - - // clear own sessionStorage items if all tests passed - if ( config.reorder && defined.sessionStorage && details.failed === 0 ) { - for ( i = 0; i < sessionStorage.length; i++ ) { - key = sessionStorage.key( i++ ); - if ( key.indexOf( "qunit-test-" ) === 0 ) { - sessionStorage.removeItem( key ); - } - } - } - - // scroll back to top to show results - if ( config.scrolltop && window.scrollTo ) { - window.scrollTo( 0, 0 ); - } -}); - -function getNameHtml( name, module ) { - var nameHtml = ""; - - if ( module ) { - nameHtml = "" + escapeText( module ) + ": "; - } - - nameHtml += "" + escapeText( name ) + ""; - - return nameHtml; -} - -QUnit.testStart(function( details ) { - var running, testBlock; - - testBlock = id( "qunit-test-output-" + details.testId ); - if ( testBlock ) { - testBlock.className = "running"; - } else { - - // Report later registered tests - appendTest( details.name, details.testId, details.module ); - } - - running = id( "qunit-testresult" ); - if ( running ) { - running.innerHTML = "Running:
                              " + getNameHtml( details.name, details.module ); - } - -}); - -QUnit.log(function( details ) { - var assertList, assertLi, - message, expected, actual, - testItem = id( "qunit-test-output-" + details.testId ); - - if ( !testItem ) { - return; - } - - message = escapeText( details.message ) || ( details.result ? "okay" : "failed" ); - message = "" + message + ""; - message += "@ " + details.runtime + " ms"; - - // pushFailure doesn't provide details.expected - // when it calls, it's implicit to also not show expected and diff stuff - // Also, we need to check details.expected existence, as it can exist and be undefined - if ( !details.result && hasOwn.call( details, "expected" ) ) { - expected = escapeText( QUnit.dump.parse( details.expected ) ); - actual = escapeText( QUnit.dump.parse( details.actual ) ); - message += "
                          1. "; - - if ( actual !== expected ) { - message += "" + - ""; - } - - if ( details.source ) { - message += ""; - } - - message += "
                            Expected:
                            " +
                            -			expected +
                            -			"
                            Result:
                            " +
                            -				actual + "
                            Diff:
                            " +
                            -				QUnit.diff( expected, actual ) + "
                            Source:
                            " +
                            -				escapeText( details.source ) + "
                            "; - - // this occours when pushFailure is set and we have an extracted stack trace - } else if ( !details.result && details.source ) { - message += "" + - "" + - "
                            Source:
                            " +
                            -			escapeText( details.source ) + "
                            "; - } - - assertList = testItem.getElementsByTagName( "ol" )[ 0 ]; - - assertLi = document.createElement( "li" ); - assertLi.className = details.result ? "pass" : "fail"; - assertLi.innerHTML = message; - assertList.appendChild( assertLi ); -}); - -QUnit.testDone(function( details ) { - var testTitle, time, testItem, assertList, - good, bad, testCounts, skipped, - tests = id( "qunit-tests" ); - - if ( !tests ) { - return; - } - - testItem = id( "qunit-test-output-" + details.testId ); - - assertList = testItem.getElementsByTagName( "ol" )[ 0 ]; - - good = details.passed; - bad = details.failed; - - // store result when possible - if ( config.reorder && defined.sessionStorage ) { - if ( bad ) { - sessionStorage.setItem( "qunit-test-" + details.module + "-" + details.name, bad ); - } else { - sessionStorage.removeItem( "qunit-test-" + details.module + "-" + details.name ); - } - } - - if ( bad === 0 ) { - addClass( assertList, "qunit-collapsed" ); - } - - // testItem.firstChild is the test name - testTitle = testItem.firstChild; - - testCounts = bad ? - "" + bad + ", " + "" + good + ", " : - ""; - - testTitle.innerHTML += " (" + testCounts + - details.assertions.length + ")"; - - if ( details.skipped ) { - addClass( testItem, "skipped" ); - skipped = document.createElement( "em" ); - skipped.className = "qunit-skipped-label"; - skipped.innerHTML = "skipped"; - testItem.insertBefore( skipped, testTitle ); - } else { - addEvent( testTitle, "click", function() { - toggleClass( assertList, "qunit-collapsed" ); - }); - - testItem.className = bad ? "fail" : "pass"; - - time = document.createElement( "span" ); - time.className = "runtime"; - time.innerHTML = details.runtime + " ms"; - testItem.insertBefore( time, assertList ); - } -}); - -if ( !defined.document || document.readyState === "complete" ) { - config.pageLoaded = true; - config.autorun = true; -} - -if ( defined.document ) { - addEvent( window, "load", QUnit.load ); -} - -})(); diff --git a/src/main/resources/static/img/404.png b/src/main/resources/static/img/404.png deleted file mode 100644 index 9dc273ec66253d2545255d59fc4bca5698a4eed8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27828 zcmZ6ybzGER&^HVV%7O?ijes;rr$~25NOyNgcbAkjN-feNB2v=bQnGY+x^ym`?}fkn zem>9h{s}whoS8Wj-jEC)(4mP21}u2vk+4enp$L z2O}foIhw56HGhX)A~%8>5167cqMbuXzZVY`$&v5eWple7S{{5;(p)51LI@#X;Ub&Q z+b$G`gOqXvA}Qa2!N^pUsA0i4I3NizFgPRxFE>P%68ZoAFESMp1kQ#2f2jT~5d(og zawv;IXi@*~4S=6I4dDN~-9N%$oVQ5G5IFj)4`Kh;Nsm8CK?lhGJNJJGaX{#ll$}Dz z(up|#?_t4Uw{(<82LBJC1SK-Co*@^E`{93h|KFcX+1&mgLNPFHa4;BwiZ3ql|2vEt zW{LHG?f57^Dh`fmb};o@@c(<5SXcw>fAm|0gG| zm{^z(D4LS$-(ho9&YM|Y@o58=O|vX>uqrIK4z?7QNgE#bJQbDo_4O|wzt30D1^lM~ zN}oq5%jt1H0aEf)a=d*Tj{wVkUkAdS;v#P8#{qktJ=wi~f}iy7Z&ai9Ub|xQ)%^ zQ~=Ed;y|;rMRI5DMMgdz8g}{xzRo1+x;vssO85!c!E7AmT26O#&#cISe2VYSff77w zapMbcF9vDGpNT*cx%wdaqBF78JjK;0lT7f+k)uO_6WPNX6j2GAyFQQJa;mTCr++CS z&mOPgvn-&{llRmRbbtvl5KIVuqmEqw617Of391p%-?BBXg;ecxJXD4Wu^cAPHCvG4^2_9exc82+j z0zeOxsIJO@Rt^e-k#Im)RJk=vGxjHpsg_x=6^6eI2n%cZ+<{Jx=4utFvD|X@o(-J< zup~^(AF!|9UM&_tuZcJy%>pH=6?{+@rb&QA=Vy*oyqW$L1(JG;P8T+a*rUaSG(!Lf zsf$)apB&~z2{`_vedHyaNgnHwHd##>Q@jvzluTB@T2v+;9O9&BQq}!e5G4Q4 zDXaje7&j1(G6ZjY44%5~qerAyAE^}bQ2mNULe4S88ul=}Q2rqMk5=Z9R_Aq;EEbg+wN<#_xeo!nF9q7zYb9>T&Muk@I!_A@PWS%W6pkb<=c<@Y$TCOfPDQ7 zFGs&(U%7UNvHYJeK9v&-yQ18VaRSz#;~WXyxl?DNcUF9m2LF}_zG^akyQ!o&qup(0 z9Eo-krb8;C-?mmuU1) z`}ctMmneqTfS?mX0KN=7Qmi~ewp!9gLJtwatB+{67KnFymva{__$WgA&&Ry70fc%J zN>qR29F)$Cr)vh87$HwUA<}%~sV$pa6ptPWe)LGjurMmr6N&bWbbj#JwGXPVtC4G} zP|~|#lAMyk!AwSd{m+IBQA*&A5FkI2t%79us@Ni5;E?>Mwm7r8d^)C>4HsZ#el1xj3+MeS^ zzUc#!cr;fW27ob_F@kvsN^5|q6>VhQHMRCz1}VtDVV5sq_+8`YACG4OF}C@zuR9N? z?(kqHC@5K4&y zH-eAf9f8wF67o}x{g)Wge{>~pDN);;fyjq1^lv{Sbig%Ia$|{r{Z<&yd_h?mRn>Hc zRKMr}UFNOv9TF)1NB8JL;n}eSk92l-OdKMa|L8_uB6n_=IRt%c85&b~ROheE$CyX} zEUK0kd-qQGQ^u;LgGZ{81Z5%W4-?^j5{d^UrSY_Cz?HW?0rvM2`HwSIA{uCEVxnRK zvwT3Z43K*(1&OExO{1r`{BSZJ;7x)u2(W)I9mLPWw$d)Dv4H0wyfS7XJP}D4|6j~& z$5{!JlOx_)Vnud38+ZZ?MeoTkPk6_c+Aqc{$OYY&HCV*DHk$0g^m zo1FBpPY*4ne13FRR8$m@LG_THE{jGSQBMdeq7jqgeiDO4LP60+QpEK~*m42Gn!6NJr%;E- zNlGhudn#%q^v}p69@)Xzi1NtihgZ337TE5>J z5rC|Dmd`${{I=@TrsZkYh@|Tj(*3K>WiV8k;>}71@B%OUrC`V1H z@33AJ0Y-S&pW9DPcMzC}R9H)znUDaE*Po8xI>nB*Zr&gDmKp+@rD>-!(khzCff-qS z9?b=7r1-`?xo*$BwVo{p(5{x3udi>LZ@!N{NOC~xEj27jRi^ap7_%`mUG_8NlN1#y zmx5U6vjmUDiX3ZRNx718)Z{7s^a>~AEcowqU<1Or>1#=o%e2&QIS%w+`~EGcTPE)WWvG)OJcbfzfJY+flTs?7x}{(buUSq7$16wBY1D7!n`eS z?3aDb{!^n2b17&Y`cLCU{{knFvrXIW-_Zm>0!>54GpVPBy!GJURXBaZAxx2jy;@8u zyROO-NbZX5(;a9Xw>$A@e}ZctPbAg6B~MYqwj6ngSypcq{>VY0c-NAi9$MnN?)nsq zR1tLzfPu)8!NEB*o>vu86FAfoxp<(;$yz+U#WMoaCGt8QnJf7q(ssrQVxoLMASh74 zERK?|2}81lhz}nZhqQn>L^c}FNhGAf)e7zEJJP7v37$6!Z3mALBwl|bUuZakvY3OU z!IZN;76<_M${5Sjo54rl@BIi9fUr>_6D&6Dm3d+vo`_=;8GKkQ8vIt|*d9#_J3tD0 zfyDkNFI(-9I&mS8m~KMT9&l@v4QV!iQE&Q>Z4<`jYe4ZAqJ;{cnX>0q`T~VsdK9;w z__m^7j*nwY~1Eo5#M+lh`9GpQIzG3H@0JRfa2#p9Ic}YazccQ1K=$no40Y@ z=mnw2TAvT+d*cG=Umb+%+p?a#JiX1gor4XUuXCzX=%Qhwn8gxN0Fq%ja`IH0RZjrk z|18hp^2-hs(7luoYK|fT5`!=0udH@#H?m%`Y36r8gwNf%ajNU{jWOBA20Z6(wfSe- z&cp<#7I(90yXnTC7BJ#+U=Y?N|3o{~+5UFvcPNmFT5wH{teN5wYexHhmwS+-6yD;$ zp66T&Rx$wQG9X%>HU{;}-rcc;0*h_!gwNoKU0%Nr<%Av+BMEYC_EzKi13|hlXRPyWHp3W>gu1;XapxR~KKNG_1|wxNL*Oc2 zq2nB>_f}Al6uhfQaRjxN2cmyP`z9FUF3sNQAAEKaaA$>Mp;5FOBAP&NLGagM;&w~kBqR6A5A`AhPj%W@F6G%XT7m|)>JC5tNUYL)+ zCE#5el}BfnLLV(3SJOMo+Wxp4866$fH#?_+<0-XkcSs|NimsYkJw{p-rXsZ+3X;=7 zWb_|`$2uHf z&BoLp`gL)DGk7xRFp6m#424v-^!4P6X0G67d zvQ*wL*7p9@Sq{<6ZHxChSnv^Z`QdIC)Dry$&{-x*E7m;*90jnI1H*x6A9r;zy8!>b zdM<$&GdaLeXdxWM@F&lD=W1JoCwT9Gi-5hcl_GlG8d1SV%YKc?Jy#quGra-XX^K#b}$DGX2y!4am<5*8FewogXR8p z>&-Id3!T2T`ZiSP6``}YeSuoh`E-@{E(5aiZW_+I`rRpGYbpTwmI`&LZfdVl8=t?S zhRp|0$fW%&7kv*g8kN!B{)_{H#aab;t`@7#)Ae+feWe-rLbMldh8~{x>53hsJrdJmtvyweA}*mt&b|y&}BL%{1hnc z%!3;zz7?J+L>>2w)Z-F4JXSqVzrAi$eD`jD-X@|A^sC{G0++yhP~05mPE|)UrLr0~ zD8S}hteGv3oT(g37T#r+d0GP9S8q|@Z6P+2QIwGWez`govJ+npDoGlk@Dh@M7N-MH z1`@nCzk{;tX#nK8$g!P(WHl#?5kbEy>im3Klk=EqYY;T$g!WC9s|b%?_Hr5#m>23b8^E>xqr&B+sf;cv0@F5!B}{ZXBaW3sT)cwWI6rPXN=8eBfX zjwGN&Nf!yoN^F-0+E1sRyVy&rYHfg+F7dxFJ?lv{RU*<`zOo@1Wey>! zp*bH2@r~pBc?|#jRn=Nj1O8jdAJtPYjK*Pp>1EEd3Nj*OEBb=agR;9g=2sPhkKGnU zypHJ(4-=)cmqMU2iX;e3CSk_;%K94tZE!;kiLIo93 z0VY}_Ni*QfsP&nI6QM(?N(}9i7c{HB^a2AI#}}A^+PH4py!0{hva{#EX5sX#bf~vQ zMGUzl_uBHEhMbCsSQPGMpvw5d^nInO{{YVt4k-vtKVYRb+sHBOZB0|VW&k?PstF-a z^E8|ZLzjg|C|x%)(>Y)J_{DQMX6;-y-igUAOm*@tdh91$GI3B8i8^&Ff{j^lT51j0 zmj9x4kdU3&foIx0rna}lbA#M6PyEIprBb#)+u#8yw)b1Q%nZvCp4L7O1U{<4Io`Q2 zea&jpEc`+PrP6HFZPE1#0p!!)qNa`k1?5kUa>K$?W}V>|$#1G$WPCKFD={RW`3>Ps zfx{#Dhh`>Q$KX`Kf2X0iOYph#+3ZbnGu?16?xX6k0vu^RQ7`hF4pm}Y(qlZJM|klI zqr2_*A)^R3YGb?0ANHTu_w!Ov*)IO^PJ?X|X6{4M=Rd`DRz(})-F_Uibo%4mCjC{n zyZe}UJZ>SKvS?!!D#ru=UX@{jolX$h%b{j89U5*EIiz$ozxkbB^tHXy{dM2gOgWK$ zj+USmsoQuRg>&ENg_^uDRGbLJM?DArY(7X$<}`n<`B+lv#s!xb4xvSsD{|*qL5)alNPItzQA3i_ z(EL^L2hUC}Piky2)oFa&WR%S-d)^mA-~A3|Q7IIcke%H`_7l5|`AM;Op1r=2>ZkIl zy%d^uG0JGJr~O(0V5d!_Na}~ z!J)xI#=*<$nE^)FkXWlhnG51gR2p*>H;*)?J=$J%3eBPCXxU{?Dbp!kF^Dk+JJps! zSy{&B7))xbp{1;$@2kWK;u?y4E;NXHpiO~B$@)z%RUCLpiQRb3Y%Kg$sLmJJ@$QSv z=9jmc%w1-9k(IX}=vI~-u;1#)K7Ekwb}_0HWYOhJC=*M^hi9u1;k+80#(U`S*lRf# z1K^o^l1N;tzi|MT)UcfSo^4cm7yb7;2ae@}8s*>;P|w0Uj%Bn_!t&Szz6_4_<(kb2 zs8ICD)eDZGB@gn3r2rhf%I7)q??huqZ*@rx@#YJRnD^RDyJoU!iUCX1{;7!JW^5ae zHHyTdd&*L0aDQSp{D>_h!|HjaU+M?)CPD?UqN0Jhq6`0HAJ)KXF?rDeI-Tf$xatp z6rZ`)0RLjpIQGv#8RCS-43l`ZJ!^gct0c%;cxNZ!$(8Wmu65$7BsW(@(FS5;s#R6I z+PkE{8-gG^pjGblp+w^6#Q?#xsnp}+V?kgZz&+2+01GI%Pu@Y>ARcx%ykVw>t*0N^ zR_`#L$$(n8<0=a2tPsBneYVu~E>K~Txp32wz*>?PyumrlPL423T|cP?O|lMeOLI|4 zxoq~%wx-&<_>Cv2haZIsmMqym$TL5&@~>Q*W7mJtRsyJbR1qCP34S?^dF3~{y4_Sj zYS=6Co~|4~vKM-^J$Z-4haa|%qtIWOhwzZrTur*#w%`E}INa<(DTw=KpyOH7YtLnw zIh%+d_5#l37O;L+?)QP8DtQka>rqz@xrqYtB5L;C+}!46dwPtNaxc!6D8&hhMV$?A zD$t|fN^rgjU}_<6kErf^rBm(HV9=@#)JO!dWDcNX@lq@y23xy1m9=x+VgCLn(3s&b z?7wyj8YsBK2E#~wxUgcC@S1teQ)0sAP$y;T0*!?%&eKRo9rk^Xs#VLoX5Ck^A9xvR zC#*m^Q=R3F9QH~to%>p**_FBx&7sg|KnU!csKuuKlAe{mRBby>fA#7|T*G_H#a(4;BQ$+LHW%;v&AH4oq3xDTlhZxd4!+jpF@QZxlA9 zcv$6wfHwigqTc}nyBY5$1Rs|luSE|F;N3Tv%^T|vKGw-I46~JL9Ze+uTA$4o-R!G; z8D7++^Asl5&%_j{#?JV$%J<@~FT_d&Tp!Hqrejc6rlOy4*nbd55K;X-FjeV^G?*5l zNdEiV6^GaNLZ!#9_enjy$lRjj7 zjd+Lqh1+=GSmz%pp)PZ_2$}tQ*W<#8+NuVlQJz2INJ#&^1rQwOgBnAyNy67URik7Q zi6VRdYNQ&T>ZAXxkEZoJq;H2kDF~I(OAm`pP^v%wB8dAKvKAF@JGJE>uu+1D$W!li z%~pb#;}^L+fi6g~oSM+p{e)<6=OOK*ac~xU<*H^3>gh%G_3j~FR;&wne-PPnXu3l0 z?i^XApPk#ol&8smCQDDK@Je|v3H($Jy^~s~t9JiEQC`R=wo8471=J!~+JNVszs@H( z6%F7d_sMrH9MgKD)E2iq0QdpgWo*W^o>N#!d zI=^p7!-XCE1x-BP;nW9c4`0+h+$G&Sf1V&h8g>`my{2P1F5G7P>Up83pm}v{s*d@6 z)vmxr^kgKlaZ0e7y0S%BS^*&>a@TO$!AHFa=wUErzBesPo@>vY$o3%oki)ggxBR{^ z6R3dmlCwmTl9C+r_%pllRF5 zGeKGE1x4gw5>v__0)@D1y&wwA21RRvInyea;i#yniI)sy+q64XoWs*;c&pz;n&NuM zSG&p_+8W8tACH?b%1M5Pz^9;-y{xgD@2%FR2k?B;x60Asi^6Oqj0a}YSz7iO+e4+W z!3mKV0_Kr574(dA{mY2}dF|E1y@QPx#VWsb=*I4rw437Zep!B9z; zK*?^Gr6xsa@d^Sd=S6rz$sEwqAS-N+HPk}9lQ(KD7X`_0-!YMAhp+=qs+*=~dVtp9 z205|LmmHN-ow=^`lXc@{O*Rl za?{^=T-Hwz-qvW_wVrYn6Y$jrRix7;QRP8au zu?NQ!c*VEg1~vb9!!jJz`OW@lj)by5MFep9Z98IbXZKgv)i`h-?4HKkGJ-BZjvnuG6^CIkzUCQh+Q?mS2n;AT-?|2Sncd*K7 zm~~pRnUc+RwQe_6Y(s`1d2MwY^%0c< zJ71AjVSEL~>hqQt!vo&EYzdH0x6*TwAGC|Fy^DjHZ&sLGiQsrYqSu?t)Vm%fuJwJG zKu477*Tu)B?I&lu$xJsWT^%+t=7157KMLGpH+>T5ijVHxWpZwR6#mrjFx{Nz`kbTd z1aX|%6ib%TTE@~}Y$f1UCujW{!t!h#{x#3&#VEExQ}f;{spV-W;1h$W89$TD-xsCx)f6&4d#O)&Iv2pF zN_xYx^p$6*)8r3JW;siHdsG_54@F6QCrjG#ihIMDM*#s?V5gmgI-3?g&jv-Qth?Yt z3~?Y+)VxgrGR1>>-=&`W_Qfb}HA~qb#uC6 z<@YT+Dv(~!Yr}X`J-^KUF{`b1ACt+7dxiPji_5}g`HOiPIrW!$1t{~G87QDpKi`Lp zL6-i!a7P}^i^J{P8@n?aS5V8e%O9t$skBGgSSiw&Ob@QEBc;6E0T%jk5kXC5h<2k# zI}JB#?75cDND%iE{X=bNdqFqXv%q5&+TVI9ACvSaB7j57@!@UPzSr%OvxeE)aZ<)| zNtgPj{7m%Abf5{Kvja<02%m$uHRY3~&u~`8qg{$SGfCY0_oCo&m@tj3>(|<+AMoM> zEu+s06@VHj2)F`C4R->nEk@UYdi%skDEg5H-=3%9zZys?4HQV!``>fFsM)SPgneX; z-hi^=N1DXHrF|b1M}NeS_j7(u=_?QXE6<#71}yq1$squ3m($SQjF&MwksZ*e$f;!M zdqmOw3(7%9N0-9VyCGtm0!mjUMkSBOEG?PO2fc|OvepI)sUT2T(DwTy6STVpkG*Vm z30zZ=8S3)^Kh0e{mY#&0zwAzd8&ktA%#PZ;?fxEPU*ZI67XuaMiLlOGZ>(p2qvPS7 z8}$yod)g6zK{c>VorUk9Z48*;GaCo2BCXcQZcdmqUQ7PFY!8SEquh`|qFBl$ndtM!QCFBz!PCaR8!gOowor9KGmx zhZHgId+7Q6as(&z)y=wxw>#PH8?QQ23s3s?4a2$`f-Pthx|Yk8!&e8)sWNl+rn{+& zvtBW8AJX-L0bG#%s9cKc6$UaME3(x~HGv<}b~U0?WKBYqr>i@TLNOeN5p#dc)u@1y zD+q0+Z)@xzfetH!L6a%v?Gh@G9SW^N&)4h%M2O4D+{tv$hE4I*CtC`i5NC6=8AXw#ur_pIa!k(Q_uN6+ZVHmSt{g%}rQAPMm36(8$2?K{vL#E3*7E?m71d#tjU%t(ptIxU_KSytzgjTTioId?2fo+yUZ?#_JWKWHFsj7 zKX$}FI;l*?yU=dlDW1s&0$2T{cp2?eqt{ZX`DzK*u<@?)H-K^Qwx2vED9xsh>;IwhgN01&GUy)QE`{zYq#V_UprE%j74EYAi^Ql5i+J!P!T za^;7+RL0P&&F?}`1PrmnM0(z>({NKaP42Z6J-0VU^aLv|*>s5W@VkqRaIP9jTj24` zdri?XrWJ<8nIukxa!SBL&Av7`#s>U~AhUOc`)kFND093a8?NfNo2$oirtLR|TWO)u z3)jp3Ewz2XFOIk5yW?*^5Ca8G(Q5GU(|4Fu#~t*TovWI8~H4$SA2Z| zyL~e4k&Oqm@#c^H3qJlBuya6@a!Q$Z_luJW^C?F?e3_$TdQiNQhQuz&#N0TMU-!FR zlb}~b#CHH_)${$JAO60{oba*HxJS`QJ}TzpzwX=b?$;lKdH4LVlOqJ%Ze=y=XpZ!a zCwN*N2Py;hfRa?k!8cG)b;iIarg%2vCGQJaNB*s&Wp?;i4d+z;H3ys$t~CVibVW|) zCxfS7A~v_vK7}V>^L%8>6!e^>ramy+`XULaN|xtSXYihfGl*uce~kDY5>lXv(av8V6~u0iM~pukXSl+krwTAI_(j``et zqT%KUpQg`_`)BCg-EHh0mcWiEQ7`cw`~QeTWMwLB1-kAGP!z_3_4GwS}kkpe&{85k_++E~sK?2hu;hunOT`kB0`YXYkE{Ks5- zK`qvPNZzZo$T}y-oL_#H*8X;K&9o3xyGhpMwcsP}Z1#QljgI(PzU&C07VcpXFc{Uv zHEnI@8fsg~FV+fTxw_xW%e{Vgcg)Mjj@ld(B8%)jvho$_drK1z?`|k2l}l@kWWkm2 zCQu5$!jJwjJeaGMA?@J!{cmV?OcJNQ1q>xKtL!s-EyVS*9R*9|x{c^Tv|u8J_>>|F zB`rI+wlTiN*theY(YFR&A%njk*nyG$aQ|;0M260%`zYKNVNZpE-5_uU>)cJB-p`u# zj=#9MjSewebJzITzhq}Gl`nxspC93^oz*vb@bkK;Z0O&-eiPx?&}%vnD0&rmM1~Vo zR`X=Lf*RRszcHT1y^&$%=Gq?TzQym^HZdbJ{F%p&MzOT&q7=H@@<>lFGK9#w1>cC7Ji&u}8ZflaCO( z8@4blN0Ue*3aF&{tjy?FoKSe`fNF8C4wxV{Y!lsE{vkP7_VnC5DSnh1MzllQMthK5 zK3P;`USj1fDPZO7q>8)M60aT@T2blNTl?&pWLM#ttFZr@Q79T@(3230ro}oxLxt;g zkMn*_D!g`NZR7~WaN4jk#d60&##`=t@Y$Pm{^^RQwu73s3i_dpL$u+i$3(b9I+(~& z97LvA%NGeKx@{j#1L?-T{nIML_cwxm9FsdiN*iHuG_Ssv^H@*x7NQ&$N=bE{`(maD zh^jZGjle>qtSG9hx4_VK{7CsOLsFi3ogU^JO3dTrDD+MJnCDmj=KF_p^_UuE<^#g$ zhC?U?rwJr{c>}9OFX%fB!uW*>L?m;GzQ2c`2QB&2OntiGFnXuw{KOVT?=xQ2d#RM%c(0t{d#ts2G_P;PBO^$AWndWtO zM6%j0Np-&9I#={ZN4LEbWQnhCplr1q>JbG2iu54}HO!3-_TRg(Z*JF~L^Y3cG7pj& zqp6#`+;!9{aGS{OzPkO{(B?3?yE-mc^PrkBd1AYtZ=gF}Ji$s)F)t!#(tL-W@gS zg?r1lB#4#o(hoH!nD&%2mjx&;@wfrNtue^fcrOuf4JiB%#2$+xP>ENQvsA*~;7^f-TDz0b)e5{h8C7rz*V z`_MjgdSr$y)o1Wt%fAzjf*5_Nt@n%54)ak8Z{|E3<8vsqm%#_;Fn4_2 zS^;in&F+eXVJ)p=tNi49UX;S$yL3KN($Gx}DDdcwI98j^Nxp~T(|@MQ1@r^(jwUXx zO&)}ylSd?m;kxO(3R`wj?pP#oG7jYqkb+|jdFGFGuefceHaUvD+DkSR?B2CIe^G;D zm%r%wqomzSOBh{nHF=WqB81H|^Tbxc7!hzMjgvhoAhBHmMM7ToB)g#qm-j>UUlzr; zSe!6Av_Hc&&6YGBf_?iyiA1B#pt5&AO7Q5hmZmQa#8!wbc3A^`cw?j+Eg>aM6qobk z4YM}wdxlFbrQILfEB?R_fdd(S_ZOOKU4{1Z8Cvwz@`o4jzKH>vgqC$p$~f*c@_7oF5$x1RL$qIOybzcmC%GD5n|`?L6~%Iz zYfj)dzFvt(>DxxC-Kt1&)s6pRuNnkAfu>sjlc|(+RSh`gTd3a>Ox)tN;}9Y&C+GBC zCI_c!-CbyT@;y3A0_;Uy0nwNRYnu{cRL=>6#LGi~E#$5)^tguO_q69QV&192Winq0 z#b^{Wf}K{InrXa;zG4Y?4db?RMIA7{dcQ(PKscPwgs zN)PyJ734D?cf>SZnN5s;=(|a|X~1 zKQ5dJywpwgpdYd6re74rVcbsJ>3`*ZoWh&oC1@OBZwEiCz#B&Z@5}g0&srqE;)Q1E z8xOr}ogV3XWiuL=0|!x6Sz31Y+%85)TQ6M~?$)vyvKr4VU!0v$E{K+4BAQDrx6cW> zycfz$Z0Zr#?DIY=Za&Yomxj0m1^tc;O7EGG{ESInOw+z?SoC#pe0WaEyO4dtWA(WB3y=IbC{cVvYf~ETM`9Kv3%(D#GK4nPZuK3VjB99oB}VI_$?o za``-TIKw$}xE5nx`&tjFV$ohF<6Jdkw6wEtVi&$a;0794^`W5fi+Z)u-Nnt_p^e;jrR*6Kwvq4JgOsV&8QCs<$e!I6{wyP1RcIUjoyhxKF zmacGpu6pSdTY1fOsjsFdeoxxm52iEFGk0;a+HtF@akBxf)N0N88}F1UW9uO}o#diA zvKZeoW7;zCb%Wiks@{Wf=DgmC`_R>a+aDst!FI$jCy`|SVj!_pjz`uBB5g_p{Nd)c zByTZ%Y>HN_u3ky^e7z1z*NSluIudpjO_zcWD~Bl6=;0&2mjm6E$=8&=&iEmPi!z1X zz%%*t=sJovwT=eNzFp1X;*QwDfP1L-74#D~u1G{~m*P-NA>ubRF z^!@b4>w>#0QemPu1C=W!y9X%BRhG6B+m3qMfp_Vf4sYJBof4y}%KQNmN5H&Gj5 zE`JypgkT{Ng*Ab`uNdxFz-m~-+0Kh~HTpQZoK9&PyMY0C@FaQRW~9cS9&fL)8cp5T8s^{&Zi>E2V+Y>0JMTZeHS@;w;AW?a($^7R+`0o$TPgv9 zMWdyK>;t8@JNE`f?X+M{%SW5q*_GaMx}i`?z6z3)3ncutuNFfl>2?^#g5p&zoJ%d+m)$9Cu+SQz;l7%Gu7D3aRI(cPqM-_hxp_`1d>9f9|G+4>SF} z5IVfKASfH&-qXph1taXAx%vF@xyl5Lx?M^OmNp!ho}TVEwG*emK_q1dDh-TJ#xUwy z!LF{I&`+>3cQne(xZAX~uW8Vouqqt=!5+jmve5ZHUYaN4w#k+}M|Y_c9eEn~f?!pu z+MeQ5`594%x7HgMs{qB0uQw?Je;@jNvlro;H`nHr%|J^+my|(Ymyl_0$4imS zw(G5b=`v=Ipa5CwHh^UHwP4)B7*{ShO(QON!Jtq0Dg$lj_lCj zHOo#F@{5|;!1~=;*%n^3DtX7&@(EZ!GaNP5NUzsAwQe<5GSIwWt=Z3Zni704j(KGb zce>|=ZTuW~K5hKQy%U|G@0~8QMpnA42ZyF5eCb@z(pIKF+NUL+VGz za7c>{Tow4MIm~`hBSIP*HyEuU@Zx5Y{^+YeCV;67uMm{yD)-;`E_cz6G(7Is*Svh6s&GSr z14TS7NB`fq0GbFLHVUrdb*qGihTvDWgC+49<-Vm)X<*uR@K?WAM=P$%9WRpDYlYRa z#a!y^95_mKTt60SGo5RvofrRWysr@;@m5!UikucC(DgB?6qE&OZ=}k5W@Y}mlwy0! z^xlbW>i7Eg`tH#l-3u9C8bx1A0+t?5?f!rC)&sotWe$cJ>Dp%DtQ@&ddx%z!;VkD| zqp4hGDZxr7rvauAFw!$!9=j@XCqwiu92v~sQNplGvK==!aM$17muzPZ`ic5lJPEIV z*N0mkjzpDd8=bA9kvX?lCLkqaD48FHyBxjC82liez?e25DzCqA_ip_(qLX{rCIAqrq$!q$=6Qxupwp1>U5k-{9YF} z!~UQDMp)mt6ENMZt`?0w!s6y`gDw`Js^!z?1{xMa;5TNA28K@e@2XGqtNDjU3_uoI zJ8|vHcZXK_oa}wt0te0oI)g7=Y5qLxUaBo+sU^Q4OfB#!p`!%mC8%LR`wdErZ&Wfe zJa`=!eyC^5Y^>h22C*le_4Ylt?#L~H4r^Daml8^Eo8!U%=ff7kK}fAC>X+A~|6I0; z7e#M#ojKq+QUhb%>z^&YIL;~SGri?JFvRzGI_74_3p*JDw;3IrO8YQ2cK`4}pVdK` z#7GGEh>)My)UY^x^5Vsdnz`&rFB+IvjJvs69g>r_clpND$D=hB+k3ko8as)Oy9X|r zonwEPLvq&mhU!w!xr0{TlN)rjcj?de9qgVeOfyoXE#5W`D>}v+W@VK?*?(V^ym0)qwC7^E^zp`r%81F-#)epn>dQV8bAjOtH`Nz4=9FV& z8#(;;*}&J?_s!J+-tBr7W=rZseJg=lt3a9W z^pRxGZj+K!QGm`42D84dR?f62zKqA$O&!8Gc*WXS)xzGo$1|ck8OK!2#&i ziZ{x~p~hJn$J!szNms<-qQ3U|ZH7O;GZ&%OA1)P8o;fDQv-+m$vjzDiQqhijX%-Rb-r?p%dvb*lGZTbc_3>3&FZ12 z8#T~S9uCdXYW(^FZIY)GP?ww-{p$IaSjzIuSpbM?x0&6QDbkF04o{V$sM|~CwyI|; zQ|OAhP4}CDCU2nH z&xD>DW`^h`W6r2#=YH>co8N%bKZ^C?a6pwBmI_}HBtlA z&Wlb)Z3rsf8daxVm+5g_JOwgOvS+$0jn;ifM3ve(60B!tLWdJoV}AnoRgnKZP5}J- z0{FLkq*r9{MMtaka-xh-$zvYoian#ES3r4rwU!?Auh2M^rmK3`<<)`F98*8L}YZDuM>JRS$cj*X!Zk|;Wc$#Yx; zHHF(BQs(^B`nEtnq-IAOzL4C~Pc!&jqrZx}Us$PGoD=agscw_k&N7i*+r_yV=iwOiw`a$s5MmK~5ZHq+U`knc zyay@E{g#v&o4ML}8EI)Yqort^CW>Z(wQb$0=!=#wxNEMPOX0EC&?NgDt2whe(t`Qx z8Pj;yup49fQ#r`p zN;(uokxy|}Nl#5<8chBF>6i@+j7B^+AApjk1M+xBv0 z6T7HxC)^0aKjrs{UxyRAzf$XK15~m;({!P#a_##Cw4NK)=5?5#cf+dglN|V>lWQgpp zuCwC7i_T0k@;Q1;qn_=T@vm}C;jd3v=DZ^Fu=;krH4O#EBdk}xdB$mV4E`Fa3jCVcH9)?*raWEN6tR5^Ff4p zA~wPxzxv<0|8kk0(AL%%G9i_>G}X_A5ExSE34kNo|4AARHl^qKbGYS!@XiyOFfS86 z0t6apRy-0j8;1GP_@ zMe*VlZl=V`6Ozy0#0WvXzQFj`kZmo*GwtA{gaG*F|Ab$_v1fIo!k&=Uo0fuvOt!%~ za&$!ybWw*Gb`860C}0HmqkDsmZF>V<8Ee$T+_f&XwMoqZRQ1Y_FbotkiD(&=k@a2y z*oA_s0hd9Tn*!pySM)DAb9MKaTGBbJ@>Y905HBE59P%a3a@Myy2RRm>itNp$UEJ-1fA zd`#^X0^?7tL5off2RX{x_ezvsD{_%M$^cGzm{G}H5Be1jBXfHBw;C|QTK6f@DsPFz z2;-CuX384h>}@Oi9k8h&8`)lQC!()b#P{gNN$>7_QTi>J9UN6^V0Txlt~xe0b~Uvf zG3B@MLBl)S>kpWDeT&{EjOG9BQ=cnfx2k5`-)I0;@sItBsryASI*UFlWNW2%e;8c< zMch3~FTHcBvaArmqS$_sAhllRR5>(?008aC8yLvxgsunu^`Dn#>AH7icF_GN;KH}H z{oC-Jd+5CHQ14f+P!B&~l35A?4KsG%;t(_^c3A0ik7Y59o89YIbWeNGCwW(`$32eY z)Kenq)M^uzp)ARgv2$AOL&DL&brC3ZG$w2IKpC{W2~Wd_22F$H;8MwE04k7Bp$!g# znHFA>oO?TCzF)pF$&h2TLJ@w+Ja1%ey)&89@}KT4pA{N-ce8o3v$>NQbyiQW@)#GC z0!@~D5kx=(6QXJ^Ue;foA4nNXg};R;&B+>E8h;YgJ@y=)*0_q}8LS5@gDju;98LeD zpky31AVvtR>!EBOn+4d2K9?NG83c#~sZ8H+&i6B~aU&WMP&_0zIaO*^UGJGEo)Fi^ zr1JZ|>AW>%!kZ}cG0yU<<2?AL;XUV*wmDI%lW^`|>o42O59eMazy|#5%`Be&$%qX| zWRj{Si`@mb_Bro(YrNfNaHjTG3g`Ty)p9Rl);jKqnu*o;j9=&Q^TIcK46iyhae~+3 zyLAnh&$t}@^#t?H1^_@?djwkT`17Mm^5nrjRFKXASOjLxrw=%W>9OLjNx5aG7q6Qu zy9^t4S|??0ThUt44`A6yT)TD>)A>>soa(jxyBTYQ!%umREfl`}a+m766ayFstCIOg zTEb?3Dm{+AzIv)DtfI&uon@?%nc1UgYx#Yet_j z%nChF_;qWop2!h})|$X`JOVa+fez{0vy@ix|KziZeB=$xdbp{ZGqxLjcbtk(i2l>? zg=FxQj@A8)0RzX->e+wf4?EGF6?p^OcEXB*4Wmp8IdEeU@#r zWLLGtk6l%Cy5}}6?;XSKt8M1mwtLz>;6NMzc9w!%9ppX!x1!_qn3P?RnCQYz&_E9X z$jLlC-Loo@kcTzGa>gDu11iw{mEe7F z;->5v8T3#xYdq`vhG zK2I-HpTNkqQp88Qk6+x`c`lBq(J_0xFMQYb>g(|E@U`Y1$?>}Gl>36EyJo!L07P#? zu=aXz@aM{NnNFZ(MX}c(|BWsfKpdGtJ&ev3|B~o?Qv8l|w*Qv#=}s4xs8e^yZfVQe z>~4)V%TZUYR1zD$^=L-Q-BvXV^kkGGt5v6b|5l%jM7-kF&bW2w)tIYp-t`yt?gr2w zXhI?zRry6{A3NOk3BVER|6+?|PJPUPD=q3&*d1q0!_<2)VWdZkzjRBa2dGzSsaS7v zx5-kz*Q8k;-u)(9)&1M=5g9cbi|De}%PqwSX`=zFv8FWQK*BX@uFhev_6>?K#O5*JsdUkL=Lb9uHd6rL!Nh%DWr8L9^Gaz64c7-(C+8=CRwkiX@eAb#-;o z#|NvBuo}AEUa<$u=UnW|T49LPfeu-ZSy)45pv8Y4>{#M&7IE#lFLW3a^cT9X%yA38 zQ!kr3f4?UTY1ZiagadPQOiQt9YBSMlc7P?oBKem;ZflS@4e(6OgRIlJ#oTKY@(AdH z@3ADxqsDzfA!@ zBEi$w2MyRTI_rMpLw>@+@t8I7y??LWu{~F((iXMy{ey#VY;A3y`3<4(=`k&V43W*_ zo8TS(LAywSwWO=kmGi=)Qo%@fpC)DI0q8>DS@@kD4G&NFZfqk{k3=_QvH@1!EAz(i z^@rSNNoDcZRGM?BPARZBw#X9xH?N?Q&od3$>}W6=Sk&Ggo9QGS&45r|WP3q=vR|R~ zK`HGLPRsO+@Z`=MFT~5m)b!WY4u+|z>3X-@sCL$iB~TGByq%vNdHF-G;-`HVW}viM=fmxpK{@16)_$F556Q{9zirU>yB_oKnu@%8 zZyTSsc~|GUUg4m7PTs!QzXymO)Yo13Y^+L?$P`B7{K^*d{H+?1trfS!j-V74pA^AQ+?^t@59P}9B;!ZW!~7X$m}?)SEOM^gD#_#SmE9b2vX?@MG(Ld^SjNfFm? zC(7AmBx!;&IeJZAgtjj)ANBGtTn@dBYH38&oM8TL%-P+rcv{KB!_(I4eN`)@@#B2g zbwPHOn`OmVI8`tu3`ZIq|Ltnq_z%Y9+@kUZ5 zAf6S`J!$=$aK~%=`8|hcPodK+em(OdD%@*lT7o2~5e?bRnB-66s$Y^w8ZCV zUe}?9K&Wo*y*Lf;qJUWihk=Dc>AapM1PzrQE&9tu9=6t#3k6!-YayXt;tHyzI0O>M zE8~%*IkQc3TJE*TBVH%_zRIuYTwMG4TFx@Osnp2|3ByfG5%nV$NH#V$=inGp*sjhf`(P;OXJ8Gl6$_kGz{75jq%B*zmnp$mG6_c*f# z8b8xZK0sonY!@bdz`)dM|1GpaMgjWrkzY?UNlV64!iWa%gh**nxJPf-h0?|@0Zc37F08ShHCgNb;BGz=&X1?-oXd6dQB8kZQl zBoj&D{cHZ@gpRak`YbZC?h1C8s#$2a*y=6ho=(Z3I5xurVWV3*J@_)W7O%zH&k}ti z$ld59^-w55^{G(R^U7J7h28P|#7q|F?l&w$4<0;NvTa~VfmZ6nH7!=!$TlM`w*@Y&CuEF5w^+9Atg6Y11Q@x#SPpKh_zRJQOmVuRMpAOHp$`Ts>!@={e*RmLYl zmmSb@%q-iwl6h!%rpjzWs%vW7f5=L4_mi2A2?@Gh?c0e6*n4u(>CG@sCzE8$+JZ46 zCT*jZ6vxT!iqG_0q`cPC4FL68+^Jd?_|1L+ZaH2;K0b4am^3Byem!JFA$kxswO#{$ z$F-Ld3KoY~t0SqlvsI2fsTCC!8EWdMS1GwOZIVAo0zZEf8C@W&HQ6v-Q(YOK30Lo4 zHXj>w=sukgNcR~qxV+rLx;;7+DrSm7t)q zeTkaMQ8z^Lug0*cb*!(icdZYmDFeq+yv@Lp_2PFV5n#_^R2%0|PFx9Li_AB%jO);1lhRyvETuzd7~@~cWhooW+&*XQ?YCetX|w0oi? zv+c03FiU=WNwPS0HBi3@Lm)X;jgy;0iEy`2;#owGa32WC%)+gAbNDqGOPA;K@w@Sk zr{XU`)Qg*=n9oS9BJAu3-z@Xyn_TUzXmQhqxt%90SXXlu^J0cC7J@CXyD}+F50B+^ z)M%gc+7;irW*X(OeZ1&)YS^5u^wn_;vfiPOiWd1IN2$?W+bBkboz!yJL#nfc49oiSt~BafBw7jzM5yVHv`}z?k2Uar%gi z#0VIo&+${{f#hH2=5#O;h!R`S-Ca+LgD;hgD|LrASBG_N#Bf2*Z~r=w>it#KjDnQ> z;K-AwiEJOmvtInz{4pD{V3X^b#`JT3IB9HtPUrKNBH>!ghfD(@c~~i7BGJDkD}J{# z^yyR=Y_<=d?belB`^}R6#{$2fDNA3Gkw*pf%sad>Rer6dvGmh*F>TP8^Ng8NHRnq& zjN@_J-MtPbA4fO0D}zK5TVvyustd2%0`V-+w6s6|W`q2#dY{1PM}xFJ`_D~o>-8}M zED-_&X(AYM`{@Szk0notQYF5}S|x0p%XcHEb+Zs-WGvQL$vEG=>!cyGbSZ&5^E);+xLyvwVryguRcjzEmh z49$r;o8)+z<2BXPg}Vvo+&!rNH1X|9&5V&{WTN+eJOUTi`_WCIl9CeN=;ySzqZ5Gv zD^xFXf$eg3Xv~oR#hm~HLVhRn<(!L)8D)M%8d+5(>>zZCsPlVeQ^#!qR9;LJQIth1 zx{n?`3ZR1CRaRF!)mfyd-;nhgtM}%W>*_qR`O(y*jp|Kb9k;u3g3-Xgm?V$I=#Oyd zA%FKc2cNBO4==o1pO}oSd9LJwnhpAr5iEJC4N(-D6Qbs4IsVVBfIBmghc4F1zjksu zdBGS@!puj}Lb`G2rkH+?|CEB24!SJx>>$$N(|Vh`zK6~BWIEnzPqWJ%--4Tw1kk~< zqlWoj#|B;JZ7lrO^#@<3YR~kJnNc>)riMG#XwDI;_8D)DUsS@Tx)1}XKKkvH zg}f{pDF@nFcPL@k>c{k&8`0A zdv^{}n`Oq$)%kwH^= zT67lPlgc0WJ&N84{q-v=OasmGYlVzr1RV&3S~;Zt)(KVuVoJ)p;#`Y!6VBwy{UuFR z+%&87zICh7%&W(g(K+(l-eXUzy?%8$w=)%Vm-N2>{6aUPTdjx8vu;vVPXCuZZH-ay z!PXs%svOnMJwzgOuwK~N|K*)%>cf$GdU|{erUn*S@!#@Urf9@ICfoE_JGn1WE!(Tn zf{-S`>UN*zJtWI2xvKKQWTx3-h=TXYa202M{&C|UZ^u4;fohSVrARZ<)BJ?a<@cAY z1vLUW1OyCC_ zn@&m6meZShc4bSCyQM#^hiAAiND!was~$<=hIaedx!E7g#9*~YV*4Q=u>!&L<{%(K z<7n9hdCzi9w9q&dXK23KCFdGzB^amV4plSzze?z3$4KYR+dd>5h>3Cet|W!mM?+|{ zR3h&>y*YK_c(^Zmow?{JVj(yX;4^HR3S;vgaJbG99cyd5cCEh1_3hDU6qA?lTSq}g zZq>NNnZ|=)`?W{iKfoi>yoW^fqOyH@I*W*iaBZLY0%7M>g;<3s8}Cjx+qYHa?y@p# z&GQ4%i>^<+(}`z|qpz|%O5Nz?M9N!QZu)L+ZlV&r5L|)~kf`h8dXCv5M7XBzOM}BsuoPWRL87P<6$&WXx z_^y*gBh>95#5j``m~+Ois**1~VnLm8ka!W{$9w+h-YqRUkD|YcPjp}dV*T2kL2wSM z1hiP=@!Kzn#nQ^6jBPq4+C0O7LRhh(GBkKy5)xfxy$@NRqc8yeV8XrWGZaFTXPF6* z?Cfkikc`!_OujdWiP(gcl9Fn$*lIIJ?$Rwm1_i%n0!@zigW}v z7T?p;(`DqR$(z9AfPsMc9u-5;5TV7i>;eJ;`4+Q9n@)|Sa@h8PVzi?t&zK2Y@`{SA z#xXCbP@rOddVu(yNMXhhF-7oHJwD~-miFpR%*to53{0(WnvpJ@7!3XZI-B zi+VT{f`^CKmQ&b}$C>P;8JO_C(vle)1DQ>dCYsH9q4{EtN9lfE2;4m3l+?2WF>0cI zh>G&Ha(BO2&}F4-WaOY#tAl)|PYJ{Ia=$w3XxgfU(mp_hvQzu@dgVs^Ec*9 ze!;Ul2V%&dr||-n&Z%OwxZa}pXg;}ld1e`NZzV+F0x2Z`0I$Kh1JtVw zn5OEc(&9Sih_T~qYe4+-V28gSl`3G%0w;i79|?CFgxG$5+i;<`#3`}eG?s2RZ^udn z@DLna-JJXy+z;tWJFl%_AhJxsPy!DomZ<7E_Mz7>e@2x2}=>X|7_5%sw5h*~RwQkfRl{2Qrfy$U%}65!?F&TzIplpBO>Cp{#Z zD)`P)Dre!Jf1CUIic)M@7ypvt0Yve@iIV*@uYJz5A!AO|F7|_}(m`nf>=&GsWNvy1 zIVg=yO+yn}m(Pg+7sR9>zk3U5c*&4}%7p``M8=AbhGnI_SF2#!kfVQO$}?oo@1>ux zx_@$d>g^A!e_He)pA>@qS`8sWAQcu_NZtMgF5P`be6(|ml(VtILgXY#d&3bQt;y?{ zlSgffcLNIx3+sAGG^znW@yc1j15UkrNav4$H2=i@_rb3aZpAA-b@e&|wEJaqM^-0Z zULusyt74<;iMKopb5}@vk$ji$vqgY(@qwUo=nW~sN5lJ(l%f>h3%3%v)vqLZQyV(C z2ZBp#Cf|+JIWo%GOUHP53JD5QV7(KUu}s4o1jZ=Vt_WuS$xZU@K3GEv+P_9W5;ZZu z2tj){&r(?EvXnKl71FhSoE)O9v|J&5m7n5iEyNEl^li4cuRP*lgvksP@5JG&mN;0o z2;BJb0qbOzHb%0W)YV(qGN$YXR>u{S5^rG@=NDd$RAK8#W#@OavX^ykPjAVDG?5wK z!B?>i_!fp42Nm4>eCY^{?R@R{T`Jh7g_~&gzuZqW(Tn+_reAh0^O>soL;TC6haUJq z1^JmlAZhqI2-y2HHZf&}SNn4D&s;-V486ttZ4d6mzR=TK_5xbjT&gez6>OzTuiLxm z)g?z#-s;xwp8U^pe-xexD7<%z121rX)QEkRD{6U4KVyd0eS6qHkT;f|6F9Y~v2A4O zD#0+i>?4Bd!xA=*bCAmHwXvIF0Yk1-#L#OQ9i6#2s~AZdxKAL_1#Ae!V*e2c#Loa$ zfy%R` z(sjziuY_x0JKV{*^pL~@u{g7`b8%(c`-=^m5kDK_4op}@4WnuMvh6VoJ7fm`y}{k< zFeAu@w+WVR?AIXf5U7%f>ZAth01OOH&O9w(v0}ErE?hzuQ%eeG)>UTLZ;k`Ub@f*^=Q=^;`Zf^ZQKgd=yA z0Q^si-V;0sVuqBE^15DT>;BggP4%J!hy5o>wBQppQOQBqyWf78E}AfuQ=*{^77vn~ zG1vW4^PaP(CaCA3^R(duJSr+H`gkoIdG`mYcz7`l#z!7E`Y>5MlAG6CGlR{X&YLL^ zNpIboJ*RvaBXcqI@;ddD=~ax3PFAaWhJ;C<-v4K=ncc*9Z@t0C)KJ36 z2!o!hIpadXgra%u$2dW1(Dt-E`ETu#5izfz2|LWKb@2^G{Jj6)biRkPko#s5eV+DYT-~DO3C7^EA)&Wj-7ER zEw>*okhU2}ckJg`wJ4sdaT|t{piK^5&;IwNWfg)LR_|O)>J?~l$;DqOq;b&TN=rPl zqPt1uz*v%Qz1>CXHKuR1UXIrtgF}L*cMZL#_3tE>%?TbTD!%(*=M#?k1O>gnu+DPp zf$h+-FJEihUQ0VFHY2lnp7tQy#g!cIQeV1z7#>FZ-J;|166f82PfqZv@LSfd-Tbsv zYJ=%#CKEr zScdNUOGBwMgilH|lZl<)-H4W0{N)){-byN*QY6N(?JvfvBJ${Yn)Zsp!hdJ#{F@wo zM;JWonycCPv#NI%TlUC?yTomUD&I|$l{ucL#d8}F^t|I2>$*nD^@djOcNDR0=}?rJ zK}!6;=bgyL!rk4yb$))H4w{L7$-U+F5_8O3K131v=iprKWo&Ez>A@OVdSc?SysWsK zqkA|ATB>VU$bUim2*>U9i>xgO!ju=LP)i6fgJ2~SnH2Qck5HF}{ z{K?uk?{N+{g1e(#soGQ@|91-i#s{-1MJCoo`M+?TCB|LDnel_y{h~$E;<|{8dcV6Z zV`;3HD)c=Pj5;p(;j;LDzvtfB!r=K^@GO{+Q9voLf2Figlphn!wY4iw3%2;LHBu^{ z`Lf`awFLsidHK=*U2h>P=E%7m$QcLD*Qxm_ygMxT0Pc#WR4CkonMdk^c(E#pVmcdK zIkk%XdxHoN{_B1srvJhMvoQb#J;+%Q>h0DqQ|^flE`pp1V5aHWk@pl3)a##&t2b9F zjW!ftmSuLw1vd+2wnj$c{SQ=_aS3L{FUa9dBDh*yS$G7<`8F*|z1h+CZmsI{9UZry zSo15z3z+HUNP`KFy5;cxw?A>glQfT-1I{TrIy(3tv{Q3Q2M9C6&6()wr7T-R@SC^C zZY+f`paSTihG`pZs`_fMzjH-vlr{gJE4eY^*O8GA?2^rj4Pf1eNc1VpB^#5ffGjMF zHTuN56ap69#0=->Paqi1C3disd(Oac^?z_BM~wxSB|`aaJ;=+7da^QNf>`PW#wPUf z@tx|&>QVi*7GX)W&^@Lu-QFo-u-qd)UEKe0G#nL_WKIN`^B9$^awp)xP99P!Oii}A za*Z06qxw=?TU+a)mOCb2N!f<=;b6&e51R`9LzV3)9Mr{Cs9{WYKD6EU}mfOuvEd}f9N{@4H8cArO%CwlsW$zWU$7Thm8sa5RtLLR)hx45818k;DG__^{77hjQ}BOyEQia$fLAXt^LM-}$s%ve zK?Y=wdK`;~VbMaGH*ou#OWAg^?Ekl~V0?Gt-u9rOH4dAQH1WtN02j;R+62m0Ei3OT zk!HG;|LtG~7FFKBUEMQ=G8YG0Ab0>TaT|60!?(f!7MfuYA3B=#>rXN4y%sChzyII& z9cV33I`=yY-P@|F?CRHP0Hka2#ak{kP|QjAq4hJGqVV%(T^`4za6K3N(F?tkN? z`w9mYzySG`DU0Uwo(Rtvwag()+j;|Wp(Ch;WzRF%UXuW2g*{*N|2tn0)b8SU7jFOF zlYwMXX!|DIH4B|f(W;(3=%r4MC+69cd#FPo^hEA?+G~ui;D5h$Aq2vqqcCp_ZR-XW zY0i@hI8(yT4aUS%uc86;7hz2FMQIC~w*WSCEZrvW*m033=Mk_+T9HDDO#Wc|Gf#;f z9<(2P>%FTsLPkvdTMB?x?J4Ta?mfzEZ|E6m)>KUgqp#G~+xw&^YDuHuvxz5gNIY8= zu3IexLATcD1&9+*D4|D0PzP>{jKoLHXfU-I4&0Gs?`r)*)BNBl1gRA&mUhIdb6Amf zISB{Zz(w38XwF<1Lk=BW}a2MO9LfLwxnK+Hl`peF4$hk z0`1ig&*Cn$OPAHRqa_dYTcG`+y|op`xGu0arPFn7Kcd8jr8>k}WVEX#KRY}7OjTXo zOt>;7HW*3u9$=*ZmlkQe@mixnQmVHeHTEfu zW$l8)40S?x3Up{kUt)KZ{>GaJmh$9yi%~fN4a?Cg8^y%?cW@V-2F4!Km<{F~zC(!$ zr_@f+OZ-x#?R*~m&CGYhV_u$+p@NOrX7G%L64w zWEpZ$}L#VA~~^oZIFT#xX6Q)iLtvI1LH{)UBj% zi}`9meC|rgb7n7-HYin z88|J|l-8xIS_DP{0FeJ$UN&tzB2~DF?P5WhQ@fQ(S-8zbpO(R z&VVY$mD7&wH)`-HeU*VOp%Af14$NlUb6=)v4WM6%@B5vx-1jp%nC zzY2wl`d|gzLw6gWSXs5xt8woO9+^C?9KQoE%ZiE$dR8!OAGQE9*<9__#wO<}4)`;E z_ZRs>))pwhB~~olReAMQ2fw2SLhq^>EZ3f)@2)g+b@-2b%k+uojBdZn`5BRZ zo%Ac$+XP0qd2{d)2Il@A8$r0F$0xdr;Z4p3w^pRE(Vc;#no1@Q>lsbgf;6#o{0?rF z=jDEzk|^$rqyd~DG89Xn_no8Lv$c-^R=s$ zUr)5udH($QBIk&u@4Lk+JY>T)NHsHdtyrFs2jDm{yonkL-Fv&0tcvv0q6sx0xNcyF zrMw);wtW0;t}$mzJ3Bkg#tmMdQE$6nSx~JJ;)<>)dpw>EkIJUl;ni!_#-9;Haps2O4 z;oW6W+a1JDJW4N-#D({)0jtvPNxp7}H^x&Q zMFBIv8TyCJ6pCdFWmQVQ12_M)`&ktE`}q5PGG3!HtFB)>wZdiH#OO`@APyTx&Hmjf zRV3>ABPQ$25?X+s9`#v4NZs+jKSuhs=HhWQXuo^2$##hRQ!<>Z2i#JAm-^GblG>p5 z=1?dJ-38jgVci~SVj?*qfg{)M1~R|%uUQqt*8rP|k$3Ua8hn1-mG-f+nx8NW)-Uar zBPCwWVkOkp`yljviFmmoW*P!T9UbO4IS@)1=&!v%W2{pr$Y51>c- z6`LXZ=TDwIftys=4n8aUX`ozcnbdVh1yTOCl1**sx#EKds&x+jaluU}IchfljQ|ld z+Rm3aX$G$EsQ~Is=h@i{#p>+{CjGid$845lxd@NN{Y!MH97#iF)Ig4!GaT1f#^$IA zg?WF&TQSugOJ-ci_TJ@$^9PB-T6wOYF~5h`6vCtSVDW95X2rFR&*dkl(&sJve<=URD?fNO0g4 zh!ACsgt?OMtP2qH^W1y4s!3pC1J+&a`*7zD?uB6Hp7NoLY%mUoiALl1^ z0sLx6+uFe?uOTO|6e!9pab`k!TBtcKRmkxOhu03wZ+_I#yMx;=lo@fu#x%Pn4(A#6 zj2VxxDY>R&KK1I`uly)x&x%!6{6hnw0?43-A;CwDUrvZ&jkyN5a|3Bx`%`dcSPX;s zHNO=h_t&o+a=Wz{~gTsvihkLPrCa#j<%>x#qkd_ZLCB5eiNE6!7KPQc@ zdR_nlW$}WZ`{0{7UkYQE&9DE;UyZ}D0bzYrUaV!&9aN1CYuZ}kn3YA(UH@n3WyyCh zFiS5UAOGq1Jv4{{sfY{CRPc5fWnd!%JI|p`AtFKlDlxxo2dVOM1K*j}AGWjACh&Jl z$h}bAx~T#6bxdW6kfsQjwzf!AfpoXr2?)rKda_w@nOm@D>!vYuH^_Gi1c=T5 z5ZnsX1Xza;^RAV}7_*Rs%q03WUKBZP+_?)XhIt{Fw_~-1%Ic94T(XgMvOu5KIR?9T zD>w0Th`sv2-Zj?qE5!s-MT_n8bzQq=%+AhEY78*t0mpYQyeAvum3ssP1Wx!tV~nj% z_y3Xv^2YeMzGUOIYWL(VC{;+ znF*R=l^8mcg8Nhp+e+bn>D{^#lrEek@#K)7$#1*$IVobjly`FG4$o-qM%4skIS8zm z=N21aOb0%uIt*yxx(W?z?47eVEeySbn}fa2&wg?!?OuVMJb0#^x*{zJ#H-~PHkB&L z=bggL|8c|Hv7anPg_noED73$O`S|#&lLHvR?(VHHLiy4hHg0OiUlBz=aR%k{V?B4$3Jya7VRG>|izows;Pminy4W;JSv@0*AE8JpDC$lw;(ai)lz0xX|HQshIY zMc&Gv+SU=+pmkbI!A5*=fpBI-Oo8vC4IP4T8@Z+UO$nRD9-Nu@NfqZjn<9OLgO}In zZ;?R`T%fwhAx-$8DN;I?YWNwrW6N zVu{6FZ{!Xq?u9Uzrl-vB3cDdQ<7y`n!%@cRG(1nA+q2aGNxm^4hvmNXzJprU3N6$? zJ;1`kvS^!rp!2YF$U&4ENDcKOTw=GJXzA!u%B{L$Wb1GgwK#D%1pr2R`n`V`7hE8K z{eHS?%sdiyqU_l?xk`oC$_)~Op40nXCK6$Oyr9YpQ4ve*JLi!Zhs zxbvXUekByg&BWKw&#!3(AtaPlIabH4wG`j4lv2lT5m_o-w>RZR92bu(ZVJz>C#cY_B$!e9EgK9CM{VsaX2H`;hGqMcukH+4YmA8yIWK| zY@cWUJ(m9{O<63W@2=VaC2Y^dAtV2ST|hboQ@o*TCR;t?o#VD8yr+VbS$HoZ?P*Un zAzYg#RH@16)Znx`p8NSi&%0^6RmIc(kbld>D)cRw z&kJp{!t17CQbhM@ox=f$%`cInn#iGkhwMM&`KF8%f0uQx;PyKBS@{jG)`npg6QBW= zc*zp?O;Oav`#Tk*-Wp3j4M`Z8Mf!qpobb70apb4=NH>syN7fE5Kf7pcwyKwp`FSVj znwR3tY0{m4nRzQr8SaZ^XR;Xr0iku?1u zGgI#7kG(%oiRtG~J9%nv<5E#>=2XQQRMqNZsT(!1}8DJ%3ZQD#HZF+iA zRFbF1hH#(wHyN%OcN0(aA@QFCuelwO^YL1g{{2)^;UKhc{t0a~-%w|<#?byx_3K3o zHVT!j8XJp=%pG`$G^rzsXb+2@uV%QahP`uyON7dmR4r~$dYv=RJ_RYaV&s7rUelm$ zDh-}I)vA!;^hB4)s9~l3aLf8wxqt7wCJaWEKmw};S=_=No#|2<28J|Y2?@K%vW?07 zo0AJGai0%2=ETjyG3?)yhMErAjBU9l`)P*2U`>f9V$gPCzmLSo`0wZd0@!)CgcTKj zd+*}2h^}t^m+lLM547A35C#jk)>)N=G?1bdxPL~QpCySr{Y614b38*x-C#%opi4O?TAOY;99^gtjb}SYan+HdgkoR|e>F zog=Vh^u$fZ!@XN|w!3^${}YgM?lUy&D;q#@|>x=x}@lKbkxN6q#E&aE#jtMsK<4RUzBQ*%& zPPN@o?)xH;4)B9oio;Thkn;(g;iR4vrUzPrdq&WsM>r}O-#7aWrdrkQBl*sdR^)hE zjb=6(0^Iu6nYP%~-JOGUI>vj8@7IT97qukuf296pU&-xpgkxdPVWU7MANj}UK1g8! zUS5xy)sK#iKr9t4VptV1ot_&;^%KezUU6%5Kuut7^lX>?Z%+hW8k8BoLu-~wWI=b5eQu#aH9)FdnaD5+mL#zas+z#_8xU>NSt zWqY?{xPSFe&A2F|$LE9%-^{&mhK%%I{J;CeVTQS$6YGBIiiJRBe$Y<0_tx}-Dy)_@ zJWDL@#yU{=sX;YU2`A~7d&kbv8HA+L^2aW+I7;}TS!p>Adtapz%Gp#8H{(u|Y8GLv zVNv0_eZ808{p4Kkiejy*t>Aucw4YG9g#V54N_5q52Ik{CGSU89ixdJV(fsD4-D`Vy zABo-2>S3Ak-dt~>fTreXgOgKRgv0LqcEw%-iH5BL5Bql=AH)KbA7HBRW$coRnP_Qi zC0LSjFiCYwRu>S8YQ~}bzNg!+TV6l+My)Bh%Vy;^1ESYKibVc30`l15IEE-lBWC^q zOk&(qhY@f(MF#ZfW8o%hZvw<6J~VLfN)G0&K&fDG^1|>l7p^r(;xR&xGR$lqczUCR zY%4LJ6x$E%lAREnqM$ij!i|vob_fIuNArDhmkj2sH!+>s(4+6xqp`@jV@+g3rN2tGG4re)kYBnTrokS!!qVwChrM z(EW56%?+&~;a(yGTFz7eb(HGf#xHZPqLOnBFb|{0-t?+}KLxilU`jsdngd|N{r8a+ zoryuYAD5=`Rna3ib4tw*0J)vo>;3Bk)qKDXN=!n+ApUHsp(=iBvg%8qyPlFfFZ|h? ztYwy$1PB*;rXY;$fdh@h$;Pw5vt`RjiEnszr=W8pcOC5X?B;f&a<;<_8Y_>AzHg6W zw`X27@X={(m?f2<*}vae6sknh%152vzr5y1rW3nGYo zHg9LuRvk;)b@Z}(3Df@Mt&Mp7KQBPI*CuuJbwUCHzMuQQ6~3PbO1hib4TuSs;08q> z@=iJiV@5zVcFz-bNL>aBeIxOq`Sp?z=|_)A*TJ;;%e$MNo|x)-XMW~klI8H zJA^Po0>K)a9TU6CY(2e4*8YSxw-~q5lsk&#)$^Y7WFKPJ7n8(<7bFdqSNC<|)iSO+ z%Q}m5FQ~@6nzz`a-n`jp#&SV*8$~`(P@OixVE#Ru&O)&B`mKKbzuj^$>|j?D%7+C# z8v5{LYB%08&*nd-Nj6PXWkMyW;%~C{vN8(LF7LLaQ7;yBg9KJ-BVA-(lcFV0PH$K; z(#Rif6n|7Y=5XPkoGYf+lAev}WL2El=wbt9JIK$`GB7a-iCT+4UtZGrefjh#KDZ2f ziwt{@ibsA23W_{Iw&Th0KBaIk;O$6D>yy5zH91Tf>pnAXRD?pi+^sjti|o&D?B_0e zr4};}a)hh;J~cbKr18+_Cy?>y{ZH4wT64@}`g2J!j?;)6zJxI8a!%`lj!4h|ybaM?jf{`! zkB|>mc(w|Wfi8?Uw4KqfEhsJU-?r9bBW-fA_gyA_#~~lXb2X&p@8*2uK%-qUV}=cR zYcKo3o=a6#%ADQAQ#^e6QX@}iha~QjG_dyCqy6xf;s^f07*~X{@znBxv9PfDHK=5J zg6NnQrk3)SBg$ea182rE9hTd5P0B6t3-3Fyvbdf=t?|D80iavZ>wFSc8}cW2i98uA zHb;uG%&szDE#`!~jp>Hg=G0r%C?czv6oeHt#g=H@slNKlt`2(VZ1nf@Lo?T8qDYW_ z_h~|>My~CS5e_{DxaAHzd9j5iAtjYTU;I63o*a$@krt0Ex!)eR{Yn7lZAYnKzI(0w zi5@|>707qiWhHg-piz{$*WDZ7D4G(bKIC4lkot^89(nVD*3WGc&*7bKE>a;F_M+O6 zC=5NF!r+@)LIi%!)xMv!a97ZbmF?8ERsSODI9@R_Iyx%M!NGAv6>TU_zAga{*GBcp zC8mZ0BF1#$%9Bem!vjT|IoR2&&aq_D0ytO#8R_Z$EP%>5ppw8dmQ0~bW&9YMG#)P% z*kN0v0G@y`JgyOgFD8sv(7mnx?b?%l^xJK~20mNG1dU$oeQ=tuT()#QOzA~V1R$*@G>Y^m z4pT6GDx%SX(p*lGVDzlHd!SWch62@O60P;37;cMV*4OB*IU*~!qp3ABS}b(Ow+<>Yotq#{08hFK@!$nDca4|Q zFPtkNRcFfWfdIMj<>hse-+cbT5wlNc=G;l z!sB)w?oaStI%ESrYy=o!Qp{vNh1(ck{1GuMG0J8CRX#S%L}>qB=q(#)L-h8d6jn1+ z)sY#!uDu^Wt;Jd2v$L)Erxj3V_O_%Z-a|+~eVWkRMD4|>d}Bcw z8K;nx>=0(Jbc~ds8=DhR0~O?SHDu-#$VIYF_jGj|u>mz39csc-9tLc#Ax5hT-Hr|F zoZz?`vh-{1Af-VhbG9X=55*Q^!8|)FKs>U!Ufdg!_Md&|P;ubfmz!`O-Cv1xZ@&GJ zCvPx8Mk=z^?*r5-Q<95sQ(q0Qui47jcq$$sPaXL3+l8s^ z)a;^HLnP`*IbUx^QUP5)?}J@kBg(Mj+;oK*e#sx6#lLg|v_}0n;mQ1`GSW%x9Kg-M zpPriPhYxRR;kZHc<&+#Ud3FUWY0%x|GdT_m*)K?@r{VO~`qIk|3%}-mx-piTyCTG! zypl1YmMI+HlE)OXXUb4ft6$jXXy8?~?)`OGD<0d=-8pw!r-5z!;pzxqD*E)@H468Zl{v9JV`Ma)(I*e|2 ze*XNqni-gwxMCeLA70vh*I}I)Tjg@oy3w(tjFjRxj`$m+UpRc|cohGeKcXNiA!%zf zHv8$2Bn9jlX`jc7Vf@+PfSewkC7%9qphd`npF{<#*jsTB17elY9Lc8VPo4Wn1*O=F8&)kl6Nm26CnjKZSH6t&#dk9cec;549r zavyX23+}$~(X!eIk+i;^Xc`IlB%v!_df0MgEQLUMewbweO|v+e+&P~P7=jiDxL{Tb z&tBPPXv044Mgp)p@V^LNmxK$wqDA?2ry5A2ZG#yKG%Y*m|FFWRR|Re^TZ`!m?$JWd z(R8+T4?Y_grKyI1^bEt7|Gs=nUxJ}1mcn7Y!mb$Hi^L!-qkE1;zH&(D95xbd?@W1^nyT={hmTDaVB*?dmuo7CsqSoUJ}zEypR$Kd@p zQg{<9aa)PIQ{y3L4DfEL--r&g7UI?p)UQJqRmLg-UA^Q=(0~# z14PPo^<6>IlNNekD2NP@$sY!5bL6k zLt7oxVbixr3{OOst;hTJ{IW=3HT1dzPj<*Nldbtv>#ijnB43nelW34A>FTkbsnP=(uSm5kATT_n54b-r-Pb|#v zuxh&N$hfZ5N%g1;-vHv#1_V@!154`8EAg#(ViP^q|j?}fHzxO8) zn(?;~b8~Y8Mh#vreE7f9e3YaJK?^zAhLn`l$DBA|1nm0XKUOFmp4~2)lNvqO5LTtd zSD0(==}WO{R2}x;MhRanmxWKPy!7VdQ;uPk=%EjExSv^$U=dBVe{zN2EGmIH=|l#y z^GlkKP*0{_ySz1~Ky3=Iw zR)h_YuSks6o~{;#k&4eiIxjl&Y`)FoEsoxT{P18*Yq9d@Aylwu9?!vxq5DLrYsoR0eZJ#jB8OY4FAV{^g}_|5uM}X-E5L( z(7pdM4}ZclXMG7dKfID5G2ZZU^w{ zzT&vrr%2@DrinpR;hwU=H>;nok_HHaJgr%aDFxwQv?vvFI1O?bgvmQxUSoc`D27R{ zpH`PGVKv@?q_5BKi&niXd+K@xbs+`WhGtjwN{m@h!5IFqmJvO7_0W2fG&M5ji@1r< zNqJ>EO+;3toPye$+AkB1;qXrIob?&^uK1HjwzY1;4ln5&s>biUV2APY%S9D*2H~KZ zaG=OOIo%|901}BP<2<4V30DJ}X%XUG)jjI(x>lf>RHJjoJv#MsK>{A0#iaLLltT?W zXgT5v)IT-x`A?;O;RZrVYTYE4kAtwlGBa`PXISzOQ9@yacgmS0EakIybEs zP*+)NDvJ{JV;m_?o4dR)gbT4L@9$t|K@XX&;QZ7lXVUjWL|7cfLB_A%(e|$AMv4Iu^sXnb|1H8x2g-xKM)zBqAdt zyvoSA)%V#6(nl7ah#K*7fAY_*GDixDD zFe^3}$@oja{?$1g+^4@jc`we)WIi*{MO*44)g!W& zbqw(kO>7+77KwM-d1&R@<3VjKiGOO<8MGF0gU-*8r(fuUdl+X1|L3JvMLnzW^~jo2 z{NIaH4{yq2`g~JfGMazW%^nn&x*9UvG?R91=|2p7YIwibldkYZ;M})2XOVB-oPWL| znx=@{+Ps6!68Ugf8~jd93atsqQs+lKl z0^yPq-Zbq&%aSEsX8j;%p$`(41*(nrT9@HP`#Fr_qy-+*sHl?3XGS}N-ig4-I9)@7HBu1*OO4puMDhKA1_w{3T?dlwOx_X&kaxA(KMmdhsrf;d&(t;9^!!1}gC zMnPLEJt`#Nr7YO`F+$K>#XYwVyoo+5<$R2aEgSyel(u51fowC}j?N(_L6=z#F&HWk zkQf>{>UPdn2 zoZ8$l;&y{F;8LhG922>0zUN#0J51pf8BN~a3j#!Alm<21@vU{r6Gp21p09#s-0Y|e zKFI65ng}+{6#9NdamSB_+t3p9?)>4qho2U1@@z#RD*{Ja`|CW`)ISc}oAc9D6aWLN zC9~SlQRM5_e^pRd&Q#x$MciN#KvS$kEgndBzYG$It-fK4yvFPP{x%cFzf7;A%*ddL z$Un!Y%(I9#0l$or<1;ETVIXc#ZPlJrAn%TPV5>2FxNE`^E2p3J%rMfb%Kl*GEe_L7 zHqi)`5qmUnY;S^Y#8?^Q%R<9>N&0*KBfo|2&y;b7rxq0c*fdpaPiYe{Nq%{MVns;O z#Mh?0)R&#sh5nKrb}6dC;N5dG+AWLo)OpHBH=qi*EB!>_0aC{KUscZ9m@Z03v=kW* zmWs7Cgxx5hRK%K@)SH4qPXbVtIW?L!cX=YhziojNz&@HkY=1^dMwU`9tu7^M7a%g~ z@Cld5=_YX3nv=UEcn}iO!Jn`vozmYe`tdgL!~@#yBBD9LgP-bE zw??vad~CU@Nl_(eK{Usxgk;ZakVzocWgB%VdeT^O{YlT`p^-kn1IK93PQOHh@LTP& zmnQ=@=Zj*^Cn{Q}yFZ>|o?UI*j%k=L{Ow0$d-qlz5UXqbK2US$AxXotmK7NY5pN#M z0h90F0`ZRpO0=D6!3=t6w-H?!z6_7D0~&2|9nJGJIrUcPA1W$ZWq-?W|2YHeCur79 zHaJMo-LzSBq7KIsfSqT&%a%qIVUCjph-G8bkny^BxP7QSHoN42{HvzktAPDmSy{1e ziesJ7wHT8O4sl?$pzI6!S71?CJJ2)N3t=FP`dox;-!po1edNkr^A2a)nh0Y0va*s% zHgD-~2~X<20jr0#rwF6v3_FTi~@gawETp7qzzGCc5SJFO2j1TIJ+ z(N~?%F~^xF40x@-(k^8oRj7prmIOM@Rnv=?Ddi3DGJd#B-`~S_GlRzgQJC~OF7XlP z6LOHCDj{bR?oE?=Y|-Aa7^k0Tdi}czT?*ga<3(R+<_@pG=Ev)Q!WnLEouc5~^IK6b zi<^`*fxj9Cf1<5%c9E)zyxgpZoreNMS&Hba_N%6YnbU;+5dlH(Z6Jjn_;F<7{hbK8 z1s!MP&nyPoSB~d`>iWWWKm)Wf_rar*A%*!BARtZR$=N0Ug1H#Wv-yt;XBt|LyHzy4 zB#VeaQy0GBEyhR4Y}?B!S1c40A1|BJ^&08kJ^S3>o16IY4%h0L8yt2Xw)J42E+7RF zD&riJyOIx@zXt9U>$a{}5M-B>(63jWfq8bP)7Po_96a?W)a}EHetj|&wz0Kc)`SVl z4#>AZM^FxG^le=anJEPmyrS)IBw$evaS6XIZD9HwjJa7ezl`okg<2$f`F55hZ>FRn zMk4PB?Y)GYQQS`Dk_Gdp4cha^PZo!unICYE#Sd$EaH0D3Q?K@x@ye&vB*es@cCPNK zY7VewMIeaKSXFHrc(*P!apv{}{^TvLmtAuv-_bXq?tMB^?EkB!rNssAT1FsKPlo%i zIecDFu7Gt2WTifZKnRr6srl3>icD*7*(~L`L26@%7?c&2xYgHJ3uEW1M3W#@S$)la zlPVrL9gNwkv|DqfYb0AM^F)2qk4FIKBtLS0DiZs&Bl1S{v$K^t6HQQ!H{(Dfmn#~9 zbpc~#){9PWsG~4=fc$c#fO0T$_lmnbGkAT}1q2)eBJHJ|TO-tLqDLN3OFn<3XoPan z=edQoGTe%VLGqE1?W&hfILxuWh~fcmg-Dry++gJo)4Z2&L@z05?Waju754tcR=~6v zFU5dcM6rL(;HU2*u@5q2p@t#>j1!j-P9JEtnDN7>AJsU&KSG!;!daoj%%zOq9~zu> zyGX=-3zWGobXPd{rE|J_YY9n8+Lw#tj_{pM&{Mne%I#UzNa7Bm9O`O(NBCGKC|jii zrJMoX@gW!7BgC0W%{o98@v9BxU=1BVBV-r_zdML##N_5HeVjepyA7AD9e~Zlp}*Xai9B*qMty-1Wp))RA%vvA;X6yh^xpe8^UeKS0NX(F;lv&_=@lK(-DFkj8`Y3x@I(jxyw{M&meEvoMF;;c_Gpo9r_G6HnNQd0E)$w3(n zRdx5b;kzEN6Y%sX-eS=bw!;f|^$Po`msJ~a{fPm_15o)`SII)%TEmmJUA_+Rzz)ux z#+65p<*h16KHHqhul0ta2<^ru13qv_qHdx@Ij)--R7`z3z$&X?)Bl8iS}17nqa6j_ zobTYSFm)TK-2TDOmNjBbh@j$fwr(rVH~I_XeSvRrgBHAv^Ni?3IA993>0l>2^Yd1~ zAC}cbwCm`%3@SPHY+CSQ<^JrNQ(WJpK~XZB7T0%H(lCFt zJwxNgPzb1sm_h>b8uNIWA#%*K5`eAOFndgWbOCjhn>itrI&u3k$_@F^x-a9dS{U%Z z_J+~;OW6b^^-aHPG*0?6e*OvmqqbhMBu?a3DdD zVqDY*4!ntrDbE}0pRNSuNawpZlw%q|5m!hbW_YVXEk$(WVCFela?sNH4>`(`Q7e{L znB}9dg=mB9!iXCw5kDIP{QJkbn>HU<_uZH6DmU!(kyQ5`k9PF{<$#0G9yQKPj`ec? zqa_{8vJGvIt_!|EOD}4&JP@Z~S9fO%>F&zW8mZLwbW%oR-n;W=G&S%%S4vqKsId!Y zT!)xGCYuV6QQ);U|6KFfim10<;Wq$CQRCBS@Rlv=K|&uxB#)4(^&8^_kAa{CJ|*^- zlJ$zUz8WdMh(;@wa_>Oj=nOV$@17@%g*Y=zd%tvo{&J8HmJof<<`P0NE5%$=MRTBd zs%%{@<&hjl`21p1UUQ65-o2JwDe>K3domTGLe&p|=7qxfWhbjKaVc~)1RpqsJ=13g z=&Qi`QB7pfq21%{bL7v}Y2l@UG`SQO2P5-5hKPXkdbLId%jl3hz> z43^@Z99AlU_Qx*&<62|)o%&0Vx2AR9Gd>=ZN_d}<)VI@y+w(mwULD!M4jx_^;Ukn{ zq>PbHUCOm8u6Mt$Owj@UAt6t`ukyJRYj2w@*DFc~iVjcIbBTk>-#5zLaEvM+xJmpP z#Um|dur8NkANMfwq+W`5eLx5ao0CC3JwGzyr+{s=QKU;l-{B@V&<~iHXIsD8_nAzP zAos5nf+IP74ch9Wzt?pIwxjcyCS6~MxMVoRR|>coCTA;QH)j;)b2-D)pAJ^=C)d<) zepZ@ZAMYUPVR2B$xAhlnxi0WSaeAV`vXQ>l-No#V1*d9Z$UlCI_#9d8#QvEt+<{*U1|pz`{fbS0B9|2;j}zXZ=Isr z45S#Go*+QvmVSS`M6gACxd}StKexBH)2Pbwb#;KwNC2PG;==rm4~)Z1#WdeK62Zoy z%XvZj6xHLyt_|fQKl>B&s^Zdz0^2g9^1G5>%*i@mpxMLH8rjFl+s%?{(YJEZo&aYZjiX-(Pu$ zl?d{A(bpr^PFk^`Rh9ljV&eAaXYotE33(2_*C%cBJ4SzR-N-_v0}TL0;X zr#%iHX^{xV6!YGAx5^b6Od46%$H2%aD$=YRxcgh)18i}Gvzn&n&AkFo1g?L4X3#&+ zL-gCv>3~4#(cVhPWO8!GW_`*XIR~DLO!TzB&E9YcE4u%w4nNrhbWn;hJtcjjiMC>UW-VaS`c9KEIVUJL5qs!s z_orHeuQ5DEstV!ZX22I)sixV|3xpt+2zH65ptNH_f;X$*$`guq(KZ(6rw467p#Trm z1N7zyVZhhm6)?QM+Riuvimy8^rpgG%whYF{YgWk9iC;pRgmC+_qq?g%cl|~jrmh=! zb*4N8ww)Y}eq#-s-HdxkS#GQzmk8R`($IRw=h3XM{?Qn-U+7&2&$}ONe@ZVSA~1Zb z@0-yZZ-G{B#tYBbEKS+#gY6^;5R-W_+D1aA#&M%OEp_MPsf2Gt_w1W_R(EGc#F9h} z$LgeSC5TXqZW&cG-84xtC|fM1@CMC3Gi1Z`m_mCVuoK6sJB(C00rbYEjhf(G1SQ5x zfhIJsiWvKF0P9-ZRDX$RB;N^^Jzvp?GOuz-8q4{SCkK-BNdczeqg?#Uk2j)mv%&Lv za%)m97e~-)>PRWCE&8}?_xYpYC_VkY#J#cxLO1MlF}D|wdFxC|r#8;TM;57`-gC80 zWbMjRm>-tF@aeL`Ww?pkm~Iy6##?^@4{=W)%Cmn_z7c}S0B`3-c)`=D3mfS8krIut z4mW)3b=IVosi`KV&VRm;^yBEr@%|sHPkv7aFl?_jxe0a@+kNTzkR$MS* zt6@*;XgcunJnhh}^!zK*9aW!}b_Q865w?0>SrLNoUaURjAgKRU1s(`) zKe2;@@GWwsA0PR@mih-i4G|`mEV1f|F~ekz5V#e~tZDMK4_9-I*MOMX z2;Ys|jkXE{0_{H~XL;;$6zj;%by3AOdLz!NGmJYwtdc8obwEz*!!P2|_2V2nNh$E0 zbjrw9on+7FaxW%@f}}Rw`X9-)mg|n3S8}cjpgdfjagETbvfkjogqz~!YhTvc=g9r4 zs=3vnZ^Vg`d=ChIe2}EO-j^R(SsT=F0wGO)98Y%WwqloZ@=z0=P zO3-Bd+#B!4OYg3YF$uP-7K@&^EzNP6k~;DKJcwzE&DW$#K!A6BvbeCVPE)N5qN)4H ztsfQ~fmwQOl(?dSz0xdegh+RcO`>q{8bBHmDdA`bL!AZCR~uW{Utu9|SX3lIwV%|~_ak&x>n+r9I4DW8lde{tsbFRyB-_}!xOZhYq5b>M>h>hf0^ z+3;I&z1~6w0C-UlgTM8c|J9KBL4(-03?ifXK^*=&g8meqe| ze{0=Ju=`XclmG!WHFPMvR!tdytT59l*YOIu&qUj)1;ZDz5N4vfn)g%>bG$1+e5v+4 zt@zH*$Vmas*2y%-B$>KDUzTKwd6iAtvRfkuvg_&BMI){opwD-GrgvkEBNcszl3BaT z73LGBK8O#VS;0>|Io@(!eTx0V8ci6#p1SARBntC2;0fdV*2rwq0wJE1o_WSG(0fVn zej!Hj5q#MJO>Fv5b7m++G&VTv-Y42^JBRs$izT*^@oS_asa#{FUAG^a%FDOwvC`2VW<>bNM|t?MBq6p;}SkRFgOL2@W{5NQDs>F$smx>R5Y>25(l zx`##-1SF+91SE%&l#utr=RD_pAOG^3nftzS@3q%jyZwp@Mm4{+CVc)6T=U`w%J(Tk z=_c~j4i|3BD*$MC@}~UM|6xM=VhCyiTX*kIIKKaAnKSqjD55PnS?isi7eobokVoVs(RsrZCDce25x_%3RjI^ri~zUqBWP zzhPZ*d>^ahE73<@Q7N!mStVYJbB{0((5aV=`{jR**vU8`^Sd(nSS-o-GEa`2zsK%i zr<#4^YiN_4k8Mzdkwgc2bJt>}5n@<6P!{-4;ll_0p1z{yN(#rL%O6%GV9cN>`imnR4w*SV9Iwa9HE`( zfNkUE?(Xi4Z!GXC#llFJnppSggBZ~Q0fO))ktYZac>_96lD%{z$`;;RlN1B1N3uxBa zVHQ}ek`Ti?nDIO-&p~jskr%ogD^dugHtOEcCUi1-pSjw&GSxIxrS3)6+B=WupW{iU zZtaHf_M;5iVIzObv6BSu+AE>(PF;=;t*YdlhHE(y%hU?GwS-nnMN0i=)z5%YoQcWMp<5zBpHy}bJsy&7u3C;v3*kAwrv|+fy zi`}XaHk=feH*kBf$SJz`k+X?^GB3Wr=1N``O_-;W_Wl)_A_-mAXKC; zl8!>r%&UY6j=xSX2n?X0xQzWLOBUSr`7~lfwTzMfECDHxL6sJNN&6mhQ|Pl8L{}Ek z=>`*yL<_lvL9&XNazKpg;b6%bo6L*nFFb{ItDXfEqxzf)vN0lXpaP0f@hYxh2-}EZ zr!(&hEZ-RB+OV$0>l02a&}1n^pFI!^8<|(V^p(GXU(A~QqmtHi-;4%Q%A8GZX0r9% zFY#f2sWsrR0rwW&=SLTD%3C|=W+ezlUjCQ38;f3=X2YS?oeM6U9HrhTW}8Zo)Nw&*Z;|DZ^uwMIuz?>DyiHOwz5kSjh~>fb8g!sT)qyTMJ^uR^v^ z$)eB7E#gHk3gC&z-e5KqvT{Qor2u~8wxHjib191KV$*x2AW4px5OJjFsN~C0|0+XE z=!B&Gohq{&8W4aL+uPdXCDH564WSudiQndE)EXOp+c%qSFHk{MT-wj6wQtG!>PpPg zmm%R5X6L0jUGFsCtKqBLX7>BXcfpC_A6m+Yd9WSuH4m|#n780U^miHy0L4}pP;4*n z8ZY7h#Vv*&&?4VQ<@PnF>)(kG@~yUtHH$Kd5J^rELy1^y5a`D`OSp_A_(1^d=bk@;70vf15H@a(~EnVXYIQ9 zGzvTwzxp!^+GRi{a~hWh5(lt21?QdCCLajM5tZ)#(2wk^;L{8Z(WYz0tlLKy?T7Yd z^%UI{NHwut5lJ0TF^D(com9nx3uGEa^q<CT0G{+zEVru)rS{B0o}H+oVXxEl@W-o>mXH8Xc@fim1(vtU%q>bwFA}{&jDPpiShP zTaxa80lD4z`lvT504QR5sc2|y6W_5tepesjDGW_dOmzvy1z@MqN*|=$jk7`bn~S+B z!Dy0dm(M$X@H{>b;*)!srT7SGv`@?5j2n4H4{_=>j1PZ?qU+6;(7lxS&2&B+t+ zCbOxyWTlODQhsvnrt+)PI#jdhZllpZr!{hT{JrEcbkKKt&r(PzSbTWk85d8&ne+hQ zrUgBFb0lUv_7 z*6#BuMh{i#O|0)>2vYk>mB$ZV(UG?jSL2mC9bRlDPm+-fewFd@y(*jf2xVoK3;aE@ z2f&eg3ls?x@ZgeO6|X1kLN`1Nk2*uvl;{>PRM}V0kYl^>Wjlgo)% zH;%4k2wq{7?_H=AH0THQjjSRUavpqm5KWJw zMXF6riYUx9qB;I(g2t?ei7!;R}h#BHHw+Lb*`?0BDiVh%{5j`@3{cPJ!U{C ztV=VS%`@ab!w}2-y9rgiJNW={?m`(03lZsnhk(FlphSi^hlZQ)O#sIa zg{rSz+820&@H(-TmNK%qI@r6MQ+Zjk1q3JdX2LYy%rAZEArw=TIp!l$am7~bXYhU* zH-Slti{7%;9Cz7`mm1dQ)N64*hAno3vz<0VjlOLfaKc0FcMcCclUpd3xFgHcwS@+R zCKrirX>CdW<|{i`Jhne&k*j=)7;_mO&y@uHv@_t3H!xx~)M@m;Sb;Xk@)|e6YiCdf z41O?Ck*z>Y{#82hMp^d49|nAjw`VqgnAjmxe^LzJyW$+?{~hG#R!7Tsu|UYAbj zlt*~ySZ?^h9lE}(KL9|`!@Xwxx!KCs)5`a!&BJ<}+(v>ua@Fa)>@F{M{4OhQNgRAH z^NLqTUV`eU1-E|FNwC?{vx^d{mw?J9fRB&g%p1{S!>H5Ok;gPoh*wC0L3NFTnW`Xt zyF&COQ6}VOe{saZ!K3=V3KmG$0o(M5@z@N$Rs2@(B!h)mixLDM!pXIL8292On#jOS zK#2Rzk2B!zl2*LkJlRxcMkj>{>f}1*0|2Api#wIwF^sStBsYidojap&0UTOyW|x!> zzz+|+afi#&7Qf(g#PIe8y#qNRvNSS#jsEnrO$(Pi7wh)W@Uz6j8oy9_=N|qCXn#;!b$O+we*%94Y4l?KT9Ki3?_m>$UL5sl#5Y zu7PktXm}5G6K4XzO6JKv0Zfb*U#K&+@=weh`xCo)YMcc4yJR{|%$*9EXXpTw_88&D z^IDaC`F!-@5O`e`RM&cQ7h7W)${Pf6&R4gS4j{1Y1(WQRWb9Xmp#CVop&e*`DRTlw zx#clppeWl9Sp$HckiJ@V-kuqSuNvhjNpC)4RPD*a$iup;b^XDQ&@Gv; zB=?@1Lr$JXi#dOHy$NmR!>{Mye+;6452Cy!cv?^Lykk)bHs!I?%zH6L^R)D4E;LJF2pQrjHr3E0g+!M2fJRnb36KyQ-c{v7O8g7aij4Hnk zs^|uBdFz@bcN?eIu2THQU9!oM`K%qB);6S!w~2WJ_Ks(GpD^zWvNAIxnfwyj_Od{u zkCPL5P0R9Q%soAq$$q)p=H*jdN0o(ELpLS2hN*FSXO8H?Z|uDLX>YkQS!3Jr>Bjki z&~>pLP)%in&3LHfds-T)=Fi-hND3t*^AUjh*jn5Gr-tF~Ax=B9oa8-N+1|{HlB%j$ z96jy0>goHA@3k*RG;3~P8On~XuFv69w48hW$wIg-^5yH7&2Qdj`TEQ6D$oR^a_esBmCQBl3*UpzJ*4>CZ1Q|MIy%OxP`AmWDSj&kpu9OkvxmLWpYJr{!O@DYW2ME7x6|K`jLq^b#J&=oSnp{2ePpz9 z6T-)9z+JB(m5!23ZoH!b4CnrltrhhXyWagbq_rwvic%-*Hn=hqeS#35a+c&_$xe`s z60d!Q?|l>bYwv@~jYV(DkEPEuy^B6acrATrsSot}NFVVO!2{q#+i}Mu&X)fW4{I-d zVN({G)CZKQtNJC^z0LKnK@@z@vIxoBGSNG~*GqI4)XPmm&6SmvB{7@>51xp{4%N>_ z!-1P)(Wv3zlWD27;w$>bV05QMlKtAaVLtWPuPyaJW=Tl7j{JhRmil@+09}P4trh79 zj^$gPu)83ddpN-M!H(SxOmLcc&ES&4pw?@NUTj;rQ$@XXnHHA2TYpK?E)-AsH*8q6V<+L@@aE z6h+rF0cXp9NAzSKfuJudj6|Y)@`3Q{My-A4!$w0{H)MkuddBxIrh0Wg-y^qKa1ssp zGJn&DEB22wyMo2uSYyfH;;YDMymRtdd#n6DzY!B#$-2^8eEe7RQRz%2nfBN(d`(jp z)V398)oc}7rVY<(eBsAie-`T0Afw1)%f?Uqt-W>vTlG%iCI8_CzuV!LQeGc!Qah;A z|Bo_rPVK7H`%kDlZ-Zy1q_F-grH>`o>TV+O2U&8^$}#g9me~7q?z-i$|z~lQZuAm%?3D5{N!X za_Bob+b-%iOaXRsB}4hI_OsE44EXDf|H%1bcSRqKgjJT=c~MLss(*fPb$Gr6_t4Cb zA3uh|3MRQwfZnvX^(yk4@H~H&2Ytp+cV%%T^JG(z)~4-_sGBxl6?>ffYdA_w7GT;p z+IHj9k4NY{uB-?xWR^33jYQYlLVr7w$qXbZN8-Ufs>*(q05At1%kWlFM}*MzHU|il zl{PSuoeTVOuPuMYRzj$g#UouU=}DS;fiPNFgOGY~VfhTzE;naZA3P&(eHRchPK&#$ z2G_eAQ{wy5yDHM?#h_YGrr#kRd?NZ<=xmP1q1I_NwT#rxstX2ucgYjz- zTohx;cyleioMyj4>PL!b$85V_oFCPGn%z$_iSX#MVdB93(?R`eX6b&UNBHjr%$b0l z6E<*+akG)x1uk)4ty1Q;t3**-4Zs*De!*IR!NhuWy8(6$z0%S4US{k8 zKdEMvtqP;RrLDTfXfum7=2o;w?{M)-f7Q|qr7EE7lCp{w1-EELcVW` zRCw^_aW9N>SAkKSol2DX#4LwKb?Iw$aj14^AzV~LPBjjd0a%j^ad^M;p*JqAb)trQ zqTo>l2ecj@nvLV__CjjWVnsnQ=uW1cY`el2KJPaJLN2do6J>xg#X)^D&#BmZ^HuaT zHUs2kdfs~9*0#_~IwQDLXm?jHOz$p@CQ2JBa*?T2`#T%c8;{p&>Gn38v? zO5EOCtxSCLri3Q|A6ED)0i6cmZaDsJ;;+SNM_Sm~tiz9iyuyRAsmsVM5~a%t)7-v$ zGBLx=FMZge9KGEwoA|YvHi_q24HeT>#steQ7+2SJ5V*;iJUhK-r2oz0`GkU*c`W+( zgEKm1^f?qtyUbiEiTkzJ4bobz)hnKD0)z|jzkDW==p9efk?Lnau1CS8Tj%g*2MKs# z<}LIPx}Wv4z_nv%plRx~^-$*9^IZopse$jq2GFgYm{WwROL|`^F$Az?c(|SPmPb7l z6I$lbjRJxZkvRV3_qLy*mt270HXl7*Z_C=A7|AAtT%OFk&gw`cbrq_wcdm=ehNfe# z=ohuFn`2TFHOPk1@Na}jAgR(7rngBKYQv_1wJ;F1QFEnOlgd(FMbLkJZfOIC1;c%N zcuYt!rXEeXq@9ZCQbMxLp3T9-AyfKODNFWtZzxO3hHre`KBy_E6$l)&)~z#6M(K+1 z@j3YN%1$Lso^x9s@*McI&Raf6zY z7CG19uk=}2rGOuvkpD!rx`Fz9E8?U+j-`eAta9zjb-USoAfs6)@Px~hf@{eM=IQ!b zOk~VMd z$FjSi8ux`~SjCKA=jWikvaB}_u;@08;9m!#Jg#9eFPn82w}>e!ld7fM&;6ILc63`Y z9}5x9FEsM+_bZZFG_^fu?s`nq`axxD)JKP+M61ojx^&TT}Nv85}y>tH!?mhI+q+)LCT%UOC$#mM+gf%8>{s2N&0*#GtP+YeH45O}f+pfUbZ~qTlh-W$tyy`oRH? zTx7*eP==a;%>^YmGU5Zn4o9tPGUUUfnTEBjl2ce3?^ib6L@oy{9*kPVLvgnWZrSub z-Jw;^_;IeRHzraQE|@1x7h#}x1UN1X$`-G-l%hD45f*_)mOefdI;-yoEp?NaL$+9L z+}l=8K&|OsQB@TdWX^u`!@JF9;ImN+HtDk=6&=3l&GE9GdBF8Dzwta>O$ISTgZr7< z7XAL?wzf?_OGk2cUZc=yixeODdy(AS%jsje?7sqoi?!)OfaOUm>!r)TTmbTnRXfF) zx0^r0^?ZDMRH|CI`~Z$xc~>H=?zRN1{~nCaOF0=?6IIiDd{JeZnEz<;9x-|6o(!V; z!$Jyo_BY@YE0R({ufLC|)~J{!+)P*3`IJD@y5BS@7t_1qn$hujOB)fuMJ(Up`La#E z0CwyNt$DZo7@<$o$&2N`<>%#DNLgzYCU4`z3Zb!1(Z6=!QKYuvHhh>`SJmc+DLT*5 zYt0zbBiYMhAgHqs(+wg8Q5c6@OqYY8PC>02dri3p6NOadk~<+Vm*03X9<_58*5fNZ zko3h(XBJrOnaSXM%;$HRxxc6<30r&=dG7ym?MFGeB4iM^9EbgJ$_IFqRBw!H zSyp#ii{CZqJMs!zH^b}QDb+d+XI~ms&-e3aDl?T0+--lFI$owV>fWvu!tw;x)zHB+ z=iWCVN(M(heyf$2LP?e%t;BNK^F{S7@~j$uj#xZp7yMp0fUpRDakVq*4&_?N%`iUc(v7P>*dAO^*7h0bj>_IuHvT;$E!6_j~r<%oJ@_j?C@^2 z6AwS{P@JGzOlLs)o}38|JT~T3&K(uD5{&ZJ5100gERR*UZe}GOS=E!9E7s1 zlMwccSR?OHT2m0(d&dysCWqr2KeDf4>>T0a-+x=NEw*2TXC*;X|^Ej>YzEh<}@{`45k|`vAf0 z6q^1Xu}wuvu1I4nx>I~`cvxb$ip9MI6{B-YLPc{qp`7FnWMzpjN_7Gj}(a$CCc5h}F zK+3D)4rBDv?Vif0KJZ7qD~2f91*7JPUN1Q3ZLAjRYj1)o+~G{f+6O+OSC)b*WukDv zWg{EdFSQ%}d@vBQR%=ALZP<{JJ)cz7Cd+F+*_*9l@0M!UQ|LvlmFr%+TJtiwcqw-q)3BNHsilpZAMKulO;y5-aD?hFN9J2BCVuTiF*f zrEcq1kS6>j5TDT1L57VVTTqPm*ZjHa_*{g7Gw3Iz^l2 zZvhy(wE0V*lWEZ<%R1N;58x6c7b}zTVq#d-e8X@uee|Jju(8z<9dS29@TZ+@JR5^< zS_by_nRVm%SOKV4{~~l!A`%oej87V-9xe#YA16-uDk|9Yb&hn;%*KnP-`Nz7Sdu`YBAF(Ao11_m=vFhZ zmzFSTWE5K4>4u_<_r%0mbwuI7B#RU(WzuF^Gc>s03P==8m-F%99z{k=6lr zb8V)m^9mEBTz&dW1Lp!*pZ8`pKF8e6*t_P*&y7Zm0}sj5Q(OKhr$Pg^Jxp|qJ2rId`nZW z%t`b0W;EA!wa;u+=AGw1h37SXVS);H-mNd&_n+Wem3T-v>Ai0n$Ai4wKKm12D(dg? zuzFbE=E4TzZUN_4T;uGdfWvP9Zyy{V zoKQZG#_zptu8uIhx3FQ~Uw5%yG0OF7X&kor1a=n&`_nwLeD|f+>iAovDw$sYyc^5f zPy{jRizLmg*re55BE>D|bvG6S|{gM#U|6y1LL5}+{ z4L`Jcizt9CGy>6{>H5UeRV`$#2Z+s|&7$~+(760~kM|vua$9!hS2lE(9wY?M7p^K1 z++RNXW1P5{BIc23St8oZyQ93)pzEuiE;iG-D}e_w;pNS%4~kclxgNT*I9v1%92mGz zzjf3_=5u+U0jN&+{hUEd8sIeC+`%@I0n1dC_kl;E#zo-~SU-e2FKL2)8u+vw0Yr_$AaxpabMMT&HF;f8| z@5@ZSb(U(%`-t$S6r`n7hjb;sq?nxj*2vZUie6?=5Oos$>z*cOG^!t{v@#26HJ+q` z>-}vQ{gdf>5v2d-gh<6wY|HZny$s#XDUv-Gx#P1=v$$=;-JWD!*)rV_QiY{W<)32G zGPG%qDLnK)ZC1nbF)bk4l#q)lX4A13US?dZc}U`2O>NRBk~enB0XdQ}0 zqp!o_dSyf38O!Xr(fa|jy{vclXH8_bB?(kBk+s4m#&^eKt`VG(VS2;Tcypm3BB#fQ z+GmA_xrLTiOLXL~RR}q{>+3x#Anm&^=0QWd8Cjx)`fP;Hx>M0yu>Gk9gfdQMiACYO z$;#bq1!JnL8okWa&{!bke{0lb#<6VurnT*s)Okd7G*p>^zv$-uJQp8iM>v(&K(fGU zZqs$84NS3qvnTKTv0toa(zmUUHNRjGIya%dh35~IysQ3@mwcv|JCd)cUYK|&NB@07 z?psZ4bigG4{4p>3a7}5@)~;DUyk44%lJ}l(mekl{4L@A&_S{#knBmVhuGBZdrT;YI zDf-Lvxm9p65JCrdRg90BJu=+nN?tgBN!V7U@$%Te1#vJEc4c$KyyDE2R7cEx=qJ7b z_#2C}QLslhx1ICUHsE-ht7+ESn<|i2H$A>^R0L7m_mD+9p5D&7o9od`k}ay}wzkI( zYHz~qZa(-Mx#~qbwg#*yb|siR+ITI|a>2 zYEjSB&lnb+bD zT$_6PV8x-4q^r{e*2-HP+Im~FVJIc}4OfiJ;c=W=W-;Y^fi|m>-!cN99FRY>^W!|- zR3GQL0E9>~1?8*zy!`V;sj9pjW6O1xr#3#Icg)Av?+YmxcjDCyij5hlawxGR8-T%z zmDRJuG-EaGqebf-i%Fy@yDOe(i`96-oj(;1RYb(E(WDz8bd7Z$;kQVEcjPsmbuJDN zR~rAN{Bh?@a|-FVe1GTwt-TqBweTsm)PndTLQP)FAd@$^IrqV+_N5@?yqe4ikAN|o zH_+(iiO8G_9PZ8hw)WO#7#1?2{3yk5)uZc`9LhvTe4w#AuXQtykp8%5i9l>?m(0<{HvI9Rwx1;TpJdkc zM@46bN$Pb>i`NJCU!dL$U)L1OEYok+{@p^aA)tLPr}&vXcd03JFy5fHv(UH7+wWY` z!&g0wN?r`hkS7mK8U^s=7ERxYTJ`7zl?y-i>&mA}O42qy3=jvwRbi1Y>q5EDJ0rYB zzI0g%45i=f=l{C@GGS@|0W{rSU0h{jm#YUfnHpu1yQY??lZeWCr~OcUc7S@~^AB2@ zT(ZlA9%*pMZ9*1IaWps!hi>P_3Gk|fJ?fg`^{IC>8#}sF-KfPr`a(3#DjhhVQ~+@A zmNq0C6`CrNrNv&8`_y7xKs4aMXoC^5;7-fR0}~S@YO_h>dlK$nNlQ;Hko2=JYAvNr zJu4!@l|Al8-uDa)wXrRJ@TThI^2G5kO+7N1oyYA4BJB(F;sfxk7ey6S+~W^$!I@Jk z7vrGzI$aOz=ij8Fq@+B>DxDS&4Sy3qMT*+P!9R)Op zfdH>3f%8`{LzE=RFME|nM{k-Uhculi#y? zk1kE<2mOljNd{}|-Wek;L~m&ior5d03?rs8q8}aEBJQ?ych( z50Z^h$1-c#s_R9k5l6Zn*)uO{D7?Se#oocqhQju<%%9Oh+4O z8z5$Y^0c5Uuw};$CBf9^l zZ>8FXY&t1#j2$dWlFPY!MO@Ijcp7U^`<7YtV9IRKgNQ)-6LX7~&Q}l?`kUOlD_}z} z`ZIcuC2cTN{kQza8qIfGyTY13aL7qz$*D@NFf4->_hE+X&fVAdy~EEA3_b?Qt>oY=&ZuQIFsx4&!e+v8DK z_PR_aREoM1P5k(#7G??1izq?_1@+IQDx>M^K`S#Ai&_h_X~VWoD-CrnX_O6vmY8w8(d%a1^ifgF%YU}A@A?>2-sTw@Kn6>q+Q>4$*G!4<}O&b`oy zwXWp$DWqOdP|y(-E$vTQ9oD5%pLr=mL&Mhk99{JiI586_nkge@z8=+xCjSA-6H^C= z-3ETUo}ZWxuVT^^?x#W5jwJ@pg7u3RQt6DEzE_YX#45vKzCcpIb<2Y)@!bRGc;rx&lA~I(z@ay9rf!q;Q53#4yb1YGZ0aFJ{`mue+ z87JunALoWyO7Kb!)v01`zof`-3wNd&5Ez0ATBRR^@_>Fp)Q}BCb$St?Y7GLHff0?f zA$Kcc*5sds@4%qgIymt4C=}`vIKkmudNzGunLL8?S$W6P=}HcpM!x;FR=NiH;6McSrMt0W>>`8I5h8uwvO?e3P1dMU0BePNZ@dm*~}ikEm6a&Z-(k1y(l zzJ|p&ddf_paY3|}v-W~^ycZsZICu}hqHog!2S=c9LnI2bc92?Xqk18x^(!Z;%6V8x z_;=$@%h_WD*&V^|Kwr!Oq_r|SI(qX6NK!g&YuSBlS{p_3r|cE5E`R{W$eu>$qIy}-*8>k?5; zYOiD`tZ+zc4Z=l_GAQk9SBeej@UTNeMfF1%j~*AYG~9*6=7P@l6y!lGCJBGThJCQL zkZvf;3cLAR;?C=i=u1n%usoX4o(5{OP48WC%aVex-Y+-1YP2nWd3XVwQr9`yW~a{g z!qUa%0P}l))p-lS$y;(bmv)g5xvFI)Etv~Xp(!k{iuL{B#Bf~k8{^n02%D2bc=I4f z!+2ZV$D?KG>L(wB)r`HuheULW^1ticQyi{%RcEpX*! zh8W7`vo0=$tWAK)+$5Vvr_mC-0|Q;q2udNJtXg;b4v&KZ!p$S2HUUNVLSACBHkD5Iia!vN3 zyyN33_iCF)t*uLdIi5m^5UdeM;;tNH=DX)|8@Y4Xj9ELsH9S?1x`(QhIy(F>bnl`BT7ytS52Vl!Q zaxuH9{(3{g*ylSqkOh?+gviF>KKTOD86nl;qSw;A;{N8Mh2wUtu%*(@ay4shi;tm# z>Mr5>FKuKdpMJuC$#ctR6|Z!wth)!B1CjP2%Dou?kN}-BVB51NzQkCh_|lG8FhM~F z#NBA(2rN4|yf|&_^a&&?xZ}uTg9_=3S~Ejm}_|0`L1=(rM@cy%esw!X%uk)G~UQ*sg zfo(>zE54Hh(B>(A(-5L7G(io~WGQxgcJ9#9EuoT`V-3j_J|?ChZ*F6f?@la0$KIsG zes8aOi^sF`%%aIaH#e$$I95#Z*7IaJCreAqRlvt#v!GXad_&hvyhKmqPcz%sNh2E& zTrxv1oK^ahDD9{Nt};B6)S>LMdfdtn*vc`ch7JxLUCFrss!2EQmey-(eQ)=x5QRpfAhx)xXJ-uP{y`)@;81-B~mCf|EF*3 z@dde=m{gHw*`NKEmX>RXcE)S?dGD_!lR4L`0()~JV&XZ~z<0T#@M2ps8GseBYq0T{ z5Cpu&y}Q0A=t00n@T|d3iJ_+gwrymSo*pu0?#R+$mA`%(@491JF&y`N!EBPtN$hc! zep%)U;P8@f!gK6$)q+W)4Kl>#5Ccq$m)HDPe_K>0(U%-j4-YHBZx0fqx<1VVT>la5 zI>+ct#AhB&`E>R8LNhpgM;am7FEpF_sn9mo@onoS!SmlN4|k98z+Mr9EVNf-bKRO; z#JKp*T7)ab%%=CN1d=iV6yz~XtdG!ygYPx!4?QeGR1&j5G8lmpDSG{0kIMMx4c;b) zr}4R3@~%ktJ0J@PN!$ApPX&d~Fd8~<7`T~#=2qax+j_ILC$?0Tz*w@cojWpP-{+JN z?kGe-O1qkJ-yVM%UZ%r2Sn5dcx%Pfiz`VB(A7Vb8TW@JYjfI%$t+^Sm##uDd>|zld zpXf58q5M8PJ`nW$6eW0lqp~_)=n(^F02iDVV(419Iq z98h){4YKf9aQV6AnK1FezB9yhaFE=BHK&9+PVE=EWrG(_p)+>LHbFVNT@as=Vfg}X7qK}KD!5geby zHZbLas$`B|r%K(O;)mm~-od{2)e<}jATbkr!cZbn1^PTI3ZZW7F_Lbjl=1|#D=r@)*C_O7y6s z1*@yOZ#YVJRaJ57dVmmN@pE}@TlF9p3T$q|@;2bu^viCekqD>NO1|JH_qCT}(l*UR z5arn?b~#9rysj5$A-R}gU9S@rlLGg2rQX+Kiil3|4iR;_j~FPhN)A^c3!C*~awd#? z*RV(Rc&Ft}kX6a#q*1;s594>@ z0G)U>dP`YpDj!Z~0vtwQ}2I&w3GytNAW=? zC3Q#?DQT&qwIK3uWS#O}J93EJB6xI2I}-~sZ&i|AO#-H3CMVAGRnLo||NJm`?k*Y7 z(m6I{twA^agCj2~U-#gTkhPSmwl_fiCI-F8O4NKiF((wT35LR6CzOB$``?FVxtCQV zNeXGX=l)ju26l(2n4TL_Em(Grva4Ag1%c^9aX(K6iYc)E`=pN;1i(a6Ko(+pX+IdL zK>2dVrcA##HdG0eJ_9YBL8CM(*!Gw@=i_j@;8uz_H3KVI{{!;>{#+#~a8PH5>Blt( zS7WYWvy2QSM^r)ki8<^3_B8KJ+7pC%`tfoRRa8)7!A@~tzRK*buJ;Lt6#f}w@TzR` z(li;_%QF~@hMcyMcaF%8M8M@YV9vfVqkG#}1CEPYIAw+HCy!%OPz~8lS^~nHsLR8!E zbXeOR+0L%?^u1glNIc&2$&9R_oty3{SS`79t(p|~137o?kvJjNe^$|>RtD_FUCIYk zm& z65t%CmgwdkcN?E?Zqi8SFOom`Lk60334!2M%OM^<7cE9i%f!9M6(I~*_3)#>4Ol)9 zc8Nf6|2t(%xFD5%byt(~*$m4r0A!AB1qQEMSkPDl13^HW*@rC9q66;uR6(PdaVJIO zIRE_|3luEMGtxnBM0Kp3X9&+0sdW1##9shNu?l>wMit7tCym6lH))4W?9>!1PY;K_ zK{NNocPfF!{^*z`YXHjj-)|CvejML)mKazXBH2O9y&81Y#=b>5m~2ETX~@aCnU?PO z-I0bD*MA?iW~uWdY_1G?@?>MpmW1WsMf%pi85fB8j}w8FQR3}ESxn8N2Nu{UcRN47 zOOLay+WA*@EXE~O0>sUOmfl=|-;LEOp30g{;VRos&jj09nHdi|3hVp#+jPN_UwLVx z%zrO29k*Xy-jRxOlXnwL?G^9V6e5z2B1ZeZpb>^Z$APP>2W8N>h<#xa>p#cCqbv(T z%aU74v~;3l<^vq=Nh-?hxxPk`-NQB;;Z*|m=43LR42$a!hj7l=)Q-R+2Cc5<3p*3`v~RluieMO!EhN_1S{dP3 zfH$lEu06n%txmGX21&B}K{HwGl%7t5XsUQoBweQ|Mt*?szC z_UKu{SgM;dASv?90X2UnkJ3k@*J*CZ4v#W}Pc4`6n)*h;7MNhvob`lmUA8hQ#NLz@ zxRhts8OKd9{%6Fb3F036n|Qb<2BU~MWV4^LOSi7iriF-mc1$K)KKP`Sbl;>yb>03J zTuR^u*X{L6!GL*12PZmGk$)!)Y>lJ{u*VfpYg`cb#;C$@X>5olFbLEa1*o_MCv{C2 z&f$kDfoQj8{dqu10AV`x_szCU7e`53YEM$gj1s~GE-GKZjizEay^i(os+?u|ZutNS z%XZAqFY`({Xzv;)9Rxm{V_sjTM!GWGkSxkb&xAPIj6g&+3A9aLn~2Iz?-m54Bb_yl z+eM?+yyh6zzW;7pEJi-|fYBmNPEgf;YFzM(f&ezxqa2}T?eTl4FOjXk|AF&|nmH)s zj>^g8>^VEPUKusYOK2YIL>RAW^d!-@cXN`KJP~ z{b9F{?ailY>1y_0O9IPrMr?(SVcE3e1JjIhF|@3IsG)8jMQ~>Dkk&EGRL<7k^L{Sw z?k5$X;n6FM|8JPue}91lJD2pk_9w6>AGSY+`1^U*hj+0-FRnxVMs0=s1Oe7rlZ)eq z$P$6;r93S;Of~OKs%QfTYXoXy-d5=BckRxZ0Lvd?NchDiv)oB7@TbDs`pGOO^tHl^(_^8V}>1O@RO^>;kPk^@%3FL(A-PU** z!bKQNQWap<@>R}e*{|{TD+_<@N&0_QI|()|Q)~Y%7|$cbpJrYNMgcMHYTGJwjS0s3 z#`7(T4$EIqxAPhQ0-8{8i>F^%ltw1>ze|S!%=TwoKnbX_h+)PYgo{c+%Hc34-9u%K zf_JC^=-@tN7Z)y!Izg>^L;~Y?2NvCWF=^?vbYf}p=>P8-jz|`!LQ!4Hx5i)2u*=1u zX&DCgGjJe(JTg!j>hcw_OqySD+b0Vs>xlk68~=?*qy?}35mXfp`|r~GXI!Me;{K6Z Xg=CJTD&t~7z@MCqGNSa6;p_hc>|fnc diff --git a/src/main/resources/static/img/captcha.png b/src/main/resources/static/img/captcha.png deleted file mode 100644 index b8f557589da9dbcad348335117cd3cc6e560b3ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4166 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 K;zxOl(EkCysPc>e diff --git a/src/main/resources/static/img/favicon.ico b/src/main/resources/static/img/favicon.ico deleted file mode 100644 index aef341238a37862ea97ec2369b2c31f67e6bb03f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9603 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 zthis._items.length-1||t<0))if(this._isSliding)g(this._element).one(Q.SLID,function(){return e.to(t)});else{if(n===t)return this.pause(),void this.cycle();var i=ndocument.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},t._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},t._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=t.left+t.right
                            ',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:Ee},je="show",He="out",Re={HIDE:"hide"+De,HIDDEN:"hidden"+De,SHOW:"show"+De,SHOWN:"shown"+De,INSERTED:"inserted"+De,CLICK:"click"+De,FOCUSIN:"focusin"+De,FOCUSOUT:"focusout"+De,MOUSEENTER:"mouseenter"+De,MOUSELEAVE:"mouseleave"+De},xe="fade",Fe="show",Ue=".tooltip-inner",We=".arrow",qe="hover",Me="focus",Ke="click",Qe="manual",Be=function(){function i(t,e){if("undefined"==typeof u)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var t=i.prototype;return t.enable=function(){this._isEnabled=!0},t.disable=function(){this._isEnabled=!1},t.toggleEnabled=function(){this._isEnabled=!this._isEnabled},t.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=g(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(g(this.getTipElement()).hasClass(Fe))return void this._leave(null,this);this._enter(null,this)}},t.dispose=function(){clearTimeout(this._timeout),g.removeData(this.element,this.constructor.DATA_KEY),g(this.element).off(this.constructor.EVENT_KEY),g(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&g(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,(this._activeTrigger=null)!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},t.show=function(){var e=this;if("none"===g(this.element).css("display"))throw new Error("Please use show on visible elements");var t=g.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){g(this.element).trigger(t);var n=_.findShadowRoot(this.element),i=g.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(t.isDefaultPrevented()||!i)return;var o=this.getTipElement(),r=_.getUID(this.constructor.NAME);o.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&g(o).addClass(xe);var s="function"==typeof this.config.placement?this.config.placement.call(this,o,this.element):this.config.placement,a=this._getAttachment(s);this.addAttachmentClass(a);var l=this._getContainer();g(o).data(this.constructor.DATA_KEY,this),g.contains(this.element.ownerDocument.documentElement,this.tip)||g(o).appendTo(l),g(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new u(this.element,o,{placement:a,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:We},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}}),g(o).addClass(Fe),"ontouchstart"in document.documentElement&&g(document.body).children().on("mouseover",null,g.noop);var c=function(){e.config.animation&&e._fixTransition();var t=e._hoverState;e._hoverState=null,g(e.element).trigger(e.constructor.Event.SHOWN),t===He&&e._leave(null,e)};if(g(this.tip).hasClass(xe)){var h=_.getTransitionDurationFromElement(this.tip);g(this.tip).one(_.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},t.hide=function(t){var e=this,n=this.getTipElement(),i=g.Event(this.constructor.Event.HIDE),o=function(){e._hoverState!==je&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),g(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(g(this.element).trigger(i),!i.isDefaultPrevented()){if(g(n).removeClass(Fe),"ontouchstart"in document.documentElement&&g(document.body).children().off("mouseover",null,g.noop),this._activeTrigger[Ke]=!1,this._activeTrigger[Me]=!1,this._activeTrigger[qe]=!1,g(this.tip).hasClass(xe)){var r=_.getTransitionDurationFromElement(n);g(n).one(_.TRANSITION_END,o).emulateTransitionEnd(r)}else o();this._hoverState=""}},t.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},t.isWithContent=function(){return Boolean(this.getTitle())},t.addAttachmentClass=function(t){g(this.getTipElement()).addClass(Ae+"-"+t)},t.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},t.setContent=function(){var t=this.getTipElement();this.setElementContent(g(t.querySelectorAll(Ue)),this.getTitle()),g(t).removeClass(xe+" "+Fe)},t.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=Se(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?g(e).parent().is(t)||t.empty().append(e):t.text(g(e).text())},t.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},t._getOffset=function(){var e=this,t={};return"function"==typeof this.config.offset?t.fn=function(t){return t.offsets=l({},t.offsets,e.config.offset(t.offsets,e.element)||{}),t}:t.offset=this.config.offset,t},t._getContainer=function(){return!1===this.config.container?document.body:_.isElement(this.config.container)?g(this.config.container):g(document).find(this.config.container)},t._getAttachment=function(t){return Pe[t.toUpperCase()]},t._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(t){if("click"===t)g(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(t){return i.toggle(t)});else if(t!==Qe){var e=t===qe?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=t===qe?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;g(i.element).on(e,i.config.selector,function(t){return i._enter(t)}).on(n,i.config.selector,function(t){return i._leave(t)})}}),g(this.element).closest(".modal").on("hide.bs.modal",function(){i.element&&i.hide()}),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},t._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},t._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Me:qe]=!0),g(e.getTipElement()).hasClass(Fe)||e._hoverState===je?e._hoverState=je:(clearTimeout(e._timeout),e._hoverState=je,e.config.delay&&e.config.delay.show?e._timeout=setTimeout(function(){e._hoverState===je&&e.show()},e.config.delay.show):e.show())},t._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Me:qe]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=He,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout(function(){e._hoverState===He&&e.hide()},e.config.delay.hide):e.hide())},t._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},t._getConfig=function(t){var e=g(this.element).data();return Object.keys(e).forEach(function(t){-1!==Oe.indexOf(t)&&delete e[t]}),"number"==typeof(t=l({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),_.typeCheckConfig(be,t,this.constructor.DefaultType),t.sanitize&&(t.template=Se(t.template,t.whiteList,t.sanitizeFn)),t},t._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},t._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ne);null!==e&&e.length&&t.removeClass(e.join(""))},t._handlePopperPlacementChange=function(t){var e=t.instance;this.tip=e.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},t._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(g(t).removeClass(xe),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},i._jQueryInterface=function(n){return this.each(function(){var t=g(this).data(Ie),e="object"==typeof n&&n;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),g(this).data(Ie,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return Le}},{key:"NAME",get:function(){return be}},{key:"DATA_KEY",get:function(){return Ie}},{key:"Event",get:function(){return Re}},{key:"EVENT_KEY",get:function(){return De}},{key:"DefaultType",get:function(){return ke}}]),i}();g.fn[be]=Be._jQueryInterface,g.fn[be].Constructor=Be,g.fn[be].noConflict=function(){return g.fn[be]=we,Be._jQueryInterface};var Ve="popover",Ye="bs.popover",ze="."+Ye,Xe=g.fn[Ve],$e="bs-popover",Ge=new RegExp("(^|\\s)"+$e+"\\S+","g"),Je=l({},Be.Default,{placement:"right",trigger:"click",content:"",template:''}),Ze=l({},Be.DefaultType,{content:"(string|element|function)"}),tn="fade",en="show",nn=".popover-header",on=".popover-body",rn={HIDE:"hide"+ze,HIDDEN:"hidden"+ze,SHOW:"show"+ze,SHOWN:"shown"+ze,INSERTED:"inserted"+ze,CLICK:"click"+ze,FOCUSIN:"focusin"+ze,FOCUSOUT:"focusout"+ze,MOUSEENTER:"mouseenter"+ze,MOUSELEAVE:"mouseleave"+ze},sn=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),(e.prototype.constructor=e).__proto__=n;var o=i.prototype;return o.isWithContent=function(){return this.getTitle()||this._getContent()},o.addAttachmentClass=function(t){g(this.getTipElement()).addClass($e+"-"+t)},o.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},o.setContent=function(){var t=g(this.getTipElement());this.setElementContent(t.find(nn),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(on),e),t.removeClass(tn+" "+en)},o._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},o._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ge);null!==e&&0=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t - * Licensed under MIT (https://github.com/Johann-S/bs-custom-file-input/blob/master/LICENSE) - */ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global = global || self, global.bsCustomFileInput = factory()); -}(this, (function () { 'use strict'; - - var Selector = { - CUSTOMFILE: '.custom-file input[type="file"]', - CUSTOMFILELABEL: '.custom-file-label', - FORM: 'form', - INPUT: 'input' - }; - - var textNodeType = 3; - - var getDefaultText = function getDefaultText(input) { - var defaultText = ''; - var label = input.parentNode.querySelector(Selector.CUSTOMFILELABEL); - - if (label) { - defaultText = label.textContent; - } - - return defaultText; - }; - - var findFirstChildNode = function findFirstChildNode(element) { - if (element.childNodes.length > 0) { - var childNodes = [].slice.call(element.childNodes); - - for (var i = 0; i < childNodes.length; i++) { - var node = childNodes[i]; - - if (node.nodeType !== textNodeType) { - return node; - } - } - } - - return element; - }; - - var restoreDefaultText = function restoreDefaultText(input) { - var defaultText = input.bsCustomFileInput.defaultText; - var label = input.parentNode.querySelector(Selector.CUSTOMFILELABEL); - - if (label) { - var element = findFirstChildNode(label); - element.textContent = defaultText; - } - }; - - var fileApi = !!window.File; - var FAKE_PATH = 'fakepath'; - var FAKE_PATH_SEPARATOR = '\\'; - - var getSelectedFiles = function getSelectedFiles(input) { - if (input.hasAttribute('multiple') && fileApi) { - return [].slice.call(input.files).map(function (file) { - return file.name; - }).join(', '); - } - - if (input.value.indexOf(FAKE_PATH) !== -1) { - var splittedValue = input.value.split(FAKE_PATH_SEPARATOR); - return splittedValue[splittedValue.length - 1]; - } - - return input.value; - }; - - function handleInputChange() { - var label = this.parentNode.querySelector(Selector.CUSTOMFILELABEL); - - if (label) { - var element = findFirstChildNode(label); - var inputValue = getSelectedFiles(this); - - if (inputValue.length) { - element.textContent = inputValue; - } else { - restoreDefaultText(this); - } - } - } - - function handleFormReset() { - var customFileList = [].slice.call(this.querySelectorAll(Selector.INPUT)).filter(function (input) { - return !!input.bsCustomFileInput; - }); - - for (var i = 0, len = customFileList.length; i < len; i++) { - restoreDefaultText(customFileList[i]); - } - } - - var customProperty = 'bsCustomFileInput'; - var Event = { - FORMRESET: 'reset', - INPUTCHANGE: 'change' - }; - var bsCustomFileInput = { - init: function init(inputSelector, formSelector) { - if (inputSelector === void 0) { - inputSelector = Selector.CUSTOMFILE; - } - - if (formSelector === void 0) { - formSelector = Selector.FORM; - } - - var customFileInputList = [].slice.call(document.querySelectorAll(inputSelector)); - var formList = [].slice.call(document.querySelectorAll(formSelector)); - - for (var i = 0, len = customFileInputList.length; i < len; i++) { - var input = customFileInputList[i]; - Object.defineProperty(input, customProperty, { - value: { - defaultText: getDefaultText(input) - }, - writable: true - }); - handleInputChange.call(input); - input.addEventListener(Event.INPUTCHANGE, handleInputChange); - } - - for (var _i = 0, _len = formList.length; _i < _len; _i++) { - formList[_i].addEventListener(Event.FORMRESET, handleFormReset); - - Object.defineProperty(formList[_i], customProperty, { - value: true, - writable: true - }); - } - }, - destroy: function destroy() { - var formList = [].slice.call(document.querySelectorAll(Selector.FORM)).filter(function (form) { - return !!form.bsCustomFileInput; - }); - var customFileInputList = [].slice.call(document.querySelectorAll(Selector.INPUT)).filter(function (input) { - return !!input.bsCustomFileInput; - }); - - for (var i = 0, len = customFileInputList.length; i < len; i++) { - var input = customFileInputList[i]; - restoreDefaultText(input); - input[customProperty] = undefined; - input.removeEventListener(Event.INPUTCHANGE, handleInputChange); - } - - for (var _i2 = 0, _len2 = formList.length; _i2 < _len2; _i2++) { - formList[_i2].removeEventListener(Event.FORMRESET, handleFormReset); - - formList[_i2][customProperty] = undefined; - } - } - }; - - return bsCustomFileInput; - -}))); -//# sourceMappingURL=bs-custom-file-input.js.map \ No newline at end of file diff --git a/src/main/resources/static/js/discuss-publish.js b/src/main/resources/static/js/discuss-publish.js deleted file mode 100644 index d0692a0..0000000 --- a/src/main/resources/static/js/discuss-publish.js +++ /dev/null @@ -1,38 +0,0 @@ -$(function(){ - $("#publishBtn").click(publish); - $("#backIndexBtn").click(backIndex); -}); - -function publish() { - $("#publishModal").modal("hide"); - // 获取标题和内容 - var title = $("#recipient-name").val(); - var content = $("#message-text").val(); - // 发送异步请求 - $.post( - CONTEXT_PATH + "/discuss/add", - {"title": title, "content": content}, - // 处理服务端返回的数据 - function (data) { - // String -> Json 对象 - data = $.parseJSON(data); - // 在提示框 hintBody 显示服务端返回的消息 - $("#hintBody").text(data.msg); - // 显示提示框 - $("#hintModal").modal("show"); - // 2s 后自动隐藏提示框 - setTimeout(function(){ - $("#hintModal").modal("hide"); - // 操作完成后,跳转到首页 - if (data.code == 0) { - location.href = CONTEXT_PATH + "/index"; - } - }, 2000); - - } - ) -} - -function backIndex() { - location.href = CONTEXT_PATH + "/index"; -} \ No newline at end of file diff --git a/src/main/resources/static/js/discuss.js b/src/main/resources/static/js/discuss.js deleted file mode 100644 index 547c490..0000000 --- a/src/main/resources/static/js/discuss.js +++ /dev/null @@ -1,82 +0,0 @@ -$(function(){ - $("#topBtn").click(updateTop); - $("#wonderfulBtn").click(setWonderful); - $("#deleteBtn").click(setDelete); -}); - -// 点赞 -function like(btn, entityType, entityId, entityUserId, postId) { - $.post( - CONTEXT_PATH + "/like", - {"entityType":entityType, "entityId":entityId, "entityUserId":entityUserId, "postId":postId }, - function(data) { - data = $.parseJSON(data); - if (data.code == 0) { - $(btn).children("i").text(data.likeCount); - $(btn).children("b").text(data.likeStatus == 1 ? '已赞' : '赞'); - } - else { - alert(data.msg); - } - - } - ) -} - -// 置顶 or 取消置顶 -function updateTop() { - $.post( - CONTEXT_PATH + "/discuss/top", - { - "id": $("#postId").val(), - // $("#postType").val() 帖子当前的 type - "type": ($("#postType").val() == 1) ? 0 : 1 - }, - function (data) { - data = $.parseJSON(data); - if (data.code == 0) { - // 偷个懒,直接刷新界面 - window.location.reload(); - } - else { - alert(data.msg); - } - } - ) -} - -// 加精 -function setWonderful() { - $.post( - CONTEXT_PATH + "/discuss/wonderful", - {"id":$("#postId").val()}, - function (data) { - data = $.parseJSON(data); - if (data.code == 0) { - // 加精成功后,将加精按钮设置为不可用 - $("#wonderfulBtn").attr("disabled", "disable") - } - else { - alert(data.msg); - } - } - ) -} - -// 删除 -function setDelete() { - $.post( - CONTEXT_PATH + "/discuss/delete", - {"id":$("#postId").val()}, - function (data) { - data = $.parseJSON(data); - if (data.code == 0) { - // 删除成功后,跳转到首页 - location.href = CONTEXT_PATH + "/index"; - } - else { - alert(data.msg); - } - } - ) -} \ No newline at end of file diff --git a/src/main/resources/static/js/global.js b/src/main/resources/static/js/global.js deleted file mode 100644 index 4d74514..0000000 --- a/src/main/resources/static/js/global.js +++ /dev/null @@ -1,34 +0,0 @@ -var CONTEXT_PATH = ""; - -window.alert = function(message) { - if(!$(".alert-box").length) { - $("body").append( - '' - ); - } - - var h = $(".alert-box").height(); - var y = h / 2 - 100; - if(h > 600) y -= 100; - $(".alert-box .modal-dialog").css("margin", (y < 0 ? 0 : y) + "px auto"); - - $(".alert-box .modal-body p").text(message); - $(".alert-box").modal("show"); -} diff --git a/src/main/resources/static/js/index.js b/src/main/resources/static/js/index.js deleted file mode 100644 index 2b6e881..0000000 --- a/src/main/resources/static/js/index.js +++ /dev/null @@ -1,33 +0,0 @@ -$(function(){ - $("#publishBtn").click(publish); -}); - -function publish() { - $("#publishModal").modal("hide"); - // 获取标题和内容 - var title = $("#recipient-name").val(); - var content = $("#message-text").val(); - // 发送异步请求 - $.post( - CONTEXT_PATH + "/discuss/add", - {"title": title, "content": content}, - // 处理服务端返回的数据 - function (data) { - // String -> Json 对象 - data = $.parseJSON(data); - // 在提示框 hintBody 显示服务端返回的消息 - $("#hintBody").text(data.msg); - // 显示提示框 - $("#hintModal").modal("show"); - // 2s 后自动隐藏提示框 - setTimeout(function(){ - $("#hintModal").modal("hide"); - // 刷新页面 - if (data.code == 0) { - window.location.reload(); - } - }, 2000); - - } - ) -} \ No newline at end of file diff --git a/src/main/resources/static/js/jquery-3.1.0.min.js b/src/main/resources/static/js/jquery-3.1.0.min.js deleted file mode 100644 index f6a6a99..0000000 --- a/src/main/resources/static/js/jquery-3.1.0.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v3.1.0 | (c) jQuery Foundation | jquery.org/license */ -!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.1.0",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null!=a?a<0?this[a+this.length]:this[a]:f.call(this)},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"label"in b&&b.disabled===a||"form"in b&&b.disabled===a||"form"in b&&b.disabled===!1&&(b.isDisabled===a||b.isDisabled!==!a&&("label"in b||!ea(b))!==a)}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(_,aa),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=V.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(_,aa),$.test(j[0].type)&&qa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&sa(j),!a)return G.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||$.test(a)&&qa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext,B=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,C=/^.[^:#\[\.,]*$/;function D(a,b,c){if(r.isFunction(b))return r.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return r.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(C.test(b))return r.filter(b,a,c);b=r.filter(b,a)}return r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType})}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(D(this,a||[],!1))},not:function(a){return this.pushStack(D(this,a||[],!0))},is:function(a){return!!D(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var E,F=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,G=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||E,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:F.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),B.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};G.prototype=r.fn,E=r(d);var H=/^(?:parents|prev(?:Until|All))/,I={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function J(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return J(a,"nextSibling")},prev:function(a){return J(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return a.contentDocument||r.merge([],a.childNodes)}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(I[a]||r.uniqueSort(e),H.test(a)&&e.reverse()),this.pushStack(e)}});var K=/\S+/g;function L(a){var b={};return r.each(a.match(K)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?L(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function M(a){return a}function N(a){throw a}function O(a,b,c){var d;try{a&&r.isFunction(d=a.promise)?d.call(a).done(b).fail(c):a&&r.isFunction(d=a.then)?d.call(a,b,c):b.call(void 0,a)}catch(a){c.call(void 0,a)}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b=f&&(d!==N&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:M,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:M)),c[2][3].add(g(0,a,r.isFunction(d)?d:N))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(O(a,g.done(h(c)).resolve,g.reject),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)O(e[c],h(c),g.reject);return g.promise()}});var P=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&P.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var Q=r.Deferred();r.fn.ready=function(a){return Q.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,holdReady:function(a){a?r.readyWait++:r.ready(!0)},ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||Q.resolveWith(d,[r]))}}),r.ready.then=Q.then;function R(){d.removeEventListener("DOMContentLoaded",R),a.removeEventListener("load",R),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",R),a.addEventListener("load",R));var S=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)S(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0, -r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h1,null,!0)},removeData:function(a){return this.each(function(){W.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=V.get(a,b),c&&(!d||r.isArray(c)?d=V.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return V.get(a,c)||V.access(a,c,{empty:r.Callbacks("once memory").add(function(){V.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length\x20\t\r\n\f]+)/i,ja=/^$|\/(?:java|ecma)script/i,ka={option:[1,""],thead:[1,"","
                            "],col:[2,"","
                            "],tr:[2,"","
                            "],td:[3,"","
                            "],_default:[0,"",""]};ka.optgroup=ka.option,ka.tbody=ka.tfoot=ka.colgroup=ka.caption=ka.thead,ka.th=ka.td;function la(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&r.nodeName(a,b)?r.merge([a],c):c}function ma(a,b){for(var c=0,d=a.length;c-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=la(l.appendChild(f),"script"),j&&ma(g),c){k=0;while(f=g[k++])ja.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var pa=d.documentElement,qa=/^key/,ra=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,sa=/^([^.]*)(?:\.(.+)|)/;function ta(){return!0}function ua(){return!1}function va(){try{return d.activeElement}catch(a){}}function wa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)wa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ua;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(pa,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(K)||[""],j=b.length;while(j--)h=sa.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.hasData(a)&&V.get(a);if(q&&(i=q.events)){b=(b||"").match(K)||[""],j=b.length;while(j--)if(h=sa.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&V.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(V.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c-1:r.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h\x20\t\r\n\f]*)[^>]*)\/>/gi,ya=/\s*$/g;function Ca(a,b){return r.nodeName(a,"table")&&r.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a:a}function Da(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Ea(a){var b=Aa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(V.hasData(a)&&(f=V.access(a),g=V.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c1&&"string"==typeof q&&!o.checkClone&&za.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(m&&(e=oa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(la(e,"script"),Da),i=h.length;l")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=la(h),f=la(a),d=0,e=f.length;d0&&ma(g,!i&&la(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(T(c)){if(b=c[V.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[V.expando]=void 0}c[W.expando]&&(c[W.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return S(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(la(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return S(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!ya.test(a)&&!ka[(ia.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c1)}});function Xa(a,b,c,d,e){return new Xa.prototype.init(a,b,c,d,e)}r.Tween=Xa,Xa.prototype={constructor:Xa,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=Xa.propHooks[this.prop];return a&&a.get?a.get(this):Xa.propHooks._default.get(this)},run:function(a){var b,c=Xa.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Xa.propHooks._default.set(this),this}},Xa.prototype.init.prototype=Xa.prototype,Xa.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},Xa.propHooks.scrollTop=Xa.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=Xa.prototype.init,r.fx.step={};var Ya,Za,$a=/^(?:toggle|show|hide)$/,_a=/queueHooks$/;function ab(){Za&&(a.requestAnimationFrame(ab),r.fx.tick())}function bb(){return a.setTimeout(function(){Ya=void 0}),Ya=r.now()}function cb(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=aa[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function db(a,b,c){for(var d,e=(gb.tweeners[b]||[]).concat(gb.tweeners["*"]),f=0,g=e.length;f1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?hb:void 0)),void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&r.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(K); -if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),hb={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=ib[b]||r.find.attr;ib[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=ib[g],ib[g]=e,e=null!=c(a,b,d)?g:null,ib[g]=f),e}});var jb=/^(?:input|select|textarea|button)$/i,kb=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return S(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):jb.test(a.nodeName)||kb.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});var lb=/[\t\r\n\f]/g;function mb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,mb(this)))});if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=mb(c),d=1===c.nodeType&&(" "+e+" ").replace(lb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=r.trim(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,mb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=mb(c),d=1===c.nodeType&&(" "+e+" ").replace(lb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=r.trim(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,mb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(K)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=mb(this),b&&V.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":V.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+mb(c)+" ").replace(lb," ").indexOf(b)>-1)return!0;return!1}});var nb=/\r/g,ob=/[\x20\t\r\n\f]+/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":r.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(nb,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:r.trim(r.text(a)).replace(ob," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type,g=f?null:[],h=f?e+1:d.length,i=e<0?h:f?e:0;i-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(r.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var pb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!pb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,pb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(V.get(h,"events")||{})[b.type]&&V.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&T(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!T(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=V.access(d,b);e||d.addEventListener(a,c,!0),V.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=V.access(d,b)-1;e?V.access(d,b,e):(d.removeEventListener(a,c,!0),V.remove(d,b))}}});var qb=a.location,rb=r.now(),sb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var tb=/\[\]$/,ub=/\r?\n/g,vb=/^(?:submit|button|image|reset|file)$/i,wb=/^(?:input|select|textarea|keygen)/i;function xb(a,b,c,d){var e;if(r.isArray(b))r.each(b,function(b,e){c||tb.test(a)?d(a,e):xb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)xb(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(r.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)xb(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&wb.test(this.nodeName)&&!vb.test(a)&&(this.checked||!ha.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:r.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(ub,"\r\n")}}):{name:b.name,value:c.replace(ub,"\r\n")}}).get()}});var yb=/%20/g,zb=/#.*$/,Ab=/([?&])_=[^&]*/,Bb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Cb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Db=/^(?:GET|HEAD)$/,Eb=/^\/\//,Fb={},Gb={},Hb="*/".concat("*"),Ib=d.createElement("a");Ib.href=qb.href;function Jb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(K)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Kb(a,b,c,d){var e={},f=a===Gb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Lb(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Mb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Nb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:qb.href,type:"GET",isLocal:Cb.test(qb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Hb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Lb(Lb(a,r.ajaxSettings),b):Lb(r.ajaxSettings,a)},ajaxPrefilter:Jb(Fb),ajaxTransport:Jb(Gb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Bb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||qb.href)+"").replace(Eb,qb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(K)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Ib.protocol+"//"+Ib.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Kb(Fb,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Db.test(o.type),f=o.url.replace(zb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(yb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(sb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Ab,""),n=(sb.test(f)?"&":"?")+"_="+rb++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Hb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Kb(Gb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Mb(o,y,d)),v=Nb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Ob={0:200,1223:204},Pb=r.ajaxSettings.xhr();o.cors=!!Pb&&"withCredentials"in Pb,o.ajax=Pb=!!Pb,r.ajaxTransport(function(b){var c,d;if(o.cors||Pb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Ob[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r(" - - - - - diff --git a/src/main/resources/templates/error/500.html b/src/main/resources/templates/error/500.html deleted file mode 100644 index 5a05a17..0000000 --- a/src/main/resources/templates/error/500.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - Echo - 500 - - -
                            - -
                            - - -
                            -
                            - -
                            -
                            - - -
                            - -
                            - - - - - - diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html deleted file mode 100644 index 42a8e1f..0000000 --- a/src/main/resources/templates/index.html +++ /dev/null @@ -1,230 +0,0 @@ - - - - - - - - - - Echo - 首页 - - -
                            - -
                            -
                            - - -
                            -
                            - - -
                            -
                            -
                            - - - - - - - - - - -
                            - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                              -
                            • - - 用户头像 - -
                              -
                              - - - -
                              -
                              - 发布于 -
                                -
                              • -
                              • |
                              • -
                              • 回帖
                              • -
                              -
                              -
                              -
                            • -
                            - - -
                            -
                            - - - -
                            -
                            -
                            - -
                            - -
                            - -
                            -
                            -
                            - -
                            -
                            -
                            - -
                            - -
                            -
                            -
                            -
                            -
                            - - - - - - - - diff --git a/src/main/resources/templates/mail/activation.html b/src/main/resources/templates/mail/activation.html deleted file mode 100644 index e8263e3..0000000 --- a/src/main/resources/templates/mail/activation.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - Echo - 激活账号 - - -
                            -

                            - , 您好! 😃 -

                            -

                            - 您正在注册 Echo, 这是一封激活邮件, 请点击 - 此链接, - 激活您的 Echo 账号! 🎉 -

                            -
                            - - \ No newline at end of file diff --git a/src/main/resources/templates/mail/forget.html b/src/main/resources/templates/mail/forget.html deleted file mode 100644 index f511daa..0000000 --- a/src/main/resources/templates/mail/forget.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - Echo - 忘记密码 - - -
                            -

                            - xxx@xxx.com, 您好! -

                            -

                            - 您正在找回 Echo 账号的密码, 本次操作的验证码为 u5s6dt , - 有效时间5分钟, 请您及时进行操作! -

                            -
                            - - \ No newline at end of file diff --git a/src/main/resources/templates/site/admin/data.html b/src/main/resources/templates/site/admin/data.html deleted file mode 100644 index 0054b69..0000000 --- a/src/main/resources/templates/site/admin/data.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - Echo - 数据统计 - - -
                            - -
                            - - -
                            - -
                            -
                            网站 UV
                            -
                            - - - -
                            -
                              -
                            • - 统计结果 - -
                            • -
                            -
                            - -
                            -
                            活跃用户
                            -
                            - - - -
                            -
                              -
                            • - 统计结果 - -
                            • -
                            -
                            -
                            - - -
                            - -
                            - - - - - - - diff --git a/src/main/resources/templates/site/discuss-detail.html b/src/main/resources/templates/site/discuss-detail.html deleted file mode 100644 index 9dd2945..0000000 --- a/src/main/resources/templates/site/discuss-detail.html +++ /dev/null @@ -1,224 +0,0 @@ - - - - - - - - - - - - - - Echo - 帖子详情 - - -
                            - -
                            - - -
                            - -
                            - -
                            - - -
                            - - - - - -
                            -
                            - -
                            - - 用户头像 - -
                            -
                            -
                            - 发布于 - -
                            -
                            -
                            - -
                            - -
                            - - -
                            - -
                            - -
                            -
                            -
                            条回帖
                            -
                            - -
                            - -
                              -
                            • - - 用户头像 - -
                              -
                              - - - - 楼 - -
                              -
                              -
                              - 发布于 - -
                              - -
                                -
                              • -
                                - - :   - - - 回复 - :   - - -
                                -
                                - - -
                                -
                                -
                                - - - - -
                                -
                                - -
                                -
                                -
                                -
                                -
                              • - - -
                              • -
                                -
                                - - - - - -
                                -
                                - -
                                -
                                -
                              • -
                              -
                              -
                            • - -
                            - - - - -
                            - -
                            -
                            -

                            - - - - - -

                            -

                            - -

                            -
                            -
                            -
                            - - -
                            - -
                            - - - - - - - - - - - - - - - - - - diff --git a/src/main/resources/templates/site/discuss-publish.html b/src/main/resources/templates/site/discuss-publish.html deleted file mode 100644 index b0e5c1f..0000000 --- a/src/main/resources/templates/site/discuss-publish.html +++ /dev/null @@ -1,122 +0,0 @@ - - - - - - - - - - - - - - Echo - 发布文章 - - - -
                            - -
                            -
                            -
                            - -
                            -
                            - -
                            - -
                            - -
                            - - - -
                            - - - - -
                            - -
                            - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/templates/site/followee.html b/src/main/resources/templates/site/followee.html deleted file mode 100644 index c434477..0000000 --- a/src/main/resources/templates/site/followee.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - Echo - 关注 - - -
                            - -
                            - - -
                            -
                            - - - -
                              -
                            • - - 用户头像 - -
                              -
                              - - - 关注于 -
                              -
                              - - -
                              -
                              -
                            • -
                            - - -
                            -
                            - - -
                            - -
                            - - - - - - - - diff --git a/src/main/resources/templates/site/follower.html b/src/main/resources/templates/site/follower.html deleted file mode 100644 index ed6b736..0000000 --- a/src/main/resources/templates/site/follower.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - Echo - 粉丝 - - -
                            - -
                            - - -
                            -
                            - - - -
                              -
                            • - - 用户头像 - -
                              -
                              - - - 关注于 -
                              -
                              - - -
                              -
                              -
                            • -
                            - - - -
                            -
                            - - -
                            - -
                            - - - - - - - - diff --git a/src/main/resources/templates/site/forget.html b/src/main/resources/templates/site/forget.html deleted file mode 100644 index 432c453..0000000 --- a/src/main/resources/templates/site/forget.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - Echo - 重置密码 - - -
                            - -
                            - - -
                            -
                            -

                            重置  密码

                            -
                            -
                            - -
                            - - -
                            - 请输入请输入您的账号或绑定的邮箱 -
                            -
                            -
                            -
                            - -
                            - - -
                            - 请输入新密码 -
                            -
                            -
                            -
                            - -
                            - -
                            - 请确任两次密码是否匹配 -
                            -
                            -
                            -
                            - -
                            - -
                            - 请输入图片验证码 -
                            -
                            -
                            - - - -
                            -
                            -
                            - -
                            - -
                            - 请输入邮箱验证码 -
                            -
                            - -
                            -
                            -
                            -
                            - -
                            -
                            -
                            -
                            -
                            - - -
                            -
                            - - - - - - - diff --git a/src/main/resources/templates/site/letter-detail.html b/src/main/resources/templates/site/letter-detail.html deleted file mode 100644 index 5d62145..0000000 --- a/src/main/resources/templates/site/letter-detail.html +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - - Echo - 私信详情 - - -
                            - -
                            - - -
                            -
                            -
                            -
                            -
                            来自 的私信
                            -
                            -
                            - - -
                            -
                            - - - - - - -
                              -
                            • - - 用户头像 - - -
                            • -
                            - - -
                            -
                            - - -
                            - -
                            - - - - - - - - - diff --git a/src/main/resources/templates/site/letter.html b/src/main/resources/templates/site/letter.html deleted file mode 100644 index ba85fa6..0000000 --- a/src/main/resources/templates/site/letter.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - Echo - 私信列表 - - -
                            - -
                            - - -
                            -
                            -
                            - - - -
                            - - - - - - - - - - -
                            -
                            - - -
                            - -
                            - - - - - - - - diff --git a/src/main/resources/templates/site/login.html b/src/main/resources/templates/site/login.html deleted file mode 100644 index 4b73baf..0000000 --- a/src/main/resources/templates/site/login.html +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - Echo - 登录 - - -
                            - -
                            - - -
                            -
                            -

                            登  录

                            -
                            -
                            - -
                            - -
                            -
                            -
                            -
                            - -
                            - -
                            -
                            -
                            -
                            - -
                            - -
                            -
                            - -
                            -
                            -
                            -
                            - - - 忘记密码? -
                            -
                            -
                            -
                            -
                            - -
                            -
                            -
                            -
                            -
                            - - -
                            - -
                            - - - - - - - diff --git a/src/main/resources/templates/site/my-post.html b/src/main/resources/templates/site/my-post.html deleted file mode 100644 index 30f6fb1..0000000 --- a/src/main/resources/templates/site/my-post.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - Echo - 我的帖子 - - -
                            - -
                            - - -
                            -
                            - -
                            - -
                            - -
                            -
                            帖子总数 ()
                            - - - -
                            -
                            -
                            - - -
                            -
                            - - - - - - - diff --git a/src/main/resources/templates/site/my-reply.html b/src/main/resources/templates/site/my-reply.html deleted file mode 100644 index a19ebe6..0000000 --- a/src/main/resources/templates/site/my-reply.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - Echo - 我的回复 - - -
                            - -
                            - - -
                            -
                            - - - -
                            -
                            回复的帖子 ()
                            - - - -
                            -
                            -
                            - - -
                            - -
                            - - - - - - - diff --git a/src/main/resources/templates/site/notice-detail.html b/src/main/resources/templates/site/notice-detail.html deleted file mode 100644 index 36ed623..0000000 --- a/src/main/resources/templates/site/notice-detail.html +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - Echo - 通知详情 - - -
                            - -
                            - - -
                            -
                            -
                            -
                            -
                            系统通知
                            -
                            -
                            - -
                            -
                            - - -
                              -
                            • - 系统图标 - -
                            • -
                            - - -
                            -
                            - - -
                            -
                            - - - - - - - - - - diff --git a/src/main/resources/templates/site/notice.html b/src/main/resources/templates/site/notice.html deleted file mode 100644 index d98d508..0000000 --- a/src/main/resources/templates/site/notice.html +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - Echo - 通知 - - -
                            - -
                            - - -
                            -
                            - - - - -
                            -
                            - - -
                            - -
                            - - - - - - - diff --git a/src/main/resources/templates/site/operate-result.html b/src/main/resources/templates/site/operate-result.html deleted file mode 100644 index db878f0..0000000 --- a/src/main/resources/templates/site/operate-result.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - Echo - 操作结果 - - -
                            - -
                            - - -
                            -
                            -
                            -

                            -
                            -

                            - 系统会在 8 秒后自动跳转, - 您也可以点击 此链接, 手动跳转! -

                            -
                            -
                            -
                            - - -
                            -
                            - - - - - - - diff --git a/src/main/resources/templates/site/profile.html b/src/main/resources/templates/site/profile.html deleted file mode 100644 index 0da08b1..0000000 --- a/src/main/resources/templates/site/profile.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - Echo - 个人主页 - - -
                            - -
                            - - -
                            -
                            - -
                            - -
                            - -
                            - 用户头像 -
                            -
                            - - - -
                            -
                            - 注册于 -
                            -
                            - - - - - - - - - -
                            -
                            -
                            -
                            -
                            - - -
                            -
                            - - - - - - - - diff --git a/src/main/resources/templates/site/register.html b/src/main/resources/templates/site/register.html deleted file mode 100644 index 727092f..0000000 --- a/src/main/resources/templates/site/register.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - Echo - 注册 - - -
                            - -
                            - - -
                            -
                            -

                            注  册

                            -
                            -
                            - -
                            - - -
                            -
                            -
                            -
                            - -
                            - - -
                            -
                            -
                            -
                            - -
                            - -
                            -
                            -
                            -
                            -
                            - -
                            - - -
                            -
                            -
                            -
                            -
                            -
                            - -
                            -
                            -
                            -
                            -
                            - - -
                            -
                            - - - - - - - - diff --git a/src/main/resources/templates/site/reset-pwd.html b/src/main/resources/templates/site/reset-pwd.html deleted file mode 100644 index 330d74c..0000000 --- a/src/main/resources/templates/site/reset-pwd.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - Echo - 重置密码 - - -
                            - -
                            - - -
                            -
                            -

                            重置密码

                            -
                            -
                            - -
                            - - -
                            - 请输入请输入您的账号或绑定的邮箱 -
                            -
                            -
                            -
                            - -
                            - - -
                            - 请输入新密码 -
                            -
                            -
                            -
                            - -
                            - -
                            - 请确任两次密码是否匹配 -
                            -
                            -
                            -
                            - -
                            - -
                            - 请输入图片验证码 -
                            -
                            -
                            - - - -
                            -
                            -
                            - -
                            - -
                            - 请输入邮箱验证码 -
                            -
                            - -
                            -
                            -
                            -
                            - -
                            -
                            -
                            -
                            -
                            - - -
                            -
                            - - - - - - - diff --git a/src/main/resources/templates/site/search.html b/src/main/resources/templates/site/search.html deleted file mode 100644 index 987658b..0000000 --- a/src/main/resources/templates/site/search.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - Echo - 搜索结果 - - -
                            - -
                            - - -
                            -
                            -
                            相关帖子
                            - -
                              -
                            • - 用户头像 -
                              -
                              - -
                              -
                              -
                              - - 发布于 -
                                -
                              • -
                              • |
                              • -
                              • 回复
                              • -
                              -
                              -
                              -
                            • -
                            - - -
                            -
                            - - -
                            -
                            - - - - - - - diff --git a/src/main/resources/templates/site/setting.html b/src/main/resources/templates/site/setting.html deleted file mode 100644 index 7261f59..0000000 --- a/src/main/resources/templates/site/setting.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - Echo - 账号设置 - - -
                            - -
                            - - -
                            -
                            - -
                            上传头像
                            -
                            -
                            - -
                            -
                            - - - - -
                            -
                            -
                            -
                            -
                            -
                            -
                            - -
                            -
                            -
                            - - -
                            修改密码
                            -
                            -
                            - -
                            - -
                            -
                            -
                            -
                            - -
                            - -
                            -
                            -
                            -
                            - -
                            - -
                            -
                            -
                            -
                            -
                            -
                            - -
                            -
                            -
                            -
                            -
                            - - -
                            -
                            - - - - - - - - - - -- Gitee From 86547f257c1815d6368fc44d63e95aff175017fe Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Wed, 23 Feb 2022 21:41:25 +0800 Subject: [PATCH 038/125] =?UTF-8?q?=E8=8E=B7=E5=8F=96=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E7=B2=89=E4=B8=9Dbug=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/service/FollowService.java | 6 +++-- src/main/resources/banner.txt | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 src/main/resources/banner.txt diff --git a/src/main/java/com/greate/community/service/FollowService.java b/src/main/java/com/greate/community/service/FollowService.java index 3bce24a..eabc687 100644 --- a/src/main/java/com/greate/community/service/FollowService.java +++ b/src/main/java/com/greate/community/service/FollowService.java @@ -407,7 +407,8 @@ public class FollowService implements CommunityConstant { for(User user:followerUsers){ Map map = new HashMap<>(); map.put("user", user); - Date followTime = findFollowTime(userId, ENTITY_TYPE_USER, user.getId()); +// Date followTime = findFollowTime(userId, ENTITY_TYPE_USER, user.getId()); + Date followTime = findFollowTime(user.getId(), ENTITY_TYPE_USER, userId); map.put("followTime", followTime); list.add(map); } @@ -422,7 +423,8 @@ public class FollowService implements CommunityConstant { User user = userService.findUserById(targetId); map.put("user", user); - Date followTime = findFollowTime(userId, ENTITY_TYPE_USER, user.getId()); +// Date followTime = findFollowTime(userId, ENTITY_TYPE_USER, user.getId()); + Date followTime = findFollowTime(user.getId(), ENTITY_TYPE_USER, userId); map.put("followTime", followTime); list.add(map); diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt new file mode 100644 index 0000000..c07c483 --- /dev/null +++ b/src/main/resources/banner.txt @@ -0,0 +1,23 @@ +${AnsiColor.BRIGHT_YELLOW} +//////////////////////////////////////////////////////////////////// +// _ooOoo_ // +// o8888888o // +// 88" . "88 // +// (| ^_^ |) // +// O\ = /O // +// ____/`---'\____ // +// .' \\| |// `. // +// / \\||| : |||// \ // +// / _||||| -:- |||||- \ // +// | | \\\ - /// | | // +// | \_| ''\---/'' | | // +// \ .-\__ `-` ___/-. / // +// ___`. .' /--.--\ `. . ___ // +// ."" '< `.___\_<|>_/___.' >'"". // +// | | : `- \`.;`\ _ /`;.`/ - ` : | | // +// \ \ `-. \_ __\ /__ _/ .-` / / // +// ========`-.____`-.___\_____/___.-`____.-'======== // +// `=---=' // +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // +// 佛祖保佑 永不宕机 永无BUG // +//////////////////////////////////////////////////////////////////// \ No newline at end of file -- Gitee From b7bad3146a3733d9ffd9338ac53458fe39cdbbee Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Thu, 24 Feb 2022 00:56:18 +0800 Subject: [PATCH 039/125] update: persistent like count --- .../controller/CommentController.java | 5 +- .../controller/DiscussPostController.java | 6 +- .../community/controller/IndexController.java | 2 - .../community/controller/LoginController.java | 21 ++- .../community/controller/UserController.java | 9 - .../greate/community/dao/CommentMapper.java | 7 + .../community/dao/DiscussPostMapper.java | 8 + .../com/greate/community/dao/LikeMapper.java | 2 +- .../com/greate/community/dao/UserMapper.java | 8 + .../com/greate/community/entity/Comment.java | 2 + .../greate/community/entity/DiscussPost.java | 105 +---------- .../com/greate/community/entity/User.java | 1 + .../community/quartz/PostScoreRefreshJob.java | 2 +- .../community/service/CommentService.java | 8 + .../community/service/DiscussPostService.java | 8 + .../greate/community/service/LikeService.java | 102 +++++------ .../greate/community/service/UserService.java | 8 + .../com/greate/community/util/ExpType.java | 8 +- .../greate/community/util/RedisKeyUtil.java | 23 --- src/main/resources/mapper/comment-mapper.xml | 11 +- .../resources/mapper/discusspost-mapper.xml | 171 +++++++++--------- src/main/resources/mapper/user-mapper.xml | 11 +- 22 files changed, 236 insertions(+), 292 deletions(-) diff --git a/src/main/java/com/greate/community/controller/CommentController.java b/src/main/java/com/greate/community/controller/CommentController.java index e84585a..f760df3 100644 --- a/src/main/java/com/greate/community/controller/CommentController.java +++ b/src/main/java/com/greate/community/controller/CommentController.java @@ -58,6 +58,7 @@ public class CommentController extends BaseController implements CommunityConsta comment.setTargetId((Integer) map.get("targetId")); comment.setUserId(getUser().getId()); + comment.setLikeCount(0); comment.setStatus(0); // 正常 comment.setCreateTime(new Date()); commentService.addComment(comment); @@ -113,8 +114,6 @@ public class CommentController extends BaseController implements CommunityConsta Map commentVo = new HashMap<>(); commentVo.put("comment", StringListConvertor.toJsonObject(comment, "picUrls")); // 评论 commentVo.put("user", userService.findUserById(comment.getUserId())); // 发布评论的作者 - long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_COMMENT, comment.getId()); // 该评论点赞数量 - commentVo.put("likeCount", likeCount); int likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( getUser().getId(), ENTITY_TYPE_COMMENT, comment.getId()); // 当前登录用户对该评论的点赞状态 commentVo.put("likeStatus", likeStatus); @@ -131,8 +130,6 @@ public class CommentController extends BaseController implements CommunityConsta replyVo.put("user", userService.findUserById(reply.getUserId())); // 发布该回复的作者 User target = reply.getTargetId() == 0 ? null : userService.findUserById(reply.getTargetId()); replyVo.put("target", target); // 该回复的目标用户 - likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_COMMENT, reply.getId()); - replyVo.put("likeCount", likeCount); // 该回复的点赞数量 likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( getUser().getId(), ENTITY_TYPE_COMMENT, reply.getId()); replyVo.put("likeStatus", likeStatus); // 当前登录用户的点赞状态 diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index 1b609c4..25f6e23 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -76,6 +76,8 @@ public class DiscussPostController extends BaseController implements CommunityCo discussPost.setTitle(title); discussPost.setContent(content); discussPost.setPicUrls(picUrls); + discussPost.setLikeCount(0); + discussPost.setCommentCount(0); discussPost.setCreateTime(new Date()); discussPostService.addDiscussPost(discussPost); @@ -118,10 +120,6 @@ public class DiscussPostController extends BaseController implements CommunityCo User user = userService.findUserById(discussPost.getUserId()); resultMap.put("user", user); - // 点赞数量 - long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, discussPostId); - resultMap.put("likeCount", likeCount); - // 当前登录用户的点赞状态 int likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus(getUser().getId(), ENTITY_TYPE_POST, discussPostId); diff --git a/src/main/java/com/greate/community/controller/IndexController.java b/src/main/java/com/greate/community/controller/IndexController.java index 06b40fb..43a1921 100644 --- a/src/main/java/com/greate/community/controller/IndexController.java +++ b/src/main/java/com/greate/community/controller/IndexController.java @@ -62,8 +62,6 @@ public class IndexController extends BaseController implements CommunityConstant User user = userService.findUserById(post.getUserId()); map.put("user", user); - long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId()); - map.put("likeCount", likeCount); // 当前登录用户对帖子的点赞状态 int likeStatus = getUser() == null ? 0 : diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index 5f88fed..08fe7ba 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -177,8 +177,7 @@ public class LoginController extends BaseController implements CommunityConstant // 增加经验 expService.handleGetExp(Integer.parseInt(map.get("userId").toString()), ExpType.EXP_LOGIN.getName()); return new Result("success", Result.SUCCESS, ticket); - } - else { + } else { return new Result("fail", "2", map); } } @@ -190,11 +189,10 @@ public class LoginController extends BaseController implements CommunityConstant */ @GetMapping("/wechat/login") public void wechatLogin(@AuthenticationPrincipal UserWeChat userWeChat, HttpServletResponse response) throws IOException { - String username = userWeChat.getNickName();//微信昵称 - String password = CommunityUtil.generateUUID();//随机密码,不能随便让人破解 - String headerUrl = userWeChat.getHeadimgurl();//微信头像地址 - String email = "wechat@none.com";//微信登录的用户,邮箱是一个特殊标识字符串 - + String username = userWeChat.getNickName(); //微信昵称 + String password = CommunityUtil.generateUUID(); //随机密码,不能随便让人破解 + String headerUrl = userWeChat.getHeadimgurl(); //微信头像地址 + String email = "wechat@none.com"; //微信登录的用户,邮箱是一个特殊标识字符串 // 若微信用户对应的账号已存在,跳过模拟注册操作,直接进入登录过程 User u = userMapper.selectByName(username); @@ -206,16 +204,19 @@ public class LoginController extends BaseController implements CommunityConstant user.setEmail(email); user.setType(0); // 默认普通用户 user.setStatus(1); // 微信登录用户默认激活,无需邮箱验证 + user.setLevel(0); // 等级默认0级 + user.setExp(0); // 经验0 + user.setLikeCount(0); // 点赞数量0 // 用户头像 - user.setHeaderUrl(headerUrl);//微信头像地址 + user.setHeaderUrl(headerUrl); // 微信头像地址 user.setCreateTime(new Date()); // 注册时间 userMapper.insertUser(user); // 这一步主要是为了获取userId user = userMapper.selectByName(username); /**模拟注册操作**/ - }else { + } else { user = u; } @@ -240,7 +241,7 @@ public class LoginController extends BaseController implements CommunityConstant //return new Result("success", Result.SUCCESS, ticket); //todo 带上ticket重定向到前端 - response.sendRedirect("http://119.91.149.96:8080/?ticket="+ticket); + response.sendRedirect("http://119.91.149.96:8080/?ticket=" + ticket); } /** diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 2f0b3a4..489f648 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -71,9 +71,6 @@ public class UserController extends BaseController implements CommunityConstant // 用户 jsonObject.put("user", user); - // 获赞数量 - long userLikeCount = likeService.findUserLikeCount(user.getId()); - jsonObject.put("userLikeCount", userLikeCount); // 关注数量 long followeeCount = followService.findFolloweeCount(user.getId(), ENTITY_TYPE_USER); jsonObject.put("followeeCount", followeeCount); @@ -148,9 +145,6 @@ public class UserController extends BaseController implements CommunityConstant // 用户 jsonObject.put("user", user); - // 获赞数量 - long userLikeCount = likeService.findUserLikeCount(userId); - jsonObject.put("userLikeCount", userLikeCount); // 关注数量 long followeeCount = followService.findFolloweeCount(userId, ENTITY_TYPE_USER); jsonObject.put("followeeCount", followeeCount); @@ -203,9 +197,6 @@ public class UserController extends BaseController implements CommunityConstant //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 map.put("post", discussPostService.toDiscussPostJsonObject(post)); - long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId()); - map.put("likeCount", likeCount); - discussPosts.add(map); } } diff --git a/src/main/java/com/greate/community/dao/CommentMapper.java b/src/main/java/com/greate/community/dao/CommentMapper.java index ed5e1a9..0250732 100644 --- a/src/main/java/com/greate/community/dao/CommentMapper.java +++ b/src/main/java/com/greate/community/dao/CommentMapper.java @@ -70,4 +70,11 @@ public interface CommentMapper { */ int selectCommentCountByUserId(int userId); + /** + * 增加点赞数 + * @param id + * @param likeCount + * @return + */ + int addLikeCount(int id, int likeCount); } diff --git a/src/main/java/com/greate/community/dao/DiscussPostMapper.java b/src/main/java/com/greate/community/dao/DiscussPostMapper.java index 3f656f2..1f018a9 100644 --- a/src/main/java/com/greate/community/dao/DiscussPostMapper.java +++ b/src/main/java/com/greate/community/dao/DiscussPostMapper.java @@ -74,4 +74,12 @@ public interface DiscussPostMapper { * @return */ int updateScore(int id, double score); + + /** + * 增加点赞数 + * @param id + * @param likeCount + * @return + */ + int addLikeCount(int id, int likeCount); } diff --git a/src/main/java/com/greate/community/dao/LikeMapper.java b/src/main/java/com/greate/community/dao/LikeMapper.java index b0d0991..bb6fb6c 100644 --- a/src/main/java/com/greate/community/dao/LikeMapper.java +++ b/src/main/java/com/greate/community/dao/LikeMapper.java @@ -35,7 +35,7 @@ public interface LikeMapper { * * @param userId * @param entityType - * @param entityUserId + * @param entityId * @return */ int deleteLikeByUserIdAndEntity(int userId, int entityType, int entityId); diff --git a/src/main/java/com/greate/community/dao/UserMapper.java b/src/main/java/com/greate/community/dao/UserMapper.java index 62ceb0f..c0dfcab 100644 --- a/src/main/java/com/greate/community/dao/UserMapper.java +++ b/src/main/java/com/greate/community/dao/UserMapper.java @@ -89,4 +89,12 @@ public interface UserMapper { * 更新用户实名信息 */ int updateRealNameInfo(User user); + + /** + * 增加点赞数 + * @param id + * @param likeCount + * @return + */ + int addLikeCount(int id, int likeCount); } diff --git a/src/main/java/com/greate/community/entity/Comment.java b/src/main/java/com/greate/community/entity/Comment.java index a1ea516..7dfaf10 100644 --- a/src/main/java/com/greate/community/entity/Comment.java +++ b/src/main/java/com/greate/community/entity/Comment.java @@ -29,6 +29,8 @@ public class Comment { private int targetId; // 帖子 id private int postId; + // 点赞数 + private int likeCount; // 状态:0 正常,1 禁用 private int status; // 发布时间 diff --git a/src/main/java/com/greate/community/entity/DiscussPost.java b/src/main/java/com/greate/community/entity/DiscussPost.java index c284dc9..844e37e 100644 --- a/src/main/java/com/greate/community/entity/DiscussPost.java +++ b/src/main/java/com/greate/community/entity/DiscussPost.java @@ -2,6 +2,8 @@ package com.greate.community.entity; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import lombok.Data; +import lombok.ToString; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; @@ -13,6 +15,8 @@ import java.util.Date; * 讨论贴 * 对应数据库表 `discuss_post` */ +@Data +@ToString @Document(indexName = "discusspost") public class DiscussPost { @@ -37,8 +41,8 @@ public class DiscussPost { @Field(type = FieldType.Integer) private int status; - @Field(type = FieldType.Date) - private Date createTime; + @Field(type = FieldType.Integer) + private int likeCount; @Field(type = FieldType.Integer) private int commentCount; @@ -46,99 +50,6 @@ public class DiscussPost { @Field(type = FieldType.Double) private double score; - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public int getUserId() { - return userId; - } - - public void setUserId(int userId) { - this.userId = userId; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - public String getPicUrls() { - return picUrls; - } - - public void setPicUrls(String picUrls) { - this.picUrls = picUrls; - } - - public int getType() { - return type; - } - - public void setType(int type) { - this.type = type; - } - - public int getStatus() { - return status; - } - - public void setStatus(int status) { - this.status = status; - } - - public Date getCreateTime() { - return createTime; - } - - public void setCreateTime(Date createTime) { - this.createTime = createTime; - } - - public int getCommentCount() { - return commentCount; - } - - public void setCommentCount(int commentCount) { - this.commentCount = commentCount; - } - - public double getScore() { - return score; - } - - public void setScore(double score) { - this.score = score; - } - - @Override - public String toString() { - return "DiscussPost{" + - "id=" + id + - ", userId=" + userId + - ", title='" + title + '\'' + - ", content='" + content + '\'' + - ", picUrls ='" + picUrls + '\'' + - ", type=" + type + - ", status=" + status + - ", createTime=" + createTime + - ", commentCount=" + commentCount + - ", score=" + score + - '}'; - } + @Field(type = FieldType.Date) + private Date createTime; } diff --git a/src/main/java/com/greate/community/entity/User.java b/src/main/java/com/greate/community/entity/User.java index c5d8d17..6d79071 100644 --- a/src/main/java/com/greate/community/entity/User.java +++ b/src/main/java/com/greate/community/entity/User.java @@ -30,6 +30,7 @@ public class User { private String institute; private String professionalClass; private int auditStatus; + private int likeCount; private Date createTime; } diff --git a/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java b/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java index f1b2742..1b64d29 100644 --- a/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java +++ b/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java @@ -83,7 +83,7 @@ public class PostScoreRefreshJob implements Job, CommunityConstant { // 评论数量 int commentCount = post.getCommentCount(); // 点赞数量 - long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, postId); + long likeCount = post.getLikeCount(); // 计算权重 double w = (wonderful ? 75 : 0) + commentCount * 10 + likeCount * 2; diff --git a/src/main/java/com/greate/community/service/CommentService.java b/src/main/java/com/greate/community/service/CommentService.java index e1b429d..403f784 100644 --- a/src/main/java/com/greate/community/service/CommentService.java +++ b/src/main/java/com/greate/community/service/CommentService.java @@ -123,4 +123,12 @@ public class CommentService implements CommunityConstant { return rows; } + public int like(int id) { + return commentMapper.addLikeCount(id, 1); + } + + public int cancelLike(int id) { + return commentMapper.addLikeCount(id, -1); + } + } diff --git a/src/main/java/com/greate/community/service/DiscussPostService.java b/src/main/java/com/greate/community/service/DiscussPostService.java index 404e84a..c276897 100644 --- a/src/main/java/com/greate/community/service/DiscussPostService.java +++ b/src/main/java/com/greate/community/service/DiscussPostService.java @@ -234,4 +234,12 @@ public class DiscussPostService { return discussPostJsonObject; } } + + public int like(int id) { + return discussPostMapper.addLikeCount(id, 1); + } + + public int cancelLike(int id) { + return discussPostMapper.addLikeCount(id, -1); + } } diff --git a/src/main/java/com/greate/community/service/LikeService.java b/src/main/java/com/greate/community/service/LikeService.java index 182ea9d..d04e8a2 100644 --- a/src/main/java/com/greate/community/service/LikeService.java +++ b/src/main/java/com/greate/community/service/LikeService.java @@ -2,6 +2,7 @@ package com.greate.community.service; import com.greate.community.dao.LikeMapper; import com.greate.community.entity.Like; +import com.greate.community.util.CommunityConstant; import com.greate.community.util.RedisKeyUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; @@ -16,7 +17,7 @@ import java.util.Date; * 点赞相关 */ @Service -public class LikeService { +public class LikeService implements CommunityConstant { @Autowired private RedisTemplate redisTemplate; @@ -24,6 +25,15 @@ public class LikeService { @Autowired private LikeMapper likeMapper; + @Autowired + private DiscussPostService discussPostService; + + @Autowired + private CommentService commentService; + + @Autowired + private UserService userService; + /** * 点赞 * @@ -35,10 +45,15 @@ public class LikeService { public void insertLike(int userId, int entityType, int entityId, int entityUserId) { // 判断是否点过赞 int likeStatus = findEntityLikeStatus(userId, entityType, entityId); + String userIdOfLikeKey = RedisKeyUtil.getUserIdOfLikeKey(entityType, entityId); if (likeStatus == 1) { // 如果用户已经点过赞,点第二次则取消赞 - likeMapper.deleteLikeByUserIdAndEntity(userId, entityType, entityId); + int result = likeMapper.deleteLikeByUserIdAndEntity(userId, entityType, entityId); + if (result == 1) { + cancelLikeEntity(entityType, entityId, entityUserId); + redisTemplate.opsForSet().remove(userIdOfLikeKey, userId); // 删除实体对应的点赞 userId + } } else { Like like = new Like(); like.setUserId(userId); @@ -46,33 +61,12 @@ public class LikeService { like.setEntityId(entityId); like.setEntityUserId(entityUserId); like.setCreateTime(new Date()); - likeMapper.insertLike(like); - } - - // 处理 redis - redisTemplate.execute(new SessionCallback() { - @Override - public Object execute(RedisOperations redisOperations) throws DataAccessException { - String userIdOfLikeKey = RedisKeyUtil.getUserIdOfLikeKey(entityType, entityId); - String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId); - String userLikeKey = RedisKeyUtil.getUserLikeKey(entityUserId); - - redisOperations.multi(); // 开启事务 - - if (likeStatus == 1) { - // 如果用户已经点过赞,点第二次则取消赞 - redisOperations.opsForSet().remove(userIdOfLikeKey, userId); // 删除实体对应的点赞 userId - redisOperations.opsForValue().decrement(entityLikeKey); // 实体获赞数量-1 - redisOperations.opsForValue().decrement(userLikeKey); // 用户获赞数量-1 - } else { - redisOperations.opsForSet().add(userIdOfLikeKey, userId); // 删除实体对应的点赞 userId - redisOperations.opsForValue().increment(entityLikeKey); // 实体获赞数量+1 - redisOperations.opsForValue().increment(userLikeKey); // 用户获赞数量+1 - } - - return redisOperations.exec(); // 提交事务 + int result = likeMapper.insertLike(like); + if (result == 1) { + likeEntity(entityType, entityId, entityUserId); + redisTemplate.opsForSet().add(userIdOfLikeKey, userId); // 新增实体对应的点赞 userId } - }); + } } /** @@ -84,19 +78,13 @@ public class LikeService { */ public long findEntityLikeCount(int entityType, int entityId) { long count = 0; - String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId); - - if (redisTemplate.hasKey(entityLikeKey)) { - // redis 中查询 - Integer num = (Integer) redisTemplate.opsForValue().get(entityLikeKey); - count = num == null ? 0 : num; - } else { - // mysql 中查询 - count = likeMapper.countLikeByEntity(entityType, entityId); - // 找到了之后存入 redis - redisTemplate.opsForValue().set(entityLikeKey, count); + if (entityType == ENTITY_TYPE_POST) { + count = discussPostService.findDiscussPostById(entityId).getLikeCount(); + } else if (entityType == ENTITY_TYPE_COMMENT) { + count = commentService.findCommentById(entityId).getLikeCount(); + } else if (entityType == ENTITY_TYPE_USER) { + count = userService.findUserById(entityId).getLikeCount(); } - return count; } @@ -125,18 +113,30 @@ public class LikeService { return likeStatus; } - /** - * 查询某个用户获得赞数量 - * - * @param userId - * @return - */ - public long findUserLikeCount(int userId) { - // todo 将用户获赞数存入 mysql user 表中 - String userLikeKey = RedisKeyUtil.getUserLikeKey(userId); - Integer count = (Integer) redisTemplate.opsForValue().get(userLikeKey); - return count == null ? 0 : count; + public int likeEntity(int entityType, int entityId, int entityUserId) { + int result = 0; + if (entityType == ENTITY_TYPE_POST) { + result = discussPostService.like(entityId); + } else if (entityType == ENTITY_TYPE_COMMENT) { + result = commentService.like(entityId); + } + if (result == 1) { + result = userService.like(entityUserId); + } + return result; } + public int cancelLikeEntity(int entityType, int entityId, int entityUserId) { + int result = 0; + if (entityType == ENTITY_TYPE_POST) { + result = discussPostService.cancelLike(entityId); + } else if (entityType == ENTITY_TYPE_COMMENT) { + result = commentService.cancelLike(entityId); + } + if (result == 1) { + result = userService.cancelLike(entityUserId); + } + return result; + } } diff --git a/src/main/java/com/greate/community/service/UserService.java b/src/main/java/com/greate/community/service/UserService.java index bcf681a..fe6a898 100644 --- a/src/main/java/com/greate/community/service/UserService.java +++ b/src/main/java/com/greate/community/service/UserService.java @@ -428,4 +428,12 @@ public class UserService implements CommunityConstant { return rows; } + public int like(int id) { + return userMapper.addLikeCount(id, 1); + } + + public int cancelLike(int id) { + return userMapper.addLikeCount(id, -1); + } + } diff --git a/src/main/java/com/greate/community/util/ExpType.java b/src/main/java/com/greate/community/util/ExpType.java index c471704..68ff986 100644 --- a/src/main/java/com/greate/community/util/ExpType.java +++ b/src/main/java/com/greate/community/util/ExpType.java @@ -15,10 +15,10 @@ public enum ExpType { static int ONE_LEVEL_OF_EXP = 0; // 通过实名认证 static int TWO_LEVEL_OF_EXP = 200; - static int THREE_LEVEL_OF_EXP = 1000; // 10天 - static int FOUR_LEVEL_OF_EXP = 2333; // 1个月 - static int FIVE_LEVEL_OF_EXP = 6666; // 2个月 - static int SIX_LEVEL_OF_EXP = 16666; // 半年 + static int THREE_LEVEL_OF_EXP = 1000; + static int FOUR_LEVEL_OF_EXP = 2333; + static int FIVE_LEVEL_OF_EXP = 6666; + static int SIX_LEVEL_OF_EXP = 16666; private static final ExpType[] TYPES = values(); private final int count; diff --git a/src/main/java/com/greate/community/util/RedisKeyUtil.java b/src/main/java/com/greate/community/util/RedisKeyUtil.java index ac57dbb..2a652ba 100644 --- a/src/main/java/com/greate/community/util/RedisKeyUtil.java +++ b/src/main/java/com/greate/community/util/RedisKeyUtil.java @@ -31,29 +31,6 @@ public class RedisKeyUtil { return PREFIX_USER_ID_LIKE + SPLIT + entityType + SPLIT + entityId; } - /** - * 某个实体(帖子、评论/回复)的获赞数量 - * like:entity:entityType:entityId -> int - * - * @param entityType - * @param entityId - * @return - */ - public static String getEntityLikeKey(int entityType, int entityId) { - return PREFIX_ENTITY_LIKE + SPLIT + entityType + SPLIT + entityId; - } - - /** - * 某个用户的获赞数量 - * like:user:userId -> int - * - * @param userId 获赞用户的 id - * @return - */ - public static String getUserLikeKey(int userId) { - return PREFIX_USER_LIKE + SPLIT + userId; - } - /** * 某个用户关注的实体 * followee:userId:entityType -> zset(entityId, now) 以当前关注的时间进行排序 diff --git a/src/main/resources/mapper/comment-mapper.xml b/src/main/resources/mapper/comment-mapper.xml index 3c493d3..85fa7f5 100644 --- a/src/main/resources/mapper/comment-mapper.xml +++ b/src/main/resources/mapper/comment-mapper.xml @@ -5,11 +5,11 @@ - id, content, pic_urls, user_id, entity_type, entity_id, root_id, target_id, post_id, status, create_time + id, content, pic_urls, user_id, entity_type, entity_id, root_id, target_id, post_id, like_count, status, create_time - content, pic_urls, user_id, entity_type, entity_id, root_id, target_id, post_id, status, create_time + content, pic_urls, user_id, entity_type, entity_id, root_id, target_id, post_id, like_count, status, create_time + + + + update comment + set like_count = like_count + #{likeCount} + where id = #{id} + \ No newline at end of file diff --git a/src/main/resources/mapper/discusspost-mapper.xml b/src/main/resources/mapper/discusspost-mapper.xml index 0f212ad..85ed521 100644 --- a/src/main/resources/mapper/discusspost-mapper.xml +++ b/src/main/resources/mapper/discusspost-mapper.xml @@ -1,83 +1,90 @@ - - - - - - id, user_id, title, content, pic_urls, type, status, create_time, comment_count, score - - - - user_id, title, content, pic_urls, type, status, create_time, comment_count, score - - - - - - - - - - - - insert into discuss_post () - values(#{userId}, #{title}, #{content}, #{picUrls}, #{type}, #{status}, #{createTime}, #{commentCount}, #{score}) - - - - - - - update discuss_post - set comment_count = #{commentCount} - where id = #{id} - - - - - update discuss_post - set type = #{type} - where id = #{id} - - - - - update discuss_post - set status = #{status} - where id = #{id} - - - - - update discuss_post - set score = #{score} - where id = #{id} - - + + + + + + id, user_id, title, content, pic_urls, type, status, like_count, comment_count, score, create_time + + + + user_id, title, content, pic_urls, type, status, like_count, comment_count, score, create_time + + + + + + + + + + + + insert into discuss_post () + values(#{userId}, #{title}, #{content}, #{picUrls}, #{type}, #{status}, #{createTime}, #{commentCount}, #{score}) + + + + + + + update discuss_post + set comment_count = #{commentCount} + where id = #{id} + + + + + update discuss_post + set type = #{type} + where id = #{id} + + + + + update discuss_post + set status = #{status} + where id = #{id} + + + + + update discuss_post + set score = #{score} + where id = #{id} + + + + + update discuss_post + set like_count = like_count + #{likeCount} + where id = #{id} + + \ No newline at end of file diff --git a/src/main/resources/mapper/user-mapper.xml b/src/main/resources/mapper/user-mapper.xml index 3364c77..63d2c94 100644 --- a/src/main/resources/mapper/user-mapper.xml +++ b/src/main/resources/mapper/user-mapper.xml @@ -5,11 +5,11 @@ - username, password, salt, email, type, status, activation_code, header_url, create_time + username, password, salt, email, type, status, activation_code, header_url, like_count, create_time - id, username, password, salt, email, exp, level, type, status, activation_code, header_url, audit_status, create_time + id, username, password, salt, email, exp, level, type, status, activation_code, header_url, audit_status, like_count, create_time @@ -95,4 +95,11 @@ update user set student_card_url = #{studentCardUrl} , student_code = #{studentCode}, real_name = #{realName}, institute = #{institute}, professional_class = #{professionalClass}, audit_status = 1 where id = #{id} + + + + update user + set like_count = like_count + #{likeCount} + where id = #{id} + \ No newline at end of file -- Gitee From 4961e0ce0e9794541e3c358deebc03777fa87ca9 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Thu, 24 Feb 2022 17:39:11 +0800 Subject: [PATCH 040/125] add get realname --- .../community/config/SecurityConfig.java | 2 + .../community/controller/LoginController.java | 10 ++--- .../community/controller/UserController.java | 26 ++++++++++++- .../com/greate/community/dao/UserMapper.java | 10 +++++ .../greate/community/service/UserService.java | 38 +++++++++++++++++-- src/main/resources/mapper/user-mapper.xml | 21 +++++++++- 6 files changed, 94 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index ef53684..7fcd3ab 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -71,6 +71,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm "/user/setting", "/user/upload", "/user/studentCard/url", + "/user/header/url", + "/user/username", "/user/updateHeader", "/discuss/add", "/discuss/publish", diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index 08fe7ba..42485f6 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -198,8 +198,8 @@ public class LoginController extends BaseController implements CommunityConstant User u = userMapper.selectByName(username); User user = new User(); if (u == null) { - /**模拟注册操作**/ - user.setUsername(username); + // 模拟注册操作 +// user.setUsername(username); user.setPassword(password); user.setEmail(email); user.setType(0); // 默认普通用户 @@ -215,12 +215,11 @@ public class LoginController extends BaseController implements CommunityConstant userMapper.insertUser(user); // 这一步主要是为了获取userId user = userMapper.selectByName(username); - /**模拟注册操作**/ } else { user = u; } - /**模拟普通登录过程**/ + // 模拟普通登录过程 // 凭证过期时间 int expiredSeconds = DEFAULT_EXPIRED_SECONDS; @@ -236,9 +235,6 @@ public class LoginController extends BaseController implements CommunityConstant redisTemplate.opsForValue().set(redisKey, loginTicket); String ticket = loginTicket.getTicket(); - /**模拟普通登录过程**/ - - //return new Result("success", Result.SUCCESS, ticket); //todo 带上ticket重定向到前端 response.sendRedirect("http://119.91.149.96:8080/?ticket=" + ticket); diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 489f648..45389df 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -60,7 +60,6 @@ public class UserController extends BaseController implements CommunityConstant * * @return */ - @Deprecated @GetMapping("/get") public Result getUserByTicket() { JSONObject jsonObject = new JSONObject(); @@ -81,6 +80,16 @@ public class UserController extends BaseController implements CommunityConstant return new Result("success", Result.SUCCESS, jsonObject); } + /** + * 获取user实名信息 + * + * @return + */ + @GetMapping("/realname/get") + public Result getRealNameUserByTicket() { + return new Result("success", Result.SUCCESS, userService.findAllUserById(getUser().getId())); + } + /** * 更新图像路径(将本地的图像路径更新为云服务器上的图像路径) * @@ -101,6 +110,21 @@ public class UserController extends BaseController implements CommunityConstant return CommunityUtil.getJSONString(0); } + @PostMapping("/username") + public Result updateUsername(@RequestBody String username) { + if (StringUtils.isBlank(username)) { + return new Result("fail", "1", "用户名不能为空"); + } + int result = userService.updateUsername(getUser().getId(), username); + if (result == 2) { + return new Result("fail", "2", "用户名不能重复"); + } else if (result == 0) { + return new Result("fail", "3", "用户名修改失败"); + } else { + return new Result("success", Result.SUCCESS, "用户名修改成功"); + } + } + /** * 修改用户密码 * diff --git a/src/main/java/com/greate/community/dao/UserMapper.java b/src/main/java/com/greate/community/dao/UserMapper.java index c0dfcab..7cfb2a3 100644 --- a/src/main/java/com/greate/community/dao/UserMapper.java +++ b/src/main/java/com/greate/community/dao/UserMapper.java @@ -14,6 +14,11 @@ public interface UserMapper { */ User selectById(int id); + /** + * 根据 id 查询用户(包括实名信息) + */ + User selectAllById(int id); + /** * 根据 username 查询用户 */ @@ -39,6 +44,11 @@ public interface UserMapper { */ int updateHeader(int id, String headerUrl); + /** + * 修改用户名 + */ + int updateUsername(int id, String username); + /** * 修改密码 */ diff --git a/src/main/java/com/greate/community/service/UserService.java b/src/main/java/com/greate/community/service/UserService.java index fe6a898..fadd1b7 100644 --- a/src/main/java/com/greate/community/service/UserService.java +++ b/src/main/java/com/greate/community/service/UserService.java @@ -46,6 +46,16 @@ public class UserService implements CommunityConstant { return user; } + /** + * 根据 Id 查询用户(包括实名信息) + * + * @param id + * @return + */ + public User findAllUserById(int id) { + return userMapper.selectAllById(id); + } + /** * 根据 username 查询用户 * @@ -235,6 +245,29 @@ public class UserService implements CommunityConstant { return rows; } + /** + * 修改用户名 + * + * @param userId + * @param username + * @return + */ + public int updateUsername(int userId, String username) { + User user = findUserByName(username); + if (user == null) { + // 名称没被占用 + int rows = userMapper.updateUsername(userId, username); + clearCache(userId); + return rows; + } else if (user.getId() == userId) { + // 新名称和原名称相同 + return 1; + } else { + // 名称被占用 + return 2; + } + } + /** * 修改用户密码(对新密码加盐加密存入数据库) * @@ -422,10 +455,7 @@ public class UserService implements CommunityConstant { * @return */ public int updateRealNameInfo(User user) { - // return userMapper.updateHeader(userId, headUrl); - int rows = userMapper.updateRealNameInfo(user); - clearCache(user.getId()); - return rows; + return userMapper.updateRealNameInfo(user); } public int like(int id) { diff --git a/src/main/resources/mapper/user-mapper.xml b/src/main/resources/mapper/user-mapper.xml index 63d2c94..9260d8f 100644 --- a/src/main/resources/mapper/user-mapper.xml +++ b/src/main/resources/mapper/user-mapper.xml @@ -19,6 +19,13 @@ where id = #{id} + + + select from comment @@ -58,12 +64,6 @@ and root_id = #{RootId} - - - insert into comment() - values(#{content}, #{picUrls}, #{userId}, #{entityType}, #{entityId}, #{rootId}, #{targetId}, #{postId}, #{status}, #{createTime}) - - select @@ -40,12 +46,6 @@ where email = #{email} - - - insert into user () - values(#{username}, #{password}, #{salt}, #{email}, #{type}, #{status}, #{activationCode}, #{headerUrl}, #{createTime}) - - update user set status = #{status} where id = #{id} -- Gitee From 31b0e7a493bb042eca9446219dc84283c728fe19 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Thu, 24 Feb 2022 19:00:37 +0800 Subject: [PATCH 042/125] fix: cancel like --- src/main/java/com/greate/community/service/LikeService.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/greate/community/service/LikeService.java b/src/main/java/com/greate/community/service/LikeService.java index d04e8a2..7edf919 100644 --- a/src/main/java/com/greate/community/service/LikeService.java +++ b/src/main/java/com/greate/community/service/LikeService.java @@ -50,10 +50,8 @@ public class LikeService implements CommunityConstant { if (likeStatus == 1) { // 如果用户已经点过赞,点第二次则取消赞 int result = likeMapper.deleteLikeByUserIdAndEntity(userId, entityType, entityId); - if (result == 1) { - cancelLikeEntity(entityType, entityId, entityUserId); - redisTemplate.opsForSet().remove(userIdOfLikeKey, userId); // 删除实体对应的点赞 userId - } + cancelLikeEntity(entityType, entityId, entityUserId); + redisTemplate.opsForSet().remove(userIdOfLikeKey, userId); // 删除实体对应的点赞 userId } else { Like like = new Like(); like.setUserId(userId); -- Gitee From 63ae9a64e58e5e6de7c89f8655da0c076dcbf918 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Thu, 24 Feb 2022 21:14:51 +0800 Subject: [PATCH 043/125] add huster type --- src/main/java/com/greate/community/util/CommunityConstant.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/greate/community/util/CommunityConstant.java b/src/main/java/com/greate/community/util/CommunityConstant.java index ca1bdc8..96b760c 100644 --- a/src/main/java/com/greate/community/util/CommunityConstant.java +++ b/src/main/java/com/greate/community/util/CommunityConstant.java @@ -58,6 +58,9 @@ public interface CommunityConstant { // 权限:版主 String AUTHORITY_MODERATOR = "moderator"; + // 权限: 实名用户 + String AUTHORITY_HUSTER = "huster"; + // 对象存储类型:头像 String COS_TYPE_AVATAR = "avatar"; -- Gitee From 79f83728d7347d2b187bfb8de54a2d36ccb1abfe Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Thu, 24 Feb 2022 23:00:32 +0800 Subject: [PATCH 044/125] fix: comment or like myself don't send message --- .../controller/CommentController.java | 32 ++++++++++--------- .../community/controller/LikeController.java | 4 +-- .../controller/MessageController.java | 2 +- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/greate/community/controller/CommentController.java b/src/main/java/com/greate/community/controller/CommentController.java index f760df3..90dc27f 100644 --- a/src/main/java/com/greate/community/controller/CommentController.java +++ b/src/main/java/com/greate/community/controller/CommentController.java @@ -63,25 +63,27 @@ public class CommentController extends BaseController implements CommunityConsta comment.setCreateTime(new Date()); commentService.addComment(comment); - // 触发评论事件(系统通知) - Event event = new Event() - .setTopic(TOPIC_COMMNET) - .setUserId(getUser().getId()) - .setEntityType(comment.getEntityType()) - .setEntityId(comment.getEntityId()) - .setData("postId", comment.getPostId()); - if (comment.getEntityType() == ENTITY_TYPE_POST) { - DiscussPost target = discussPostService.findDiscussPostById(comment.getEntityId()); - event.setEntityUserId(target.getUserId()); - } else if (comment.getEntityType() == ENTITY_TYPE_COMMENT) { - Comment target = commentService.findCommentById(comment.getEntityId()); - event.setEntityUserId(target.getUserId()); + // 触发评论事件(系统通知) - 自己评论自己不通知 + if (comment.getTargetId() != comment.getUserId()) { + Event event = new Event() + .setTopic(TOPIC_COMMNET) + .setUserId(getUser().getId()) + .setEntityType(comment.getEntityType()) + .setEntityId(comment.getEntityId()) + .setData("postId", comment.getPostId()); + if (comment.getEntityType() == ENTITY_TYPE_POST) { + DiscussPost target = discussPostService.findDiscussPostById(comment.getEntityId()); + event.setEntityUserId(target.getUserId()); + } else if (comment.getEntityType() == ENTITY_TYPE_COMMENT) { + Comment target = commentService.findCommentById(comment.getEntityId()); + event.setEntityUserId(target.getUserId()); + } + eventProducer.fireEvent(event); } - eventProducer.fireEvent(event); if (comment.getEntityType() == ENTITY_TYPE_POST) { // 触发发帖事件,通过消息队列将其存入 Elasticsearch 服务器 - event = new Event() + Event event = new Event() .setTopic(TOPIC_PUBLISH) .setUserId(comment.getUserId()) .setEntityType(ENTITY_TYPE_POST) diff --git a/src/main/java/com/greate/community/controller/LikeController.java b/src/main/java/com/greate/community/controller/LikeController.java index f9cd96c..91bc38d 100644 --- a/src/main/java/com/greate/community/controller/LikeController.java +++ b/src/main/java/com/greate/community/controller/LikeController.java @@ -63,8 +63,8 @@ public class LikeController extends BaseController implements CommunityConstant map.put("likeCount", likeCount); map.put("likeStatus", likeStatus); - // 触发点赞事件(系统通知) - 取消点赞不通知 - if (likeStatus == 1) { + // 触发点赞事件(系统通知) - 取消点赞不通知、自己点赞自己不通知 + if (likeStatus == 1 && entityUserId != getUser().getId()) { Event event = new Event() .setTopic(TOPIC_LIKE) .setUserId(getUser().getId()) diff --git a/src/main/java/com/greate/community/controller/MessageController.java b/src/main/java/com/greate/community/controller/MessageController.java index de75dc4..4fb2d92 100644 --- a/src/main/java/com/greate/community/controller/MessageController.java +++ b/src/main/java/com/greate/community/controller/MessageController.java @@ -332,7 +332,7 @@ public class MessageController extends BaseController implements CommunityConsta map.put("post", discussPostService.findDiscussPostById((Integer) data.get("postId"))); Comment comment = commentService.findCommentById((Integer) data.get("entityId")); map.put("comment", comment); - if (comment.getEntityType() == ENTITY_TYPE_COMMENT) { // 回复 + if ((Integer) data.get("entityType") == ENTITY_TYPE_COMMENT) { // 回复 map.put("parent", commentService.findCommentById(comment.getEntityId())); } } -- Gitee From 98fb249a58a80d209e77bc754774cf3b1e4c732d Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Fri, 25 Feb 2022 10:28:56 +0800 Subject: [PATCH 045/125] add view count --- .../greate/community/controller/DataController.java | 8 -------- .../community/controller/DiscussPostController.java | 7 +++++++ .../community/controller/MessageController.java | 1 + .../com/greate/community/dao/DiscussPostMapper.java | 8 ++++++++ .../com/greate/community/entity/DiscussPost.java | 3 +++ .../community/service/DiscussPostService.java | 4 ++++ src/main/resources/mapper/discusspost-mapper.xml | 13 ++++++++++--- 7 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/greate/community/controller/DataController.java b/src/main/java/com/greate/community/controller/DataController.java index 1933142..1d7ae8f 100644 --- a/src/main/java/com/greate/community/controller/DataController.java +++ b/src/main/java/com/greate/community/controller/DataController.java @@ -40,16 +40,12 @@ public class DataController { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); long uv = dataService.calculateUV(format.parse(start), format.parse(end)); -// model.addAttribute("uvResult", uv); hashMap.put("uvResult", uv); -// model.addAttribute("uvStartDate", start); hashMap.put("uvStartDate", start); -// model.addAttribute("uvEndDate", end); hashMap.put("uvEndDate", end); -// return "forward:/data"; return new Result("success", Result.SUCCESS, hashMap); } @@ -67,16 +63,12 @@ public class DataController { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); long dau = dataService.calculateUV(format.parse(start), format.parse(end)); -// model.addAttribute("dauResult", dau); hashMap.put("dauResult", dau); -// model.addAttribute("dauStartDate", start); hashMap.put("dauStartDate", start); -// model.addAttribute("dauEndDate", end); hashMap.put("dauEndDate", end); -// return "forward:/data"; return new Result("success", Result.SUCCESS, hashMap); } diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index deea23b..15f9958 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -76,6 +76,7 @@ public class DiscussPostController extends BaseController implements CommunityCo discussPost.setTitle(title); discussPost.setContent(content); discussPost.setPicUrls(picUrls); + discussPost.setViewCount(0); discussPost.setLikeCount(0); discussPost.setCommentCount(0); discussPost.setCreateTime(new Date()); @@ -110,6 +111,9 @@ public class DiscussPostController extends BaseController implements CommunityCo // 帖子 DiscussPost discussPost = discussPostService.findDiscussPostById(discussPostId); + if (discussPost == null) { + return new Result("fail", "1", "没有找到帖子"); + } String content = HtmlUtils.htmlUnescape(discussPost.getContent()); // 内容反转义,不然 markDown 格式无法显示 discussPost.setContent(content); @@ -130,6 +134,9 @@ public class DiscussPostController extends BaseController implements CommunityCo expService.handleGetExp(getUser().getId(), ExpType.EXP_BROWSE.getName()); } + // 增加帖子浏览量 + discussPostService.viewPost(discussPost.getId()); + return new Result("success", Result.SUCCESS, resultMap); } diff --git a/src/main/java/com/greate/community/controller/MessageController.java b/src/main/java/com/greate/community/controller/MessageController.java index 4fb2d92..0b7e857 100644 --- a/src/main/java/com/greate/community/controller/MessageController.java +++ b/src/main/java/com/greate/community/controller/MessageController.java @@ -320,6 +320,7 @@ public class MessageController extends BaseController implements CommunityConsta for (Message notice : noticeList) { Map map = new HashMap<>(); // 通知 + notice.setStatus(1); // 设置已读 map.put("notice", notice); // 内容 String content = HtmlUtils.htmlUnescape(notice.getContent()); diff --git a/src/main/java/com/greate/community/dao/DiscussPostMapper.java b/src/main/java/com/greate/community/dao/DiscussPostMapper.java index 1f018a9..60d741a 100644 --- a/src/main/java/com/greate/community/dao/DiscussPostMapper.java +++ b/src/main/java/com/greate/community/dao/DiscussPostMapper.java @@ -82,4 +82,12 @@ public interface DiscussPostMapper { * @return */ int addLikeCount(int id, int likeCount); + + /** + * 增加浏览数 + * @param id + * @param viewCount + * @return + */ + int addViewCount(int id, int viewCount); } diff --git a/src/main/java/com/greate/community/entity/DiscussPost.java b/src/main/java/com/greate/community/entity/DiscussPost.java index 844e37e..0462984 100644 --- a/src/main/java/com/greate/community/entity/DiscussPost.java +++ b/src/main/java/com/greate/community/entity/DiscussPost.java @@ -41,6 +41,9 @@ public class DiscussPost { @Field(type = FieldType.Integer) private int status; + @Field(type = FieldType.Integer) + private int viewCount; + @Field(type = FieldType.Integer) private int likeCount; diff --git a/src/main/java/com/greate/community/service/DiscussPostService.java b/src/main/java/com/greate/community/service/DiscussPostService.java index c276897..3c5a3ec 100644 --- a/src/main/java/com/greate/community/service/DiscussPostService.java +++ b/src/main/java/com/greate/community/service/DiscussPostService.java @@ -242,4 +242,8 @@ public class DiscussPostService { public int cancelLike(int id) { return discussPostMapper.addLikeCount(id, -1); } + + public int viewPost(int id) { + return discussPostMapper.addViewCount(id,1); + } } diff --git a/src/main/resources/mapper/discusspost-mapper.xml b/src/main/resources/mapper/discusspost-mapper.xml index 74290ac..cfd904c 100644 --- a/src/main/resources/mapper/discusspost-mapper.xml +++ b/src/main/resources/mapper/discusspost-mapper.xml @@ -5,11 +5,11 @@ - id, user_id, title, content, pic_urls, type, status, like_count, comment_count, score, create_time + id, user_id, title, content, pic_urls, type, status, view_count, like_count, comment_count, score, create_time - user_id, title, content, pic_urls, type, status, like_count, comment_count, score, create_time + user_id, title, content, pic_urls, type, status, view_count, like_count, comment_count, score, create_time @@ -43,7 +43,7 @@ insert into discuss_post () - values(#{userId}, #{title}, #{content}, #{picUrls}, #{type}, #{status}, #{likeCount}, #{commentCount}, #{score}, #{createTime}) + values(#{userId}, #{title}, #{content}, #{picUrls}, #{type}, #{status}, #{viewCount}, #{likeCount}, #{commentCount}, #{score}, #{createTime}) @@ -87,4 +87,11 @@ where id = #{id} + + + update discuss_post + set view_count = view_count + #{viewCount} + where id = #{id} + + \ No newline at end of file -- Gitee From b2d652fd6eea3853613f5f7080b28582ec4c2421 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Fri, 25 Feb 2022 10:39:26 +0800 Subject: [PATCH 046/125] add delete comment --- .../community/controller/CommentController.java | 12 ++++++++++++ .../java/com/greate/community/dao/CommentMapper.java | 8 ++++++++ .../com/greate/community/service/CommentService.java | 10 ++++++++++ src/main/resources/mapper/comment-mapper.xml | 7 +++++++ 4 files changed, 37 insertions(+) diff --git a/src/main/java/com/greate/community/controller/CommentController.java b/src/main/java/com/greate/community/controller/CommentController.java index 90dc27f..7789914 100644 --- a/src/main/java/com/greate/community/controller/CommentController.java +++ b/src/main/java/com/greate/community/controller/CommentController.java @@ -154,4 +154,16 @@ public class CommentController extends BaseController implements CommunityConsta return new Result("success", Result.SUCCESS, page); } + + /** + * 删除帖子 + * + * @return + */ + @PostMapping("/delete") + public Result setDelete(@RequestBody HashMap map) { + int id = map.get("id"); + commentService.updateStatus(id, 2); + return new Result("success", Result.SUCCESS, "删除成功"); + } } diff --git a/src/main/java/com/greate/community/dao/CommentMapper.java b/src/main/java/com/greate/community/dao/CommentMapper.java index 0250732..ef89137 100644 --- a/src/main/java/com/greate/community/dao/CommentMapper.java +++ b/src/main/java/com/greate/community/dao/CommentMapper.java @@ -77,4 +77,12 @@ public interface CommentMapper { * @return */ int addLikeCount(int id, int likeCount); + + /** + * 修改评论状态:0-正常; 1-禁用; 2-删除; + * @param id + * @param status + * @return + */ + int updateStatus(int id, int status); } diff --git a/src/main/java/com/greate/community/service/CommentService.java b/src/main/java/com/greate/community/service/CommentService.java index 403f784..3856659 100644 --- a/src/main/java/com/greate/community/service/CommentService.java +++ b/src/main/java/com/greate/community/service/CommentService.java @@ -131,4 +131,14 @@ public class CommentService implements CommunityConstant { return commentMapper.addLikeCount(id, -1); } + /** + * 修改评论状态:0-正常; 1-禁用; 2-删除; + * + * @param id + * @param status + * @return + */ + public int updateStatus(int id, int status) { + return commentMapper.updateStatus(id, status); + } } diff --git a/src/main/resources/mapper/comment-mapper.xml b/src/main/resources/mapper/comment-mapper.xml index 060acd6..9d2f043 100644 --- a/src/main/resources/mapper/comment-mapper.xml +++ b/src/main/resources/mapper/comment-mapper.xml @@ -88,4 +88,11 @@ set like_count = like_count + #{likeCount} where id = #{id} + + + + update comment + set status = #{status} + where id = #{id} + \ No newline at end of file -- Gitee From f12c6ff5c0c72aefffb3accfd79b17210c913c56 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Fri, 25 Feb 2022 11:29:54 +0800 Subject: [PATCH 047/125] add test properties --- .../community/config/ElasticSearchConfig.java | 5 +- .../controller/SearchController.java | 1 - .../community/controller/UserController.java | 23 ----- .../resources/application-develop.properties | 11 +-- .../resources/application-test.properties | 91 +++++++++++++++++++ src/main/resources/application.properties | 2 +- 6 files changed, 98 insertions(+), 35 deletions(-) create mode 100644 src/main/resources/application-test.properties diff --git a/src/main/java/com/greate/community/config/ElasticSearchConfig.java b/src/main/java/com/greate/community/config/ElasticSearchConfig.java index 65f3f7c..7bf8ce5 100644 --- a/src/main/java/com/greate/community/config/ElasticSearchConfig.java +++ b/src/main/java/com/greate/community/config/ElasticSearchConfig.java @@ -38,6 +38,9 @@ public class ElasticSearchConfig { @Value("${elasticsearch.port}") private int port; + @Value("${elasticsearch.scheme}") + private String scheme; + @Bean public RestHighLevelClient restHighLevelClient() { @@ -46,7 +49,7 @@ public class ElasticSearchConfig { new UsernamePasswordCredentials(username, password)); RestClientBuilder builder = RestClient.builder( - new HttpHost(hostname, port, "https")) + new HttpHost(hostname, port, scheme)) .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() { @Override public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) { diff --git a/src/main/java/com/greate/community/controller/SearchController.java b/src/main/java/com/greate/community/controller/SearchController.java index 3188970..1c846a7 100644 --- a/src/main/java/com/greate/community/controller/SearchController.java +++ b/src/main/java/com/greate/community/controller/SearchController.java @@ -71,7 +71,6 @@ public class SearchController extends BaseController implements CommunityConstan page.setRows(searchResult == null ? 0 : (int) searchResult.getTotalElements()); jsonObject.put("keyword", keyword); -// jsonObject.put("discussPosts", discussPosts); JSONArray result = (JSONArray) JSONArray.toJSON(discussPosts); page.setResult(result); jsonObject.put("discussPosts", discussPosts); diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 45389df..083fc26 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -52,9 +52,6 @@ public class UserController extends BaseController implements CommunityConstant @Value("${server.servlet.context-path}") private String contextPath; - @Value("${qiniu.bucket.header.url}") - private String headerBucketUrl; - /** * 通过ticket获取user * @@ -90,26 +87,6 @@ public class UserController extends BaseController implements CommunityConstant return new Result("success", Result.SUCCESS, userService.findAllUserById(getUser().getId())); } - /** - * 更新图像路径(将本地的图像路径更新为云服务器上的图像路径) - * - * @param fileName - * @return - */ - @PostMapping("/header/url") - @ResponseBody - public String updateHeaderUrl(String fileName) { - if (StringUtils.isBlank(fileName)) { - return CommunityUtil.getJSONString(1, "文件名不能为空"); - } - - // 文件在云服务器上的的访问路径 - String url = headerBucketUrl + "/" + fileName; - userService.updateHeader(getUser().getId(), url); - - return CommunityUtil.getJSONString(0); - } - @PostMapping("/username") public Result updateUsername(@RequestBody String username) { if (StringUtils.isBlank(username)) { diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index 8ca5108..c2ef5d7 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -59,6 +59,7 @@ elasticsearch.username = elastic elasticsearch.password = elastic2021. elasticsearch.hostname = es-50b9cgrk.public.tencentelasticsearch.com elasticsearch.port = 9200 +elasticsearch.scheme = https # Quartz spring.quartz.job-store-type = jdbc @@ -70,13 +71,6 @@ spring.quartz.properties.org.quartz.jobStore.isClustered = true spring.quartz.properties.org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool spring.quartz.properties.org.quartz.threadPool.threadCount = 5 - -# qiniu -qiniu.key.access = 6NWps_pOPyTISxhI_xzPrjTzB2OscLcCwi5MobhS -qiniu.key.secret = Htl8C-_oHhy_FUjirGEdDo0ztDeAI_WXoBfDqfpi -qiniu.bucket.header.name = header--community -qiniu.bucket.header.url = http://qnvxyvq1p.hd-bkt.clouddn.com - # tencent cos tencent.secretId = AKID1rR2RcXCcmgMo1yf7LK34uUosgEXaPyI tencent.secretKey = 5uUnpb8OO9gxyjEVVFjywd3EApDLCm6B @@ -85,8 +79,7 @@ tencent.secretKey = 5uUnpb8OO9gxyjEVVFjywd3EApDLCm6B caffeine.posts.max-size = 15 caffeine.posts.expire-seconds = 180 - -# OAuth2 ΢ŵ¼ +# OAuth2 wechat.client.clientId = wxa75d140e71f8903e wechat.client.clientSecret = 2e6dbcad650a9fa495a762c0eb28906a wechat.client.accessTokenUri = https://api.weixin.qq.com/sns/oauth2/access_token diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties new file mode 100644 index 0000000..fd13847 --- /dev/null +++ b/src/main/resources/application-test.properties @@ -0,0 +1,91 @@ +bbs.captcha-enable = false + +server.port = 8080 +server.servlet.context-path = + +community.path.domain = http://localhost:8080 + +community.path.editormdUploadPath = E:/GreateCommunity/src/main/resources/static/editor-md-upload + +# Thymeleaf +spring.thymeleaf.cache=false + +# MySQL +spring.datasource.url = jdbc:mysql://172.16.0.4:3306/bbs-dev?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong +spring.datasource.username = root +spring.datasource.password = Root@2021 +spring.datasource.driver-class-name = com.mysql.jdbc.Driver + +# Mybatis +mybatis.mapper-locations = classpath:mapper/*.xml +mybatis.type-aliases-package = com.greate.community.entity +mybatis.configuration.useGeneratedKeys = true +mybatis.configuration.mapUnderscoreToCamelCase = true + +# Spring Mail +spring.mail.host = smtp.qq.com +spring.mail.username = xuetao1999@vip.qq.com +spring.mail.personal = HUSTer +spring.mail.password = ttgqzosyzyjmdhja +spring.mail.protocol = smtps +spring.mail.properties.mail.smtp.ssl.enable = true +spring.mail.code-expiration=3600000 +spring.mail.reg-header=Register +spring.mail.forget-password-header=Register + +# Redis +spring.redis.database = 10 +spring.redis.host = 10.66.17.52 +spring.redis.port = 6379 +spring.redis.password = root2021 + +# Kafka +spring.kafka.bootstrap-servers = localhost:9092 +spring.kafka.consumer.group-id = test-consumer-group +spring.kafka.consumer.enable-auto-commit = true +spring.kafka.consumer.auto-commit-interval = 3000 + +# Elasticsearch +elasticsearch.username = elastic +elasticsearch.password = elastic2021. +elasticsearch.hostname = 172.16.0.8 +elasticsearch.port = 9200 +elasticsearch.scheme = http + +# Quartz +spring.quartz.job-store-type = jdbc +spring.quartz.scheduler-name = communityScheduler +spring.quartz.properties.org.quartz.scheduler.instanceId = AUTO +spring.quartz.properties.org.quartz.jobStore.class = org.springframework.scheduling.quartz.LocalDataSourceJobStore +spring.quartz.properties.org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate +spring.quartz.properties.org.quartz.jobStore.isClustered = true +spring.quartz.properties.org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool +spring.quartz.properties.org.quartz.threadPool.threadCount = 5 + +# tencent cos +tencent.secretId = AKID1rR2RcXCcmgMo1yf7LK34uUosgEXaPyI +tencent.secretKey = 5uUnpb8OO9gxyjEVVFjywd3EApDLCm6B + +# Caffeine +caffeine.posts.max-size = 15 +caffeine.posts.expire-seconds = 180 + +# OAuth2 ΢ŵ¼ +wechat.client.clientId = wxa75d140e71f8903e +wechat.client.clientSecret = 2e6dbcad650a9fa495a762c0eb28906a +wechat.client.accessTokenUri = https://api.weixin.qq.com/sns/oauth2/access_token +wechat.client.userAuthorizationUri = https://open.weixin.qq.com/connect/oauth2/authorize +wechat.client.tokenName = access_token +wechat.client.authenticationScheme = query +wechat.client.clientAuthenticationScheme = form +wechat.client.scope = snsapi_userinfo +wechat.resource.userInfoUri = https://api.weixin.qq.com/sns/userinfo +wechat.config.app-id = appid +wechat.config.client-id = client_id +wechat.config.secret = secret +wechat.config.client-secret = client_secret +wechat.config.state = state +wechat.config.wechat-redirect = wechat_redirect + +logging.level.com.greate = debug +logging.level.org.springframework.security = DEBUG \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 6501fe3..6c4036e 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,5 @@ # profile(ʱ develop, ߲ʱǵøij produce) -spring.profiles.active = develop +spring.profiles.active = test # logback logging.path=classpath:logback-spring-${spring.profiles.active}.xml \ No newline at end of file -- Gitee From e0ad84e0e8b1d39bb146e04fd265a5456799f0c8 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Fri, 25 Feb 2022 11:35:45 +0800 Subject: [PATCH 048/125] fix: properties --- src/main/resources/application-test.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties index fd13847..bfa9d8b 100644 --- a/src/main/resources/application-test.properties +++ b/src/main/resources/application-test.properties @@ -35,7 +35,7 @@ spring.mail.forget-password-header=Register # Redis spring.redis.database = 10 -spring.redis.host = 10.66.17.52 +spring.redis.host = 172.16.0.10 spring.redis.port = 6379 spring.redis.password = root2021 -- Gitee From 3918d60a68efe3ff93638a4b476f0dff1d9f7cb1 Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Sat, 26 Feb 2022 16:02:29 +0800 Subject: [PATCH 049/125] =?UTF-8?q?=E4=B8=80=E9=94=AE=E6=B6=88=E9=99=A4?= =?UTF-8?q?=E6=9C=AA=E8=AF=BB=E6=B6=88=E6=81=AF=E6=8E=A5=E5=8F=A3-?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0huster=E5=AE=9E=E5=90=8D=E8=BA=AB=E4=BB=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/config/SecurityConfig.java | 3 +- .../controller/MessageController.java | 29 +- .../greate/community/dao/MessageMapper.java | 216 ++++++------- .../com/greate/community/dao/UserMapper.java | 3 +- .../community/service/MessageService.java | 11 + .../greate/community/service/UserService.java | 5 +- src/main/resources/application.properties | 4 +- src/main/resources/mapper/message-mapper.xml | 285 +++++++++--------- src/main/resources/mapper/user-mapper.xml | 8 +- 9 files changed, 314 insertions(+), 250 deletions(-) diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index 7fcd3ab..eed4722 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -83,7 +83,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm "/follow", "/unfollow", "/exp/**", - "/cos/credential" + "/cos/credential", + "/message/unread" ) .hasAnyAuthority( AUTHORITY_USER, diff --git a/src/main/java/com/greate/community/controller/MessageController.java b/src/main/java/com/greate/community/controller/MessageController.java index 0b7e857..25191b2 100644 --- a/src/main/java/com/greate/community/controller/MessageController.java +++ b/src/main/java/com/greate/community/controller/MessageController.java @@ -39,9 +39,21 @@ public class MessageController extends BaseController implements CommunityConsta // 查询当前用户的所有未读私信数量 int letterUnreadCount = messageService.findLetterUnreadCount(getUser().getId(), null); result.put("letterUnreadCount", letterUnreadCount); + // 查询当前用户的所有未读系统通知数量 - int noticeUnreadCount = messageService.findNoticeUnReadCount(getUser().getId(), null); - result.put("noticeUnreadCount", noticeUnreadCount); + // int noticeUnreadCount = messageService.findNoticeUnReadCount(getUser().getId(), null); + // result.put("noticeUnreadCount", noticeUnreadCount); + + //评论 系统通知未读数量 + int commentNoticeUnreadCount = messageService.findNoticeUnReadCount(getUser().getId(), TOPIC_COMMNET); + result.put("commentNoticeUnreadCount", commentNoticeUnreadCount); + //点赞 系统通知未读数量 + int likeNoticeUnreadCount = messageService.findNoticeUnReadCount(getUser().getId(), TOPIC_LIKE); + result.put("likeNoticeUnreadCount", likeNoticeUnreadCount); + //关注 系统通知未读数量 + int followNoticeUnreadCount = messageService.findNoticeUnReadCount(getUser().getId(), TOPIC_FOLLOW); + result.put("followNoticeUnreadCount", followNoticeUnreadCount); + return new Result("success", Result.SUCCESS, result); } @@ -364,4 +376,17 @@ public class MessageController extends BaseController implements CommunityConsta // return new Result("success", Result.SUCCESS, noticeVoList); return new Result("success", Result.SUCCESS, page); } + + /** + * 所有未读消息设为已读 + * + * @return + */ + @GetMapping("/message/allread") + public Result allreadMessage() { + int userId = getUser().getId(); + messageService.readAllConversationId(userId, null); + + return new Result("success", Result.SUCCESS, "未读消息全部已读"); + } } diff --git a/src/main/java/com/greate/community/dao/MessageMapper.java b/src/main/java/com/greate/community/dao/MessageMapper.java index 01b0dcc..b52fd72 100644 --- a/src/main/java/com/greate/community/dao/MessageMapper.java +++ b/src/main/java/com/greate/community/dao/MessageMapper.java @@ -1,104 +1,112 @@ -package com.greate.community.dao; - -import com.greate.community.entity.Message; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -@Mapper -public interface MessageMapper { - - /** - * 查询当前用户的会话列表,针对每个会话只返回一条最新的私信 - * @param userId 用户 id - * @param offset 每页的起始索引 - * @param limit 每页显示多少条数据 - * @return - */ - List selectConversations(int userId, int offset, int limit); - - /** - * 查询当前用户的会话数量 - * @param userId - * @return - */ - int selectConversationCount(int userId); - - /** - * 查询某个会话所包含的私信列表 - * @param conversationId - * @param offset - * @param limit - * @return - */ - List selectLetters(String conversationId, int offset, int limit); - - /** - * 查询某个会话所包含的私信数量 - * @param conversationId - * @return - */ - int selectLetterCount(String conversationId); - - /** - * 查询未读私信的数量 - * @param userId - * @param conversationId conversationId = null, 则查询该用户所有会话的未读私信数量 - * conversationId != null, 则查询该用户某个会话的未读私信数量 - * @return - */ - int selectLetterUnreadCount(int userId, String conversationId); - - /** - * 修改消息的状态 - * @param ids - * @param status - * @return - */ - int updateStatus(List ids, int status); - - /** - * 新增一条私信 - * @param message - * @return - */ - int insertMessage(Message message); - - /** - * 查询某个主题下最新的通知 - * @param userId - * @param topic - * @return - */ - Message selectLatestNotice(int userId, String topic); - - /** - * 查询某个主题下包含的系统通知数量 - * @param userId - * @param topic - * @return - */ - int selectNoticeCount(int userId, String topic); - - /** - * 查询未读的系统通知数量 - * @param userId - * @param topic - * @return - */ - int selectNoticeUnReadCount(int userId, String topic); - - /** - * 查询某个主题所包含的通知列表 - * @param userId - * @param topic - * @param offset - * @param limit - * @return - */ - List selectNotices(int userId, String topic, int offset, int limit); - - - -} - +package com.greate.community.dao; + +import com.greate.community.entity.Message; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface MessageMapper { + + /** + * 查询当前用户的会话列表,针对每个会话只返回一条最新的私信 + * @param userId 用户 id + * @param offset 每页的起始索引 + * @param limit 每页显示多少条数据 + * @return + */ + List selectConversations(int userId, int offset, int limit); + + /** + * 查询当前用户的会话数量 + * @param userId + * @return + */ + int selectConversationCount(int userId); + + /** + * 查询某个会话所包含的私信列表 + * @param conversationId + * @param offset + * @param limit + * @return + */ + List selectLetters(String conversationId, int offset, int limit); + + /** + * 查询某个会话所包含的私信数量 + * @param conversationId + * @return + */ + int selectLetterCount(String conversationId); + + /** + * 查询未读私信的数量 + * @param userId + * @param conversationId conversationId = null, 则查询该用户所有会话的未读私信数量 + * conversationId != null, 则查询该用户某个会话的未读私信数量 + * @return + */ + int selectLetterUnreadCount(int userId, String conversationId); + + /** + * 修改消息的状态 + * @param ids + * @param status + * @return + */ + int updateStatus(List ids, int status); + + /** + * 新增一条私信 + * @param message + * @return + */ + int insertMessage(Message message); + + /** + * 查询某个主题下最新的通知 + * @param userId + * @param topic + * @return + */ + Message selectLatestNotice(int userId, String topic); + + /** + * 查询某个主题下包含的系统通知数量 + * @param userId + * @param topic + * @return + */ + int selectNoticeCount(int userId, String topic); + + /** + * 查询未读的系统通知数量 + * @param userId + * @param topic + * @return + */ + int selectNoticeUnReadCount(int userId, String topic); + + /** + * 查询某个主题所包含的通知列表 + * @param userId + * @param topic + * @param offset + * @param limit + * @return + */ + List selectNotices(int userId, String topic, int offset, int limit); + + /** + * 消除所有未读私信 + * @param userId + * @param conversationId conversationId = null, 将该用户 所有 会话的未读消息状态设置为已读 + * conversationId != null, 将该用户 某个 会话的未读消息状态设置为已读 + * @return + */ + int updateStatusAll(int userId, String conversationId); + + +} + diff --git a/src/main/java/com/greate/community/dao/UserMapper.java b/src/main/java/com/greate/community/dao/UserMapper.java index 7cfb2a3..bac50eb 100644 --- a/src/main/java/com/greate/community/dao/UserMapper.java +++ b/src/main/java/com/greate/community/dao/UserMapper.java @@ -60,7 +60,8 @@ public interface UserMapper { int updateExpAndLevel(int id, int exp, int level); /** - * 修改用户实名信息审核状态 + * 修改用户实名信息审核状态, + * 当审核通过时,同时修改用户身份为实名用户huster */ int updateAuditStatus(int id, int auditStatus); diff --git a/src/main/java/com/greate/community/service/MessageService.java b/src/main/java/com/greate/community/service/MessageService.java index af27519..78acb28 100644 --- a/src/main/java/com/greate/community/service/MessageService.java +++ b/src/main/java/com/greate/community/service/MessageService.java @@ -136,4 +136,15 @@ public class MessageService { return messageMapper.selectNotices(userId, topic, offset, limit); } + /** + * 消除所有未读私信 + * @param userId + * @param conversationId conversationId = null, 将该用户 所有 会话的未读消息状态设置为已读 + * conversationId != null, 将该用户 某个 会话的未读消息状态设置为已读 + * @return + */ + public int readAllConversationId(int userId, String conversationId){ + return messageMapper.updateStatusAll(userId, conversationId); + } + } diff --git a/src/main/java/com/greate/community/service/UserService.java b/src/main/java/com/greate/community/service/UserService.java index fadd1b7..9c61bb9 100644 --- a/src/main/java/com/greate/community/service/UserService.java +++ b/src/main/java/com/greate/community/service/UserService.java @@ -334,6 +334,8 @@ public class UserService implements CommunityConstant { return AUTHORITY_ADMIN; case 2: return AUTHORITY_MODERATOR; + case 3: + return AUTHORITY_HUSTER; default: return AUTHORITY_USER; } @@ -399,7 +401,8 @@ public class UserService implements CommunityConstant { } /** - * 修改用户实名信息审核状态,保存用户实名信息 + * 修改用户实名信息审核状态,保存用户实名信息, + * 当审核通过时,同时修改用户身份为实名用户huster * * @param userId * @param auditStatus diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 6c4036e..afd699a 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,5 @@ # profile(ʱ develop, ߲ʱǵøij produce) -spring.profiles.active = test +spring.profiles.active = develop # logback -logging.path=classpath:logback-spring-${spring.profiles.active}.xml \ No newline at end of file +logging.path = classpath:logback-spring-${spring.profiles.active}.xml \ No newline at end of file diff --git a/src/main/resources/mapper/message-mapper.xml b/src/main/resources/mapper/message-mapper.xml index 4167ac9..345d2b2 100644 --- a/src/main/resources/mapper/message-mapper.xml +++ b/src/main/resources/mapper/message-mapper.xml @@ -1,138 +1,149 @@ - - - - - - id, from_id, to_id, conversation_id, content, status, create_time - - - - from_id, to_id, conversation_id, content, status, create_time - - - - - - - - - - - - - - - - - - - - update message - set status = #{status} - where id in - - #{id} - - - - - - insert into message() - values(#{fromId}, #{toId}, #{conversationId}, #{content}, #{status}, #{createTime}) - - - - - - - - - - - - - - + + + + + + id, from_id, to_id, conversation_id, content, status, create_time + + + + from_id, to_id, conversation_id, content, status, create_time + + + + + + + + + + + + + + + + + + + + update message + set status = #{status} + where id in + + #{id} + + + + + + insert into message() + values(#{fromId}, #{toId}, #{conversationId}, #{content}, #{status}, #{createTime}) + + + + + + + + + + + + + + + + + update message + set status = 1 + where to_id = #{userId} + and status = 0 + + and conversation_id = #{conversationId} + + + \ No newline at end of file diff --git a/src/main/resources/mapper/user-mapper.xml b/src/main/resources/mapper/user-mapper.xml index b5cb194..b358275 100644 --- a/src/main/resources/mapper/user-mapper.xml +++ b/src/main/resources/mapper/user-mapper.xml @@ -71,9 +71,13 @@ update user set exp = #{exp}, level = #{level} where id = #{id} - + - update user set audit_status = #{auditStatus} where id = #{id} + update user set audit_status = #{auditStatus} + + , type = 3 + + where id = #{id} -- Gitee From 742ae2c3a07f402ed0146fcac0ae1d5b71c82b69 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Sat, 26 Feb 2022 23:07:59 +0800 Subject: [PATCH 050/125] update table comment --- pom.xml | 29 ++++----- .../controller/CommentController.java | 60 +++++++++---------- .../community/controller/ExpController.java | 4 +- .../controller/MessageController.java | 22 +++---- .../community/controller/UserController.java | 27 ++++----- .../greate/community/dao/CommentMapper.java | 14 ++--- .../community/dao/DiscussPostMapper.java | 4 +- .../com/greate/community/entity/Comment.java | 8 +-- .../com/greate/community/entity/Event.java | 2 +- .../community/service/CommentService.java | 30 +++++----- .../community/service/DiscussPostService.java | 6 +- .../service/ElasticsearchService.java | 9 +++ .../resources/application-develop.properties | 6 +- .../resources/application-produce.properties | 4 +- src/main/resources/application.properties | 2 +- src/main/resources/mapper/comment-mapper.xml | 22 +++---- .../resources/mapper/discusspost-mapper.xml | 4 +- .../greate/community/ElasticsearchTest.java | 6 +- 18 files changed, 128 insertions(+), 131 deletions(-) diff --git a/pom.xml b/pom.xml index eca76dc..2c9e449 100644 --- a/pom.xml +++ b/pom.xml @@ -31,10 +31,10 @@ - - - - + + + + @@ -105,14 +105,14 @@ - - - - + + + + org.springframework.data spring-data-elasticsearch - 4.2.1 + 4.3.1 @@ -138,7 +138,7 @@ com.alibaba fastjson - 1.2.58 + 1.2.79 @@ -147,13 +147,6 @@ spring-boot-starter-quartz - - - com.qiniu - qiniu-java-sdk - 7.2.23 - - com.qcloud cos-sts_api @@ -197,6 +190,7 @@ org.springframework.boot spring-boot-maven-plugin + 2.3.4.RELEASE @@ -209,6 +203,7 @@ org.apache.maven.plugins maven-surefire-plugin + 2.22.2 true diff --git a/src/main/java/com/greate/community/controller/CommentController.java b/src/main/java/com/greate/community/controller/CommentController.java index 7789914..64907eb 100644 --- a/src/main/java/com/greate/community/controller/CommentController.java +++ b/src/main/java/com/greate/community/controller/CommentController.java @@ -49,13 +49,10 @@ public class CommentController extends BaseController implements CommunityConsta comment.setContent((String) map.get("content")); comment.setPicUrls(StringListConvertor.join((List) map.get("picUrls"))); - comment.setEntityType((Integer) map.get("entityType")); - comment.setEntityId((Integer) map.get("entityId")); - if ((comment.getEntityType() == ENTITY_TYPE_COMMENT)) { - comment.setRootId((Integer) map.get("rootId")); - } + comment.setParentId((Integer) map.get("parentId")); + comment.setRootId((Integer) map.get("rootId")); comment.setPostId((Integer) map.get("postId")); - comment.setTargetId((Integer) map.get("targetId")); + comment.setParentUserId((Integer) map.get("parentUserId")); comment.setUserId(getUser().getId()); comment.setLikeCount(0); @@ -64,36 +61,35 @@ public class CommentController extends BaseController implements CommunityConsta commentService.addComment(comment); // 触发评论事件(系统通知) - 自己评论自己不通知 - if (comment.getTargetId() != comment.getUserId()) { + if (comment.getParentUserId() != comment.getUserId()) { Event event = new Event() .setTopic(TOPIC_COMMNET) .setUserId(getUser().getId()) - .setEntityType(comment.getEntityType()) - .setEntityId(comment.getEntityId()) - .setData("postId", comment.getPostId()); - if (comment.getEntityType() == ENTITY_TYPE_POST) { - DiscussPost target = discussPostService.findDiscussPostById(comment.getEntityId()); - event.setEntityUserId(target.getUserId()); - } else if (comment.getEntityType() == ENTITY_TYPE_COMMENT) { - Comment target = commentService.findCommentById(comment.getEntityId()); - event.setEntityUserId(target.getUserId()); + .setEntityId(comment.getParentId()) + .setEntityUserId(comment.getParentUserId()) // 发送给谁 + .setData("postId", comment.getPostId()) + .setData("commentId", comment.getId()); + if (comment.getParentId() == 0) { + event.setEntityType(ENTITY_TYPE_POST); + } else { + event.setEntityType(ENTITY_TYPE_COMMENT); } eventProducer.fireEvent(event); } - if (comment.getEntityType() == ENTITY_TYPE_POST) { - // 触发发帖事件,通过消息队列将其存入 Elasticsearch 服务器 - Event event = new Event() - .setTopic(TOPIC_PUBLISH) - .setUserId(comment.getUserId()) - .setEntityType(ENTITY_TYPE_POST) - .setEntityId(comment.getPostId()); - eventProducer.fireEvent(event); - - // 计算帖子分数 - String redisKey = RedisKeyUtil.getPostScoreKey(); - redisTemplate.opsForSet().add(redisKey, comment.getPostId()); - } +// if (comment.getRootId() == 0) { +// // 触发发帖事件,通过消息队列将其存入 Elasticsearch 服务器 +// Event event = new Event() +// .setTopic(TOPIC_PUBLISH) +// .setUserId(comment.getUserId()) +// .setEntityType(ENTITY_TYPE_POST) +// .setEntityId(comment.getPostId()); +// eventProducer.fireEvent(event); +// +// // 计算帖子分数 +// String redisKey = RedisKeyUtil.getPostScoreKey(); +// redisTemplate.opsForSet().add(redisKey, comment.getPostId()); +// } return new Result("success", Result.SUCCESS, "评论成功"); } @@ -106,8 +102,8 @@ public class CommentController extends BaseController implements CommunityConsta page.setPath("/comment/get/" + discussPostId); // 帖子的评论列表 - List commentList = commentService.findCommentByEntity( - ENTITY_TYPE_POST, discussPostId, page.getOffset(), page.getLimit()); + List commentList = commentService.findCommentByPost( + discussPostId, page.getOffset(), page.getLimit()); // 封装评论及其相关信息 List> commentVoList = new ArrayList<>(); @@ -130,8 +126,6 @@ public class CommentController extends BaseController implements CommunityConsta Map replyVo = new HashMap<>(); replyVo.put("reply", StringListConvertor.toJsonObject(reply, "picUrls")); // 回复 replyVo.put("user", userService.findUserById(reply.getUserId())); // 发布该回复的作者 - User target = reply.getTargetId() == 0 ? null : userService.findUserById(reply.getTargetId()); - replyVo.put("target", target); // 该回复的目标用户 likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( getUser().getId(), ENTITY_TYPE_COMMENT, reply.getId()); replyVo.put("likeStatus", likeStatus); // 当前登录用户的点赞状态 diff --git a/src/main/java/com/greate/community/controller/ExpController.java b/src/main/java/com/greate/community/controller/ExpController.java index 63fc3be..a45cff4 100644 --- a/src/main/java/com/greate/community/controller/ExpController.java +++ b/src/main/java/com/greate/community/controller/ExpController.java @@ -1,11 +1,9 @@ package com.greate.community.controller; import com.alibaba.fastjson.JSONArray; -import com.google.gson.JsonObject; import com.greate.community.entity.Exp; import com.greate.community.entity.Page; import com.greate.community.entity.Result; -import com.greate.community.entity.User; import com.greate.community.service.ExpService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; @@ -31,7 +29,7 @@ public class ExpController extends BaseController { @PostMapping("/exp/page") public Result getPageOfExpLog(@RequestBody Page page) { // return new Result("success", Result.SUCCESS, expService.getExpPageByUserId(getUser().getId(), page.getOffset(), page.getLimit())); -// + List expList = expService.getExpPageByUserId(getUser().getId(), page.getOffset(), page.getLimit()); JSONArray result = (JSONArray) JSONArray.toJSON(expList); page.setResult(result); diff --git a/src/main/java/com/greate/community/controller/MessageController.java b/src/main/java/com/greate/community/controller/MessageController.java index 0b7e857..5c0ad26 100644 --- a/src/main/java/com/greate/community/controller/MessageController.java +++ b/src/main/java/com/greate/community/controller/MessageController.java @@ -315,6 +315,13 @@ public class MessageController extends BaseController implements CommunityConsta // 查询某个主题所包含的通知列表 List noticeList = messageService.findNotices(user.getId(), topic, page.getOffset(), page.getLimit()); + + // 设置已读 + List ids = getUnreadLetterIds(noticeList); + if (!ids.isEmpty()) { + messageService.readMessage(ids); + } + List> noticeVoList = new ArrayList<>(); if (noticeList != null) { for (Message notice : noticeList) { @@ -331,10 +338,10 @@ public class MessageController extends BaseController implements CommunityConsta // 若为评论或者回复的消息 if (Objects.equals(notice.getConversationId(), TOPIC_COMMNET)) { map.put("post", discussPostService.findDiscussPostById((Integer) data.get("postId"))); - Comment comment = commentService.findCommentById((Integer) data.get("entityId")); + Comment comment = commentService.findCommentById((Integer) data.get("commentId")); map.put("comment", comment); if ((Integer) data.get("entityType") == ENTITY_TYPE_COMMENT) { // 回复 - map.put("parent", commentService.findCommentById(comment.getEntityId())); + map.put("parent", commentService.findCommentById((Integer) data.get("entityId"))); } } if (Objects.equals(notice.getConversationId(), TOPIC_LIKE)) { @@ -346,7 +353,9 @@ public class MessageController extends BaseController implements CommunityConsta } // 发送系统通知的作者 - map.put("fromUser", userService.findUserById(notice.getFromId())); + if (notice.getFromId() != SYSTEM_USER_ID) { + map.put("fromUser", userService.findUserById(notice.getFromId())); + } noticeVoList.add(map); } @@ -355,13 +364,6 @@ public class MessageController extends BaseController implements CommunityConsta JSONArray result = (JSONArray) JSONArray.toJSON(noticeVoList); page.setResult(result); - // 设置已读 - List ids = getUnreadLetterIds(noticeList); - if (!ids.isEmpty()) { - messageService.readMessage(ids); - } - -// return new Result("success", Result.SUCCESS, noticeVoList); return new Result("success", Result.SUCCESS, page); } } diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 083fc26..2296e89 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -6,15 +6,11 @@ import com.greate.community.entity.*; import com.greate.community.service.*; import com.greate.community.util.CommunityConstant; import com.greate.community.util.CommunityUtil; -import com.qiniu.util.Auth; -import com.qiniu.util.Json; -import com.qiniu.util.StringMap; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import java.util.*; @@ -241,22 +237,21 @@ public class UserController extends BaseController implements CommunityConstant Map map = new HashMap<>(); // 显示评论/回复对应的文章信息 map.put("comment", comment); - if (comment.getEntityType() == ENTITY_TYPE_POST) { - // 如果是对帖子的评论,则直接查询 target_id 即可 - DiscussPost post = discussPostService.findDiscussPostById(comment.getEntityId()); - //map.put("post", post); + if (comment.getRootId() == 0) { + // 如果是对帖子的评论 + DiscussPost post = discussPostService.findDiscussPostById(comment.getPostId()); //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 map.put("post", discussPostService.toDiscussPostJsonObject(post)); - } else if (comment.getEntityType() == ENTITY_TYPE_COMMENT) { + } else { JSONObject parent = new JSONObject(); - // 如过是对评论的回复,则先根据该回复的 target_id 查询评论的 id, 再根据该评论的 target_id 查询帖子的 id - Comment targetComment = commentService.findCommentById(comment.getEntityId()); - parent.put("comment", targetComment); - User parentUser = userService.findUserById(targetComment.getUserId()); + // 如过是对评论的回复 + Comment parentComment = commentService.findCommentById(comment.getParentId()); + parent.put("comment", parentComment); + User parentUser = userService.findUserById(parentComment.getParentUserId()); parent.put("user", parentUser); map.put("parent", parent); - DiscussPost post = discussPostService.findDiscussPostById(targetComment.getEntityId()); - //map.put("post", post); + + DiscussPost post = discussPostService.findDiscussPostById(comment.getPostId()); //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 map.put("post", discussPostService.toDiscussPostJsonObject(post)); } @@ -264,7 +259,7 @@ public class UserController extends BaseController implements CommunityConstant comments.add(map); } } -// jsonObject.put("comments", comments); + JSONArray result = (JSONArray) JSONArray.toJSON(comments); page.setResult(result); jsonObject.put("comments", page); diff --git a/src/main/java/com/greate/community/dao/CommentMapper.java b/src/main/java/com/greate/community/dao/CommentMapper.java index ef89137..eb970a2 100644 --- a/src/main/java/com/greate/community/dao/CommentMapper.java +++ b/src/main/java/com/greate/community/dao/CommentMapper.java @@ -17,13 +17,12 @@ public interface CommentMapper { /** * 根据评论目标(类别、id)对评论进行分页查询 - * @param entityType 评论目标的类别 - * @param entityId 评论目标的 id + * @param postId 帖子 id * @param offset 每页的起始索引 * @param limit 每页显示多少条数据 * @return */ - List selectCommentByEntity(int entityType, int entityId, int offset, int limit); + List selectCommentByPostId(int postId, int offset, int limit); /** * 根据根评论对回复进行分页查询 @@ -35,15 +34,14 @@ public interface CommentMapper { List selectCommentByRootId(int rootId, int offset, int limit); /** - * 查询评论的数量 - * @param entityType - * @param entityId + * 查询帖子下评论、回复的数量 + * @param postId * @return */ - int selectCountByEntity(int entityType, int entityId); + int selectCountByPostId(int postId); /** - * 查询回复的数量 + * 查询某个评论回复的数量 * @param rootId * @return */ diff --git a/src/main/java/com/greate/community/dao/DiscussPostMapper.java b/src/main/java/com/greate/community/dao/DiscussPostMapper.java index 60d741a..cfe1506 100644 --- a/src/main/java/com/greate/community/dao/DiscussPostMapper.java +++ b/src/main/java/com/greate/community/dao/DiscussPostMapper.java @@ -46,10 +46,10 @@ public interface DiscussPostMapper { /** * 修改评论数量 * @param id - * @param commentCount + * @param addCount * @return */ - int updateCommentCount(int id, int commentCount); + int addCommentCount(int id, int addCount); /** * 修改帖子类型:0-普通; 1-置顶; diff --git a/src/main/java/com/greate/community/entity/Comment.java b/src/main/java/com/greate/community/entity/Comment.java index 7dfaf10..c6703a6 100644 --- a/src/main/java/com/greate/community/entity/Comment.java +++ b/src/main/java/com/greate/community/entity/Comment.java @@ -19,14 +19,12 @@ public class Comment { private String picUrls; // 发布评论的作者 private int userId; - // 评论目标的类型(帖子、评论) - private int entityType; // 回复的根评论 id private int rootId; - // 评论目标的 id - private int entityId; + // 评论父 id + private int parentId; // 指明对哪个用户进行评论(用户 id) - private int targetId; + private int parentUserId; // 帖子 id private int postId; // 点赞数 diff --git a/src/main/java/com/greate/community/entity/Event.java b/src/main/java/com/greate/community/entity/Event.java index 656147f..02b8c65 100644 --- a/src/main/java/com/greate/community/entity/Event.java +++ b/src/main/java/com/greate/community/entity/Event.java @@ -12,7 +12,7 @@ public class Event { private int userId; // 事件由谁触发 private int entityType; // 实体类型 private int entityId; // 实体 id - private int entityUserId; // 实体的作者(该通知发送给他) + private int entityUserId; // 通知发送给谁 private Map data = new HashMap<>(); // 存储未来可能需要用到的数据 public String getTopic() { diff --git a/src/main/java/com/greate/community/service/CommentService.java b/src/main/java/com/greate/community/service/CommentService.java index 3856659..a48e0af 100644 --- a/src/main/java/com/greate/community/service/CommentService.java +++ b/src/main/java/com/greate/community/service/CommentService.java @@ -33,6 +33,7 @@ public class CommentService implements CommunityConstant { /** * 根据 id 查询评论 + * * @param id * @return */ @@ -41,15 +42,15 @@ public class CommentService implements CommunityConstant { } /** - * 根据评论目标(类别、id)对评论进行分页查询 - * @param entityType - * @param entityId + * 根据 帖子id 对评论进行分页查询 + * + * @param postId * @param offset * @param limit * @return */ - public List findCommentByEntity(int entityType, int entityId, int offset, int limit) { - return commentMapper.selectCommentByEntity(entityType, entityId, offset, limit); + public List findCommentByPost(int postId, int offset, int limit) { + return commentMapper.selectCommentByPostId(postId, offset, limit); } public List findReplyByComment(int rootId, int offset, int limit) { @@ -58,16 +59,17 @@ public class CommentService implements CommunityConstant { /** * 查询评论的数量 - * @param entityType - * @param entityId + * + * @param postId * @return */ - public int findCommentCount(int entityType, int entityId) { - return commentMapper.selectCountByEntity(entityType, entityId); + public int findCommentCount(int postId) { + return commentMapper.selectCountByPostId(postId); } /** * 查询回复的数量 + * * @param rootId * @return */ @@ -77,6 +79,7 @@ public class CommentService implements CommunityConstant { /** * 分页查询某个用户的评论/回复列表 + * * @param userId * @param offset * @param limit @@ -88,6 +91,7 @@ public class CommentService implements CommunityConstant { /** * 查询某个用户的评论/回复数量 + * * @param userId * @return */ @@ -97,6 +101,7 @@ public class CommentService implements CommunityConstant { /** * 添加评论(需要事务管理) + * * @param comment * @return */ @@ -113,11 +118,8 @@ public class CommentService implements CommunityConstant { // 添加评论 int rows = commentMapper.insertComment(comment); - - // 更新帖子的评论数量 - if (comment.getEntityType() == ENTITY_TYPE_POST) { - int count = commentMapper.selectCountByEntity(comment.getEntityType(), comment.getEntityId()); - discussPostService.updateCommentCount(comment.getEntityId(), count); + if (rows == 1) { + discussPostService.addCommentCount(comment.getPostId(), 1); } return rows; diff --git a/src/main/java/com/greate/community/service/DiscussPostService.java b/src/main/java/com/greate/community/service/DiscussPostService.java index 3c5a3ec..3e787d1 100644 --- a/src/main/java/com/greate/community/service/DiscussPostService.java +++ b/src/main/java/com/greate/community/service/DiscussPostService.java @@ -170,11 +170,11 @@ public class DiscussPostService { * 修改帖子的评论数量 * * @param id 帖子 id - * @param commentCount + * @param addCount * @return */ - public int updateCommentCount(int id, int commentCount) { - return discussPostMapper.updateCommentCount(id, commentCount); + public int addCommentCount(int id, int addCount) { + return discussPostMapper.addCommentCount(id, addCount); } /** diff --git a/src/main/java/com/greate/community/service/ElasticsearchService.java b/src/main/java/com/greate/community/service/ElasticsearchService.java index 968c83b..88e711d 100644 --- a/src/main/java/com/greate/community/service/ElasticsearchService.java +++ b/src/main/java/com/greate/community/service/ElasticsearchService.java @@ -38,6 +38,15 @@ public class ElasticsearchService { elasticsearchRestTemplate.save(post); } + /** + * 从 Elasticsearch 服务器上查找数据 + * @param id + * @return + */ + public DiscussPost getDiscussPostById(int id) { + return elasticsearchRestTemplate.get(String.valueOf(id), DiscussPost.class); + } + /** * 将数据从 Elasticsearch 服务器中删除 * diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index c2ef5d7..f6cf85c 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -17,7 +17,7 @@ community.path.editormdUploadPath = E:/GreateCommunity/src/main/resources/static spring.thymeleaf.cache=false # MySQL -spring.datasource.url = jdbc:mysql://gz-cdb-ejk0kptx.sql.tencentcdb.com:57734/bbs-dev?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong +spring.datasource.url = jdbc:mysql://gz-cdb-ejk0kptx.sql.tencentcdb.com:57734/bbs-test?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong spring.datasource.username = root spring.datasource.password = Root@2021 # Mysql 5.0+ 汾ʹ com.mysql.jdbc.Driver @@ -43,14 +43,14 @@ spring.mail.reg-header=Register spring.mail.forget-password-header=Register # Redis -spring.redis.database = 10 +spring.redis.database = 30 spring.redis.host = gz-crs-limbivl1.sql.tencentcdb.com spring.redis.port = 21993 spring.redis.password = root2021 # Kafka spring.kafka.bootstrap-servers = 159.75.254.198:9092 -spring.kafka.consumer.group-id = test-consumer-group +spring.kafka.consumer.group-id = develop-consumer-group spring.kafka.consumer.enable-auto-commit = true spring.kafka.consumer.auto-commit-interval = 3000 diff --git a/src/main/resources/application-produce.properties b/src/main/resources/application-produce.properties index 54c848c..dcd7eea 100644 --- a/src/main/resources/application-produce.properties +++ b/src/main/resources/application-produce.properties @@ -36,14 +36,14 @@ spring.mail.reg-header=Register spring.mail.forget-password-header=Register # Redis -spring.redis.database = 11 +spring.redis.database = 1 spring.redis.host = localhost spring.redis.port = 6379 # Kafka spring.kafka.bootstrap-servers = localhost:9092 # ֶμ Kafka װе consumer.proerties޸, ޸ϺҪ Kafka -spring.kafka.consumer.group-id = test-consumer-group +spring.kafka.consumer.group-id = produce-consumer-group spring.kafka.consumer.enable-auto-commit = true spring.kafka.consumer.auto-commit-interval = 3000 diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 6c4036e..6501fe3 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,5 @@ # profile(ʱ develop, ߲ʱǵøij produce) -spring.profiles.active = test +spring.profiles.active = develop # logback logging.path=classpath:logback-spring-${spring.profiles.active}.xml \ No newline at end of file diff --git a/src/main/resources/mapper/comment-mapper.xml b/src/main/resources/mapper/comment-mapper.xml index 9d2f043..586ba4e 100644 --- a/src/main/resources/mapper/comment-mapper.xml +++ b/src/main/resources/mapper/comment-mapper.xml @@ -5,17 +5,20 @@ - id, content, pic_urls, user_id, entity_type, entity_id, root_id, target_id, post_id, like_count, status, create_time + id, content, pic_urls, user_id, parent_id, root_id, parent_user_id, post_id, like_count, status, create_time - content, pic_urls, user_id, entity_type, entity_id, root_id, target_id, post_id, like_count, status, create_time + content, pic_urls, user_id, parent_id, root_id, parent_user_id, post_id, like_count, status, create_time - + + + SELECT LAST_INSERT_ID() + insert into comment() - values(#{content}, #{picUrls}, #{userId}, #{entityType}, #{entityId}, #{rootId}, #{targetId}, #{postId}, #{likeCount}, #{status}, #{createTime}) + values(#{content}, #{picUrls}, #{userId}, #{parentId}, #{rootId}, #{parentUserId}, #{postId}, #{likeCount}, #{status}, #{createTime}) + @@ -48,12 +51,11 @@ - select count(id) from comment where status = 0 - and entity_type = #{entityType} - and entity_id = #{entityId} + and post_id = #{postId} diff --git a/src/main/resources/mapper/discusspost-mapper.xml b/src/main/resources/mapper/discusspost-mapper.xml index cfd904c..863e4f3 100644 --- a/src/main/resources/mapper/discusspost-mapper.xml +++ b/src/main/resources/mapper/discusspost-mapper.xml @@ -53,9 +53,9 @@ where id = #{id} - + update discuss_post - set comment_count = #{commentCount} + set comment_count = comment_count + #{addCount} where id = #{id} diff --git a/src/test/java/com/greate/community/ElasticsearchTest.java b/src/test/java/com/greate/community/ElasticsearchTest.java index ec8210e..df7444e 100644 --- a/src/test/java/com/greate/community/ElasticsearchTest.java +++ b/src/test/java/com/greate/community/ElasticsearchTest.java @@ -4,7 +4,6 @@ import com.greate.community.dao.DiscussPostMapper; import com.greate.community.service.ElasticsearchService; import lombok.Data; import lombok.extern.slf4j.Slf4j; -import org.checkerframework.checker.units.qual.A; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -28,4 +27,9 @@ public class ElasticsearchTest { elasticsearchService.saveDiscussPost(discussPostMapper.selectDiscussPostById(1)); elasticsearchService.saveDiscussPost(discussPostMapper.selectDiscussPostById(2)); } + + @Test + public void testGet() { + log.info(elasticsearchService.getDiscussPostById(33).toString()); + } } -- Gitee From cc44cdee8fccffbd2f38647f5e28c06b52c016ca Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Sat, 26 Feb 2022 23:09:12 +0800 Subject: [PATCH 051/125] update redis properties --- src/main/resources/application-develop.properties | 2 +- src/main/resources/application-test.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index f6cf85c..862c75d 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -43,7 +43,7 @@ spring.mail.reg-header=Register spring.mail.forget-password-header=Register # Redis -spring.redis.database = 30 +spring.redis.database = 3 spring.redis.host = gz-crs-limbivl1.sql.tencentcdb.com spring.redis.port = 21993 spring.redis.password = root2021 diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties index bfa9d8b..5bbd81d 100644 --- a/src/main/resources/application-test.properties +++ b/src/main/resources/application-test.properties @@ -34,7 +34,7 @@ spring.mail.reg-header=Register spring.mail.forget-password-header=Register # Redis -spring.redis.database = 10 +spring.redis.database = 2 spring.redis.host = 172.16.0.10 spring.redis.port = 6379 spring.redis.password = root2021 -- Gitee From 190c49c432f305e1399e50316f56bb66139d27fb Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Sun, 27 Feb 2022 11:01:56 +0800 Subject: [PATCH 052/125] update spring-kafka version --- pom.xml | 1 + src/main/java/com/greate/community/entity/Comment.java | 2 +- src/main/resources/application-develop.properties | 2 +- src/main/resources/application-produce.properties | 2 +- src/main/resources/application-test.properties | 2 +- src/main/resources/application.properties | 2 ++ 6 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 2c9e449..9063610 100644 --- a/pom.xml +++ b/pom.xml @@ -102,6 +102,7 @@ org.springframework.kafka spring-kafka + 2.8.2 diff --git a/src/main/java/com/greate/community/entity/Comment.java b/src/main/java/com/greate/community/entity/Comment.java index c6703a6..887c91e 100644 --- a/src/main/java/com/greate/community/entity/Comment.java +++ b/src/main/java/com/greate/community/entity/Comment.java @@ -29,7 +29,7 @@ public class Comment { private int postId; // 点赞数 private int likeCount; - // 状态:0 正常,1 禁用 + // 状态:0 正常, 1-禁用, 2-删除 private int status; // 发布时间 private Date createTime; diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index 862c75d..2ad2bf2 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -17,7 +17,7 @@ community.path.editormdUploadPath = E:/GreateCommunity/src/main/resources/static spring.thymeleaf.cache=false # MySQL -spring.datasource.url = jdbc:mysql://gz-cdb-ejk0kptx.sql.tencentcdb.com:57734/bbs-test?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong +spring.datasource.url = jdbc:mysql://gz-cdb-ejk0kptx.sql.tencentcdb.com:57734/bbs-dev?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong spring.datasource.username = root spring.datasource.password = Root@2021 # Mysql 5.0+ 汾ʹ com.mysql.jdbc.Driver diff --git a/src/main/resources/application-produce.properties b/src/main/resources/application-produce.properties index dcd7eea..c4257af 100644 --- a/src/main/resources/application-produce.properties +++ b/src/main/resources/application-produce.properties @@ -10,7 +10,7 @@ community.path.domain = http://1.15.127.74 spring.thymeleaf.cache=true # MySQL -spring.datasource.url = jdbc:mysql://127.0.0.1:3306/greatecommunity?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong +spring.datasource.url = jdbc:mysql://127.0.0.1:3306/bbs?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong spring.datasource.username = root spring.datasource.password = root # Mysql 5.0+ 汾ʹ com.mysql.jdbc.Driver diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties index 5bbd81d..47d8d59 100644 --- a/src/main/resources/application-test.properties +++ b/src/main/resources/application-test.properties @@ -11,7 +11,7 @@ community.path.editormdUploadPath = E:/GreateCommunity/src/main/resources/static spring.thymeleaf.cache=false # MySQL -spring.datasource.url = jdbc:mysql://172.16.0.4:3306/bbs-dev?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong +spring.datasource.url = jdbc:mysql://172.16.0.4:3306/bbs-test?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong spring.datasource.username = root spring.datasource.password = Root@2021 spring.datasource.driver-class-name = com.mysql.jdbc.Driver diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 6501fe3..39ed4af 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,7 @@ # profile(ʱ develop, ߲ʱǵøij produce) spring.profiles.active = develop +#spring.profiles.active = test +#spring.profiles.active = produce # logback logging.path=classpath:logback-spring-${spring.profiles.active}.xml \ No newline at end of file -- Gitee From 0df54a2bf6da8c9b31d8906c5e8ac3e023edace4 Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Sun, 27 Feb 2022 12:17:35 +0800 Subject: [PATCH 053/125] =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../greate/community/controller/LoginController.java | 8 ++++++-- .../java/com/greate/community/dao/UserMapper.java | 5 +++++ src/main/java/com/greate/community/entity/User.java | 2 +- src/main/resources/application-test.properties | 2 +- src/main/resources/application.properties | 2 +- src/main/resources/mapper/user-mapper.xml | 11 +++++++++-- 6 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index 42485f6..0c34c87 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -189,13 +189,15 @@ public class LoginController extends BaseController implements CommunityConstant */ @GetMapping("/wechat/login") public void wechatLogin(@AuthenticationPrincipal UserWeChat userWeChat, HttpServletResponse response) throws IOException { + String openid = userWeChat.getOpenId(); String username = userWeChat.getNickName(); //微信昵称 String password = CommunityUtil.generateUUID(); //随机密码,不能随便让人破解 String headerUrl = userWeChat.getHeadimgurl(); //微信头像地址 String email = "wechat@none.com"; //微信登录的用户,邮箱是一个特殊标识字符串 // 若微信用户对应的账号已存在,跳过模拟注册操作,直接进入登录过程 - User u = userMapper.selectByName(username); +// User u = userMapper.selectByName(username); + User u = userMapper.selectByOpenid(openid); User user = new User(); if (u == null) { // 模拟注册操作 @@ -211,10 +213,12 @@ public class LoginController extends BaseController implements CommunityConstant // 用户头像 user.setHeaderUrl(headerUrl); // 微信头像地址 user.setCreateTime(new Date()); // 注册时间 + user.setOpenid(openid); //微信用户openid userMapper.insertUser(user); // 这一步主要是为了获取userId - user = userMapper.selectByName(username); +// user = userMapper.selectByName(username); + user = userMapper.selectByOpenid(openid); } else { user = u; } diff --git a/src/main/java/com/greate/community/dao/UserMapper.java b/src/main/java/com/greate/community/dao/UserMapper.java index bac50eb..b5e7644 100644 --- a/src/main/java/com/greate/community/dao/UserMapper.java +++ b/src/main/java/com/greate/community/dao/UserMapper.java @@ -108,4 +108,9 @@ public interface UserMapper { * @return */ int addLikeCount(int id, int likeCount); + + /** + * 根据 openid 查询用户 + */ + User selectByOpenid(String openid); } diff --git a/src/main/java/com/greate/community/entity/User.java b/src/main/java/com/greate/community/entity/User.java index 6d79071..45fa369 100644 --- a/src/main/java/com/greate/community/entity/User.java +++ b/src/main/java/com/greate/community/entity/User.java @@ -32,5 +32,5 @@ public class User { private int auditStatus; private int likeCount; private Date createTime; - + private String openid; } diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties index fd13847..bfa9d8b 100644 --- a/src/main/resources/application-test.properties +++ b/src/main/resources/application-test.properties @@ -35,7 +35,7 @@ spring.mail.forget-password-header=Register # Redis spring.redis.database = 10 -spring.redis.host = 10.66.17.52 +spring.redis.host = 172.16.0.10 spring.redis.port = 6379 spring.redis.password = root2021 diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index afd699a..4af6390 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,5 @@ # profile(ʱ develop, ߲ʱǵøij produce) -spring.profiles.active = develop +spring.profiles.active = test # logback logging.path = classpath:logback-spring-${spring.profiles.active}.xml \ No newline at end of file diff --git a/src/main/resources/mapper/user-mapper.xml b/src/main/resources/mapper/user-mapper.xml index b358275..fc9e3cf 100644 --- a/src/main/resources/mapper/user-mapper.xml +++ b/src/main/resources/mapper/user-mapper.xml @@ -5,7 +5,7 @@ - username, password, salt, email, type, exp, level, status, activation_code, audit_status, header_url, like_count, create_time + username, password, salt, email, type, exp, level, status, activation_code, audit_status, header_url, like_count, create_time, openid @@ -15,7 +15,7 @@ insert into user () - values(#{username}, #{password}, #{salt}, #{email}, #{type}, #{exp}, #{level}, #{status}, #{activationCode}, #{auditStatus}, #{headerUrl}, #{likeCount}, #{createTime}) + values(#{username}, #{password}, #{salt}, #{email}, #{type}, #{exp}, #{level}, #{status}, #{activationCode}, #{auditStatus}, #{headerUrl}, #{likeCount}, #{createTime}, #{openid}) @@ -125,4 +125,11 @@ set like_count = like_count + #{likeCount} where id = #{id} + + + \ No newline at end of file -- Gitee From 6363adb30f64903a9a2002263efbef9db64abc05 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Sun, 27 Feb 2022 14:53:51 +0800 Subject: [PATCH 054/125] add logback-spring-test --- src/main/resources/application.properties | 4 +- src/main/resources/logback-spring-test.xml | 93 ++++++++++++++++++++++ 2 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 src/main/resources/logback-spring-test.xml diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a1ee24d..1cfcf25 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,6 +1,6 @@ # profile(ʱ develop, ߲ʱǵøij produce) -spring.profiles.active = develop -#spring.profiles.active = test +#spring.profiles.active = develop +spring.profiles.active = test #spring.profiles.active = produce # logback diff --git a/src/main/resources/logback-spring-test.xml b/src/main/resources/logback-spring-test.xml new file mode 100644 index 0000000..b38d595 --- /dev/null +++ b/src/main/resources/logback-spring-test.xml @@ -0,0 +1,93 @@ + + + community + + + + + + ${LOG_PATH}/${APPDIR}/log_error.log + + ${LOG_PATH}/${APPDIR}/error/log-error-%d{yyyy-MM-dd}.%i.log + + 5MB + + 30 + + true + + %d %level [%thread] %logger{10} [%file:%line] %msg%n + utf-8 + + + error + ACCEPT + DENY + + + + + + ${LOG_PATH}/${APPDIR}/log_warn.log + + ${LOG_PATH}/${APPDIR}/warn/log-warn-%d{yyyy-MM-dd}.%i.log + + 5MB + + 30 + + true + + %d %level [%thread] %logger{10} [%file:%line] %msg%n + utf-8 + + + warn + ACCEPT + DENY + + + + + + ${LOG_PATH}/${APPDIR}/log_info.log + + ${LOG_PATH}/${APPDIR}/info/log-info-%d{yyyy-MM-dd}.%i.log + + 5MB + + 30 + + true + + %d %level [%thread] %logger{10} [%file:%line] %msg%n + utf-8 + + + info + ACCEPT + DENY + + + + + + + %d %level [%thread] %logger{10} [%file:%line] %msg%n + utf-8 + + + debug + + + + + + + + + + + + + \ No newline at end of file -- Gitee From ebfbe1ce2315528fc25df146a44a67ae0273fd00 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Sun, 27 Feb 2022 15:20:50 +0800 Subject: [PATCH 055/125] fix: get commments by postId --- src/main/java/com/greate/community/service/ExpService.java | 2 +- src/main/resources/application.properties | 4 ++-- src/main/resources/mapper/comment-mapper.xml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/greate/community/service/ExpService.java b/src/main/java/com/greate/community/service/ExpService.java index 8e16f06..fed500a 100644 --- a/src/main/java/com/greate/community/service/ExpService.java +++ b/src/main/java/com/greate/community/service/ExpService.java @@ -38,7 +38,7 @@ public class ExpService { // 未实名无法获得经验值 User user = userService.findUserById(userId); - if (user.getAuditStatus() != 2) { + if (user == null || user.getAuditStatus() != 2) { return 0; } // 经验值不符合类型 diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 1cfcf25..a1ee24d 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,6 +1,6 @@ # profile(ʱ develop, ߲ʱǵøij produce) -#spring.profiles.active = develop -spring.profiles.active = test +spring.profiles.active = develop +#spring.profiles.active = test #spring.profiles.active = produce # logback diff --git a/src/main/resources/mapper/comment-mapper.xml b/src/main/resources/mapper/comment-mapper.xml index 586ba4e..498d874 100644 --- a/src/main/resources/mapper/comment-mapper.xml +++ b/src/main/resources/mapper/comment-mapper.xml @@ -34,7 +34,7 @@ from comment where status = 0 and root_id = 0 - and post_id = #{post_id} + and post_id = #{postId} order by create_time asc limit #{offset}, #{limit} -- Gitee From 11c61ae75afb77a463d55489f25d5add8c82a21e Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Sun, 27 Feb 2022 15:29:57 +0800 Subject: [PATCH 056/125] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dcomment-mapper?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../greate/community/filter/AuthenticationTokenFilter.java | 2 +- src/main/resources/application.properties | 4 ++-- src/main/resources/mapper/comment-mapper.xml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java b/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java index 8ced5aa..cbee5c8 100644 --- a/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java +++ b/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java @@ -47,7 +47,7 @@ public class AuthenticationTokenFilter extends OncePerRequestFilter { if (loginTicket != null && loginTicket.getStatus() == 0 && loginTicket.getExpired().after(new Date())) { // 根据凭证查询用户 User user = userService.findUserById(loginTicket.getUserId()); - log.info("用会话户信息: " + user.toString()); + log.info("用户会话信息: " + user.toString()); // 构建用户认证的结果,并存入 SecurityContext, 以便于 Spring Security 进行授权 Authentication authentication = new UsernamePasswordAuthenticationToken( diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a1ee24d..1cfcf25 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,6 +1,6 @@ # profile(ʱ develop, ߲ʱǵøij produce) -spring.profiles.active = develop -#spring.profiles.active = test +#spring.profiles.active = develop +spring.profiles.active = test #spring.profiles.active = produce # logback diff --git a/src/main/resources/mapper/comment-mapper.xml b/src/main/resources/mapper/comment-mapper.xml index 586ba4e..599cc37 100644 --- a/src/main/resources/mapper/comment-mapper.xml +++ b/src/main/resources/mapper/comment-mapper.xml @@ -34,7 +34,7 @@ from comment where status = 0 and root_id = 0 - and post_id = #{post_id} + and post_id = #{postId} order by create_time asc limit #{offset}, #{limit} @@ -63,7 +63,7 @@ select count(id) from comment where status = 0 - and root_id = #{RootId} + and root_id = #{rootId} -- Gitee From 67829d3732840b9a61f91aacacf05c03c334d0fb Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Sun, 27 Feb 2022 15:53:43 +0800 Subject: [PATCH 057/125] update sensitive words --- .../controller/CommentController.java | 71 +- .../controller/DiscussPostController.java | 3 - src/main/resources/sensitive-words.txt | 22535 +++++++++++++++- 3 files changed, 22567 insertions(+), 42 deletions(-) diff --git a/src/main/java/com/greate/community/controller/CommentController.java b/src/main/java/com/greate/community/controller/CommentController.java index 64907eb..43fbdc9 100644 --- a/src/main/java/com/greate/community/controller/CommentController.java +++ b/src/main/java/com/greate/community/controller/CommentController.java @@ -31,15 +31,9 @@ public class CommentController extends BaseController implements CommunityConsta @Autowired private CommentService commentService; - @Autowired - private DiscussPostService discussPostService; - @Autowired private EventProducer eventProducer; - @Autowired - private RedisTemplate redisTemplate; - /** * 添加评论 */ @@ -106,43 +100,46 @@ public class CommentController extends BaseController implements CommunityConsta discussPostId, page.getOffset(), page.getLimit()); // 封装评论及其相关信息 + if (commentList == null || commentList.isEmpty()) { + return new Result("fail", "1", "帖子不存在"); + } + List> commentVoList = new ArrayList<>(); - if (commentList != null) { - for (Comment comment : commentList) { - Map commentVo = new HashMap<>(); - commentVo.put("comment", StringListConvertor.toJsonObject(comment, "picUrls")); // 评论 - commentVo.put("user", userService.findUserById(comment.getUserId())); // 发布评论的作者 - int likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( - getUser().getId(), ENTITY_TYPE_COMMENT, comment.getId()); // 当前登录用户对该评论的点赞状态 - commentVo.put("likeStatus", likeStatus); - - // 存储每个评论对应的回复(不做分页) - // todo: 对回复做分页和排序处理 - List replyList = commentService.findReplyByComment( - comment.getId(), 0, Integer.MAX_VALUE); - List> replyVoList = new ArrayList<>(); // 封装对评论的评论和评论的作者信息 - if (replyList != null) { - for (Comment reply : replyList) { - Map replyVo = new HashMap<>(); - replyVo.put("reply", StringListConvertor.toJsonObject(reply, "picUrls")); // 回复 - replyVo.put("user", userService.findUserById(reply.getUserId())); // 发布该回复的作者 - likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( - getUser().getId(), ENTITY_TYPE_COMMENT, reply.getId()); - replyVo.put("likeStatus", likeStatus); // 当前登录用户的点赞状态 - - replyVoList.add(replyVo); - } + for (Comment comment : commentList) { + Map commentVo = new HashMap<>(); + commentVo.put("comment", StringListConvertor.toJsonObject(comment, "picUrls")); // 评论 + commentVo.put("user", userService.findUserById(comment.getUserId())); // 发布评论的作者 + int likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( + getUser().getId(), ENTITY_TYPE_COMMENT, comment.getId()); // 当前登录用户对该评论的点赞状态 + commentVo.put("likeStatus", likeStatus); + + // 存储每个评论对应的回复(不做分页) + // todo: 对回复做分页和排序处理 + List replyList = commentService.findReplyByComment( + comment.getId(), 0, Integer.MAX_VALUE); + List> replyVoList = new ArrayList<>(); // 封装对评论的评论和评论的作者信息 + if (replyList != null) { + for (Comment reply : replyList) { + Map replyVo = new HashMap<>(); + replyVo.put("reply", StringListConvertor.toJsonObject(reply, "picUrls")); // 回复 + replyVo.put("user", userService.findUserById(reply.getUserId())); // 发布该回复的作者 + likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( + getUser().getId(), ENTITY_TYPE_COMMENT, reply.getId()); + replyVo.put("likeStatus", likeStatus); // 当前登录用户的点赞状态 + + replyVoList.add(replyVo); } - commentVo.put("replys", replyVoList); + } + commentVo.put("replys", replyVoList); - // 每个评论对应的回复数量 - int replyCount = commentService.findReplyCount(comment.getId()); - commentVo.put("replyCount", replyCount); + // 每个评论对应的回复数量 + int replyCount = commentService.findReplyCount(comment.getId()); + commentVo.put("replyCount", replyCount); - commentVoList.add(commentVo); - } + commentVoList.add(commentVo); } + JSONArray result = (JSONArray) JSONArray.toJSON(commentVoList); page.setResult(result); diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index 15f9958..41f4c7b 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -31,9 +31,6 @@ public class DiscussPostController extends BaseController implements CommunityCo @Autowired private ExpService expService; - @Autowired - private CommentService commentService; - @Autowired private LikeService likeService; diff --git a/src/main/resources/sensitive-words.txt b/src/main/resources/sensitive-words.txt index cf1c998..c2c6872 100644 --- a/src/main/resources/sensitive-words.txt +++ b/src/main/resources/sensitive-words.txt @@ -1,4 +1,22535 @@ -赌博 +10八 +香港总部 +颠覆中国政权 +烟草局 +温总理 +文革 +文化部 +文化大革命 +文物局 +文学城 +自由亚州 +自由运动 +对日强硬 +一部分人因年龄或健康原因将不得不退下去 +一党专政 +一党专制 +一贯道 +一国两制 +国际法院 +新疆独 +新疆独立 +找政府评理 +贾庆 +林黄菊 +18大的人事 +政变 +政府 +政局雾里看花 +银行联合管理局 +政权 +正法 +镇压 +政治 +中功 +伊拉克 +伊斯兰 +伊斯兰运动 +中共 +一中一台 +政治反对派 +政治犯 +政治风波 +政治局十八 +政治字眼(如两岸关系等) +郑恩宠 +蒋介石 +中南海 +中南海波澜起伏 +中南海斗争 +中南海高层权利斗争 +中南海惊现东宫小朝廷 +中南海秘闻 +原子能机构 +中共权斗 +中共权利斗争 +中南海权力斗争 +中宣部 +中央 +治军方针定调 +中央军委 +中央派系斗争 +中央团系 +李三共志 +国家安全 +造反 +李克强第五代领导人 +李克强接班人 +国家机密 +国家主要部委 +国军 +国民党 +胡紧掏 +胡锦涛 +胡锦滔 +胡锦淘 +胡景涛 +国民根本大法 +国庆 +非典 +东突厥斯坦伊斯兰运动 +海关总署 +国务院 +国贼 +海洋局 +海外民运 +国资委 +封杀 +东西南北论坛 +分析 +中共派系力量再达成妥协 +反革命 +反攻 +反攻大陆 +反共 +反华 +反恐委员会 +反社会 +游龙商务联盟 +游戏管理员 +反政府 +反目 +优化官员 +应召 +印章 +反日 +反人类 +反腐败 +反封锁 +颠覆中华人民共和国政 +东北独立 +帝国之梦 +帝国主义 +弟大物勃 +北京市亿霖 +布局十八大 +藏独 +党政一把手 +党中央 +党风日下 +邓小平 +邓晓平 +党禁 +党退 +布什 +大纪元 +测绘局 +大陆当局 +分裂 +压迫 +分裂中国 +分裂中华人民共和国 +第5代领导 +第四代 +多党 +第五代领导 +第五代领导人 +第五代领导新星 +第五代中共领导人 +独裁 +独裁政治 +独夫 +独立 +动乱 +北京 +18大 +1717wg.88448.com +北京当局 +绑架 +18da +暗杀 +报警 +北京政权 +暴力 +暴乱 +暴政 +爆炸 +安理会 +安全部 +安全监管 +安全局 +保监会 +保密室 +西藏 +西藏独 +西藏独立 +西藏天葬 +西山会议 +打压 +爱滋 +出卖 +18届 +18届常委 +18届名单 +18届委员 +18届中央 +18权力布局 +18预测 +爱国运动正名 +爱国者同盟 +奥运 +奥运会 +18大的人事安排意见 +18大人事变动 +连战 +两岸关系 +两岸三地论坛 +亡党 +两个中国 +两会 +连准 +秘书长 +密码 +南联盟 +内幕 +深圳国领 +深圳红岭 +年轻高知团系接班 +收货 +收容所 +示威 +世华商务 +事实独立 +廉政大论坛 +柳树中学 +六四 +卖国 +卖国唐捷 +人弹 +人民 +人民报 +人民报讯 +天安门 +天安门录影带 +天安门母亲 +天安门事件 +天安门屠杀 +天安门一代 +末世论 +人民大会堂 +绵恒 +绵恒异议人士 +人民大众 +人民大众时事参考 +人民内情真相 +人民日报 +人民真实 +人民真实报道 +人民真实报告 +人民之声 +人民之声论坛 +人权 +人事变动 +人事布局出手既稳又重 +人事接班 +人体炸弹 +人员安排 +人员变动 +人渣 +人质 +六四民主运动 +天府广场集会 +通信维权 +铁道部 +统独 +统计局 +统战 +美国参考 +美国佬 +美国之音 +台*湾 +台办 +台独 +台盟 +台湾 +台湾独 +台湾独立 +台湾共合国 +台湾狗 +台湾建国运动组织 +台湾联盟 +台湾青年独立联盟 +台湾政论区 +台湾自由联盟 +摊牌要权 +贪官 +贪污犯 +唐人电视台 +讨伐 +讨伐中宣部 +缅甸 +美利坚 +权威主义国家的合法性理论 +全国两会 +蒙独 +蒙古独 +亲美 +亲民党 +亲日 +青天白日旗 +蒙古独立 +六四事件 +六四学生运动 +领事馆 +令狐计划 +同胞书 +令计划 +透支 +突厥斯坦 +涂运普 +屠杀 +团派 +团派政治明星 +推翻 +推翻社会主义制度 +退党 +外汇局 +外交部 +外交论坛 +外交与方略 +外蒙 +外围 +晚年周恩来 +平反 +迫害 +罗蒙马格赛基金会 +十大穷人 +十六大 +十八大 +十八大权力变更 +十八大人事 +十八大人事安排意见 +十八大人事调整 +十八大未来 +十八大预测 +省市换班第五代冒起 +省委大门集合 +省政府大门集合 +十八大政治局 +萨达姆 +萨拉托加 +三个代表 +如何推翻中共 +瑞士金融大学 +上访 +上海帮 +上海孤儿院 +上海垮台 +上海市劳动和社会保障局违规使用社保资金 +社保基金会 +社会主义 +融资 +审计署 +生当作人杰之昨日重现 +十八换血 +十八届 +十八年 +商务部 +商务领航 +十八庆红 +数据中国 +刷卡 +刷卡消费 +双十节 +刘奇葆热门人选 +四川独 +四川独立 +出台 +膏药旗 +高层人事变动 +加拿大皇家骑警 +胡权利瓜分 +胡书记 +胡温 +胡晓炼 +胡耀邦 +胡玉敏 +胡泽君 +胡振民 +胡总书记 +建国党 +检查部 +韩长赋 +韩东方 +韩联潮 +韩正 +韩正降职副市长 +捍卫社会主义共和国 +监管局 +建设部 +僵贼 +僵贼民 +姜春云 +姜大明 +姜洪禄 +姜建清 +姜伟新 +姜异康 +将则民 +江Core +江core.江ze民 +江澤民.江八 +江八点.江独裁 +江蛤蟆.江核心 +江流氓 +江戏子 +江责民 +江则民 +江泽慧江泽林 +江泽民.江贼 +江贼民.江折民 +江猪.江猪媳 +江主 +酱猪媳 +抗日 +抗议 +教养院 +教育部 +老人政治 +公证 +公证处 +共军 +锦涛 +共青团背景 +共铲党 +老江 +联合行动 +联大 +联合国 +联合起诉最高人民法院 +老毛 +老毛子 +积克馆 +共产 +共产党 +回民 +回民暴 +回民 +暴动 +换届隐忧 +共党 +大史 +复转军人 +公关 +公馆 +军长发威 +军事委员会 +军委 +军委主席 +军转安置 +军转干部 +公开批评中央高层领导人 +公开信胡 +公开信胡书记空中民主墙 +鸡毛信文汇 +恐怖份子 +恐怖主义 +纪元 +公投 +理想信念斗争 +持不同政见 +腐败 +从陈良宇倒台看中国政局走势 +周恩来后悔 +周恩来自责 +周刊纪事 +周恩来忏悔 +中央召开北戴河会议决定十八大高层人事 +中国在统一问题上的投降主义 +中国真实内容 +子女任职名单 +咨讯紫阳 +中国政坛“清华帮”盛极而衰 +中国政坛新星中的四大天王 +中国政治新星 +中国泛蓝联盟 +中国复兴论坛 +中国改革年代政治斗争 +西藏论坛 +中国高层权力斗争 +中国高层人事变动解读 +中国六四真相 +中国论坛 +中国媒体十大事件 +中国民主党联合总部 +中国社会的艾滋病 +中国社会进步党 +中国社会论坛 +中国共产党 +中国孤儿院 +中国和平 +中国联通 +中国太子 +中国网通 +中共当局 +中共独裁 +中共反腐风暴大背景揭秘 +中共高层变动:王兆国将任常委或取代贾庆龄 +中共领导人黑幕 +香港明报 +星亚网络影视公司 +中共十八布局 +中共十八大的基层选举 +中共十八大前夕 +中共十八大前夕人事布局出手既稳又重 +中共十八大热门人选 +中共十八热门人选 +中共十八人事 +中共十八人事变动 +中共十八人选 +中国威胁论 +中国问题论坛 +中国移动 +中国移动通信 +中国银联 +18大委员名单 +大中国论坛 +大中华论坛 +18高官互调 +4.25事件 +钟山风雨论坛 +重新评定 +邮政局 +印尼伊斯兰祈祷团 +中央政治局 +中医药局 +40万名车车主名单 +信访局 +信号 +信息产业部 +信用卡 +信用卡空卡 +信用危机 +星相 +版署 +新生网 +新势力 +英雄纪念碑 +九评共产党 +新党 +中华人民正邪 +中华时事 +燕南评论 +央视内部晚会 +中华养生益智功 +中华真实报道 +中华大地思考 +宇明网 +宇宙真理 +语音 +中华大众 +中华讲清 +阿拉 +安南 +东洲 +北韩 +鲜族 +俄国 +民告官 +民国 +民航局 +民进党 +民联 +民意 +民意论坛 +民运 +民阵 +民政部 +民猪 +民主 +民主潮 +民主墙 +民族矛盾 +民族问题 +诺贝尔和平奖 +大法 +大法弟子 +dpp大法 +fa lun +falu +发抡 +发抡功 +洗脑 +下法轮 +发轮 +发伦 +发伦功 +发仑 +发沦 +发纶 +发论 +发论功 +发论公 +发正念 +发囵 +发愣 +发瞟 +罚抡 +罚伦 +罚仑 +罚沦 +罚纶 +罚囵 +筏抡 +筏轮 +筏伦 +筏仑 +筏沦 +筏纶 +筏论 +筏囵 +伐抡 +伐轮 +伐伦 +伐仑 +伐沦 +伐论 +伐囵 +乏抡 +乏轮 +乏伦 +乏仑 +乏沦 +乏纶 +乏论 +乏囵 +阀抡 +阀伦 +阀仑 +阀沦 +阀纶 +阀论 +阀囵 +法 轮 功 +法*功 +法.轮.功 +法L功 +法lun功 +法功 +法会 +法抡 +法抡功 +法轮 +法轮大法 +法轮佛法 +法轮功 +法伦 +法仑 +法沦 +法纶 +法论 +法十轮十功 +法西斯 +法院 +法正 +法谪 +法谪功 +法輪 +法囵 +法愣 +珐.輪功 +珐抡 +珐轮 +珐伦 +珐仑 +珐沦 +五不 +五不争鸣论坛 +五出三进 +五套功法 +邝锦文 +垡抡 +垡轮 +垡伦 +垡仑 +垡沦 +垡纶 +垡论 +垡囵 +茳澤民 +荭志 +闳志 +闵维方 +氵去 +氵去车仑工力 +转法轮 +砝抡 +砝轮 +砝伦 +砝仑 +砝沦 +砝纶 +真、善、忍 +真理教 +真善美 +真善忍 +砝论 +砝囵 +泓志 +屙民 +珐纶 +珐论 +珐囵 +falun +Falundafa +fa轮 +Flg +弟子 +地下教会 +炼功 +梦网洪志 +轮大 +抡功 +轮功 +伦功 +摩门教 +三水法轮 +三唑仑 +天皇 +天怒 +天葬 +车臣 +达赖 +功法 +讲法 +基督 +基督教 +护法 +回教 +教徒 +功友 +大师 +达赖喇嘛 +虹志 +鸿志 +洪传 +贯通两极法 +光祖 +洪吟 +洪哲胜 +洪志 +宏法 +观世音 +宏志 +弘志 +古兰经 +红志 +车库 +车仑 +经文 +东方红时空 +风水宝地 +舆论 +舆论反制 +风雨神州 +自杀手册 +自杀指南 +自已的故事 +自由 +自由民主论坛 +自由网 +自由写作奖 +自制手枪 +自主择业 +宗教压迫 +先天健康法 +阻止中华人民共和国统 +昨日重现 +咨询 +咨讯 +风雨神州论坛 +东方时空 +独立台湾会 +访问链接 +飞扬论坛 +独立中文笔会 +东南西北论谈 +真相 +真象 +侦探设备 +争鸣论坛 +正帮通信公司 +正见 +正邪大决战 +正义党论坛 +北京之春民主论坛 +北美讲坛 +倒陈运动的最大受益人 +反封锁技术 +反腐败论坛 +地下刊物 +恶搞晚会 +北美讲坛 +北美论坛 +地铁十号线塌方 +逊克农场26队 +春夏论坛 +邓颖超日记 +国研新闻邮件 +国色天香网 +春夏之交 +春夏自由论坛 +亚洲周刊 +亚洲自由之声 +博讯 +邓小平和他的儿子 +政坛两黑马 +政坛明日之星 +中國當局 +中朝 +中电信 +中俄边界 +中俄边界新约 +中俄密约 +致胡书记的公开信 +指点江山论坛 +北美自由论坛 +参加者回忆录 +大纪元新闻网 +九-评 +九.评 +九、评 +九—评 +九成 +九成新 +九码 +九评 +新观察论坛 +新华举报 +新华内情 +新华社 +新华通论坛 +大众真人真事 +大家论坛 +新唐人 +新唐人电视台 +新闻办 +新闻封锁 +新语丝 +印尼伊斯兰祈祷团 +北大三角 +地论坛 +9.635 +9评 +中华人民实话实说 +杂志 +E周刊 +安装卫星电视 +代表大会 +论坛 +南大论坛 +南大自由论坛 +强硬发言 +南华早报 +你说我说论坛 +木子论坛 +两会报道 +两会新闻 +轻舟快讯 +热站政论网 +时代论坛 +时事参考 +时事论坛 +万维读者论坛 +统独论坛 +特讯 +世界经济导报 +世界通 +超常科学 +传说的胡曾联手是一种假象 +大纪元 +港澳办 +跨世纪的良心犯 +告全国股民同胞书 +华岳 +华岳时事论坛 +华夏文摘快递 +华语世界论坛 +和平请愿书 +华人媒体 +华通时事论坛 +华夏文摘 +广 闻 +广电局 +广东五元集团 +广告 +广闻 +红潮谎言录 +告全体网民书 +告中国人民解放军广大官兵书 +港料 +大史记 +联总之声 +集会 +集体上访 +讲事实 +要说法 +霍英东临终遗言 +大史纪 +高校群体事件 +传中共中央关于18大的人事安排意见 +安眠酮 +代血浆 +普萘洛尔 +呋塞米 +西布曲明 +testosterone +胰岛素样生长因子 +促红细胞生成素 +地西泮 +尼可刹米 +甲睾酮 +adrenaline +erythropoietin +地奈德 +莫达非尼 +氯噻嗪 +苯巴比妥 +促性腺激素 +泼尼松 +麻黄草 +雄烯二醇 +地塞米松 +tamoxifen +strychnine +androst +新型毒品 +杜冷丁 +兴奋剂 +mdma +海洛因 +海luo因 +heroin +diamorphine +diacetylmorphine +鸦片 +阿芙蓉 +咖啡因 +cocain +三唑仑 +美沙酮 +麻古 +k粉 +凯他敏 +ketamine +冰毒 +苯丙胺 +cannabis +大麻 +爱他死 +氯胺酮 +benzodiazepines +甲基安非他明 +安非他命 +吗啡 +morphine +摇头丸 +迷药 +乖乖粉 +narcotic +麻醉药 +精神药品 +爱女人 +爱液 +按摩棒 +拔出来 +爆草 +包二奶 +暴干 +暴奸 +暴乳 +爆乳 +暴淫 +屄 +被操 +被插 +被干 +逼奸 +仓井空 +插暴 +操逼 +操黑 +操烂 +肏你 +肏死 +操死 +操我 +厕奴 +插比 +插b +插逼 +插进 +插你 +插我 +插阴 +潮吹 +潮喷 +成人电影 +成人论坛 +成人色情 +成人网站 +成人文学 +成人小说 +艳情小说 +成人游戏 +吃精 +赤裸 +抽插 +扌由插 +抽一插 +春药 +大波 +大力抽送 +大乳 +荡妇 +荡女 +盗撮 +多人轮 +发浪 +放尿 +肥逼 +粉穴 +封面女郎 +风月大陆 +干死你 +干穴 +肛交 +肛门 +龟头 +裹本 +国产av +好嫩 +豪乳 +黑逼 +后庭 +后穴 +虎骑 +花花公子 +换妻俱乐部 +黄片 +几吧 +鸡吧 +鸡巴 +鸡奸 +寂寞男 +寂寞女 +妓女 +激情 +集体淫 +奸情 +叫床 +脚交 +金鳞岂是池中物 +金麟岂是池中物 +精液 +就去日 +巨屌 +菊花洞 +菊门 +巨奶 +巨乳 +菊穴 +开苞 +口爆 +口活 +口交 +口射 +口淫 +裤袜 +狂操 +狂插 +浪逼 +浪妇 +浪叫 +浪女 +狼友 +聊性 +流淫 +铃木麻 +凌辱 +漏乳 +露b +乱交 +乱伦 +轮暴 +轮操 +轮奸 +裸陪 +买春 +美逼 +美少妇 +美乳 +美腿 +美穴 +美幼 +秘唇 +迷奸 +密穴 +蜜穴 +蜜液 +摸奶 +摸胸 +母奸 +奈美 +奶子 +男奴 +内射 +嫩逼 +嫩女 +嫩穴 +捏弄 +女优 +炮友 +砲友 +喷精 +屁眼 +品香堂 +前凸后翘 +强jian +强暴 +强奸处女 +情趣用品 +情色 +拳交 +全裸 +群交 +惹火身材 +人妻 +人兽 +日逼 +日烂 +肉棒 +肉逼 +肉唇 +肉洞 +肉缝 +肉棍 +肉茎 +肉具 +揉乳 +肉穴 +肉欲 +乳爆 +乳房 +乳沟 +乳交 +乳头 +三级片 +骚逼 +骚比 +骚女 +骚水 +骚穴 +色逼 +色界 +色猫 +色盟 +色情网站 +色区 +色色 +色诱 +色欲 +色b +少年阿宾 +少修正 +射爽 +射颜 +食精 +释欲 +兽奸 +兽交 +手淫 +兽欲 +熟妇 +熟母 +熟女 +爽片 +爽死我了 +双臀 +死逼 +丝袜 +丝诱 +松岛枫 +酥痒 +汤加丽 +套弄 +体奸 +体位 +舔脚 +舔阴 +调教 +偷欢 +偷拍 +推油 +脱内裤 +文做 +我就色 +无码 +舞女 +无修正 +吸精 +夏川纯 +相奸 +小逼 +校鸡 +小穴 +小xue +写真 +性感妖娆 +性感诱惑 +性虎 +性饥渴 +性技巧 +性交 +性奴 +性虐 +性息 +性欲 +胸推 +穴口 +学生妹 +穴图 +亚情 +颜射 +阳具 +杨思敏 +要射了 +夜勤病栋 +一本道 +一夜欢 +一夜情 +一ye情 +阴部 +淫虫 +阴唇 +淫荡 +阴道 +淫电影 +阴阜 +淫妇 +淫河 +阴核 +阴户 +淫贱 +淫叫 +淫教师 +阴茎 +阴精 +淫浪 +淫媚 +淫糜 +淫魔 +淫母 +淫女 +淫虐 +淫妻 +淫情 +淫色 +淫声浪语 +淫兽学园 +淫书 +淫术炼金士 +淫水 +淫娃 +淫威 +淫亵 +淫样 +淫液 +淫照 +阴b +应召 +幼交 +幼男 +幼女 +欲火 +欲女 +玉女心经 +玉蒲团 +玉乳 +欲仙欲死 +玉穴 +援交 +原味内衣 +援助交际 +张筱雨 +招鸡 +招妓 +中年美妇 +抓胸 +自拍 +自慰 +作爱 +18禁 +99bb +a4u +a4y +adult +amateur +anal +a片 +fuck +gay片 +g点 +g片 +hardcore +h动画 +h动漫 +incest +porn +secom +sexinsex +sm女王 +xiao77 +xing伴侣 +tokyohot +yin荡 +KC短信 +KC嘉年华 +短信 +短信:广告 +短信广告 +短信平台 +短信群发 +小灵通 +短信群发器 +小6灵通 +短信商务广告 +段录定 +无界浏览 +无界浏览器 +无界 +无网界 +无网界浏览 +无帮国 +KC提示 +KC网站 +电信 +UP8新势力 +动5感地带 +白皮书 +UP新势力 +移3动 +移动 +移动公司 +移动集团 +移民 +易达网络卡 +安魂网 +罢工 +罢课 +铃声下载 +纽崔莱七折 +手机复制 +手机铃声 +手机铃声下载 +手机游戏 +神7州行 +网关 +神通加持法 +全1球通 +如6意通 +清仓 +灵动卡 +超市 +答案卫星接收机 +打折机票 +高薪养廉 +考后付款 +佳静安定片 +号 +航班 +航空 +航空母舰 +航空售票 +航天 +号码百事通 +考前发放 +成本价 +诚信通手机商城 +大2众卡 +辅导 +高利贷 +联 通 贵宾 卡 +联4通 +黑庄 +黑马 +黑手党 +黑车 +联通 +联通贵宾卡 +联通商务通 +联总 +联总这声传单 +联总之声传单 +高息贷款 +高干子弟 +恭喜你的号码 +恭喜您的号码 +高干子女 +各个银行全称 +各种发票 +高官 +高官互调 +高官子女 +辅导班 +复式 +喝一送一 +卡号 +复制 +监听王 +传:单 +传单 +旦科 +钓鱼岛 +钓鱼台 +当官靠后台 +党校安插亲信 +传九促三 +客户端非法字符 +刻章 +大麻树脂 +大麻油 +陈宝生 +程凯 +程铁军 +程真 +陈炳德 +陈炳基 +陈车 +陈川平 +陈存根 +戴秉国 +戴海静 +戴相龙 +陈德铭 +陈国令 +董贵山 +董万才 +懂文华 +陈冀平 +冯东海 +冯敏刚 +冯寿淼 +冯素英 +陈际瓦 +陈建国 +陈军 +陈奎元 +陈雷 +傅成玉 +傅申奇 +傅志寰 +傅怡彬 +贾安 +贾庆林 +贾廷安 +贾育台 +贾治邦 +希拉克 +希特勒 +傅雯娟 +符贵 +符强 +符跃兰 +陈良宇 +陈蒙 +陈敏尔 +陈破空 +陈润儿 +陈水扁 +陈文清 +邓楠 +迪里夏提 +陈希 +颜射 +阎明复 +焉荣竹 +严家其 +严家祺 +陈希同 +陈小同 +陈新权 +陈宣良 +陈训秋 +陈一谘 +丁关根 +丁元 +丁子霖 +陈元 +陈政高 +陈至 +李 洪 志 +李安东 +李斌 +李长才 +李长春 +李长江 +李成玉 +李崇禧 +李从军 +李大师 +李登辉 +李法泉 +李刚 +李海峰 +李汉柏 +李鸿忠 +李洪峰 +李洪宽 +李洪志 +李宏志 +李宏治 +李红痔 +李继耐 +李纪恒 +李建国 +于大海 +于浩成 +于起龙 +于幼军 +李金城 +李金章 +李景田 +李康 +李克 +李克强 +李兰菊 +李老师 +李立国 +李禄 +徐邦秦 +徐斌 +徐才厚 +徐粉林 +徐光春 +徐建国 +徐敬业 +徐匡迪 +徐乐江 +徐绍史 +徐守 +徐水良 +徐天亮 +徐一天 +许达哲 +许家屯 +许其亮 +许云昭 +肖爱玲 +肖钢 +肖捷 +肖强 +肖亚庆 +李录 +李买富 +李鹏 +李契克 +李荣融 +李瑞环 +李少民 +李盛霖 +李世明 +李适时 +李淑娴 +李铁映 +李旺阳 +李文斌 +李熙 +李希 +李向东 +李小朋 +李小鹏 +李小雪 +李学举 +李学勇 +李延芝 +李毅中 +李玉赋 +李玉妹 +李源潮 +李月鸟 +李月月鸟 +余欣荣 +余英时 +余远辉 +俞杰 +俞正声 +李兆焯 +李志绥 +李总理 +李总统 +李幛喆 +李岚清 +列宁 +列确 +林保华 +林彪 +林长盛 +林军 +廖锡龙 +林明月 +林慎立 +廖晖 +林树森 +林业局 +林幼芳 +凌锋 +林左鸣 +林樵清 +令狐安 +刘宾深 +刘宾雁 +刘成军 +刘春良 +刘冬冬 +刘刚 +刘国凯 +刘华清 +刘慧 +刘家义 +刘建华 +刘京 +刘俊国 +刘凯中 +刘明康 +刘鹏 +刘奇葆 +刘千石 +刘青 +刘山青 +刘石泉 +刘士贤 +刘士贤司马晋 +刘伟 +刘伟平 +刘文胜 +刘文瑜 +刘晓波 +刘晓江 +刘晓凯 +刘晓竹 +刘晓榕 +刘学普 +刘亚洲 +刘延东 +刘永川 +刘永治 +刘玉浦 +刘玉亭 +刘源 +刘粤军 +刘云山 +刘振来 +刘振起 +刘振亚 +刘志军 +刘淇 +陈至立 +陈子明 +陈总统 +陈左宁 +邓昌友 +邓可人 +邓天生 +邓笑贫 +阿拉法特 +蔡崇国 +蔡继华 +蔡挺 +蔡武 +蔡振华 +艾斯海提·克里木拜 +安立敏 +巴赫 +巴特尔 +巴音 +朝鲁 +白志健 +白春礼 +范长龙 +范印华 +万晓东 +汪梦飞 +汪洋 +汪岷 +王宝森 +王炳章 +王策 +王超华 +王传平 +王丹 +王东明 +王辅臣 +王刚 +王冠中 +王光亚 +王国生 +王涵万 +周强 +周生贤 +周天法 +周旋 +周英 +周永康 +朱保成 +朱成虎 +朱丹 +朱德 +朱嘉明 +朱金基 +朱琳 +朱明国 +朱溶剂 +朱容基 +朱维群 +朱之鑫 +朱总理 +朱镕基 +王和民 +王鸿举 +王洪章 +王沪 +王沪宁 +王华庆 +王华元 +王家瑞 +王建军 +王建平 +王金山 +王进东 +王军涛 +王俊莲 +王乐泉 +王莉莉 +王立英 +王力雄 +王明方 +王荣 +王儒林 +王瑞林 +王润生 +王若望 +王三运 +王胜俊 +王寿祥 +王太华 +王通智 +王万宾 +王为璐 +王维民 +王伟 +王伟光 +王希哲 +王喜斌 +王侠 +王宪魁 +王晓初 +王新宪 +王秀丽 +王旭东 +王学军 +王冶坪 +王毅 +王勇 +王玉普 +王兆国 +王正福 +王正伟 +王志刚 +王忠民 +王岐山 +方励之 +方舟子 +曹长青 +郭伯雄 +郭庚茂 +章虹 +章沁生 +张宝顺 +张博涵 +张伯笠 +张成寅 +张春贤 +张德江 +张钢 +张高丽 +张耕 +张国清 +张海阳 +张宏堡 +张惠新 +张基 +张纪南 +张健 +张建平 +张杰 +张军 +张开双腿 +张连珍 +张林 +张平 +张庆黎 +张庆伟 +张汝成 +张仕波 +张铁健 +张万年 +张伟国 +张文岳 +张先玲 +吴爱 +吴百益 +吴邦国 +吴定富 +吴方城 +吴官正 +吴宏达 +吴弘达 +吴仁华 +吴胜利 +吴双战 +吴新雄 +吴学灿 +吴学璨 +吴仪 +吴玉良 +吴镇南 +吴毓萍 +武吉海 +吾尔开希 +张晓刚 +张晓平 +张小平 +张轩 +张研农 +张阳 +张裔炯 +张毅 +张又侠 +张玉台 +张云川 +张昭富 +张志清 +张中伟 +张左己 +张岱梨 +何德普 +何峰 +何家栋 +何平 +何清涟 +何勇 +郭金龙 +黄局 +黄康生 +晴宜 +黄菊 +黄树贤 +黄献中 +黄翔 +黄兴国 +黄作兴 +黄慈萍 +黄殿中 +魏凤和 +魏家福 +魏京生 +魏礼群 +魏新生 +尉健行 +袁纯清 +袁贵仁 +袁家军 +袁荣祥 +卫留成 +卫生部 +温家宝 +赵爱明 +赵海青 +赵洪祝 +赵克石 +赵乐际 +赵南 +赵品潞 +赵铁锤 +赵宪庚 +赵晓微 +郑义 +郑源 +郑中 +温加饱 +温元凯 +温云松 +邢元敏 +邢铮 +黄华华 +黄祸 +黄建国 +黄晶 +郭罗基 +郭平 +郭声琨 +郭树清 +郭岩华 +郭炎炎 +郭永平 +曹刚川 +杨崇汇 +杨传升 +杨传堂 +杨刚 +杨怀安 +杨焕宁 +杨建利 +杨建亭 +杨洁篪 +杨晶 +杨利民 +杨利伟 +杨士秋 +杨松 +杨巍 +杨衍银 +杨元元 +杨月清 +杨周 +姚月谦 +姚增科 +耶和华 +叶冬松 +叶剑英 +叶青纯 +曹建明 +曹康泰 +曹清 +白恩培 +薄熙来 +白景富 +白军 +白立忱 +白立朴 +白梦 +鲍戈 +鲍彤 +杜导斌 +谢长廷 +谢和平 +谢小庆 +谢旭人 +谢选骏 +谢中之 +辛灏年 +杜恒岩 +杜鹃 +费良勇 +杜青林 +杜学芳 +杜宇新 +杜智富 +贝领 +本.拉登 +不来提不都热西提 +柴玲 +梁保华 +柳斌杰 +楼继伟 +邱学强 +齐墨 +仁吉旺姆 +仁青加 +卢越刚 +马大维 +莫伟强 +申维辰 +任亚平 +蔣彥永 +舒晓琴 +盛华仁 +努尔白克力 +彭枫 +彭清华 +欧泽高 +宋xx +司马晋 +司马义·铁力瓦尔地 +水扁 +史莲喜 +石宗源 +石大华 +司马璐 +司徒华 +宋爱荣 +宋楚瑜 +宋平 +宋平一句话 +宋书元 +宋秀岩 +宋育英 +宋祖英 +苏家屯 +苏荣 +苏绍智 +田成平 +田力普 +田修思 +童世平 +童屹 +童增 +铁凝 +苏士亮 +苏树林 +苏晓康 +孙宝树 +孙春兰 +孙大发 +孙建国 +孙金龙 +孙思敬 +孙晓群 +孙政才 +孙忠同 +汤光中 +汤涛 +唐柏桥 +唐家璇 +唐捷 +陶驷驹 +潘国平 +钦本立 +普京 +尚福林 +尚勇 +邵家健 +穆斯林 +秦光荣 +乔石 +秦晋 +秦银河 +邵明立 +邵琪伟 +沈德咏 +沈浩波 +沈素琍 +沈彤 +沈跃跃 +潘云鹤 +孟建柱 +孟令伟 +孟学农 +聂卫国 +祁建 +钱达 +钱国梁 +钱其琛 +钱运录 +马会 +马凯 +马克思 +罗保铭 +罗干 +毛一鲜 +毛泽东 +毛泽东123 +毛泽东2 +毛贼东 +梅克保 +罗礼诗 +罗清泉 +罗正富 +罗志军 +骆惠宁 +骆琳 +马良骏 +马强 +马三家 +马时敏 +马晓天 +马英九 +马志鹏 +马飚 +马馼 +卢展工 +路甬祥 +鹿心社 +陆兵 +陆浩 +陆委会 +吕京花 +吕秀莲 +吕祖善 +梁光烈 +梁擎墩 +常万全 +克林顿 +雷春美 +东突厥斯坦伊斯兰 +迟浩田 +克劳塞维茨 +迟万春 +仇保兴 +康日新 +康涛杰 +黎安友 +黎阳平 +拉丹 +拉登 +拉姆斯菲尔德 +高瞻 +葛振峰 +金道铭 +金日成 +金书波 +金尧如 +金振吉 +华过锋 +胡春华 +胡绩伟 +胡江 +胡平 +华惠棋 +华建敏 +华莱士 +金正日 +金壮龙 +靖志远 +高自联 +高莺莺 +高强 +高文谦 +焦国标 +焦焕成 +蒋峰 +蒋洁敏 +蒋经国 +蒋文兰 +蒋彦永 +高武生 +付申奇 +连胜德 +贺邦靖 +关卓中 +贺国强 +干以胜 +简鸿章 +回良玉 +江罗 +冠希 +江绵恒 +江棋生 +江青 +恩格斯 +114 +CBD +板楼 +别墅 +车库 +城堡 +成本价 +酬宾 +大降价 +地产 +度假区 +二期 +发售 +房 +房产 +房地产 +房峰辉 +房间 +房型 +房源 +房展 +房折 +风水宝地 +公馆 +公寓 +购房 +豪宅 +号码百事通 +喝一送一 +衡阳万通房产 +户型 +花园 +街铺 +精装 +景观住宅 +均价 +开发 +开盘 +看房 +两限房 +楼盘 +娄义 +买二送一 +买房 +买一送一 +卖车 +卖房 +面积 +名宅 +票据 +平米 +抢购 +求:购 +求购 +全户型 +认购 +三期 +商铺 +商圈 +商业楼 +生态区 +首付 +售楼 +特等奖 +特惠房 +特价 +特卖会 +投注 +旺铺 +威海 +现房 +小户 +小旺铺 +写字楼 +洋房 +样板房 +样板间 +样板间 +一码 +一平 +一期 +一切证件 +一梯两户 +一折起 +优惠 +折上折 +周年庆 +住宅 +装修 +准现房 +租房 +租售 + +第八类 其他: +常劲 +本田 +鲍筒 +拨打 +伴游 +QQ宠物 +本公司2 +世纪中国基金会 +610洗脑班 +帮穷人 +2004年公共服务奖 +2006年十句最真实的谎言 +001工程 +分家在 +大红赤龙七头十角 +第一批下海经商的人富 +俄罗斯 +周年庆 +苗圩 +明斯克号 +清纯 +穷 人 +穷人 +屈万祥 +善恶有报 +汕尾 +生态区 +生肖 +盛雪 +盛雪辛灏年 +师傅 +师父 +石戈 +食捻屎 +使馆 +驶你老母 +驶你母 +试卷 +试题答案 +圣战 +权柄 +全哲洙 +瘸腿帮 +群体灭绝 +燃烧辅助工具 +热比娅 +热线 +忍 +忍无可忍 +明心 +水去车仑 +斯诺 +四级答案 +四联航空 +透视镜 +透视眼镜 +万能钥匙 +万润南 +网管 +网上赚钱 +网特 +网通 +网赚队伍 +往事并不如烟 +威而柔 +威海 +素人 +宿命论 +隧道 +檀鑫 +名山县 +体健貌端 +天鹅之旅 +名师 +慕歌 +木犀地 +穆罕默德 +倪育贤 +年福纯 +捻 +潜在用户 +抢粮记 +龙虎豹 +瞒报 +毛片 +绿色环保手机 +绿色雨 +龙虎豹宋书元 +龙卷风 +领取 +长期 +城堡 +担保 +吹喇叭 +歌 +歌德 +歌功颂德 +高丽棒子 +蛤蟆 +个人崇拜 +看中国 +凯旋 +口蹄疫 +来京上访 +蓝光 +蓝丝带 +举行 +均价 +靖国神社 +警察 +静坐 +揭批书 +接班 +结欠 +结帐 +戒严 +刀林荫 +登辉 +登天梯 +翟渠 +翟小衡 +点金 +东突 +东突厥斯坦 +东土耳其斯坦 +吨 +多维 +二码 +二乙基酰胺 +二注 +发~票 +发财诗 +发改委 +分众 +封从德 +疯狂掠夺大陆股民 +凤凰 +佛展千手法 +戈扬 +鸽派 +工力 +工自联 +共黨 +古怪歌 +管理员 +哈批 +114 +1258 +1259 +12590 +12593 +1 0 1 5 9 +10000 +10010 +10086 +10159 +13423205670 +13725516608 +13875448369 +15112886328 +189 +6-4tianwang +64 +68170802 +6a6.net +7.31 +7.310 +89-64cdjp +8945212 +23条 +259o +381929279 +3P +4-Jun +AV +BJ +CBD +CCTV +CDMA +DICK +Dick +FLG +FOCUSC +FUCK +Fuck +GAMEMASTER +GCD +GameMaster +IP17908 +KEY_TEXT +NMD +QQb +SM +Soccer01.com +TMD +UltraSurf +bignews +Bitch +boxun +Chinaliberal +chinamz +Chinesenewsnet +cnd +Creaders +dafa +Dajiyuan +df'd +Dfdz +die +dpp +Freechina +freedom +Freenet +fuck +fuck your mother +hongzhi +hrichina +huanet +hypermart.net +incest +jiangdongriji +l2590803027 +lihongzhi +ma +making +minghui +minghuinews +nacb +na?ve +nmis +paper64 +peacehall +piao +playboy +renminbao +renmingbao +rfa +safeweb +sex +shit +simple +svdc +taip +tibetalk +triangle +triangleboy +txwq.net +unixbox +ustibet +voa +voachinese +wangce +wstaiji +www +xinsheng +yuming +yy通讯录 +zhengjian +zhengjianwang +zhenshanren +zhuanfalu +zhuanfalun +八九 +八老 +回民吃猪肉 +习近平 +TMD +毛民进党 +妹妹淫水 流 +机吧 +联国 +1989六四 +性爱电影 +李红智 +梁光烈 +巴黎市长 +成人BT +免注册淫色电影 +UltraSurf +鐵血三國志 +性爱图库 +公安 +777黄站 +大龟头顶住嫂嫂的花心深处 +插 穴 射 喷 精液 +兽奸 +PORN +毛可卡因 +阴茎挺进滋润肉洞里在阴户中抽送 +falundafa +三八淫成人网 +发^^轮 +毛江折民 +毛拉登 +免费淫*女A片段 +d7se我淫我电影 +madelove +淫奸美女穴 +美女极品穴 +…快插我淫穴… +乱武天下 +玩穴 +lineageⅡ +居然花钱请人教性爱姿势(组图)免费淫电影a片 +肛交 +go-vern-ment +奸你 +四眼醫生強制飲尿 美巨乳小野悠美第二彈 +坤迈 +高嘉 +兼职女教师 +嫂嫂的穴 +龟头在她的阴道里抽插 +张梅颖 +幼女嫩逼 +meimei的阴蒂 +淫女性息 +强奸35岁处女全过程/淫妹阴毛小穴 +这年头就这样 +阴屄 +贺龙 +酱猪媳 +毛台湾共和国 +欢乐潜水艇 +陰唇 +淫虎大型色站 +免费淫奸黄色电影a片 +drop +免费强奸淫电影 +幸福花園 +老公,他要插进来了 +9JBW +巨乳美女RINA无码第2弹 +十八电影掰穴特写红免费性视频聊天激情少妇图 +新華內情 +meinv嫩穴 +麻黄素 +绝品美女が恍惚颜の绝顶快感 +操逼样 +褻 +日本激情淫穴贴图 +女优 +雞吧 阴茎 插 騷穴 嫩穴 小穴 +錢 國 梁 +巨乳 +fuck温总理 +熱血傳奇 +夜色导航 +風騷淫蕩 +麻黃素 +插阿姨的洞洞舔女朋友的下身 +驶你爸 +轮奸做爱高潮录象 +测试 +赛你老母 +內射 +李岚清 +芬太尼 +日本妹妹 +fuck生春袋 +rf 行会战争 +卫生部 +fuck手机复制 +法论工 +meimei的小屄好痒 +毛干拎娘 +黄色免费淫乱电影 淫女色情图片 +幸福花园 +奸他 +朱狨基 +JPEEN +色情信息 +六岁幼女阴穴近拍 +meimei被操的淫水直流 +粪便 +私人服务器 +master +希特勒 +猥褻 +马卖马屁 +淫B +激情淫色自拍 +mi zhuan +免费淫奸女A片段试看 教你怎样延迟射精18岁以下禁 +又粗又长的肉棒 +新大陆 +吳 方 城 +胡紧套 +肉棒与阴道摩擦 +韩国成人激情淫洞 +丰满小妹的丰褪美腿 嫩得流水的小meimei +淫妻交换 +你说我说论坛 +政治反对派 +聚商 +hang hai shi ji +街头对抗靠 +ㄙㄞ你爸 +淫色导航 +淫乱护士电影 +淫乱狂穴 +吗逼 +蒋中国 +暴政 +香港激情淫影院 +发正念 +坤邁 +抽插18岁处女妹妹淫叫不断 +淫窝窝 +手伸到下体抚mo嫩穴 +中广网 +fuck宋楚瑜 +砍死你 +混 沌决 +神風~ Kamikaze Street Vol。 13 : 里山加与 +婬乱军团 +紮卡維是英雄 +免费午夜激情视频 +曾慶红 +乱伦之淫穴 +国产嫖娼 +淫液下留 +哥哥用力舒服死我了 +騰武 +space +毛你二大爷 +吞精骚妹 +中国真实内容 +新大陸 +天然むすめ 素人~このみ +小泉純一郎 +色情 网 站 导航 +粉红的的奶头粉嫩的阴唇 +色妹妹淫穴 +热血传奇 +天联世纪 +操逼电影 +英雄世纪 +东突,免费淫色情电影 令人喷血的春宫108姿势(组图)18岁禁看 +跑跑卡丁车 +9之游 +淫b +裸 +操车臣 +装逼呢 +地震 +肏meimei的小骚屄 +肉感炮友 +跟妹妹肏穴好舒服 +xi you +反恐委员会 +骡干 +淫液顺着肉棒 +中華民國 +赫鲁晓夫 +狂操小穴 +Tokyo Hot n0252 原田友美 高飞车美人教师精液炸沉 +國產嫖娼 +日本鬼子 +国管局 +svdc +小阴唇 黏液流下 舌头舔进阴道 +中華民国 +系统公告 +meinv视频图情色贴图区成人性光牒 +臭机 +毛天安门事件 +聂荣臻 +淫妻交換 +毛人弹 +徐光春 +屁股 +波霸 +meimei等你大鸡吧来插 +GAN +热站政论网 +免费成人图片 色情meinv做爱meinv小穴写真 +又肥又紧的屄儿 +中國狗 +金山 +小穴不断被顶入 +不倫繼母的性猥褻 +龟头在嫂嫂的小穴穴口研磨 +处女被强迫吃春药后被开苞 +毛洪志 +毛淫语连连 +费良勇 +反封鎖技術 +AV女优 激情小电影 熟女俱乐部 +法轮功靠 +熟女人妻 太太自愿拍片被机射在里面 +mo fa qi bing +届中央政治局委员 +夜聊视频聊天室 +发$$纶 +色网阴道特写强奸33岁处女全过程 +胡新宇 +淫獸學園 +何加棟 +王子杰 +毛看牌软件 +儿子添着妈妈大的阴唇 +淫穴嫩穴 +插meimei小穴 +GCD +Fag +遗言 +目標軟體 +默克尔 +午夜性爱惊魂 +操淫荡护士穴 +可视视频聊天 +恼杀美巨乳meinv~吉川萌 +地 下 教 會 +幼男搞幼女 +蔡庆林 +鸡吧插进肉穴 +紅十字會 +台湾共和国 +团中央 +吴 宏 达 +红顶商人 +丁子霖 +插那吗B +掄功 +激情女优 +稀少罕见的美少女蝴蝶屄 +mm的诱人双峰→免费试看片 +唐柏桥 +阿拉法特 +福莱斯特 +刘云山 +葫蘆案 +情色电影立即看 +鋼管舞 +免费淫色情电影 教你如何鉴别处男处女的方法(组图)18岁禁看 +asiasex +調教 +插深些 +神經病 +狹義道 +肉棒在小穴深初来回抽动 +鸡巴深深地插在妈的阴户里 +点点激情播放性电影 +侧那 +強淫女優 +我的阴茎使劲的抽插她的小穴 +人代会 +性愛 圖庫 +死gd +精子 淫穴 淫液 +周莹 +肉棒插入小穴 +猛地插入了她的肥穴 +联大 +经血 +毛你姥姥的 +chengmingmag +骚BB免费色电影 +薄一波 +宏 法 +腚眼 +淫痴 +口头检查 +日本成人激情论坛 +文化大革命 +民为法执 +達賴 +三级片A片下载观看 +死gm +白肌meinv?琴也 +激情成人网 -用品 -知识 -保健 +抽插21岁处女meimei淫叫不断 +免费淫色情电影 欢迎点击进入观看/林/心如/20岁处女偷拍/免费A。B片 +免费黄色淫秽电影 +小穴流水meimei手指插 +gameline +六四屠杀 +女優 +小B +日本帝國 +法谪功 +人民真实 +伸到老师的小穴里 +潮姫 史上最高の潮吹き女 +日本帝国 +meimei的小阴户 +辣妹狼图~肏穴图 +含住肉棒上下使劲吸吮起来 +百家性大型免费黄站 +陰囊 +輪攻 +精神病 +王策 +小b +巨额骗储 +毛佳静安定片 +鸟gm +骚屄 +TeSt +激情电影免费下载裸体美女乳房图 +日翻 +美臀嫰穴 +毛王兆国 +小卵泡 +日本成人激情网站 +肉棒 好粗啊…… +情色俱乐部美女奸淫。黄色电影裸体电影PP点点激情电影 +數碼精靈 +迅雷下载免费黄色淫乱电影 +6?4靠 +全裸女优 +達赖 +正悟网 +毛小泉纯一郎 +持不同政见 +鸟gM +淫癡 +台湾淫电影 导航 +外•挂 +www。gpchina。net +春色满园淫妻系列 +删 号靠 +美沙酮 +VIP独占~秘密之大乱交(最终话) +blogbaby +中华民国 +阴道里的大肉棒来回抽插 +操草妈 +helper +毛两腿之间 +中国淫女论坛 +48xp。com 电影免费 +亲哥哥……meimei的小穴……舒服死了…… +美国参考 +中华民國 +看棋软件 +操美女穴 +毛海洛因 +淫女俱乐部 +絲襪足交 +淫荡┅好舒服 +GAMEmaster +陈独秀 +淫水愛液 +农村人乱伦事 +女大学生在夜店被朋友轮奸 +拉案 +总书记 +毛毛一鲜 +火热的精液喷射在子宫上 +肉棒捅进阴户里 +香港色情影星美女裸体 +毛性交 +大人の隠れ汤 乱交游戯温泉へようこそ +因特天盟 +肉具 +司馬義?鉄力瓦爾地 +菊花蕾 +INSERT +騷棒 +恋爱盒子OL +颜骑 +騷棍 +bingnews +耿飙 +近亲相奸 背徳愉悦 9 +耿飚 +护法 +韩国身份证 +法院 +san guo qun ying zhuan +福爾摩薩 +筹码 +免费电影現役看護婦 +泄题 +捅她 +毛日Gm +你她馬的 +G。M +一四我 +肥东交警 +Tsubaki House-Triple Shot Vol01校花三姐妹 +大众真人真事 +航空母舰 +喷尿 +CAO NI MA +窝窝色网之家 +毛刘云山 +毛日GM +第七色明星淫欲 +毛李洪志 +G-M +FLG +空中小姐的淫蕩性生活 +淫肉誘惑 +灯草和尚 +方晓日 +肉棒的抽插…。好爽 +挺动我的下体 +国防科工委 +空降 +大奶美逼 +肉逼 +人學生meimei 埼玉援交 vol。2 なな&まい +玉穴 +搔meimei色站大全 +jiaochun +淫荡meinv医生 +抽插35岁处女妹妹淫叫不断 +我操你 +倒臺 +操浪妻淫女 +插的我好爽 +汉 奸 +妖媚熟母 +極品黑絲 +激情网站地址 +…好舒服 奸淫 操 +賣財富 +星战前夜 +毛泽東 +Tora-Tora-Tora Platinum Vol。9 Runa Mikami +fuck新华内情 +一夜激情成人聊天室 +ming yun +曾慶紅 +免费淫色论坛 +日本情色论坛 +品穴 +黄色免费淫奸电影我和女友干爽后再她meimei +makinglove +making +saobi +日本激情淫电影 +激情电影在线观看 +游戏向导 +老师和我做爱好爽 +阴茎插入肉洞里 +ya dian na +NeoSteam +色mm穴激情 +fuck新唐人 +火辣图片 +阴户紧紧包含着肉棒 +發正念 +淫色贴图365 +奇域 +百戰天蟲 +上有网 +跑跑 +毛李铁映 +小B样 +福摩萨 +私—服 +一卡多号 +桃色电影 +只允许法规年龄的人注册 +淫奸处女电影论坛 +浮夸风 +骚妈 +鸡巴插入花心 +salop +美女淫色贴图区 +处女 +插 9p +pussy +六决不 +淫汁飛散大亂交 +情色 美女 -公安机关 -记者 -犯罪嫌疑人 +處女開包 +白虎阴穴 +淫穴贴吧 +又粗又硬的肉棒 +一党独裁 +毛禁书 +售軟體 +骚女 +插 8p +金正日 +骚妻 +網路創世紀 +發$$倫 +毛昏药 +鸡巴……插死我了 +吴 仪 +商务部 +肉棒插入大肉穴 +狂插阿姨穴 +操的我好爽啊……我又要泄┅┅ +百家性大型色 +插 7p +和meimei肏屄 +遊行 +偷电 +龟头粗壮赤红 +管理 +淫荡女医生穴 +官商勾结 +小鸡巴 +插 6p +pp243淫色导航 +foseaon +继母的爱液 +骚妹 +色网阴道特写强奸30岁处女全过程 +中国民主党 +17大 +火药制作 +法仑攻 +明星合成图 +色meimei大型黄站 +中國遊戲中心 +语音激情视频聊天室 +赛福鼎•艾则孜 +(現映社)オバサマ5人 潮吹き絶叫雨あられ! +台湾20岁成人 +媽的B +发**沦 +fuck傻逼 +免费强奸电影 +碩大龜頭緊緊頂著她的阴道 +抽插24岁处女妹妹淫叫不断 +西藏分裂 +56xp。com 电影免费 +邝锦文 +董賤華 +tankbb +毛公安局 +gu long qun xia zhuan +马克思 +午夜成人电影 +penis +群魔色舞 +制服狩 +江Core +千岛湖之旅 +16大 +贛您娘 +大 纪元 +免费淫电影吴宗宪搞笑语录(25禁看) +贱 +六四 +古龍群俠傳 +鮑嶽橋 +打到共产党 +垮臺 +激情淫女小穴 +高潮集錦 +销魂洞 +吃大便 +血腥內幕 +肉唇 +不要将你的精液射进我的小穴了里啊 +罂粟 +吴 官 正 +机八 +台湾獨立 +足球经理 +換妻雜交 +父女姐弟淫乱 +肉棒插入阴户内 +抽插33岁处女meimei淫叫不断 +重题工 +处女心经 +后面插入处女的肉穴 +毛发伦 +小嘴吐出龟头 +監禁陵辱 +大众成人网 +降半旗 +港激情图源成人色情论坛 +長瀨 +支那 +164网址宽频影院网 +毛法轮大法 +儿子的肉棒好大啊 +發^掄 +無碼淫漫 +香港成人淫电影 +众志成城 +G_m +余震 +kamikaze girls 07 Nagisa Sasaki +fils de pute +肉棒嫩逼 +賤 +毛可卡叶 +fuck新闻出版署 +抽插 +肉棒放在阴道口 +打炮 +日穿 +八九民主运动 +靓穴美女 +美骚妇 +fuck信息产业部 +盐酸二乙酰吗啡 +吃鸡巴 +毛烂比 +QQ音速 +媚药少年 +三陪女 +地 下 刊 物 +免费淫乱电影 +胯下呻吟 +阿扁万岁 +欧美淫色贴图网址 +輪暴 +乡巴佬 +轮干 +測試员 +xing ji jia yuan +免费痴女吸精 +他媽地 +鄧穎超 +93bb成人小电影 +毛新闻出版署 +傻比 +那嗎逼 +亚洲无码 +妓女自拍做爱电影 +嫩肉 穴口 舌头 +和親姐姐作愛 +肉棒在小穴四周游移轻撩 +干meinv小穴 +大鸡巴干进meimei的小穴 +激情色 +楊思敏 +蒙巴顿 +宫泽Keito 超美系模特儿引退作 +suck +车仑女干 +天下無雙 +黑手党 +王鹤寿 +温比 +AV女优和平凡男人1日结婚 +强奸免费淫电影 +遊戲幣 +干八个美女的小穴 +毛对日强硬 +Neko GN Vol。1潮姬 史上最高之潮吹少女 +紅燈區 +易當 +大陆娱乐黄站 +色情导航 排行榜 +fuck +护士mm乱淫 +舔鸡巴 +自残 +玉蒲团讯雷下载 +最新n0242 东热RQ大乱交2007 Part1 +五月天 +嫖妓指南 +抽插30岁处女妹妹淫叫不断 +龟头顶住她的花心深处 +宁王府论坛 +拔出來 +八嘎 +屁精 +裸聊合法 +科技精英遇难 +2逼 老逼 +法棆功 +死GD +paper64 +fuck外/挂 +icpcn +冰风传奇 +梵高 +强奸 小穴 +3P +溫家宝 +淋病 +陽具 +偷情網 +江賊民 +天图 +操草拟妈 +免费淫奸女A片段试看 强*十八岁美女护士 +jy2 +hero108 +死GM +毛拍肩神药 +视频脱衣秀亚洲少女韩国无码片 +干你娘 +操出售手枪 +肉棒插进湿润花蕊 +fuck外-挂 +免费免注册淫电影 +色女 +jx2 +温州娱乐鹿城黄站 +四人幫 +亚洲淫色俱乐部免费淫 +溫家寶 +tie xue san guo zhi +魔性的meinv 鈴木麻奈美 +欣赏7感俏護士和医生22潮淫水图 +糞便 +fuck社。会。正。义。力。量 +淫奸妹妹穴 +龟头在阴唇上抽插 +minhui +免费处女淫女下载看电影性开苞 +插你爺爺 +骑士 +如果你未满29周岁请自觉离开。 +许家屯 +火辣圖片 +用骚痒难捺的阴部淫荡地摩擦着粗壮的鸡巴 +干你妈 +LIUSI +激情裸體 +杨建利 +轮 +毛干gm +手记注册日韩5027部激情电影 +毛买卖枪支 +巨乳護士南つかさ20連發中出 +台独靠 +毛你妈逼 +免费dse淫乱 +挥发型迷药 +中央電視臺 +射精时必须注意的几件事 +那嗎錯比 +抽插52岁处女妹妹淫叫不断 +教你怎样延迟射精38岁以下禁免费淫电影a片 +发@@纶 +禽兽集团%少儿禁 +激情淫色贴图导航 +VULVA +张 林 +操鸡 +鸟Gm +日你老母 +毛国家民委 +綠色灵数碼 +江八點 +臀部猛烈的撞击 +輪 +易志熹 +插你爷爷 +懷念十五年前的大學生 +轮奸内射 +李红志 +4f +大龟头顶住她的花心深处 +沾满蜜水又湿又滑柔软的 阴唇 +午夜情色电影 +大卵泡 +64 +老女嫩B +3D西游 +公審江澤民 +淫奸妹妹的屄 +猶太豬 +爽死我了 +小B樣 +鸟GM +共和 +淫电影//现场强奸19岁处女扒开小穴清晰做爱阴道裸体图 +淫穴贴图 +小穴 双手紧抓住 丰臀 +admin +姐姐的肥阴户 +日本激情淫色 +打倒中国共产党 +插入处女的肉穴深处 +成人激情asp电影通道 黄色免费电影 sp色情播放 +3p +俠客天下 +測試員 +淫荡美少女 +张 伟 国 +陈慧琳精品 +你二大爺 +它媽的 +你二大爷 +遊戲新幹線 +10 Little Asians Vol。 14~10人微乳素人娘~ +毛密宗 +露出了娇小鲜嫩的小屄洞 +tian di xuan men +毛色情小电影 +pao pao tang +那嗎瘟比 +嗎啡 +成人激情视频聊天室 +你的小穴好深啊 +免费淫奸女A片段试看 欢迎点击进入观看/林/心如/20岁处女偷拍/免费A。B片 +出售假币 +兒屆中央政治局委員 +毛海洋局 +骑她 +台湾万岁 +毛万税 +毛日gm +kao +14se淫色图片 +插烂meimei小屄 +网管 +肥逼 +做爱视频表演黄色小说 +fuck台湾民国 +扑哧一下鸡吧操进了逼里 +哥哥的肉棒好大啊 +Kamikaze Premium Vol。 8 +本土無碼 +毛日gM +无修正 +fantasyjourney +银行账號 +hrichina +躶 +淫水 …你的大肉棒 +Fku +黄色性交裸体图_做爱贴图性交成人贴图 +英雄世紀 +夢見る大和撫子 Pretty Little Asians Vol。48 +不注册免费淫电影 +18岁禁淫荡小处女 +ggol +美女视频图情色贴图区成人性光牒 +女人 +96 +出售枪支 +毛干gM +tmd +周锋锁 +中国猪 +鸦片 +激情成人电影 +boke +免费激情视频聊天室 +数码精灵 +罌粟 +女也 +激情淫色游戏 +总统号 +毛新闻管制 +钦本立 +四人帮 +插 4p +淫穴贴图论坛 +公告 +粗大的鸡巴穴洞 +操完姐妹操嫂嫂 +国务院 +完美时空 +小嫩穴把大鸡巴包得紧紧的 +龙新民 +足脚交 +注册激情电影 +三八淫 +机叭 +插 5p +十六大 +吗啡碱 +免费mm黄色淫乱电影 +飙车 +又嫩又紧的阴户 +电影下载 +愛的奉獻 +下载免费淫电影 +林心如合成淫照片 林心如淫照片 +淫电影//现场强奸18岁处女扒开小穴清晰做爱阴道裸体图 +香港淫穴裸体图 +苯環利啶 +yuanmingxinsheng +伸入蜜穴 +┅┅手握住我的大肉棒 +踢 +bong +台湾总统 +色网阴道特写强奸21岁处女全过程 +GirlDV热门成人影片 +性虎色网 +插 3p +愛的奉献 +毛狗日的 +怪兽总动员 +本站10018多部激情电影全部免费试看三天 +操黑 +毛司法部 +民政部 +毛丫的 +女乃 +trickster +毛小日本 +肉棒插入阴道里 +操比毛 +半夜我把龟头插进妹妹的深处 +Cs +毛六。四 +林伯渠 +曲线消魂 +爱的乱伦 +乱世三国 +激情淫bb +战国英雄 +bukkake +色屋图片 +未亡人柔肌 +陈军 +鸡巴射出精液  泄了 +毛孙文 +天怒 +斯蒂芬霍金 +黄孟复 +柔软的肉壁紧紧的包著龟头 +網絡公祭 +手淫 +遊戲米果 +脬 +日本成人电影 性生活影片 免费在线成人电影 +旅游局 +本站10002多部激情电影全部免费试看 +肉壶 +免费在线观看 +毛法愣 +X到噴屎尿 +dajiyuan +喪服妻欲望 +日本meimei +转化 +肉棒在子宫口游荡 +日本MM色比图吧 +歡迎G11情色電影院 +鄒家華 +無碼h漫 +朱巨 +Baopi +GY +中国论坛 +独裁 +龟头在阴户抽插 +抽插24岁处女meimei淫叫不断 +在线激情电影 +肉棒舌頭 蜜穴 +雙峰微顫 +有容奶大 +李总统 +操你媽 +GP +你的逼……真紧 +GN +GM +金槍不倒 +藤武 +外挂 +劉曉波 +薄码 +斯诺 +鑫诺 +二B +免费女A片段 +免费淫电影吴宗宪搞笑语录(22禁看) +银民吧 +毛肛门 +讨伐 +少女床上春色销魂 +毛麦角酸 +AV +中国人民志愿军 +……好粗…好舒服 +狂插meimei穴 淫水流 +大使官 +sheng da fu weng +岳武 +捏你鸡巴 +NET +tester +美女偷拍成人小说激情网香港激情图源成人色情论坛脱衣美女做愛 +毛届中央政治局委员 +血腥内幕 +把肉茎抽出插入屁眼里 +wu lin wai shi +帶套肛交 +操你娘 +狗诚 +BI +BC +曹庆泽 +美国成人激情网站 +清纯派meinv可爱的让人想狂干她!【RMVB/195MB】 +信息产业部 +CS +hdw +黑屄 +臺 +免费A片 +肉壁 +51淫色导航 +jiejie的穴好紧啊 +二b +套子 +三级片 +Bc +欧美大乳 +法稐功 +CM +操参事室 +366成人网站 +fuck色情 +强奸处女学妹 +捅他 +ttwg666 +暴淫 +淫妻浪女小说 +性宝贝淫色导航 +现场直播女主持人教你做爱 +日蛋 +MY +耣 +陈功 +法论攻 +漢奸 +李旺阳 +阴唇 +几叭 +军长发威 +阴茎在阴道快感 +亚洲激情淫色贴图 +大唐豪侠 +中国移动联电信午夜激情电影秘密通道 +風騷欲女 +毛郭伯雄 +一九八九年六月四日 +game master +龟头操进处女阴道 +浪少妇和医生疯狂做爱 +狭义道 +毛干你娘 +可愛均整清純派美女可愛均整清純派美女 +虐待 +自慰抠穴 +fuck王八蛋 +机巴 +屌7 +洞抽少妇 +kang zhan +fuck色情服务 +淫网 +星空幻想 +毛反华 +mo你全身 +毛人民银行 +监管局 +视讯情人聊天室 +自杀指南 +外掛 +免费成人影片 +Gm +肏 +毛二屄 +强*十八岁美女护士看完保证你打飞机免费淫电影a片 +捅你 +手伸到儿媳妇下体抚mo嫩穴 +蜜穴裡輕插緩送 +轮功 +meimei的小嫩穴 +中华讲清 +黑客 +肛 +熟女护士 +唐人互动 +bastard bastard +超级诱人销魂表情免费播放变身辣妹 插入妈妈白嫩的诱惑 +联通移动秘密通道情色电影午夜成人电影 +65情网色论坛色情电影 +歡樂性今宵 +J8 +吹萧 +唐人互動 +JB +谭震林 +毛激情电影 +免费淫奸女片 +流蜜汁 +淫聲浪語 +SM插进湿润的小穴 +盛雪 +猛男狂干美女 +發~掄 +美女裸体在线免费淫电影 +feng yun +肉香 +国家分裂 +欧美激情淫色贴图网 +薄碼 +extremeskate +63xp。com 电影免费 +fawanghuihui +龙与地下城 +毛干你妈 +發*淪 +人斩少女3赤裸忍者 +林慎立 +肉棒插入少妇嫩穴 +又肥又大的阴户 +LB +飄流幻境 +厕所盗摄护士jiejie性感 +毛透视眼镜 +兔meimei贴图区 +日b +高潮集锦 +处女的阴道特别紧 +45xp。com 电影免费 +小乳头 +U R靠 +成人电影,黄色电影,色情电影,免费电影试看 +花花公子 +警奴 +朱总理 +偷窥图片 +风骚少妇 +残忍老爸玩我小穴 +UR +本站10010多部激情电影全部免费试看三天 +百家性大型黄色站 +抗曰 +FLG媽B發掄 +免费激情聊天室 +少妇房中自淫,和两勇男玩5P,操得直叫爽 操日本淫女穴 +茎 +朱德 +incest +淫亂熟女 +國家總理 +注册激情电影(切记只允许法规年龄的人注册)注册快感吧!! +里根 +TW +金城安娜-痴女教官NO。7 +犯践 +黃色小說 +强奸轮奸美女视频 +Wg +毛干GM +…好舒服…小穴 +粉嫩人妻在老公面前被人搞 +狂插日韩骚逼打飞机必看 +魔法飞球 +郭 平 +国外激情淫色贴图 +奸淫女老师 +发**抡 +犯踐 +亚洲午夜激情那个电影中心 +运营商 +老毛 +WG +老比 +高岗 +悠遊網 +發$淪 +毛干Gm +李山 +毛基督教 +淫妹阴毛小穴 +老母 +性电影免费在线试看 +清华同方 +毛江独裁 +妹妹被操的淫水直流 +本?拉登 +奶头 +99BBS +嫩穴美女挖嫩穴淫女嫩穴俱乐部 +黄色免费淫乱电影 +亚洲情色套图 +就去日 +fuck外汇局 +日Gm +遇难 +操淫荡meimei穴 +牛顿 +曰本 +激情淫电影 +QB +遇難 +tian zhi lian yu +美女嫩穴 妹穴 亮穴 女人穴 +阿不來提•阿不都熱西提 +肏又大又嫩的屄儿 +j8靠 +日本淫色 +毛乳房 +日GM +huan le qian shui ting +保釣 +肉棒插入小阴户内 +pnisse +【亚洲/无码】Mugen Vol。11 Ai Hazawa羽沢愛!【AVI/ 699MB】 +魔法飛球 +骚妇激情 +我含住他的阴茎 +SM舔穴 +天安门事件 +本站10021多部激情电影全部免费试看 +做爱网有激情自拍裸体 +奸淫电影 +jinyong +监听器 +肛门潮吹 极太合体 原千寻 红音 桜田 +meimei做爱 +百家性大型色站 +西藏独 +成人激情网站 +硬挺 +po tian yi jian +殺你一家 +Sb +色情成人网站 +臺灣島國 +天安門殘案 +allbisexual。com +扮开嫩穴 +SM +婷婷口含鸡巴 +十八代 +搔meimei黄站 +日本成人 +龍圖智庫 +毛反动 +SB +倡议书 +股市民谣 +可待因 +现场强奸18岁处女扒开小穴清晰做爱阴道裸体图 +亚洲成人贴图区论坛 +fuck我妳老爸 +肉棒抵住阴唇 插入 +?(SOD)超天然素材 桐島あゆみ +舌战法庭 +極品波霸 +色97愛 +ERA OF FAITH +给你爽 +周容重 +喪服妻欲望下载 +奸她 +犯賤 +轉法輪 +抗日 +吳 百 益 +退黨 +你它媽的 +毛反共 +发轮 +jiejie的肥阴唇 +gth +49xp。com 电影免费 +午夜成人激情聊天室 +湿淋淋的骚阴道 +毛人大 +大陆娱乐鹿城黄站 +她妈 +snk。ni8。net +苯环已呱啶 +姐姐的嫩阴唇 +摇头玩 +冈峦 +毛口交 +秦青的幸福生活 +亚洲激情无码BT +阴囊 +毛文物局 +delete +色 +赵紫阳 +激情淫色贴图区 +張德江 +肛门 +肉棒用力的抽插着小阴唇 +射进妈妈里面 +成人情色网站 +免费在线黄色小电影 +163网址宽频影院网 +鬼公 +TokyoHot之极品meimei +ㄙㄞ你母 +奶娘 +激情玩穴电影 +苏绍智 +阎安 +错B +肛門 +黑窑奴役 +性爱护士 +泡泡堂 +操臭化西 +ZD +免费淫乱电影下载 +粗大的龟头缓缓磨擦着湿漉漉的阴户 +告全体网民书 +saohuo +在骚穴里抽插著阳具 +urTNND +luan shi san guo +d p p +the world of legend +回良玉 +两会新闻 +銀行帳號 +掌上靈通 +错b +老师的阴道好紧 +免费看三级电影淫电影 +她娘 +在线小淫虫电影 +淫之学妹喷尿射得好高 +1989年6月4日 +毛江猪 +pp点点通 +法伦功 +切七 +哲民 +护士小穴 空姐小穴 +QQ堂 +昏药 +saohuao +操 淫荡 好爽 +meinv主持26小时全天激情热舞 +公务员的工资 +奸夫淫妇 +淫糜 +妹妹的阴户 +喷 射 +免费淫 电影a片。母子淫奸乱轮现场 +強制フェラ 失神セックス +沒有人權 +烏雲其木格 +game MASTER +玉女吹箫的姿势和技巧图 +联总 +丁香大型成人社区 +緊縛淩辱 +人性本色 +政治局 +日本淫电影 +蒋树声 +遊戲發獎員 +母子姦情 +鲍威尔 +fuck退党 +日B +龙洲影院日本娱乐性免费电影 +紧缚凌辱 +妳马的 +AVW FUCK DOWN!最后性 +日你奶奶 +国家安全 +亚洲区人妖射精图最淫人体网站 +fuck驶你娘 +代表大会 +集團熟痴女川奈-南智子-澤宮有希-櫻田由加里4時間 +gM +装B靠 +独占动画~女热大陆 file 2 +駛你娘 +fuck系统公告 +她馬的 +日你爺爺 +gy +天使之恋 +qiangjian +蒋经国 +操妳祖宗 +gn +gm +heatproject +军妓 +臺湾國 +大鸡吧插妹妹 +阴唇阴道 +blowjobs +耶和華 +奶大穴肥多条肉棒难满足 +瞿秋白 +gp +dong fang chuan shuo +saga +藏春阁【全免费】 +发^^论 +JOB +無碼H漫 +yong bing chuan shuo +数通 +中国政府 +用舌头舔着大小阴唇 +他妈的靠 +meinv嫩穴淫水直流 +你奶奶 +dao jian +fuck系统 +毛私-服 +省長 +g8 +平可夫 +肏屄 +老骚货 +省长 +包二奶 +operator +国产骚货 +内射 +搔穴自慰 +项小吉 +那娘老比 +白虎陰穴 +夢城互動 +运营官 +淫电影//教你如何鉴别处男处女的方法 +浴室自拍 +凌辱?妥?学?@~??Δ畏耪n後~ +gamemaste +meteor academy +黑马@SQ Evolution Vol。3 柳濑遥 +日你爷爷 +拉客 +cS +bt +反封锁技术 +集體淫 +流口水啦 +lovebox +六四点击 +亚洲淫色贴图论坛 +18摸 +弟弟淫奸姐姐 +肉棒 高潮 +郝建秀 +毛农业部 +毛塞你公 +騷浪 +杨勇 +毛私/服 +日本激情淫色视屏 +cs +王稼祥 +毛色情 +1001an。com +臭化西 +K粉 +藏独 +法仑工 +抽插46岁处女妹妹淫叫不断 +成人bt +膀胱 +jiaochun +学运 +毛国安局 +抽插47岁处女meimei淫叫不断 +淫奸小姨子穴 +da hua chun qiu +毛虐待 +fuck十五周年 +刘晓竹 +失密 +歡樂時代 +射精 +毛阴部 +不爽不要錢 +爱爱激情电影 +穷逼 +干阿姨小穴 +卖骚 +肉棒插入阿姨 ……爽呀 +傻瓜 +几八 +发论 +au +水从穴里流出来 +奇淫寶鑒 +jinv +做爱淫乱小说 +军委 +毛粮食局 +我和二姨在车上舔 +痴女護士 +厕所盗摄meinv淫穴 +嗎個 +色网址联盟 +抽插婷婷 +时事论坛 +meinv小穴贴图偷拍少女乳房 +賽博先鋒 +BT淫穴 +毛一贯道 +東升 +尚禾 +港澳办 +韩国激情淫色网站 +Mai骚 +身寸米青 +法$$仑 +操妹妹湿穴 +性高潮 +轻轻地抽插著阳具 +插嫩穴 +婷婷激情俱乐部导航 +葵 +关卓中 +鹿城黄站百家性 +毛乳波臀浪 +胴体 +色网阴道特写强奸25岁处女全过程 +小姨子她饱满乳峰上的粉红乳晕 +蝴蝶谷淫图片 +国家领导人 +Reign Of Tera 2 +美穴 +文 革 +新人×ギリギ 七海 +萋 +阿姨的大阴唇 +出墙红杏 +playboy +胸部 +奴隷调教 +我的淫荡老师 +顶级轮奸套图站 +操穴插逼 +藏獨 +免費性愛電影 +阴唇上摩擦着 +凯丰 +久之游 +想插穿她那肥嫩的小骚屄儿 +淫穴自拍 +摸你全身 +陈云 +發@@掄 +戳比 +国民政府 +遺言 +龟头顶住她的阴户 +日本淫荡meimei +item +T。M。D靠 +聖戰 +文九天 +现代情色小说 +梅花网 +jx +婷婷俱乐部 +抽插41岁处女妹妹淫叫不断 +草枝麻 +阳具 +我 操 穴 +毛六四真相 +欢乐性今宵 +杨思敏 +和姐姐淫穴 +老江 +吗啡片 +黄色我该死免费淫奸a片偷拍MM接客宾馆 +超女世界Online +GAMEMASTE +洗钱 +orgasmus +黄蓉舔小龙女的乳头 +色情網站 +叔嫂肉欲 +飘飘 +塞白 +眯眯爱大型黄站 +妹妹陰毛 +色淫成人 +小穴 +成人色情 +大师 +押小 +夜夜色娱乐网 +大肉棒…插我……」 +春城娱乐(淫窝) +骚批 +挺送 肉棒 激烈 撞击 +反社会 +法$$伦 +j8 +肛jiao +抽插著阿姨的淫穴 +免费淫女在线看电影 +中国军用运输机 +機戰 +操逼毛 +jiejie的阴道好紧啊 +肉棒不斷的抽插著她的肉體阴道口 +免注册淫电影 +淫荡少妇被轮奸 +天安門一代 +onlineworms +李师付 +狂插喷爱液 +八九學潮 +jb +赛博先锋 +meng xiang +毛天安门录像带 +張万年 +肉棒插进阴户里 +h站 +干死客服 +不爽不要钱 +日gM +美女淫水狂流 +淫穢 +做爱电影 +免费淫奸女A片段试看 强*十八岁meinv护士看完保证你打飞机 +Test +meinv 淫穴 +peng peng bang +毛鸦片液 +%共產黨爛逼 +丰盈雪白的肌肤、肥嫩饱满的乳房、红晕鲜嫩的小奶头 +wg +完美時空 +黄色文学 +鸡吧插进 +65xp。com 电影免费 +jiba +蘋果日報 +淫穴 +免费成人电影图片 +抽插34岁处女meimei淫叫不断 +臺灣 +新闻办 +官人我要 +大鸡吧插meimei +喷你 +騷水 +wG +meinv鸡吧图 +操母狗 +日本巨乳淫女 +現場直播~女主持人教你做愛 +fuck新手指导员 +天使之戀 +台湾18成人小说 免费成人电影 +王宝森 +賣軟體 +視娘辣妹 +毛妓院 +骚妇掰B +超级乐者 +战牌 +ur +轮大 +江湖 淫娘 +yuming +法$$侖 +鸡歪 +tw +教你怎样延迟射精39岁以下禁免费淫电影a片 +仙境传说 +毛鸦片渣 +不玩了 +骚妇掰b +免费A片观看 +小穴被插的好爽啊 +毛换妻 +和妹妹肏穴 +成人情色导航 +阴户抽插 +抽插34岁处女妹妹淫叫不断 +鲍鱼 +现代学生妹操屄水平真是高 +我上小姨子小说 +拔屄 +唐捷 +阴道抽搐一阵暖流自子宫深处涌向龟头 +抽插21岁处女妹妹淫叫不断 +聚友网络 +sm +淫秽 +拉法叶舰 +sf +观看淫电影 +新疆国 +國家分裂 +梓霖 +sb +小女嫩穴 +把舌头伸入jiejie的 +林伟 +新疆國 +墮淫 +日本素人 +午夜激情美穴贴台湾性福联盟 +手记注册日韩5006部激情电影 +ro +全國人大 +蘇秀文 +诛仙 +毛信息产业部 +毛四川独立 +ri +再奸 +法惀功 +發@淪 +爽女美图美搜性感图涩界成人电影网小小鸟绝色meinv写真图 +lisishijian +轮奸 +毛透视软件 +國民黨 +色慾 +杨周 +何加栋 +肛屄 +肉便器 +屁眼 +毛罗 干 +金发表姨花蕊,少女的狭窄洞口 +System +全身一阵颤抖 大鸡巴 +fuck小肉粒 +騷母 +日gm +淫女乱搞免费三级片 +伸入jiejie裙内 +騷比 +qb +archlord +毛台办 +法$$倫 +毛恶搞晚会 +法囵功 +强奸23岁处女全过程/*妹阴毛小穴 +天安门残案 +大雞巴 +二奶大奖赛 +毛阴道 +李师傅 +色情 +dick吕秀莲 +配合着蜜洞内肉棒的抽插 +我咧干 +恐怖主義 +五月天成人激情网站 +xia yi dao +mannweib +fuck新华社 +獨立 +毛敬国神社 +干x娘 +又大又粗的肉棒 +又深又紧的穴 +抗战 +奸杀美女大学生 +fuck我操你 +毛他妈 +抗戰 +顶进少妇的花心 +疯狂的抽插起来 +makinglove +搶 糧 記 +大麻树脂 +每天24小时循环更新的免费色情内容 +rxjhwg +激情免费电影 +大鸡巴插进她肉洞里 +騷洞 +51xp。com 电影免费 +成人小说 SM 做爱 +肉棒顶的人家小穴好痒 +乱伦之淫骚穴 +操你妈 +传奇3G +netbar +傅鐵山 +姜春云 +招妓 +口含鸡巴 插入阴道 +噗嗤一声滑入阴道 +浩天银科 +窃听器材 +tantra +操陈晓宁 +群奸輪射 +色meimei淫穴 +宋慶齡 +女添男精狂射图 +免费淫色情电影 教你怎样延迟射精18岁以下禁免费淫电影a片 +hun +手记注册日韩5032部激情电影 +达芬奇 +宏象 +六四回忆录 +洪哲胜 +淫荡娇妻打开双腿 +奧巴馬 +夜情 +毛林彪 +抽插54岁处女meimei淫叫不断 +我把艳姨给干了 +tiang tang +口含龟头 +神出鬼没!3个丁字裤辣妹到处袭击肉棒(中文字幕) +妹妹的小穴……舒服死了…… +夫妻多p +caob +肉棒噗嗤一声滑入阴道 +亚洲免费黄网 +阴茎插入少妇阴道 +点击这里试看美女做爱现场 +日本淫穴电影 +成人影院 激情影院 +电视流氓 +香港激情图源成人色情论坛脱衣meinv做愛 +喇嘛 +體奸 +u r靠 +game MASTER +海盗时代 +我和姨在车上干 +赌马 +性生活 +威而柔 +免费淫奸女A片段试看 处女第一次阴道做爱全过程(全套图片) +heatproject +日你爸 +法十轮十功 +大鸡巴插进小穴 +毛你老味 +梅花網 +海明威 +kuaik +混蛋神风流史 +做爱视频 +fuck台办 +无码淫女 +审计署 +教室里淫乱狂搞 +pute +初流出!ロリプリ +人美乳甜屄嫩操起来真爽 +性交内射 +操大逼 +发~~纶 +GC365 +麻醉乙醚 +毛十年动乱 +默哀 +夜色聊人 +处女第一次阴道做爱全过程(全套图片)免费淫电影a片 +鑫諾 +毛血腥图片 +自焚 +62xp。com 电影免费 +毛片空姐的嫩穴裸体明星夜总会小姐贴图 +rxjh +Crazy Fuck : Miki Uehara 上原美纪 +MK 星云 +操逼 +吹簫 +免费淫奸女A片 +an hei zhi men +情色聊天室 +淫奸医生 +vrtank +系統消息 +联易 +希望之声 +淫电影//现场强奸20岁处女扒开小穴清晰做爱阴道裸体图 +GAME master  +断电 +廉政大论坛 +性感meinv淫穴 +经济社会理事会 +成人性交视频 +毛回教 +追查國際 +騷媽 +小唇被他的嘴巴包裹住 +105bb成人小电影 +骚乳 +san guo ce +性戰擂臺 +淫奸女电影直接试看 +删号靠 +性交图 +插的妹妹好爽啊 +性交圖 +發^侖 +voachinese +一夜性网 +露乳 +洪 传 +meng huan zhi xing +淫电影论坛 +凱圖科技 +儿子顶到妈妈的花心 +法仑功 +淫奸meimei电影 +rivals +互友财富 +輪功 +人體攝影 +处女第一次阴道做爱全过程(全套图片) +luan +严家祺 +子宫口吮吸着龟头 +fuck新闻办 +回民人吃猪肉 +吸精 +fuck卫生部 +淫色网站导航 +淫蜜 +小泉纯一郎 +齊藤亞樹 +参事室 +毛反政府 +乱伦之淫穴网 +又粗又长的大肉棒 +泳衣+丝袜~让你销魂舒畅 +免费电影吸精痴女 +短信猫 +大 参 考 +强奸22岁处女全过程/*妹阴毛小穴 +未满19岁的请自行离开 ! +总统的讲话 +淫奸jiejie电影 +痴女/淫乱 看護婦/女医 剃毛/パイパン!【AVI/723MB】 +姐姐的小穴 +情色BT +fag +kang zhan +张榕明 +發論 +洗肠射尿 +品色永远免费淫电影 +赤裸 +他嗎的 +射顏 +激情视频女半夜播放成人节目免费裸体视频 +林心如做爱网有激情自拍裸体图片 +脚交 +淫奸电影 淫色猎暴淫电影 射雕淫女传 风骚小龙女 美女淫女图-小龙女淫女俱乐部影 在线淫电影 +仙侶奇緣 +北美自由论坛 +英雄online +删 号 +香港 +发@@论 +毛干死你 +兩國論 +放荡 +狂插 肥穴 +淫奸小姨论坛 +检察院 +啊……快插啊……小屄要美死了…… +射颜 +争鸣论坛 +公务员工资 +充值 +小姨子她饱满乳峰上的粉红乳晕,金发表姨花蕊 +meimei的淫穴被龟头顶住 +发抡功 +免费注册看免费电影通道 +傅杰 +毛反封锁技术 +penis +掰开少女穴 +肉丝裤袜 +黄易群侠传 +你妈比 +阴沟 +舔我的龟头 +騷妹 +大鸡巴插进妹妹的小穴 +騷妻 +骑他 +大鸡吧插妹妹淫屄 +張 偉 國 +Angel Cosplay Vol。 2 新村爱加贺美由贵 +Tora-Tora Platinum Vol。8 宫泽Keito 完全无修正第二弹 +滕武 +發^倫 +18岁少女破处 +Red Hot Jam Vol。6 露出初体验~Chia +插後庭 +毛伊拉克 +U R靠 +非常漂亮的日本美少女,日起火! +阴水 +欠日 +工作人員 +胡嘉 +50xp。com 电影免费 +騷女 +鹿城大型黄站 +毛老毛子 +龟头用里插入阴道 +装逼 +re xue jiang hu +抢尸 +娄义 +大鸡巴顶进妹妹的花心 +他娘的 +肖强 +押大 +运营人 +毛侨办 +免费淫电影a片 +淫蟲 +早洩 +屄屄特寫 +賣騷 +成人贴图区 +好大的阴户 +李维汉 +裸体插淫穴 +淫驴屯 +免费淫电影吴宗宪搞笑语录(28禁看) +武力统一 +欧美清晰打炮淫乱人妖淫乱图 +shemale +rxwg +gameMASTER +吹箫 +解放军镇压 +三国群英传 +發$$掄 +猛插小护士骚穴 +奸幼 +preteen sex preteen sex +long zu +曹建明 +李红痔 +CAO +穿著PE校服 +成人夜话 +法仑共 +骑你 +法仑公 +共青团员 +砍翻一条街 +aszol +免费淫奸女A片段试看 瞄準她的肉穴插了進去…… +免费成人图片 +放蕩少婦賓館 +gamemy +中国最淫的免费淫图图 +毛天安门一代 +滚那吗老比 +顺着大鸡巴湿淋淋的流下 +媽的騷穴被你插得爽死了 +a片 +清晰內射 +工作人员 +激情玩淫穴电影 +亚洲乱伦之淫穴 +妹妹吸精 +国内动态清样 +骚B贱 +6。4 +贱逼 +阴毛 +浴室乱伦 +毛廁洞 +酥穴 +东热RQ大乱交2007 +舌头舔弄着小穴的内壁 +成人網站 +亚洲互动 +情色艺术天空 +激情淫色下载 +江口美貴 桃咲あい 早乙女みなき 雨宮せつな +欧美成人贴图区 +骚 +黑鲍娇 +插入小姐的嫩穴 +追查国际 +成人色情图片 +台湾成人激情视频聊天室 +免费午夜艳情电影 +欠操 +淫奸………啊 好舒服 +肉慾 +毛伊朗 +抗震救灾 +互舔淫穴 +大比 +抗震救災 +狂插少女的嫩bb +guild wars +潮喷 +我和妹妹肏穴 +陰核 +出售此号靠 +賀龍 +和婶婶做爱 +香港免费黄色淫乱电影 +草擬媽 +淫奸jiejie穴 +eve +毛乳 +無碼長片 +少妇房中自淫,和两勇男玩15P,操得直叫爽 操日本淫女穴 +发~轮 +幹你妈逼 +日本黄色三级短片 +少妇贴图穴论坛 欧美淫色贴图区 +舌头舔着阴核 +强奸17岁少女全过程 +性爱 电影 +午夜免费视频激情聊天室 +fuck外专局 +马凯 +毛基地组织 +……好舒服 舔穴 +教你怎样延迟射精34岁以下禁免费淫电影a片 +干他 +女幹三虧 +妹妹 +中国之春 +超美女优MUGEN EX Vol。 7~浜崎ひめ +transsexuell +發@@綸 +騒 +明星裸体写真图 美女网络视讯三点 +搶劫犯 +法~轮 +淫妻爱好者 +盐酸二乙醯吗啡 +杨怀安 +法$$沦 +大陆免费黄站 +新语丝 +抽头 +毛新疆独立 +騷 +免费淫电影下载地址 +风骚小阿姨 -新闻 +事实独立 +欧美激情穴淫奸 +日本女优 +曹你 +芸能人使い捨てM奴隷DX 聖乃マリア nike 新片! +斑竹 +星際家園 +性奴會 +淫奸meimei论坛 +超爽艳图 +liu xing hu die jian +阎王 +美女视频短片 +臺獨 +法~輪 +毛姣西 +残忍的虐待强奸美丽的淑女 +釋迦牟尼 +放蕩 +洪 傳 +黑社會 +压迫 +联梦 +adult +淫蕩 +母乳と巨乳と淫乱の完熟物語 +那吗错比 +扬振 +潮噴 +干X娘 +fuck私服 +强硬发言 +肉棒插入少妇的阴户内 +台湾青年独立联盟 +温 元 凯 +朱勝文 +肉棍狂插 阴精 +哥哥淫奸妹妹论坛 +法菕功 +干你 +18男人momoB +抽插25岁处女meimei淫叫不断 +践踏中国女性 +輪奸大美女 +龟头通过子宫口直抵花心 +金玉天立 +抢劫犯 +肉棒插入阴道 + 瀬咲るな +g。m +毛叫小姐 +meinv嫩穴 妹穴 亮穴 女人穴 +母亲 +北极冰 +誘姦 +mabinogi +嫵媚挑逗 +meinv与猪性交电影 +水滸Q傳 +亚洲成人激情淫穴 +暗黑之门 +妹妹小穴 +淫奸姐姐论坛 +【亚洲/无码】【极品荡女-宝乃ありか 完結版!】【WMV/358MB】 +幹他 +夜色淫女导航 +嫩穴 狂 插 +操操你 +效忠天皇 +抽插小淫穴 +迷幻藥 +大鸡吧顶进小穴 +少妇房中自淫,和两勇男玩6P,操得直叫爽 操日本淫女穴 +淫妹妹成人情色论坛 +毛连战 +舔吮 乳房 干小穴 +幹您娘 +曰你 +開苞 +吞精 +情色成人视频聊天室 +韩国激情淫色贴图 +pk1937 +淫獣圣戦 XX+圣獣伝 ツインドールズ +肉棒插入meimei的肉缝 +本站10016多部激情电影全部免费试看 +毛洪兴 +去氧麻黄堿或安非他命 +斷电 +毛靖国神社 +紫瑞专业 +毛民政部 +大胆少女 +毛生鸦片 +妳娘 +武林群俠傳 +矽穀動力 +计生委 +张伯笠 +淫荡女生 +地球文明 +淫驢屯 +嫩穴meinv挖嫩穴淫女嫩穴俱乐部 +老瘪三 +和阿姨做爱 +一党专制 +操淫荡少妇穴 操淫荡妹妹穴 操淫荡姐姐穴 +和jiejie肏屄 +美腿 +幼交 +陈毅 +Offgamers +插入姐姐蜜穴 +聚梦 +掌上灵通 +错逼 +淫穴摩擦龟头 +fuck骚 +新华内情 +我就色 +雞女 +操操他 +大鸡巴┅┅太棒了 +笨逼 +淫meimei成人情色论坛 +银行帳号 +鸡巴蜜穴高潮 +雞奸 +毛人民广场 +換妻大會 +亚洲激情影院论坛 +淫虫 +六四屠城 +江油余震 +幹的爽 +我妳老爸 +阿沛 +歡樂潛水艇 +百家性超级淫色图片 +操穴贴图 +淫虐 +张廷发 +免费a片日本淫电影 +被干的喷水的高清图 +刀OL +打砸抢 +牛逼 +我的性启蒙老师 +毛XX +淫色电影网站  +毛推油 +奸情 +滝沢优季 Prisoner Of Love绝爱的监禁牢狱 +…用力干…嫩穴紧插 +东北风情熟女之惑 +阴唇湿润小妹舔乳 +破处 +granado +付申奇 +毛卖党求荣 +大 參 考 +meinv潮吹 +盛华仁 +毛社会主义 +阴穴新玩法 +台湾自由联盟 +fuck孙文 +操淫荡护士 +傻屄 +中国分裂 +淫民激情文学图库专题 +奥巴马 +法**倫 +抽动肉 +現金交易 +超级淫图 +發~侖 +16dy-圖庫 +小穴流出汁液 +毛石进 +screw +老癟三 +陰戶 +日本激情图库脱衣裸体做爱 +手伸到儿媳妇下体抚摸嫩穴 +淫民俱乐部日韩激情片 +情色导航 激情爽电 +調理勞務系 +激情视频在线 +淫妹妹电影论坛 +被奸淫的女教師 +巨乳俏女醫 +ggq +免费淫区隐蔽入口 +雅典娜 +大中华论坛 +深夜進入少女家中玩強奸 +meinv性交极品大片 +玉蒲团玉女心经 +vip在线成人电影 +*法*轮*功* +qq音速 +星蓝妹妹 +fuck洗脑班 +發~倫 +军事委员会 +色中色网址大全 +淫荡 +TABLE +雞吧 +gamegold +想上你 +拉凳 +李金華 +minghui +神話R。Y。L +五星紅旗 +yifeng +18歲淫亂 +迷幻药 +法**侖 +小穴被我操的红肿 +肉棒肉洞 肉缝 +代链 +人民大會堂 +毛强奸 +车仑 +毛烂屌 +日本淫色动画贴图 +巨奶 +好嫩 +女尔 +妈妈 +鰢 +SM援交 +www。ccwcc。cn +溫比 +多维网 +潮吹 +激情在线 +蔣中正 +大肉棍… …干的 …好舒服 +偷情男女 +后面插入处女肉穴深处 +你娘卡好 +laqia +女尻 +情色天堂论坛咪咪情色论坛 +Arisa Kumada +鹿城黄站bt +快活林情色网 +入穴一遊 +淫水翻腾 +激情淫影片 +367成人网站 +女屄 +毛烂屄 + 夏树唯 +混沌诀 +gcd +毛鸡叭 +淫荡的小穴 +阴核 +dh315 +meimei黄站 +*李*洪*志*靠 +淫奸妹妹电影论坛 +色欲 +啊无卵 +酥痒 +蒂巴因 +磨得人家小穴……好用力……好酥 +弟弟淫奸jiejie穴 +免费在线收看淫色电影 +肏又紧又嫩的穴 +美女走光 +日你老娘 +Tokyo Neko ATN-002 東京猫 Vol。 2 星川はるか +官人我要2 +做爱图 +法**伦 +毛私服 +拉手冲 +清晰内射 +干你妈B +台聯 +饿比 +免费a片 +gay +台联 +流星蝴蝶劍 +乱伦熟女网 +gan +叶群 +中国游戏中心 +母亲の结婚生活完全版 +cheng ji si han +17岁处女小阴唇张开 淫水流出图强奸免费淫电影 +無修正 +陷阱超人嘩嘩曼 +雞叭 +大卵子 +奶子 +毛宋楚瑜 +法**仑 +龟头已顺利挣开她紧合的阴唇 +大纪园 +处女穴 阴唇 肉缝 +做爱自拍 +毛毛贼东 +龟儿子 +机机歪歪 +毛破鞋 +吸吮着红嫩的乳头 +月经不调 +shengda +来回去舐她的小穴 +官人我要1 +kele8 +小卵子 +売春婦 +情感视频欣赏 +宋美齡 +社会主义 +毛meimei淫色 +bjzc +法黁功 +舌尖不断在肉缝里上下舔着 +激情论坛 +駛你爸 +性爱图片 +亚洲激情淫洞 +紅衛兵 +欲火焚身 +酥癢 +绵阳 +fuck驶你爸 +肉棒触碰前面的肉穴 +幹死客服 +火辣寫真 +妹妹的淫穴被龟头顶住 +宋美龄 +毛外交部 +jiejie的小穴 +毛毛厕洞 +严方军 +金毛学生妹 +封神傳說 +林心如做爱网有激情自拍裸体 +苯甲基芽子堿 +女优爽图 +乱伦淫穴 +干你妈b +学生爱国运动正名 +舌头伸到妈妈的小穴里 +yuanming喷你 +妹妹阴毛 +和熟睡的妹妹做爱教你一手 +中廣網 +激情淫色电视 +毛日本RING +淫奸小姨子电影 +segame +美女性生活贴图 +马三家 +热 站 政 论 网 +鸟g M +看牌軟體 +生奸内射 +調教虐待 +毛晚年周恩来 +日本激情片论坛 +妹妹的嫩屄 +一九八九六四 +猪容基 +气性坏疽病 +毛塞你娘 +操陈希同 +流星蝴蝶剑 +激情淫穴小妹 +换妻杂交 +戳那吗比 +胸垫 +阿姨和我乱伦理小说 +舌头舔小肉縫 +南蛮子 +张筱雨 +不良詞語@美乳女神RINA(中文字幕) +毛温加宝 +姐姐的嫩穴 mm嫩穴 +fuck上妳 +鸡巴受不了了┅┅喔┅┅好爽┅┅我要泄了┅┅ +近亲相奸 +插淫女小穴 +你老母的 +香港情色俱乐部 +毛温总理 +創意鷹翔 +戴晶 +李 总 统 +激情視頻 +群奸乱交 +钱 国 梁 +國家主席 +日本成人淫色DVD +fvc +聖母 +口肯 +无码精选 +电车之狼 +Shine +大陆黄网导航 +qq自由幻想 +naked naked +绵陽 +鸦片渣 +你全家 +卢福坦 +a片试看 +fy0 +18dy粉红色高跟鞋 +拐卖 +15年纪念日 +毛原子能机构 +jb靠 +吃精 +本站10018多部激情电影全部免费试看 +毛干你妈b +母子做爱 +早泄 +成人a片 +戒急用忍 +西藏問題 +密穴贴图 +fv( +高畫質~ 超絕美貌社長秘書 佐佐木渚沙!【WMV/102MB】 +女幹 +淫B浪女 +释欲 +成人激情导航 +她的阴道好紧啊 +激情影片网站 +fuc +po tian yi jian +白浆四溅 +采花堂 +扒开她的嫩穴 +fuk +免费在线激情电影 +放荡少妇 +女干 +淫腔 +19岁女生主动让男生开苞全过程◥免费黄色电影 +帕巴拉•格列朗杰 +毛多维社 +毛鸡八 +日本成人乱伦 +龟头用力刺入淫穴 +汪东兴 +姐弟淫乱小说 +男女蒲典 +d7se淫色穴图片下载 +曹刚川 +西藏問题 +又大又肥的屄 +淫奸jiejie meimei MM 姨妈 舅妈直到流水 +三K黨 +cdjp李鵬* +毛火棒 +破坏 +fu( +我和jiejie肏穴 +男人本色 +雪白的屁股对着肉棒 +拳交 +舌头舔小肉缝 +仙界傳 +无码无套 +美女 成人 +鸡 +鸠 +毛meimei免费电影 +姚文元 +釋欲 +鸨 +淫荡校妓 +傻子 +六四回憶錄 +毛江择民 +常劲 +馬克思 +CNN +鸡掰 +轮公 +灌滿精液 +电影免费试看片 +巨屌 +暴动 +planetside +BnB +淫奸护士小说 +草你 +色站排行导航 +色女免费黄色小电影 +輪奸 +欢欢娱乐时空 +如此大的肉棒插的小穴快不行了 +发@@轮 +Shit Shit +毛他爹 +soul ultimation nation +少妇被操穴 +Kamikaze Premium Vol。 25:特級神風~榊彩彌 +省長的兒媳婦 +又鸟女干 +毛法轮功 +太子党 +阴道好紧插起来那真是爽极了 +騷卵 +阴茎插入肉洞 +海盜王 +美女主持26小时全天激情热舞 +免费裸女视频聊天 +日死 +看高潮屋 +褲襪 +輪姦 +少年阿宾 +毛妈逼 +四川獨立 +情色成人论坛淫图导航 +巨炮兵團 +無盡的任務 +天暢 +紧紧的小穴 +huan ling you xia +絲襪美腿、痴女、女同 +16dy-图库 +GAME +赛她娘 +回民吃豬肉 +搏客Online +菜B +18dy免费 +新絕代雙驕 +淫色 +党卫兵 +fku +姐姐被插的好爽 +14岁幼女B嫩阴 +耻辱轮奸 +flg +民主黨派 +大东亚共荣 +美丽女教师的性经历 +小淫女 +毛江八点 +熟女家政妇 山本ちづこ +厕所盗摄护士jiejie性感美腿图 肉丝美腿艳情淫欲 +巨炮兵团 +亚洲成人电影 +毛斯大林 +妓女 +弟弟的肉棒好硬啊 +抽插41岁处女meimei淫叫不断 +智凡迪 +毛监听王 +抽插19岁处女meimei淫叫不断 +偷拍 +暴動 +鸦片液 +超级舞者 +周天法 +摇頭丸 +支持達賴 +淫妹妹成人娱乐 +蔣樹聲 +可爱卡通小穴 +插的妈妈的小穴好爽 +海盗王 +红灯区 +日比 +免费在线淫电影 +毛新闻出版 +fuck鲜族 +爛B +嚴雋琪 +欧美淫奸女直接试看 +肉棒插 淫水 +毛人民大会堂 +姐姐和我乱伦理小说 +大煙 +毛红卫兵 +黑马@meinv全身神秘黑让你爽到眼框黑 +民意论坛 +国研室 +又深又紧的阴户 +魔幻森林 +风骚小女孩湿身露体 +fuck上你 +贱女人-淫护士 +大陆淫乱meinv图图片 +逼 +在线播放a级电影 +淫奸小姨子论坛 +肉棒直插花心 +共党 +qq幻想 +抡功 +免费淫电影吴宗宪搞笑语录(26禁看) +北韩 +全 国 两 会 +新西游记 +恥辱醫護免费下载 +扒屄 +swdol +高俊 +卖逼 +重生 +勃不起斯懦夫 +江贼民 +肉棒插在阴道里 +給你爽 +插小穴射了 +操护士穴真爽 +温B +法$$抡 +阴茎被小穴紧紧包住 +zhengqing +冒险岛 +趙紫陽 +抢劫 +母子奸情 +奸染 +鸭店 +欠干 +毛多维网 +cronous +发~~沦 +温b +共军 +欠幹 +骸卒 +姐弟激情淫乱 +like999 +xia ke tian xia +淩辱 +夏赞忠 +男人看的猛爽电影 +手记注册日韩5026部激情电影 +kuai le xi you +尉键行 +法*轮 +毛莫索里尼 +喷精 3p +法@@論 +菜b +qqtang +sanguohx +清华网管 +性虎色網 +发**仑 +拉丹 +洗浴间爽奸白嫩美乳少女 +姐姐的嫩阴户 +5kuai +放蕩少婦 +激情性爱电影观看网 +什么什么大冒险 +天安门一代 +毛泽东 +ㄙㄞ你娘 +嫩穴任我插 爽 +極品波神 +毛东突暴动和独立 +婚外恋 +毛系统 +毛几届中央政治局委员 +huo xian ren wu +共青團員 +台湾盲人美女在家疯狂做爱 +巨商 +毛靠腰 +发**伦 +小穴夹着肉棒摩擦阴道 +变态小日本街头强制脱衣最新加强版多片 +极品成人3gp +傻B江核心 +jiejie和我乱伦理小说 +我操 +淫の方程式 +肉洞 肉棒 肉缝 +群奸亂交 +月卡 +人 民 內 情 真 相 +洗着鸳鸯浴操屄真惬意 +鹿城最新娱乐bt 色情365 +re xue ying hao +天下无双 +狂操 插 干 老板娘 +f u c k +mm激情穴贴图 +騷批 +毛鸟你 +tian zhi lian yu +毛法功 +本站10011多部激情电影全部免费试看 +粗长的大肉棒 +百家性淫网站 +官方工作員 +qi yu +sheng zhan +溫加寶 +苏家屯 +三個呆婊 +美女电影 +100bb成人小电影 +淫逼 +shu ma jing ling +昱泉 +胡平 +啊……阿姨要洩了…… +吗b +中宣部是中国的艾滋病 +亚洲激情淫色电影 +台灣獨立 +精液射入穴中 +张闻天 +哈批 +淫荡妈妈骚姊姊 +阿拉 +奸暴 +塞你老师 +マーメイドになった「恋から」ギャル。岡島優里(全编) +操出售假币 +淫淫电影 +鋼甲洪流 +18岁 青▲学院中学1年生 +鹽酸二氫埃托啡 +luan wu tian xia +处女开苞 +xizang +色网阴道特写强奸22岁处女全过程 +阴道里的大肉棒用力顶着 +生奸內射 +89动乱 +毛伱妈 +淫奸女图片 +百家性大型黄站妹妹 +Tokyo Hot n0249 : 南丽美 菊攻无限中出39连発 +用力扣进小穴 +官方工作员 +环保总局 +hanbiton +你她马的 +地下教会 +毛卖卡 +fuck威而柔 +狂插少妇穴 +装屄呢 +shen qi +fuck水去车仑 +Queen8 社长秘书のパンスト +劳动保障部 +毛售软件 +共鏟黨 +亲哥哥……妹妹的小穴……舒服死了…… +大龟头顶住花心 +林心如掰穴自拍 +笨蛋 +花柳 +法^論 +錢 達 +聊齋艷譚 +fuck台湾党 +本站10001多部激情电影全部免费试看三天 +胡耀邦 +迷歼药 +胡錦涛 +王昊 +文胸 +颜色革命 +粉屄 +精液直射入她的小穴深处 +共匪 +阝月 +塞你老師 +拉皮条 +ttmd +qi ji shi jie +少妇房中自淫,和两勇男玩2P,操得直叫爽 操日本淫女穴 +毛美国佬 +楊震 +李登柱 +我日 +免费在线看淫电影下载 +鹽酸二乙醯嗎啡 +淫奸女护士电影 +插如妈妈肉穴 +肉棍 +华夏Online +手指拨弄着穴口 +劳+教+所 +肉棒 +傻逼靠 +屌西 +淫贱 +抽插22岁处女妹妹淫叫不断 +抵制 +骚浪人妻 +男女交欢 +你操得我更爽 +成克杰 +淫贼 +儿子顶到阿姨的花心 +长身丝袜美女~赤く烂れたマンコが痛 +操小姐b +额尔德尼 +如果你未满23周岁请自觉离开。 +鈤 +恥辱醫護电影在线观看 +hai dao wang +痴meinv醫生松島 +獲救 +刘国凯 +成人A片 +法@輪 +淫货 +男女交歡 +法^^輪 +史玉柱 +無碼絲襪 +阴道里嫩肉把鸡巴包得紧紧 +cnd +政府软弱 +塔利班 +堂品色 永远的免费色堂永远免费 +陈宣良 +妹妹做爱 +a$$hole +大肉棒深深地插 +你马的 +ustibet +教你怎样延迟射精30岁以下禁免费淫电影a片 +杨得志 +聖火 +歡樂城 +毛酱猪媳 +我该死视频做爱 +奸淫护士 +dtfy +7。22 +suck你妈的 +少妇野外淫穴电影 +皇軍 +法@轮 +法^^轮 +毛民航局 +8岁女生主动让男生开苞全过程 +毛董文华 +操你媽的 +江擇民 +剑侠世界 +毛天安门档案 +溫總理 +她NND +hai zhi yue zhang +丁香成人论坛贴图区 +免费淫色meimei电影网 +小逼 +濫交 +淫貨 +姦夫淫婦 +插入阴道里抽插 +发纶 +二B 帝國 +人 民 内 情 真 相 +身寸 +援交自拍 +安全隱秘 +美女出租车内强行进入 +二B 帝国 +杀人 +淫色影院 +婚外戀 +胡紧掏 +孙家正 +连线机 +毛蒋中正 +升达 +bao皮 +操宾周 +吗的 +55xp。com 电影免费 +毛瘸腿帮 +毛国家主要部委 +暴徒 +淫賤 +小穴的淫骚香味┅好爽 +亚洲淫图 +超級舞者 +兽交 +renewal +鸡店 +法^论 +如来 +無碼做愛 +腾讯 +骚女叫春 +程铁军 +成人午夜场 +dong fang chuan shuo +孟建柱 +色97爱 +毛萨达姆 +fuck售ID +fuck驶你母 +李 总 理 +淫女小电影 +晚年周恩來 +黄色情挑艳情小说网骚meimei成人论坛 +meinv嫂子的小骚逼 +法$$掄 +售号 +毛计牌软件 +裸露自拍 +毛是鸡 +Tokyo Hot n0252 : 原田友美 高飞车美人教师精液轰沈 +腳交 +奸一奸 +丫头养的 +ADMIN +wizardsoft +超淫荡丝袜meimei +傻B靠 +做爱 +雞八 +双鞋的故事 +自拍寫真 +共產黨 +美国之音 +插的妈妈好舒服 +帐号 +qi ji +激情影视 +教你怎样延迟射精25岁以下禁免费淫电影a片 +毛国资委 +毕加索 +fuck性交 +大東亞 +哥哥用力舒服死我吧 +tampon +乱伦小说 +b样 +法@@论 +肉欲 +vrtank +外专局 +暴干 +chuan qi +Admin +可愛虎牙學生妹 +政變 +知的障害 +滑湿小屄洞 +如果你未满20周岁请自觉离开。 +發輪 +MADELOVE +无码 +鎷 +日本成人激情短片 +李長春 +baopi +免费成人meinv +舔 b +美女主持24小时全天激情热舞 +爛逼 +王超华 +可哥精 +和meimei肏穴 +小骚屄儿meimei +欲女 +饿b +统计局 +王 秀 麗 +插穴 美穴 ……好爽 +淫奸女护士 +毛迷魂药 +meng huan xi you +八 仙 +石戈 +8 仙靠 +小穴流水妹妹手指插 +波佳达 +免费免注册淫色电影 +成人免费黄电影 +登辉 +饿B +urban-rivals +厦门大游行 +骚卵 +1989 事件 +手记注册日韩5004部激情电影 +激情淫 +生徒胸觸 +手指不断在肉穴扣弄 +毛林业局 +暴幹 +生徒胸触 +zirui +姐姐的小穴被大鸡巴插得好舒服哟 +无套肉棒浓稠内射漂亮屄 +邢铮 +操你老妈 +八九 +群p +尉 健 行 +用舌尖在我的肉棒上舔 +FUCKYOU +顏騎 +嫂嫂淫穴 +fuck外\挂 +受精 +batard +毛干你妈逼 +東突暴動和獨立 +集会 +鸠屎 +抽插 磨蹭 穴 B 逼 +媽個B +大陆鹿城 +和meimei玩插穴 +嘻遊中國 +钱达 +哀悼 +1989#天安门 +骚包 +售卡 +你老母 +藏婦會 +血洒天安门 +性器肛门~原千寻、桜井 +G m +天浴 +x到噴屎尿 +成人18免费电影 +腾人 +zhongguohun +毛她妈的 +姚月谦 +博讯 +色狼 +購金 +强奸19岁处女全过程/*妹阴毛小穴 +G M +胡錦濤 +Tibet独立 +天下貳 +毛花柳 +毛军事委员会 +軍妓 +毛小肉粒 +垃圾游戏靠 +擠母奶 +妈妈的阴道好紧啊 +成人午夜場 +saobi +亚洲激情成人电影 +东洋屄 +天安门母亲 +群P +无须注册淫奸小电影 图片 +插小穴meimei直流水 +鸡吧菊花穴 +騾幹 +江西大余池江中学女教师(绝对真实)」 +援交妹 +强*十八岁美女护士看完保证你打飞机免费电影 +色猫 +月經不調 +木子论坛 +抽叉姐姐 +暴奸 +fuck傻B +法论公 +幹你媽 +抽插45岁处女妹妹淫叫不断 +法论共 +老师干的我好爽 +辽宁女 +台湾成人黄色网站 +Fuck You +安全局 +八仙 +轻轻地抽动著阳具 +妈批 +美乳艷娘 +TENGREN +龟头紧顶她的子宫口 +铀 +發**倫 +亂倫熟女 +大字报 +中国人民解放军 +又嫩又紧的屄 +柯庆施 +操你老娘 +何候华 +黄克诚 +亚洲激情淫电影 +李 祿 +法十輪十功 +美少女FUCK限界大挑戦 +f a l u n +李长春 +PUSSY +信長之野望 +李 禄 +母子乱乱论 +现金交易 +色色成人 +赛妳娘 +抽插42岁处女妹妹淫叫不断 +榮毅仁 +毛黑社会 +毛黑手党 +少女 被 插 +獸欲 +xin mo jie +妖美巨尻物语 - 风间ゆみ +碧香亭 +89运动 +美女主持脱衣 +(國產)視頻-网吧老板玩穴 +肉棒压着阴蒂 +少林傳奇 +毛天安门屠杀 +湿穴 +kai tian +偷拍美穴 +色情排行榜 色情导航 +教养院 +毛人民 +共产 +厕所盗摄美女淫穴 +点击观看*林心如做爱*色情电影*免费淫电影a片 +口内爆射 +日爽 +嫩鲍鱼 +淫奸护士电影试看 +午夜淫电影 +淫水自乐 +最新99bb)有名女优~松岛やや +戈扬 +美女直播做爱 +河利秀失控全裸+深夜成人節目 +都江堰 +DELETE +搔妹妹色站大全 +香港激情图源成人色情论坛脱衣meinv做爱 +fuck四川独立 +裸体贴图香港成人电影网 +可怜系新人美少女甘南三才 +激情淫色贴图 +做爱在线观看 +Kamikaze Girls Vol。29 铃房ありさ +江猪媳 +Red Hot Jam Vol。10 高树圣良 +骚屄儿 +肉洞 +成人性爱视频 电影 聊天室 +去你妈的 +疯狂jiejie淫穴 +Early Melissa Lauren +李志绥 +完蛋操 +鲁迅 +insert +gamemaster +馬英九 +燕玲论坛 +g m +集体性爱 +工力 +鸡巴对准柔软的阴肉缝沟 +肉棒的抽插……干的好爽 +毛乔石 +插meimei淫屄 +法~論 +用他的舌尖舔着我的乳头 +亚洲淫娃 +fuck外_挂 +jiejie和我乱伦理电影 +毛卖国 +SARS +sphincter +台灣國 +肉棒插入meinv的肉缝 +法论功 +西藏 +正悟網 +用你粗大的肉棒 +魅惑巨乳 +台灣国 +性保姆被雇主掀翻在高潮 +陈一谘 +fuck食屎 +達賴喇嘛 +日本RING +fuck台湾独立 +銷售 +强奸19岁处女全过程/淫妹阴毛小穴 +gangbang +毛刘少奇 +草妈 +本站是国家合法电影网请您用手机注册~! +两国论 +风艳阁 +大法 +人肉搜索 +教你怎样延迟射精31岁以下禁免费淫电影a片 +揉阴核与嫩肉 +风骚侍女 +天下贰 +ying xiong shi ji +猛戳阴穴 +腾仁 +大波 +MM屄 +插穴手淫 +毛蒋经国 +布什 +奸淫嫂嫂 +鸡巴 +腾任 +裸陪 +肉沟 +台独分子 +尸虫 +弟弟淫奸熟睡jiejie +小姨和我淫BB小说 +幹你娘 +护士掰开阴道插B +pao pao dao +跟meimei肏穴好舒服 +一夜性網 +李总理 +huan le qian shui ting +17game +小穴淫图 +少妇床上的激情 +顶进她的花蕊 +博訊 +天安门录像带 +牛魔王 +红十字會 +质检局 +一次可看四位meinv同床較勁很可愛的女主角 +骚穴淫液 +抽插19岁处女妹妹淫叫不断 +成人激情影院 +peng peng bang +淫西 +肉棒在乳沟来回猛抽 +哭夭 +吸精少女 +回民暴 +dpp +狂操丰满小姨穴 +明星淫圖 +帝國主義 +将肉棒对准她的穴口 +法^輪 +陰 +贱货 +三级电影网香港色情服务 +红楼美穴肛交淫图 +淫奸电影 淫色猎暴淫电影 +公车奸美女淫奸女电影试看。 +大鸡吧插又肥又嫩的屄儿 +Tora Tora Gold Vol。18 : 冈田さな Sana Okada +你大爷 +明星淫图 +欧美成人帖图区 +你大爺 +少妇房中自淫,和两勇男玩13P,操得直叫爽 操日本淫女穴 +狗操卖逼 + 菊地麗子 +李大師 +懶教 +操你妈靠 +成人自拍 +成人激情电影 +屁蛋 +大纪元 +小穴在上下套动 +丁字裤 +中国留学生--张丽 双插 +silkroad +操雞 +中华大众 +lei ting zhan dui +求救遭拒 +操朝鲜 +强奸少妇 +毛卖号 +发$$沦 +淫奸美女图 淫奸刘亦菲 +毛泽东靠 +鸡巴 嫩穴 嫩肉 +淫色貼圖 +法^轮 +多维社 +無套內射 +李大师 +强奸处女学妹,摄像机拍下强奸阿姨。 +胡錦淘 +幹你媽b +火线任务 +强*十八岁meinv护士看完保证你打飞机免费电影 +fuck信访局 +女学生拍我该死 +无界 +中國共產黨 +移动联通秘密通道 +精液射如妈妈的穴 +法~论 +淫師蕩母 +雞 +日本騷貨 +操达赖 +ボインお姉さんお色気修行! みさき優香 +艾滋 +人民内情真相 +省长儿媳妇 +日本激情淫色文章 +系统讯息 +大陆娱乐免费黄站 +多維週刊 +jin wu shi jie +大卫教 +蝴蝶逼 +激情聊天 +阿扁 +新天翼 +厕所性感meinv清晰淫穴 +17Game +性福联盟 +插那吗比 +日本领事馆 +隂 +信访局 +淫meimei电影 +新光明 +ever quest +名人大道 +毛美利坚 +利瓦伊汉 +滚那吗 +最强美乳初解禁 +歌华 +狂插meimei小穴 +去你妈 +hanbit +摸咪咪 +中国社会论坛 +曾道人 +美女主持25小时全天激情热舞 +毛太子党 +打野炮 +御の二代目 +毛退党 +gun gun qiu +陰屄 +那吗瘟比 +毛台湾狗 +淫电影网 +台盟 +淫乱小穴 +八仙靠 +免费秀聊视舞聊天网 +FLG 妈批 +原子弹 +私!服 +建设部 +中國性愛城 +戀愛盒子 +金枪不倒 +豔婦淫女 +李 總 理 +精子 +风骚淫荡 +Sex Sex +尾行 +手记注册日韩5033部激情电影 +wanwang +Party +欧美激情淫影院 +色女脱衣秀 +独立 +丰盈雪白的肌肤肥嫩饱满的乳房红晕鲜嫩的小奶头 +妈的骚穴 操 穴 逼 +操他妈 +毛你姥 +变态~幼男插嫩屄 +靠 +嫩穴【极品】阴蒂 +姘头 +毛马英九 +成人百強 +chao nv +毛黎阳评 +成人百强 +天游 +六合彩 +妓女自拍 +駛你母 +猪猡 +交換夫妻 +自治机关 +不用注册免费小电影骚b免费色电影免费 +fuck台湾国 +騷屄 +87bb成人小电影 +毛你娘 +萨马兰奇 +温元凯 +開發 +張立昌 +厉无畏 +wangyou99 +嫂狂欢隔壁小弟打手枪 +拉皮條 +免费裸体美女性交电影 +胡錦滔 +傻批 +滥比 +搔妹妹黄站 +网址情色成人大全 +监禁陵辱 +Pink Puncher)Double FACE +你姥姥 +帕巴拉?格列朗傑 +玉杵 +d f d z +愈快乐愈堕落 +传销 +法@@轮 +色情論壇 +Barefoot Confidential 46 +欢城 +你娘咧 +阴茎在殷素素的阴道里抽插 +Voyage +呆比 +恥辱醫護bt下载 +陈水扁 +偷歡 +干姐姐小穴 +投毒杀人 +牛B +fuck靠 +market +法(輪)功 +阴户 +meimei MM激情 +日王 +后备专员 +色情服务 +免费淫色电影 +輪公 +肉棒在阴道内抽插 +毛你妈 +花心成人论坛 +meinv性生活贴图 +免费成人美女 +特派员 +舔她小穴 +大家论坛 +正邪大决战 +世界经济导报 +法@@輪 +裝備展示 +肉棒狂插女人小嫩穴 +手记注册日韩5034部激情电影 +免费午夜爽片 +dse淫乱小说在线看 +舌头舔进阴道 +偷欢 +成人激情爽电影 +艳照 +她妈地 +强奸十八岁美女护士看完保证你打飞机免费电影网站 +梦幻国度 +自拍淫荡骚妇们的性福 +meinv下体淫水直流 +毛王震 +滿洲國 +幼女嫩穴 +六四參加者 +和两勇男玩37P +成人网站导航 +tian long ba bu +在线玩美美免费电影 +法$论 +新疆独 +GM001 +六四风波 +snk。ni8。net +黄菊 +cai hong qi shi +av成人网 +新生网 +扒开她的小穴穴 +氣性壞疽病 +张晓丞 +毛静坐 +biao子 +六四動亂 +乳此動人 +奴事件 +和两勇男玩38P +性交無碼 +admin靠 +滚那吗错比 +法*論 +免费淫电影吴宗宪搞笑语录(24禁看) +针孔偷拍 +熟婦人妻 +fuck新闻管制 +89動亂 +作秀 +插逼清晰图 +手机注册看激情电影 +piss +和两勇男玩39P +rfa +本?拉登 +毛meimei黄站 +米开朗基罗 +温暖湿润的感觉笼罩龟头周围 +本站10015多部激情电影全部免费试看 +核工业基地 +强奸轮奸meinv视频 +wowjingye +自杀手册 +愛圖公園 +集体淫 +鸡巴插进小穴 +两性电影在线免费欣赏 +手分开嫩肉缝 +90bb成人小电影 +肉棒插干她的小穴 +和两勇男玩33P +佛祖 +督察 +强奸41岁处女全过程/淫妹阴毛小穴 +chuang shi ji +狂插美女穴 +罗 干 +chui chui +台独 +郭盈恩挑战性交吉尼斯(对256男)直播全记录 +和两勇男玩34P +卡通动漫meinv淫乱 +mo li bao bei +抽插48岁处女meimei淫叫不断 +插烂她的小屄 +精液射在meimei的子宮 +六四之前 +猛插林心如小穴 +看完保证你打飞机 +肉棒插入美穗子的肉缝 +是雞 +和两勇男玩35P +群交 +粉红的的奶頭粉嫩的阴唇 +香港淫穴 +網捷信 +欽 本 立 +谢中之 +龟头挤进了姐姐的小穴 +花园bt亚洲激情区 +穴淫贴图女人穴贴图穴淫液贴图 +黃菊 +陰穴新玩法 +成人色网 +和两勇男玩36P +幼男做爱meimei做爱 +bi xue qing tian +AV成人影院 +刘俊国 +刘宾深 +毛英雄纪念碑 +教你怎样延迟射精37岁以下禁免费淫电影a片 +操meimei湿穴 +傷亡 +gu long qun xia zhuan +極品白虎 +嘭嘭幫 +amateur +fuck台湾帝国 +陈良宇 +殺手 +娇嫩的蜜穴 肉穴 +help +大鸡巴 干进 小穴 +张开双腿 菊花穴 +龟头挑逗花蕊嫩肉 +穿豹紋的美女,很有野性美。看她咬著肉根就可看出來。 +超級乐者 +大 中 国 论 坛 +十三點 +滥B +亚洲性虐 +手指还插在她的淫穴 +發^^綸 +公安局 +口味稍重 CD2 +社。会。正。义。力。量 +台獨 +毛军国主义 +鹿城黄站小说 +淫亂潮吹 +嘭嘭帮 +九霾 +性战擂台 +强*十八岁meinv护士 看完保证你打飞机 +走向圓满 +足球經理 +维护 +台湾午夜色情小说 +鰻の罪と泥鰌の罪とレズ陵辱 +免费淫奸女A片段试看 少妇扒开阴道图 +一起玩游戏网 +puneta puneta +rmb +操抽你丫的 +快插吧!┅┅快┅┅ +毛台湾国 +法$論 +走向圓滿 +亚洲电影区 +发~~抡 +六四运动 +浪妻淫女 +法制办 +車侖 +性交电影 +淫奸少女穴 +品色堂 +毛去死 +hero +日本骚货 +免费电影欧女乱欲 +白液四溅 +做爱激情小电影 +魔鬼曲線風騷女优青木玲 - FACE 68 +动漫色图 +最淫官员 +muhon +耶稣 +陽痿 +法(輪)功 +看完保证你打飞机免费电影网站 +毛三陪 +操小姨子穴真爽 +陈炳基 +高级卖淫女确实不一般 +黄色 +wowsupplier +肉棒插入美穗子的肉縫 +熟婦騷器 +minpaonews +推油 +用力操舒服死我吧 +肥穴姐姐 +亲爱的快操我的B +耶穌 +民國 +走私 +干出淫水 +騰訊 +欧美无套 +海科數碼 +肥美的阴唇 +Pink Puncher~美熟女淫乱乳娘~Erotica : 友惠 +美护士是男人操屄的目标 +民国 +月經 +da hua zhan guo +鮑彤 +抽插43岁处女妹妹淫叫不断 +怎样延迟射精26岁以下禁 +新生網 +肥嫩的阴部 +中國成人論壇 +网域 +xi you fu mo lu +阴缔 +鸡院 +成人淫伦 +淫荡女医生 +激情网站 +臺灣獨立 +realextreme +fuck傻比 +法~纶 +毛阳精 +鹿城免费黄站 +淫奸小电影 +手记注册日韩5009部激情电影 +南蛮 +怎样延迟射精19岁以下禁 +监察部 +我该死免费色情电影 +国土资源部 +周旋 +普贤 +就去誘惑 +东亚共荣 +操你爸 +紅 色 恐 怖 +AV-熟女 五十路 -故知新 -藤由美 53- +成人激情电影在线播放 +数据中国 +免费淫电影吴宗宪搞笑语录(23禁看) +激情淫洞网站 +龟头挤进了紧窄湿润小嫩穴 +免费淫*黄色电影a片 +吸吮肉棒 +新金瓶梅 +xin jiang hu +卖b +林心如毛片 +捅入meimei的阴道 +zhang chang +大*FA弟*子 +粉嫩粉嫩的小穴 +做爱淫图 +小幼女开处清晰大图 +阳精 +騷B +驶你公 +luan wu tian xia +鳥g M +抽插40岁处女meimei淫叫不断 +沾满了淫 +毛马卖马屁 +卖B +淫女在线看电影 +混乱冒险 +av成人电影网 +海科数码 +温逼 +徐建国案件 +顶进嫂子的花心 +色情激情电影观看 +奴役童工 +媽逼 +顶到妈妈娇嫩的花心 +成人激情网站大全 +抽插 …好刺激……好粗… +fuck天鹅之旅 +情色电影 +国家主席 +毛你妈的 +不用注册免费淫电影 +周鐵農 +本站10004多部激情电影全部免费试看三天 +鸡巴插小穴 +桃园蜜洞 +星际家园 +强制执行 女体崩壊~1 +淫奸女教师穴 +臺灣共產黨 +fuck小泉纯一郎 +發~~論 +中文情色网站 免费母子乱伦 +嗯┅┅嗯┅┅舒服死了……meimei又要丢了 +操吃大便 +小穴流淫水 +李登辉 +毛江贼民 +Homosexual +免费meimei黄色淫乱 +华夏II Online +祁培文 +法**抡 +清秀巨乳学妹校园内被轮奸 +毛温馨 +fuck天安门录像带 +Media +司马晋 +欠人骑 +美女嫩穴淫水直流 +F。L。G +人妻色誘 +毛卖财富 +南京大学法学院 +小比样 +插暴 +鹿城百家性大型黄站 +氵去 +gmworkers +她媽地 +乳霸 +張 宏 堡 +肉棒挤入蜜穴 +淫水涟涟 +他妈靠 +六四之后 +交配 +柔软红嫩的小阴唇 +小嫩雞 +毛国民党 +淫奸姐姐穴 +塞你母 吸毒 +豬頭 +Government +妈妈屄好痒呀 +愛滋病 +啊… 你弄的我好通啊 不要……不要…… +99Baby Sana Okada in Maid +走向圆滿 +滾滾球 +殺人犯 +天安門慘案 +柔软红嫩的小阴唇紧紧地护住她的阴道口 +165网址宽频影院网 +fuck是鸡 +和两勇男玩30P +走向圆满 +白液四濺 +喔┅┅我又要泄┅┅泄了 +人妻色诱 +法~綸 +護士誘惑 +你以为你装逼就能骗我 +成人导航X色成人导航 +激情淫穴 +秘裂 +幼女开雹 +無毛穴 +张 昭 富 +吴邦国 +政治迫害 +血灑天安門 +hui huang +毛华国锋 +性骚扰 +毛江戏子 +完全免费电影在线看 +和两勇男玩32P +毛迷奸药 +親日 +u r +阳具插入小肉穴 +幼女小嫩穴 +和两勇男玩31P +日本淫荡妹妹 +毛反恐委员会 +激情淫窟 +ON9 +Premium)オトナの変态●稚园 神谷姫 +淫情贴图 +靠夭 +假币 +鸡巴插入蜜穴 +long hun +妹妹的小嫩穴 +jiejie的嫩穴 mm嫩穴 +怎样延迟射精21岁以下禁 +e Idol Vol。19 杏童なつ!【RMVB/698MB】 +完全自由注册看成人电影 +53淫色导航 +李德生 +chong wu wang +fuck神通加持法 +pp点点通色穴激情片 +看牌软件 +朱镕基 +淫女小穴 +Lady Sonia-熟女丝袜 13 +情色影院 +用力狂插骚穴 ┅┅好爽 +罢吃 +将则民 +淫靡 +kqking +八九事件 +少女露嫩穴 少妇嫩穴 meinv的嫩穴 +嫩 流 插 肉 +初中妹妹的小美穴 +法**掄 +双腿夹著我的腰部使我的肉棒进入的更深 +反中游行 +bing feng chuan qi +舔b +哈宝 +阴精 +mo你鸡巴 +大鸡巴小浪穴 +兩個中國 +百纳成人激情影院 +蒙古鞑子 +fuck希拉克 +讓你操 +18歲淫亂 +肏妹妹淫屄 +五奶小青 +可怜卖菜妇 +侠客天下 +毛牛逼 +爱色cc +粉红穴 +舔B +ryl +毛劳+教+所 +美乳 +烂游戏 +性娱情色导航 +野性家庭教師 +网 特 +阴道好紧 +插入jiejie蜜穴 +小MM +中青旅創格 +王胜俊 +亂倫之公公與兒媳的秘密 +阴穴 +jushang +密穴貼圖 +激情MM +学生妹 +粗壯的肉棒插入淫蕩的小穴 +绝对女神 +GAMEMASTER +嫩b +賤逼 +和两勇男玩7P +令人喷血的春宫108姿势(组图)21岁禁看 +游衍 +淫荡护士 +游行 +操B指南 +裸聊 +血腥衝突 +几届中央政治局委员 +紫黛 +勞+教+所 +帝國傳奇 +美体艳姿 +群陰會 +国资委 +快樂西遊 +激情导航 +和两勇男玩6P +小参考 +blueeye +免费观看淫电影 +法*輪 +黃色文學 +姐都快被你搞死了! +和两勇男玩49P +姐弟淫乱 +深喉 Deepthroat This 8 +吾尔开西 +少妇房中自淫,和两勇男玩20P,操得直叫爽 操日本淫女穴 +封杀 +tengren +档案局 +和两勇男玩5P +ㄙㄞ你公 +黄翔 +三挫仑 +刘丽英 +操春药 +超英赶美 +丝路传说 +夫妻俱樂部 +成人淫乱小说 +爛貨 +日本成人激情影院 +鸡巴 淫穴 +jian你 +法轮攻 +反腐败论坛 +圣堂科技 +和两勇男玩4P +毛性欲 +塞你爸 +激情電影 +賣逼 +美腿丝足 +毛奸 +pusium pusium +情色影院 导航 18岁禁看 +meinv主持脱衣 +猪毛 +免费在线淫电影网 +GM +和两勇男玩47P +床上激情淫乱小搔穴 +抽插52岁处女meimei淫叫不断 +肉棒插进肉洞里 +中央政府 +毛你爸 +日本女优8分钟长片 +fuck温家宝 +法^^论 +台湾一夜激情成人聊天室 +台湾 +滾那嗎瘟比 +握住阴茎看准肉洞猛的一下插了进去 +GY +毛发论公 +教你怎样延迟射精35岁以下禁免费淫电影a片 +MM的小穴 +和两勇男玩3P +淫荡少妇穴少妇嫩穴 meinv的嫩穴 +倭寇 +www。zqrl。com +性交淫图 +和两勇男玩48P +罢餐 +大阴唇姐姐 +男女激情淫乱图 林心如合成 +十景缎 +操淫荡少妇 操淫荡meimei 操淫荡jiejie 操淫荡护士 操淫荡 空姐操 老师操女老师 学生操老师 操老师小说 +靖国 +測試 +法$轮 +navyfield +游戏蜗牛 +sex +摸你鸡巴 +和两勇男玩45P +免费淫色情电影 瞄準她的肉穴插了進去…… +毛一鲜 +淫女吃鸡巴 +处女阴道库 +穷b +阴壁肌肉紧紧挤压着棒鸡巴 +無產階級 +聖泉學淫 +史迪威 +fuck体育总局 +mo fa fei qiu +嫩B +法@论 +和两勇男玩46P +激情淫穴网站 +俞正聲 +林果 +陆定一 +國研 +点对点裸聊 +毛希拉克 +操陈功 +成人贴图网站 +毛撒尿 +法$輪 +革命 +小比樣 +罢食 +毛游戏宫理员 +毛巡查员 +妹妹的穴好多水 +北美仙人球碱 +梁擎墩 +manager +揚振 +网捷信 +初二辣妹 +龟头插入肉縫 +李登輝 +一夜九次郎 +狗日靠 +密洞 +色情小电影 +成人色站 +干老师小穴 +胡緊掏 +逼孕套 +專政 +免费淫电影,看完保证你打飞机 +朱琳 +鸡巴便结结实实的插进娇嫩的花蕊 +极品波神 +成人书库 +性欲喘息教師 +淫奸护士jiejie穴 +陽物 +mir3 +测試员 +mi zhuan +全免费淫色情电影 +快活林导航 +你媽逼 +枪决女犯 +一黨 +bitch +日本激情淫穴网站 +三去车仑功 +jiang shan +小穴收缩颤抖著 +十八淫妹电影 +triangle +學生愛國者運動證明 +Gm +毛外专局 +毛妓 +免费淫电影论坛 +方舟子 +露屄 +淫奸女护士电影在线免费观看点击进入 +测試員 +一党专政 +军火价格 +毛李先念 +59xp。com 电影免费 +玉蒲团 +舌尖刮著陰唇上的淫水 +法^^論 +我和小姨淫穴 +激情淫色文章 +屄屄特写 +免费试看片 +我是g和m +掛機 +毛发论功 +如果你未满33周岁请自觉离开。 +它媽地 +meinv孩含双棍玩内射 +金毛穴 +白粉 +游戏宫理员 +毛古方迷香 +他爸爸 +六四动乱 +毛贺龙 +日本淫荡女孩 +狂插 浪穴 +中华人民共和国 +淫水丝袜 +静坐 +玉蒲團 +露阴照 +和两勇男玩9P +rplan +肉棒插得我好爽 +大龟头戳进了子宫里 +斯蒂芬 +法@論 +淫妻的亂交免费在线看 +色情 激情 淫乱 卡通 高潮 +中华人民共和國 +维权 +产权局 +快樂AV +fuck小鸡鸡 +最新两性激情小说 +正清网 +鸡巴顶开花瓣 +本站10019多部激情电影全部免费试看三天 +王瑞林 +湿润的嫩穴中 +和两勇男玩8P +美丽世界 +trannie +六四風波 +聯眾 +干你老母 +毛三级片 +国研 +5街区 +免费视讯meimei +路甬祥 +他媽的 +大麻油 +发**论 +集會 +潤星 +狂插meinv老师 +公车奸meinv淫奸女电影试看。 +我有网 +仁寿警方 +姐姐的阴道好嫩啊 +拉姆斯菲尔德 +真理组织 +日本meinv鲍鱼贴图区 +免费淫色情电影 +干你老比 +天安门档案 +日本mm性激情电影 +發~~輪 +女儿嫩穴操mm嫩穴操女人嫩穴 +又粗又硬的大肉棒 +摸你 +娇小鲜嫩的小屄洞 +欧美激情成人电影 +meimei的嫩阴唇 +独占Princess Collection 若叶 +和jiejie淫穴 +f a l u n d a f a +嫩穴 搔穴 +人妻榨乳 +监狱 +驚天動地 +雞掰 +毛六四事件 +愛田由~(Moodyz)女教師 レイプ 輪姦 +淫乱诊所 +透视眼镜 +熟女護士 +laqia +色网阴道特写强奸23岁处女全过程 +一本道1137~陵辱巨乳~薫まい +個批 +嫩BB +毛你老母 +成人午夜场影院 +美女嫂子的小骚逼 +毛二B +二逼 +誅仙 +shen hua +毛双峰微颤 +假陽具插穴 +天安们母亲运动 +F_U_C_K +尻庇 +發綸 +方励之 +性伦乱小说 +21cn +歐美圖區 +新体操(仮)~妖精达の轮舞曲~ +吗比 +mm屄 +和熟睡的meimei做爱教你一手 +强效失意药 +连続失禁 +扶正肉棒,瞄準她的肉穴插了進去 +搞她 +淫婦自慰 +〓成人写真〓 +新江湖Online +毛奸夫淫妇 +口爆 +毛刘 淇 +shit +彭珮云 +游戏监督员 +色情网址网上视频 +淫奸少女电影 +手机注册电影 +hai dao wang +sw2 +公务员 +毛倭国 +疯狂赛车 +小穴里流 +迟浩田 +淫女淫图淫书淫片 +UR +不卡免费淫电影 +搏客 +亚洲激情淫色贴图网 +毛破坏 +桑拿房的淫乱图片 免费母子淫乱图片 +da hua +快到高潮时,他哭了。 +賓館女郎 +發@@論 +svs +亞洲情色網 +娘餓比 +ㄐ巴 +西游 +jiejie的穴夹的我好紧小说 +趙 紫 陽 +黄色小电影 +┙ +┘ +┛ +成人午夜激情视频聊天室 +从后面插漂亮小穴妹 +┚ +┝ +├ +┟ +┞ +┑ +┐ +┓ +┒ +┕ +干GM的娘 +└ +妳馬的 +┗ +┖ +┈ +毛海关总署 +┉ +┊ +┋ +┌ +┍ +┎ +┏ +━ +│ +┃ +和两勇男玩44P +┄ +┅ +┆ +┇ +和两勇男玩43P +┻ +┺ +┹ +メイド召しませ 第一话 +┸ +┿ +┾ +┽ +┼ +┳ +┲ +東亞病夫 +┱ +9v9e +┰ +弟弟淫奸姐姐穴 +┷ +┶ +┵ +┴ +罢饭 +┪ +┫ +┨ +┩ +射雕淫女传 +┮ +┯ +┬ +qian nian +┭ +┢ +┣ +ci77 +┠ +┡ +┦ +┧ +┤ +拔屄自拍 +┥ +极品成人激情影院 +5街区 +政治封锁 +和两勇男玩42P +日本人淫乱操淫荡少妇操淫荡meimei +司馬義•鉄力瓦爾地 +冯东海 +广东王 +国外美女黄网 美女激情SM处女淫水图台 +╈ +╉ +╊ +╋ +肉棒狠狠插嫩穴 +╄ +╅ +╆ +╇ +毛看牌器 +╀ +Yukata Angel Vol。 1 : 矢崎茜 +╁ +╂ +色mm的嫩穴 +╃ +惹火身材 +日韩妹妹嫩穴淫图 +如果你未满30周岁请自觉离开。 +和两勇男玩41P +色情导航 +02jam +你的鸡吧好大啊干的我好爽哦 +如果你未满31周岁请自觉离开。 +成熟性感大meinv +骚穴 +毛尻 +毛黄色电影 +積存的巨乳妻子積存的巨乳妻子 +抽插32岁处女妹妹淫叫不断 +1000y +淫奸处女穴电影 +茎候佳阴 +毛法仑 +yi wang chuan shuo +Chink Chink +赵晓微 +beijingspring +成人娱乐网 +和两勇男玩40P +艳尻 北原多香子 +剛比樣子 +毛基督 +cao你 +抽插39岁处女妹妹淫叫不断 +fuck托管理事会 +操波霸 +本站所有电影完全免费无需手机注册 +他NND +和meimei做爱 +屄屄 +滚滚球 +毛鸡掰 +賤貨 +人体摄影 +老二在她湿润的阴道口边摩擦 +法*论 +毛轮奸 +淫电影下载论坛 +插我 +欲火 +asgard +jiejie的阴道好嫩啊 +龟头被舔得又麻又痒 +中国问题论坛 +dick +47xp。com 电影免费 +你的小穴好紧┅┅夹┅┅夹得我好舒服 +亚洲免费淫色电影下载 +毛看棋器 +骚屄淫水泛滥 +鬼村 +fagtard fagtard +勃大精深 +亚洲色妹妹 +黑天使 +肉棒插进美穴 +长途汽车上的淫乱乘客 +仆街 +少妇偷情 +賴昌星 +肉棒的抽送 淫乱 用力干 +激情小说 +顶级影片禁书禁图 +客服人員 +制服美妇 +又粗又长的肉棒插入阴道里 +小澤圓(小沢まどか)的退隱作 +血B +激情打炮 +毛高校群体事件 +吮吸小穴 +民主 +lovebox +操淫荡少妇 操淫荡meimei +广电局 +淫荡少妇穴 +残废 +动漫激情淫色 +zhuanfalu +成人午夜电影 +conquer +毛江八 +家庭主妇 翔田千里 志村玲子 +安眠酮 +免费午夜成人影院 +肉棍狂插嫩穴 +Chudi Chudi +毛干妳妈 +毛舔西 +阳痿 +激情成人视频聊天室 +血b +我靠 +淫液不断从穴里流出 +黃金聖水 +金庸群侠转 +ever quest +掰开她的小穴 +gy +日本淫荡电影 +经典免费淫电影下载 +gm +色妹妹乱伦理小说 +moxiang +張 伯 笠 +诱惑视频 +藏青會 +看中国 +李金华 +騷逼 +错那吗逼 +少妇淫心我要看淫心情迷电影淫心情迷电影 +美女 +qiangjian +如果你未满34周岁请自觉离开。 +激情meimei聊天室 +激情美穴 +情色俱乐部meinv奸淫。黄色电影裸体电影PP点点激情电影 +jiejie被插的好爽 +毛窃听器材 +jiejie的阴户好嫩啊 +大鸡吧在她的小嘴抽送 +嘴唇吸小肉缝 +tibet +毛鸡巴 +操78 +yong heng +无套自拍 +在线看淫色电影 +毛烟草局 +嘩嘩曼 + 山咲Chiyuri +屠城 +梦城互动 +meimei嫩穴被狂插 +操测绘局 +xinguangming鸟你 +我操了美丽的女律师 +毛干妳娘 +人民报 +毛枪决现场 +hellgate:london +g。m +无码电影 +毛纠察员 +教你怎样延迟射精28岁以下禁免费淫电影a片 +姐姐的穴好大啊 +王汉斌 +小騷比 +紅十字会 +耶苏 +姐都快被你搞死了 +毛以茎至洞 +怎样延迟射精23岁以下禁 +好弟弟使劲干姐姐 +美女 淫穴 +刘永川 +老人政治 +亞洲有碼 +鄧 笑 貧 +残廢 +前凸后翘 +点击观看*林心如做爱*色情电影*免费淫 电影 +强奸40岁处女全过程/淫妹阴毛小穴 +电影试看片 +fuck他祖宗 +张 钢 +强奸22岁处女全过程/淫妹阴毛小穴 +戴秉囯 +viprxjh +罢工 +白肌美女?琴也 +欧美两性淫乱 +政治协商会议 +毛新生网 +血腥冲突 +他母親 +床上夫妻激情自拍图 +皮條客 +布莱德雷 +天鹅绒活动 +91bb成人小电影 +蕩女 +熟女颜射 +罗礼诗 +法@纶 +哥哥插入我的小穴 +你以为你装屄就能骗我 +dyonline +毛法西斯 +屌妳 +台湾电影网龙游龙洲影院日本娱乐性免费电影在线 +刘 淇 +三个呆婊 +淫术炼金士 +narod。ru +日本大型黄色美女做爱 +欧美淫图 +爱抚淫女的阴户 +台湾午夜色情 +省長兒媳婦 +orgasums +圣角色扮演学园~大泽萌 +做愛 +韩 东 方 +fuck天安门 +美女发春激情在线电影 +法^^纶 +香港激情图源成人色情论坛脱衣美女做爱 +口活 +fuck氵去 +tian xia er +王剛 +卖B发论公 +蒙独 +蕩妹 +kakajb +狂插淫洞 +homosexuel +黄慈萍 +导航色站 +jb +倪育贤 +性爱日记 +meinv穴 +智障 +海盜時代 +bbscity +奇乐网 +肉棒在阴唇上摩擦传来快感 +色情视频聊天 +色狐狸网址 +大波粉B +色情导航 免费色情电影 +靠北 +贱种 +wizard-soft +*法*轮*功*靠 +狂插嫂子穴 +刘伯承 +少妇扒开阴道图 +毛佛教 +第十六次代表 +愛女人 +Red Hot Fetish Collection Vol。41若叶こころ +性奴会 +高校群体事件 +黑社会大姐大性欲很旺盛 +南蠻子 +meng huan guo du +乌云其木格 +激情潮喷 +毛色情电影 +沃尔开西 +大波粉b +激情小說 +妈浪女骚 +淫欧美淫暴 +在线免费观看性感摸特日本性感奶霸图片骚 +亚洲激情论坛 +激插 +18禁 +龟头顺着肉壁插入她的阴户 +阿姨的阴唇好大啊 +批林批孔 +成人激情午夜 +戴秉國 +6月4日 +第7色大型黄色网站 +蒙獨 +姐姐的穴好紧啊 +共產主義 +小嫩逼 +32283 +测绘局 +小浪穴┅大鸡巴 +changeu +pao pao tang +fuck杀人犯 +毛董贱华 +盗电 +一边一国 +罗干 +成人激情免费电影院 +董文华 +韩联潮 +本站10006多部激情电影全部免费试看 +毛光明日报 +免费淫奸女A片段试看 淫电影//少女被强奸到高潮时偷拍小A片 +激情妹妹聊天室 +文化部 +………好舒服喔 +操操你妈屄 +魔力宝贝 +軍國主義 +哭么 +法@綸 +蕩婦 +六四參加者回憶錄 +淫女穴影院 +操达赖喇嘛 +南华早报 +台湾成人免费情色电影 +淫色电影 +殘廢 +毛妳妈的 +十八岁美女护士电影网站 +多维新闻 +操Gm +统治 +偷情 +你的肉棒干 +fuck推油 +毛小鸡鸡 +whore +丁关根 +监督 +大鸡巴坚挺插淫穴 +新疆独立 +i n c e s t +尹庆民 +d7se淫色穴图片和美女发春激情3级片试看 +net +(ATHENA)奥様欲情日記 エプロンをめくって犯して うずく人妻美巨乳スペシャル +网址之家 +野性姐妹花 +法^^綸 +毛洗脑班 +殘废 +外**掛 +夫妇乐园 +亚洲成人激情淫影院 +毛联易互动 +日本激情动漫 +肏穴 +驶你娘 +虎虎虎~淫秽的身体 Tora-Tora Gold Vol。25 : Shizuku Natsukawa +口淫 +东亚病夫 +狂操穴喷出阴精 +zhicheng163 +所盗摄护士jiejie性感美腿图 肉丝美腿艳情淫欲 +来插我 +激情淫洞小说 +江油餘震 +溫B +处女阴道特写爽图 +本站10006多部激情电影全部免费试看三天 +徐才厚 +它NND +ㄐ八 +在线淫穴 +son of bitch +午夜激情电影网 +自由亚洲电台 +kele8 +nabi +操机掰 +毛计生委 +挨球 +贯通两极法 +操GM +狗比 +干妳马 +發$侖 +日本暴淫网 +魔獸幣 +情色成人 +濕了還說不要 +game17 +臭作 +锤锤 +三個代婊 +肉穴 +舔雞巴 +f r e e d o m +温柔女孩操屄竟如此陶醉 +李小朋 +cjsh +色色五月天 +大航海时代 +我扒开了她的阴道 +肉棒插入小姨的肉縫 +淫乱工作 +H動漫 +美女做爱激情电影 +9you +公审李鹏 +sb +美国 +免费淫色强奸电影 +踢踢球 +成人午夜场,吸精痴女护士 +露陰照 +超级色情网站 乱伦色情小说 香港娱乐网黄站 性bt论坛 +feng kuang sai che +奴畜抄 +自拍写真 +Bitch +伊斯蘭 +冰風傳奇 +戳逼 +外**挂 +和两勇男玩50P +抽插29岁处女meimei淫叫不断 +淫之插穴虐待破处流血 +众明星乱淫禁书 +现役看护妇电影下载 +江湖淫娘 +pp244淫色导航 +歇b +赌球 +小泉彩~黑人体内射精连续20发 +它妈的 +钱其琛 +發**掄 +母奸 +內射美婦 +外—挂 +淫女信息 +fuck死gd +nacb +毛抑制剂 +是鸡 +大陆性美女淫穴 +狂操操小小姨穴 +fuck死gm +幼交图嫩女兽交 +混沌诀靠 +情色文學 +鮮族 +中文情色网址导航 +奧美電子 +多党执政 +少妇被鸡吧操 +和两勇男玩52P +情色文学 +含住我的小鸡鸡 +臺灣帝國 +免费淫电影网址大全 +操你祖宗 +龜投 +nabi +meinv护士被奸 +毛塞你老母 +紅火女郎~真央~壓倒性的震撼力~汙染女人的快感 +嫂子的阴道好大啊 +hai dao shi dai +色迷城 +宁王府淫色 +爆草 +受灾 +和两勇男玩51P +受災 +操表妹操 +王冶坪 +梅花屄 +新疆打砸抢 +豬容基 +whoyo +淫荡少女穴 +激情淫色 +穴淫 +贱B +和阿姨淫穴 +香港成人激情影院 +外—掛 +客服人员 +作ai +亞洲淫图 +大膽少女 +黨中央 +干妹妹小穴 +我和小啊姨在车上做 +又肥又嫩的小骚屄儿 +华西列夫斯基 +小平 +和两勇男玩53P +淫穴 大鸡巴干 好爽 +nage +国际足坛五大 +成人激情图库 +毛李弘旨 +嫩B弓虽女干 +客户服务人员 +yuckfou +抽你丫的 +网龙 +龟头碰到子宫口 +988wow +制服美婦 +发**纶 +又大又肥的阴道 +卖软件 +刀online +毛官逼民反 +狂插小穴 +穴海 +秦 晉 +妹妹社区淫色 +秦 晋 +征服小姐 +贱b +非典 +龟投 +战牌靠 +古柯 +羅幹 +Biaozi +淫荡教师穴 +吹喇叭 +大鸡巴顶进meimei的小穴 +淫妇自慰 +套弄鸡巴 +笨屄 +獸奸 +學生愛國運動正名 +激情小浪穴 +法轮工 +淫城乱伦屋 +白嫩meinv穴 +新斷線 +Whitey Whitey +aika +淫水横流 +qqpp +qqr2 +摇头丸 +滚那吗瘟比 +Asian Hot 018 岸田香織 女陰破壊 +KOKESHI COWGIRL Vol。29 石川优季奈 +女人被迷奸的时候也很爽 +新手辅导员 +大鸡巴在她的小嘴抽送 +美女与猪性交电影 +经插进我的穴了 +dfdz +卡通美女淫乱图 +杂种 +repent +買賣 +贝肉 +百家性大型黄站 +穴爽 +激情最新网址 +肉壁包容着鸡吧很舒服啊 +fils de pute +毛分裂祖国 +毛龟孙子 +性無能 +黄色小说 +妹妹淫图 +basterd +毛麻醉乙醚 +花瓣正在潺潺地渗出蜜汁 +我和jiejie的淫乱史 +Clayton Dodge Clayton Dodge +统独 +插妻子小穴 +旅館自拍 +雞巴 +他媽ㄉ王八蛋 +法~~綸 +本站10001多部激情电影全部免费试看 +激情 +李继耐 +毛摩门教 +操插妳 +顾顺章 +牛比靠 +六四参加者 +宏法 +日本激情淫色动画片 +meng huan guo du +基督教 +亀頭 +淫奸表姐论坛 +森田めぐみ 凌辱饲育 +管裏員 +赣江学院 +免费性爱电影 +阴道夹的我好紧 +靠么 +vgbh +李老师 +淫奸表妹 +在线淫影院 +嫩穴 插干 …快插我吧 +Qzone精彩由你而来 +阳物 +香港成人电影网五月成人情色论坛 +美女极品嫩穴 +多黨執政 +毛卖国求荣 +在线免费观看黄片A片 +色情网址网上做爱 +┅┅别再磨了┅┅痒死啦!┅┅快 +renminbao +粗大的肉棒………我受不了 +毒龍舔腳 +爱妻淫穴 +洪 吟 +熟女亂倫 +奸淫……好舒服 +RMB +少妇房中自淫,和两勇男玩17P,操得直叫爽 操日本淫女穴 +淫奸护士姐姐穴 +game +情色电影网站 +錘子 +民主墙 +欧美淫图 成人色情网 +onair +油田总部 +iuiuu +抵制日货 +无网界 +da hua zhan guo +操你老母 +乳頭 +肉簫 +免费成人激情电影 +104bb成人小电影 +JB靠 +姐姐的肥穴 +曹剛川 +淫奸美女 +爽死你淫图 +插入小姨的子宫 +插 护士 +藤人 +猛插 +tong shi tian di +荣誉之战I--钢甲洪流 +你老妹 +jiaochuang +藤仁 +罗富和 +榮譽之戰I--鋼甲洪流 +馒头屄 +氣性坏疽病 +妖艷醫生 +陰毛 +GameMaster +导弹 +春色AV激情片 +18DY性爱电影 +賽你老母 +让你操 +san guo hao xia zhuan +淫女淫洞 +刘澜涛 +老二 +hun luan mao xian +抽插26岁处女妹妹淫叫不断 +欧美淫女在线看电影 +碧雪情天 +亚洲淫色网站 +极品成人A片无码 +肉棒插到花心深处 +毛麻醉枪 +路易 +fuck台独 +莎木online +狂插日本学生妹 +耶蘇 +怪獸總動員 +淫女老师 +脑残 +tengwu +毛鸡奸 +全免费淫电影 +干你良 +街头篮球 +政治打击 +瀨名 +學潮 +露出了娇小鲜嫩的阴道 +吳德 +李禄 +fuck世界日报 +抽插55岁处女妹妹淫叫不断 +毛王昊 +陰水 +fofg媽的 +幹的你 +猫扑 +肉箫 +發*侖 +毛税务总局 +劉奇葆 +騷貨 +山口组 +fuck受虐狂 +易丹轩 +免费淫女看电影网站 +特码 +X妈牛比 +公子开 +日朱骏 +蓬浪 +王子傑 +淫护士 +插妹妹小穴 +minghuinews +手记注册日韩5010部激情电影 +毛李瑞环 +李鹏* +狗B +哥伦布 +许世友 +吴弘达 +好肥的阴户 +97sese +六四事件 +瞒报 +藤任 +群奸 +手指扒开红嫩的阴唇 +tum tum +張朝陽 +毛轮功 +狗b +鹿城最新娱乐小说 +aids +性饥渴 +捏你奶子 +毛性爱 +陳毅 +妹妹黄站 +监听王 +艷舞淫業 +華國鋒 +死亡笔记 +wg武功 +最强美乳おたま初解禁 +成人之家 +免费A片日本淫电影 +無碼精選 +阴茎把子宫顶烂 +最新99bb)有名女优~及川奈央-痴女教师 +魔法奇兵 +你妈了妹 +无界浏览 +錢運錄 +欲望 +捅比 +中青旅创格 +免费试看激情成人电影 +操 gm +比卵 +鸡吧插进肥嫩的小骚屄 +BT激情 +艳星诱惑 +操嫩穴 +日本熟母 +操你大爷 +强奸23岁处女全过程/淫妹阴毛小穴 +中原油田 +监管 +大纪元新闻网 +免费成人情色激情视频聊天 +肉缝 +QQ幻想 +黄祸 +神经病 +干她妈 +插穴图 +GOQO +整根阴茎没入她空虚已久的阴户 +法$$淪 +日本美女吃精图 +发沦 +强奸28岁处女全过程/淫妹阴毛小穴 +法@@綸 +世界都 +毛欢城互动 +95bb成人小电影 +亚洲激情网 +我的小穴好爽 +金瓶梅 +免费在线淫奸mm电影 +月经 +換妻 +毛梅花网 +紫彩乃潮吹赛红音 +马大维 +龟头挤进了jiejie的小穴 +成人色情网站 +毛十八摸 +你它妈的 +私處 +手指对她阴蒂的刺激 +中条英机 +尉健行 +免费电影未亡人柔肌 +国际法院 +王军涛 +賣號 +肛门拳交 +毛受虐狂 +吴德 +銀民吧 +2。23會議 +淫荡少妇穴少妇嫩穴 美女的嫩穴 +教你如何鉴别处男处女的方法(组图)18岁禁看 +操插你妈 +指导员 +少妇房中自淫,和两勇男玩8P,操得直叫爽 操日本淫女穴 +星戰前夜 +干洋妞穴 +遊戲監督員 +毛鸠屎 +travestido +出售此号 +裤袜 +美麗世界 +粗鸡巴 嫩穴 +和妹妹肏屄 +淫乱小说 +毛卵 +台湾18岁成人 +張宏堡 +日本精選無碼DVD +毛杀人犯 +我将肉棒狠狠插入漂亮的老师小淫嘴抽插数十次 +强奸34岁处女全过程/淫妹阴毛小穴 +少妇房中自淫,和两勇男玩19P,操得直叫爽 操日本淫女穴 +淫水横溢 +虎虎虎~ Tora-Tora Platinum Vol。2 : 魔性的meinv 鈴木麻奈美 +操淫荡少妇 操淫荡护士 激情穴贴图 +huo xian ren wu +淫女吃尿 +嫩缝 +外••挂 +fuck舔西 +亞洲淫娃 +人体炸弹 +法^纶 +亲亲小芳 色咪咪论坛 新亲密爱 六月龙盟 人间仙境情色网 +毒品 +发浪 +插妳 +教你怎样延迟射精22岁以下禁免费淫电影a片 +fuck他妈的 +天安门大屠杀 +痛批政法委 +da tang +毛南联盟 +肉縫 +傻卵 +蒋中正 +毛独立 +免费成人A片 +黑省副省長 +封从德 +淫欲日本 +山口組 +黑省副省长 +淫贱妹妹贴图论坛 +發^^論 +淫女浪穴 +内衣模特露点走光 +zhen feng shen +成人激情聊天室 +發@侖 +韓國自拍無碼系列之二) +色情电影 色情排行榜 +毛台独 +妈……你的小穴好插 +原子能机构 +江绵恒 +东西南北论坛 +曼施坦因 +成人激情淫洞网站 +中国孤儿院 +淫色贴图 +胡緊套 +淫魔 +姐姐的屄 +长身丝袜meinv~赤く烂れたマンコが痛 +李老師 +狂插淫荡女护士 +毛玉杵 +亚洲艳情男女图吧 +射屏 +法@@纶 +fuck死GM +学潮 +fuck死GD +瑪雅網 +求你插插我吧好痒 +菜逼 +社科院 +台湾民國 +曾 慶 紅 +法耣功 +外交部 +耶和华 +jin yong qun xia zhuan +傻吊 +tan ke bao bei +勃起 +步飞烟 +骚逼大型成人色站 +Tora Tora Gold Vol。16 香山圣 +教你怎样延迟射精26岁以下禁免费淫电影a片 +淫荡 穴 淫洞 +我淫我色淫色导航 +淫乱小姨子小说 +龜兒子 +令人喷血的春宫108姿势 +法~~纶 +台湾民国 +平成女忍者 奥义中出し陵辱 +法磮功 +毛叶剑英 +溫 元 凱 +猪操 +胡紧涛 +nigga nigga +审查 +龟头压挤阴道 +用劲吸吮咬舐着湿润的穴肉 +k粉 +手记注册日韩5022部激情电影 +少女床上自拍 +狂插日本美女护士 +色mm激情论坛 +嫩縫 +育碧 +李少民 +wowassist +熱 站 政 論 網 +陳曉寧 +毛小泉 +法^綸 +大波波 +江核心 +林长盛 +免费电影 美女电影 +kefu9you +激战 +f_u_c_k +89年的斗争 +廁所偷拍 +完全免费淫电影 +肉棒伸入她的口中 +幼女玩性 +法倫 +Image)ヌーディストGALビーチ +天天干贴图 +小電影 +晚年周恩来 +淫妻的穴 +大鸡巴好趐┅┅趐┅┅快┅┅别揉了 +妈个b +览叫 +咬着龟头 +feng kuang sai che +操操你八辈祖宗 +唐人街情色导航 +成人两性电影 +卖ID +迪里夏提 +毛游行 +午夜电影 +熟女乱伦 +解放軍306醫院 +PP电影 +八九学潮 +┅干的妈好爽 +色情网站 +教你怎样延迟射精18岁以下禁 +meinv口含鸡吧玩内射 +表舅妈与我 +9you +操操gM +走光偷拍 +万里 +色情导航 导航 +specialforce +义解 +sheng da fu weng +無碼淫女 +淫民欧美激情贴图 +好弟弟使劲干jiejie +目标软件 +侬着冈峦 +淫女疯狂偷情 +淫 电影 +老逼 +海洋局 +汪岷 +鹿城娱乐 +毛卖ID +狂插日本少妇 +liu xing hu die jian +露点 +屎妳娘 +fuck傻子 +粉嫩美少女穴让你插 +毛淫 +肉棒在姐姐的阴道里 +操mm嫩穴 +搞他 +甜嫩穴 +民主党派 +大花B +法侖 +插小穴的快感 +狗b新光明 +操操gm +香港色情影星meinv裸体 +瘋狂賽車 +嫩鲍 +狗杂种 +黄片 +zhengjianwang +小姨的穴 +白梦 +黑点 +幹妳馬 +亚洲激情片 +亚洲情色 +日领馆 +毛新闻办 +一本道 +赵海青 +殘疾 +猛干 添 +台湾18dy电影 +yi wang chuan shuo +陈至立 +含屌 +操吃屎 +浪女叫春成人招妓网色性网电影性暴力电影 +fuck吴仪 +人民银行 +午夜激情 +骚洞 +反封锁 +成人激情论坛 +相奸 +國賊 +春光外泻 +插她 +slanglist +法伦 +Red Hot Jam Vol。 藤崎夕凪 +免费电影妖艷醫生 +龟奴 +后庭 +女教師 レイプ 輪姦 +趙 海 青 +民政局 +爆乳家庭教师 +毛傻卵 +绝品meinvが恍惚颜の绝顶快感 +毛邮政局 +外*掛 +卖QQ +免费激情论坛 +艾滋病 +新石器時代 +外/挂 +美女护士被奸 +预审查 +胡乔木 +fuck小泉 +插的jiejie好爽 +mforest +pao pao +熟女顏射 +骚比 +stoneage +亚洲情色淫穴 +狂插日本meinv护士 +骚母 +用手指分开两片肥嫩的阴唇,露出了那娇小鲜嫩的小屄洞 +水扁 +司马璐 +龟头对准菊门 +袁纯清 +插你丫的 +法仑 +雜種 +毛三民主义 +外-挂 +粉红色的大阴唇正紧紧的闭合着 +奸淫空姐 +漂亮。女記者採訪時被逼姦 +星戰情緣 +断電 +屄儿好┅┅好爽!┅┅好舒服!┅┅ +毛性无能 +日逼 +18岁淫乱 +外/掛 +激情淫穴导航 +足腳交 +儿子淫奸jiejie +对著暴露的美穴狂插 +法$$论 +聶榮臻 +草你妈靠 +Bao皮 +三反五反 +龜头 +狂插 +强制浣肠 +淫兽学园 +韩日成人激情电影 +把肉茎舔乾净 +mwo +法沦功 +法婨功 +龟头 +毛恐怖主义 +mxd +天安門母親 +猖妓 +外-掛 +毛傻吊 +朱林 +韩启德 +Heterosexual +色站导航 +大鸡巴顶进妹妹的小穴 +搞你 +你馬的 +妈个B +KAO +法@@掄 +香港激情性爱影院 +練完瑜伽功做?才爽呢(國產3p) +老卵 +变态心魔女仲村 生中出 +骚水 +龜奴 +色情聊天室 +麻痹 +騷穴 +綿阳 +成人圖片 +拉登 +蔣彥永上書 +国贼 +綜聯數碼 +色情五月天 +肉棒插入meimei小穴 +魔域 +羞耻母 +免费成人两性影院 +吴仁华 +老师被干小穴 +抽插56岁处女meimei淫叫不断 +蒋彦永上书 +国外meinv黄网 meinv激情SM处女淫水图台 +性愛圖片 +色情导航 av电影 +牙齿轻咬着阴核 +淫荡姐姐勾引小弟玩操屄 +朱溶剂 +插淫妇骚穴 +李宏志 +邓笑贫 +fuck文化部 +肉棒抽插…不要 +MUGEN EX Vol。4 +她的阴道乳房真美 +毛彭真 +發論功 +煞逼 +台湾成人网站 +阳具插入小穴中 +partita +插入内射 +世界日报 +CCTV +大鸡吧塞进逼里使劲插我 +日本淫妞 +哥哥我爽晕了 +谭绍文 +邻居少妇 干邻居少妇 邻居的少妇 邻居美少妇 操淫荡少妇 +阳具对准她湿润的小穴口 +MUGEN EX Vol。 7~滨崎(MX-07) +烂人 +ㄖ +日本色诱女郎图库激情成人视频聊天室 +Bastard +puSSy puSSy +phuck +去死 +盖世太保 +f a 轮 +admin +三去车仑 +sealonline +鲍岳桥 +毛美国 +情色 激情 美女 穴 +pao pao dao +法~淪 +两性淫乱小说阅读 +完美國際 +发@伦 +天上碑 +胡XX +肉棒 插得太深了 +强奸护士 +连胜德 +免费淫奸女A片段试看 强*十八岁美女护士看完保证你打飞机 +淫穴把整个龟头吸住 +狂操 +青樓 +射入阴道里 +抢 粮 记 +MASTER +女教师家访遭遇体剃毛内射肛交口爆喷尿虐待 +毛人大代表 +蜜汁 舔穴 塞入 +成人论坛导航 +极品金牌素人口交系列 +溫逼 +陽萎 +操操XX +法$$論 +hkhk68 +胸涛乳浪 +亚洲淫色俱乐部 +奴隶调教 +盤古軟體 +网星 +tnnd +毛一夜情 +好爽┅好舒服小骚穴 +网易 +f a 輪 +狂插林心如穴 +綿陽 +西洋美女 +狗成 +368成人网站 +乱伦父女 +國產偷拍 +Gold Angel Vol。7 纹舞らん 可爱 +发@仑 +倒台 +日軍 +性愛插穴 +15年前的“共和国卫士” +又硬又大的肉棒 +插入……大肉棒 +叫春 +台湾小穴自拍护士做爱 +潮吹喷射地狱 不行触摸的喘气 4P肉奴隶中出 +毛卖B +吗的靠 +将手指插入她的穴里 +法@@抡 +抽插20岁处女meimei淫叫不断 +北京之春 +不要!嗯──啊啊、啊啊!” +亚洲激情帖图 +法(轮)功 +轩辕二 +獸交 +毛吴仪 +无码炮图 +大中国论坛 +同房 +美幼 +毛穆斯林 +肉棒就顺着湿滑的阴道口插进去了一半 +cdjp +台灣狗 +哦……再快……小屄要美死丁…… +性色俱乐部 +发$$轮 +zl-fm。com +倫功 +女学生嫩B +外@挂 +风尘劫 +fuck他马的 +自民党 +毛一中一台 +毛吕秀莲 +青天白日旗 +t2dk +骚浪 +封神 +58xp。com 电影免费 +大鸡巴用力的往小穴里面狠插 +陵辱面接4人淫乱娘 +earthciv +春藥 +毛罗干 +庆 红 +她的阴道好深啊 +本站10020多部激情电影全部免费试看 +鸡8 +和阿姨作爱 +nnd +地藏 +九評 +毛卖QQ +操藏独 +淫语连连 +賤種 +如果你未满19周岁请自觉离开。 +戳那吗逼 +18摸 +插的meimei流淫水 +三去车侖 +臭机八 +膏药旗 +GAME MASTER +jiang wang +外?挂 +日本激情电影 +qqtang +柳下惠 +。gm +莖候佳陰 +令人喷血的春宫108姿势(组图)22岁禁看 +猪头 +让我操高潮淫水一直流溅 +新闻管制 +無界流覽 +外?掛 +好大的阴户啊 +性感动感美女日本幼少女性感写真 +援助交际 +亚洲激情影院 +陰蒂 +强奸38岁处女全过程/淫妹阴毛小穴 +成人电影 淫穴嫩穴骚穴 +海之乐章 +小骚娘们的小嫩骚屄 +89风波 +蔣彥勇 +c a o靠 +我日靠 +玫瑰园 +鸡巴对准穴口猛地插进去 +嫩鮑 +毛滚 +毛管理员 +亞洲瘋情 +4-Jun +淫奸表姐 +在线淫电影 看完保证你打飞机 +淫水狂喷 +万钢 +肉茎 +外@掛 +好……小……小骚穴 +發倫功 +……好爽喲 插穴 +fuck傻屄 +操插你 +ri ni ma +亲美 +日本激情淫影院 +ayawawa +日你妈啦逼 +免费黄色淫电影一社会男子在宾馆里强奸一 +如果你未满27周岁请自觉离开。 +台湾成人黄色电影 +老兵 +大鸡巴插小穴 +八九年那个春夏之交 +卖号靠 +小穴疯狂地吮吸着我的阳精 +援助交際 +青楼 +三去车仑工力 +18dy村妓 +本站10008多部激情电影全部免费试看 +tui tui xia +胸濤乳浪 +毛国土资源部 +骚棍 +刘华清 +盗窃犯 +手指抠肉洞 肉缝 +骚棒 +强奸美女狂插处女阴道 +大跃进 +插淫屄 +毛贱逼 +陰阜高聳 +月光宝盒 +周六性吧 +儿子的肉棒好长啊 +红色的小穴 +下贱 +梦幻之星 +本站10011多部激情电影全部免费试看三天 +tianxungame +抽插51岁处女妹妹淫叫不断 +VIP激情成人电影 +89暴乱 +三级电影淫电影艳情电影 +毛穆罕默德 +杀手 +處女 +坐脸 +淫水爱液 +辅助程序 +純情尤物由美(中文字幕) +鸡巴抽插好……爽 +25dy淫色贴图 +民警当副院长 +肉莖 +杨巍 +運营者 +鸡芭 +婊子养的 +我湿淋淋的阴道 +陷阱超人哗哗曼 +欧美成人漫画贴图区 +壓制 +如果你未满35周岁请自觉离开。 +和平演变 +ji zhan +爱神之传奇 +狗操 +lastchaos +她的阴户好嫩啊 +meimei的穴好紧 +鄒德威 +法$纶 +教你怎样延迟射精32岁以下禁免费淫电影a片 +妓女靠 +肉棒狠狠地插进小淫穴中 +刷钱 +淫穴电影 +毛氵去 +龟头插小穴 +MAKELOVE +机掰 +毛舆论钳制 +啊┅┅用力┅┅用力插烂我的淫穴 +下賤 +meimei的嫩阴户 +来干 +明星捐款 +毛卖比 +粗制吗啡 +插进 小穴 嫩穴 +新手輔導員 +Tora Tora Gold Vol。15 香山圣 +海洛因 +杨帆 +温馨 +毛他母亲 +meinv极品嫩穴 +龟头顶破了处女膜 +口內爆射 +龟头插进了小穴 +悲惨-双胞胎一起被奸 +红十字会 +365情色网 +靠你妈 +meimei的阴唇好嫩啊 +玉乳 +法*綸 +小屄又湿又滑 +王丹 +少女被强奸到高潮时偷拍小A片免费淫电影a片 +淫乱插穴好爽 +懶趴 +淫浪少妇和医生疯狂做爱 +操操Gm +淫电影//教你怎样延迟射精 +呂秀蓮 +风骚欲女爽爽网 +情色图片成人小说 +虐奴 +陰莖 +教你怎样延迟射精41岁以下禁免费淫电影a片 +插 干姐姐 好爽 +淫色贴图小说 +狂插老师穴 +大*FA 弟*子 +8 仙 +大 中 國 論 壇 +操操GM +屙民 +完美国际 +猛將 +猛将 +色情小说 BT限制级电影 +激情淫穴小站 +美女淫图 +無碼體驗 +不像我讓你打~ +cctv +露毛 +项怀诚 +刘青 +成人午夜剧场 +老土 +50zhou +把我的穴插烂了 +睪丸 +一元激情电影 +46xp。com 电影免费 +鹿城娱乐情色 +wan wang zhi wang +抽插27岁处女meimei淫叫不断 +中天萬方 +代理 +亮穴 +机战 +成人 激情 淫 另类 +狗日 +欧美做爱 +香港激情淫色贴图网 +发^仑 +台幣 +狂插处女穴 +巡府媳 +国家主要部委 +台湾独立 +色网阴道特写强奸24岁处女全过程 +幸运抽奖管理小组 +jue dui nv shen +东方红时空 +迷姦雙胞妹妹 +龟头挤进了她的阴道 +毛东亚病夫 +成人免费 +免费成人图片 色情美女做爱美女小穴写真 +Groove Party +我跟妹妹肏穴 +性之站 +去你媽的 +台湾十八两性电影 +獨占動畫~肛門 1~長谷川 +好紧的阴道啊 +淫色全免费 +抠穴 +陰茎 +痛经 +杨元元 +操XX +日本黄色电影 +餘震 +本站10007多部激情电影全部免费试看三天 +成人激情性爱电影 +大鸡吧插人阴户 +毛鸦片 +色mm激情图片 +吃屎 +睡着的武神 +發$$綸 +用肥嫩的小穴套弄着我的阳具 +毛吗啡 +包pi +拒绝食堂 +谢非 +毛淫靡 +討伐 +疯狂jiejie教弟弟小说 +妹妹乱伦理淫穴 +情色视频聊天 +se淫乱姐姐小说 +法*纶 +鹿城黄站 +無網界 +李 錄 +三角裤 +Kao +吊子 +六月四日 +情色天崖 +丝诱 +成人 激情 淫乱 另类 高潮 +发抡 +十五周年 +都市2046 +抽插37岁处女妹妹淫叫不断 +林保华 +狗日的 +乳腺 +讨伐中宣部 +發~~綸 +89暴亂 +法崘功 +佛教 +淫奸少妇论坛 +文革 +日本免费激情学生美 +圣泉学淫 +成人情色论坛导航 +黄色网站 +日本天皇 +基督基督教 +Pajawa Pajawa +色mm穴激情图片 +残疾 +抽插26岁处女meimei淫叫不断 +张春桥 +反社會 +林樵清 +反攻 +少女激情自拍 +屄毛 +FLG妈B发抡 +亚洲淫穴电影 +舔屁眼 +18淫书 +剑网2 +日本激情淫色下载 +剑网3 +插穴淫图 +猛干 +劉延東 +精液射在妹妹的子宮 +我日你妈 +mo li bao bei +Tibet国 +wan mei shi jie +你老味 +『第一爽图区』 +用舌头舔着他的马 眼 +民族 +災区 +激情美女贴图九九情色 +青 天 白 日 旗 +強制飲尿便器小野悠美 +毛明慧网 +江山 +18dy电影 +操曹刚川 +未满20岁的请自行离开 ! +中機電 +大鸡巴插进了的小穴 +灾区 +raycity +日本激情淫色影院 +很黄很暴力 +災區 +小犬蠢一狼 +王勝俊 +纳粹 +17岁处女小阴唇张开 +老味 +藏独靠 +宋书元 +外$掛 +万维读者论坛 +下身 +瘟B +銷魂洞 +Anal Asspirations 7 +親 美 +毛卖淫 +小穴被插 +灾區 +寫真 +高级应招女 +肉棍子 +发^伦 +毛唐家璇 +抽插53岁处女妹妹淫叫不断 +情色成人基地 +連続失禁 +外*挂 +空姐护士淫荡图片 淫荡女护士 淫荡少妇穴 +guild wars +在线免费观看性感mo特日本性感奶霸图片骚 +瘟b +反日 +教你如何鉴别处男处女的方法(组图)18岁禁看免费淫电影a片 +皮條 +臺灣黨 +百家乐 +又长又大的肉棒 +潮吹喷射地狱 不行触mo的喘气 4P肉奴隶中出 +61xp。com 电影免费 +风雨神州论坛 +麥角酸二乙基醯胺 +骚b +钓鱼台 +虎虎虎~ Tora-Tora Platinum Vol。2 : 魔性的美女 鈴木麻奈美 +山本 +男人阁-套图站 +陸肆 +我和姐姐 +李录 +裸體少婦 +毛密洞 +淫乱熟女 +幹你媽逼 +抽插23岁处女meimei淫叫不断 +毛meimei贴图区 +毛东突组织 +美女激情视频聊天室 +春药 +鸡吧阴茎插嫩穴小穴 +同床 +賽維創世 +奸杀meinv大学生 +放荡少妇宾馆 +轩辕剑 +比毛 +游戏指导员 +fuck驶你公 +回民暴動 +一面做愛 +娇小鲜嫩的小屄 +温家保 +biaozi +毛体育总局 +代开发票 +18成人网 +屌毛 +手记注册日韩5007部激情电影 +教你怎样延迟射精29岁以下禁免费淫电影a片 +毛手机复制 +黃片 +龟头缓慢地从我的阴道中戳入拉出 +少妇房中自淫,和两勇男玩12P,操得直叫爽 操日本淫女穴 +meinv主持27小时全天激情热舞 +骚B +手机注册激情网站 +手记注册日韩5016部激情电影 +信不信我撞死你 +十年动乱 +毛宋祖英 +沦功 +激情潮噴 +大鸡巴紧紧的插穴 +……插的……好舒服 +法$綸 +浪女淫水 +车牌反光 +两岸关系 +操gm +meimei的小穴好紧啊 +神甲奇兵 +淫乱jiejie小说 +掰开嫩穴 淫液 +gun gun qiu +贱bi +肏姐姐屄 +纪念松岛MM引退大作-松岛枫合集4 +爽穴 +淫护士小说 +比水 +她的阴道真紧 +王刚 +毛骚B +發浪 +東熱空姐 +免费在线成人电影 +免费淫色电影网站 +超恶い状态10人の俗人たち +睾丸 +免费淫女骚穴在线看电影 +操gM +com流氓 +皮条 +回民暴动 +流出大量淫水 +淫乱 爽电影 +淫奸女教师 +台湾帝国 +银行账号 +东土耳其斯坦 +on9 +毛胡锦涛 +飞扬论坛 +激情动漫成人 +Marc Dorcel)Jesse & Jenna expertes du vice +王克 +如果你未满24周岁请自觉离开。 +亚洲淫色 +琼浆玉液 +司马义•铁力瓦尔地 +靠你媽 +干的爽 +援交 +美女网站脱衣美女百分百作爱 +赛维创世 +百海 +抽插到高潮 +两腿之间 +王八 +哥哥的大肉棒 +扒开她的嫩阴道 +免费桃色电影不需注册 +六四運動 +点击观看*林心如做爱*色情电影 +熱血英豪 +三级淫水写真 +掩埋 +麦叫酸 +于浩成 +日本情色电影 +寇晓伟 +外$挂 +毛胡锦淘 +wg99 +先奸后杀 +惊天动地 +毛圣女峰 +游戏发奖员 +问道 +性感誘惑 +發淪 +一码中特 +坦克寶貝 +臺灣建國 +moxiang +要色色 +气象局 +女儿的阴道好大啊 +fuck賣.國 +TENGWU +18Chinese Japanese AV Girls +倭国 +毛三个代婊 +王兆国 +阿姨的阴户好肥啊 +白烂 +和两勇男玩18P +張 昭 富 +屠杀 +社會主義 +免费淫色情电影 20岁女大学生被强#(组图)全过程 +姐姐的阴户 +成人淫图 +王兆國 +醬豬媳 +狼友 +情色导航 +台湾盲人meinv在家疯狂做爱 +錯比 +外~挂 +中宣部是中國的愛滋病 +18岁少女处夜激情性爱电影 +毛六?四 +和两勇男玩17P +taip +择民 +淫色贴图导航 +魔幣 +淫电影//教你如何鉴别处男处女的方法(组图)18岁禁看 +cnouc +鳳舞天驕 +GAME master +梦~ 总辑篇-GONZO Vol。 4 Rio +代练 +倚天 +手记注册日韩5025部激情电影 +操插深些 +激情淫穴影院 +抽插27岁处女妹妹淫叫不断 +娘饿比 +威而钢 +150m。com +法@@沦 +射爽 +巨灵神 +成人网我该死免费视频 +fuck税务总局 +娘個比 +入穴一游 +猥亵 +89風波 +肛門噴水 +wen dao +劲舞 +和两勇男玩19P +张大权 +jhwg +bt淫色电影 +绿色环保手机 +毛阴蒂 +中国共产党 +在线免费淫电影 +陈蒙 +sex +野雞 +好粗的大肉棒 +插那吗逼 +da hai zhan +张 志 清 +射雕淫女传9 +李洪 +王兆囯 +游戏管理员 +私立淫乱学园 完全版(中文字幕) +好硬的大肉棒 +胡緊濤 +我和女大学生在公共汽车上做爱 +教你怎样延迟射精20岁以下禁免费淫电影a片 +jiejie的肥穴 +jie tou lan qiu +小穴套着鸡巴 +ma chang da heng +免费淫电影吴宗宪搞笑语录(19禁看) +毛温家宝 +胡喬木 +卖淫 +又嫩又紧的穴 +j8 +告全體線民書 +毛妳娘的 +日本激情漫画贴图 +武林外轉 +狂插小浪妹 +盜撮 +大B私服 +抽插36岁处女meimei淫叫不断 +遲浩田 +快乐到死 +乳丰穴嫩激情性电影 +jhsz +浪穴被你插得爽死了 +法**淪 +老师含住我的小弟弟 +運營組 +毛倭寇 +淫絲蕩襪 +武林外转 +毛工商局 +泡沫经济 +傅作義 +大史 +信息 +新黨 +新幹線 +宫泽Keito无修正第二弹 +u r靠 +rape +鸡鸡插入穴嫩 +精液浴 +发廊 +彈 劾 +极景 +干骚女 +強姦犯 +meimei的大阴唇好嫩啊 +綠色數码 +毛硬挺 +狂插美女护士小说 +凸肉优 +龟头插入肉洞里 +和两勇男玩10P +滥逼 +少妇小穴被操的很爽 +谋略高手 +用我的舌头刮着她的阴蒂 +long yu di xia cheng +一对熟女间的性虐游戏 +极品嫩穴 淫穴嫩穴 扒开嫩穴 抚摩她的嫩穴 +妹妹的穴好紧 +恐怖份子 +放蕩熟女 +双龙入洞 +弟弟的肉棒好大啊 +游龙在线 +法**沦 +腾武 +长长的肉棒插进我的阴道里 +毛叫床 +捅我 +品色堂永远免费开放注册中 +本站10020多部激情电影全部免费试看三天 +装B +淫水直流 +xzhonline +淫奸meimei的屄 +fuck温家保 +阿姨的肥阴唇 +Gold Angel Vol。8 仲村りお +免费黄色淫奸电影3级片a片手握着我的大鸡巴 +湿了还说不要 +吸精痴女护士 +香港激情图源成人色情论坛脱衣美女做愛 +杀你全家 +插妹妹淫屄 +自制手枪 +jiba +操b指南 +手机激情淫色网址 +盗撮 +av电影 色情导航 +毛托管理事会 +美女野兽做爱淫图 +赖昌星 +hong bao shi +无需手机注册激情电影 +又顶到我的子宫 +和两勇男玩12P +就去诱惑 +舔奶 +戳那吗B +汕頭頻傳擄童割器官 +口射 +民族分裂 +裸体小姐作爱视频彩福联盟社区 大奶妹脱 +龜公 +放荡少女少妇 +台湾免费淫电影 +11月更新成人导航 +master +亚洲激情meimei +mixmaster +钟山风雨论坛 +alod +全国人大 +和两勇男玩11P +ora-Tora Gold Vol。4~~ささきふう香~~92cm G罩杯美爆乳 +法^沦 +我与网吧老板娘 +makelove +毛新闻出版总署 +密穴 +dragon +27dy淫色贴图 +十八岁禁入电影 +WEB牌戰 +The Best by Private 71: The Best Little Horny Asians +和两勇男玩14P +龟公 +毛你爷爷的 +奸淫电车 +包皮 +厕所盗摄护士jiejie +舌头穴 +毛贱货 +淫奸阿姨论坛 +毛僵贼民 +淫奸小姨子 +滾那嗎B +itembay +和两勇男玩13P +台湾成人19贴图 +肉棒好粗 插 +韩光 +熟女護士亂舞 +痴美女醫生松島 +豐唇豔姬 +吗啡 +基督 +经典炮图 +日片罕见3P加肛交 +爱液 +全家死光光 +和两勇男玩16P +屄……爽死……了……嗯……嗯……快……快 +精选明星扒b图 +灵游记 +運营組 +淫液沾满阴道 +做爱大全 +田纪雲 +毛仆街 +cdjp李鹏* +大鸡巴干妹妹 +ti ti qiu +色情 导航 +三民主义 +毛阴茎 +公告消息 +私¥服 +毛一国两制 +和两勇男玩15P +jiao chun +贩毒 +igxe +情色导航 激情爽电影 +插入蜜穴 +毛嫩b +作爱 +阴茎插小穴 +高級逼 +美少婦 +射精女皇系列Ladies In Lust +高潮 +fuck外 挂 +免费激情网 +淫液从密穴 骚穴 嫩逼里流出来 +氢弹 +俄罗斯美少女惨遭蹂躏-嫩的不能再嫩 +漂亮女站着撒尿躺下被操 +發$$論 +朝天穴 +创世之子猎艳之旅 +阴茎被火热而湿润的阴道所包含着 +毛嫩B +毛六-四 +jinku +劍俠情緣OnlineII +蒋彦永 +av貼圖 +激情 电影 +陈良 +MM视频聊天室 +叫床 +沙僧 +萬里 +中国激情淫色贴图 +12岁处女开包现场 +gang jia hong liu +髙潮 +中俄边界 +欲望成人3GP视频 +虎虎虎~ Tora-Tora Platinum Vol。1 金沢文子 +挂机 +毛发抡 +呆卵 +毛六。四 +外卦 +肉棒插入风骚少妇穴 +MM嫩穴 +少妇房中自淫,和两勇男玩3P,操得直叫爽 操日本淫女穴 +正清網 +好紧的阴户 +被10个猛男轮奸草得血直流 +情欲奸岳母 +林文漪 +狂插处女穴 淫水流 +情色導航 +激情套图 +倖存 +pussy +發掄功 +民意 +吳 官 正 +一面打電話給現任男友 +運營组 +操女人穴 色情贴图 性交贴图 +白石ひより-完全攻略 +狗娘 +新疆獨立 +邓 笑 贫 +陰締 +mland +下體 +插进鲜嫩的小穴 +你爺 +fuck尉健行 +迷魂药 +你爸 +mai骚 +科洛斯 +淫色俱乐部 +小嫩鸡 +红 色 恐 怖 +张昭富 +你爷 +奇淫宝鉴 +韩桂芝 +18dy淫间道 +勁舞 +午夜免费爽电影 +发愣 +大陆激情淫穴小说 +汕尾事件 +严家其 +粗大肉棒插入蜜穴 +103bb成人小电影 +最牛钉子户 +强奸21岁处女全过程/淫妹阴毛小穴 +干少妇小穴 +信号拦截器 +舔吮她的阴唇 +嫩穴狂插还流水 +zhan guo ying xiong +圣角色扮演学园 +色图乡 +a$shole +暴力虐待 +轮盘赌 +網龍 +艳乳 +淫奸熟睡的妈妈亚洲床上色情图库少女做爱 +杨林 +弟弟淫奸熟睡姐姐 +蝴蝶谷黄站 +又硬又粗的肉棒 +陽精 +Dick +法~~論 +变态 +毛二乙基酰胺 +爱滋 +日本成人激情 +fuck他母亲 +makelove +法@淪 +操淫荡 极品嫩穴操淫荡少妇 +抽插43岁处女meimei淫叫不断 +迅雷下载免费淫乱电影 +絲襪高跟 +春夏自由论坛 +20岁女大学生被强#(组图)全过程 +插他 +骚逼小姨 +抵制奥运 +全 國 兩 會 +观看淫电影 看完保证你打飞机 +汉奸 +美女嫩穴 +未满18岁的请自行离开 ! +日本成人激情淫穴 +封神榜 +操meimei +裙下風光 +两岸三地论坛 +牛B,牛比 +阳萎 +激情成人影院 +肉棒在阴道中疯狂抽射 +毛狗b +首長 +臺幣 +大会堂 +喔…快…爽死 +暴操淫荡小妹妹 +免费性爱电影网 +免費偷窺網 +窩窩客 +淫B浪穴 +强奸犯 +首长 +哪有a片 百万美女贴图夫妻激情免费视频 +又肥又紧的屄 +李宏旨 +xi you fu mo lu +避孕套 +黄色免费电影美女 +孫逸仙 +张伟国 +教你怎样延迟射精18岁以下禁 免费淫 电影a片 +新石器时代 +毛田纪云 +激情视频聊天论坛 +藏青社 +陰精 +RED HOT IDOL Vol。3 Concentrated Sex : 山咲舞 Mai Yamasaki 4 +成人激情asp电影通道 +乳此絲襪 +大鸡吧插meimei淫屄 +干您娘 +On Air +你他媽的 +淫水从穴门流出 +弟弟摸姐姐胸部小说 +密碼 +阿旺晋美 +嫩bb +日本無碼o ~幼齒女學生 +法^^淪 +G。M +吸毒犯 +三个代表 +綠色數碼 +温家宝 +肉棒插入子宫 +快干我!快干我┅┅我要被干 +我含着阴茎 +插你 +龔學平 +jinv +联众 +朱容基 +全球公審江澤民 +岡巒 +雞巴暴脹 +激情淫色网站导航 +抽插36岁处女妹妹淫叫不断 +MUGEN EX Vol。3 魅惑美少女 : 小日向葵 有码女优首度无码隆重登场 +复员 +激情裸聊 +亚洲淫影院 +欧美两性淫乱图片 +小雞巴 +穴口挤出淫水 +她的小穴插了进去 +porn +毛信访局 +外~掛 +比样 +運營者 +法~~论 +聚丰 +新绝代双骄 +手指插的进小淫穴 +肥嫩的阴穴 +捏弄 +联合国 +黃色影視 +倚天屠龙别记 殷素素 +蒙古達子 +阴蒂 +mythos +狂插 鸡巴狂插 +完全免费淫色电影 +美騷婦 +台湾 18 成人网 +弟弟淫奸jiejie论坛 +淫奸熟睡的妈妈 +窃听器 +独夫 +免费色情激情电影网站 +三級片 +eqsf +温家寶 +艳情小说 +fuck王乐泉 +外\挂 +鎮壓 +fuck温馨 +女友下班后被别人献花接走给操了 +抽插46岁处女meimei淫叫不断 +操你八辈祖宗 +中机电 +世界日報 +插你娘 +情色六月天mm淫乱 +39CK +王八蛋 +xinsheng +血逼 +裙下风光 +自慰 +下流地帶 +鸡巴插进了的小穴 +小泉 +亚洲/无码 +fuck小穴 +熟女乱伦联盟 +下流地带 +阴茎 +爱国者 +贼民 +哥白尼 +賤B +校园激情淫色 +爽女美图 +大便 +12次下跪 +王太華 +魏 新 生 +乳此动人 +淫亂軍團 +冈村宁次 +臺灣民國 +和条友做爱 +扒穴 +www。gpchina。com。cn +cao靠 +田紀云 +舔屄 +誘色uu +肏又嫩又紧的穴 +嫩穴肉縫 +賣B +985985 +txsanguo +美女主持27小时全天激情热舞 +干你媽b +流星學院 +少女嫩穴被插出血 +昏迷 +和两勇男玩29P +毛伊斯兰 +se淫乱jiejie小说 +舔舔私处meimei嗷嗷叫 +陆肆 +狗屁 +马的 +狂操搔逼妈妈 +狗屎 +炮友 +骚妹爽图 +阿芙蓉 +mbs +鸡巴 插 嫩穴 +刘少奇 +週六性吧 +做ai +AV女优 +阴莖 +日本激情淫穴电影 +吴仪 +毛反日 +挖挂 +愛妻淫穴 +淫荡老师穴 +无网界浏览 +18男人摸摸B +生命奇迹 +毛佛祖 +┅舒服死大鸡巴插 +舐她的小穴 +激情淫色视屏 +发~~仑 +淫奸处女穴论坛 +色空寺 +臺灣民国 +靖国神社 +毛学潮 +廖承志 +插你媽 +换妻 +meimei乱伦理淫穴 +崔英杰 +桃園蜜洞 +嫩逼 +他ㄇㄉ +大龟头在花心深处 +爆乳美脚RQ中出し鬼輪姦-- 森高レナ +爱的奉獻 +捅进了她的阴道 +台湾女人裸体贴图 +戴红 +毛观世音 +喷雾型迷药 +抽插31岁处女meimei淫叫不断 +王辅臣 +sm女王 +春光外瀉 +大学骚乱 +苯甲醯甲荃芽子堿 +啊雅娃娃 +二乙基酰胺 +牛比 +亚洲激情 贴图区 +黑白无常 +fuck性爱 +本站10003多部激情电影全部免费试看三天 +发~~伦 +性飢渴 +惹火自拍 +黄色免费超级淫图 +大乳 +美女插穴 +毛厕洞 +林彪 +极品成人电影 +和两勇男玩24P +傅铁山 +粗长的肉棒粉嫩的玉门里进出 +日本淫图 +龔学平 +幹GM +ㄐ掰 +军民冲突 +法~沦 +人肉 +萬鋼 +淫水流出图强*免费淫电影 +刘千石 +免费淫电影吴宗宪搞笑语录(18禁看) +哗哗曼 +性爱 图库 +共产主义 +抽插18岁处女meimei淫叫不断 +九评 +乱伦淫书丝袜淫图 +和两勇男玩23P +毛后庭 +免费淫奸女A片段试看 令人喷血的春宫108姿势(组图)18岁禁看 +小姐打飞机 +华通时事论坛 +迷姦雙胞meimei +免费淫奸黄色电影 +美少妇 +和两勇男玩22P +計牌軟體 +激情XXX电影( +徐匡迪 +生孩子没屁眼 +全球公审江泽民 +我草 +色弟弟 +无码片 +国民党万岁 +伸入姐姐裙内 +(盗摄)女子公共澡堂! +avi免费淫电影下载 +onewg +她妈的 +和两勇男玩21P +成人色网站 +少女一丝不挂做爱淫水直流! +爱的奉献 +朱毛 +亚洲黄站 +近親相姦 +点卡 +刘正荣 +开放杂志 +嫩穴肉缝 +妹妹等你大鸡吧来插 +毛客服 +肥西 +meimei┅┅爽快┅┅死了 +护士穴 +luan shi san guo +pp点点激情播放 +斧头镰刀 +胸罩 +公车淫奸meimei +裸聊日本成人电影 +毛狂操你全家 +日本淫色贴图区 +meinv做爱激情电影 +毛拉姆斯菲尔德 +淫奸嫂子穴 +和两勇男玩28P +胡主席 +三陪 +烂鸟 +(SOD)芸能人 範田紗の超高級ソープ嬢 +小骚比 +下阴 +桑國衛 +蔵獨 +遊戲管理者 +ying xiong wang zuo +弟弟mojiejie胸部小说 +盛大富翁 +台湾成人18贴图 +手记注册日韩5013部激情电影 +圣者无敌 +和两勇男玩27P +天主教 +龟头 磨蹭 插入 小嫩穴 +淫穴 夹 好爽 +弟弟淫奸jiejie +炼功 +免费淫奸女A片 +江八 +俏臀摄魄 +操薄一波 +作爱聚会 +和两勇男玩26P +cheng ji si han +品香堂 +李雪峰 +下陰 +kjking +近親相奸 +如果你未满32周岁请自觉离开。 +复制 +赣您娘 +驶你母 +貝肉 +國產AV +操操你妈 +365情色 +台湾身份证 +毛新义安 +肉棒在小穴里好爽 +濫比 +和两勇男玩25P +白癡 +吳邦國 +成人黄色电影 +毛台湾党 +我考 +於天瑞 +zlywy +漏B +插入內射 +國家領導人 +NND +肉棒刺入我的小穴 +免费淫奸女A片段试看 令人喷血的春宫108姿势 +册那娘饿比 +Poon Poon +法~~轮 +流星学院 +毛妈卖妈屁 +值勤 +打砲 +无关键词(导航搜索) +國軍 +鸡巴 嫩穴 淫荡 +SUCK +依星 +淫蕩 大雞巴 嫩穴 +simple +falundafa +亚洲激情妹妹 +大肉茎插进小肉洞 +毛亲民党 +國 賊 +教你怎样延迟射精33岁以下禁免费淫电影a片 +cabal +小姐打飛機 +黄色免费电影 +政治犯 +温家堡 +法$$纶 +wgpj +歡迎G12情色電影院 +倒塌 +NPC +手记注册日韩5015部激情电影 +唐人電視臺 +淫民俱乐部和meinv发春激情3级片试看 +滥货 +廖锡龙 +多人轮 +dse淫乱小姨小说 +13点 +海盗的悠闲生活 +公子冲 +偷情 乱伦 +狗干 +野外操B更刺激 +法^淪 +cao b +狗幹 +贱比 +老鸨 +凸肉優 +T。M。D +狂插meinv穴 +吞精騷妹 +发$仑 +新闻出版署 +白痴 +插 干jiejie 好爽 +妈的b +保监会 +美乳鬥豔 +滚那吗B +多人輪 +fuck王兆国 +笨比 +卖比 +操淫荡少妇 操淫荡妹妹 操淫荡姐姐 操淫荡护士 操淫荡 空姐操 老师操女老师 学生操老师 操老师小说 +妹妹美图网 +斐得勒 +娇妻偷欢超爽日本电影 +Red Hot Fetish Collection Vol。30 森田めぐみ +久遊 +和两勇男玩20P +杨月清 +成人午夜 +高文谦 +RI NI MA +激情爽电影,夜夜最消魂! +色网联盟 +吳儀 +zhengjian皮条 +超淫荡丝袜妹妹 +毛二逼 +YOUXIKA +妈的B +佳静安定片 +14se淫色图片 免费vagaa电影 免费电影 +NMD +毛恩格斯 +寂寞自摸 +生命奇跡 +欧美激情淫色贴图区 +新任教师の淫行物语 +610辦公室 +Red Hot Fetish 纹舞らん--スケパン刑事 +基地組織 +学生妹meinv在野外偷情 +援助交易 +23dy淫色贴图 +吳邦囯 +爷爷 +自拍 +法~~輪 +BlowJobs +学生暴动 +淫荡少妇露逼自拍 +梦幻西游 +郭 羅 基 +齐墨 +吾爾開希 +cao ni ma +幻靈遊俠 +fuck投毒杀人 +何候華 +雞歪 +手记注册日韩5000部激情电影 +激情玩穴网 +妹妹的嫩阴唇 +butthole +爸爸 +毛妳老母的 +管理员 +金酷 +meimei的屄 +马场大亨 +肉棒插入穴中 +学联 +淫荡妈妈之办公室助理 +发$伦 +计生风暴 +外_掛 +毛买财富 +肉蒲团 +挑战 +发*仑 +做爱爽图 +法$$綸 +tian zhi you xia +tom在线 +t2dk +taobao靠 +插你妈 +母子乱伦 +东条英机 +杨振 +周百刚 +毛主席复活 +亞洲互動 +站前留學 外國人英語會話教師的癡態紀錄 (3月作品) +浓浓的精液喷入了子宫 +mir +極品奶妹 +肉蒲團 +发$$论 +吞食天地 +中华养生益智功 +用手指玩弄着阴户 +法@@淪 +Biao子 +堕淫 +代練 +f_u_c_k +亲吻小屄 +Himiko 010 Riko Kurusu 来栖! 中出 +日本第一av女优武藤兰被10男糟蹋全记录1小时 +操濫妳那騷穴 +制服诱惑 +精液榨取 +毛澤東 +ALERT +cha你 +外_挂 +2。23会议 +boxun +產黨 +网爱 +陈破空 +管理員 +Pink Puncher~生中出SEX Ais Cumshot Inside Sex !! : 姬野爱 +色网阴道特写强奸31岁处女全过程 +操淫荡护士 操淫荡 空姐操 +壮汉给纯情处女开苞 +fa轮 +政府無能 +去你的 +黄色影视 +熟妇骚器 +斷電 +天安門事件 +毛吴官正 +毛食捻屎 +红楼绮梦 +asktao +毛发正念 +香港顶极淫片 +臺灣共和國 +色區 +色区 +网特 +外\掛 +小澤瑪利亞~~誘惑色情 +盐酸二氢埃托啡 +免费淫电影网址 +劍俠世界 +bt成人 +帝国主义 +大龟头碰到阴户底部最敏感的地方 +66xp。com 电影免费 +强*十八岁美女护士 看完保证你打飞机 +三唑仑 +成人图片 +zhengjian皮條 +李昌 +大肉棒干我的小穴和屁眼 +钓鱼岛 +吳 宏 達 +前凸後翹 +306醫院 +气性壞疽病 +戴相龙 +发*伦 +那嗎B +那娘错比 +21世纪中国基金会 +long hun +毛干七八 +插穴 +rxjhhvip +強姦物語 逢乃 +黑鮑娇 +老虎机 +fuck +蒋介石 +乱伦熟睡的jiejie +就去色色 +爆炸 +毛狗日 +六四死難者 +meinv +肉棒顶到花心 +Tora-Tora Platinum Vol。11 持田茜 +赵南 +毛社科院 +亚洲淫色图 +来爽我 +肉棒插进阴户内 +沈彤 +大鸡巴操得我好爽啊 +干阿姨的骚穴 +韓啟德 +推推俠 +在线清晰日本超爽mm毛 +好紧的小穴 +meinv视频短片 +苏晓康 +滕文生 +操射 +淫荡女mm的嫩穴 老师嫩穴 +sm调教 +郭 岩 華 +美乳看護學生 +毛胡耀邦 +netdream +幹死你 +何 德 普 +陰部 +柴玲 +毛死gd +免费淫奸女A片段 +插烂妹妹小屄 +外陰 +銀行帳号 +操草你妈 +两性午夜激情电影 +fuck售软件 +跳大神 +毛死gm +毛生孩子没屁眼 +汤光中 +日你妈啦屄 +推推侠 +小穴好紧 +女做爱光盘亚洲 +色魔 +天鹅绒行动 +发*沦 +乱伦熟睡的姐姐 +淫奸妹妹论坛 +香港GHB水 +高潮白漿 +淫色成人网址导航 +jing tian dong di +干老师的穴好爽 +色鬼 +和少妇做爱好爽 +法^倫 +震级 +万岁 +澳洲光明网 +淫洞 贴图 +一夜情交友 +咪咪圖片 +street of EROS 07 +street of EROS 08 +发~抡 +国产幼女屄屄套图 +淫女床上的自慰 +圓滿 +毛江泽民 +姐弟激情淫色 +狗城 +非常三国 +Red Hot Jam Vol。6 Chiaの露出初体験 +黄色图片 +20岁女大学生被强#(组图)全过程免费淫 电影 +好色妹妹电影做爱论坛 +bukake +平反六四 +非常三國 +姐姐的阴唇好大啊 +最淫成人贴图区 +da qing di guo +fuck吴 仪 +小鸡鸡 +成人网站 +fuck社会主义 +肉棒 ……好舒服喔 +圓满 +邪恶的党 +阴部翻过来看超拽 +千年 +张钢 +meinv插穴 +掰穴皮卡丘 +免注册台湾18dy +弟弟的大肉棒 +三国策 +WANZ)强制猥亵 非合法ドラッグ +妹妹的阴道真紧 +毛妈批 +东突暴动和独立 +精液射进小姨的子宫 +舔舐着阴道内壁 +少女免费激情电影 +毛皮条 +鹿城激情淫色贴图 +強制浣腸 +操打炮 +毛身份生成器 +毛睾丸 +法^侖 +红卫兵 +操抽插 +美仙子 美乳+美腳 天中梨子 +o2jam +免费淫奸女A片段试看 20岁女大学生被强#(组图)全过程 +生殖器 +小穴任由大鸡吧来回抽插 +美脚残酷物语膣壁浸透汁 +毛强效失意药 +處女小穴 阴毛 +淫奸处女 +yutong +亂武天下 +乱伦 +幹砲 +西游伏魔录 +和妈妈玩插穴 +萨斯 +大胆出位 +meretriz +毛肉洞 +大衛教 +黃色網站 +发$沦 +秘密調教凌辱 +fuck西藏独立 +三句硬话 +澳洲光明網 +快活林黄站 +fuck煞逼 +免费黄色网站电影 +幹你良 +hotsex +買月卡 +LineageⅡ +熱血江湖 +去妳妈 +日韩meimei嫩穴淫图 +乳交 +在线激情电影 - 会员注册 +fuck台湾共产党 +美體豔姿 +毛精子 +蠢猪 +mm美图 +女友坊 +肉棒快速抽插 +林心如做爱*色情电影*免费淫电影a片 +林肯 +淫乱军团 +法^伦 +毛小乳头 +中國 +免费淫 电影 +好色cc +台湾色色导航 +毛澤东 +抚弄后插入小穴 +中国 +淫奸电影 +推翻 +vaameline +日本美女图库 +亚洲成人激情影院 +超级樂者 +毛阳具 +抽插50岁处女meimei淫叫不断 +连邦 +露穴 +激情文学区 暴乳母娘 国外淫色贴图网址 +DICK +卖。国 +淫乱秘史 +台湾裸体贴图成人免费电影 +男人最爱的淫图 +裸体少妇 +mm美圖 +di guo chuan qi +乱交 +如果你未满22周岁请自觉离开。 +不用注册淫电影网站 +肉棒好粗 +天安門屠殺 +黄色免费电影meinv +内射魅惑の美少女精液滋滋往外冒 +肉棒插入嘴 +絲路傳說 +天閹 +毛弓虽女干 +蒸汽幻想 +林业局 +新唐人電視臺 +毛孙逸仙 +李 旺 阳 +操屄 +毛丫头养的 +妹妹的屄好紧啊 +Gold Angel Vol。8 Super Erotic Girl : Rio Nakamura 仲村りお +操陈水扁 +我和小姨淫 +姚依林 +你的小穴好温暖… +群阴会 +遊戲指導員 +毛国务院 +两个中国 +毛工力 +妹妞露穴 +毛枪决女犯 +在线淫洞影院 +操尼 +thsale +最新娱乐黄站 +处女性开苞 +孤儿 +pk1937 +毛片 +発射 +成人午夜激情电影 +发@沦 +装屄 +金发表姨子的鲜嫩蜜穴 +恋爱盒子 +台湾成人23贴图 +凯图科技 +九評共產黨 +RED HOT JAM 7 Eeos Note 姬崎水希 +aion +江折民 +肉棒插入肥肥的淫道 +孤兒 +粗大的龟头 +黄色漫画 +王涵万 +圆满 +台湾党 +插婷婷小穴 +奸淫少妇穴 +天安门惨案 +疯狂抽插嫩穴 +日本淫色贴图 +肉棒插进蜜穴 +天阉 +meinv激情性交射精电影 +2逼靠 +那吗B +李 旺 陽 +香港成人色网址大全 +爛比 +法^仑 +总理 +妳媽的 +圆滿 +unixbox +肉棒的抽插淫荡少妇穴 +军转 +欧美成人激情网站 +毛日你娘 +抽插25岁处女妹妹淫叫不断 +毛新党 +被老师强奸的小初中生 +手记注册日韩5018部激情电影 +黄色免费电影淫电影在快要射精时迅速地将 +慰安婦 +高麗棒子 +姐的嫩阴道 +顶到花蕊 +Ttmd +Gate To Heavens +压/无码 +棒阴道好痒痒 +弟弟的肉棒好粗 +用力刺激小穴 +干小姐小穴 +taobao +我的小屄儿好痒 +阴道图片 +私**服 +sars +张震 +性交課 +免费淫虫在线看电影 +麻醉钢枪 +强奸29岁处女全过程/淫妹阴毛小穴 +性爱擂台 +激情 少女 成人论坛 乱伦 +星際online +柯慶施 +法^^沦 +真理教 +中国美女淫色贴图 +gc365 +21cn +高潮白浆 +人民報 +成人午夜激情聊天室 +毛日你妈 +幹穴 +精子射到妈妈的穴里 +毛狗操 +中宣部 +毛佛展千手法 +王希哲 +妈妈你的穴好紧 +摩门教 +龙虎 +操淫荡妹妹穴 +妈个比 +GM美国 +血洒 +美利坚 +淫meimei电影论坛 +wai gua +血洗 +中天万方 +┅┅妈舒服死了 +GM美國 +毛金日成 +龟头抵制花心顶住子宫口 +李 少 民 +亚洲贴图区月宫 +狂插 嫩穴 +搜狐 +meinv主持24小时全天激情热舞 +勾魂少妇 +caoB +勾魂少婦 +KISS +免费在线淫电影欣赏 +Red Hot Idol Vol 1 +毛六四 +蒙古达子 +干炮插穴 +冊那 +解放军306医院 +共产党靠 +肉棒插入浪穴 +to173 +外@@掛 +性病 +女儿的阴道好嫩啊 +免费淫电影a片。母子淫*乱轮现场看扶正肉棒 +香港免费淫电影 +上妳 +毛苹果日报 +范田紗~120%!H喜不自禁住在一起日記 +阴茎把淫穴塞满 +教你怎样延迟射精18岁以下禁免费淫电影a片 +Priston Tale +先审后贴 +卓奥 +soma +K他命 +李文斌 +钦 本 立 +卓奧 +奥运 +新诗年鉴 +globalrescue +免费淫色电影下载 +压制 +淫荡家族群体性交 +meinv激情视频聊天室 +干全家 +互联经纬 +脫衣舞 +吴 百 益 +藏妇会 +分家在 +毛美国之音 +933cn +五星红旗 +插你老母 +淫奸护士穴 +鸡吧刺入她肛门 +中国娱乐黄站 +骚浪淫水的小屄儿 +麥角酸二乙基酰胺 +qi ji shi jie +色色连 +龍與地下城 +社。會。正。義。力。量 +弓雖 +慰安妇 +嗯…… 啊… 不要停…… 啊…… 插的再深一点… +yxzbw +奧運 +干穴 +指点江山论坛 +幼男做爱妹妹做爱 +淫奸阿姨穴 +八九风波 +白小姐 +毛董建华 +毛外\挂 +错那吗比 +pp241淫色导航 +毛外汇局 +假阳具插穴 +艳妇淫女 +本站10002多部激情电影全部免费试看三天 +哥哥淫奸meimei穴 +交换夫妻 +兴奋剂 +风月大陆 +东正教 +扎卡维是英雄 +成人电影 +無碼炮圖 +法功 +淫水嫩穴 +國 家 安 全 +靈遊記 +毛迷歼药 +弓虽女干 +亚洲成人激情视频 +94bb成人小电影 +家庭乱伦小说 +mforest +圣母 +马巧珍 +毛外_挂 +情报 +创网 +册那 +可爱双胞胎美幼少女的性趣[亚无][402mb] +毛铁道部 +game588 +大鸡巴狠狠插进了她那又肥又嫩的小骚屄儿 +高治联 +二穴中出 +无码体验 +汶川 +实现你的幻想 +塞你公 +外@@挂 +日本18淫电影网 +咪咪图片 +情色谷 +奸淫护士穴 +卡通美女淫色贴图 +剑网 +发^抡 +口交 +自由民主论坛 +扒开她两扇阴唇 +免注册在线淫电影 +反党 +毛死GD +大血比 +kqking +泄密 +骚鸡 +淫荡痴女贴图 +幹你老母 +一邊一國 +成人色情网站初中女生偷拍 +毛死GM +dick呂秀蓮 +発妻 +外教上课迟到就挨操 +fuck射精 +幹你老比 +mm乱淫自拍图片 +激情淫色mp3 +儿子的肉棒顶到妈妈的花心 +毛狂操 +水浒 +爱女人 +新华社 +71776 +法@倫 +垃圾游戏 +……浪穴……大肉棍 +巴赫 +分裂 +毛李登辉 +pp点点激情 +淫色搔女网 +鸡巴对准淫穴 +毛李红志 +淫女穴 +美乳斗艳 +毛天鹅之旅 +凌辱 +勁爆 +狗卵 +nana无修正AV女优ハメ撮り +弟大物勃 +北京当局 +天天干貼圖 +戴 相 龍 +88jb +roi world +共和国卫士 +fuck审计署 +汇款 +反共 +领取 +游戏橘子 +性交课 +煙膏 +大鸡巴干meimei +六合采 +anal +分裂国家 +姐弟淫乱还玩3P +毛系统公告 +法*功 +免费妹妹黄色淫乱电影 +淫賤少女 +光之國度 +火麻 +戴 相 龙 +騷妹妹 +金鱗豈是池中物 +男女激情淫乱图片穴 +肉把鸡巴包得紧紧 +東北xx網 +closeupsof。us +洪传 +受虐狂 +毛警匪一家 +毛龟公 +操操蛋 +毛睾 +毛五星红旗 +拉姆斯菲爾德 +fuck西藏天葬 +狗狼養的 +買春 +fuck王岐山 +免费淫色情电影 教你怎样延迟射精18岁以下禁 +阴道图打手枪专用 +媽媽的 +又肥又紧的阴道 +高清性愛 +淫奸处女电影 +克林顿 +办理证件 +毛发抡功 +毛傻比 +成人图片导航 +激爽电影VIP会员注册区 +刀剑•英雄 +色情工厂 +ji女 +不要注册激情免费电影 +系统 +午夜成人场 +陳水扁 +你媽的 +毛煞逼 +納粹 +毛游戏管理员 +毛性虐待 +康生 +超級樂者 +雞8 +亚洲成人午夜场 +fuck王刚 +注册通道看情色电影 +色网阴道特写强奸26岁处女全过程 +布雷尔 +受傷 +gamemaster +人妻交换 +抽插29岁处女妹妹淫叫不断 +乱伦都市 +fuck系统讯息 +受伤 +olgad +淫妻浪女 +男人若妻夢交 +秦晋 +Tokyo Hot n0156~160合集收藏版 +操淫荡少妇 +戈万钧 +wg886 +捅逼 +走光 +Suck +父女激情淫色 +操你八輩祖宗 +毛何候华 +保卫台湾 +肉棒插蜜穴 +抽插53岁处女meimei淫叫不断 +白虎嫩B +达尔富尔 +毛阴唇 +法@侖 +政协 +激情自拍小电影 +趙 曉 微 +政協 +抽插55岁处女meimei淫叫不断 +高橋英4套片合共 +少妇自慰 +狗剩 +操淫荡少妇 操淫荡妹妹 +白虎嫩b +儿子淫奸姐姐 +八九民运 +毛升达毕业证 +被幹 +王炳章 +助理 +卵子 +本拉登 +翘臀嫩穴 +被干 +毛肉棒 +哥哥干的人家好舒服啊 +沧澜曲 +月宫套图社 +法lun功 +教你怎样延迟射精36岁以下禁免费淫电影a片 +操mm穴交 +陰門 +催情药 +中华 +激情淫影院 +日本灌肠 +suck你媽的 +在线淫电影,免费淫色情电影 +激情四川方言版 +高 潮 喷精 +姦淫電車 +姬胜德 +蔣經國 +我你老板 +韓正 +手记注册日韩5012部激情电影 +李 月 月 鳥 +人妻交換 +前网 +transexual +低價金幣 +台湾成人24贴图 +hardcore +女儿淫奸妈妈穴 +日本顶级淫片 +摸擦小肥穴 +卡卡金币 +14色se成人站 +性学教授 +小阴唇被鸡巴猛的塞进去 +法@伦 +龙腾工作室 +妳老母的 +李紅志 +現役看護婦 +毛肉棍 +大鸡巴插入肉穴 +8。9 +軍民衝突 +中功 +精品性交图 +瑞士金融大学 +系统消息 +邻居美少妇 操淫荡少妇 +成人色情导航 +完全免费在线淫电影 看完保证你打飞机 +色狼俱乐部 +滾那嗎老比 +孫中山 +陰阜 +淫电影//居然花钱请人教性爱姿势(组图) +可卡因 +色情电影 +张林 +税务总局 +meinv淫图 +qqyinsu +mystina +淫图新社区 +鲍戈 +妈妈嫩穴…痒 +血比 +piao liu huan jing +天之煉獄 +顏射 +午夜激情妹妹 +馬巧珍 +姑妈的阴道好紧啊 +处女开包 +现役看护妇 +亞洲性虐 +法@仑 +日你全家 +她媽的 +發~~掄 +去她妈 +姐姐的阴道好紧啊 +分裂國家 +毛淫荡 +365 sex +毛联合国 +…你的穴太紧了 +tie jia zheng xiong +招鸡 +久遊網 +fuck倭寇 +本站10022多部激情电影全部免费试看 +大 史 记 +若叶~Princess Collection(1163) +极品波霸 +丁香社区 +发仑 +张志清 +毛钱其琛 +特种部队 +狠狠地肏 +丁香社區 +李 月 月 鸟 +┅我要泄了┅┅喔 +无毛穴 +camon +王 冶 坪 +操我 +金鳞岂是池中物 +发伦 +hai dao shi dai +long yu di xia cheng +干七八 +毛高丽棒子 +天骄 +ezgaming +日本灌腸 +X媽牛比 +少妇的骚穴淫液 +你的大鸡巴好粗 +成人激情论坛导航 +李洪智 +狗养 +赤匪 +xin chang zhi ye wang +劲爆 +处女淫荡色情网址大全 +混 沌决靠 +陳雲 +美女小穴贴图偷拍少女乳房 +江独裁 +lihongzhi +小乳頭 +大话战国 +性色社区 +淫荡俱乐部 +街头对抗 +母子乱伦之淫穴 +兆鸿 +敬國神社 +杜鲁门 +毛回民暴动 +扎卡维 +国家总理 +那吗老比 +賽妳阿母 +天龍八部 +法腀功 +比的 +台獨分子 +鲍彤 +六四平暴 +野合 +酥胸誘惑 +大法弟子 +公审江泽民 +可卡叶 +韓啓德 +毛江主席 +光之国度 +在线免费激情裸聊 +搞B +拿破仑 +法西斯 +赤化 +政变 +AV足球賽11男VS11女大對決 +毛环保总局 +洞洞淫水清晰大图 +针对台湾 +独立台湾会 +儿子顶到姐姐的花心 +傭兵傳說 +懆您娘 +四海龙女 +发^^仑 +帳號 +领土 +穴图 +xing kong huan xiang +webgame。com。cn +色链 +杨尚昆 +阴唇 黏液流下 +粗大的鸡巴插入穴洞 +強姦處女 +东升 +法*倫 +現役看護婦下载 +圣火 +办理文凭 +公交车上操女大学生 +强暴 +淫荡女护士 +穴圖 +少妇房中自淫,和两勇男玩1P,操得直叫爽 操日本淫女穴 +亚洲午夜成人影院中心 +快克 +三K党 +克林頓 +护士脱衣图台湾激情电影 +免费淫电影 看完保证你打飞机 +fuck网管 +少妇嫩穴扒开嫩穴扒开嫩穴 +pcik +薩達姆 +色情小说 +手记注册日韩5023部激情电影 +成人电影免费成人电影 +法国 +发^^伦 +激情成人淫片 +妳她妈的 +人大代表大會 +成人论坛 +張震 +逼你老母 +李 文 斌 +操日本淫女穴 +精蟲 +中共 +毛三陪女 +啊……快插啊……小屄美死了 +陳奎元 +大波騷婦 +小骚洞 蜜穴 +本。拉登 +成人导航 +黑星女侠 +纪登奎 +毛管理人员 +牛逼靠 +刘亦菲淫阴道流血色片 +懆您妈 +发**轮 +黄色免费淫乱电影强奸片 +毛共匪 +扒开嫩穴 抚摩她的嫩穴 下身也不停的抽插着 +rxjhvip +ハイパー×潮吹きハイパ 麻美ゆま +U/R靠 +媽B +habbo +japansweet +dekaron +淫色小说网短片色情 +阿扁萬歲 +香港激情淫色区 +鸡巴插进娇嫩的花蕊 +法*侖 +阿姨的阴道好大啊 +兆鴻 +u r靠 +妈逼 +情色照片 +紧穴 +神州天戈 +瞳-饮精地狱!监禁无限中出 +哥哥使劲插我 +野鸡 +贺国强 +強暴 +毛看棋软件 +免注册淫电影爱的色放 +血腥图片 +民航局 +処女強奪3穴串挿輪姦 +毛日你 +53xp。com 电影免费 +法$倫 +操那吗比 +鹽酸二氢埃托啡 +射进小穴 +粗硬大肉棍… 抽动…好舒服 +本站10013多部激情电影全部免费试看三天 +视频聊天导航 +騷婦掰B +模拟机 +乳此丝袜 +掰穴打洞 +死全家 +法^^抡 +偷情宝鉴 +安南 +58jb +傻× +吴方城 +宋楚瑜 +森水Cocoa +立即登陆观看激情爽片 +上海孤儿院 +强奸 +肉棒噗嗤一声插入阴道 +工自联 +日本成人贴图区论坛 +午夜剧场成人视频聊天 +淫荡美眉就喜欢玩男人 +做愛寫真集 +阴道 +直操她嘴射精 +强奸44岁处女全过程/淫妹阴毛小穴 +xing zuan wu yu +project +淫水四益 +阴茎在子宫口游荡 +淫水絲襪 +幹炮 +人民币 +公车淫奸jiejie +装逼靠 +小穴被大鸡吧胀的好痒 +卡弗蒂 +色狼论坛 +免费淫色贴图 +烂逼 +中南海 +昝愛宗 +骚穴怒放 +毛他妈的 +干进妹妹的小穴 +鸡巴用力深度插入 +淫奸jiejie论坛 +媽比 +姐弟激情淫秽 +计牌软件 +伊拉克 +成人影視 +下载黄色淫乱电影 +都市乱伦 +日本情色淫电影 +垮台 +VIP特区 激情在线 +fgmtv +肉棒深深插入纖弱的肉洞裡 +青天白日 +feng wu tian jiao +鹿城娛樂 +傻b +穴居人淫色贴图 +共黨 +B博士 +新魔界 +封神传说 +東方資通 +免费在线淫电影网站 +宾馆女郎 +性感肉丝 +中共中央中华人民共和国 +毛多维新闻 +打倒中國共產黨 +caobi +18dy影院 +舔哥哥鸡巴 +情妇 +杨白冰 +成人影视 +清纯派美女可爱的让人想狂干她!【RMVB/195MB】 +hero108 +淫语痴女 +大 史 記 +日你妈靠 +色天堂18禁 +毛淫货 +眾志成城 +肉棒狂插好爽 插我 +華夏II Online +干爆 +华建敏 +毛淫贱 +你妈靠 +少女被强奸到高潮时偷拍小A片 +毛肉棍子 +街頭籃球 +毛人代会 +他吗的 +韓桂芝 +人民幣 +自由亚洲 +湿润的花蕊 +jiejie的小穴被大鸡巴插得好舒服哟 +毛发轮 +靠母 +發~~淪 +法鯩功 +厕所偷拍 +強姦 +欧美淫乱美女论坛 清晰的窥阴图 +六四参加者回忆录 +大粗肉棒插入阴户 +本站10014多部激情电影全部免费试看 +四清 +FUCK +qeeloo +江氏 +达赖 +台湾分裂 +肏我的小屄 +卫生棉条真人使用图 +李弘旨 +色情淫图 +做愛自拍 +mm在线电影a片3级片 +极欲燃烧 +中国人都在上的四大当 +东热空姐 +儿届中央政治局委员 +操穴喷水 +fuck十八摸 +金币网 +杀人犯 +校花沉沦记 +少妇野外淫穴 +免费淫色妹妹电影 +干炮 +叼你 +插在小穴里的肉棒 +吴百益 +功夫online +teen +真三國無雙OL +免费淫奸女A片段试看 教你如何鉴别处男处女的方法(组图)18岁禁看 +肉棒在阴道内喷射 +梦中的女孩 +怎样延迟射精25岁以下禁 +testicle +非洲 +肉棒深入花心 +天皇陛下 +bignews +色妹妹大型黄站 +哲 民 +淫奸少女贴图淫奸女护士贴图淫暴亚洲 +破鞋 +賣淫 +地震局 +暴行白書女 +好死不如赖活着 +自由亞洲 +mm电影小片段试看免费淫影片 +体育总局 +达賴 +fuck威而钢 +天安门屠城 +免费激情电影 爽电影 +激情书屋男女做爱片段 +幼齿 +迷藥 +灼热的龟头紧顶住柔嫩的菊花口 +朱蒙 +午夜激爽电影网【成人电影色区】 +歐美無套 +毛外-挂 +鸡巴狠狠插入娇嫩夹紧的阴道中 +馬萬祺 +淫色电影论坛 +safeweb +SpecialForce +曰GM +紅頂商人 +肉棒深插 +狗乘 +丝袜淫妇 +咪咪情色 +私服 +傻B +hun luan mao xian +淫乱金发meinv +亂世三國 +阴部 +插嫩穴 淫水流 +玩弄她的骚屄嫩肉 +幹bi +你姥姥的 +爽爽爽台湾成人贴图 +曰Gm +毛外/挂 +《金瓶梅》的巨著 +插我 用力插 好爽 +webgame。com。cn靠 +无码内射 +淫荡痴女 +大鸡吧寸寸深入直顶她小屄的花心 +女同志淫乱贴图 +性爱频道 +激情淫色动画片 +操你全家 +掌上书城 +毛妓女 +毛水去车仑 +操操 +英雄纪念碑 +双峰微颤 +妹妹穴 +教你怎样延迟射精19岁以下禁免费淫电影a片 +毛国际法院 +毛黄 菊 +大鸡巴顶进meimei的花心 +nigger nigger +磕药 +情報 +wg17173 +买卖枪支 +強衛 +fuck五星红旗 +哥哥的肉棒好长啊 +专制 +火線任務 +幸运抽奖 +洗脑班 +教你怎样延迟射精24岁以下禁免费淫电影a片 +毛胡紧套 +塞你娘 +灭绝罪 +尖阁列岛 +龙 虎 门 +舔的下体湿润阴毛 +丽春苑 +陈晓宁 +乳 +骚屄娘们儿 +发~沦 +激情热舞 +prostituta +禁断少女 +老少乱伦 +hang hai shi ji +激情小电影 +幹妳媽 +手记注册日韩5001部激情电影 +郑万通 +成人小說 +强奸30岁处女全过程/淫妹阴毛小穴 +狂操你全家 +按摩棒 +台湾成人21贴图 +孫家正 +郑源 +美女口含鸡吧玩内射 +赛你娘 +小电影免费看高潮屋贴图做爱视频表演 +日本美女鲍鱼贴图区 +av贴图 +民主潮 +(人妻。com)人妻の情事2 夫以外の男に中出しされた妻たち +装备展示 +婷婷淫色贴图 +做爱视频下载 +毛切七 +鹿城色妹妹大型黄站 +106bb成人小电影 +中国大型免费成人黄色图片区 +毛牛比 +操博讯 +免费免注册淫电影 +姨妈和我乱伦理小说 +猛插小嫩穴 +台湾成人视频聊天 +meinv激情SM处女淫水 +雪山狮子 +民猪 +豖者 +錢其琛 +毛官商勾结 +台灣倫亂網 +天之游侠 +美女穴 +煞筆 +黄色靠 +freenet +毛贾庆林 +开房 +操催情药 +怀念十五年前的大学生 +冰锋 +mankind +子宮 +本站10017多部激情电影全部免费试看 +子宫 +次郎 +吕秀莲 +玩3p色链 +希拉克 +特別公告 +煞笔 +youxika +吸精痴女 +你把妈的穴穴插满了 +一夜情 +肉缝 小肉穴 +仆 +sealonline +巡查员 +回民 +毛王八蛋 +mierda +大麻 +xin chang zhi ye wang +激情解码两性电影 +亞洲風暴情色 +交通部 +毛狗屁 +赛妳阿母 +狂插meimei穴 +毛毛XX +对日强硬 +五月四日 +遗精 +毛狗屎 +毛温家保 +洪兴 +弓雖女幹 +轮流执政 +發掄 +流亡 +操大*FA弟*子 +最大的性虐待及另類性生活網站 +粉嫩淫臀 +韩国三级电影 +无码做爱 +反华 +欧美激情淫色贴图 +淫东方 +淫語痴女 +nude nude +新唐人电视台 +毛奶子 +毛军委 +毛新光明 +叛党 +法^^掄 +毛王岐山 +民进党 +廖晖 +香港激情论坛 +黃易群俠傳 +qi xia +李沛瑶 +王洪文 +ling tu +龟头顶在花心深处 +丁字褲翹臀 +廖暉 +又骚又大的屄 +姣西 +巡查員 +激情淫穴小说 +信长之野望 +六四死难者 +姐姐的阴户好嫩啊 +免费成人电影 +驶你老师 +美女下体淫水直流 +口交靠 +小姨令我射了好几次 +极品奶妹 +淫戰群P +毛鸡芭 +毛严方军 +林心如做爱网 +兩腿之間 +那嗎老比 +干爽 +坐庄 +三国群英传OL +烂货 +免费淫奸女A片段试看 强*十八岁meinv护士 +和姐姐肏屄 +成人小说 +幹妳娘 +天天情色 +磕藥 +干牠 +反動 +色书库 +六。四事件 +13點 +反动 +epochtime +厕奴 +女醫師過度輪姦陰道麻痺+大量中出強制飲尿小便斗 +鸡巴插入肉洞 +教你怎样延迟射精21岁以下禁免费淫电影a片 +佣兵传说 +foutre +mao xian dao +親 日 +發**綸 +弹 劾 +silkroad +厕所盗摄护士姐姐性感美腿图 肉丝美腿艳情淫欲 +十年動亂 +漢 奸 +萬歲 +毛军妓 +百家性黄站 +家乐福 +田紀雲 +又猛插几下 +儿子淫奸jiejie穴 +王永生将军 +本站10016多部激情电影全部免费试看三天 +jiejie的阴户 +si lu chuan shuo +美女激情SM处女淫水 +大揭露 +于大海 +操大便 +粗大的肉棒 +盛大 +弟大勿勃 +李兰菊 +阴道口湿淋淋的 +家庭乱伦 +少妇操尿穴 +東突 +本站10015多部激情电影全部免费试看三天 +大富翁 +捐款名单 +毛胡乔木 +口圭 +将肉棒插在阴道里面 +討伐中宣部 +淫meimei成人娱乐 +fuck傻吊 +米青 +ghost +大 紀元 +藏青会 +反人类 +吾爾開西 +又肥又嫩的阴户 +政治協商會議 +日本激情淫影片下载 +劍俠情緣 +遊戲蝸牛 +它妈地 +又骚又淫的屄 +Kamikaze Girls Vol。 27高清晰版本 +Archlord +爆操 +皮条客 +免费淫奸女护士图片 +淘宝靠 +儿子淫奸姐姐穴 +肉棒狂插流出淫液 +丁元 +淫民激情文学图库 +龟头直抵子宫口 +远程偷拍 +bt淫色电影免费下载 +meimei淫图 +国产无码 +操林 +毛斧头镰刀 +淫阴贴图 +fuck you +法~倫 +古龙群侠传 +共产党 +星鑽物語 +淫水狂流 +白立忱 +抽插33岁处女妹妹淫叫不断 +毛王太华 +毛龟头 +aids +一中一台 +带练 +fuck天安门一代 +一党 +操meinv穴 +张万年 +神淚 +激情成人午夜 +99bb成人小电影 +毛他祖宗 +那娘瘟比 +粉穴嫩逼 +粉嫩粉嫩的小穴流水 +精液喷射小穴 +勁舞團 +死刑枪毙 +至淫绝地 +农业部 +fuck fuck +扶不起的阿斗 +插后庭 +淫荡美女医生 +meimei的穴好多水 +和阿姨玩插穴游戏 +看棋軟體 +石首 +公審李鵬 +洛奇 +密传 +真主 +手指用力扣进小穴 +阴茎被肉壁紧紧的夹着 +毛驶你老母 +淫液流入穴 +姊姊的小骚屄 +无疆界 +雨星网 +东亚 +apex +性感美女淫穴 +阴唇 口含鸡巴 +艾森豪威尔 +淫液顺着肉洞流下 +日本激情淫穴片 +自插小穴 +urban +自慰摳穴 +一根材激情五月天 +毛狗娘 +极品激情电影 +干 …插我的穴 +美女鸡吧图 +韩日成人激情影院 +硕大的肉棒 +夢~ Pure Idol Vol。 20 : 望月なな +色情电影免费看 +毛外—挂 +军国主义 +淫乱姐姐小说 +hacking +在线淫电影 免费淫奸女A片段试看 +操护士的穴 +自拍美穴 +成人黄色网站 +不玩了靠 +上海帮 +啊 ……用你的鸡吧插我 +法~侖 +叛國 +学生爱国者运动 +婁義 +日本淫色动画片 +粗……肉洞 +挺进小穴 +强奸25岁处女全过程/*妹阴毛小穴 +倚天二 +叛国 +大鸡巴 用力地干 +wg666 +莲花逼 +毛监察部 +操大东亚共荣 +将肉棒插进她身体的最深处 +夫妻俱乐部 +欧美淫乱meinv论坛 清晰的窥阴图 +戳B +狼族淫色群交蜜穴 +fuck圣女峰 +台湾建国运动组织 +黑鬼 +wulin2 +抽插49岁处女meimei淫叫不断 +一股滚热的精液从插得紫红的龟头马眼里激射而出 +淫电影 强*十八岁meinv护士看完保证你打飞机 +fuck文物局 +国家机密 +婷婷激情俱乐部 +保密局 +1989 事件 +英雄王座 +肉棒狂插 浪穴 嫩穴 +毛发论 +肉棒顶开阴唇 +男女激情电影 +它爸爸 +情色藝術天空 +Red Hot Fetish Collection Vol。 34 : Saito真央 +激情淫色网站 +下作 +日韩淫女电影 +龟头在阴道里抽插 +下体 +meinv发春激情在线电影 +行房 +shao lin chuan qi +爆乳娘 +大东亚 +曰gM +上你 +哥哥粗大的肉棒 +我漂亮的老师狗爬式做爱现场 +戳b +傅作义 +发展研究中心 +系統管理員 +奶頭 +七五事件 +曰gm +法愣 +干进她穴内的龟头 +LIHONGZHI +陰部特寫 +插进少女粉红阴道 +Fuck +生春袋 +素人娘 +抽插31岁处女妹妹淫叫不断 +MAKINGLOVE +羅富和 +ㄙㄞ你老师 +色meimei乱伦理小说 +enculer +スクールガール 直美 +母子淫奸乱轮现场看 +猛嫩穴把肉棒包得紧紧 + Maki +儿子的大肉棒 +妹妹的嫩阴户 +jian xia qing yuan +毛蒙古独立 +靠爸 +淫师荡母 +延迟射精 +露B +发奖使者 +YGBH +激情网址导航 +女馬 +嗎逼 +狂插淫洞 明星陰穴 +karma +淫护士电影 +啊呀娃娃 +毛联易 +りすぎ家庭教師 ほしのキララ +震級 +露b +52淫色导航 +足球經理線上 +学生与警察 +海盜王ONLINE +大使馆 +Kamikaze Girls Vol。30-中野美奈 +香港激情淫电影 +帶练 +Tora-Tora Platinum Vol。11 S级圣女 持田茜 +熟妇人妻 +淫电影 +小穴……好爽 菊穴 +多维周刊 +古方迷香 +中华真实报道 +又大又硬的肉棒 +高校暴乱 +匯款 +白虎少妇 +色猫情色论坛 +刘宾雁 +你媽比 +侦探设备 +好长的肉棒 +乔冠华 +法~伦 +黄色三级片 +蔡崇国 +jianghu +温加宝 +学习班 +chuan shuo +反革命暴亂 +插妈妈的小穴 +lei ting zhan dui +濫B +发^沦 +废物 +李瑞環 +mo huan sen lin +唐家璇 +又鳥女幹 +www。qq965。com +运营长 +台湾成人22贴图 +阴阜 +刚发育好的处女就这么被干 +歇逼 +本站可能有不适合未成年人观看的内容 +噴精 +穴门美女图库 +蜜穴贴图 +淫奸mm电影 +护士诱惑 +郭罗基 +放尿 +放屁 +成人在线免费淫电影 +狂风暴雨 +不举 +法~仑 +星钻物语 +它妈 +shaolincn +鲜族 +阴门 +三夫妻结伴旅游换妻大乱交 +淫民激情文学图库欣赏 +反革命暴乱 +毛我操你 +毛欢城 +劍俠情緣II +mo擦小肥穴 +值勤帳號 +淫虎成人导航 +エロい女中出し20連発姫野愛 +淫奸小姨电影 +本站绝无任何形式木马病毒 +骚姐乱伦 +無套自拍 +白虎少婦 +test +毛麻醉药 +wu jin de ren wu +粗大的阴茎与紧窄的阴道壁之间的剧烈磨擦 +jiejie的嫩阴唇 +賣比 +張榕明 +口合 +慰春情 +偷窥无罪 +幼男 +凌锋 +xyd +黃色電影 +offgamers +贞操 +迅雷下载淫乱电影 +xyj +陰道 +盐酸二氫埃托啡 +台办 +姫野爱 +バコバコ风俗 W指名 遥めぐみ×美优千奈 A +賤比 +xyq +夫妻激情自拍图 +歡迎G10情色電影院 +插B +洪吟 +看单亲妈妈给儿子的性启蒙 +坦克宝贝 +性交靠 +ma chang da heng +懂文华 +售软件 +國權 +雞芭 +毛公安 +放荡熟女 +肉穴肥肥的裹着阴茎 +激情裸体 +抠 插 磨蹭 穴 +性免费电影 +黄色做爱电影 +西藏喇嘛 +六四以後 +插b +劍網 +王从吾 +麻醉药 +烫的大鸡巴在小穴里来回抽插 +免费视频裸聊 +丰满的视频聊天主持 +熊焱 +大鸡巴 插 少妇 +性爱 +处女膜 +吗个 +Pure Idol Vol。20 望月なな !【RMVB/543MB】 +和嫂嫂淫穴 +网络创世纪 +everstar +狂插妹妹穴 +小騷貨 +砍翻一條街 +操插gm +厕所盗摄护士姐姐 +李瑞环 +插你全家 +广电 +popkart +第九城市 +鬼畜輪奸 +fuck傻卵 +插小穴妹妹直流水 +出售账号 +迷药 +婷婷激情网 +肉棒插入又大又深的穴 +瘟比 +我使劲快速抽插龟头好麻 +插入她的搔B爽死了 +肉摩擦她处女的肉穴深处 +纶功 +插妹妹图 +外 挂 +激情淫贴图网 +狂插护士穴 +吮吸肉棒 +毛一党专制 +午夜情人 +BIAOZI +fei chang san guo +我操靠 +陈昌智 +操操逼 +妓院 +huan ling you xia +阳具在她的蜜穴里抽插 +卖国求荣 +他马的 +熊炎 +香港激情淫色贴图区 +8仙靠 +女马 +亲 美 +毛喷你 +大众成人网站 +捅进她的阴道 +政府无能 +姐姐被轮奸 +舌頭穴 +新闻出版总署 +催眠悪用集団轮奸30连発 +骚嫩的蜜穴紧紧地裹着大鸡巴 +操插gM +TTMD +Pink Puncher Premium Angel 光咲玲奈 +李洪志 +立花里子のレズビアン母乳M女コレクション +八九風波 +西藏獨立 +日本无码成人电影 +阿片烟 +大陆鹿城黄站 +操护士 +杭州二元 +共铲党 +激情淫色论坛 +激情淫穴小少妇 +法錀功 +亚洲色meimei +hellgate +www。gpchina。com。cn +王沪宁 +狂操空姐 +毛高校骚乱 +世模 +法轮功 +仙劍 +xiao yu er yu hua wu que +騷雞 +卫生巾 +fofg妈的 +干妳妈 +chinesenewsweek +彭佩云 +六-四 +淫meimei +粗硬 大 龟头 狂插 +rjwg +喷 +幹拎娘 +feng shen bang +教育部 +婷婷淫女小说 +荣毅仁 +Apexsoft +什麼什麼大冒險 +shen zhou tian ge +抽插小穴 +8仙 +豔照門 +仙剑 +臭西化 +熟母 +d7se淫色贴图 +騷B熟女 +免费淫电影在线观看 +H淫乱乳娘 Tora Tora Gold Vol。23 星之雪 +法@掄 +homosexuell +豬操 +江猪 +新義安 +万淫堂 +令人喷血的春宫108姿势(组图)19岁禁看 +BT亚洲无码影片 +肉棒小浪穴┅ +爱幼阁 +布莱尔 +JHSZ +lastchaos +臺灣狗 +打手槍 +不良少女日记 +淫荡的嫂子 +爹娘 +宁王府淫图导航 +成人图库,操女人穴,色情贴图,性交贴图,操MM穴,超级淫图 +嘉联 +肉棒顶入小穴口 +你色吗 +干妳娘 +稻生美纪 - miki +做愛電影 +女儿的阴道好紧啊 +操妳妈 +歪逼 +淫水四濺 +激情淫色贴图论坛 +我受不了啦!┅┅好勇猛的鸡巴 +冉英 +免费午夜电影 +毛台湾帝国 +黄家骁 +抽插39岁处女meimei淫叫不断 +狗狼养的 +六。四 +builtfree。org +張 林 +美国小姐淫荡舔乳照 +大力丸 +炮友之家 +色情网站 色情导航 +干一干 +好嫩的屄啊 +免费淫色电影论坛 +網管 +毛射精 +歡歡娛樂時空 +毛西藏独立 +激情 乱伦 性 +asshole +人大代表 +h站靠 +浪叫 +mei li shi jie +法抡功 +逼痒 +情兽 +mo huan sen lin +夏夏娱乐免费黄站 +免费淫色情电影 免费淫奸女A片段试看 +法轮大法 +林心如特级片 +你弄得阿姨爽死了 +毛膏药旗 +麗春苑 +狂乳激揺 +钱 达 +緊穴 +超美少女系列 蛯原舞 +本站10019多部激情电影全部免费试看 +激情电影 +宾周 +激情成人桃色电影 +爸干得你┅┅舒服 +台湾情色網 +在乳房和阴道摸弄 +美乳美穴 +大史记 +女卫生间盗摄图 +淫水四溅 +MAD MAD +毛去你妈的 +毛李宏旨 +毛妳马的 +免费黄色电影/色情电影/激情电影/黄色电影/我该死/A片 +乌兰夫 +肉棒精液淫液阴精 +免费淫色影院 +肉棒好粗啊 +清華同方 +花和尚成人论坛 成娱情色导航 +摸你雞巴 +劉少奇 +flyfff +日本激情片 +怎么能知道女性手淫过 +大龟头顶住了她的花心深处 +巨骚 +干X +小泉恶搞 +大肉棒插入阴户内 +給處女開苞 +新聞出版署 +插护士穴真爽 +金瓶梅4 +弓虽 +黑逼 +金瓶梅5 +こどもの时间VOL。1-7 +內衣 +金瓶梅1 +妹妹的阴道好紧啊 +金瓶梅2 +六。四 +金瓶梅3 +18岁以下禁 +亚洲穴贴图激情自拍穴 +曲線消魂 +毛经社理事会 +法(轮)功 +淫女教师小说 +枪淫少妇 +巨騷 +本站10021多部激情电影全部免费试看三天 +牛头马面 +日本av女优 +bastard +逼癢 +伦乱小说大全 +亚洲美女 +三极试看片 +少妇自淫 +欠骑 +鄭萬通 +淫水橫溢 +肉棒插进子宫了 +毛阴户 +Baichi +又紧又嫩的屄儿 +大型黄站 +bankai +huang yi qun xia zhuan +毛塞白 +激情黄色在线 +傻鳥 +fuck新疆独立 +基地组织 +抽插47岁处女妹妹淫叫不断 +meinv穴自拍 +二屄 +妈卖妈屁 +操车仑 +吊 +回教 +大鸡吧来回抽插着小穴 +毛克林顿 +牲口 +事屎 +fuck透视眼镜 +mo yu +毛可待因 +爱图公园 +六四民運 +黃色漫畫 +朱骏 +毛傻屄 +干机掰 +媽的 +毛日他娘 +U-R +卫星遭黑客攻击 +抢火炬 +吳 邦 國 +少婦偷情 +MUGEN EX VOL 9 人体喷泉!强烈な潮吹きホール!(MX-09) +贱人 +jiangdongriji +色网阴道特写强奸32岁处女全过程 +在线黄色电影 +毛发展研究中心 +成人激情视频聊天室秘密入口 +东条 +东方传说 +色聊人午夜激情聊天 +巨炮肉穴 +老师的淫液 +wetback +手记注册日韩5029部激情电影 +龟头抽插小穴 +TMD +周總理 +乳峰 +fuck我干 +毛马克思 +成人导航网 +聯 總 +姫辱 +乳房急促而有节奏的起伏着 +操他 +毛耶和华 +肥嫩嫩的大陰唇粉紅色的小陰唇 +操插Gm +运营 +zu qiu jing li +裹本 +一边一国独裁 +朝鲜 +插你爸 +色网阴道特写强奸28岁处女全过程 +娇妻超市被奸 +张 伯 笠 +射了 +肉棒 乱伦 肉洞 +东京物语Vol。 3 优质美少女 +龟头在阴道中抽插 +大鸡吧狠狠插进了她那又肥又嫩的小骚屄儿 +二奶大赛 +操插GM +98bb成人小电影 +雞院 +摸陰蒂 +wtf +激情淫少女穴 +打飞机 +操得直叫爽 +妈个老比 +f r e e n e t +阴阜高耸 +强奸20岁处女全过程/*妹阴毛小穴 +天鹅之旅 +淫影院论坛 +铁道部 +丰满肥大有阴唇湿润了 +红宝石 +六四民运 +唐人电视台 +打手枪 +di qiu wen ming +现场做爱偷拍电影 +欧美乱淫贴图 +宮路ナオミ - 美腳★角度 (超美) +wyd +毛骡干 +淫荡少妇白洁 +麻醉枪 +法抡 +Sex +每日公告 +T浓厚中出FUCK Red Hot Fetish Collection Vol。44 : 夏川Saya +六四平反 +顶到阿姨的花心 +歡迎G9情色電影院 +娘b +法*掄 +射你 +发^^抡 +山本五十六 +如果你未满26周岁请自觉离开。 +tian yi zhi lian +淫荡女护士 淫荡少妇穴 +淫奸护士论坛 +乳尻 +色情工廠 +棒插到妈妈的穴里 +xin shi qi +遊戲送獎員 +fuck售号 +中國政府 +娘B +激情淫色小穴 +tiao zhan +抽插淫水 +毛肛 +劍網2 +劍網3 +無碼無套 +phuc +妈的靠 +烟膏 +乳尖 +成人午夜影院 +魔兽金库 +droiyan +雞雞 +强奸24岁处女全过程/淫妹阴毛小穴 +大波骚妇 +少妇扒开阴道图-淫賤少女阴唇特写图免费淫电影a片 +淫水橫流 +色电影 +fuck唐家璇 +西藏天葬 +极品激情影院 +狗娘养的 +食捻屎 +又硬又大的肉棒插入阴户 +程真 +天之炼狱 +龟头在她的阴户里抽插 +仑功 +魔兽金币 +kan66免费电影 +顶级学妹美穴淫图 +地震捐款 +巨乳俏女医 +捐款名單 +美女含双棍玩内射 +luanshi +賣國 +san guo +正見網 +转法轮 +发@@仑 +六四以后 +吳桂賢 +开粉红小阴唇 +日本大型黄色meinv做爱 +發~輪 +台灣豬 +亚洲激情淫贴图 +南联盟 +寻仙 +淫水淋湿的阴毛 +亂倫熟女網 +肉棒捅入阴道里 +淫荡小护士 +fuck社保基金会 +大陆性meinv淫穴 +童屹 +操布雷尔 +毛想上你 +风骚小护士 +朝鮮 +tian jiao +@sshole靠 +cha你 +带链 +厕所盗摄护士姐姐性感 +龟头狂插肉洞 +亚洲激情淫搔穴贴图 +fuck外挂 +毛情色 +李弘志 +法@抡 +骆 冰 淫 传 +泡365免费电影 +董建華 +处女流水淫图 +草你媽 +小浪穴 插死 人家了 +台湾 18 成人网站 +淫色网址导航 +剃毛 +毛老母 +朱駿 +Groove +羞恥母 +淫浪女 淫妻浪女 于东 浪女淫叫 淫妻……漫画 淫色贴图东方淫色 +遺忘傳說 +汽车爆炸案 +看棋器 +抽插50岁处女妹妹淫叫不断 +插比 +張梅穎 +萬人暴 +法掄 +激情淫色贴图网址 +红海湾 +本站10010多部激情电影全部免费试看 +wstaiji +cunt cunt +粉红色的小嫩逼淫 +妈要吃你的肉棒 +操你奶奶 +jin wu shi jie +董必武 +狡猾的风水相师 +粗挺的阴茎上沾满了处子的鲜血 +性器 +插gm +蓋世太保 +U/R +阿姨的阴道好大 +上海交警 +林榮一 +癡乳 +性感妖娆 +肥嫩的阴唇 +妹妹嫩穴被狂插 +哥哥使劲插我 爽死了 啊 啊 +外交论坛 +毛妹妹免费电影 +梁保华 +发@@伦 +毛小穴 +插gM +99bb +托管理事会 +Fuzz Vol11 Ririko Asahina 朝日奈りりこ 加藤つばさ +1989#事件 +骚妹妹 +母子淫奸乱轮现场看,瞄準她的肉穴插了進去…… +扬震 +韦国清 +成人激情电影通道 +湿淋淋的阴道被肉棒插出血 +河 殤 +夏夏娱乐 黄站电影 +淫民俱乐部做爱顶级 +激情淫咪咪贴图区 +毛检察院 +东京热5月新片 +癟三 +瘋狂抽送 +華夏Online +小泽玛丽亚7~淫乱的肉体 +淫少妇 +鸡巴靠 +免费视频激情聊天室 +台湾18黄网亚洲华人bbs性论坛 +毛窃听器 +美国淫女在线看电影欣赏mm乱淫自拍图片 +賓周 +河 殇 +胡景涛 +WEB战牌靠 +東京熱最受歡迎長腿meinv~藤澤安奈~腿長人又漂亮 +激凸走光 +法~~掄 +操女人穴 +干的你 +魔性的美女 鈴木麻奈美 +强制执行 女体崩壊~YUU Vol。1 +孙文 +草你娘 +令人喷血的春宫108姿势(组图)18岁禁看 +四我周 +毛摇头玩 +fuck四人帮 +午夜的诱惑网友自拍 +少女艳星诱惑色图 +国权 +法$抡 +BT无码区 激情电影 +干八个meinv的小穴 +免费淫爆影片 +电监会 +劳拉 +山西黑砖窑 +mimi淫色贴图 +大海战II +shaiya +毛肉壁 +深愛色色 +mo jian +meimei的阴道好嫩啊 +狂插meinv护士小说 +毛台联 +粮食局 +口爆吞精 +经社理事会 +20dy淫色贴图 +sanguohx +淫色贴图网 +小便 +性感妖嬈 +少儿不宜 +公媳乱 +毛独立台湾会 +蒋震文 +扒开嫩穴 +大龟头在我的阴道口来回磨擦 +發^輪 +淫奸姐姐小说 +台湾黄色成人电影 +草你妈 +日本姐弟乱伦小说 +阿姨的阴户好紧 +免费成人激情视频聊天 +公媳亂 +少女被插 +婷婷成人激情网站 +21dy淫色贴图 +奶大屄肥 +黃色圖片 +李鵬 +狗雜種 +免費A片 +淫荡贵妇 +獨立臺灣會 +奇淫的老板娘 +meimei穴 +fuck生孩子没屁眼 +温暖的冬夜老师拼命亲吻我 +免费电影 成人电影 激情电影 +肉棒抽插……的爽死了 +feng shen +圣战 +台湾政论区 +朱胜文 +dekaron +恶搞晚会 +吾尔开希 +钱运录 +秦真 +Tora Tora Gold Vol。24~伊泽夕 +插 10p +高自联 +du shi 2046 +毛经济社会理事会 +操陈至立 +爆乳人妻 +迷奸药 +狂插处女血流不止! +童顏巨乳 +饱满的乳房肥嫩的阴唇又肥又嫩的小骚屄儿 +操财政部 +智能H3 +毛国研室 +北大三角地论坛 +民联 +财政部 +热血江湖 +发~仑 +大鸡巴干进妹妹的小穴 +舆论钳制 +bi样 +品嘗不倫主婦 +插 11p +小姨子穴 +粉嫩小淫穴 +铁血三国志 +无尽的任务 +捅入她的阴道里 +白立朴 +妹妹 MM激情 +帶链 +婊子靠 +肉棒乱插 好舒服 +霍金 +meinv出租车内强行进入 +fuck死全家 +猛舔她的肥穴 +扉之陰 +操大法 +插 12p +尋仙 +又粗又大的肉棒 +江八点 +李至伦 +张磊 +petrealm +淫奸meimei电影论坛 +阿弥陀佛 +台湾建国 +莫伟强 +免费淫电影,免费淫色情电影 +馬万祺 +Gold Angel Vol。7 Super Erotic Girl : Ran Monbu 紋舞らん +插 14p +激情淫片 +哥哥淫奸妹妹穴 +插 13p +本站10012多部激情电影全部免费试看 +宋平 +你爺爺的 +发~伦 +成人色情网 +姐弟激情淫影片 +毛傻子 +大龟头顶住子宫深处 +干GM +王文京 +洪志 +内衣 +接班 +九评共产党 +中共/中共中央 +乳射 +插 15p +大花逼 +濕身誘惑 +手记注册日韩5020部激情电影 +教室炉轮奸精液过剰注入 若月秋穂 +真 善 忍 +美媚穴贴图 +杀你一家 +又大又嫩的穴 +淫乱电影 +【亚洲/无码】【生奸中出无套内射-相沢、夏樹、 美月遥】【AVI/1220MB】 +脱衣舞 +淫色电影免费在线观看 +日本激情淫 +艳舞淫业 +强奸17岁处女全过程 +法$掄 +淫奸电影少妇扒开阴道 +杜冷丁 +肉棒插入肉缝 +你它马的 +扒开嫩阴道 +法*抡 +Ninn Worx - Fem LAmour +liu xing xue yuan +邪教 +俏臀攝魄 +徐邦秦 +奴隸調教 +淫水漣漣 +無碼 +少妇房中自淫,和两勇男玩9P,操得直叫爽 操日本淫女穴 +操你 +transsexual +口含鸡巴 +KEFU +国安局 +淫电影//处女第一次阴道做爱全过程(全套图片) +淫妻乱交 +免费色情电影 +林心如淫电影 +色meimei成人论 +热血英豪 +mes couilles +U R +内裤 +幹GM +干鸡 +光通 +毛麻醉钢枪 +毛社。会。正。义。力。量 +bt 色情工厂 +华盛顿 +Jiaochun +扉之阴 +Yellows Vol。2 女体天国 2 天然素人娘18人 +毛共产主义 +龟孙子 +赵 紫 阳 +專制 +淫奸meinv图 淫奸刘亦菲 +毛特别公告 +urban靠 +av成人 +日韩成人激情电影 +h r i c h i n a +她奶奶的 +激情淫贴图 +朱嘉明 +快感 +食屎 +毛国防部 +露逼 +transsexuel +骚货 +活动管理员 +任弼时 +ctracer +大妈油 +情色小电影 +宁王府导航 +强奸林心如扒开阴道 +周铁农 +插你祖宗 +ai滋 +溫泉室的男女 +淫屄儿 +胡景濤 +射进女儿的屁眼里 +fuck透视软件 +舔她的花蕊 +我和小少妇乱伦理淫穴 +PP一点通 - 成人电影 +母子交歡 +天安門大屠殺 +日本卡通淫色动画片 +公车淫奸姐姐 +大陆淫乱美女图图片 +無界 +嗎b +鬼畜轮奸 +让我的肉棒缓缓的插进潮湿饥饿的娇嫩的肉洞里 +炮打中宣部 +于永波 +走资派 +內褲 +网游久久金币 +性奴 +成人文學 +明斯克号 +操吹箫 +精液喷涌而出 +毛日X妈 +六月four日 +骚姐姐 +毛外挂 +宝德 +成人文学 +轮盘机 +华义 +三個代表 +系統公告 +免费成人激情视频聊天室 +日本黄色小电影 +da tang hao xia +中央电视台 +插少女阴道 +抽插 捅 挺 阴唇 处女膜 +母子交欢 +中国天使成人网我该死免费视频 +江獨裁 +滾那嗎 +毛懒教 +丁關根 +国产偷拍 +肉棒弄得湿溜溜的 +猪聋畸 +全裸 +楊帆 +卐 +刘全喜 +满洲国 +毛普京 +疯狂抽送 +SEX +區 +淫电影//少妇扒开阴道图-淫賤少女阴唇特写图 +猪毛1 +卵 +89bb成人小电影 +中国meinv淫色贴图 +傻鸟 +抗震 +大紀元 +剛比 +Tokyo Hot n0188 田中爱 +毛国民党万岁 +和护士jiejie淫穴 +操你妈屄 +毛屁眼 +小穴插的紧紧 +淫穴淫水流 +張 志 清 +55sss偷拍区 +55sss偷拍區 +脱内裤 +發~論 +媽祖 +毛卖逼 +插 操 干 骚穴 嫩穴 小穴 密穴 淫水流 +兔meimei色色贴图区 +功 +毛夜情 +宁王府成人论坛导航 +岩崎 Sky Angel Vol。27 +天地玄門 +淫荡口交 +www。gpchina。net +聚友網路 +摩門教 +他馬的 +个批 +賣卡 +专政 +人妻熟女 +小骚穴┅┅好舒服 +64xp。com 电影免费 +操陈毅 +安息 +蜜穴肉棒肉縫 +少妇大穴VS驴吊 +把舌头伸入姐姐的 +發~~倫 +日本免费黄站 +一黨獨裁 +於永波 +64事件 +tranny +郭平 +肛門拳交 +毛强硬发言 +務 +法车仑工力 +輪流執政 +法~~抡 +灨你娘 +動 +我讓朋友強姦我的小姨子 +大城舞衣子(有碼無碼)大合輯~~~超優!!(可分開下載哦!!!) +操妳娘 +通知 +合成淫色贴图 +Qqyinsu +fuck晚年周恩来 +小穴┅┅好棒┅┅好爽 +孔雀王 +操医生小穴 +淫妹妹电影 +强奸42岁处女全过程/淫妹阴毛小穴 +妈逼靠 +lineage2 +大肉棒刺入肉穴 +吴桂贤 +成人激情视频聊天 +GMworker +segame +阴道好肥啊 +Taiwan国 +neosteam +日本淫色电影 +joyxy +色情靠 +無毛美少女 +毛王乐泉 +小魚兒與花無缺 +中宣部是中国社会的艾滋病 +乳头 +epochtimes +河殇 +插GM +女秘书做爱吞精图 +少妇房中自淫,和两勇男玩14P,操得直叫爽 操日本淫女穴 +黑五类 +毛法(轮)功 +厲無畏 +摩力遊 +店長推薦最新強片Sky Angel Vol。43最新強片 +操妹妹 +杨震 +發**論 +法轮公 +爽图网 +出售账号靠 +法轮共 +穴太紧了 插进 +你他妈的 +毛神通加持法 +毛我干 +免费操小姨子 操小姨 +性欲 +voa +含 肉棒 插 小穴 +潘金莲全传 +发改委 +今晚我把表姐操上了 +欧美激情 +天天任我淫 +网址大全 +mo shou shi jie +阿沛•阿旺晋美 +够酷GOQO +统独论坛 +毛阝月 +激情淫色故事 +fuck新闻出版 +打飛機 +操妳媽 +佛展千手法 +龙 虎 门靠 +欧美暴淫 rsync 月宫成人贴图区 +国产AV +chinesenewsnet +xin xi you ji +jin yong qun xia zhuan +插Gm +啊……我的小屄……给你……肏得好……舒服……啊 +金新月 +靓穴meinv +feltch +幹全家 +中共中央 +操那嗎逼 +子女任职名单 +卖卡 +谷牧 +幹逼 +東方傳說online +無需刷卡 +俞正声 +淫穴小说 +台湾成人25贴图 +梅毒 +騷浪美女 +致幻劑 +法沦 +毛乡巴佬 +自由亚州 +黄色做爱小说 +成人激情影视区在线视频脱衣服 +game master +昝爱宗 +歐美大乳 +淫秽小电影 +致幻剂 +法輪功 +肥嫩的小骚屄儿阴部 +meinv淫色贴图区 +弟弟粗大的肉棒 +人民代表大会 +天地玄门 +圣女峰 +成人激情电影网 +worms +臭b +大……鸡巴……操得……很……很……舒服 +淫奸jiejie +江择民 +xiao77 +baichi +大亂交 +农村公公与媳妇乱伦 +曾 庆 红 +超激情电影快速注册 在线观看爽!爽!爽!! +干部 +毛水利部 +恥辱醫護免费 +风骚女秘书 +我也要泄了 +操产权局 +毛国管局 +法~掄 +浪婦 +肏妹妹屄 +毛投毒杀人 +搖頭丸 +庆红 +看着有点舍不得操 +89學潮 +亚洲激情 +法@@仑 +伦理淫穴小说 +阿呀娃娃 +tian xia wu shuang +姘頭 +Itsuka_part2 +劲暴 +毛三唑仑 +性交自拍 +无码做爱淫图 +撒尿 +好紧的阴道 +妹妹的小阴户 +火辣辣免费爽片 +火辣写真 +人也 +大清帝国 +用手指分开两片肥嫩的阴唇 +肉棒插入妹妹小穴 +傲神傳 +毛徐光春 +她妈靠 +自由亞州 +姨妈的肥阴唇 +1989 天安門 +法*淪 +强 奸 +免费淫奸女A片段试看 少妇扒开阴道图-淫賤少女阴唇特写图 +1989 天安门 +挺着硬梆梆的肉棒 +干逼 +網路公祭 +欧女乱欲 +kart +骚姨妈 +5jq +电影小片段试看免费淫影片 +红月 +賣幣 +一夜情聊天室 +天安门屠杀 +龚学平 +六四之後 +毛哈批 +嫂嫂我要 +鞭王 +最淫熟女网 +肉棒插入淫荡少妇穴 +陰道圖片 +後庭 +把精液射进我的小穴里 +亚洲激情淫色网址 +huang yi qun xia zhuan +韩正 +邓力群 +性交贴图 +乱伦淫书成人网 +三级片看美国女人的性交 +莫索里尼 +sheng zhe wu di +淫逼嫩穴清晰图 +主席 +恥辱醫護 +奇侠XIAH +屙 +人代 +四川 +手记注册日韩5030部激情电影 +操女人嫩穴 +總書記 +毛游戏发奖员 +總理 +屍 +妈妈美穴 +屌 +福尔摩萨 +屎 +屄 +男女激情淫影片播放 +淫女刮毛 +尿 +乱伦禁书 +尻 +毒販 +少妇房中自淫,和两勇男玩0P,操得直叫爽 操日本淫女穴 +激情日本电影_成人情色电影_成人小电影 +meimei淫水 流 +卢跃刚 +余英时 +tianji +激情做爱色情淫妇做爱 +經血 +密宗 +美女偷拍成人小说激情网 +亚洲成人激情 +神话R。Y。L +毛卫生部 +polla +共*党 +日九城 +卡通动漫美女淫乱 +毛胡主席 +台湾共产党 +UR靠 +先烈的电话 +反日活动 +毛贺国强 +台湾国 +抽插48岁处女妹妹淫叫不断 +射 +捏你雞巴 +fuck温加宝 +疆独 +李師父 +护士淫乱 +新唐人 +插得好爽啊 +发@抡 +任你淫 +鄧小平 +小骚货 +周鉄農 +两片暗紅的陰唇一張一合 +soundofhope +幼逼 +熟美婦淫交實錄 +美少妇的哀羞 +硕大龟头紧紧顶著她的阴道 +肉洞深处不断地蠕动 +盘古软件 +王秀丽 +淫乱色情小说 +fuck王昊 +24dy淫色贴图 +安拉 +卖号 +星光伴我淫 +和姐姐插穴 +共軍 +午夜激情免费电影免费看激情小电影 +zhuanfalun +打倒中国 +激情贴图 +淫荡妖艳女医生 +少妇做爱小说 +核潜艇 +原千寻~白领迷奸 Finger Charm +怎样延迟射精20岁以下禁 +毛网管 +qq视频脱衣秀亚洲少女韩国无码片 +淫奸姐姐 +亦凡 +肉棒插入肉穴 +法@沦 +恐怖分子 +干meimei小穴 +毒贩 +水浒Q传 +167网址宽频影院网 +日本激情免费小电影 +(无)导航网站连接 +李大钊 +SOD 厳选!残虐レイプ集 +帝国传奇 +薑春雲 +你他马的 +赵 晓 微 +毛多维周刊 +免费meimei黄色淫乱电影 +法淪 +草拟妈 +疆獨 +如果你未满18周岁请自觉离开。 +日韩淫乱美女图 +滾那嗎錯比 +GAME MASTER +人民之声论坛 +se中国 +厕所盗摄meinv +光明日报 +fuck统计局 +毛高俊 +他妈地 +蒙古独立 +鐵甲爭雄 +日本情色无码光碟 +搞比 +劳改 +大肉棒插进我的肉屄 +如果你未满25周岁请自觉离开。 +動漫色圖 +看牌器 +性感乳娘 +新人调教 Red Hot Jam Vol。9彻底调教凌辱人靓逼美 +情色成人大全 +淫荡的妈妈8淫荡护士9淫荡空姐 +海天英雄传 +好紧的屄 +9之遊 +鹿城百家性大型网站 +爽你 +全国两会 +成人视频 +武雷 +大乱交 +欲仙欲死 +干你媽逼 +淫奸护士穴论坛 +好朋友 +身份生成器 +法@@倫 +欧洲男女激情淫乱穴 mm贴图网 +明慧網 +52xp。com 电影免费 +mei li shi jie +阴道夹裹住阴茎 +卖淫女全过程 +未满21岁的请自行离开 ! +民航 +操小姨子 +淫奸小姨淫水流 +毛联大 +强奸20岁处女全过程/淫妹阴毛小穴 +日本有码 +毛威而柔 +fuck王太华 +那吗逼 +免费看三级电影淫电影艳情电影 +拉案) + +搞死 +毛六合彩 +64動亂 +arcane +欧美靓穴小小论坛帖图母子姐弟淫……男男激情欧美淫贴图 +下载淫电影 +淫电影艳情电影 +起义 +骚B熟女 +贾育台 +张伟华 +富人与农民工 +毛台湾共产党 +金日成 +法$沦 +性愛擂臺 +新聞出版總署 +免费黄色淫秽 +Lady Sonia-熟女絲襪 3 +司馬義?鐵力瓦爾地 +东京热 n0151 工藤裕子 美丽子宫大精液轮奸教室 +日本有碼 +百家性大型黄站meimei +又解开乳罩 ┅鸡巴 +黑手黨 +赌博 +造爱 +龟毛 +豔照 +赛他娘 +免费情色电影情色五月天 +毛售号 +阳具在他的穴里大幅抽插 +客报 +宁王府 +亚洲激情淫影院 +薛伟 +肏肉~X屄爽歪歪 +强奸大奶嫩逼meinv +毛王宝森 +屌七 +淫奸妹妹电影 +苯丙胺 +法碖功 +中华时事 +遊戲管理員 +红楼 绮梦 +素人著エロ俱樂部 こももちゃん +办公室性欲 +大肉棒在妈妈的阴道 +朱熔基 +毛审计署 +fuckyou +怎样免费看淫电影 +毛世界日报 +插姐妹小穴 +meteor academy +胡锦濤 +色情 娱乐 导航 +风骚女友浴室放荡 +ㄙㄞ你老母 +Mysupersales +小穴里抽插 +網络公祭 +糖糖小穴 +八路 +售ID +小泽玛丽亚~闷绝痉挛无限制潮吹 +毛阴核 +AYAWAWA +干jiejie小穴 +fuck倭国 +强奸43岁处女全过程/淫妹阴毛小穴 +劫机 +黎阳评 +集體性愛 +大j8 +少妇激情电影 +解放軍鎮壓 +国产av +龚學平 +fuck无界浏览器 +幹 +美国成人激情淫洞网站 +开苞 +干 +骚b熟女 +浪妇 +嫩穴 小穴 花心 +wu lin wai zhuan +三去車仑 +幹死CS +浪女 +fuck十年动乱 +性交 +法*沦 +傳奇3G +旅馆自拍 +粉饰太平 +少妇房中自淫,和两勇男玩18P,操得直叫爽 操日本淫女穴 +独裁政治 +淫妇周艳茹和儿子的性战 +毛特码 +奥马尔 +高校骚乱 +毛驶你老师 +法@@伦 +小嫩穴贴图 +法~~淪 +欢乐数码 +统战 +马良骏 +苯環已哌啶 +工商局 +法~抡 +絲襪寫真 +免费淫奸女直接试看 +手机注册色情电影网站 +美國之音 +江八条 +淫荡女优放荡插逼 +妹妹的大阴户 +大 纪 元 +超性感裸体艳舞 孔裏唾梦 DANCE 2 アナリズ现场收音 +九城 +成人片 +幾芭 +罗 干 +绵恒 +laghaim +10 Little Asians Vol。 14 +@sshole +把你的小穴夹紧……用力…… +总局 +天安門 +mo fa qi bing +不得入内 +不用注册免费淫 电影 +小姨子的阴道好紧啊 +d7se淫色穴图片和meinv发春激情3级片试看 +幹死GM +强奸33岁处女全过程/淫妹阴毛小穴 +GameMaste +淫奸阿姨电影 +插入 嫩穴 +正见网 +法$淪 +法@@侖 +bedclip。com +jing tian dong di +插死你 +公车淫奸妹妹 +teensexy +一夜情异物插穴性爱网 +暗黑之門:倫敦 +成人激情色情电影 +亲情淫乱 +骚逼 +粗肉棒 大鸡巴 +淫奸女同事穴 +9城 +劳教 +我就去色 +林心如被疯狂轮奸 +在线淫电影网站 +天安门 +尸体 +舌头在小穴周围舔弄 +郭岩华 +肉棒插进了湿湿的阴道 +淫奸姐姐 妹妹 MM 姨妈 舅妈直到流水 +性佣 +免费淫水流 +彩虹骑士 +天安門屠城 +ling you ji +法^掄 +歡迎光臨亞洲瘋情 +游戏道 +無碼小處女 +龟头顶开阴户 +周子玉 +凤舞天骄 +刀劍?英雄 +破天一劍 +淫荡少妇 +老騷比 +台湾19岁成人 +棉条 +陳希同 +肛门喷水 +dafa +强奸46岁处女全过程/淫妹阴毛小穴 +NPC靠 +畜生 +大陆温州鹿城黄站 +王子淫传 +親民黨 +re xue jiang hu +奸 +E块冒险 +升天 +余秋里 +爆吧 +biaozi +未成年人禁入 +毛短信群发器 +蔣彥永 +射奶 +fuck台联 +毛欲火焚身 +破天一剑 +成人影院 +欲仙欲浪 +徐向前 +发论公 +干妈妈的小穴穴 +功法 +counselor +廁所盜攝 +fuck外交部 +三去車侖 +我和网吧老板娘 +胡锦淘 +365淫色贴图 +QQtang +检查 +免费淫 色电影 +妈 +meimei嫩穴 +毛你大爷 +TMD靠 +密室淫行 +靠背 +日本激情淫骚穴 +干 淫洞 +嗑药 +fuck兴奋剂 +官方 +强奸17岁处女全过程/淫妹阴毛小穴 +小穴好爽 +泽民 +妓 +蜜穴被阴茎插入 +劉伯承 +游戏管理员1 +鸡巴全根没入 阴道 +姦 +淫色宝贝导航 +禽獸 +明慧网 +jiejie +的 +嫩穴 +床上激情自拍图 +6。4 +完美世界 +透視軟體 +瞄準她的肉穴插了進去…… +merde +江罗 +WG武功 +A片大放送 +用手指挖她的小穴,弄得她娇喘连连 +哦……你插的好深啊……又顶到我的子宫……啊 +毛燕玲论坛 +肏meimei淫屄 +香港成人激情论坛 +吴宏达 +毛肛交 +死刑过程 +李师父 +妹妹的阴唇好嫩啊 +卖国 +遊龍線上 +姘 +免费品嘗不倫主婦 +抽插28岁处女meimei淫叫不断 +皇军 +操吹喇叭 +捅B +毛鸟gM +婷婷激情淫液 +六四以前 +大肉棒插进了她的体内 +用舌头对着阴道阴蒂等地方用力地舔着 +毛发奖使者 +毛我日你 +萬稅 +测拿 +本站10005多部激情电影全部免费试看 +荡妖艳女医生 +chinamz +fuck希望之声 +淫电影//令人喷血的春宫108姿势(组图)18岁禁看 +幼女口交 +嫩穴 +屍体 +狂插嫩穴 浪穴 骚穴 +宗教 +meimei小穴好紧 +madelove +阴道深处 +天安門事件1989 +郁慕明 +建国党 +外$$挂 +fuck小乳头 +fuck天安门屠杀 +慈善会 +国外A片电影-美国色情电影一点点激情下载 +性愛 +偷窺圖片 +毛驶你爸 +免费成人聊天室 +jiejie的嫩阴户 +胡启立 +apexon +激情淫色漫画论坛 +亚洲成人激情网站 +falun +qi shi +素人初撮り生中出し 观月雏乃 +去氧麻黃碱或安非他命 +强奸18岁处女全过程/*妹阴毛小穴 +免费淫乱卡通动画片 +淫荡家教 +性傭 +张萬年 +365成人贴图 +毛黄菊 +44lian色站大全 +亞甲二氧基甲基安非他明 +情色图片 +少妇白洁 +床上功夫 +日本淫荡少妇 +毛公安部 +江core +亚洲meinv +幼女情色论坛 +积克馆 +鸡巴插肉缝 淫荡 小穴 +舔着两片湿润的阴唇 +反人民 +龙洲影院日本娱乐性免费 +萨拉托加 +焚烧 +胡锦滔 +金瓶梅情色網 +坐台 +父亲 +淫蕩貴婦 +发论功 +tui tui xia +插入妈妈的穴好爽 +肉棒插入乱伦射精 +婷婷成人激情淫洞 +万润南 +老师嫩穴 极品嫩穴 淫穴嫩穴 +戀愛盒子OL +性息 +逼樣 +大话西游 +彭真 +干丰满少妇 +買幣 +干妳老母 +掰穴 +鸡巴猛插 +江八條 +插进小穴射了 +新人调教 Red Hot Jam Vol。9 Myuu +毛奸你 +恐怖主义 +领导 +勁樂 +性爱插穴 +你呀的鸡巴长歪了吧 +採花堂 +毛鸟gm +干一家 +性情 +宋庆龄 +十三点 +反政府 +姐姐和我乱伦理电影 +异见人士 +淫荡┅插 小穴 +法~~沦 +少妇房中自淫 +韩 联 潮 +youxia +短信群发器 +發倫 +毛孙中山 +爱图公园论坛 +butthead +毛希望之声 +客服 +六?四 +wowcaifu +Ezgaming +絲襪 +富豪们的疯狂做/爱方式 +肏烂你的屄 +成人小电影 +天安门录影带 +少妇 +皓宇互動 +狂舔少妇两腿之间 +jie tou lan qiu +操婊 +365情色小说 +淫乱护士激情电影 +肏meimei屄 +PENIS +大奶骚女 +f l g +招雞 +亂交 +孕 +免费黄色淫乱电影 +日本风骚女电影 +皓宇互动 +法^^侖 +你爷爷的 +在线观看淫电影 +弟弟的肉棒又粗又大 +Red Hot Fetish Collection Vol。28 +肉棒又粗又大少女又痛又爽 +少修正 +被操 +女老板一丝不挂躺在我身边 +阻无通畅 +骚妇露逼 +meng huan xi you +和親jiejie作愛 +見到這個美女就會有性欲 +把肉棒抽出来 +咬着她的奶头干了她 +在线淫电影 +几芭 +H动漫 +laghaim +無需入會 +幻灵游侠 +毛商务部 +貞操 +日本淫色漫画 淫色少妇小说 淫色少妇 +tmd +品色激情电影 +fuck特码 +……好舒服 ……好爽 +大鸡巴 +肉棒抽出她嘴中 +林心如色情贴图 性交贴图 +发$抡 +曰gM +任建新 +毛贱 +GAMEMASTER +鑽插 +肉棒插进来肉穴 +妈妈挺动雪白的肥臀 +鸡巴顶在女儿的嫩穴 +李紅智 +大型色站 +新鄭和 +U-R靠 +中央 +和妹妹玩插穴 +翹臀嫩逼 +在线激情淫电影 +乳此丰满 +针扎 +法^^仑 +勁暴 +蒙尘药 +張筱雨 +毛胡紧掏 +舔她的小洞洞 +免费淫奸女A片段试看 欢迎点击进入观看/林/心如/20岁处女偷拍 +鞭神 +免费淫色meimei电影 +免费成人娱乐電影 +小骚逼 +Tora Tora Gold Vol。23 : ほしのゆき Yuki Hoshino +鸡鸡 +法^^伦 +性交极品大片 美腿少妇 +共榮圈 +学生淫图 +毛鬼村 +毛塞你老师 +毛淫秽 +89学潮 +毛色情服务 +弟弟淫奸姐姐论坛 +阎明复 +Tmd +淫色护士小说 淫色故事 淫色文章 +熟睡中的妹妹 +强*十八岁meinv护士看完保证你打飞机免费电影网站 +外$$掛 +性教育片-性教育电影 +劉淇 +snatch +全球华人春节联欢晚会 +毛湿透的内裤 +中奖 +日本av +精子射到姐姐的穴里 +账号 +公车上干女司机 +学生爱国者运动证明 +他奶奶的 +貓撲 +娘 +北川 +shine +jian xia qing yuan +偷窥拍摄 +颜射 +夏夏小说黄站 +注册免费淫电影 +曹长青 +Red Hot Jam Vol。8 让你用子宫感觉 藤崎夕凪 +干的好爽……要爽死我了 +盜竊犯 +敢坐飞机吗 +damn +美国凯德 +damm +操她妈 +百家性大型bt黄站 +娼 +李建國 +宁王府成人导航 +survivalproject +李建国 +海底水中插屄~Aqua Sex +李淑娴 +毛教育部 +劲樂 +都市情爱乱伦淫妻古典武侠制服明星性爱宝典24式教材 +毛阴水 +师春生 +动漫激情淫色贴图 +发伦功 +好大的肉棒 +发*抡 +少女bb图 +64动乱 +不斷收緊陰道來吞噬我的龟头 +婊 +神通加持法 +MM被干小穴 +甲基苯丙胺 +教師禁斷接吻 +胡锦涛 +强奸meinv狂插处女阴道 +免费色情电影 强奸小说 +操淫荡 空姐 +浴尿 +处女性开苞 免费黄色淫乱电影bt下载试看 +操她 +被插 +神雕外传之郭襄 +公公狂操儿媳妇小穴 +102bb成人小电影 +婬 +幹機掰 +kai tian +溫傢寳 +少妇操b图 操农村少妇 少妇操尿图 +征服 +n0255 三国冬子 - 不用厌牝中出し廃弃処分 _k7 +苯甲酰甲荃芽子堿 +毛阴毛 +市長 +抽插44岁处女meimei淫叫不断 +周恩來 +市长 +东南西北论谈 +媽 +發侖 +大 紀 元 新 聞 網 +再用力插…。啊 +狂插小浪穴 +┅插┅小穴┅插我 +新石器 +13点靠 +公交车上淫乱小穴狂插 +女死囚 +干小蜜洞 +操妳 +輪奸大meinv +毛枪支弹药 +钱国梁 +一个事实 +操妻 +毛李宏志 +www。gpchina。com +亂倫 +日本淫虫在线看电影 +問道 +淫亂 +毛王刚 +heterosexuell +毛江猪媳 +嫖 +法^抡 +h动漫 +五不 +江澤民 +淫乱 +赵洪祝 +法^^倫 +倚天屠龙别记 +98bb +西藏独立 +靠腰 +蒋彦勇 +逼毛 +華義 +淫书 +上床 +广闻 +血灑 +你色嗎 +毛吴邦国 +握着他的鸡巴上下套弄 +六四周年祭 +淫液流入 +administrator +肉棒狂插嫩穴 +san guo yan yi +巨乳meinvRINA无码第2弹 +董建华 +crazyspeed +去妳的 +AV女优-杏子 +封淫 Sky Angel Vol。50 宫泽Keito 超美系模特儿初无修正引退纪念作 +淫女 喷精 +骚浪美女 +毛卖。国 +迅雷下载免费黄色淫乱电影 免费淫奸女A片段 +毛江青 +成人情色贴图 +51yxb +大粗鸡巴插进小穴 +毛回回 +日韩免费午夜电影 +道教 +鸡巴在她的阴道里抽插 +毛国防科工委 +中国社会进步党 +姐弟淫穴小说 +爆乳 +世紀天成 +淫丝荡袜 +丫的 +毛骚逼 +大鸡吧插进阴道 +lateinos +阿兵哥艳遇录 +逼样 +出租汽车罢工 +成人激情 +哥哥淫奸meimei论坛 +digimagics +本站10003多部激情电影全部免费试看 +烂游戏靠 +淫*女电影片段试看 +彭德懷 +曰 +毛乳交 +阿兵哥言语录 +王震 +日本淫蕩孕婦 +天皇 +格老子 +塞你老母 +Jap Jap +日死你 +大鸡巴在她的蜜穴里抽插 +日屄 +免费台湾18电影 +日本淫乱漫画图片 欧美母子淫乱图片 +中华人民实话实说 +huanet +车臣 +幸存 +淪功 +阿里布达年代记 +小穴 肉棒 插穴用力插 +紅 燈 區 +全免费淫色电影 +抽插22岁处女meimei淫叫不断 +功夫小子 +香港激情淫色影院 +女教師赤版免费下载 +成人 性爱 +迷奸系列 +法輪大法 +在乳房和阴道mo弄 +婊zi +发@论 +带套肛交 +毛售ID +强奸大奶嫩逼美女 +现金 +操布莱尔 +18dy淫色贴图 +淫花宫色女中心 +欢迎点击进入观看/林/心如/20岁处女偷拍/免费A。B片 +无毛美少女 +精水 +国产熟女做爱深喉肛交无码 +濫逼 +屌鸠 +张立昌 +干它 +嫩B弓雖女幹 +激情淫色文章论坛 +幼女狗交 +私#服 +花样性交 +劲乐 +無網界流覽 +郭伯雄 +男人若妻夢交下载 +厕所盗摄meinv性感 +做雞 +教你如何延迟射精 +FUCK YOU +艷情小說 +小电影 +亲日 +太監 +太监 +黑鲍娇 +梅德韦杰夫 +欧美尤物炮图图库 +臭西 +发$轮 +想不到的黑幕 +色狼論壇 +20岁处女偷拍/免费A。B片 +乳沟 +私%服 +法蜦功 +中华大地 +生成身份证 + Kurumi +欧美清晰打炮能看的淫乱 +毛神经病 +没有人权 +孙中山 +妈的穴让你插 +幼妓 +色猪猪成人导航 +(現映社)女の最強は30代エロ真っ只中 +應招 +冰毒 +hai tian ying xiong zhuan +那媽 +強姦你 +毛恐怖份子 +达癞 +神風痴女生中出!【MKV/767MB】 +隐窝窝 +免费偷窥网 +妈比 +宋任穷 +街头扒衣 +非常不错的人妻轮奸 +SM女王 +姦淫未成年的小女护士 +情色 +台湾岛国 +精液射进小穴里到了高潮 +jiejie的肥阴户 +鸡巴插进穴 +Q币 +欣赏特级毛片pp 点点毛片 meinv毛片 大陆毛片 +万税 +三个代婊 +窝窝客 +毛三个呆婊 +那可汀 +禽兽 +rivals靠 +干老师的穴 +奸淫 +台湾是主权国家 +操操比 +操那吗逼 +賣党求榮 +嫩嫩 小肉缝 小肉穴 +少女被操喷精图 +抽插20岁处女妹妹淫叫不断 +人學生妹妹 埼玉援交 vol。2 なな&まい +色魔堂电影论坛 +丁香欧美成人贴图区 +僵賊民 +教派 +本 +骚女淫频乐园 +免费淫电影下载 +姦情 +幹她 +运营者 +强奸meinv +多維社 +毛高校暴乱 +日本女优激情电影 +四川独立 +颜射自拍 +嫩女~嫩屄~插的红肿喷浆 +誘惑視頻 +私*服 +fuck天皇陛下 +熟婦 +讲法 +郭 罗 基 +阴茎在我阴道里急速抽送 +多位东热女优参演 +幹七八 +免费淫电影 +鸡吧勃起插入阴道 +他母亲 + 七海りあ +插的小穴都流水了 +动乱 +回民吃猪肉 +套牌 +激情人体18禁 +liu xing xue yuan +狂插meimei的小穴 +fuck吴官正 +發~綸 +幹妳 +piao liu huan jing +kk粉 +毛上妳 +幼女性交 +謝長廷 +挺动阿姨雪白肥臂 +册那娘比 +强奸39岁处女全过程/淫妹阴毛小穴 +幼女 +日X妈 +大奶騷女 +向忠发 +中公網 +愛幼閣 +曾庆紅 +欧美淫色贴图 +MUGEN EX Vol。 8 美脚痴女 红音まい +我和meimei肏穴 +性福联盟 淫宝贝导航 +私/服 +日X 妈 +法**論 +扒光 +操布什 +那妈 +Alod +私-服 +苏兆征 +身障 +system +六月联盟 +色情电影 免费电影 成人影院 +淫水翻騰 +强奸美女 +xian jing chuan shuo +干妳 +航海世纪 +六四點擊 +a 片成人免费激情小电影 +宁王府娱乐 +真三国无双OL +陈慕华 +真孔雀王 +消息 +yeeplay +操 +东突 +毛鸟GM +淫穴兽交 +胡锦涛靠 +蔡和森 +痴乳 +干娘 +风骚护士 +东方互通 +少妇 淫穴 +4。25 +阴茎在子宫喷射黏液 +阴部特写 +毛鸟Gm +高丽樸 +我也要泄了┅┅喔 +大 紀 元 +人权 +免费淫电影吴宗宪搞笑语录(27禁看) +通用娼婦 +peachall +神婆 +成人聊天室 +onlineworms +成人漫畫 +国军 +一夜情的免费电影 +15768 +欧美激情淫电影 +日她 +红嫩的小肉穴 +黄金圣水 +日本激情淫穴 +Tokyo Hot n0248 菊池奈津美 本物RQ体内汁注入22连发六月联 +勁乐 +江戲子 +做爱图片 +蒋彦勇上书 +我奸 +狂插荡护士 +Administrator +美神ルナ Runa Mikami +毛傻逼 +瘸腿幫 +李铁映 +操淫荡少妇穴 操淫荡meimei穴 操淫荡jiejie穴 +騷浪人妻 +登 辉 +毛军长发威 +水利部 +法轮大法靠 +婷婷淫色 +臀部 +丰唇艳姬 +嗎的 +BT色工厂 +川岛芳子 +淫叫 +布朗 +中年美婦 +本站10007多部激情电影全部免费试看 +阴道好紧啊 +外~~挂 +淫民堂 +道县公安 +孙逸仙 +merde +CUP爆乳家庭教师 +fuck商务部 +成人漫画 +小姨子淫色导航 +MM激情视频聊天 +台湾情色香港顶级淫片 +毛妹妹淫色 +游戏管理者 +少妇房中自淫,和两勇男玩7P,操得直叫爽 操日本淫女穴 +22park +抢粮记 +午夜激情宽频影院 +插屁眼 +反革命 +干她 +我和jiejie +小骚屄儿妹妹 +极品做爱套图 +强奸你 +东社 +钢管舞 +江湖使者 +僕街 +支持台湾 +婷婷激情小说 +毛生春袋 +爷爷顶到嫂子的花心 +天畅 +新疆分裂 +Kefu +搖头丸 +战场 +打倒 +法**论 +毛胡紧涛 +強姦媽媽…肉缝 +乳溝 +610办公室 +苯比 +发$$抡 +大奶头 +祖宗 +中公网 +韩杼滨 +登 輝 +毛私—服 +Rape +亚洲最大激情电影 +6-4tianwang +小嫩穴流血了 流水了 +eight仙靠 +刘文胜 +又长粗的肉棒 +i3hun +好嫩的阴户 +挺入阴道 +董贱华 +…你的鸡巴 用力干 +亚洲激情淫少妇贴图 +回回 +李作鹏 +瘸腿帮 +徐水良 +日 +自由门 +阴茎挺进狭窄的阴户 +日本激情视频聊天室 +好色meimei电影做爱论坛 +歡迎G8情色電影院 +妹妹小穴好紧 +嚮導 +屍體 +wow520 +张 万 年 +網星艾尼克斯 +淫穴电影网 +八九年那個春夏之交 +wangce +武林群侠传 +恼杀美巨乳美女~吉川萌 +肉棒沾满了唾液 +成人 激情 性爱 午夜 高潮 情色 +MUGEN EX Vol。4 吉川萌 +抑制剂 +舆论反制 +亞洲自然超可愛美巨乳 +幼图 +毛强奸犯 +77bbb +極景 +男男激情影院 +外~~掛 +淫欲世家 +…好棒啊……好舒服 +何勇 +毛广电局 +幼圖 +小屄儿里又暖又紧 +亚洲激情淫色文章 +waigua +日本小泉 +观世音 +奸污 +江流氓 +meimei的嫩屄 +asgard +jiejie被轮奸 +18dy免费观看 +免费放淫电影**日本高校女生性交 +销售 +好紧的屄啊 +祁建 +18岁少女处夜激情性爱电影下载中心 +美神ルナ +毛系统讯息 +Kamikaze Girls Vol。 30~中野美奈 +阴道夹的好紧 +发*论 +嫩穴把肉棒包得紧紧 +太王四神记 +航海世紀 +freedom +午夜激情美穴 +K姐 +激情淫乱图片穴欧美男人淫色贴图 +麦司卡林 +铁甲争雄 +舔脚 +馬場大亨 +eight仙 +电影 +┻┼ +地下刊物 +鬼轮奸 +操赤匪 +民运 +插入meimei穴中 +免费电影 +文殊 +联合国大会 +淫色释放贴图 +性交吞精 +肉棒插入湿淋淋的肉洞 +三民主義 +田纪云 +麦角酸二乙基酰胺 +淫奸处女论坛 +8?9靠 +日本成人激情电影 +fuck湿透的内裤 +欧美激情淫色下载 +发$论 +阿姨的阴道好紧啊 +星战情缘 +fuck升达毕业证 +周恩来 +pangya +赤龙剑心 +天之遊俠 +wow711 +免费bb电影 +naive +野性家庭女教师 +抽 +母女雙飛 +舔腳 +黄色电影 +囘良玉 +sh!t +wg9996 +針孔偷拍 +毛妈B +我淫我色导航 +免费淫色情电影 处女第一次阴道做爱全过程(全套图片) +私?服 +突破封锁 +伟哥 +張萬年 +操戳你 +同性恋 +少妇房中自淫,和两勇男玩3P,操得直叫爽 +asshole +TNND +沈阳公安 +娼妓 +娼妇 +我日你 +Kamikaze Girls Vol。29 : Arisa Suzufusa +党中央 +毛嫖客 +色界 +經典炮圖 +吴 邦 国 +令人喷血的春宫108姿势(组图)20岁禁看 +ha bao +激情电影免费下载裸体meinv乳房图 +幹妳老母 +射了还说要 +镇压 +安纳咖 +成人電影 +bastard +出售神符 +大鸡巴 干进 花心 +美女潮吹 +吴 方 城 +買財富 +黄色激情电影 +午夜激情电影 +掰开MM嫩穴 +鸡吧顶住阴道口 +戳 +日本性爱电影 +穿豹紋的meinv,很有野性美。看她咬著肉根就可看出來。 +黑毛屄 +meinv电影 +日本人淫乱操淫荡少妇操淫荡妹妹 +性欲喘息女教師 +尼克松 +李 瑞 環 +夫妻作爱电影 +ASS李弘旨 +肉棒插入肉洞 +幾巴 +光線 +妹妹张开双腿等你操  +色网阴道特写强奸27岁处女全过程 +插淫穴的快感 +操腫 +瓦良格 +你是鴨 +賣ID +免费激情电影 +操丰满小穴 +新手指导员 +小嘴吞吐的肉棒 +拦截器 +batard +东北独立 +petgirl +肏jiejie屄 +日X 媽 +喷精 +本站的免费成人电影 +草嫣 +少妇床上欲火难耐自mo图 +作弊器 +操淫女穴贴图 +强奸36岁处女全过程/淫妹阴毛小穴 +镇压学生 +毛鸡鸡 +插 +免费淫电影网站 +劲舞世界 +小姨的嫩阴道 +裸体meimei林心如穴 +不需付费的色情电影 +淫电影//令人喷血的春宫108姿势 +弟弟的肉棒好长啊 +剛癟三 +仙境傳說 +李月月鸟 +乱伦小荡妇 +联 总 +最新一本道~超级名模系列第13弹 : 真乃瞳 +成人免费影院 +掯 +轻舟快讯 +硅谷动力 +草的你媽 +湿淋淋的阴道 +SM处女淫水图 +久游 +臭鸡巴 +掛 +Paki Paki +绕过封锁 +午夜成人 +玩逼 +mysupersales +魔兽世界 +保证你打飞机 +香港激情片色情工厂直播香港彩福联盟激情 +玛雅网 +發^綸 +激情黄色电影 +毛国家主席 +Gamemanger +足球经理在线 +无套内射 +捻 +毛共狗 +干干 +百家性大型黄站视频 +蜜洞 +激情3级片试看 +鸡毛信文汇 +宁王府成人 +FLG 媽批 +张小平 +针孔摄像机 +避孕 +野性家庭女教師 +法* +免费顶级欲图禁片 +26dy淫色贴图 +同性戀 +肉棒狂插穴口 ┅好爽┅┅ +鸟你 +毛蒙独 +天安门母亲运动 +fuck石进 +干妈妈的爽 +马英九 +Client Server +人大常委 +以及家人 +步非烟 +干保姆小穴 +我幹 +da hang hai +双十节 +我干 +葫芦案 +本站10013多部激情电影全部免费试看 +免费淫色电影-无需注册 +淫骚穴电影 +搓揉裸露在外的那对奶子 +你是鸡 +你是鸭 +去氧麻黄碱或安非他命 +钻插 +淫奸meimei穴 +中年美妇 +李 瑞 环 +挂 +抽插32岁处女meimei淫叫不断 +淫乱潮吹 +168www +DJMAX +慾火 +午夜影院秘密通道_免费不需注册看电影 +毛妹妹黄站 +江豬媳 +伦功 +和护士姐姐淫穴 +meinv淫水狂流 +鲜嫩蜜穴 +烂b +两性激情电影 +香港激情淫色贴图 +felch +999日本妹 +母子淫奸乱轮现场看……扶正肉棒 +李先念 +xinguangming +废墟 +小灵通 +吸精痴女護士 +中文搜性網 +黄色免费淫电影网 +苏秀文 +魂online +夜色城 +老师小穴 +烂B +他妈ㄉ王八蛋 +18岁女生主动让男生开苞全过程◥免费黄色电影 +國民黨萬歲 +……太舒服了 淫肉穴 +日本激情淫色贴图 +网络公祭 +猛烈 挺送 肉棒 激烈 撞击 +毛华建敏 +激情视频聊天 +肉棒插入骚穴 +邓颖超 +肉棒好大啊 +賣QQ +淫电影免费在线观看 +发~纶 +奇迹世界 +联易互动 +十七大 +fuck想上你 +chi long jian xin +毛吗啡片 +操少妇嫩穴 +白漿四濺 +原味絲襪 +刘晓波 +他奶奶 +酣乐欣 +示威 +狂插儿媳妇的阴道 +李克強 +李克强 +刘士贤 +駛你老師 +妩媚挑逗 +天翼之鏈 +美女吞精 +东热美女一个比一个强 +运营组 +台湾成人电影 +特别公告 +仙界传 +jiejie的穴好大啊 +福摩薩 +大鸡巴 插入 肉缝 +强奸25岁处女全过程/淫妹阴毛小穴 +狂插妹妹的小穴 +阿雅娃娃 +夫妻3p +少妇扒开阴道图-淫賤少女阴唇特写图 +fuck台湾共和国 +抽插54岁处女妹妹淫叫不断 +江则民 +熟妇 +免费dse淫乱图片 +懒教 +成人免费电影 +毛威而钢 +淫电影//教你怎样延迟射精18岁以下禁免费淫电影a片 +亞無碼 +买财富 +操成人片 +法× +新手指導員 +淫声浪语 +剛度 +李 嵐 清 +熟女 +又大又嫩的阴户 +江戏子 +干他妈 +久游网 +淫色少妇狗小说大全 +性 +淫图淫片全部免费 +TOM在线 +剑侠情缘II +DROP +┅大力插┅大鸡巴 +MM的小嫩穴 +BASTARD +台湾狗 +Parade Vol。57:巨乳絞りボンデージ +用你的阴茎插我的阴道 +鴉片 +fuck乡巴佬 +咪咪色界 +service +社会院 +最淫大陆成人贴图电影区 处女一丝不挂自慰图片 +台湾身材一流美女楼梯性爱 +插你奶奶 +台湾独 +淫民激情文学图库下载淫民激情文学图库专题 +毛驶你母 +88科技 +流氓 +淫奸少妇穴 +顶级乱伦高潮淫水 +普京 +毛靠 +免费妹妹黄色淫乱 +风水 +女教师禽兽轮奸陷阱 +亚洲有码 +X到喷屎尿 +毛賊東 +赵 海 青 +李 淑 嫻 +六月聯盟 +動亂 +中獎 +天翼之链 +ucdao +a4y +a4u +家庭教师は女子校生 藤沢美歩 +大史纪 +操陈良宇 +海天英雄傳 +bxqt +鹿城娱乐成人俱乐部 +射 精 +朱容雞 +kuaik +刚比样子 +处女淫水图台湾女人裸 +falun +毛胡XX +刘山青 +兔妹妹贴图区 +動乱 +大肉棒 +愛液橫流 +最新成人激情电影网站 +女干三亏 +di guo chuan qi +撅起大白腚 +fuck社科院 +操肿 +濫貨 +學生妹 +强奸32岁处女全过程/淫妹阴毛小穴 +大阳具从后面插入她的小穴 +賀國強 +亲民党 +龟头喷射出浓浓的精液 +淫亂工作 +陆委会 +免费淫色妹妹电影网 +毛发改委 +淫圖 +KeFu +苏振华 +老b +(Waap)女教師 盗撮 - 志保 +荡女 +萨达姆 +操婊子 +万王之王 +earthciv +傻逼 +毛傻B +亚洲激情淫穴 +淫图 +夠酷GOQO +大鸡吧在小穴内壁摩擦 +老B +要射了 +肉棒已经整根插入穴中 +大众色情成人网 +網 特 +fuck双峰微颤 +操肏 +光宇華夏 +江山美人志 +ボディフェティッシュ 桜子 DVDISO +tian shi +毛干妳老母 +∪R靠 +赵小明 +慰 +中文搜性网 +毛青天白日 +民運 +黄 菊 +毛监管局 +抽插30岁处女meimei淫叫不断 +李月月鳥 +在线淫电影 淫奸电影 黄色电影 +慾 +龟头 花心 骚屄 +毛希特勒 +dragonheart +救災 +救灾 +午夜成人影院 +日韩淫女 +他干 +童颜巨乳 +淫女论坛 +精子射到jiejie的穴里 +鸡巴小穴 +手伸到两腿间 +法埨功 +私\服 +荡妹 +插白洁小穴 +鸡八 +露點 +免费成人十八影院 +消滅共產黨 +黄永胜 +肉缝 嫩嫩 +整个龟头插入小穴 +干尼 +淫女贴图区 +濕透的內褲 +lineage2 +男女激情淫影片图片 +枪支弹药 +肉棒插入 嫩穴 +荡妇 +风雨神州 +麦克阿瑟 +银行帳號 +礼品机 +把大龟头对准她的阴道口 +妹妹的阴蒂 +光线 +馬凱 +妹妹骚图 +毛迷药 +淫妞 +大鸡巴好粗… +免注册淫电影在线观看 +賤人 +萬淫堂 +萬王之王 +你的小穴好紧 +及びタイトル ?(Calen)セーラー服とマシンガン 柚木ティナ +wu jin de ren wu +粉穴 +全免激情聊天室 +毛食屎 +父女激情淫色文章 +戳你 +肮脏美学 +揉搓淫骚穴 +22dy淫色贴图 +淫妻 +他奶娘的 +姦染 +天纵 +minhui +鳥gm +淫妹 +ray-city +下载免费淫色强奸电影 +宇明网 +卫星接收器 +媚藥少年 +郑义 +毛卖软件 +遊戲新斷線 +淫间道 +爽mm +黄色免费淫电影母子淫奸电影 +李鹏 +淫姐 +陈总统 +群交亂舞 +内射美妇 +摸阴蒂 +去他妈 +抽叉jiejie +亚情 +淫电影//少女被强奸到高潮时偷拍小A片 +布雷爾 +淫娃 +18禁-空中小姐的淫荡性生活(无码)。 +欧美淫图片 咪咪爱论坛 +智冠 +淫乱金发美女 +他妈 +蒙古獨立 +新郑和 +官逼民反 +李 淑 娴 +内测帐号 +做鸡 +meinv含双棍玩内射 +騷婦露逼 +發^論 +嫩穴里他的鸡巴 +蔓ぺ +Waigua +偷拍掰开阴唇做爱 +性无能 +做鸭 +天縱 +fuck私\服 +龌龊 +我淫我色网站 +meimei的阴道好紧啊 +遥想当年春衫薄 +毛共产党 +社保基金会 +天堂2 +抽插49岁处女妹妹淫叫不断 +輪子功 +政治避难 +买春 +法*輪*功 +消息公告 +民進黨 +street of EROS 07 小泉リカ +webmaster +俄罗斯 +水去车仑 +毛天安门 +Mugen Vol。11 Ai Hazawa羽沢愛!【AVI/ 699MB】 +淫婦 +婊子 +肉棒猛烈拔插 +荡母淫儿 +精液射入了她的体内 +色图专区 +fofg +mes couilles +女激情淫影片下载 +107bb成人小电影 +谭政 +亞情 +吕京花 +淫妹妹贴图 +身份证生成 +101bb成人小电影 +觀世音 +滚 +滛 +鷄巴 +手记注册日韩5002部激情电影 +干死你 +服务管理 +渡口 +毛回良玉 +又黑又粗长的鸡巴 +f r e e c h i n a +鸡巴插入拔出 真舒服 +瘪三 +欧美激情淫色 +电影淫电影艳情电影 +毛妈祖 +最新黄站 +龟头抽插很紧的处女阴道 +fuck卖.国 +龟头 插进 阴户 +她马的 +悔过书 +shyt +日他娘 +少妇床上欲火难耐自摸图 +毛法轮 +性感诱惑 +毛死全家 +张潮阳 +阴茎在我的肉洞中抽送着 +核武器 +写真 +性虐待 +成人贴图区论坛 +WEB战牌 +fuck新生网 +发^轮 +性免費電影 +激情meinv贴图九九情色 +教你怎样延迟射精23岁以下禁免费淫电影a片 +成人网址导航 +Painful Groins Getting Pounded : Akira Shiratori 白鸟あきら +mo你 +中华人民正邪 +抽B淫穴 +∪R +xin jue dai shuang jiao +伍凡 +(Tokyo Neko) Tokyo Neko GN Vol。1 Ibuki XVID+Ogg +淫人情色导航 +sm調教 +毛社保基金会 +妹妹的阴唇好大啊 +大鸡巴 大肉棒狂插嫩穴 +中央军委 +释迦牟尼 +大阴唇jiejie +柯賜海 +干Gm +煞笔靠 +常委 +邱会作 +fuck他爹 +天天免费成人 +做鴨 +水去车侖 +操蛋 +穴门meinv图库 +現金 +管里员 +干GM +发~论 +鸡叭 +阴唇阴道大图三级 +連戰 +性视频聊天图幼女日屄视频脱衣聊天室明星 +易当 +jiejie的阴唇好大啊 +幾八 +淫乱图片 +所盗摄护士姐姐性感美腿图 肉丝美腿艳情淫欲 +淫色BT娱乐导航 +干勒 +徐和柴学友 +肉缝 蜜穴 肉棒 +流淫 +混亂冒險 +毛人体炸弹 +刘杰 +半夜我把龟头插进meimei的深处 +江西田园置业集团 +豆豆秀 +手记注册日韩5014部激情电影 +淘宝 +干小姨子小穴 +性趣 +亚洲成人情色网站 +你妈的 +EVENT +国外A片电影 +胡耀帮 +淫奴 +法陯功 +淫女 +锤子 +淫奸 +钱 其 琛 +龟头插进 +少妇被强奸密穴流水 +肉棒插入美女的肉缝 +hellgate:london +抽插42岁处女meimei淫叫不断 +白嫩騷婦 +jiangshan +淫妇 +大鸡吧操小逼 +傳銷 +王润生 +免费看淫电影 +淫奸熟睡小姨子 +MUGEN EX Vol。7 濱崎(MX-07) +毛刘淇 +邹家华 +湿透的内裤 +乳房 小穴 鸡巴 +干入 +肉棒插进阴道里 +濕了還說要 +成人色情乱伦影院 +激情淫色合成贴图 +一本道~松下美里 +插入穴 爽 +redmoon +毛鮑 +┅┅啊┅┅好舒服啊 +kjking +meimei社区淫色 +Red Hot Jam 9 ミュウの新人调教 +李贵鲜 +妳妈的 +港澳成人午夜激情 +免费淫 电影a片 +桃色 +傅申奇 +毛李岚清 +毛傅鹏 +插入媽媽…肉缝 +中華人民共和國 +di qiu wen ming +八老 +膏藥旗 +她的小屄不紧 +中華人民共和国 +鸡吧 +桃色星期五 +putain +群交乱舞 +fuck我日 +邓发 +毛摇头丸 +baichi +漢娃娃 +BLOW +遺囑 +騷B賤 +外 挂 +Mix Studio Vol。 7女医 +妹妹的小淫穴 +在线免费成人电影 +moyu +淫屄 +卡斯特罗 +达赖喇嘛 +草的你妈 +李立三 +d7se +厕所盗摄 +女教師赤版 +人弹 +27军军长 +gong fu xiao zi +高丽棒子 +肉棒在jiejie的阴道里 +遗忘传说 +愛滋 +天聯世紀 +KOKESHI COWGIRL Vol。24 炎的10番勝負2 前編 : 工藤Hatsumi +美国激情淫色网站 +幼女淫图 +法綸 +成熟性感大美女 +cao +根正苗红 +诱色uu +好爽 +大阳具 +shen zhi ling yu +彭珮雲 +黄色淫乱电影 +江豬 +干到 +大乳頭 +xian jie zhuan +本站10008多部激情电影全部免费试看三天 +谋杀 +津瑞 +6。4事件 +国家民委 +【亚洲/无码】极品女优-姬野愛!【RMVB/488MB】 +日韩免费成人电影 +mao xian dao +猛男狂干meinv +值勤帐号 +老骚比 +毛江核心 +女教师淫乱课堂 +懶叫 +造愛 +urban-rivals靠 +日批 +大話西遊 +tie jia zheng xiong +护士嫩穴扒开嫩穴嫩穴 +遺嘱 +毛疆独 +天安們母親運動 +毛旅游局 +桃色 激情电影 +5173 +强奸26岁处女全过程/*妹阴毛小穴 +銀行账號 +goqo +巨乳素人 +色色 +毛淫毛 +幹你 +陳總統 +pp点点激情片播放 +他娘 +毛骚 +妹妹騷圖 +洱 +邓小平 +永恒之塔 +三国豪侠传 +%共产党烂逼 +妹妹的小屄好痒 +乳暈 +fuck我操 +僵贼 +姐姐的小屄 +布希 +彩票机 +激情貼圖 +智傲 +明星裸体写真图 meinv网络视讯三点 +淫告白 +插穴止痒 +梦幻情人射了10次的强片 +支持达賴 +刘延东 +毛蒙尘药 +发^^沦 +拔出来 +绿色數碼 +熟女玩3P内射来满足欲望 +fosaon +發~~侖 +發@輪 +精液射进妈妈穴里面 +乳晕 +鸡巴受不了了┅┅要泄 +完全免费在线淫电影? +插 小姐 +teen sexy +楊振 +毛蒙古达子 +毛淫水 +义母 +他媽 +禁书 +最新 Queen8 无修正素人 +多维 +米田共 +锦天 +少林传奇 +乳波臀浪 +吃雞巴 +凸点装 +大力抽送 +极品黑丝 +绿色數码 +安非他命 +高莺莺 +毛港澳办 +猛烈的挺送、肉体激烈的撞击 +支持达赖 +习仲勋 +脸盘美身材好就是屄丑点 +39仓Ku +roiworld +插穴止癢 +淫 +淪 +肏妹妹的小骚屄 +强*十八岁meinv护士看完保证你打飞机免费淫电影a片 +系统管理员 +在线淫色电影 +天安门英雄纪念碑 +儿子添着妈妈肥大湿润阴唇 +免费电影 meinv电影 +绿色数碼 +她的阴道好紧 +日本激情淫色贴图区 +午夜场 +暴亂 +图片不爽你砍我 +fuck邪教 +白嫩丰腴的大腿掰开成大字形,肥嫩的小骚屄儿 +无码长片 +亚洲成人网 鹿城最新娱乐网 +tian shang bei +添 穴 两腿间 +和阿姨乱伦 +龙虎靠 +手记注册日韩5035部激情电影 +抽插45岁处女meimei淫叫不断 +發^^倫 +現貨 +淫*女电影片段试看淫mm +365激情淫色贴图 +cocksucker cocksucker +情色导航 成人电影 +毛老逼 +激情淫色文章网站 +日本AV女優 +毛法*轮*功 +3p炮图 +性感动感meinv日本幼少女性感写真 +鳥Gm +搜神记 +60xp。com 电影免费 +歡樂數碼 +黄色情挑艳情小说网骚妹妹成人论坛 +淫語連連 +苏东解体 +日你九城 +色男淫女 +顏射自拍 +暴乱 +润星 +台湾身材一流meinv楼梯性爱 +暴乳 +文物局 +鳥GM +tnnd +痴女吸精 +免费操小姨子 操小姨 操小姐图片 操小姐小说 操小姐自拍 按摩洗浴操小姐 操外国小姐b +zhenshanren +真封神 +时代论坛 +海之樂章 +小日本 +shen me shen me da mao xian +毛上你 +仿真假钞 +亚洲**联盟激情视频 免费下载做爱图片 +她爸爸 +新华通论坛 +保證很像學生妹 +好大的阴唇 +应召 +絲襪淫婦 +鸡吧猛的抽插嫩穴 +popoming +操日风骚少妇穴 +黎安友 +淫荡护士穴 +fuck小日本 +毛我日 +綸功 +马时敏 +hua hua man +狂插儿媳 +三级小电影 +性爱电影网 +公车淫奸女学生 +1989天安门 +激情色情 +台湾女人裸体贴图香港成人电影网 +亞洲色 +温州鹿城成人网 +使劲插我啊 +东北xx网 +蕾丝内裤被龟头顶穿 +发@@抡 +艳照門 +则民 +射了還說要 +淫女嫩穴图 +Duty Vol 50背徳の近亲相奸 +劳动教养所 +人大 +潘国平 +朱可夫元帅 +军民血腥冲突 +免费淫奸女A片段试看 20岁女大学生被强 +免费观看美女裸体贴图 +輪奸內射 +西遊伏魔錄 +毛淫欲 +meinv极品穴 +毛鸡 +舔西 +绿色数码 +毛鸠 +pp242淫色导航 +a片/A片下载/毛片/毛片下载 +毛江Core +sofben sofben +淫水也流湿了我干进她穴内的龟头 +干bi +暴操淫荡小meimei +管里 +民阵 +卖财富 +runstar +逼孕 +麦角酸二乙基醯胺 +死 +毛天皇陛下 +自由之門 +日本娱乐性免费电影在线 +又肥又大的穴 +刚比 +中國分裂 +SYSTEM +电影免费试看 +仙侣奇缘 +中国大学 高清女厕盗拍 vol。01 +K房 +视频自拍 +独占动画~潮崎~高校女教师陵辱1+2 +免费聊天室 +刚瘪三 +騷女叫春 +成人社区 +党主席 +西藏问題 +成人社區 +中國恐怖組織 +fei chang san guo +手记注册日韩5024部激情电影 +sperm +三国世纪 +毛鲍 +chinaliberal +阴精喷向龟头 +少妇房中自淫,和两勇男玩16P,操得直叫爽 操日本淫女穴 +sm援交 +幹x娘 +辉煌 +下注 +mo xiang +强奸45岁处女全过程/淫妹阴毛小穴 +女巨乳女教師 +翘臀嫩逼 +新闻出版 +錯B +捅进她的阴道里 +bitch +抽插38岁处女meimei淫叫不断 +艳照门 +巡查 +吸精小少女 +89-64cdjp +干gM +淫秽男女激情淫乱 +hanbitsoft +西藏问题 +18岁处女床上开苞 +more +白虎小穴 +bukakke +欢乐城美国在线 咪咪爱论坛 +香港马会 +嫩穴狂插直到痉挛 +李 岚 清 +人大代表大会 +毛日本鬼子 +午夜激情情色网 +肉棒进入肉洞 +自由之门 +caobi +fuck王震 +肉棍干騷婦 +啊 啊 啊 好哥哥 +日本meinv图库 +毛强卫 +淫奸少妇电影 +墨索里尼 +免费免注册在线看电影 +交媾 +東北獨立 +法纶 +肉棒的抽插 ……啊 +下流 +色网阴道特写强奸29岁处女全过程 +礼品 +发^论 +品色永远免费堂pin6 meinv发春激情3级片试看 +兔妹妹色色贴图区 +叶剑英 +乱伦+都市+制服 +q币 +毛懂文华 +二五互联 +发@轮 +姦汙 +高丽棒 +國家機密 +毛肉缝 +yuanming +干gm +紅月 +淫水大量流出 +metin +由喜贵 +谢长廷 +三去車侖工力 +大鸡巴插进meimei的小穴 +二五互聯 +娇妻超市被奸,淫荡妈妈之办公室助理 +江贼 +鸡吧插到嫩穴 +久之遊 +美女激情性交射精电影 +买春堂 +奴隷女教師-女尻狩り 吉野あゆみ +淫蕩少婦好色老師 +gate to heavens +册老 +麦角酸 +他祖宗 +fuck新光明 +操蠢猪 +88bb成人小电影 +fuck铁道部 +欢乐城 +亮屄 +大唐风云 +宋祖英 +傅全有 +神之领域 +龟头插入淫荡少妇 +混沌靠 +巧淫奸戏 +……媽的騷穴癢死了 +發$輪 +幾叭 +蒙哥马利 +大话春秋 +一股淫液从肉洞喷出 +淫荡少妇穴 操淫荡少妇 +曾培炎 +kefu +花心大型色站 +meinv偷拍成人小说激情网 +断水 +干啦 +冊老 +官方管理者 +xian jing chuan shuo +免费注册激情视频聊天 +transvestite +性情中人 +刘凯中 +狂插空姐 +操冰毒 +妹妹的大阴唇好嫩啊 +毛我操 +日本AV女优 +抽插37岁处女meimei淫叫不断 +湿了 +毛吴 仪 +伤亡 +售號 +朱容鸡 +日韩淫乱meinv图 +酥胸诱惑 +lian ai he zi +法**輪 +含着龟头 +分裂祖國 +meng huan zhi xing +Tora-Tora-Tora Vol。22 : 冬月ひな +Ji女 +淫水和精液浸濡的小穴里 +秘密通道 +fuck驶你老母 +烂比 +新视野工作室 +狂操小姐 +分裂祖国 +陈随便 +鲍鱼贴图妖色成年网电影 +大哥 等等 我尿完后 再给你干肉穴 +操b +学生妹同男友夜晚做爱并轮插 +hypermart。net +狂插妹妹穴 淫水流 +巧淫奸戲 +fuck水利部 +何德普 +成人午夜激情 +操B +海盗王ONLINE +ying xiong wang zuo +遗囑 +毛抢劫 +大東亞共榮 +*李*洪*志* +辛灏年 +保证你打飞机免费电影网站 +kaixuan +毛新唐人 +發*輪 +AV OPEN)(TOD129)近亲3姐妹狂乱夜 +尸體 +别他妈的装 +fuck私—服 +虎虎虎~变态心Tora Tora Gold Vol。17 : Mako Takeda +一贯道 +fuck宋祖英 +台灣民國 +肉棒插入阴户 +J-Girl 双穴~水原 小笠原崎 +妈的 +值勤账号 +屎你娘 +试看片 +妳她媽的 +出售手枪 +喵的 +365免费情色网欢欢成人娱乐 +fuck天安门档案 +逼奸 +鸡巴磨得舒服 +遗嘱 +白嫩美女穴 +fuck私-服 +灌满精液 +桑国卫 +操妳全家 +玖玖金币 +your mom your mom +creaders +搞大肚婆爽+口交泻水淫图 +温馨提示 +张 宏 堡 +斷水 +人妻 +shit +我和姐姐肏穴 +如果你未满21周岁请自觉离开。 +中国威胁论 +方毅 +肉棒插入 +法**轮 +舆论 +斯大林 +Aids +ling you ji +插的妹妹流淫水 +瓜娃子 +jing ling +賣月卡 +刘淇 +你他馬的 +发*轮 +鸡奸 +王俊博 +鸡女 +乳房 +僵贼民 +公务员调资 +制服美少女 鮎川なお +新聞管制 +fuck私/服 +毛他马的 +阴壁的嫩肉夹得我非常舒服 +淫店 +黄色淫电影/大幅的陰毛覆蓋著她的迷人洞 +Tokyo Hot n0232 : 真宫梨沙子 +西哈努克 +莎士比亚 +明慧 +台灣民国 +硕大的龟头 +黄 菊 +毛吗啡碱 +操你爷爷 +renmingbao +meimei的屄好紧啊 +分裂中国 +日本 +欢城互动 +57xp。com 电影免费 +消灭共产党 +个人资料 +王 秀 丽 +UPDATE +分裂中國 +调教 +天安門檔案 +日本顶级淫女 +傅鹏 +68wow +无产阶级 +贾廷安 +bt免费淫电影下载 +毛交通部 +高丽朴 +偷操嫂嫂 +mm要我使劲插它的穴 +鲜红小嫩屄被群奸真可惜 +du shi 2046 +妈b +喬石 +Lateinos +严隽琪 +淫穴 大鸡巴 +狂插我的小嫩穴 +街上钓个漂亮马子回家玩 +meinv主持25小时全天激情热舞 +輿論鉗制 +服務管理 +蒋正华 +遭警察殴打 +本拉丹 +房事 +妈B +美女性交极品大片 +红肿的小穴摩弄 +跨下呻吟 +毛骚货 +插小穴 +大腿 +啊…我的亲丈夫…用他的手…插…啊…啊…进了人家的小穴 +最新一本道)超正MODEL系列 仲里愛 +精液 +红 灯 区 +希望online +天然むすめ~08-15 素人むすめたち +拍卖官 +新浪 +qq堂 +peacehall +肉棒……插死浪穴了 +快操我快操我的小B电影 +把阴户内塞得满满 +预测 +大肉棒干进小穴 +鄧朴方 +大幅的陰毛覆蓋著她的迷人洞 +教你怎样延迟射精40岁以下禁免费淫电影a片 +19dy淫色贴图 +少女露嫩穴 少妇嫩穴 美女的嫩穴 +徐建國案件 +龟头插入阴唇 +appie +玉女心經 +罗荣桓 +精液喷射在子宫上 +又粘又湿的阴户 +弹劾 +日韩激情电影 +發@@倫 +巨乳女教師 +迷奸熟妇怎样抚摩女性的私处更刺激 +午夜激情剧场 +瞳 +黄大仙 +法**綸 +我和她 +扒开淫女的骚逼 +b毛 +Obama +發~淪 +龟头插入蜜穴 +共荣圈 +肉穴 大鸡巴 ……骚穴 +发$纶 +毛民运 +恥辱醫護下载 +快乐AV +邮政局 +我和小姨子 +插嫩逼 +李洪宽 +操小穴 +哪有a片 百万meinv贴图夫妻激情免费视频 +如何推翻中共 +血洗天安門 +渣波波 +李兆焯 +公安部 +表姐含我小鸡鸡 +中蕐 +情色淫电影 +herogame +騷乳 +AIDS +教你怎样延迟射精27岁以下禁免费淫电影a片 +妹妹┅┅爽快┅┅死了 +毛毛泽东 +神泣 +dick +戴海静 +ASS +神泪 +打倒中华人民共和国 +视频 +枪决现场 +刀剑 +成人禁书 +插入穴爽死了 +保钓 +fuck食捻屎 +骯髒美學 +釣魚島 +干……干我……用力地干我…… +毛西藏天葬 +免费色站 +毛干你 +开天 +手机复制 +毛兴奋剂 +SHIT +89六四 +淫情 +金尧如 +雪腿玉胯 +(Nadeshiko)夢の超高級癒し系Wおでかけソープ嬢 完全版 +干嫂子 +法溣功 +NEWSPACE +狂插秘书穴 +Kamikaze Girls Vol。23 : Haruka Kaede 枫はるか +可愛均整清純派meinv可愛均整清純派meinv +韩天石 +吸吮套弄了起来 +奥美电子 +眯 +免费台湾18 电影 +东方资通 +gan你 +騷小浪女 +無碼電影 +我和老板娘 +淫穴更紧紧将我的肉棒吸住 +fuck他妈 +男女激情图片 +國家安全 +浴室亂倫 +虎门靠 +megaone。com +cronous +叼你媽 +毛狗卵 +牛鬼蛇神 +冊那娘餓比 +儂著岡巒 +睾 +我要性交 +将肉棒插入漂亮的老师小淫嘴抽插数十次 +群奸轮射 +全球第一淫图城 +san guo hao xia zhuan +夜夜色大型网站 +龍陽 +毛靠你妈 +bing feng chuan qi +fuck我日你 +洗腦班 +fuck吴邦国 +groove party +贾庆林 +娇嫩的小阴核 +mo fa fei qiu +福呵定 +毛肉穴 +穆斯林 +虎騎 +疯狂的抽插 +敬国神社 +kong que wang +zhen kong que wang +干死GM +徐炳慧 +肉棍 嫩穴 肉洞 +操大B +手记注册日韩5028部激情电影 +meimei美图网 +妹妹的屄 +母子乱淫贴图 +色咪咪 +干比 +毛十五周年 +生孩子沒屁眼 +退役 +情色激情论坛 +性虐 +B +免费成人午夜电影 +日本淫贴图 淫妻贴图 +性虎 +阴茎被她紧紧地夹住感到肉洞急促地收缩 +居家女人的淫荡性事 +温州黄站 +抽插56岁处女妹妹淫叫不断 +华岳时事论坛 +儿子粗大的肉棒 +淫电影 强*十八岁美女护士看完保证你打飞机 +b +张开的小阴唇 +李小鹏 +玉女心经 +毛机八 +家人一起凌辱母亲和叔母 +激情成人乐园 +xia ke tian xia +rape +盛宣鳴 +黄色淫穴电影 +乘骑按摩 +xin zheng he +壮汉给纯情处女开苞见血 +應召 +免费淫色情电影 淫电影//少女被强奸到高潮时偷拍小A片 +台湾18成人网站 +本土无码 +賣B發論公 +司徒华 +apesoft +温总理 +迷人阴部护士meimei也疯狂 +情獸 +智能H3 +骚妹妹成人导航 +作愛 +古龙 +抽插28岁处女妹妹淫叫不断 +神汉 +美丽素女の性游戏 +色网阴道特写强奸35岁处女全过程 +新西遊記 +西藏國 +回民人吃豬肉 +干死CS +反攻大陆 +证监会 +西藏国 +杜智富 +毛塞你爸 +毛气象局 +反攻大陸 +又大又紧的阴户 +激情成人聊天室 +秘书自慰被偷拍 +C N +金三角 +一夜欢 +妈妈的 +强卫 +毛邪教 +胡志明 +狂插小嫩穴 +咪咪爱大型黄站 +东热meinv一个比一个强 +迷人小穴好紧好湿 +蝉童 +免费台湾激情片 +Trickster +激情淫色贴图网 +发*纶 +18歲少女 +情色电影注册观看 +小穴夹的我好紧 +撒切尔 +hua xia +江泽慧 +中国性爱城 +騰仁 +空中小姐的淫荡性生活 +一夜歡 +干死 +以茎至洞 +亲 日 +品色永远免费堂pin6 美女发春激情3级片试看 +王太华 +磨蹭阴道阴毛 +妹的穴 +两会报道 +毛工作人员 +你妈逼 +fuck斯大林 +淫色bb贴图 +無碼彩圖 +於幼軍 +内挂 +精液射进她的小洞 +慶 紅 +日本插穴 +hongzhi +懒8 +淫电影//富豪们的疯狂做/爱方式 +新党 +免费淫奸女A片段试看 母子淫奸乱轮现场看…… +淫荡少妇激情自拍 成人激情 +免费成人两性电影 +抽插大淫穴 +邹德威 +飘流幻境 +语句 +大FA弟子 +小淫穴 +淫奸秘书电影 +剑侠情缘OnlineII +SKY宫泽Keito 超美系模特儿初无修正引退纪念作 +毛反革命 +龟头插入少妇阴道 +手记注册日韩5031部激情电影 +黃孟複 +盛宣鸣 +疯狂姐姐淫穴 +wg8800 +上访 +壓迫 +大B +王乐泉 +tta2 +运營组 +人民代表大會 +刘军 +愛色cc +博白县 +抽插35岁处女meimei淫叫不断 +死亡人數 +李鐵映 +鹽酸二乙酰吗啡 +毛淫叫 +丝袜 +connard +popkart +天安门事件1989 +处女小穴 +成人爽电影网站 +MM的诱人双峰 +9游 +超强护士团 +东方传说online +他爹 +政府 +怎样延迟射精22岁以下禁 +代炼 +午夜影院 +十八dy毛电影 BTA片 免费激爽电影 +美穴張開貼圖區 +毛南蛮子 +两性小说 +尖閣列島 +如果你未满28周岁请自觉离开。 +精液喷入穴 +项英 +林心如合成淫照图片林心如淫照图片 +脫內褲 +肉棒 小穴里抽送 +丝袜高跟 +淫女炮圖 +金泽辰 +畜 +穆罕默德 +我跟meimei肏穴 +本站10000多部激情电影全部免费试看三天 +日本meinv吃精图 +秋本純菜 +操日本淫女 +helbreath +粉红嫩穴 鲍鱼嫩穴=3 +粉红嫩穴 鲍鱼嫩穴=1 +抽插51岁处女meimei淫叫不断 +粉红嫩穴 鲍鱼嫩穴=2 +天晴数码 +倪志福 +万晓东 +色色婷婷 +(最新一本道)独占动画~薰~陵辱巨乳 +手伸到下体抚摸嫩穴 +八 仙靠 +儿子的肉棒好硬 +本站10000多部激情电影全部免费试看 +sm舔穴 +人民代表 +素人之中的极品漂亮妹 +小癟三 +feng wu tian jiao +大血B +刘刚 +成人激情淫影院 +爽女美图美搜性感图涩界成人电影网小小鸟绝色美女写真图 +用舌尖插着阴道口 +我占有了妈妈和阿姨 +情色六月天 人间仙境情色网 +xin shi qi +熟女网爱记 +姐姐的穴夹的我好紧小说 +乱淫自拍图片 +俄国 +操比 +淫女炮图 +运營者 +TokyoHot之极品妹妹 +ttee +毛新华社 +天晴數碼 +610办公室靠 +陈伯达 +赤裸天使 +虎骑 +台聯黨 +毛龟儿子 +白嫩骚妇 +毛傅作义 +小穴的周围不断地缠绵着 +台湾18成人 +毛尉健行 +阿姨的穴┅好爽 +韩东方 +媽個老比 +毛毛主席 +tth2 +和jiejie插穴 +華建敏 +精童 +毛李长春 +香港两性激情文学区 +fuck身份生成器 +死亡人数 +插入妹妹穴中 +狂操淫荡女 +干你妈逼 +华语世界论坛 +天葬 +pet520 +夫妻自拍 +色诱 +毛文化部 +秦基伟 +宋xx +陈锡联 +山不过来 +逃亡艳旅 +11。xp。com成人影院 +meimei小穴 +激情裸聊 性爱电影 +BT成人无码 +血洗天安门 +人妻做爱 +fuck新党 +可憐賣菜婦 +遊戲宮理員 +情色 激情 meinv 穴 +mir3 +湿了还说要 +zhengjian +免费裸体meinv性交电影 +洗腸射尿 +gang jia hong liu +诱惑女教师 +dick dick +顶到了欣虹阴道最深处 +zheng qi huan xiang +阿罗约 +口交放尿 +连战 +…好深啊…操我 插我 +da hua chun qiu +b样 +性福源亚洲激情 +中国恐怖组织 +温家宝靠 +乳罩 +meimei吸精 +操死 +色聊激情视屏聊天室 +戰國英雄 +蔣介石 +海关总署 +帶炼 +姦淫 +懒八 +午夜免费成人黄色 +妈祖 +农民伯伯乡下妹 +强奸十八岁meinv护士看完保证你打飞机免费电影网站 +U R靠 +風豔閣 +lihongzhi +玉蒲团 玉女心经 +王力雄 +lian ai he zi +阿姨的阴户好大啊 +jiaochuang +淫奸少女论坛 +新金瓶梅成人片 +B毛 +香港激情夜 +香港激情淫穴 +草芝麻 +大 史 紀 +网星艾尼克斯 +淫奸meinv穴 +meimei张开双腿等你操  +舔逼 +wg2222 +毛妹妹贴图区 +龜頭 +装备演示 +浩天銀科 +hai zhi yue zhang +知障 +fuck希特勒 +援交薄碼 +処女 +欣赏特级毛片pp 点点毛片 美女毛片 大陆毛片 +激情电影在线注册 +免费我该死淫水流出图 +淫女与猪乱搞图 +女良 +郭 岩 华 +龟头插入少妇 +激情视频 +懶八 +星际online +人民大会堂 +发^^纶 +韩国成人激情影院 +金庸群侠传 +粉紅穴 +毛驶你娘 +操狗 +插穴好舒服 +好爽……顶得好深啊…… +龟頭 +駭客 +毛劳动保障部 +丁字裤翘臀 +虎门 +色成人 +可卡葉 +51vip +纠察员 +遊戲橘子 +儂著卵拋 +黑马@美女全身神秘黑让你爽到眼框黑 +淫战群p +毛黄色小电影 +肉棒在阴道口游荡 +你的 嫩穴 好粗 +basterd +肉淫器吞精 +食精 +强奸24岁处女全过程/*妹阴毛小穴 +钢甲洪流 +松花江污染 +免費成人網站 +騷包 +淫战群P +叫小姐 +诱惑骚妹 +人妖@Lady Sonia-熟女丝袜 12 +林心如做爱网有激情 +操嫂嫂 +淫乱的女老板 +肏穴好舒服 +激情淫色电影 +獸 +老少亂倫 +成人淫穴导航 +老毛子 +你祖宗 +毛乳头 +体育练习场盗撮スポーツジム(4カメ洋式) +插meimei图 +膣穴大陵辱 松岛 +籐原紀香Norika Fujiwara SEX +錯那嗎逼 +獨 +精童欲女 +高级逼 +李 總 統 +新四 +mingpaonews +成人 +淫肉诱惑 +毛烂逼 +┅插┅小穴 肉缝 +粉紅愛液 +浪女自慰诱惑你操 +nnd= +魏新生 +援交薄码 +免费操小姨子 操小姨 操小姐图片 +狗養 +操爽 +日你祖宗 +少妇淫图电影网 +免费激情影院 +毒龙舔脚 +上山下乡 +busterd busterd +狗娘養的 +警匪一家 +15年前的“共和國衛士” +激情聊天室 +大话 +厕所盗摄美女 +丁香成人社區 +穴里嫩肉把鸡巴包得紧紧 +日韩成人电影 +sex大型色站 +胡总书记 +操爛 +去氧麻黃堿或安非他命 +闹事 +梦遗 +彭冲 +本站10014多部激情电影全部免费试看三天 +抽插38岁处女妹妹淫叫不断 +激爱贴图 加西激情中文网 +女性私处锻炼法 +哥哥 +操 +我的穴 +税力 +裝備演示 +毛叫鸡 +好大阴户 +陈永贵 +流淫水 +操mm穴 +asshole asshole +免费淫电影吴宗宪搞笑语录(20禁看) +丁香成人社区 +粗大肉棒从后面插入 +插進 +妳娘的 +free style +插逼 +撒泡尿 +秘书的大乱交 +手记注册日韩5005部激情电影 +学生妹美女在野外偷情 +赵品潞 +坐台的 +无码H漫 +rong yao +毛鲜族 +祭日 +吳官正 +口含住鸡巴 精液 +成人午夜激情视频 +色狼小說 +扒开小穴 +激情淫色组图 +捐赠排行 +ygbh +見到這個meinv就會有性欲 +as$hole +总裁 +菊花洞 +黄色免费淫奸电影我和女友干爽后再她妹妹 +运營組 +裸体妹妹林心如穴 +蘚鮑 +愛液 +Transformaition 栗田Hiromi +插进 +疯狂姐姐教弟弟小说 +轮流干 +365成人网站 +删号 +阿姨的小穴 +伊朗 +guang zhi guo du +肉棒全部插入 +少妇房中自淫,和两勇男玩11P,操得直叫爽 操日本淫女穴 +淫meimei贴图 +戴维教 +亚洲成人无码 +台湾成人20贴图 +大肉棒……好粗 +牙齿轻咬他的龟头 +免费淫奸女A片段试看 居然花钱请人教性爱姿势(组图) +小瘪三 +午夜激情meimei +毛寇晓伟 +手机注册看性爱电影 +肉棒插入妹妹的肉缝 +快乐西游 +fuck司法部 +百家性大型娱乐黄站 +爛 +林心如做爱我该死快乐情感乐园 +大b +毛联合国大会 +ke luo si +剑侠情缘 +原味丝袜 +sars +日你 +肉棒摩擦她屁眼里的嫩肉 +淫女露穴 +禦の二代目 +收缩的阴道中抽出肉棒 +爱液横流 +然后 +爽 +jiao chuang +wu hun +san guo qun ying zhuan +嗎比 +江青 +成人激情淫论坛 +懒叫 +神曲 +洗脑 +完全免费在线淫电影 +发$$仑 +女人被干小穴 +淫电影网站 +欢乐时代 +翹臀嫩穴 +程凯 +機巴 +国 贼 +三P +骆冰淫传 +政治局常委 +肉棒插肉缝 +大龟头顶紧子宫口 +法$$轮 +毛妈的 +香港顶级淫片 +韩日成人午夜激情电影 +fuck新闻出版总署 +免费注册 试看50部 +抽插23岁处女妹妹淫叫不断 +毛共青团员 +操烂 +湿身诱惑 +干爹的龟头 +华夏文摘 +日他 +狂插妹妹小穴 +抽插40岁处女妹妹淫叫不断 +Shit +自慰女學生廁所偷拍in Toilet 1 +北京xx网 +日你媽 +谢选骏 +色情电影 卡通 成人 av 少女 +非常诱惑 +6。4事件 +狂插美女老师 +淫奸meinv +夜话紫禁城 +臺灣國 +bo ke +中國豬 +激情bt亚洲区 +国产经典 - 4级红楼梦!【wm/113MB】 +操草的你妈 +白莲教 +妈妈的穴 +開天 +涵涵 +大 史 纪 +教你怎样延迟射精42岁以下禁免费淫电影a片 +ping guo pai +法$$輪 +燕玲論壇 +迷奸 +淫民俱乐部和美女发春激情3级片试看 +诺亚 +教徒 +央视内部晚会 +操粗制吗啡 +浪穴 肉缝 嫩穴 +强奸26岁处女全过程/淫妹阴毛小穴 +大阴唇夹着大龟头 +拍肩神药 +cunt +肉棒 用力 肉縫 +淫書 +幹比 +travesti +魏京生 +墨香 +網域 +毛狗养 +王志珍 +毛耶苏 +一国两制 +江ze民 +劲舞团 +毛主席 +東突組織 +大 纪 元 新 闻 网 +222se图片 +三p +四川独 +齷齪 +成人激情性爱电影网 +暗黑之门:伦敦 +jiejie的屄 +本站10009多部激情电影全部免费试看三天 +人妻自拍 +操出售枪支 +靖國神社 +易玩网 +不注册淫电影 +高清性爱 +毛发伦功 +allsexpages +OL美女街上遥控震动A +日本人 +piao piao +法车仑功 +天龙八部 +干汝 +班禅 +新华举报 +幹死 +fuck王宝森 +毛私\服 +毛全国人大 +真善忍 +server +re xue ying hao +捐贈排行 +肉棒插到妈子宫 ┅┅爽死了 +台湾男女激情淫乱小说 +激情 少女 成人论坛 乱伦 强奸 +免费淫奸女A片段试看 教你怎样延迟射精18岁以下禁免费淫电影a片 +无界浏览器 +热比娅 +淫荡jiejie勾引小弟玩操屄 +國產騷貨 +瓜婆娘 +移彩联合 +开着摩托干了岳母 +红色恐怖 +神出鬼没!3个丁字裤辣妹到处袭击肉棒(中文字幕 +迫害 +毛穴贴图 +亚洲激情淫色网站 +烂 +淫荡老师 +小姨子的小嫩屄 +create +亚洲激情BT +省长的儿媳妇 +苹果日报 +xian lv qi yuan +于天瑞 +鸡吧在肉洞里四处搅动 +中医药局 +16大 +手记注册日韩5008部激情电影 +肉棒 插 穴 +江主席 +发@@沦 +阴小撕大 +毛台湾民国 +泡泡岛 +大鸡巴狠插小穴 +成人电影网站 +柔阴术 +勁舞世界 +淫样 +正义党论坛 +啊……我的小屄……给你……肏得好……舒服…… +强*十八岁美女护士看完保证你打飞机免费电影网站 +一黨專制 +深爱色色 +a级电影 +情色 性息 +乳此豐滿 +166网址宽频影院网 +慈善會 +xinguangming鳥你 +无码丝袜 +onhave +猛力的抽送大肉棒 +falu +空姐性交 +妈妈帮儿子套动着 +meinv野兽做爱淫图 +vulva +求自己的爸爸和她干 +乳波臀娘 +色狼小说 +肥穴jiejie +灾 +獨裁 +裸体做爱 +将阴茎尽根插入 +毛刘军 +摳穴 +龟头用力刺入阴道 +王樂泉 +周永康 +成人网站排行榜 +儿子淫奸妈妈穴 +肉棒 用力 肉缝 +淫乱护士 +六四真相 +客户服务人人员 +地 下 教 会 +tw18 +含鳥 +手记注册日韩5011部激情电影 +发$$伦 +小鱼儿与花无缺 +叼你妈 +紧致小穴抽插 +B样 +摩力游 +蓮花逼 +大肉棒插入湿湿的肉缝 +异议人士 +懶8 +dou dou +娘比 +本站10005多部激情电影全部免费试看三天 +插阴茎 +三国演义 +毛统计局 +法侖功 +北京xx網 +奶罩 +hai tian ying xiong zhuan +三级图片论坛禁自拍偷拍论坛日本黄色三级 +guai shou zong dong yuan +地富反坏右 +96bb成人小电影 +meimei的大阴户 +信仰 +迫奸 +sheng zhe wu di +牛B靠 +色女乳房阴道 +麥司卡林 +毛李鹏* +多維新聞 +嫩女 +tian shi zhi lian +妹妹嫩穴 +点击这里试看meinv做爱现场 +世维会 +嫩奶 +小日本爆撮中国女子大生vol。01 +乔石 +fuck you +豪乳 +習近平 +三去仑功 +高麗朴 +avatar +成人激情淫穴影院 +hong yue +免费在线淫电影下载 +大陆娱乐最新黄站 +龙虎豹 +嫖客 +大逼 +操那吗B +超毛大鲍 +我和少妇 +现代艳帝传奇 +realexterme +操表姐 +朝倉Riho !【RMVB/405MB】 +光宇华夏 +淫棍 +shen jia qi bing +陈希同 +发廊性息 +百家性大型黄站网址 +湿湿的阴户不断地在大鸡巴上磨擦 +日你妈 +干进meimei的小穴 +Tora Tora Gold Vol。14 星野みく +手记注册日韩5003部激情电影 +嘻游中国 +俪影蝎心 +佈雷爾 +小雞雞 +網易 +猛插表姐 +64yl +母子淫*乱轮现场看扶正肉棒 +法論 +網星 +大 史 +┅你的大肉棒┅┅好粗 +于幼军 +美マンの極意 : 相原梨花 +43lian色站大全 +台湾ye77 +肉棒里插肉洞 +亚甲二氧基甲基安非他明 +人民 +TEsT +中国成人论坛 +几巴 +免费免注册在线淫电影 +人民日报 +体奸 +我淫我色 +meinv直播做爱 +Bi样 +性感肉絲 +李嵐清 +美女高潮 +儿子顶到jiejie的花心 +强奸37岁处女全过程/淫妹阴毛小穴 +黄色激情论坛 +淫女乱伦小说 +小穴被阴茎插的好痛 +少妇淫心我要看淫心 +wan wang zhi wang +免费黄色电影 +私处 +爱巢滴水 +嫐屄 +给女人快速达高潮的秘密 +淫奸jiejie小说 +欧洲极品性交图片 +下三烂 +氵去车仑工力 +色网阴道特写强奸36岁处女全过程 +骚妹阴道 +裙内偷拍 +往事追忆录 +廁奴 +他妈的 +床上的淫荡少女 +本站10012多部激情电影全部免费试看三天 +轮奸做爱高潮 +enculer +毛烂货 +情色导航色情排行榜大陆黄网导航免费成人电影 +少妇淫乱小说 +丰满小妹的丰褪美腿 嫩得流水的小妹妹 +306医院 +nmis +金伯帆 +a片 +超毛大鮑 +17爱网 +升达毕业证 +J-spot PA-39 +東洋屄 +色网阴道特写强奸20岁处女全过程 +本站10009多部激情电影全部免费试看 +插在妈妈嫩嫩的小肉穴 +猛操狂射 +外汇局 +淫奸教师论坛 +卡通meinv淫色贴图 +手记注册日韩5021部激情电影 +鸡巴暴胀 +学自联 +日内瓦金融 +夜總會 +法*轮*功 +造反 +夏夏娱乐黄站 乱伦熟女网 +林心如做爱网有激情自拍 +野外性交 +身体障害者 +肉棒插护士穴骚穴 +好硬的肉棒 +肉棒插入小穴里 +狂插学生妹 +鹿城最新导航 +张朝阳 +肉棒淫水嫩穴 +叫雞 +蔣正華 +c a o +处女第一次阴道做爱全过程 +淫乱激情电影网站 +火棒 +色窝窝网之家 +幹一家 +江則民 +通告 +东突组织 +濕穴 +亚洲情色网 嫖娼 -刷单 \ No newline at end of file +大海戰II +freechina +干美女小穴 +新闻封锁 +高麗棒 +18dy +毛俞正声 +秘唇 +淫色五月天 +42lian色站大全 +fuck驶你老师 +淫樣 +下三濫 +毛建设部 +极品白虎 +毛列宁 +肉棒狂插小嫩B +远志明 +淫色论坛 +亚洲淫色贴图365 +下载免费淫电影淫穴流 +法论 +東條英機 +肥穴自拍 +发骚 +法谪 +六四屠殺 +奶挺臀翹 +mabinogi +济南建设路 +韓 東 方 +g片 +駛你老母 +spikegirls +日你娘 +系統 +淫色少妇做爱淫穴流 +情色 meinv -公安机关 -记者 -犯罪嫌疑人 +*法*輪*功* +侖功 +强奸17岁处女全过程/*妹阴毛小穴 +奶挺臀翘 +肉棍干骚妇 +强奸18岁处女全过程/淫妹阴毛小穴 +淫穴内好痒 +激情午夜 +兽欲 +fuck万税 +厕所盗摄美女性感 +石进 +meimei的阴唇好大啊 +法~~仑 +ai滋 +你奶 +中国复兴论坛 +妈**菊花穴 +恩格斯 +鬼輪奸 +Kamikaze_Girls_Vol。12 +黃 菊 +bb论坛 操bb图 +洪興 +台湾淫色网 +g点 +客戶服務 +快……快……幹我……幹……我快忍不住了……哼… +kai xuan +嗯┅┅嗯┅┅舒服死了……妹妹又要丢了 +你妈 +驶你老母 +舌尖舔着肉棒 阴门 +肉棒 抽插 小穴 +征途 +毛台湾独立 +WEB牌戰靠 +手机自慰网 +外交与方略 +明诺东方 +操jiejie的穴 +fuck手淫 +浪穴 +fuck新义安 +毛四人帮 +吴官正 +肉棒插得湿润了 +統 +反右题材 +cao你 +i3hun +干您 +轮子功 +毛天皇 +法~~伦 +好紧的穴 +辦公室淫亂 +kong que wang +免费成人激情影院 +安理会 +軍民血腥衝突 +张宏堡 +联通移动秘密通道 +夫妻电影 +滕仁 +公媳性交淫荡图片 +大鸡巴┅┅爽 +搞b +劉雲山 +鹿城黄站图 +滕人 +中科院 +少妇房中自淫,和两勇男玩10P,操得直叫爽 操日本淫女穴 +毛贼东 +政治压迫 +下三滥 +你姥 +陈丕显 +駛你公 +賣國求榮 +綸 +f u c k +王岐山 +fuck色情小电影 +yuanming噴你 +屆中央政治局委員 +你娘 +美女穴自拍 +移彩聯合 +吴学灿 +法$仑 +cock cock +龟头插花心深处 +OLmeinv街上遥控震动A +淫欲 +台湾成人骚b +江泽民 +激情交友 +sega +华国锋 +滕任 +干 淫穴好舒服 +两性淫乱贴图 +又紧又嫩的屄 +台湾18dy影院 +karma +cao ni ma +美国佬 +淫荡少妇极品穴 +騷姐姐 +美女成人 +南大自由论坛 +色情论坛 +出售神符靠 +毛干妳 +殺你全家 +秘书长 +成人色情午夜激情 +政权 +爱因斯坦 +法~~侖 +神之領域 +娘个比 +卖党求荣 +肉棒入少妇嫩穴嫩穴 +蜜穴 +法*仑 +免费观看女教師赤版 +高麗樸 +激情少妇 +美國佬 +成人动漫 成人文学网 成人小电影 +免费淫电影吴宗宪搞笑语录(21禁看) +六四正名 +天安門錄影帶 +色影院 +mankind +顺着红嫩的肉缝上下抚弄后插入小穴 +毛贱人 +初中meimei的小美穴 +人民礼堂 +疯狂抽插她的小穴 +破處 +肉棒一阵猛烈的抽插 +世纪天成 +亚历山大 +淫毛 +日军 +男女激情淫贴图 +强奸电影网站 +游戏送奖员 +操王 +嫩鮑魚 +你媽 +吸吮著我的阳具 +淫母 +你娘的 +我和姐姐的淫乱史 +阴唇好嫩啊 +言论自由 +亚洲成人俱乐部 +真主安拉 +美腿美穴大屌 +法$伦 +又大又嫩的屄 +統治 +222se圖片 +操迟浩田 +风骚小阿姨 +淫女 幼B +機八 +毛塞你母 +法~~倫 +服务天使 +一起玩 +错比 +淫美贴图区 +发~~轮 +肏屄好舒服 +发^纶 +粗肉棒阴户 +阴茎被子宫夹住好爽 +Jj插入嫩穴 +成人激情午夜场 +武林外史 +强奸31岁处女全过程/淫妹阴毛小穴 +肥厚柔软的大阴唇夹着大龟头 +FALUNDAFA +俄罗斯激情淫色贴图 +法*伦 +淫汁 +毛外 挂 +33bbb走光 +伊斯兰 +av小电影 +淫水 +马加爵 +处女的肉穴给他的肉棒一插到底 +快来┅┅插 肉穴 +meinv网站脱衣meinv百分百作爱 +调教虐待 +成人电影导航 +Vol。 17 ~巨乳美熟女 +帕巴拉•格列朗傑 +妹妹的小穴好紧啊 +娱乐性大型黄站 +复辟 +我第一次舔表姐的阴 +强奸系列精品 +陌生做爱在车里发生 +游戏米果 +小屄儿温暖滑嫩 +十八摸 +豔乳 +fuck神经病 +骚姐乱伦网 +无码淫漫 +国外成人激情网站 +无码彩图 +kuai le xi you +轮暴 +tibetalk +92bb成人小电影 +免费淫电影网 +干我 +天然むすめ 素人~みか +狂插白嫩幼女bb还射乳 +救援 +xing zhan qing yuan +多維網 +巨乳女优 千秋大合集 +换妻大会 +新观察论坛 +人妻阴穴 +色情帝国黄站 +强奸处女 +糞 +我的肉棒仍然在滴著精液 +舔舔私处妹妹嗷嗷叫 +侨办 +孙大午 +插的姐姐好爽 +嫩肉 嫩肉 大腿 +淫奸姐姐电影 +法$侖 +…太爽了…大鸡巴 +狂操少妇逼 +嫩穴 肉棒 肉缝 +伱妈 +(桃太郎)ファーストアナル生中出しSpecial 佐藤江梨花 特典 +毛我妳老爸 +tEST +激情淫穴的嫂嫂 +毛机巴 +代挂 +肉棒插 嫩穴 淫穴 +free style +日本激情成人乱伦 +Tora Tora Gold Vol。11 : 松田亜美 +gong fu +狂插淫穴淫水 +89年的鬥爭 +台湾十八电影 +小淫虫电影 +CREATE +外阴 +外??挂 +毛爷爷复活 +本站10004多部激情电影全部免费试看 +富兰克林 +免费淫奸女A片段试看 居然花钱请人教性爱姿势 +操穴 +transvestit +政治 +滥交 +色貓 +李 录 +免费在线观看 免费淫奸女A片段 +肉棒狂插花心深处 +回族人吃猪肉 +淫河 +淫水留入穴中 +機吧 +林祖涵 +水去車仑 +抽插44岁处女妹妹淫叫不断 +毛精液 +列寧 +发@纶 +44xp。com 电影免费 +又肥又大的骚屄儿 +淫色贴图论坛 +侬着卵抛 +色妹妹成人论 +获救 +臺灣是主權國家 +戳那嗎逼 +毛蒋介石 +成人黄色三级网站 +陳宗興 +超meinv优MUGEN EX Vol。 7~浜崎ひめ +操姐姐的穴 +新江湖 +性交无码 +yuckfu +淫語痴女性欲 +毛驶你公 +药物奸淫女高校生A片 +FUCK +瓜批 +嫩逼 淫水 +硬绑绑的阴茎插入阴道 +王若望 +网絡公祭 +zheng tu +1989事件 +玉蒲园淫书淫图射 +三男轮番干一个荡妇 +你是雞 +外??掛 +東京熱最受歡迎長腿美女~藤澤安奈~腿長人又漂亮 +强奸27岁处女全过程/淫妹阴毛小穴 +毛淫娃 +夜夜色大型黄站 +fuck田纪云 +毛手淫 +诱奸 +毛回族人吃猪肉 +好粗大的肉棒 +黑社会 +幼穴贴图 毛穴贴图 穴淫贴图 +含着他的龟头 +法輪 +花蕊 +内测 +黑鮑嬌 +快乐av +冈村秀树 +捅死你 +娘的 +曼德拉 +插的meimei好爽啊 +mo xiang +周贺 +淫荡 空姐 +digimagics +分开两片肥嫩的阴唇 +应招 +藓鲍 +淫奸电影 淫色猎暴淫电影 射雕淫女传 风骚小龙女 meinv淫女图-小龙女淫女俱乐部影 在线淫电影 +列宁 +人民广场 +山西洪洞 +淫浪 +毛龙新民 +海乐神 +planetside +3P炮图 +淫流 +男女激情淫乱穴下载 +摩洛客 +jiejie的小屄 +龙图智库 +da qing di guo +王寶森 +淫浆 +高级淫口手淫口交 +tESt +金瓶梅免费电影院 +毛李山 +淫洞 +bt淫色贴图 +mm穴激情小说 +3P炮圖 +亚洲色 +BITCH +毛三去车仑 +毛奸淫 +姐弟乱轮 yy玛雅激情贴 +干林 +大鸡巴就慢慢的插入 小穴 +混沌 +聖女峰 +超級可愛巨乳妹被狂插得鼻血滿天飛 +揚震 +www。gpchina。com +怎样延迟射精24岁以下禁 +测试员 +18dy桃色 +xing fu hua yuan +穴 +師春生 +fuck太子党 +鸡巴淫沟插B大图 +曾庆红 +插女教师的屁眼 +54xp。com 电影免费 +FALUN +成人电影网 +毛法制办 +马国瑞 +meimei的阴道真紧 +ur靠 +带炼 +淫电影a片 +轮攻 +神风- Kamikaze Premium Vol。 32 : 一色Azusa +韓國三級情色电影 +手淫~少妇自慰喷淫水 +張 萬 年 +艷照门 +幹你妈b +法轮 +(Madonna) 熟女義母 11套 AVI +操神 +民族矛盾 +淫穴影院 +烟草局 +劉曉竹 +免费淫奸女A片段 免费在线观看 +习近平 +姐姐 +的 +嫩穴 +淫液 +操大波波 +干拎娘 +综联数码 +居然花钱请人教性爱姿势(组图) +淫蕩妖艷女醫生 +meimei的小穴……舒服死了…… +情色 信息 +多人性愛 +干机 +汉娃娃 +邵家健 +法踚功 +fuck色情电影 +測试員 +A片 +藤井せいら - ボルテージ X +大参考 +韓 聯 潮 +(无关键词)导航搜索 +一次可看四位美女同床較勁很可愛的女主角 +meimei的小淫穴 +淫色成人网 +毛太监 +淫湿 +少妇穴 +triangleboy +鬼輪姦 +abc abc +乳爆 +他ㄇ的 +色网阴道特写强奸34岁处女全过程 +前任男友 +嫩屄 +成人 激情 性爱 +不注册看艳片 +小穴被大鸡巴插得好疼啊 +轮操 +fuck台湾狗 +系統訊息 +台湾淫色电影 +亚洲 +毛阴小撕大 +賤bi +UR靠 +生鸦片 +操小姐穴 +fuck孙逸仙 +(虎虎虎)风间ゆみ-新婚 +色窝窝 +connard +自由亞洲電臺 +妹妹的阴道好嫩啊 +fuck孙中山 +毛抗日 +谁知道激情网站 +香港成人电影网 +luan +假钞 +毛耶稣 +十八岁meinv护士电影网站 +李 小 朋 +賞圖交流園 +精液射入花心 +國務院 +反黨 +丝袜足交 +fuck特别公告 +肉棒插入肉 +毛妈比 +丁石孙 +淫虫电影 +免费淫电影试看 +李師傅 +夫妻乱交 +广安第二人民医院 +臭鸡 +鹿城色meimei大型黄站 +揭批书 +互淫 +管理人员 +少妇白洁的淫乱生活 +真理組織 +丁石孫 +手记注册日韩5017部激情电影 +插的妈妈好爽 +肉棒插进她的密洞使劲的抽送着 +我和少妇做爱 +guang zhi guo du +狂插美少女穴 +手记注册日韩5019部激情电影 +小穴流出 +免费A片在线 +Gカップカリスマ店員松嶋れいな20連発中出し! +国防部 +裸女乳房阴道丰臀 +制服誘惑 +ke luo si +丁加班 +尼米兹 +fuck天安门事件 +你它馬的 +操逼你老母 +成人激情淫网站 +国共合作 +毛血逼 +wowbank +色网导航 +毛流氓 +免费视讯妹妹 +1989 +金庸群俠傳 +BT激情无码 +迷人阴部护士妹妹也疯狂 +毛新手指导员 +學生愛國者運動 +毛激情小电影 +例假 +干空姐小穴 +成都锦天 +透视软件 +糾察員 +肉棒插入湿湿的肉缝 +插屄好舒服 +悠游网 +那娘錯比 +secretchina +江泽民靠 +錢 其 琛 +和妹妹做爱 +服务器 +性交做爱 +毛李鹏 +狗卵子 +开发 +少女被逼吃精喝精轮奸灌精 +八方链流量交换链 +fuck生鸦片 +發^^掄 +臺灣總統 +下载免费黄色淫乱电影 +双飞+毒龙直到分享了精液 +蒙古独 +媽個比 +餓比 +騷姨媽 +1989 天安門 +毛客户服务人员 +gong fu xiao zi +冯素英 +丝袜写真 +调理劳务系 +激情淫穴小 +测试員 +da tang hao xia +干死 狂插 操 +我周容 +叫鸡 +熟女乱伦网 +免费看激情视频免费成人做爱 +本站10017多部激情电影全部免费试看三天 +风骚欲女 +艷照門 +乱伦(无码)母爱包( 乳母 +柯赐海 +1989 天安门 +周总理 +免费淫奸女A片段试看 +吴学璨 +肉壁紧紧的包著龟头 +哥哥的肉棒好大 +打到中国 +7hero +zhengwunet +拿着鸡巴对准小穴 +幼香閣 +毛烂B +一起玩遊戲網 +高清晰无码内射 +紧窄的洞口只能含进半个龟头 +游戏管理员 +淫乱少妇 +圣淫乱学院 +小穴被阴茎顶住 +捅入妹妹的阴道 +母女双飞 +希望之聲 +淫漿 +整根肉棒被紧箍在幽暗深遽的娇嫩小穴内 +妻子小穴 +超美混血兒(小泽玛利亚出道时的珍藏) +刚度 +luo qi +张健 +烂屄 +卡通meinv淫乱图 +烂屌 +叛黨 +可可精 +淫贱meimei贴图论坛 +锦涛 +姐姐的肥阴唇 +毛发骚 +础 +激情淫文章 +fuck太监 +强奸21岁处女全过程/*妹阴毛小穴 +骚meimei成人导航 +夹得我好舒服 +傅志寰 +朱鎔基 +免费淫奸黄色淫乱电影 +共狗 +老騷貨 +精液射进穴里视频 +日啊 +幼香阁 +西藏事件 +亚/无码 +淫奸护士 +免费成人网站 +创意鹰翔 +厕所性感美女清晰淫穴 +免费观看王小丫做爱 +纪股票市场五卅惨案 +插那嗎逼 +黑鮑嬌 +色窩窩 +美女孩含双棍玩内射 +张德江 +续金瓶梅 +ju shang +18dy大众成人网 +zheng fu +淫妹妹 +被噁心男搞到高潮不停的立花里子 +激情视频聊天室 +成人論壇 +中央政治局 +发~~论 +毛新华内情 +天遊 +pp 点点激情片播放 +毛人民日报 +成人联盟 +meinv偷拍成人小说激情网香港激情图源成人色情论坛脱衣meinv做愛 +制服古典乱伦都市 +插陰 +操成人电影 +傲视 +氯胺酮 +中国和平 +彭德怀 +老师的肉棒好大啊 +fuck天皇 +李師付 +国民党 +国 家 安 全 +少妇房中自淫,和两勇男玩4P,操得直叫爽 操日本淫女穴 +大眾色情成人網 +rx008 +舔 蜜穴好爽 +错那吗B +成人情感裸女裸聊图片 +肉縫分開大腿 +水去車侖 +鸡吧一柱擎天 +阳具在阴道里来回抽插 +巨大的鸡巴戳了进去 +遊戲嚮導 +美幼专区 +賈慶林 +廢墟 +斧頭鐮刀 +退党 +meimei的阴户 +Tokyo Hot n0232 : 真宫梨沙子 傲慢RQ中出责备紊乱呼吸 +淫荡的奸淫 +亚洲激情淫色贴图区 +马万祺 +高速下載! +100ONE VIP MEMBERS +法**纶 +一貫道 +插着淫穴 +漏逼 +隱窩窩 +熟睡中的meimei +毛无界浏览器 +夫妻亂交 +毛金正日 +酒店援交 +張 鋼 +小肉粒 +fuck外—挂 +新义安 +劉傑 +夜总会 +聖堂科技 +司法部 +插阴 +網愛 +下三爛 +客户服务 +免费小淫虫 +http://minganci.tk/ +政治类: +第一代领导 +第二代领导 +第三代领导 +第四代领导 +第五代领导 +第六代领导 +第七代领导 +第1代领导 +第2代领导 +第3代领导 +第4代领导 +第5代领导 +第6代领导 +第7代领导 +一位老同志的谈话 +国办发 +中办发 +腐败中国 +三个呆婊 +你办事我放心 +社会主义灭亡 +打倒中国 +灭亡中国 +亡党亡国 +粉碎四人帮 +激流中国 +特供 +特贡 +特共 +zf大楼 +殃视 +贪污腐败 +强制拆除 +形式主义 +政治风波 +太子党 +上海帮 +北京帮 +清华帮 +红色贵族 +权贵集团 +河蟹社会 +喝血社会 +九风 +9风 +十七大 +十7大 +17da +九学 +9学 +四风 +4风 +双规 +南街村 +最淫官员 +警匪 +官匪 +独夫民贼 +官商勾结 +城管暴力执法 +强制捐款 +毒豺 +一党执政 +一党专制 +一党专政 +专制政权 +宪法法院 +胡平 +苏晓康 +贺卫方 +谭作人 +焦国标 +万润南 +张志新 +辛灝年 +高勤荣 +王炳章 +高智晟 +司马璐 +刘晓竹 +刘宾雁 +魏京生 +寻找林昭的灵魂 +别梦成灰 +谁是新中国 +讨伐中宣部 +异议人士 +民运人士 +启蒙派 +选国家主席 +民一主 +min主 +民竹 +民珠 +民猪 +chinesedemocracy +大赦国际 +国际特赦 +da选 +投公 +公头 +宪政 +平反 +党章 +维权 +昝爱宗 +宪章 +08宪 +08xz +觉醒的中国公民日渐清楚地认识到 +抿主 +民主 +敏主 +人拳 +人木又 +人quan +renquan +中国人权 +中国的人权 +中国新民党 +群体事件 +群体性事件 +上中央 +去中央 +讨说法 +请愿 +请命 +公开信 +联名上书 +万人大签名 +万人骚动 +截访 +上访 +shangfang +信访 +访民 +集合 +集会 +组织集体 +静坐 +静zuo +jing坐 +示威 +示wei +游行 +you行 +油行 +游xing +youxing +官逼民反 +反party +反共 +抗议 +亢议 +抵制 +低制 +底制 +di制 +抵zhi +dizhi +boycott +血书 +焚烧中国国旗 +baoluan +流血冲突 +出现暴动 +发生暴动 +引起暴动 +baodong +灭共 +杀毙 +罢工 +霸工 +罢考 +罢餐 +霸餐 +罢参 +罢饭 +罢吃 +罢食 +罢课 +罢ke +霸课 +ba课 +罢教 +罢学 +罢运 +网特 +网评员 +网络评论员 +五毛党 +五毛们 +5毛党 +戒严 +jieyan +jie严 +戒yan +8的平方事件 +知道64 +八九年 +贰拾年 +2o年 +20和谐年 +贰拾周年 +六四 +六河蟹四 +六百度四 +六和谐四 +陆四 +陆肆 +198964 +5月35 +89年春夏之交 +64惨案 +64时期 +64运动 +4事件 +四事件 +北京风波 +学潮 +学chao +xuechao +学百度潮 +门安天 +天按门 +坦克压大学生 +民主女神 +历史的伤口 +高自联 +北高联 +维多利亚公园 +thegateofheavenlypeace +bloodisonthesquare +为了忘却的纪念 +血洗京城 +四二六社论 +王丹 +柴玲 +沈彤 +封从德 +王超华 +王维林 +吾尔开希 +吾尔开西 +侯德健 +阎明复 +方励之 +蒋捷连 +丁子霖 +辛灏年 +蒋彦永 +严家其 +陈一咨 +中华局域网 +党的喉舌 +互联网审查 +当局严密封锁 +新闻封锁 +封锁消息 +爱国者同盟 +关闭所有论坛 +网络封锁 +金盾工程 +gfw +无界浏览 +无界网络 +自由门 +何清涟 +中国的陷阱 +汪兆钧 +记者无疆界 +境外媒体 +维基百科 +纽约时报 +bbc中文网 +华盛顿邮报 +世界日报 +东森新闻网 +东森电视 +基督教科学箴言报 +星岛日报 +亚洲周刊 +泰晤士报 +美联社 +中央社 +雅虎香港 +wikipedia +youtube +googleblogger +美国之音 +美国广播公司 +英国金融时报 +自由亚洲 +中央日报 +自由时报 +中国时报 +反分裂 +威胁论 +左翼联盟 +钓鱼岛 +保钓组织 +主权 +弓单 +火乍 +木仓 +石肖 +核蛋 +步qiang +bao炸 +爆zha +baozha +zha药 +zha弹 +炸dan +炸yao +zhadan +zhayao +hmtd +三硝基甲苯 +六氟化铀 +炸药配方 +弹药配方 +炸弹配方 +皮箱炸弹 +火药配方 +人体炸弹 +人肉炸弹 +解放军 +兵力部署 +军转 +军事社 +8341部队 +第21集团军 +七大军区 +7大军区 +北京军区 +沈阳军区 +济南军区 +成都军区 +广州军区 +南京军区 +兰州军区 +颜色革命 +规模冲突 +塔利班 +基地组织 +恐怖分子 +恐怖份子 +三股势力 +印尼屠华 +印尼事件 +蒋公纪念歌 +马英九 +mayingjiu +李天羽 +苏贞昌 +林文漪 +陈水扁 +陈s扁 +陈随便 +阿扁 +a扁 +告全国同胞书 +台百度湾 +台完 +台wan +taiwan +台弯 +湾台 +台湾国 +台湾共和国 +台军 +台独 +台毒 +台du +taidu +twdl +一中一台 +打台湾 +两岸关系 +两岸战争 +攻占台湾 +支持台湾 +进攻台湾 +占领台湾 +统一台湾 +收复台湾 +登陆台湾 +解放台湾 +解放tw +解决台湾 +光复民国 +台湾独立 +台湾问题 +台海问题 +台海危机 +台海统一 +台海大战 +台海战争 +台海局势 +入联 +入耳关 +中华联邦 +国民党 +x民党 +民进党 +青天白日 +闹独立 +duli +fenlie +日本万岁 +小泽一郎 +劣等民族 +汉人 +汉维 +维汉 +维吾 +吾尔 +热比娅 +伊力哈木 +疆独 +东突厥斯坦解放组织 +东突解放组织 +蒙古分裂分子 +列确 +阿旺晋美 +藏人 +臧人 +zang人 +藏民 +藏m +达赖 +赖达 +dalai +哒赖 +dl喇嘛 +丹增嘉措 +打砸抢 +西独 +藏独 +葬独 +臧独 +藏毒 +藏du +zangdu +支持zd +藏暴乱 +藏青会 +雪山狮子旗 +拉萨 +啦萨 +啦沙 +啦撒 +拉sa +lasa +la萨 +西藏 +藏西 +xizang +xi藏 +x藏 +西z +tibet +希葬 +希藏 +硒藏 +稀藏 +西脏 +西奘 +西葬 +西臧 +援藏 +bjork +王千源 +安拉 +回教 +回族 +回回 +回民 +穆斯林 +穆罕穆德 +穆罕默德 +默罕默德 +伊斯兰 +圣战组织 +清真 +清zhen +qingzhen +真主 +阿拉伯 +高丽棒子 +韩国狗 +满洲第三帝国 +满狗 +鞑子 + +领导名人类: +胡的接班人 +钦定接班人 +习近平 +平近习 +xjp +习太子 +习明泽 +老习 +温家宝 +温加宝 +温x +温jia宝 +温宝宝 +温加饱 +温加保 +张培莉 +温云松 +温如春 +温jb +胡温 +胡x +胡jt +胡boss +胡总 +胡王八 +hujintao +胡jintao +胡j涛 +胡惊涛 +胡景涛 +胡紧掏 +湖紧掏 +胡紧套 +锦涛 +hjt +胡派 +胡主席 +刘永清 +胡海峰 +胡海清 +江泽民 +民泽江 +江胡 +江哥 +江主席 +江书记 +江浙闽 +江沢民 +江浙民 +择民 +则民 +茳泽民 +zemin +ze民 +老江 +老j +江core +江x +江派 +江zm +jzm +江戏子 +江蛤蟆 +江某某 +江贼 +江猪 +江氏集团 +江绵恒 +江绵康 +王冶坪 +江泽慧 +邓小平 +平小邓 +xiao平 +邓xp +邓晓平 +邓朴方 +邓榕 +邓质方 +毛泽东 +猫泽东 +猫则东 +chairmanmao +猫贼洞 +毛zd +毛zx +z东 +ze东 +泽d +zedong +毛太祖 +毛相 +主席画像 +改革历程 +朱镕基 +朱容基 +朱镕鸡 +朱容鸡 +朱云来 +李鹏 +李peng +里鹏 +李月月鸟 +李小鹏 +李小琳 +华主席 +华国 +国锋 +国峰 +锋同志 +白春礼 +薄熙来 +薄一波 +蔡赴朝 +蔡武 +曹刚川 +常万全 +陈炳德 +陈德铭 +陈建国 +陈良宇 +陈绍基 +陈同海 +陈至立 +戴秉国 +丁一平 +董建华 +杜德印 +杜世成 +傅锐 +郭伯雄 +郭金龙 +贺国强 +胡春华 +耀邦 +华建敏 +黄华华 +黄丽满 +黄兴国 +回良玉 +贾庆林 +贾廷安 +靖志远 +李长春 +李春城 +李建国 +李克强 +李岚清 +李沛瑶 +李荣融 +李瑞环 +李铁映 +李先念 +李学举 +李源潮 +栗智 +梁光烈 +廖锡龙 +林树森 +林炎志 +林左鸣 +令计划 +柳斌杰 +刘奇葆 +刘少奇 +刘延东 +刘云山 +刘志军 +龙新民 +路甬祥 +罗箭 +吕祖善 +马飚 +马恺 +孟建柱 +欧广源 +强卫 +沈跃跃 +宋平顺 +粟戎生 +苏树林 +孙家正 +铁凝 +屠光绍 +王东明 +汪东兴 +王鸿举 +王沪宁 +王乐泉 +王洛林 +王岐山 +王胜俊 +王太华 +王学军 +王兆国 +王振华 +吴邦国 +吴定富 +吴官正 +无官正 +吴胜利 +吴仪 +奚国华 +习仲勋 +徐才厚 +许其亮 +徐绍史 +杨洁篪 +叶剑英 +由喜贵 +于幼军 +俞正声 +袁纯清 +曾培炎 +曾庆红 +曾宪梓 +曾荫权 +张德江 +张定发 +张高丽 +张立昌 +张荣坤 +张志国 +赵洪祝 +紫阳 +周生贤 +周永康 +朱海仑 +政治局常委 +中纪委 +主席像 +总书记 +中南海 +大陆当局 +中国当局 +北京当局 +共产党 +党产共 +gcd +共贪党 +gongchandang +阿共 +共一产一党 +产党共 +公产党 +工产党 +共c党 +共x党 +共铲 +供产 +共惨 +供铲党 +供铲谠 +供铲裆 +共残党 +共残主义 +共产主义的幽灵 +拱铲 +老共 +中共 +中珙 +中gong +gc党 +贡挡 +gong党 +g产 +狗产蛋 +共残裆 +恶党 +邪党 +共产专制 +共产王朝 +裆中央 +土共 +土g +共狗 +g匪 +共匪 +仇共 +communistparty +政府 +症腐 +政腐 +政付 +正府 +政俯 +政一府 +政百度府 +政f +zhengfu +政zhi +挡中央 +档中央 +中央领导 +中国zf +中央zf +国wu院 +中华帝国 +gong和 +大陆官方 +北京政权 + +迷信、邪教类: +福音会 +中国教徒 +统一教 +观音法门 +清海无上师 +盘古 +李洪志 +志洪李 +李宏志 +轮功 +法轮 +轮法功 +三去车仑 +氵去车仑 +发论工 +法x功 +法o功 +法0功 +法一轮一功 +轮子功 +车仑工力 +法lun +fa轮 +法lg +flg +fl功 +falungong +大法弟子 +大纪元 +dajiyuan +明慧网 +明慧周报 +正见网 +新唐人 +伪火 +退党 +tuidang +退dang +超越红墙 +自fen +真善忍 +九评 +9评 +9ping +九ping +jiuping +藏字石 +集体自杀 +自sha +zi杀 +suicide +titor +逢8必灾 +逢八必灾 +逢9必乱 +逢九必乱 +朱瑟里诺 +根达亚文明 +诺查丹玛斯 +人类灭亡进程表 +按照马雅历法 +推背图 +推bei图 +济世灵文 +诸世纪 + +色情类: +爱女人 +爱液 +按摩棒 +拔出来 +爆草 +包二奶 +暴干 +暴奸 +暴乳 +爆乳 +暴淫 +屄 +被操 +被插 +被干 +逼奸 +仓井空 +插暴 +操逼 +操黑 +操烂 +肏你 +肏死 +操死 +操我 +厕奴 +插比 +插b +插逼 +插进 +插你 +插我 +插阴 +潮吹 +潮喷 +成人电影 +成人论坛 +成人色情 +成人网站 +成人文学 +成人小说 +艳情小说 +成人游戏 +吃精 +赤裸 +抽插 +扌由插 +抽一插 +春药 +大波 +大力抽送 +大乳 +荡妇 +荡女 +盗撮 +多人轮 +发浪 +放尿 +肥逼 +粉穴 +封面女郎 +风月大陆 +干死你 +干穴 +肛交 +肛门 +龟头 +裹本 +国产av +好嫩 +豪乳 +黑逼 +后庭 +后穴 +虎骑 +花花公子 +换妻俱乐部 +黄片 +几吧 +鸡吧 +鸡巴 +鸡奸 +寂寞男 +寂寞女 +妓女 +激情 +集体淫 +奸情 +叫床 +脚交 +金鳞岂是池中物 +金麟岂是池中物 +精液 +就去日 +巨屌 +菊花洞 +菊门 +巨奶 +巨乳 +菊穴 +开苞 +口爆 +口活 +口交 +口射 +口淫 +裤袜 +狂操 +狂插 +浪逼 +浪妇 +浪叫 +浪女 +狼友 +聊性 +流淫 +铃木麻 +凌辱 +漏乳 +露b +乱交 +乱伦 +轮暴 +轮操 +轮奸 +裸陪 +买春 +美逼 +美少妇 +美乳 +美腿 +美穴 +美幼 +秘唇 +迷奸 +密穴 +蜜穴 +蜜液 +摸奶 +摸胸 +母奸 +奈美 +奶子 +男奴 +内射 +嫩逼 +嫩女 +嫩穴 +捏弄 +女优 +炮友 +砲友 +喷精 +屁眼 +品香堂 +前凸后翘 +强jian +强暴 +强奸处女 +情趣用品 +情色 +拳交 +全裸 +群交 +惹火身材 +人妻 +人兽 +日逼 +日烂 +肉棒 +肉逼 +肉唇 +肉洞 +肉缝 +肉棍 +肉茎 +肉具 +揉乳 +肉穴 +肉欲 +乳爆 +乳房 +乳沟 +乳交 +乳头 +三级片 +骚逼 +骚比 +骚女 +骚水 +骚穴 +色逼 +色界 +色猫 +色盟 +色情网站 +色区 +色色 +色诱 +色欲 +色b +少年阿宾 +少修正 +射爽 +射颜 +食精 +释欲 +兽奸 +兽交 +手淫 +兽欲 +熟妇 +熟母 +熟女 +爽片 +爽死我了 +双臀 +死逼 +丝袜 +丝诱 +松岛枫 +酥痒 +汤加丽 +套弄 +体奸 +体位 +舔脚 +舔阴 +调教 +偷欢 +偷拍 +推油 +脱内裤 +文做 +我就色 +无码 +舞女 +无修正 +吸精 +夏川纯 +相奸 +小逼 +校鸡 +小穴 +小xue +写真 +性感妖娆 +性感诱惑 +性虎 +性饥渴 +性技巧 +性交 +性奴 +性虐 +性息 +性欲 +胸推 +穴口 +学生妹 +穴图 +亚情 +颜射 +阳具 +杨思敏 +要射了 +夜勤病栋 +一本道 +一夜欢 +一夜情 +一ye情 +阴部 +淫虫 +阴唇 +淫荡 +阴道 +淫电影 +阴阜 +淫妇 +淫河 +阴核 +阴户 +淫贱 +淫叫 +淫教师 +阴茎 +阴精 +淫浪 +淫媚 +淫糜 +淫魔 +淫母 +淫女 +淫虐 +淫妻 +淫情 +淫色 +淫声浪语 +淫兽学园 +淫书 +淫术炼金士 +淫水 +淫娃 +淫威 +淫亵 +淫样 +淫液 +淫照 +阴b +应召 +幼交 +幼男 +幼女 +欲火 +欲女 +玉女心经 +玉蒲团 +玉乳 +欲仙欲死 +玉穴 +援交 +原味内衣 +援助交际 +张筱雨 +招鸡 +招妓 +中年美妇 +抓胸 +自拍 +自慰 +作爱 +18禁 +99bb +a4u +a4y +adult +amateur +anal +a片 +fuck +gay片 +g点 +g片 +hardcore +h动画 +h动漫 +incest +porn +secom +sexinsex +sm女王 +xiao77 +xing伴侣 +tokyohot +yin荡 + +时事类: +汉芯造假 +杨树宽 +中印边界谈判结果 +喂奶门 +摸nai门 +酒瓶门 +脱裤门 +75事件 +乌鲁木齐 +新疆骚乱 +针刺 +打针 +食堂涨价 +饭菜涨价 +h1n1 +瘟疫爆发 +yangjia +y佳 +yang佳 +杨佳 +杨j +袭警 +杀警 +武侯祠 +川b26931 +贺立旗 +周正毅 +px项目 +骂四川 +家l福 +家le福 +加了服 +麦当劳被砸 +豆腐渣 +这不是天灾 +龙小霞 +震其国土 +yuce +提前预测 +地震预测 +隐瞒地震 +李四光预测 +蟾蜍迁徙 +地震来得更猛烈 +八级地震毫无预报 +踩踏事故 +聂树斌 +万里大造林 +陈相贵 +张丹红 +尹方明 +李树菲 +王奉友 +零八奥运艰 +惨奥 +奥晕 +凹晕 +懊运 +懊孕 +奥孕 +奥你妈的运 +反奥 +628事件 +weng安 +wengan +翁安 +瓮安事件 +化工厂爆炸 +讨回工资 + +广告、非法信息类: +专业代理 +帮忙点一下 +帮忙点下 +请点击进入 +详情请进入 +私人侦探 +私家侦探 +针孔摄象 +调查婚外情 +信用卡提现 +无抵押贷款 +广告代理 +原音铃声 +借腹生子 +找个妈妈 +找个爸爸 +代孕妈妈 +代生孩子 +代开发票 +腾讯客服电话 +销售热线 +免费订购热线 +低价出售 +款到发货 +回复可见 +连锁加盟 +加盟连锁 +免费二级域名 +免费使用 +免费索取 +蚁力神 +婴儿汤 +售肾 +刻章办 +买小车 +套牌车 +玛雅网 +电脑传讯 +视频来源 +下载速度 +高清在线 +全集在线 +在线播放 +txt下载 +六位qq +6位qq +位的qq +个qb +送qb +用刀横向切腹 +完全自杀手册 +四海帮 +足球投注 +地下钱庄 +中国复兴党 +阿波罗网 +曾道人 +六合彩 +改卷内幕 +替考试 +隐形耳机 +出售答案 +考中答案 +答an +da案 +资金周转 +救市 +股市圈钱 +崩盘 +资金短缺 +证监会 +质押贷款 +小额贷款 +周小川 +刘明康 +尚福林 +孔丹 + +药物毒品类: +安眠酮 +代药物毒品类:血浆 +普萘洛尔 +呋塞米 +西布曲明 +testosterone +胰岛素样生长因子 +促红细胞生成素 +地西泮 +尼可刹米 +甲睾酮 +adrenaline +erythropoietin +地奈德 +莫达非尼 +氯噻嗪 +苯巴比妥 +促性腺激素 +泼尼松 +麻黄草 +雄烯二醇 +地塞米松 +tamoxifen +strychnine +androst +新型毒品 +杜冷丁 +兴奋剂 +mdma +海洛因 +海luo因 +heroin +diamorphine +diacetylmorphine +鸦片 +阿芙蓉 +咖啡因 +cocain +三唑仑 +美沙酮 +麻古 +k粉 +凯他敏 +ketamine +冰毒 +苯丙胺 +cannabis +大麻 +爱他死 +氯胺酮 +benzodiazepines +甲基安非他明 +安非他命 +吗啡 +morphine +摇头丸 +迷药 +乖乖粉 +narcotic +麻醉药 +精神药品 + +其它: +穴海 +协警 +纳米比亚 +专业调查 +有华龙 +jq的来 +电信路 +第一夫人 +党鞭 +黄巨 +荡尽天下 +家元自称玉皇大帝 +主席李世民 +何祚庥 +刘刚 +不要沉默 +后勤集团 +食堂涨价 +发国难财 +浪漫邂逅 +红满堂 +张小洋 +炸学校 +子宫 +叫晶晶的女孩 +回派 +社会黑暗 +国之母 +国母 +国姆 +东方微点 +震惊全球 +nowto +chengdu +徐明 +六月飞雪 +暴力虐待 +暴力袭击 +天府广场 +粮荒 +洗脑班 +复制地址到地址栏 + +骂人、讽刺类: +李愚蠢 +中国猪 +台湾猪 +进化不完全的生命体 +震死他们 +贱人 +装b +大sb +傻逼 +傻b +煞逼 +煞笔 +刹笔 +傻比 +沙比 +欠干 +婊子养的 +我日你 +我操 +我草 +卧艹 +卧槽 +爆你菊 +艹你 +cao你 +你他妈 +真他妈 +别他吗 +草你吗 +草泥马 +草你丫 +操你妈 +擦你妈 +操你娘 +操他妈 +操你妈 +日你妈 +干你妈 +干你娘 +娘西皮 +狗操 +狗草 +狗杂种 +狗日的 +操你祖宗 +操你全家 +操你大爷 +妈逼 +你麻痹 +麻痹的 +妈了个逼 +马勒 +狗娘养 +贱比 +贱b +下贱 +死全家 +全家死光 +全家不得好死 +全家死绝 +白痴 +无耻 +sb +杀b +你吗b +你妈的 +婊子 +贱货 +人渣 +混蛋 +媚外 +和弦 +兼职 +限量 +铃声 +性伴侣 +男公关 +火辣 +精子 +射精 +诱奸 +强奸 +做爱 +性爱 +发生关系 +按摩 +快感 +处男 +猛男 +少妇 +屌 +屁股 +下体 +a片 +内裤 +浑圆 +咪咪 +发情 +刺激 +白嫩 +粉嫩 +兽性 +风骚 +呻吟 +sm +阉割 +高潮 +裸露 +不穿 +一丝不挂 +脱光 +干你 +干死 +我干 +中日没有不友好的 +木牛流马的污染比汽车飞机大 +他们嫌我挡了城市的道路 +当官靠后台 +警察我们是为人民服务的 +中石化说亏损 +做人不能太cctv了 +领导干部吃王八 +工商税务两条狼 +公检法是流氓 +公安把秩序搞乱 +剖腹一刀五千几 +读不起选个学校三万起 +父母下岗儿下地 +裙中性运动 + +其它次要的适合于后台审核的敏感词: +自制 +制造 +制作 +收购 +求购 +电话 +手机 +销售 +联系 +qq +出售 +买 +卖 +匕首 +管制刀具 +弹药 +bb弹 +违禁品 +军用品 +电棍 +手枪 +机枪 +步枪 +气枪 +电狗 +手狗 +枪模 +模型枪 +仿真枪 +狙击枪 +信号枪 +麻醉枪 +来福枪 +来复枪 +冲锋枪 +散弹枪 +卡宾枪 +枪支 +枪械 +炸药 +硝铵 +火药 +燃烧瓶 +可燃物 +爆炸物 +炸弹 +雷管 +原子弹 +燃烧弹 +tnt +自制 +制造 +制作 +收购 +求购 +电话 +手机 +销售 +联系 +qq +出售 +买 +卖 +sb +sm +发票 +按摩服务 +他妈的 +乱伦 +幼交 +援交 +上門服務 +五连发 +文爱 +文聊 +认干爹 +自由中国 +自由亚洲 +自考本科学历 +自考毕业证 +皇冠平台 +皇冠代理 +美女诱惑 +炸药 +炮友 +洗钱 +窃听器 +捐肾 +真人视频 +真人博彩 +业主名单 +娱乐城 +身份证 +学历证 +办证刻章 +作弊器 +定位器 +上分器 +干扰器 +發票 +破解器 +预测器 +警察证 +高仿证 +军人证 +居民户口本 +士兵证 +假言正 +英语等级证 +资质证书 +会计师证 +毕业证书 +四六级证书 +军官证样本 +假军官证 +高仿身份证 +假身份证 +假户口本 +高仿户口本 +假结婚证 +高仿学位证 +假文凭 +毕业文凭 +国外文凭 +假证件 +学历证书 +军车套牌 +假车牌 +护照 +车辆牌照 +公文 +行驶证 +国安证 +驾照 +工作证 +证件 +言正 +记者证 +驾驶证 +户口本 +军官证 +警官证 +台独 +藏独 +华南教会 +18禁 +38式 +54狗 +54式 +54手 +54手枪 +56式 +63式 +64狗 +64枪 +64式 +64手 +64手枪 +762毫米 +77枪 +77式 +77手 +81式 +92枪 +92式 +92手 +92手枪 +aaaa级 +Asami +Asano +AV棒 +AV女优 +AV种子 +A片 +BB弹 +BB枪 +bt下载 +b毛 +CP99 +CS狗 +cz100枪 +ed2k +fapiao +fa票 +ghb水 +GHB液 +GLOCK +G水 +happy水 +high粉 +high水 +Kanou +king粉 +KK情色交友 +Kurumi +K粉 +m9长刺 +mp654k +P2P +qvod +SexInSex +TNT +txt全集 +txt下载 +vip名单 +x卧底 +阿普唑仑 +艾司唑仑 +安非他命 +安來美久 +安眠酮 +安纳咖 +安钠咖 +胺 +胺吗啡 +巴雷特 +掰屄 +白冰 +白粉 +白洁 +白莲教 +白刃 +白丝 +白牙签 +白牙簽 +百家乐 +百性阁 +办驾驶 +办假 +办理%证 +辦証 +包吹 +包射 +包爽 +包脱 +包夜 +爆菊 +爆器 +爆药 +爆炸物 +北京小姐 +苯丙胺类 +苯环利定 +苯基丙酮 +苯三酚 +苯乙酸 +匕首 +苄 +冰毒 +冰读 +冰古 +冰鉆石 +冰牙签 +冰油 +冰砖 +冰磚 +冰钻 +丙酮 +波推 +伯莱塔 +勃朗宁 +博彩 +薄熙来 +捕狗 +不雅照 +步狗 +步枪 +步槍 +采花网 +苍蝇粉 +苍蝇水 +藏刀 +操美女 +草榴 +插穴 +茶魚 +长刺 +长刀 +长治筋 +朝鲜版人民币 +潮吹 +车船税 +成品冰 +成人电影 +诚信名单 +痴汉 +充气娃娃 +冲锋枪 +冲那翼 +抽插 +出货 +出售 +出台 +储蓄卡 +床照 +吹箫 +春药 +纯冰 +纯古 +刺刀 +丛林刀 +醋酸酐 +催泪 +催眠喷雾剂 +催眠水 +催眠药 +催情 +催情粉 +催情口香糖 +催情水 +催情药 +催情药水 +催情液 +打倒共产党 +打牌药 +打手 +大冰砖 +大冰磚 +大尺度 +大粗鸡巴 +大屌 +大法 +大和扶子 +大黑鹰 +大鸡巴 +大堀香奈 +大麻 +大马士革 +大奶 +大中华 +代办 +代开 +代開 +代考 +代制 +代做 +甙 +单管 +弹簧刀 +刀具 +导弹 +导航 +等级证书 +邓小平 +地高辛 +地税 +地西泮 +点棍 +电棒 +电狗 +电购 +电棍 +电击 +电击棒 +电击器 +电警棍 +电驴 +电视棒 +电子狗 +丁硫环磷 +丁香 +丁香岛 +丁字裤 +定额 +定金 +訂購鹽酸羥亞胺 +东京热 +动漫 +毒龙钻 +毒品 +毒药 +赌博 +赌博粉 +赌博药 +赌场 +赌具 +杜冷丁 +盾牌 +多P +娥眉气枪 +锇 +二级片 +二踢脚 +二硝基苯酚 +二硝基间苯二酚 +二亚甲基双氧安非他明 +发piao +发飘 +发嘌 +法轮 +法人 +番木鳖碱 +钒 +反党 +反对两会 +反共 +犯人 +防暴枪 +防爆 +防弹 +防身武器 +房产证 +房租 +仿真 +仿真狗 +仿真枪 +仿真人民币 +肺脏 +粉笔炸弹 +粉穴 +风吹凉 +风间遥 +风枪 +疯插 +砜 +夫妻聚会 +夫妻玩 +玞槍雷明頳 +氟 +氟硝安定 +涪陵楼凤 +负面信息 +复仇 +复制器 +改号 +干扰王 +肝肾 +肝源 +肝臟 +酐 +肛交 +肛栓 +钢叉 +钢针狗 +钢珠 +钢珠狗 +钢珠枪 +高偿 +高仿 +高仿枪 +高官 +高管 +高价收 +高氯酸铵 +高清 +高压%枪 +高压狗 +高压击棒 +戈博 +格斗 +镉 +工字皮碗 +弓nu +弓弩 +弓月杏里 +公务员 +公寓 +供应 +供应敌 +供應 +供應K粉 +供應冰毒 +汞 +共党 +狗粮 +枸橼 +古柯 +古柯碱 +古柯叶 +股民 +股票 +骨髓 +蛊毒 +故山爱表 +刮刀 +胍 +乖乖水 +乖乖水配方 +乖乖药 +管猎 +掼蛋 +灌肠 +灌水 +光气 +硅烷 +国税 +果子冰 +过机 +海乐神 +海洛因 +酣乐欣 +號碼 +核弹 +黑车 +黑狗 +黑市 +黑丝 +黑索金 +后庭 +後藤麻美 +胡椒基甲基 +胡椒基甲酮 +胡椒醛 +胡景涛 +胡桃泽马里奈 +蝴蝶刀 +虎頭 +虎牙 +花和尚 +化骨水 +化学冰 +化学冰牙签 +换妻 +皇冠 +黃牙簽 +黄白牙签 +黄冰 +黄冰糖 +黄绿牙签 +黄片 +黄曲霉素 +黄体酮 +黄图 +黄牙签 +磺 +挥发型迷药 +惠美梨 +毁容 +昏迷药 +昏睡药 +活体 +火狗 +火药 +机打 +鸡巴 +鸡奸 +激光枪 +激情 +极品 +极品性感尤物 +集束 +妓院 +加冰 +加勒比 +夹阴 +甲基 +甲基安非他明 +甲基苯胺 +甲基苯丙 +甲基苯丙胺 +甲基苯丙酮 +甲基可可碱 +甲基麻黄素 +甲卡西酮 +甲硝西泮 +假bi +假币 +假幣 +假钞 +假发票 +假护照 +假酒 +假冒 +假牌 +假钱 +假学历 +假烟 +假硬币 +假证 +间苯三酚 +肩迷药 +肩章 +兼职 +监听 +监狱 +間苯三酚 +简历 +碱 +建筑 +江泽民 +蒋大彬 +角膜 +叫床 +解放軍 +解码 +解码器 +解码仪 +借记卡 +金弓 +金卡 +禁播 +腈 +精液 +警灯 +警服 +警棍 +警号 +警花 +警徽 +警衔 +警用 +镜丽子 +狙击 +狙击枪 +巨乳 +捐肝 +捐献 +军车进京 +军刺 +军刀 +军狗 +军品 +军刃 +军用 +军用品 +军用枪 +咖啡碱 +咖啡因 +卡拉 +开奖 +开票 +开刃 +开山刀 +开锁 +开他敏 +开心水 +砍刀 +尻 +考号 +柯碱 +可待因 +可卡因 +可可精 +可塑 +刻章 +客户 +空中飞人 +口爆 +口服迷昏药 +口服型昏迷药 +口交 +口径 +口徑 +快播 +快播色情片 +快开 +兰博 +拦截器 +浪穴 +劳务 +老板 +老虎机 +雷管 +雷明登猎狗 +雷明顿 +雷鸣登 +黎城面 +李克强 +李鹏 +力斯曼 +联通 +恋之欲室 +两会 +猎刀 +猎狗 +猎箭 +猎枪 +獵槍 +磷 +硫酸铊 +六合 +六合彩 +六级证 +六四 +龙虎机 +楼凤 +楼盘 +露点 +露乳 +庐江 +芦名未帆 +铝热 +绿冰 +氯胺酮 +氯氮卓 +氯仿 +乱交 +伦理 +轮盘 +裸聊 +裸女 +裸舞 +落榜 +麻狗 +麻古 +麻古冰 +麻古果子 +麻古配方 +麻谷 +麻果 +麻黃 +麻黃素 +麻黄 +麻黄碱 +麻黄素 +麻烟 +麻醉 +麻醉剂 +麻醉枪 +吗啡 +买肝 +买枪 +买肾 +買賣 +麦角胺麦角酸 +麦角醇 +麦角酸 +麦角酸提炼技术 +麦角乙二胺 +卖肝 +卖枪 +卖肾 +麥角 +麥角酸 +賣合成K粉 +慢性毒药 +毛片 +毛瑟 +毛泽东 +莓牛奶 +美眉 +美沙酮 +美痧酮 +美堂丽子 +美臀 +镁粉 +门肾革 +蒙汗 +蒙汗药 +蒙汗药配方 +迷粉 +迷幻 +迷幻药 +迷昏 +迷昏药 +迷魂 +迷奸 +迷奸药 +迷情 +迷情药 +迷香 +迷烟 +迷药 +迷晕 +醚 +蜜蜂采水 +蜜桃成熟时 +缅古 +缅果 +喵喵药 +名刀 +名录 +明慧网 +模具 +模型枪 +莫洛托夫 +内射 +钠 +奶油冰 +男公关 +嫩逼 +嫩穴 +尼美西泮 +尼蒙尔克素 +镍 +农夫导航 +农夫电影 +驽 +驽弓 +弩 +弩机 +弩箭 +弩枪 +女优 +拍肩迷药 +哌啶 +哌嗪 +哌替啶 +潘金莲 +炮图 +跑事 +陪聊 +陪睡 +喷射 +硼 +批发 +砒 +票据 +品色 +品色堂 +屏蔽 +屏蔽器 +破处 +破氧 +破氧毒素 +蒲友 +期货 +起爆器 +气动 +气狗 +气木 +气枪 +气枪弹 +汽动 +汽狗 +汽枪 +汽油弹 +氣槍 +器官 +铅弹 +签证 +前阴 +鉆石冰 +潜伏者 +潜水刀 +枪刺 +枪猎 +枪模 +枪手 +枪支 +槍 +槍袋 +槍琯 +槍管 +槍箱 +强奸 +强奸水 +强奸丸 +强开 +羟 +羟亚胺 +羥亞胺 +橋本杏子 +窃听 +青蒿素 +青楼十二房 +氢弹 +氢化可的松 +清债 +清帐 +情蛊 +情色 +氰 +氰化 +氰化钙 +氰化汞 +氰化钾 +氰化钠 +氰化物 +求生刀 +巯 +曲马多 +去氧 +全钢刀 +全集 +全裸 +全套服务 +醛 +群p +群交 +燃烧 +燃烧弹 +燃烧剂 +燃烧瓶 +热武器 +人民币 +人皮 +人兽 +人体器官 +人妖 +仁科百华 +仁科百華 +任意号码 +日本avbt下载 +日韩无码 +日韩有码 +揉奶 +肉棒 +肉洞 +肉棍 +肉蒲团 +肉穴 +如月可怜 +乳交 +赛马会 +赛馬会 +三级片 +三箭 +三箭氣 +三棱 +三棱刀 +三利达 +三连发 +三氯甲烷 +三陪小姐 +三唑 +三唑仑 +三唑侖 +散弹枪 +桑拿 +骚B +骚屄 +骚逼 +骚冰 +骚妹 +骚女 +骚穴 +扫描枪 +色狗 +色情 +色情片 +色情五月天 +色色 +色图 +色淫 +色友 +色中色 +杀人 +杀手 +杀它 +沙菲片 +沙林 +山心恨 +山猪 +删贴 +商务 +上门 +上门按摩 +上门服务 +少妇 +少妇白洁 +舌尖漫游 +射钉 +射钉枪 +射鱼弩 +身份信息 +身份證 +砷 +深喉 +深圳小姐 +神仙水 +神仙糖 +肾源 +肾臟 +胂 +腎源 +生源 +失身粉 +失身水 +失忆粉 +失忆水 +失忆药 +十八大 +十八小妹自拍網 +十字锁 +视频聊天 +视频下载 +视频秀 +视讯 +收藏品 +收购 +收购肝 +收购肾 +手島優 +手弓弩 +手狗 +手机变号 +手铐 +手拉AWP +手拉鸡 +手榴弹 +手弩 +手枪 +兽交 +兽兽 +售冰毒 +售假币 +售假钞 +售假护照 +售假酒 +售假钱 +售假学历 +售假烟 +售假硬币 +售假证 +售考前答案 +售考试答案 +售枪 +售套牌车 +售走私车 +书记 +熟女 +熟女镇 +数据库 +刷Q币 +甩刀 +甩棍 +双飞 +双管 +爽图 +水晶冰 +水军 +税据 +税票 +税票代 +丝足 +私服 +私家侦探 +私拍 +私售 +四号白粉 +四季彩香 +四六级 +四氢吡喃酮 +素人 +速水恋 +铊 +铊盐 +羰 +套牌 +套现 +特警 +特码 +特码网 +特殊服务 +替考 +天安门事件 +舔阴 +跳刀 +貼圖 +听话水 +听话药 +听话药水 +通信录 +通讯录 +酮 +筒见友 +偷拍 +头盔 +投注 +透视 +透视眼镜 +秃鹰 +秃鹰气枪 +土仿狗 +推油 +臀推 +托福 +脱氧麻黄素 +脱衣 +弯刀冷钢 +烷 +晚乙子爱 +万能钥匙 +王民生 +网络投注 +伪币 +伪钞 +卫星天线 +温家宝 +温切斯特 +文凭 +我爱我色 +无码 +无政府 +吴邦国 +無碼 +午夜 +武力 +武器 +武士 +武士刀 +戊基 +西班牙苍蝇粉 +西班牙苍蝇水 +烯 +锡纸 +习近平 +酰 +相思红娘 +香烟型昏迷药 +香烟型迷 +香烟型迷药 +消音器 +逍遥视频 +逍遥游论坛 +硝胺 +硝化 +硝化甘油 +硝化纤 +硝甲西泮 +硝酸 +硝酸铵 +硝酸甘 +硝酸甘油 +硝酸钾 +硝酸铊 +销案 +销魂 +銷售 +銷售K粉 +小冰砖 +小冰磚 +小飞狼 +小黑豹 +小姐服务 +小姐上门 +小口径 +小穴 +新车保险 +信息 +信用卡 +型弩 +性爱 +性愛世代 +性吧 +性服务 +性交电影 +性派对 +性图 +性息 +性用品 +性之图 +胸摧 +胸推 +学潮 +学生妹 +学生证 +学位证 +学运 +寻芳 +寻欢 +迅雷下载 +牙签冰 +牙签果 +雅照 +亚热 +亚洲 +盐羟亚胺 +盐酸 +盐酸氯 +盐酸氯胺酮 +盐酸哌替啶 +盐酸羟亚胺 +盐酸曲马多 +盐酸曲马多片 +颜射 +鹽酸 +鹽酸羥亞胺 +艳旅 +艳门 +艳舞 +艳舞女 +艳星 +艳照 +阳具 +洋妞 +陽菜 +搖頭糖 +搖頭丸 +摇头糖 +摇头丸 +夜场 +夜猫网 +夜色撩人 +夜淫 +一本道 +一品楼 +一夜情 +一夜晴 +一字型 +怡红院 +乙醚 +易容 +淫 +淫荡 +淫洞 +淫妇 +淫秽 +淫叫 +淫乱 +淫民 +淫妻 +淫人 +淫色 +淫图 +淫网 +淫穴 +淫液 +淫汁 +银行卡 +银行卡复制 +銀行卡 +引爆器 +隐形 +印钞机 +印花税 +罂 +罂粟 +硬币 +硬幣 +铀 +有偿 +有码 +幼升小 +玉女心经 +玉蒲团 +御花 +慾望技能 +原子弹 +援助妹 +云南情蛊药 +芸能人 +曾道人 +增值税 +赠卵 +炸弹 +炸藥 +战刀 +战狗 +战术 +掌心雷 +招嫖 +找鸡 +找小姐 +找鸭 +找洋 +折刀 +折叠狗 +折叠军 +折叠弩 +针孔 +针孔摄像头 +真城丽美 +真钱 +真枪 +真实文凭 +整人药 +证历 +证券 +证书 +政法 +政府 +执业 +直销 +直销财税 +职称证 +职业打手 +职業殺手 +植物冰 +指定號碼 +指纹膜 +指纹套 +酯 +制作K粉 +制作冰毒 +致幻 +致幻剂 +製作K粉 +製作冰毒 +中出 +中介 +中考 +种子下载 +重刺 +周恩来 +朱&鸡 +朱&基 +朱&雞 +朱&毛 +朱&茸 +朱&溶 +朱&蓉 +朱&榕 +朱&熔 +朱&瑢 +朱&融 +朱荣基 +朱容基 +助考 +爪刀 +专八 +专六 +专卖 +专门供应 +专业发帖 +专业开票 +专用弩 +转让 +追债 +姿丽子 +资格 +资格证 +子弹 +子彈 +自焚 +自慰器 +走私狗 +足交 +钻石冰 +钻石冰糖 +左轮 +左旋麻黄素 +左旋素 +作弊 +作弊工具 +作训 +做爱表演 +占中 +普选 +卖假军官证 +卖高仿身份证 +提供假文凭 +卖资质证书 +提供言正 +卖驾驶证 +办理四六级证书 +当面交易英语等级证 +当面交易居民户口本 +提供假身份证 +当面交易假结婚证 +当面交易驾照 +供应学历证书 +供应户口本 +卖高仿户口本 +做假车牌 +做驾照 +办理护照 +做高仿身份证 +做假文凭 +售行驶证 +办理假户口本 +当面交易车辆牌照 +售假军官证 +售工作证 +提供身份证 +当面交易军官证样本 +售警察证 +卖行驶证 +做假结婚证 +售言正 +做军车套牌 +当面交易高仿学位证 +做行驶证 +售四六级证书 +办理国安证 +卖驾照 +做高仿户口本 +卖工作证 +做假言正 +做车辆牌照 +办理高仿身份证 +做护照 +售军人证 +售护照 +提供军官证样本 +卖英语等级证 +供应毕业文凭 +做假身份证 +当面交易言正 +提供学历证书 +提供国外文凭 +做国外文凭 +办理军官证样本 +供应警官证 +做学历证书 +卖证件 +卖假证件 +卖假车牌 +办理英语等级证 +卖警察证 +卖车辆牌照 +办理记者证 +提供警察证 +做户口本 +提供证件 +办理驾照 +售士兵证 +提供驾驶证 +办理高仿户口本 +提供假证件 +办理国外文凭 +当面交易学历证书 +做假户口本 +做军官证 +供应记者证 +售高仿身份证 +当面交易四六级证书 +当面交易高仿户口本 +当面交易会计师证 +供应护照 +做军官证样本 +供应国外文凭 +卖军人证 +提供行驶证 +办理居民户口本 +卖四六级证书 +售军车套牌 +卖国安证 +提供假车牌 +供应公文 +卖言正 +提供士兵证 +售英语等级证 +提供高仿学位证 +办理高仿证 +当面交易军人证 +办理车辆牌照 +卖假言正 +提供毕业文凭 +供应国安证 +做四六级证书 +办理假文凭 +当面交易高仿身份证 +办理行驶证 +售假文凭 +供应警察证 +售假结婚证 +卖假户口本 +卖身份证 +做英语等级证 +卖毕业文凭 +办理警察证 +当面交易军车套牌 +办理高仿学位证 +售假车牌 +当面交易国安证 +供应资质证书 +做证件 +提供毕业证书 +供应工作证 +办理军车套牌 +提供高仿证 +当面交易国外文凭 +做会计师证 +售军官证 +卖毕业证书 +卖假结婚证 +办理户口本 +卖军车套牌 +当面交易户口本 +当面交易身份证 +供应证件 +售高仿户口本 +办理毕业证书 +售会计师证 +占领中环 +戴耀廷 +中大集会 +催泪弹 +泛民主派 +拉黑布游行 +学界罢课 +香港中环 +香港民主 +香港大学生 +华信民 +习会成为末代总书记吗 +习总日记 +张澜澜 +习氏 +习总书记 +apec会议扰民指数 +新疆暴恐分子会议期间发动袭击 +北京6万警察严正待命 +习近平治国新书 +apec安保盘点 +农历十一黄金周 +雾都堵城优惠假 +天赐良假 +当面交易记者证 +供应行驶证 +办理假证件 +当面交易护照 +供应高仿证 +售国外文凭 +卖公文 +供应言正 +办理假结婚证 +供应军官证 +供应高仿户口本 +做工作证 +售毕业文凭 +售军官证样本 +卖户口本 +供应假户口本 +办理公文 +提供高仿户口本 +供应军人证 +当面交易假身份证 +售公文 +提供驾照 +供应英语等级证 +做言正 +办理会计师证 +售驾照 +提供记者证 +当面交易假车牌 +售居民户口本 +提供居民户口本 +卖国外文凭 +做资质证书 +做高仿学位证 +办理假言正 +做警官证 +当面交易毕业文凭 +售毕业证书 +当面交易军官证 +供应假身份证 +做士兵证 +做记者证 +售记者证 +提供假结婚证 +办理证件 +卖会计师证 +售证件 +卖士兵证 +提供车辆牌照 +当面交易证件 +当面交易工作证 +提供英语等级证 +供应高仿学位证 +卖军官证 +供应车辆牌照 +供应会计师证 +办理驾驶证 +卖护照 +提供国安证 +供应士兵证 +供应假军官证 +卖警官证 +做国安证 +供应假车牌 +供应假言正 +售高仿证 +当面交易警官证 +当面交易驾驶证 +提供假户口本 +卖高仿学位证 +做高仿证 +提供假言正 +售学历证书 +供应四六级证书 +办理军官证 +供应军车套牌 +当面交易假证件 +售身份证 +售驾驶证 +供应高仿身份证 +办理工作证 +当面交易假户口本 +做警察证 +卖军官证样本 +办理假军官证 +当面交易假军官证 +供应驾照 +供应驾驶证 +供应毕业证书 +供应假文凭 +做公文 +办理毕业文凭 +做驾驶证 +办理军人证 +售假证件 +当面交易高仿证 +供应军官证样本 +提供军官证 +售车辆牌照 +售高仿学位证 +提供护照 +办理学历证书 +办理假车牌 +供应假结婚证 +提供警官证 +办理假身份证 +卖学历证书 +提供军车套牌 +供应身份证 +提供资质证书 +做假证件 +卖假文凭 +当面交易士兵证 +办理资质证书 +做军人证 +办理言正 +当面交易假言正 +提供军人证 +供应假证件 +做身份证 +卖居民户口本 +当面交易公文 +提供公文 +做毕业证书 +当面交易毕业证书 +当面交易假文凭 +售假身份证 +办理身份证 +做假军官证 +卖记者证 +提供假军官证 +办理士兵证 +售资质证书 +当面交易行驶证 +做居民户口本 +提供会计师证 +售警官证 +售假言正 +当面交易资质证书 +卖高仿证 +做毕业文凭 +提供工作证 +提供户口本 +售户口本 +当面交易警察证 +售假户口本 +供应居民户口本 +售国安证 +提供高仿身份证 +1325723052 +love-cindy +love—cindy +辣妈群 +加V +加v +加V信 +加v信 +加WX +加wx +qq群 +Q群 +扣扣 +V信群 +v信群 +加扣 +\+V +\+v +兼直 +兼执 +兼之 +蒹职 +蒹直 +蒹只 +蒹之 +诚招代理 +招代理 +诚聘 +诚聘代理 +小鈤工 +工貲鈤洁 +手\.木几 +賺零 +淘宝刷单 +wechat +淘宝 +天猫 +夭貓 +刷单 +拍单 +\+q +\+qq +\+Q +\+QQ +蒹耳只 +兼耳只 +威訫 +兼職 +蒹職 +网兼 +兼\.只\.招\.聘 +兼\.直\.招\.聘 +蒹\.直\.招\.聘 +蒹\.只\.招\.聘 +珈扣 +缣埴傢 +代购 +微商 +V商 +v商 +ruoxianlove +唯一扣 +详情扣 +有意扣 +有意加扣 +详请扣 +详请扣 +兼职扣 +简直扣 +煎直扣 +在家赚 +看扣 +看q +看Q +看空间 +微店 +微点 +空闲时间 +日结 +兼1职 +唯一加 +详情加 +有意加 +详请加 +详请加 +兼职加 +简直加 +煎直加 +在。家。赚。 +看。扣 +看。q +看。Q +看。空。间 +微。店 +微。点 +空。闲。时。间 +日。结 +兼。职 +兼2职 +唯一家 +详情家 +有意家 +有意家q +详请家 +详请家 +兼职家 +简直家 +煎直家 +在\.家\.赚\. +看\.扣 +看\.q +看\.Q +看\.空\.间 +微\.店 +微\.点 +空\.闲\.时\.间 +日\.结 +兼\.职 +兼3职 +唯一q +详情Q +有意q +有意加q +详请q +详请q +兼职q +简直q +煎直q +在,家,赚 +看,扣 +看,q +看,Q +看,空,间 +微,店 +微,点 +空,闲,时,间 +日,结 +兼,职 +兼4职 +唯一Q +详情Q +有意Q +有意加Q +详请Q +详请Q +兼职Q +简直Q +煎直Q +在,家,赚 +看,扣 +看,q +看,Q +看,空,间 +微,店 +微,点 +空,闲,时,间 +日,结 +兼\*职 +兼5职 +唯一抠 +详情抠 +有意抠 +有意加抠 +详请抠 +详请抠 +兼职抠 +简直抠 +煎直抠 +兼@职 +兼6职 +唯一口 +详情口 +有意口 +有意加口 +详请口 +详请口 +兼职口 +简直口 +煎直口 +兼#职 +兼7职 +唯一寇 +详情寇 +有意寇 +有意加寇 +详请寇 +详请寇 +兼职寇 +简直寇 +煎直寇 +兼¥职 +兼¥职 +兼8职 +唯一蔻 +详情蔻 +有意蔻 +有意加蔻 +详请蔻 +详请蔻 +兼职蔻 +简直蔻 +煎直蔻 +兼%职 +兼9职 +兼&职 +兼\*职 +在家赚钱 +在jia赚钱 +在家zhuan钱 +在家赚qian +在家赚money +意者加我扣 +意者加扣 +意者加我抠 +意者加我寇 +意者加我蔻 +意者加抠 +意者加寇 +意者加蔻 +意加扣 +意加抠 +意加寇 +意加蔻 +\/天 +空jian +kong间 +kong jian +陶宝 +陶bao +tao宝 +兼zhi +jian职 +傔职 +傔zhi +傔,职 +傔。职 +傔、职 +傔,职 +傔\?职 +傔?职 +傔!职 +傔!职 +傔@职 +傔职# +傔#职 +傔¥职 +傔¥职 +傔$职 +傔%职 +傔\^职 +傔&职 +傔\*职 +傔’职 +傔”职 +傔\职 +傔\.职 +工资即时结算 +50-200不等 +在家也能赚奶粉钱 +在家也能赚钱 +在家能赚奶粉钱 +在家能赚钱 +工资日结 +工资每日结算 +加我Q +加我QQ +Q1 +Q2 +Q3 +Q4 +Q5 +Q6 +Q7 +Q8 +Q9 +q1 +q2 +q3 +q4 +q5 +q6 +q7 +q8 +q9 +监职 +监,职 +监,职 +监。职 +监\.职 +监\?职 +监?职 +监!职 +监!职 +监@职 +监#职 +监$职 +监%职 +监\^职 +监&职 +监\*职 +监~职 +监1职 +监2职 +监3职 +监4职 +监5职 +监6职 +监7职 +监8职 +监9职 +加口 +不限时间 +不限地点 +不限时间和地点 +日算 +日,算 +日,算 +日。算 +日\.算 +50-100不等 +50-200不等 +50-150不等 +10-200不等 +50到100不等 +50到200不等 +50到150不等 +100到200不等 +聘口 +聘扣 +聘抠 +聘叩 +聘寇 +聘蔻 +手机挣米 +手机挣钱 +手机赚米 +手机赚钱 +赚钱 +挣钱 +兼职扣 +兼职Q +兼职q +兼职抠 +兼职叩 +兼职寇 +兼职蔻 +蒹职 +简直Q +简直q +简直抠 +简直扣 +简直家兼职寇 +兼职寇 +简直加 +联系方式 +联系Q +联系q +联系寇 +联系扣 +联系叩 +联系抠 +加Q +加q +加口 +加抠 +加寇 +加叩 +加扣 +加蔻 +兼职加 +兼职家 +煎直扣 +煎直加 +煎直家 +煎直抠 +煎直扣 +煎直寇 +煎直蔻 +煎直Q +煎直q +煎直口 +在·家·赚 +看·扣 +看·q +看·Q +看·空·间 +微·店 +微·点 +空·闲·时·间 +日·结 +微一 +微二 +微三 +微四 +微五 +微六 +微七 +微八 +微九 +微1 +微2 +微3 +微4 +微5 +微6 +微7 +微8 +微9 +薇一 +薇二 +薇三 +薇四 +薇五 +薇六 +薇七 +薇八 +薇九 +薇1 +薇2 +薇3 +薇4 +薇5 +薇6 +薇7 +薇8 +薇9 +天结 +天,结 +天。结 +天,结 +天\.结 +天?结 +天\?结 +天\/结 +天!结 +天@结 +天#结 +天¥结 +天¥结 +天%结 +天\^结 +天&结 +天\*结 +天-结 +天\[结 +天\]结 +天【结 +天】结 +天·结 +天:结 +天;结 +天~结 +天_结 +天—结 +日结 +日,结 +日。结 +日,结 +日\.结 +日?结 +日\?结 +日\/结 +日!结 +日@结 +日#结 +日¥结 +日¥结 +日%结 +日\^结 +日&结 +日\*结 +日-结 +日\[结 +日\]结 +日【结 +日】结 +日·结 +日:结 +日;结 +日~结 +日_结 +日—结 +日入 +日,入 +日。入 +日,入 +日\.入 +日?入 +日\?入 +日\/入 +日!入 +日@入 +日#入 +日¥入 +日¥入 +日%入 +日\^入 +日&入 +日\*入 +日-入 +日\[入 +日\]入 +日【入 +日】入 +日·入 +日:入 +日;入 +日~入 +日_入 +日—入 +\+我 +\+,我 +\+。我 +\+,我 +\+\.我 +\+?我 +\+\?我 +\+\/我 +\+!我 +\+@我 +\+#我 +\+¥我 +\+¥我 +\+%我 +\+\^我 +\+&我 +\+\*我 +\+-我 +\+\[我 +\+\]我 +\+【我 +\+】我 +\+·我 +\+:我 +\+;我 +\+~我 +\+_我 +\+—我 +蔻蔻 +蔻,蔻 +蔻。蔻 +蔻,蔻 +蔻\.蔻 +蔻?蔻 +蔻\?蔻 +蔻\/蔻 +蔻!蔻 +蔻@蔻 +蔻#蔻 +蔻¥蔻 +蔻¥蔻 +蔻%蔻 +蔻\^蔻 +蔻&蔻 +蔻\*蔻 +蔻-蔻 +蔻\[蔻 +蔻\]蔻 +蔻【蔻 +蔻】蔻 +蔻·蔻 +蔻:蔻 +蔻;蔻 +蔻~蔻 +蔻_蔻 +蔻—蔻 +代购 +代,购 +代。购 +代,购 +代\.购 +代?购 +代\?购 +代\/购 +代!购 +代@购 +代#购 +代¥购 +代¥购 +代%购 +代\^购 +代&购 +代\*购 +代-购 +代\[购 +代\]购 +代【购 +代】购 +代·购 +代:购 +代;购 +代~购 +代_购 +代—购 +傔职 +傔,职 +傔。职 +傔,职 +傔\.职 +傔?职 +傔\?职 +傔\/职 +傔!职 +傔@职 +傔#职 +傔¥职 +傔¥职 +傔%职 +傔\^职 +傔&职 +傔\*职 +傔-职 +傔\[职 +傔\]职 +傔【职 +傔】职 +傔·职 +傔:职 +傔;职 +傔~职 +傔_职 +傔—职 +诚聘 +诚,聘 +诚聘 +诚,聘 +诚\.聘 +诚?聘 +诚\?聘 +诚\/聘 +诚!聘 +诚@聘 +诚#聘 +诚¥聘 +诚¥聘 +诚%聘 +诚\^聘 +诚&聘 +诚\*聘 +诚-聘 +诚\[聘 +诚\]聘 +诚【聘 +诚】聘 +诚·聘 +诚:聘 +诚;聘 +诚~聘 +诚_聘 +诚—聘 +尖值 +尖,值 +尖。值 +尖,值 +尖\.值 +尖?值 +尖\?值 +尖\/值 +尖!值 +尖@值 +尖#值 +尖¥值 +尖¥值 +尖%值 +尖\^值 +尖&值 +尖\*值 +尖-值 +尖\[值 +尖\]值 +尖【值 +尖】值 +尖·值 +尖:值 +尖;值 +尖~值 +尖_值 +尖—值 +招募 +招,募 +招。募 +招,募 +招\.募 +招?募 +招募 +招\/募 +招!募 +招@募 +招#募 +招¥募 +招¥募 +招%募 +招\^募 +招&募 +招\*募 +招-募 +招\[募 +招\]募 +招【募 +招】募 +招·募 +招:募 +招;募 +招~募 +招_募 +招—募 +q +q, +q。 +q, +q\. +q? +q\? +q\/ +q! +q@ +q# +q¥ +q¥ +q% +q\^ +q& +q\* +q- +q\[ +q\] +q【 +q】 +q· +q: +q; +q~ +q_ +q— +Q +Q, +Q。 +Q, +Q\. +Q? +Q\? +Q\/ +Q! +Q@ +Q# +Q¥ +Q¥ +Q% +Q\^ +Q& +Q\* +Q- +Q\[ +Q\] +Q【 +Q】 +Q· +Q: +Q; +Q~ +Q_ +Q— +jian职 +jian,职 +jian。职 +jian,职 +jian\.职 +jian?职 +jian职 +jian\/职 +jian!职 +jian@职 +jian#职 +jian¥职 +jian¥职 +jian%职 +jian\^职 +jian&职 +jian\*职 +jian-职 +jian\[职 +jian\]职 +jian【职 +jian】职 +jian·职 +jian:职 +jian;职 +jian~职 +jian_职 +jian—职 +兼zhi +兼,zhi +兼。zhi +兼,zhi +兼\.zhi +兼?zhi +兼zhi +兼\/zhi +兼!zhi +兼@zhi +兼#zhi +兼¥zhi +兼¥zhi +兼%zhi +兼\^zhi +兼&zhi +兼\*zhi +兼-zhi +兼\[zhi +兼\]zhi +兼【zhi +兼】zhi +兼·zhi +兼:zhi +兼;zhi +兼~zhi +兼_zhi +兼—zhi +缣耳只 +兼耳只 +傔耳只 +工資曰結 +抠1 +抠2 +抠3 +抠4 +抠5 +抠6 +抠7 +抠8 +抠9 +抠 +口1 +口2 +口3 +口4 +口5 +口6 +口7 +口8 +口9 +口 +蔻1 +蔻2 +蔻3 +蔻4 +蔻5 +蔻6 +蔻7 +蔻8 +蔻9 +蔻 +扣1 +扣2 +扣3 +扣4 +扣5 +扣6 +扣7 +扣8 +扣9 +扣 +寇1 +寇2 +寇3 +寇4 +寇5 +寇6 +寇7 +寇8 +寇9 +寇 +抠1 +抠,1 +抠。1 +抠,1 +抠\.1 +抠?1 +抠\?1 +抠\/1 +抠!1 +抠@1 +抠#1 +抠¥1 +抠%1 +抠\^1 +抠&1 +抠\*1 +抠-1 +抠\[1 +抠\]1 +抠【1 +抠】1 +抠·1 +抠:1 +抠;1 +抠~1 +抠_1 +抠—1 +抠\:1 +抠!1 +口1 +口,1 +口。1 +口,1 +口\.1 +口?1 +口\?1 +口\/1 +口!1 +口@1 +口#1 +口¥1 +口%1 +口\^1 +口&1 +口\*1 +口-1 +口\[1 +口\]1 +口【1 +口】1 +口·1 +口:1 +口;1 +口~1 +口_1 +口—1 +口\:1 +口!1 +蔻1 +蔻,1 +蔻。1 +蔻,1 +蔻\.1 +蔻?1 +蔻\?1 +蔻\/1 +蔻!1 +蔻@1 +蔻#1 +蔻¥1 +蔻%1 +蔻\^1 +蔻&1 +蔻\*1 +蔻-1 +蔻\[1 +蔻\]1 +蔻【1 +蔻】1 +蔻·1 +蔻:1 +蔻;1 +蔻~1 +蔻_1 +蔻—1 +蔻\:1 +蔻!1 +扣1 +扣,1 +扣。1 +扣,1 +扣\.1 +扣?1 +扣\?1 +扣\/1 +扣!1 +扣@1 +扣#1 +扣¥1 +扣%1 +扣\^1 +扣&1 +扣\*1 +扣-1 +扣\[1 +扣\]1 +扣【1 +扣】1 +扣·1 +扣:1 +扣;1 +扣~1 +扣_1 +扣—1 +扣\:1 +扣!1 +寇1 +寇,1 +寇。1 +寇,1 +寇\.1 +寇?1 +寇\?1 +寇\/1 +寇!1 +寇@1 +寇#1 +寇¥1 +寇%1 +寇\^1 +寇&1 +寇\*1 +寇-1 +寇\[1 +寇\]1 +寇【1 +寇】1 +寇·1 +寇:1 +寇;1 +寇~1 +寇_1 +寇—1 +寇\:1 +寇!1 +抠2 +抠,2 +抠。2 +抠,2 +抠\.2 +抠?2 +抠\?2 +抠\/2 +抠!2 +抠@2 +抠#2 +抠¥2 +抠%2 +抠\^2 +抠&2 +抠\*2 +抠-2 +抠\[2 +抠\]2 +抠【2 +抠】2 +抠·2 +抠:2 +抠;2 +抠~2 +抠_2 +抠—2 +抠\:2 +抠!2 +口2 +口,2 +口。2 +口,2 +口\.2 +口?2 +口\?2 +口\/2 +口!2 +口@2 +口#2 +口¥2 +口%2 +口\^2 +口&2 +口\*2 +口-2 +口\[2 +口\]2 +口【2 +口】2 +口·2 +口:2 +口;2 +口~2 +口_2 +口—2 +口\:2 +口!2 +蔻2 +蔻,2 +蔻。2 +蔻,2 +蔻\.2 +蔻?2 +蔻\?2 +蔻\/2 +蔻!2 +蔻@2 +蔻#2 +蔻¥2 +蔻%2 +蔻\^2 +蔻&2 +蔻\*2 +蔻-2 +蔻\[2 +蔻\]2 +蔻【2 +蔻】2 +蔻·2 +蔻:2 +蔻;2 +蔻~2 +蔻_2 +蔻—2 +蔻\:2 +蔻!2 +扣2 +扣,2 +扣。2 +扣,2 +扣\.2 +扣?2 +扣\?2 +扣\/2 +扣!2 +扣@2 +扣#2 +扣¥2 +扣%2 +扣\^2 +扣&2 +扣\*2 +扣-2 +扣\[2 +扣\]2 +扣【2 +扣】2 +扣·2 +扣:2 +扣;2 +扣~2 +扣_2 +扣—2 +扣\:2 +扣!2 +寇2 +寇,2 +寇。2 +寇,2 +寇\.2 +寇?2 +寇\?2 +寇\/2 +寇!2 +寇@2 +寇#2 +寇¥2 +寇%2 +寇\^2 +寇&2 +寇\*2 +寇-2 +寇\[2 +寇\]2 +寇【2 +寇】2 +寇·2 +寇:2 +寇;2 +寇~2 +寇_2 +寇—2 +寇\:2 +寇!2 +抠3 +抠,3 +抠。3 +抠,3 +抠\.3 +抠?3 +抠\?3 +抠\/3 +抠!3 +抠@3 +抠#3 +抠¥3 +抠%3 +抠\^3 +抠&3 +抠\*3 +抠-3 +抠\[3 +抠\]3 +抠【3 +抠】3 +抠·3 +抠:3 +抠;3 +抠~3 +抠_3 +抠—3 +抠\:3 +抠!3 +口3 +口,3 +口。3 +口,3 +口\.3 +口?3 +口\?3 +口\/3 +口!3 +口@3 +口#3 +口¥3 +口%3 +口\^3 +口&3 +口\*3 +口-3 +口\[3 +口\]3 +口【3 +口】3 +口·3 +口:3 +口;3 +口~3 +口_3 +口—3 +口\:3 +口!3 +蔻3 +蔻,3 +蔻。3 +蔻,3 +蔻\.3 +蔻?3 +蔻\?3 +蔻\/3 +蔻!3 +蔻@3 +蔻#3 +蔻¥3 +蔻%3 +蔻\^3 +蔻&3 +蔻\*3 +蔻-3 +蔻\[3 +蔻\]3 +蔻【3 +蔻】3 +蔻·3 +蔻:3 +蔻;3 +蔻~3 +蔻_3 +蔻—3 +蔻\:3 +蔻!3 +扣3 +扣,3 +扣。3 +扣,3 +扣\.3 +扣?3 +扣\?3 +扣\/3 +扣!3 +扣@3 +扣#3 +扣¥3 +扣%3 +扣\^3 +扣&3 +扣\*3 +扣-3 +扣\[3 +扣\]3 +扣【3 +扣】3 +扣·3 +扣:3 +扣;3 +扣~3 +扣_3 +扣—3 +扣\:3 +扣!3 +寇3 +寇,3 +寇。3 +寇,3 +寇\.3 +寇?3 +寇\?3 +寇\/3 +寇!3 +寇@3 +寇#3 +寇¥3 +寇%3 +寇\^3 +寇&3 +寇\*3 +寇-3 +寇\[3 +寇\]3 +寇【3 +寇】3 +寇·3 +寇:3 +寇;3 +寇~3 +寇_3 +寇—3 +寇\:3 +寇!3 +抠4 +抠,4 +抠。4 +抠,4 +抠\.4 +抠?4 +抠\?4 +抠\/4 +抠!4 +抠@4 +抠#4 +抠¥4 +抠%4 +抠\^4 +抠&4 +抠\*4 +抠-4 +抠\[4 +抠\]4 +抠【4 +抠】4 +抠·4 +抠:4 +抠;4 +抠~4 +抠_4 +抠—4 +抠\:4 +抠!4 +口4 +口,4 +口。4 +口,4 +口\.4 +口?4 +口\?4 +口\/4 +口!4 +口@4 +口#4 +口¥4 +口%4 +口\^4 +口&4 +口\*4 +口-4 +口\[4 +口\]4 +口【4 +口】4 +口·4 +口:4 +口;4 +口~4 +口_4 +口—4 +口\:4 +口!4 +蔻4 +蔻,4 +蔻。4 +蔻,4 +蔻\.4 +蔻?4 +蔻\?4 +蔻\/4 +蔻!4 +蔻@4 +蔻#4 +蔻¥4 +蔻%4 +蔻\^4 +蔻&4 +蔻\*4 +蔻-4 +蔻\[4 +蔻\]4 +蔻【4 +蔻】4 +蔻·4 +蔻:4 +蔻;4 +蔻~4 +蔻_4 +蔻—4 +蔻\:4 +蔻!4 +扣4 +扣,4 +扣。4 +扣,4 +扣\.4 +扣?4 +扣\?4 +扣\/4 +扣!4 +扣@4 +扣#4 +扣¥4 +扣%4 +扣\^4 +扣&4 +扣\*4 +扣-4 +扣\[4 +扣\]4 +扣【4 +扣】4 +扣·4 +扣:4 +扣;4 +扣~4 +扣_4 +扣—4 +扣\:4 +扣!4 +寇4 +寇,4 +寇。4 +寇,4 +寇\.4 +寇?4 +寇\?4 +寇\/4 +寇!4 +寇@4 +寇#4 +寇¥4 +寇%4 +寇\^4 +寇&4 +寇\*4 +寇-4 +寇\[4 +寇\]4 +寇【4 +寇】4 +寇·4 +寇:4 +寇;4 +寇~4 +寇_4 +寇—4 +寇\:4 +寇!4 +抠5 +抠,5 +抠。5 +抠,5 +抠\.5 +抠?5 +抠\?5 +抠\/5 +抠!5 +抠@5 +抠#5 +抠¥5 +抠%5 +抠\^5 +抠&5 +抠\*5 +抠-5 +抠\[5 +抠\]5 +抠【5 +抠】5 +抠·5 +抠:5 +抠;5 +抠~5 +抠_5 +抠—5 +抠\:5 +抠!5 +口5 +口,5 +口。5 +口,5 +口\.5 +口?5 +口\?5 +口\/5 +口!5 +口@5 +口#5 +口¥5 +口%5 +口\^5 +口&5 +口\*5 +口-5 +口\[5 +口\]5 +口【5 +口】5 +口·5 +口:5 +口;5 +口~5 +口_5 +口—5 +口\:5 +口!5 +蔻5 +蔻,5 +蔻。5 +蔻,5 +蔻\.5 +蔻?5 +蔻\?5 +蔻\/5 +蔻!5 +蔻@5 +蔻#5 +蔻¥5 +蔻%5 +蔻\^5 +蔻&5 +蔻\*5 +蔻-5 +蔻\[5 +蔻\]5 +蔻【5 +蔻】5 +蔻·5 +蔻:5 +蔻;5 +蔻~5 +蔻_5 +蔻—5 +蔻\:5 +蔻!5 +扣5 +扣,5 +扣。5 +扣,5 +扣\.5 +扣?5 +扣\?5 +扣\/5 +扣!5 +扣@5 +扣#5 +扣¥5 +扣%5 +扣\^5 +扣&5 +扣\*5 +扣-5 +扣\[5 +扣\]5 +扣【5 +扣】5 +扣·5 +扣:5 +扣;5 +扣~5 +扣_5 +扣—5 +扣\:5 +扣!5 +寇5 +寇,5 +寇。5 +寇,5 +寇\.5 +寇?5 +寇\?5 +寇\/5 +寇!5 +寇@5 +寇#5 +寇¥5 +寇%5 +寇\^5 +寇&5 +寇\*5 +寇-5 +寇\[5 +寇\]5 +寇【5 +寇】5 +寇·5 +寇:5 +寇;5 +寇~5 +寇_5 +寇—5 +寇\:5 +寇!5 +抠6 +抠,6 +抠。6 +抠,6 +抠\.6 +抠?6 +抠\?6 +抠\/6 +抠!6 +抠@6 +抠#6 +抠¥6 +抠%6 +抠\^6 +抠&6 +抠\*6 +抠-6 +抠\[6 +抠\]6 +抠【6 +抠】6 +抠·6 +抠:6 +抠;6 +抠~6 +抠_6 +抠—6 +抠\:6 +抠!6 +口6 +口,6 +口。6 +口,6 +口\.6 +口?6 +口\?6 +口\/6 +口!6 +口@6 +口#6 +口¥6 +口%6 +口\^6 +口&6 +口\*6 +口-6 +口\[6 +口\]6 +口【6 +口】6 +口·6 +口:6 +口;6 +口~6 +口_6 +口—6 +口\:6 +口!6 +蔻6 +蔻,6 +蔻。6 +蔻,6 +蔻\.6 +蔻?6 +蔻\?6 +蔻\/6 +蔻!6 +蔻@6 +蔻#6 +蔻¥6 +蔻%6 +蔻\^6 +蔻&6 +蔻\*6 +蔻-6 +蔻\[6 +蔻\]6 +蔻【6 +蔻】6 +蔻·6 +蔻:6 +蔻;6 +蔻~6 +蔻_6 +蔻—6 +蔻\:6 +蔻!6 +扣6 +扣,6 +扣。6 +扣,6 +扣\.6 +扣?6 +扣\?6 +扣\/6 +扣!6 +扣@6 +扣#6 +扣¥6 +扣%6 +扣\^6 +扣&6 +扣\*6 +扣-6 +扣\[6 +扣\]6 +扣【6 +扣】6 +扣·6 +扣:6 +扣;6 +扣~6 +扣_6 +扣—6 +扣\:6 +扣!6 +寇6 +寇,6 +寇。6 +寇,6 +寇\.6 +寇?6 +寇\?6 +寇\/6 +寇!6 +寇@6 +寇#6 +寇¥6 +寇%6 +寇\^6 +寇&6 +寇\*6 +寇-6 +寇\[6 +寇\]6 +寇【6 +寇】6 +寇·6 +寇:6 +寇;6 +寇~6 +寇_6 +寇—6 +寇\:6 +寇!6 +抠7 +抠,7 +抠。7 +抠,7 +抠\.7 +抠?7 +抠\?7 +抠\/7 +抠!7 +抠@7 +抠#7 +抠¥7 +抠%7 +抠\^7 +抠&7 +抠\*7 +抠-7 +抠\[7 +抠\]7 +抠【7 +抠】7 +抠·7 +抠:7 +抠;7 +抠~7 +抠_7 +抠—7 +抠\:7 +抠!7 +口7 +口,7 +口。7 +口,7 +口\.7 +口?7 +口\?7 +口\/7 +口!7 +口@7 +口#7 +口¥7 +口%7 +口\^7 +口&7 +口\*7 +口-7 +口\[7 +口\]7 +口【7 +口】7 +口·7 +口:7 +口;7 +口~7 +口_7 +口—7 +口\:7 +口!7 +蔻7 +蔻,7 +蔻。7 +蔻,7 +蔻\.7 +蔻?7 +蔻\?7 +蔻\/7 +蔻!7 +蔻@7 +蔻#7 +蔻¥7 +蔻%7 +蔻\^7 +蔻&7 +蔻\*7 +蔻-7 +蔻\[7 +蔻\]7 +蔻【7 +蔻】7 +蔻·7 +蔻:7 +蔻;7 +蔻~7 +蔻_7 +蔻—7 +蔻\:7 +蔻!7 +扣7 +扣,7 +扣。7 +扣,7 +扣\.7 +扣?7 +扣\?7 +扣\/7 +扣!7 +扣@7 +扣#7 +扣¥7 +扣%7 +扣\^7 +扣&7 +扣\*7 +扣-7 +扣\[7 +扣\]7 +扣【7 +扣】7 +扣·7 +扣:7 +扣;7 +扣~7 +扣_7 +扣—7 +扣\:7 +扣!7 +寇7 +寇,7 +寇。7 +寇,7 +寇\.7 +寇?7 +寇\?7 +寇\/7 +寇!7 +寇@7 +寇#7 +寇¥7 +寇%7 +寇\^7 +寇&7 +寇\*7 +寇-7 +寇\[7 +寇\]7 +寇【7 +寇】7 +寇·7 +寇:7 +寇;7 +寇~7 +寇_7 +寇—7 +寇\:7 +寇!7 +抠8 +抠,8 +抠。8 +抠,8 +抠\.8 +抠?8 +抠\?8 +抠\/8 +抠!8 +抠@8 +抠#8 +抠¥8 +抠%8 +抠\^8 +抠&8 +抠\*8 +抠-8 +抠\[8 +抠\]8 +抠【8 +抠】8 +抠·8 +抠:8 +抠;8 +抠~8 +抠_8 +抠—8 +抠\:8 +抠!8 +口8 +口,8 +口。8 +口,8 +口\.8 +口?8 +口\?8 +口\/8 +口!8 +口@8 +口#8 +口¥8 +口%8 +口\^8 +口&8 +口\*8 +口-8 +口\[8 +口\]8 +口【8 +口】8 +口·8 +口:8 +口;8 +口~8 +口_8 +口—8 +口\:8 +口!8 +蔻8 +蔻,8 +蔻。8 +蔻,8 +蔻\.8 +蔻?8 +蔻\?8 +蔻\/8 +蔻!8 +蔻@8 +蔻#8 +蔻¥8 +蔻%8 +蔻\^8 +蔻&8 +蔻\*8 +蔻-8 +蔻\[8 +蔻\]8 +蔻【8 +蔻】8 +蔻·8 +蔻:8 +蔻;8 +蔻~8 +蔻_8 +蔻—8 +蔻\:8 +蔻!8 +扣8 +扣,8 +扣。8 +扣,8 +扣\.8 +扣?8 +扣\?8 +扣\/8 +扣!8 +扣@8 +扣#8 +扣¥8 +扣%8 +扣\^8 +扣&8 +扣\*8 +扣-8 +扣\[8 +扣\]8 +扣【8 +扣】8 +扣·8 +扣:8 +扣;8 +扣~8 +扣_8 +扣—8 +扣\:8 +扣!8 +寇8 +寇,8 +寇。8 +寇,8 +寇\.8 +寇?8 +寇\?8 +寇\/8 +寇!8 +寇@8 +寇#8 +寇¥8 +寇%8 +寇\^8 +寇&8 +寇\*8 +寇-8 +寇\[8 +寇\]8 +寇【8 +寇】8 +寇·8 +寇:8 +寇;8 +寇~8 +寇_8 +寇—8 +寇\:8 +寇!8 +抠9 +抠,9 +抠。9 +抠,9 +抠\.9 +抠?9 +抠\?9 +抠\/9 +抠!9 +抠@9 +抠#9 +抠¥9 +抠%9 +抠\^9 +抠&9 +抠\*9 +抠-9 +抠\[9 +抠\]9 +抠【9 +抠】9 +抠·9 +抠:9 +抠;9 +抠~9 +抠_9 +抠—9 +抠\:9 +抠!9 +口9 +口,9 +口。9 +口,9 +口\.9 +口?9 +口\?9 +口\/9 +口!9 +口@9 +口#9 +口¥9 +口%9 +口\^9 +口&9 +口\*9 +口-9 +口\[9 +口\]9 +口【9 +口】9 +口·9 +口:9 +口;9 +口~9 +口_9 +口—9 +口\:9 +口!9 +蔻9 +蔻,9 +蔻。9 +蔻,9 +蔻\.9 +蔻?9 +蔻\?9 +蔻\/9 +蔻!9 +蔻@9 +蔻#9 +蔻¥9 +蔻%9 +蔻\^9 +蔻&9 +蔻\*9 +蔻-9 +蔻\[9 +蔻\]9 +蔻【9 +蔻】9 +蔻·9 +蔻:9 +蔻;9 +蔻~9 +蔻_9 +蔻—9 +蔻\:9 +蔻!9 +扣9 +扣,9 +扣。9 +扣,9 +扣\.9 +扣?9 +扣\?9 +扣\/9 +扣!9 +扣@9 +扣#9 +扣¥9 +扣%9 +扣\^9 +扣&9 +扣\*9 +扣-9 +扣\[9 +扣\]9 +扣【9 +扣】9 +扣·9 +扣:9 +扣;9 +扣~9 +扣_9 +扣—9 +扣\:9 +扣!9 +寇9 +寇,9 +寇。9 +寇,9 +寇\.9 +寇?9 +寇\?9 +寇\/9 +寇!9 +寇@9 +寇#9 +寇¥9 +寇%9 +寇\^9 +寇&9 +寇\*9 +寇-9 +寇\[9 +寇\]9 +寇【9 +寇】9 +寇·9 +寇:9 +寇;9 +寇~9 +寇_9 +寇—9 +寇\:9 +寇!9 +jianzhi + +jian,zhi +jian。zhi +jian,zhi +jian\.zhi +jian?zhi +jian\?zhi +jian\/zhi +jian!zhi +jian@zhi +jian#zhi +jian¥zhi +jian%zhi +jian\^zhi +jian&zhi +jian\*zhi +jian-zhi +jian\[zhi +jian\]zhi +jian【zhi +jian】zhi +jian·zhi +jian:zhi +jian;zhi +jian~zhi +jian_zhi +jian—zhi +jian\:zhi +jian!zhi \ No newline at end of file -- Gitee From 2dcdc324be52433085c9fe508fe28cdc918e8924 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Mon, 28 Feb 2022 17:04:04 +0800 Subject: [PATCH 058/125] update get comment by postId --- .../controller/CommentController.java | 66 +++++++++---------- .../greate/community/dao/CommentMapper.java | 9 ++- .../community/service/CommentService.java | 16 ++++- src/main/resources/application.properties | 4 +- src/main/resources/mapper/comment-mapper.xml | 21 ++++-- 5 files changed, 70 insertions(+), 46 deletions(-) diff --git a/src/main/java/com/greate/community/controller/CommentController.java b/src/main/java/com/greate/community/controller/CommentController.java index 43fbdc9..6c14605 100644 --- a/src/main/java/com/greate/community/controller/CommentController.java +++ b/src/main/java/com/greate/community/controller/CommentController.java @@ -95,51 +95,49 @@ public class CommentController extends BaseController implements CommunityConsta public Result getCommentsByPostId(@PathVariable("discussPostId") int discussPostId, Page page) { page.setPath("/comment/get/" + discussPostId); + // 帖子下评论总数 + page.setRows(commentService.findCommentCountByPostId(discussPostId)); + // 帖子的评论列表 List commentList = commentService.findCommentByPost( discussPostId, page.getOffset(), page.getLimit()); // 封装评论及其相关信息 - if (commentList == null || commentList.isEmpty()) { - return new Result("fail", "1", "帖子不存在"); - } - List> commentVoList = new ArrayList<>(); - for (Comment comment : commentList) { - Map commentVo = new HashMap<>(); - commentVo.put("comment", StringListConvertor.toJsonObject(comment, "picUrls")); // 评论 - commentVo.put("user", userService.findUserById(comment.getUserId())); // 发布评论的作者 - int likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( - getUser().getId(), ENTITY_TYPE_COMMENT, comment.getId()); // 当前登录用户对该评论的点赞状态 - commentVo.put("likeStatus", likeStatus); - - // 存储每个评论对应的回复(不做分页) - // todo: 对回复做分页和排序处理 - List replyList = commentService.findReplyByComment( - comment.getId(), 0, Integer.MAX_VALUE); - List> replyVoList = new ArrayList<>(); // 封装对评论的评论和评论的作者信息 - if (replyList != null) { - for (Comment reply : replyList) { - Map replyVo = new HashMap<>(); - replyVo.put("reply", StringListConvertor.toJsonObject(reply, "picUrls")); // 回复 - replyVo.put("user", userService.findUserById(reply.getUserId())); // 发布该回复的作者 - likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( - getUser().getId(), ENTITY_TYPE_COMMENT, reply.getId()); - replyVo.put("likeStatus", likeStatus); // 当前登录用户的点赞状态 - - replyVoList.add(replyVo); + if (commentList != null && !commentList.isEmpty()) { + for (Comment comment : commentList) { + Map commentVo = new HashMap<>(); + commentVo.put("comment", StringListConvertor.toJsonObject(comment, "picUrls")); // 评论 + commentVo.put("user", userService.findUserById(comment.getUserId())); // 发布评论的作者 + // 当前登录用户对该评论的点赞状态 + int likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( + getUser().getId(), ENTITY_TYPE_COMMENT, comment.getId()); + commentVo.put("likeStatus", likeStatus); + // 存储每个评论对应的回复, 查询点赞量最高的前3条回复 + List replyList = commentService.findReplyByComment(comment.getId(), 0, 3); + List> replyVoList = new ArrayList<>(); // 封装对评论的评论和评论的作者信息 + if (replyList != null) { + for (Comment reply : replyList) { + Map replyVo = new HashMap<>(); + replyVo.put("reply", StringListConvertor.toJsonObject(reply, "picUrls")); // 回复 + replyVo.put("user", userService.findUserById(reply.getUserId())); // 发布该回复的作者 + likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( + getUser().getId(), ENTITY_TYPE_COMMENT, reply.getId()); + replyVo.put("likeStatus", likeStatus); // 当前登录用户的点赞状态 + + replyVoList.add(replyVo); + } } - } - commentVo.put("replys", replyVoList); + commentVo.put("replys", replyVoList); - // 每个评论对应的回复数量 - int replyCount = commentService.findReplyCount(comment.getId()); - commentVo.put("replyCount", replyCount); + // 每个评论对应的回复数量 + int replyCount = commentService.findReplyCount(comment.getId()); + commentVo.put("replyCount", replyCount); - commentVoList.add(commentVo); + commentVoList.add(commentVo); + } } - JSONArray result = (JSONArray) JSONArray.toJSON(commentVoList); page.setResult(result); diff --git a/src/main/java/com/greate/community/dao/CommentMapper.java b/src/main/java/com/greate/community/dao/CommentMapper.java index eb970a2..583a494 100644 --- a/src/main/java/com/greate/community/dao/CommentMapper.java +++ b/src/main/java/com/greate/community/dao/CommentMapper.java @@ -38,7 +38,14 @@ public interface CommentMapper { * @param postId * @return */ - int selectCountByPostId(int postId); + int selectCommentAndReplyCountByPostId(int postId); + + /** + * 查询帖子下评论的数量 + * @param postId + * @return + */ + int selectCommentCountByPostId(int postId); /** * 查询某个评论回复的数量 diff --git a/src/main/java/com/greate/community/service/CommentService.java b/src/main/java/com/greate/community/service/CommentService.java index a48e0af..818c13d 100644 --- a/src/main/java/com/greate/community/service/CommentService.java +++ b/src/main/java/com/greate/community/service/CommentService.java @@ -58,13 +58,23 @@ public class CommentService implements CommunityConstant { } /** - * 查询评论的数量 + * 查询帖子下评论、回复的数量 * * @param postId * @return */ - public int findCommentCount(int postId) { - return commentMapper.selectCountByPostId(postId); + public int findCommentAndReplyCommentCountByPostId(int postId) { + return commentMapper.selectCommentAndReplyCountByPostId(postId); + } + + /** + * 查询帖子下评论的数量 + * + * @param postId + * @return + */ + public int findCommentCountByPostId(int postId) { + return commentMapper.selectCommentCountByPostId(postId); } /** diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 1cfcf25..a1ee24d 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,6 +1,6 @@ # profile(ʱ develop, ߲ʱǵøij produce) -#spring.profiles.active = develop -spring.profiles.active = test +spring.profiles.active = develop +#spring.profiles.active = test #spring.profiles.active = produce # logback diff --git a/src/main/resources/mapper/comment-mapper.xml b/src/main/resources/mapper/comment-mapper.xml index 599cc37..6b0d004 100644 --- a/src/main/resources/mapper/comment-mapper.xml +++ b/src/main/resources/mapper/comment-mapper.xml @@ -28,36 +28,45 @@ - + - + - - select count(id) from comment where status = 0 and post_id = #{postId} + + + diff --git a/src/main/resources/sensitive-words.txt b/src/main/resources/sensitive-words.txt index c2c6872..b1bc98a 100644 --- a/src/main/resources/sensitive-words.txt +++ b/src/main/resources/sensitive-words.txt @@ -18696,19 +18696,9 @@ sm 读不起选个学校三万起 父母下岗儿下地 裙中性运动 - -其它次要的适合于后台审核的敏感词: 自制 制造 制作 -收购 -求购 -电话 -手机 -销售 -联系 -qq -出售 买 卖 匕首 @@ -18757,7 +18747,6 @@ tnt 手机 销售 联系 -qq 出售 买 卖 @@ -20336,8 +20325,6 @@ love—cindy 加v信 加WX 加wx -qq群 -Q群 扣扣 V信群 v信群 @@ -20592,24 +20579,6 @@ jian职 工资每日结算 加我Q 加我QQ -Q1 -Q2 -Q3 -Q4 -Q5 -Q6 -Q7 -Q8 -Q9 -q1 -q2 -q3 -q4 -q5 -q6 -q7 -q8 -q9 监职 监,职 监,职 @@ -21024,70 +20993,14 @@ q9 招-募 招\[募 招\]募 -招【募 -招】募 -招·募 -招:募 -招;募 -招~募 -招_募 -招—募 -q -q, -q。 -q, -q\. -q? -q\? -q\/ -q! -q@ -q# -q¥ -q¥ -q% -q\^ -q& -q\* -q- -q\[ -q\] -q【 -q】 -q· -q: -q; -q~ -q_ -q— -Q -Q, -Q。 -Q, -Q\. -Q? -Q\? -Q\/ -Q! -Q@ -Q# -Q¥ -Q¥ -Q% -Q\^ -Q& -Q\* -Q- -Q\[ -Q\] -Q【 -Q】 -Q· -Q: -Q; -Q~ -Q_ -Q— +招募 +招募 +招募 +招募 +招募 +招募 +招募 +招募 jian职 jian,职 jian。职 -- Gitee From 7ae5ca598d75516b626ab8bfe969d1298d13acd1 Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Mon, 28 Feb 2022 23:52:32 +0800 Subject: [PATCH 061/125] fix some bugs --- .../greate/community/config/SecurityConfig.java | 15 +++++++++++---- .../community/controller/MessageController.java | 2 +- .../com/greate/community/entity/DiscussPost.java | 2 +- .../com/greate/community/event/EventConsumer.java | 6 +++++- .../greate/community/service/MessageService.java | 9 ++++++--- src/main/resources/application-develop.properties | 2 +- src/main/resources/application.properties | 4 ++-- 7 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index eed4722..ec1e5df 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -74,9 +74,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm "/user/header/url", "/user/username", "/user/updateHeader", - "/discuss/add", - "/discuss/publish", - "/comment/add/**", "/letter/**", "/notice/**", "/like", @@ -89,7 +86,17 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm .hasAnyAuthority( AUTHORITY_USER, AUTHORITY_ADMIN, - AUTHORITY_MODERATOR + AUTHORITY_MODERATOR, + AUTHORITY_HUSTER + ) + .antMatchers( + "/discuss/add", + "/comment/add" + ) + .hasAnyAuthority( + AUTHORITY_ADMIN, + AUTHORITY_MODERATOR, + AUTHORITY_HUSTER ) .antMatchers( "/discuss/top", diff --git a/src/main/java/com/greate/community/controller/MessageController.java b/src/main/java/com/greate/community/controller/MessageController.java index 6c861ce..1ba5d53 100644 --- a/src/main/java/com/greate/community/controller/MessageController.java +++ b/src/main/java/com/greate/community/controller/MessageController.java @@ -215,7 +215,7 @@ public class MessageController extends BaseController implements CommunityConsta message.setStatus(0); // 默认就是 0 未读,可不写 message.setCreateTime(new Date()); - messageService.addMessage(message); + messageService.addMessage(message, true); return new Result("success", Result.SUCCESS, "发送成功"); } diff --git a/src/main/java/com/greate/community/entity/DiscussPost.java b/src/main/java/com/greate/community/entity/DiscussPost.java index 0462984..c582c14 100644 --- a/src/main/java/com/greate/community/entity/DiscussPost.java +++ b/src/main/java/com/greate/community/entity/DiscussPost.java @@ -29,7 +29,7 @@ public class DiscussPost { @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart") private String title; - @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart") + @Field(type = FieldType.Text, analyzer = " ik_max_word", searchAnalyzer = "ik_smart") private String content; @Field(type = FieldType.Text) diff --git a/src/main/java/com/greate/community/event/EventConsumer.java b/src/main/java/com/greate/community/event/EventConsumer.java index 79fd7b2..483212a 100644 --- a/src/main/java/com/greate/community/event/EventConsumer.java +++ b/src/main/java/com/greate/community/event/EventConsumer.java @@ -10,6 +10,7 @@ import com.greate.community.service.ExpService; import com.greate.community.service.MessageService; import com.greate.community.util.CommunityConstant; import com.greate.community.util.ExpType; +import com.greate.community.util.SensitiveFilter; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,6 +43,9 @@ public class EventConsumer implements CommunityConstant { @Autowired private ElasticsearchService elasticsearchService; + @Autowired + private SensitiveFilter sensitiveFilter; + /** * 消费评论、点赞、关注事件 * @param record @@ -84,7 +88,7 @@ public class EventConsumer implements CommunityConstant { } message.setContent(JSONObject.toJSONString(content)); - messageService.addMessage(message); + messageService.addMessage(message, false); } diff --git a/src/main/java/com/greate/community/service/MessageService.java b/src/main/java/com/greate/community/service/MessageService.java index 78acb28..6acf7fa 100644 --- a/src/main/java/com/greate/community/service/MessageService.java +++ b/src/main/java/com/greate/community/service/MessageService.java @@ -82,14 +82,17 @@ public class MessageService { /** * 添加一条私信 - * @param message + * @param message 私信内容 + * @param filte 是否进行敏感词过滤 * @return */ - public int addMessage(Message message) { + public int addMessage(Message message, boolean filte) { // 转义 HTML 标签 message.setContent(HtmlUtils.htmlEscape(message.getContent())); // 过滤敏感词 - message.setContent(sensitiveFilter.filter(message.getContent())); + if(filte){ + message.setContent(sensitiveFilter.filter(message.getContent())); + } return messageMapper.insertMessage(message); } diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index 2ad2bf2..d8c54eb 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -59,7 +59,7 @@ elasticsearch.username = elastic elasticsearch.password = elastic2021. elasticsearch.hostname = es-50b9cgrk.public.tencentelasticsearch.com elasticsearch.port = 9200 -elasticsearch.scheme = https +elasticsearch.scheme = http # Quartz spring.quartz.job-store-type = jdbc diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 1cfcf25..a1ee24d 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,6 +1,6 @@ # profile(ʱ develop, ߲ʱǵøij produce) -#spring.profiles.active = develop -spring.profiles.active = test +spring.profiles.active = develop +#spring.profiles.active = test #spring.profiles.active = produce # logback -- Gitee From aa8f6decf9c8851fe294864255db2612a29e8e70 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Tue, 1 Mar 2022 16:34:49 +0800 Subject: [PATCH 062/125] add: get reply list by root id --- .../controller/CommentController.java | 35 ++++++++++++++++++- .../community/quartz/PostScoreRefreshJob.java | 3 -- src/main/resources/application.properties | 1 - 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/greate/community/controller/CommentController.java b/src/main/java/com/greate/community/controller/CommentController.java index 6c14605..e65aa4d 100644 --- a/src/main/java/com/greate/community/controller/CommentController.java +++ b/src/main/java/com/greate/community/controller/CommentController.java @@ -144,8 +144,41 @@ public class CommentController extends BaseController implements CommunityConsta return new Result("success", Result.SUCCESS, page); } + @GetMapping("/reply-list/{rootId}") + public Result findReplyByCommentId(@PathVariable int rootId, Page page) { + page.setPath("/reply-list/" + rootId); + + // 跟评论下回复总数 + page.setRows(commentService.findReplyCount(rootId)); + + // 帖子的评论列表 + List replyList = commentService.findReplyByComment( + rootId, page.getOffset(), page.getLimit()); + + // 封装评论及其相关信息 + List> replyVoList = new ArrayList<>(); + if (replyList != null && !replyList.isEmpty()) { + for (Comment reply : replyList) { + Map commentVo = new HashMap<>(); + commentVo.put("comment", StringListConvertor.toJsonObject(reply, "picUrls")); + commentVo.put("user", userService.findUserById(reply.getUserId())); // 发布评论的作者 + // 当前登录用户对该评论的点赞状态 + int likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( + getUser().getId(), ENTITY_TYPE_COMMENT, reply.getId()); + commentVo.put("likeStatus", likeStatus); + + replyVoList.add(commentVo); + } + } + + JSONArray result = (JSONArray) JSONArray.toJSON(replyVoList); + page.setResult(result); + + return new Result("success", Result.SUCCESS, page); + } + /** - * 删除帖子 + * 删除评论 * * @return */ diff --git a/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java b/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java index 1b64d29..a2c88f9 100644 --- a/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java +++ b/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java @@ -32,9 +32,6 @@ public class PostScoreRefreshJob implements Job, CommunityConstant { @Autowired private DiscussPostService discussPostService; - @Autowired - private LikeService likeService; - @Autowired private ElasticsearchService elasticsearchService; diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a1ee24d..0056a96 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,4 +1,3 @@ -# profile(ʱ develop, ߲ʱǵøij produce) spring.profiles.active = develop #spring.profiles.active = test #spring.profiles.active = produce -- Gitee From 638f7447991732c03bff559b0a6a0ce7f438d756 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Tue, 1 Mar 2022 16:44:41 +0800 Subject: [PATCH 063/125] fix: elastic save post be null --- .../greate/community/event/EventConsumer.java | 19 ++++++++++++------- src/main/resources/application.properties | 4 ++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/greate/community/event/EventConsumer.java b/src/main/java/com/greate/community/event/EventConsumer.java index 483212a..75732b2 100644 --- a/src/main/java/com/greate/community/event/EventConsumer.java +++ b/src/main/java/com/greate/community/event/EventConsumer.java @@ -18,6 +18,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Component; + import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -48,18 +49,19 @@ public class EventConsumer implements CommunityConstant { /** * 消费评论、点赞、关注事件 + * * @param record */ @KafkaListener(topics = {TOPIC_COMMNET, TOPIC_LIKE, TOPIC_FOLLOW}) public void handleMessage(ConsumerRecord record) { if (record == null || record.value() == null) { logger.error("消息的内容为空"); - return ; + return; } Event event = JSONObject.parseObject(record.value().toString(), Event.class); if (event == null) { logger.error("消息格式错误"); - return ; + return; } // 增加经验 @@ -99,12 +101,12 @@ public class EventConsumer implements CommunityConstant { public void handlePublishMessage(ConsumerRecord record) { if (record == null || record.value() == null) { logger.error("消息的内容为空"); - return ; + return; } Event event = JSONObject.parseObject(record.value().toString(), Event.class); if (event == null) { logger.error("消息格式错误"); - return ; + return; } // 增加经验 @@ -112,8 +114,11 @@ public class EventConsumer implements CommunityConstant { // 将帖子转存到elasticsearch DiscussPost post = discussPostService.findDiscussPostById(event.getEntityId()); - elasticsearchService.saveDiscussPost(post); + if (post == null) { + return; + } + elasticsearchService.saveDiscussPost(post); } /** @@ -123,12 +128,12 @@ public class EventConsumer implements CommunityConstant { public void handleDeleteMessage(ConsumerRecord record) { if (record == null || record.value() == null) { logger.error("消息的内容为空"); - return ; + return; } Event event = JSONObject.parseObject(record.value().toString(), Event.class); if (event == null) { logger.error("消息格式错误"); - return ; + return; } elasticsearchService.deleteDiscussPost(event.getEntityId()); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 0056a96..f11f2d7 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,5 @@ -spring.profiles.active = develop -#spring.profiles.active = test +#spring.profiles.active = develop +spring.profiles.active = test #spring.profiles.active = produce # logback -- Gitee From 64220dae479fdfcf9ed0a64503a128ef1835f547 Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Tue, 1 Mar 2022 16:57:05 +0800 Subject: [PATCH 064/125] =?UTF-8?q?es=E4=BF=AE=E5=A4=8D=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0discusspost=E7=B4=A2=E5=BC=95=E6=98=A0=E5=B0=84?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/DiscussPostController.java | 4 ++ .../greate/community/entity/DiscussPost.java | 26 +++++------ .../greate/community/event/EventConsumer.java | 5 --- .../service/ElasticsearchService.java | 10 +++++ .../resources/application-develop.properties | 2 +- src/main/resources/application.properties | 4 +- .../mapping/discusspost-mapping.json | 45 +++++++++++++++++++ 7 files changed, 75 insertions(+), 21 deletions(-) create mode 100644 src/main/resources/mapping/discusspost-mapping.json diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index 41f4c7b..b390711 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -8,6 +8,7 @@ import com.greate.community.event.EventProducer; import com.greate.community.service.*; import com.greate.community.util.*; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; @@ -40,6 +41,9 @@ public class DiscussPostController extends BaseController implements CommunityCo @Autowired private RedisTemplate redisTemplate; + @Autowired + private ElasticsearchRestTemplate elasticsearchRestTemplate; + /** * 添加帖子(发帖) * diff --git a/src/main/java/com/greate/community/entity/DiscussPost.java b/src/main/java/com/greate/community/entity/DiscussPost.java index c582c14..63ee760 100644 --- a/src/main/java/com/greate/community/entity/DiscussPost.java +++ b/src/main/java/com/greate/community/entity/DiscussPost.java @@ -1,13 +1,12 @@ package com.greate.community.entity; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; import lombok.Data; import lombok.ToString; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; +import org.springframework.data.elasticsearch.annotations.Mapping; import java.util.Date; @@ -18,41 +17,42 @@ import java.util.Date; @Data @ToString @Document(indexName = "discusspost") +@Mapping(mappingPath= "mapping/discusspost-mapping.json") public class DiscussPost { @Id private int id; - @Field(type = FieldType.Integer) +// @Field(type = FieldType.Integer) private int userId; - @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart") +// @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart") private String title; - @Field(type = FieldType.Text, analyzer = " ik_max_word", searchAnalyzer = "ik_smart") +// @Field(type = FieldType.Text, analyzer = " ik_max_word", searchAnalyzer = "ik_smart") private String content; - @Field(type = FieldType.Text) +// @Field(type = FieldType.Text) private String picUrls; - @Field(type = FieldType.Integer) +// @Field(type = FieldType.Integer) private int type; - @Field(type = FieldType.Integer) +// @Field(type = FieldType.Integer) private int status; - @Field(type = FieldType.Integer) +// @Field(type = FieldType.Integer) private int viewCount; - @Field(type = FieldType.Integer) +// @Field(type = FieldType.Integer) private int likeCount; - @Field(type = FieldType.Integer) +// @Field(type = FieldType.Integer) private int commentCount; - @Field(type = FieldType.Double) +// @Field(type = FieldType.Double) private double score; - @Field(type = FieldType.Date) +// @Field(type = FieldType.Date) private Date createTime; } diff --git a/src/main/java/com/greate/community/event/EventConsumer.java b/src/main/java/com/greate/community/event/EventConsumer.java index 483212a..406ab73 100644 --- a/src/main/java/com/greate/community/event/EventConsumer.java +++ b/src/main/java/com/greate/community/event/EventConsumer.java @@ -10,12 +10,10 @@ import com.greate.community.service.ExpService; import com.greate.community.service.MessageService; import com.greate.community.util.CommunityConstant; import com.greate.community.util.ExpType; -import com.greate.community.util.SensitiveFilter; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Component; import java.util.Date; @@ -43,9 +41,6 @@ public class EventConsumer implements CommunityConstant { @Autowired private ElasticsearchService elasticsearchService; - @Autowired - private SensitiveFilter sensitiveFilter; - /** * 消费评论、点赞、关注事件 * @param record diff --git a/src/main/java/com/greate/community/service/ElasticsearchService.java b/src/main/java/com/greate/community/service/ElasticsearchService.java index 88e711d..6f754bb 100644 --- a/src/main/java/com/greate/community/service/ElasticsearchService.java +++ b/src/main/java/com/greate/community/service/ElasticsearchService.java @@ -17,6 +17,7 @@ import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.stereotype.Service; +import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.List; @@ -29,6 +30,15 @@ public class ElasticsearchService { @Autowired private ElasticsearchRestTemplate elasticsearchRestTemplate; + @PostConstruct + public void initEs(){ + //初始化es服务器,如果无 discusspost 索引,则创建索引 + if (!elasticsearchRestTemplate.indexOps(DiscussPost.class).exists()) { + elasticsearchRestTemplate.indexOps(DiscussPost.class).create(); + elasticsearchRestTemplate.indexOps(DiscussPost.class).putMapping(); + } + } + /** * 将数据插入 Elasticsearch 服务器 * diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index d8c54eb..2ad2bf2 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -59,7 +59,7 @@ elasticsearch.username = elastic elasticsearch.password = elastic2021. elasticsearch.hostname = es-50b9cgrk.public.tencentelasticsearch.com elasticsearch.port = 9200 -elasticsearch.scheme = http +elasticsearch.scheme = https # Quartz spring.quartz.job-store-type = jdbc diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a1ee24d..1cfcf25 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,6 +1,6 @@ # profile(ʱ develop, ߲ʱǵøij produce) -spring.profiles.active = develop -#spring.profiles.active = test +#spring.profiles.active = develop +spring.profiles.active = test #spring.profiles.active = produce # logback diff --git a/src/main/resources/mapping/discusspost-mapping.json b/src/main/resources/mapping/discusspost-mapping.json new file mode 100644 index 0000000..928b474 --- /dev/null +++ b/src/main/resources/mapping/discusspost-mapping.json @@ -0,0 +1,45 @@ +{ + "properties": { + "id": { + "type": "integer" + }, + "userId": { + "type": "integer" + }, + "title": { + "type": "text", + "analyzer": "ik_max_word", + "search_analyzer": "ik_smart" + }, + "content": { + "type": "text", + "analyzer": "ik_max_word", + "search_analyzer": "ik_smart" + }, + "picUrls": { + "type": "text" + }, + "type": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "viewCount": { + "type": "integer" + }, + "likeCount": { + "type": "integer" + }, + "commentCount": { + "type": "integer" + }, + "score": { + "type": "double" + }, + "createTime": { + "type": "date" + } + } + +} \ No newline at end of file -- Gitee From 319d721f7a195d8058833b548ed40ff752198847 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Thu, 3 Mar 2022 15:23:02 +0800 Subject: [PATCH 065/125] add visitdata --- .../community/config/SecurityConfig.java | 12 ++-- .../community/controller/DataController.java | 9 +-- .../controller/advice/ExceptionAdvice.java | 72 +++++++++---------- .../interceptor/DataInterceptor.java | 4 +- .../greate/community/dao/VisitDataMapper.java | 10 +++ .../greate/community/entity/VisitData.java | 16 +++++ .../filter/AuthenticationTokenFilter.java | 25 +++++-- ...DataService.java => VisitDataService.java} | 18 ++++- .../resources/application-develop.properties | 2 +- src/main/resources/application.properties | 4 +- .../resources/mapper/vistit-data-mapper.xml | 19 +++++ 11 files changed, 129 insertions(+), 62 deletions(-) create mode 100644 src/main/java/com/greate/community/dao/VisitDataMapper.java create mode 100644 src/main/java/com/greate/community/entity/VisitData.java rename src/main/java/com/greate/community/service/{DataService.java => VisitDataService.java} (87%) create mode 100644 src/main/resources/mapper/vistit-data-mapper.xml diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index ec1e5df..a983b66 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -5,9 +5,7 @@ import com.greate.community.auth.wechatauth.wechat.WeChatOAuth2ClientContextFilt import com.greate.community.filter.AuthenticationTokenFilter; import com.greate.community.util.CommunityConstant; import com.greate.community.util.CommunityUtil; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpMethod; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -32,15 +30,16 @@ import java.io.PrintWriter; @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter implements CommunityConstant { - @Autowired - private AuthenticationTokenFilter authenticationTokenFilter; - private final WeChatAuthorizationConfig weChatAuthorizationConfig; private final WeChatOAuth2ClientContextFilter weChatOAuth2ClientContextFilter; + private final AuthenticationTokenFilter authenticationTokenFilter; - public SecurityConfig(WeChatAuthorizationConfig weChatAuthorizationConfig, WeChatOAuth2ClientContextFilter weChatOAuth2ClientContextFilter) { + public SecurityConfig(WeChatAuthorizationConfig weChatAuthorizationConfig, + WeChatOAuth2ClientContextFilter weChatOAuth2ClientContextFilter, + AuthenticationTokenFilter authenticationTokenFilter) { this.weChatAuthorizationConfig = weChatAuthorizationConfig; this.weChatOAuth2ClientContextFilter = weChatOAuth2ClientContextFilter; + this.authenticationTokenFilter = authenticationTokenFilter; } /** @@ -55,7 +54,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm } // 认证环节我们使用自己的代码 LoginController,绕过 Spring Security 的 - /** * 授权 * diff --git a/src/main/java/com/greate/community/controller/DataController.java b/src/main/java/com/greate/community/controller/DataController.java index 1d7ae8f..507a2c3 100644 --- a/src/main/java/com/greate/community/controller/DataController.java +++ b/src/main/java/com/greate/community/controller/DataController.java @@ -1,17 +1,12 @@ package com.greate.community.controller; import com.greate.community.entity.Result; -import com.greate.community.service.DataService; +import com.greate.community.service.VisitDataService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.format.annotation.DateTimeFormat; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; -import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -22,7 +17,7 @@ import java.util.Map; public class DataController { @Autowired - private DataService dataService; + private VisitDataService dataService; /** * 统计网站 uv diff --git a/src/main/java/com/greate/community/controller/advice/ExceptionAdvice.java b/src/main/java/com/greate/community/controller/advice/ExceptionAdvice.java index b8e4b80..e063c30 100644 --- a/src/main/java/com/greate/community/controller/advice/ExceptionAdvice.java +++ b/src/main/java/com/greate/community/controller/advice/ExceptionAdvice.java @@ -1,36 +1,36 @@ -package com.greate.community.controller.advice; - -import com.greate.community.util.CommunityUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestController; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.PrintWriter; - -/** - * 处理服务端异常(500) - */ -@ControllerAdvice(annotations = RestController.class) // 扫描带有 @RestController 的组件 -public class ExceptionAdvice { - - private static final Logger logger = LoggerFactory.getLogger(ExceptionAdvice.class); - - @ExceptionHandler({Exception.class}) - public void handleException(Exception e, HttpServletRequest request, HttpServletResponse response) throws IOException { - logger.error("服务器发生异常:" + e.getMessage()); - for (StackTraceElement element : e.getStackTrace()) { - logger.error(element.toString()); - } - - response.setContentType("application/plain;charset=utf-8"); - PrintWriter writer = response.getWriter(); - writer.write(CommunityUtil.getJSONString(500, "服务器异常: " + e.getMessage())); - } - -} +//package com.greate.community.controller.advice; +// +//import com.greate.community.util.CommunityUtil; +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; +//import org.springframework.stereotype.Controller; +//import org.springframework.web.bind.annotation.ControllerAdvice; +//import org.springframework.web.bind.annotation.ExceptionHandler; +//import org.springframework.web.bind.annotation.RestController; +// +//import javax.servlet.http.HttpServletRequest; +//import javax.servlet.http.HttpServletResponse; +//import java.io.IOException; +//import java.io.PrintWriter; +// +///** +// * 处理服务端异常(500) +// */ +//@ControllerAdvice(annotations = RestController.class) // 扫描带有 @RestController 的组件 +//public class ExceptionAdvice { +// +// private static final Logger logger = LoggerFactory.getLogger(ExceptionAdvice.class); +// +// @ExceptionHandler({Exception.class}) +// public void handleException(Exception e, HttpServletRequest request, HttpServletResponse response) throws IOException { +// logger.error("服务器发生异常:" + e.getMessage()); +// for (StackTraceElement element : e.getStackTrace()) { +// logger.error(element.toString()); +// } +// +// response.setContentType("application/plain;charset=utf-8"); +// PrintWriter writer = response.getWriter(); +// writer.write(CommunityUtil.getJSONString(500, "服务器异常: " + e.getMessage())); +// } +// +//} diff --git a/src/main/java/com/greate/community/controller/interceptor/DataInterceptor.java b/src/main/java/com/greate/community/controller/interceptor/DataInterceptor.java index 0ac5593..1075775 100644 --- a/src/main/java/com/greate/community/controller/interceptor/DataInterceptor.java +++ b/src/main/java/com/greate/community/controller/interceptor/DataInterceptor.java @@ -1,6 +1,6 @@ package com.greate.community.controller.interceptor; -import com.greate.community.service.DataService; +import com.greate.community.service.VisitDataService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; @@ -12,7 +12,7 @@ import javax.servlet.http.HttpServletResponse; public class DataInterceptor implements HandlerInterceptor { @Autowired - private DataService dataService; + private VisitDataService dataService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { diff --git a/src/main/java/com/greate/community/dao/VisitDataMapper.java b/src/main/java/com/greate/community/dao/VisitDataMapper.java new file mode 100644 index 0000000..6c06b2a --- /dev/null +++ b/src/main/java/com/greate/community/dao/VisitDataMapper.java @@ -0,0 +1,10 @@ +package com.greate.community.dao; + +import com.greate.community.entity.VisitData; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface VisitDataMapper { + + int insertVisitData(VisitData visitData); +} diff --git a/src/main/java/com/greate/community/entity/VisitData.java b/src/main/java/com/greate/community/entity/VisitData.java new file mode 100644 index 0000000..584d0f3 --- /dev/null +++ b/src/main/java/com/greate/community/entity/VisitData.java @@ -0,0 +1,16 @@ +package com.greate.community.entity; + +import lombok.Data; + +import java.util.Date; + +@Data +public class VisitData { + + private int id; + private String path; + private String ip; + private int userId; + private Date createTime; + +} diff --git a/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java b/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java index cbee5c8..7b6e8a2 100644 --- a/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java +++ b/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java @@ -1,8 +1,11 @@ package com.greate.community.filter; +import cn.hutool.extra.servlet.ServletUtil; import com.greate.community.entity.LoginTicket; import com.greate.community.entity.User; +import com.greate.community.entity.VisitData; import com.greate.community.service.UserService; +import com.greate.community.service.VisitDataService; import com.greate.community.util.HostHolder; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -32,14 +35,25 @@ import java.util.Date; @Component public class AuthenticationTokenFilter extends OncePerRequestFilter { - @Autowired - private UserService userService; + private final UserService userService; + private final VisitDataService visitDataService; + + public AuthenticationTokenFilter(UserService userService, VisitDataService visitDataService) { + this.userService = userService; + this.visitDataService = visitDataService; + } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String ticket = request.getHeader("ticket"); - log.info("request请求地址: path[{}] uri[{}]", request.getServletPath(),request.getRequestURI()); + log.info("request请求地址: path[{}] uri[{}] ip[{}]", request.getServletPath(), request.getRequestURI(), ServletUtil.getClientIP(request)); log.info("获取ticket: " + ticket); + + VisitData visitData = new VisitData(); + visitData.setPath(request.getServletPath()); + visitData.setIp(ServletUtil.getClientIP(request)); + visitData.setCreateTime(new Date()); + if (ticket != null) { // 查询凭证 LoginTicket loginTicket = userService.findLoginTicket(ticket); @@ -48,7 +62,7 @@ public class AuthenticationTokenFilter extends OncePerRequestFilter { // 根据凭证查询用户 User user = userService.findUserById(loginTicket.getUserId()); log.info("用户会话信息: " + user.toString()); - + visitData.setUserId(user.getId()); // 构建用户认证的结果,并存入 SecurityContext, 以便于 Spring Security 进行授权 Authentication authentication = new UsernamePasswordAuthenticationToken( user, user.getPassword(), userService.getAuthorities(user.getId()) @@ -56,6 +70,9 @@ public class AuthenticationTokenFilter extends OncePerRequestFilter { SecurityContextHolder.setContext(new SecurityContextImpl(authentication)); } } + + visitDataService.addVisitData(visitData); + filterChain.doFilter(request, response); } } diff --git a/src/main/java/com/greate/community/service/DataService.java b/src/main/java/com/greate/community/service/VisitDataService.java similarity index 87% rename from src/main/java/com/greate/community/service/DataService.java rename to src/main/java/com/greate/community/service/VisitDataService.java index a2b47c2..350057e 100644 --- a/src/main/java/com/greate/community/service/DataService.java +++ b/src/main/java/com/greate/community/service/VisitDataService.java @@ -1,5 +1,7 @@ package com.greate.community.service; +import com.greate.community.dao.VisitDataMapper; +import com.greate.community.entity.VisitData; import com.greate.community.util.RedisKeyUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; @@ -19,13 +21,23 @@ import java.util.List; * 网站数据统计(UV / DAU) */ @Service -public class DataService { +public class VisitDataService { - @Autowired - private RedisTemplate redisTemplate; + private final RedisTemplate redisTemplate; + + private final VisitDataMapper visitDataMapper; private SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); + public VisitDataService(RedisTemplate redisTemplate, VisitDataMapper visitDataMapper) { + this.redisTemplate = redisTemplate; + this.visitDataMapper = visitDataMapper; + } + + public void addVisitData(VisitData visitData) { + visitDataMapper.insertVisitData(visitData); + } + /** * 将指定的 IP 计入当天的 UV * diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index d8c54eb..2ad2bf2 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -59,7 +59,7 @@ elasticsearch.username = elastic elasticsearch.password = elastic2021. elasticsearch.hostname = es-50b9cgrk.public.tencentelasticsearch.com elasticsearch.port = 9200 -elasticsearch.scheme = http +elasticsearch.scheme = https # Quartz spring.quartz.job-store-type = jdbc diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f11f2d7..0056a96 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,5 @@ -#spring.profiles.active = develop -spring.profiles.active = test +spring.profiles.active = develop +#spring.profiles.active = test #spring.profiles.active = produce # logback diff --git a/src/main/resources/mapper/vistit-data-mapper.xml b/src/main/resources/mapper/vistit-data-mapper.xml new file mode 100644 index 0000000..61ce808 --- /dev/null +++ b/src/main/resources/mapper/vistit-data-mapper.xml @@ -0,0 +1,19 @@ + + + + + + + path, ip, user_id, create_time + + + + id, path, ip, user_id, create_time + + + + insert into visit_data () + values(#{path}, #{ip}, #{userId}, #{createTime}) + + \ No newline at end of file -- Gitee From 9083489806c41a7ee5ca02119088e31b41cfd8cc Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Thu, 3 Mar 2022 16:57:23 +0800 Subject: [PATCH 066/125] add http trace log filter --- pom.xml | 25 ++-- .../config/HttpTraceConfiguration.java | 23 +++ .../community/controller/UserController.java | 4 - .../community/filter/HttpTraceLogFilter.java | 139 ++++++++++++++++++ .../resources/application-produce.properties | 92 ++++++------ 5 files changed, 217 insertions(+), 66 deletions(-) create mode 100644 src/main/java/com/greate/community/config/HttpTraceConfiguration.java create mode 100644 src/main/java/com/greate/community/filter/HttpTraceLogFilter.java diff --git a/pom.xml b/pom.xml index 9063610..a0fefa2 100644 --- a/pom.xml +++ b/pom.xml @@ -30,12 +30,6 @@ spring-boot-starter-aop - - - - - - org.springframework.boot @@ -106,10 +100,6 @@ - - - - org.springframework.data spring-data-elasticsearch @@ -129,7 +119,7 @@ 2.1.4.RELEASE - + org.thymeleaf.extras thymeleaf-extras-springsecurity5 @@ -148,6 +138,19 @@ spring-boot-starter-quartz + + + org.springframework.boot + spring-boot-starter-actuator + + + + + io.micrometer + micrometer-core + 1.8.3 + + com.qcloud cos-sts_api diff --git a/src/main/java/com/greate/community/config/HttpTraceConfiguration.java b/src/main/java/com/greate/community/config/HttpTraceConfiguration.java new file mode 100644 index 0000000..2902ca9 --- /dev/null +++ b/src/main/java/com/greate/community/config/HttpTraceConfiguration.java @@ -0,0 +1,23 @@ +package com.greate.community.config; + + +import com.greate.community.filter.HttpTraceLogFilter; +import io.micrometer.core.instrument.MeterRegistry; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConditionalOnWebApplication +public class HttpTraceConfiguration { + + @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) + static class ServletTraceFilterConfiguration { + + @Bean + public HttpTraceLogFilter httpTraceLogFilter(MeterRegistry registry) { + return new HttpTraceLogFilter(registry); + } + + } +} diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 2296e89..8f2e980 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -40,10 +40,6 @@ public class UserController extends BaseController implements CommunityConstant @Autowired private CommentService commentService; - // 网站域名 - @Value("${community.path.domain}") - private String domain; - // 项目名(访问路径) @Value("${server.servlet.context-path}") private String contextPath; diff --git a/src/main/java/com/greate/community/filter/HttpTraceLogFilter.java b/src/main/java/com/greate/community/filter/HttpTraceLogFilter.java new file mode 100644 index 0000000..1786605 --- /dev/null +++ b/src/main/java/com/greate/community/filter/HttpTraceLogFilter.java @@ -0,0 +1,139 @@ +package com.greate.community.filter; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import io.micrometer.core.instrument.MeterRegistry; +import lombok.extern.slf4j.Slf4j; +import lombok.var; +import org.springframework.core.Ordered; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.filter.OncePerRequestFilter; +import org.springframework.web.util.ContentCachingRequestWrapper; +import org.springframework.web.util.ContentCachingResponseWrapper; +import org.springframework.web.util.WebUtils; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.time.LocalDateTime; +import java.util.*; + +@Slf4j +public class HttpTraceLogFilter extends OncePerRequestFilter implements Ordered { + + private static final String NEED_TRACE_PATH_PREFIX = "/"; + private static final String IGNORE_CONTENT_TYPE = "multipart/form-data"; + private static final ObjectMapper mapper = new ObjectMapper(); + + private final MeterRegistry registry; + + public HttpTraceLogFilter(MeterRegistry registry) { + this.registry = registry; + } + + @Override + public int getOrder() { + return Ordered.LOWEST_PRECEDENCE - 10; + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + if (!isRequestValid(request)) { + filterChain.doFilter(request, response); + return; + } + ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request); + ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response); + var startTime = LocalDateTime.now(); + try { + filterChain.doFilter(requestWrapper, responseWrapper); + } finally { + String path = request.getRequestURI(); + if (path.startsWith(NEED_TRACE_PATH_PREFIX) && !Objects.equals(IGNORE_CONTENT_TYPE, request.getContentType())) { + //创建一个 json 对象,用来存放 http 日志信息 + ObjectNode rootNode = mapper.createObjectNode(); + rootNode.put("uri", path); + rootNode.put("clientIp", requestWrapper.getRemoteAddr()); + rootNode.put("startTime", startTime.toString()); + rootNode.put("endTime", LocalDateTime.now().toString()); + rootNode.set("requestHeaders", mapper.valueToTree(getRequestHeaders(requestWrapper))); + String method = request.getMethod(); + rootNode.put("method", method); + if ("GET".equals(method)) { + rootNode.set("request", mapper.valueToTree(requestWrapper.getParameterMap())); + } else { + JsonNode newNode = mapper.readTree(requestWrapper.getContentAsByteArray()); + rootNode.set("request", newNode); + } + rootNode.put("httpStatus", responseWrapper.getStatusCode()); + try { + JsonNode newNode = mapper.readTree(responseWrapper.getContentAsByteArray()); + rootNode.set("response", newNode); + } catch (Exception e) { + rootNode.put("response", new String(responseWrapper.getContentAsByteArray())); + } + responseWrapper.copyBodyToResponse(); + rootNode.set("responseHeaders", mapper.valueToTree(getResponseHeaders(responseWrapper))); + log.info(rootNode.toString()); + } + } + updateResponse(responseWrapper); + } + + private boolean isRequestValid(HttpServletRequest request) { + try { + new URI(request.getRequestURL().toString()); + return true; + } catch (URISyntaxException ex) { + return false; + } + } + + /** + * 组装请求参数 + * + * @param request + * @return + */ + private Map getRequestHeaders(HttpServletRequest request) { + Map headers = new HashMap<>(); + Enumeration headerNames = request.getHeaderNames(); + while (headerNames.hasMoreElements()) { + String headerName = headerNames.nextElement(); + headers.put(headerName, request.getHeader(headerName)); + } + return headers; + + } + + /** + * 组装返回参数 + * + * @param response + * @return + */ + private Map getResponseHeaders(ContentCachingResponseWrapper response) { + Map headers = new HashMap<>(); + Collection headerNames = response.getHeaderNames(); + for (String headerName : headerNames) { + headers.put(headerName, response.getHeader(headerName)); + } + return headers; + } + + /** + * 还原返回 + * + * @param response + * @throws IOException + */ + private void updateResponse(HttpServletResponse response) throws IOException { + ContentCachingResponseWrapper responseWrapper = WebUtils.getNativeResponse(response, ContentCachingResponseWrapper.class); + Objects.requireNonNull(responseWrapper).copyBodyToResponse(); + } +} diff --git a/src/main/resources/application-produce.properties b/src/main/resources/application-produce.properties index c4257af..30334c1 100644 --- a/src/main/resources/application-produce.properties +++ b/src/main/resources/application-produce.properties @@ -1,75 +1,65 @@ # ˿ -server.port = 8080 +server.port=8080 # Ŀ(Ŀ·) http://localhost:8080/...... -server.servlet.context-path = - -# վ -community.path.domain = http://1.15.127.74 - +server.servlet.context-path= +# spring actuator +management.endpoints.web.exposure.include=httptrace: httptrace +management.endpoint.health.show-details=always # Thymeleaf spring.thymeleaf.cache=true - # MySQL -spring.datasource.url = jdbc:mysql://127.0.0.1:3306/bbs?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong -spring.datasource.username = root -spring.datasource.password = root +spring.datasource.url=jdbc:mysql://127.0.0.1:3306/bbs?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong +spring.datasource.username=root +spring.datasource.password=root # Mysql 5.0+ 汾ʹ com.mysql.jdbc.Driver # 8.0+ İ汾ij com.mysql.cj.jdbc.Driver -spring.datasource.driver-class-name = com.mysql.jdbc.Driver - +spring.datasource.driver-class-name=com.mysql.jdbc.Driver # Mybatis -mybatis.mapper-locations = classpath:mapper/*.xml -mybatis.type-aliases-package = com.greate.community.entity -mybatis.configuration.useGeneratedKeys = true -mybatis.configuration.mapUnderscoreToCamelCase = true - +mybatis.mapper-locations=classpath:mapper/*.xml +mybatis.type-aliases-package=com.greate.community.entity +mybatis.configuration.useGeneratedKeys=true +mybatis.configuration.mapUnderscoreToCamelCase=true # Spring Mail -spring.mail.host = smtp.qq.com -spring.mail.username = csuxiaoxi@qq.com +spring.mail.host=smtp.qq.com +spring.mail.username=csuxiaoxi@qq.com spring.mail.personal=CSUer -spring.mail.password = scsmtmeogsgddcdg -spring.mail.protocol = smtps -spring.mail.properties.mail.smtp.ssl.enable = true +spring.mail.password=scsmtmeogsgddcdg +spring.mail.protocol=smtps +spring.mail.properties.mail.smtp.ssl.enable=true # ??????????????????? spring.mail.code-expiration=3600000 spring.mail.reg-header=Register spring.mail.forget-password-header=Register - # Redis -spring.redis.database = 1 -spring.redis.host = localhost -spring.redis.port = 6379 - +spring.redis.database=1 +spring.redis.host=localhost +spring.redis.port=6379 # Kafka -spring.kafka.bootstrap-servers = localhost:9092 +spring.kafka.bootstrap-servers=localhost:9092 # ֶμ Kafka װе consumer.proerties޸, ޸ϺҪ Kafka -spring.kafka.consumer.group-id = produce-consumer-group -spring.kafka.consumer.enable-auto-commit = true -spring.kafka.consumer.auto-commit-interval = 3000 - +spring.kafka.consumer.group-id=produce-consumer-group +spring.kafka.consumer.enable-auto-commit=true +spring.kafka.consumer.auto-commit-interval=3000 # Elasticsearch # ֶμ Elasticsearch װе elasticsearch.yml޸ -spring.data.elasticsearch.cluster-name = community -spring.data.elasticsearch.cluster-nodes = 127.0.0.1:9300 - +spring.data.elasticsearch.cluster-name=community +spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300 # Quartz -spring.quartz.job-store-type = jdbc -spring.quartz.scheduler-name = communityScheduler -spring.quartz.properties.org.quartz.scheduler.instanceId = AUTO -spring.quartz.properties.org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX -spring.quartz.properties.org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate -spring.quartz.properties.org.quartz.jobStore.isClustered = true -spring.quartz.properties.org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool -spring.quartz.properties.org.quartz.threadPool.threadCount = 5 - +spring.quartz.job-store-type=jdbc +spring.quartz.scheduler-name=communityScheduler +spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO +spring.quartz.properties.org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX +spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate +spring.quartz.properties.org.quartz.jobStore.isClustered=true +spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool +spring.quartz.properties.org.quartz.threadPool.threadCount=5 # qiniu -qiniu.key.access = xxxxxxxxxxxxxxx -qiniu.key.secret = xxxxxxxxxxxxxxx -qiniu.bucket.header.name = header--community -qiniu.bucket.header.url = http://qnvxyvq1p.hd-bkt.clouddn.com - +qiniu.key.access=xxxxxxxxxxxxxxx +qiniu.key.secret=xxxxxxxxxxxxxxx +qiniu.bucket.header.name=header--community +qiniu.bucket.header.url=http://qnvxyvq1p.hd-bkt.clouddn.com # Caffeine -caffeine.posts.max-size = 15 -caffeine.posts.expire-seconds = 180 +caffeine.posts.max-size=15 +caffeine.posts.expire-seconds=180 -- Gitee From 7d5ae45c8ad06ea4bf715f8c1c972cf16b1fad05 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Fri, 4 Mar 2022 14:42:25 +0800 Subject: [PATCH 067/125] update add exp by kafka --- pom.xml | 17 ++++--- .../controller/CommentController.java | 7 +++ .../controller/DiscussPostController.java | 17 +++++-- .../community/controller/LikeController.java | 13 +++-- .../community/controller/LoginController.java | 19 ++++--- .../greate/community/event/EventConsumer.java | 51 +++++++++++++------ .../community/filter/HttpTraceLogFilter.java | 1 - .../community/util/CommunityConstant.java | 3 ++ 8 files changed, 89 insertions(+), 39 deletions(-) diff --git a/pom.xml b/pom.xml index a0fefa2..fce4d14 100644 --- a/pom.xml +++ b/pom.xml @@ -112,20 +112,14 @@ spring-boot-starter-security - + org.springframework.security.oauth.boot spring-security-oauth2-autoconfigure 2.1.4.RELEASE - - - org.thymeleaf.extras - thymeleaf-extras-springsecurity5 - - - + com.alibaba fastjson @@ -142,6 +136,13 @@ org.springframework.boot spring-boot-starter-actuator + + + + io.micrometer + micrometer-core + + diff --git a/src/main/java/com/greate/community/controller/CommentController.java b/src/main/java/com/greate/community/controller/CommentController.java index e65aa4d..0871b85 100644 --- a/src/main/java/com/greate/community/controller/CommentController.java +++ b/src/main/java/com/greate/community/controller/CommentController.java @@ -71,6 +71,13 @@ public class CommentController extends BaseController implements CommunityConsta eventProducer.fireEvent(event); } + // 触发增加经验事件 + Event expEvent = new Event() + .setTopic(TOPIC_EXP) + .setUserId(getUser().getId()) + .setData("type", ExpType.EXP_COMMENT.getName()); + eventProducer.fireEvent(expEvent); + // if (comment.getRootId() == 0) { // // 触发发帖事件,通过消息队列将其存入 Elasticsearch 服务器 // Event event = new Event() diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index b390711..150d471 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -85,12 +85,19 @@ public class DiscussPostController extends BaseController implements CommunityCo discussPostService.addDiscussPost(discussPost); // 触发发帖事件,通过消息队列将其存入 Elasticsearch 服务器 - Event event = new Event() + Event publishEvent = new Event() .setTopic(TOPIC_PUBLISH) .setUserId(user.getId()) .setEntityType(ENTITY_TYPE_POST) .setEntityId(discussPost.getId()); - eventProducer.fireEvent(event); + eventProducer.fireEvent(publishEvent); + + // 触发增加经验事件 + Event expEvent = new Event() + .setTopic(TOPIC_EXP) + .setUserId(getUser().getId()) + .setData("type", ExpType.EXP_PUBLISH.getName()); + eventProducer.fireEvent(expEvent); // 计算帖子分数 String redisKey = RedisKeyUtil.getPostScoreKey(); @@ -132,7 +139,11 @@ public class DiscussPostController extends BaseController implements CommunityCo // 增加浏览帖子经验 if (getUser() != null) { - expService.handleGetExp(getUser().getId(), ExpType.EXP_BROWSE.getName()); + Event event = new Event() + .setTopic(TOPIC_EXP) + .setUserId(getUser().getId()) + .setData("type", ExpType.EXP_BROWSE.getName()); + eventProducer.fireEvent(event); } // 增加帖子浏览量 diff --git a/src/main/java/com/greate/community/controller/LikeController.java b/src/main/java/com/greate/community/controller/LikeController.java index 807f062..4fc8746 100644 --- a/src/main/java/com/greate/community/controller/LikeController.java +++ b/src/main/java/com/greate/community/controller/LikeController.java @@ -5,10 +5,7 @@ import com.greate.community.entity.Result; import com.greate.community.entity.User; import com.greate.community.event.EventProducer; import com.greate.community.service.LikeService; -import com.greate.community.util.CommunityConstant; -import com.greate.community.util.CommunityUtil; -import com.greate.community.util.HostHolder; -import com.greate.community.util.RedisKeyUtil; +import com.greate.community.util.*; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; @@ -20,6 +17,7 @@ import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.Map; +import java.util.Objects; /** * 点赞 @@ -79,6 +77,13 @@ public class LikeController extends BaseController implements CommunityConstant redisTemplate.opsForSet().add(userIdOfLikeKey, user.getId()); } + // 触发增加经验事件 + Event event = new Event() + .setTopic(TOPIC_EXP) + .setUserId(user.getId()) + .setData("type", ExpType.EXP_LIKE.getName()); + eventProducer.fireEvent(event); + if (entityType == ENTITY_TYPE_POST) { // 计算帖子分数 String redisKey = RedisKeyUtil.getPostScoreKey(); diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index 0c34c87..754c493 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -6,9 +6,11 @@ import cn.hutool.core.lang.UUID; import com.alibaba.fastjson.JSONObject; import com.greate.community.auth.wechatauth.domain.UserWeChat; import com.greate.community.dao.UserMapper; +import com.greate.community.entity.Event; import com.greate.community.entity.LoginTicket; import com.greate.community.entity.Result; import com.greate.community.entity.User; +import com.greate.community.event.EventProducer; import com.greate.community.service.ExpService; import com.greate.community.service.UserService; import com.greate.community.util.CommunityConstant; @@ -44,17 +46,14 @@ public class LoginController extends BaseController implements CommunityConstant @Autowired private UserService userService; - @Autowired - private ExpService expService; - @Autowired private UserMapper userMapper; @Autowired private RedisTemplate redisTemplate; - @Value("${server.servlet.context-path}") - private String contextPath; + @Autowired + private EventProducer eventProducer; @Value("${bbs.captcha-enable}") private boolean captchaEnable; @@ -174,8 +173,14 @@ public class LoginController extends BaseController implements CommunityConstant Map map = userService.login(username, password, expiredSeconds); if (map.containsKey("ticket")) { String ticket = map.get("ticket").toString(); - // 增加经验 - expService.handleGetExp(Integer.parseInt(map.get("userId").toString()), ExpType.EXP_LOGIN.getName()); + + // 触发增加经验事件 + Event event = new Event() + .setTopic(TOPIC_EXP) + .setUserId(Integer.parseInt(map.get("userId").toString())) + .setData("type", ExpType.EXP_LOGIN.getName()); + eventProducer.fireEvent(event); + return new Result("success", Result.SUCCESS, ticket); } else { return new Result("fail", "2", map); diff --git a/src/main/java/com/greate/community/event/EventConsumer.java b/src/main/java/com/greate/community/event/EventConsumer.java index 4b5ab7e..b2c1c96 100644 --- a/src/main/java/com/greate/community/event/EventConsumer.java +++ b/src/main/java/com/greate/community/event/EventConsumer.java @@ -30,17 +30,27 @@ public class EventConsumer implements CommunityConstant { private static final Logger logger = LoggerFactory.getLogger(EventConsumer.class); - @Autowired - private MessageService messageService; + private final MessageService messageService; - @Autowired - private ExpService expService; + private final ExpService expService; - @Autowired - private DiscussPostService discussPostService; + private final DiscussPostService discussPostService; - @Autowired - private ElasticsearchService elasticsearchService; + private final ElasticsearchService elasticsearchService; + + private final EventProducer eventProducer; + + public EventConsumer(MessageService messageService, + ExpService expService, + DiscussPostService discussPostService, + ElasticsearchService elasticsearchService, + EventProducer eventProducer) { + this.messageService = messageService; + this.expService = expService; + this.discussPostService = discussPostService; + this.elasticsearchService = elasticsearchService; + this.eventProducer = eventProducer; + } /** * 消费评论、点赞、关注事件 @@ -59,14 +69,6 @@ public class EventConsumer implements CommunityConstant { return; } - // 增加经验 - if (Objects.equals(event.getTopic(), TOPIC_LIKE)) { - expService.handleGetExp(event.getUserId(), ExpType.EXP_LIKE.getName()); - } - if (Objects.equals(event.getTopic(), TOPIC_COMMNET)) { - expService.handleGetExp(event.getUserId(), ExpType.EXP_COMMENT.getName()); - } - // 发送系统通知 Message message = new Message(); message.setFromId(SYSTEM_USER_ID); @@ -135,4 +137,21 @@ public class EventConsumer implements CommunityConstant { } + /** + * 消费加经验事件 + */ + @KafkaListener(topics = {TOPIC_EXP}) + public void handleAddExp(ConsumerRecord record) { + if (record == null || record.value() == null) { + logger.error("消息的内容为空"); + return; + } + Event event = JSONObject.parseObject(record.value().toString(), Event.class); + if (event == null) { + logger.error("消息格式错误"); + return; + } + + expService.handleGetExp(event.getUserId(), (String) event.getData().get("type")); + } } diff --git a/src/main/java/com/greate/community/filter/HttpTraceLogFilter.java b/src/main/java/com/greate/community/filter/HttpTraceLogFilter.java index 1786605..1d2e455 100644 --- a/src/main/java/com/greate/community/filter/HttpTraceLogFilter.java +++ b/src/main/java/com/greate/community/filter/HttpTraceLogFilter.java @@ -7,7 +7,6 @@ import io.micrometer.core.instrument.MeterRegistry; import lombok.extern.slf4j.Slf4j; import lombok.var; import org.springframework.core.Ordered; -import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.util.ContentCachingRequestWrapper; import org.springframework.web.util.ContentCachingResponseWrapper; diff --git a/src/main/java/com/greate/community/util/CommunityConstant.java b/src/main/java/com/greate/community/util/CommunityConstant.java index 96b760c..6215864 100644 --- a/src/main/java/com/greate/community/util/CommunityConstant.java +++ b/src/main/java/com/greate/community/util/CommunityConstant.java @@ -46,6 +46,9 @@ public interface CommunityConstant { // Kafka 主题:删帖 String TOPIC_DELETE = "delete"; + // Kafka 主题:增加经验 + String TOPIC_EXP = "exp"; + // 系统用户的 id int SYSTEM_USER_ID = 1; -- Gitee From 3bc10173ed65c9e1dc589a0a17fa7e89746e8e98 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Fri, 4 Mar 2022 16:52:18 +0800 Subject: [PATCH 068/125] delete some logs --- .../greate/community/config/WebMvcConfig.java | 68 +++--- .../greate/community/service/ExpService.java | 23 +- .../community/service/FollowService.java | 196 ++---------------- .../greate/community/service/LikeService.java | 12 +- 4 files changed, 73 insertions(+), 226 deletions(-) diff --git a/src/main/java/com/greate/community/config/WebMvcConfig.java b/src/main/java/com/greate/community/config/WebMvcConfig.java index cae98fc..19fc9f7 100644 --- a/src/main/java/com/greate/community/config/WebMvcConfig.java +++ b/src/main/java/com/greate/community/config/WebMvcConfig.java @@ -1,34 +1,34 @@ -package com.greate.community.config; - -import com.greate.community.controller.interceptor.DataInterceptor; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -/** - * 拦截器配置类 - */ -@Configuration -public class WebMvcConfig implements WebMvcConfigurer { - - @Autowired - private DataInterceptor dataInterceptor; - - // 对除静态资源外所有路径进行拦截 - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(dataInterceptor) - .excludePathPatterns("/css/**", "/js/**", "/img/**", "/editor-md/**", "/editor-md-upload/**"); - } - - // 配置虚拟路径映射访问 - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry){ - // System.getProperty("user.dir") 获取程序的当前路径 - String path = System.getProperty("user.dir")+"\\src\\main\\resources\\static\\editor-md-upload\\"; - registry.addResourceHandler("/editor-md-upload/**").addResourceLocations("file:" + path); - } - -} +//package com.greate.community.config; +// +//import com.greate.community.controller.interceptor.DataInterceptor; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +//import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +// +///** +// * 拦截器配置类 +// */ +//@Configuration +//public class WebMvcConfig implements WebMvcConfigurer { +// +// @Autowired +// private DataInterceptor dataInterceptor; +// +// // 对除静态资源外所有路径进行拦截 +// @Override +// public void addInterceptors(InterceptorRegistry registry) { +// registry.addInterceptor(dataInterceptor) +// .excludePathPatterns("/css/**", "/js/**", "/img/**", "/editor-md/**", "/editor-md-upload/**"); +// } +// +// // 配置虚拟路径映射访问 +// @Override +// public void addResourceHandlers(ResourceHandlerRegistry registry){ +// // System.getProperty("user.dir") 获取程序的当前路径 +// String path = System.getProperty("user.dir")+"\\src\\main\\resources\\static\\editor-md-upload\\"; +// registry.addResourceHandler("/editor-md-upload/**").addResourceLocations("file:" + path); +// } +// +//} diff --git a/src/main/java/com/greate/community/service/ExpService.java b/src/main/java/com/greate/community/service/ExpService.java index fed500a..257d015 100644 --- a/src/main/java/com/greate/community/service/ExpService.java +++ b/src/main/java/com/greate/community/service/ExpService.java @@ -7,6 +7,9 @@ import com.greate.community.util.ExpType; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Isolation; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; import java.text.SimpleDateFormat; import java.util.Calendar; @@ -33,18 +36,19 @@ public class ExpService { private final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); - public int handleGetExp(int userId, String type) { + @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED) + public void handleGetExp(int userId, String type) { int exp_count = 0; // 未实名无法获得经验值 User user = userService.findUserById(userId); if (user == null || user.getAuditStatus() != 2) { - return 0; + return; } // 经验值不符合类型 ExpType expType = ExpType.resolve(type); if (expType == null) { - return 0; + return; } Calendar calendar = Calendar.getInstance(); @@ -60,7 +64,6 @@ public class ExpService { } // 得到了经验值,记录本次经验值,并更新用户exp和rank - // todo: 需要做事务处理 if (exp_count > 0) { // 记录本次经验值 Exp exp = new Exp(); @@ -68,15 +71,15 @@ public class ExpService { exp.setType(type); exp.setUserId(userId); exp.setCreateTime(today); - expMapper.insertExp(exp); + int result = expMapper.insertExp(exp); // 更新用户exp和rank - int newExp = user.getExp() + exp_count; - int newLevel = ExpType.getLevel(newExp); - userService.updateExpAndLevel(userId, newExp, newLevel); + if (result == 1) { + int newExp = user.getExp() + exp_count; + int newLevel = ExpType.getLevel(newExp); + userService.updateExpAndLevel(userId, newExp, newLevel); + } } - - return exp_count; } public List getExpPageByUserId(int userId, int offset, int limit) { diff --git a/src/main/java/com/greate/community/service/FollowService.java b/src/main/java/com/greate/community/service/FollowService.java index eabc687..64f4de9 100644 --- a/src/main/java/com/greate/community/service/FollowService.java +++ b/src/main/java/com/greate/community/service/FollowService.java @@ -34,40 +34,17 @@ public class FollowService implements CommunityConstant { /** * 关注或取关 * - * @param userId 执行操作的用户id + * @param userId 执行操作的用户id * @param entityType 关注的实体类型,3-用户 - * @param entityId 关注的实体id + * @param entityId 关注的实体id */ public void followOrUnfollow(int userId, int entityType, int entityId) { -// redisTemplate.execute(new SessionCallback() { -// @Override -// public Object execute(RedisOperations redisOperations) throws DataAccessException { -// // 生成 Redis 的 key -// String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); -// String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId); -// -// // 开启事务管理 -// redisOperations.multi(); -// -// // 插入数据 -// redisOperations.opsForZSet().add(followeeKey, entityId, System.currentTimeMillis()); -// redisOperations.opsForZSet().add(followerKey, userId, System.currentTimeMillis()); -// -// // 提交事务 -// return redisOperations.exec(); -// } -// }); - - // 判断用户是否已经关注该实体类型的实体id -// int followStatus = findEntityFollowStatus(userId, entityType, entityId); - log.info("followOrUnfollow 方法执行"); boolean hasFollowed = hasFollowed(userId, entityType, entityId); //先对mysql进行处理 if (hasFollowed) { // 如果用户已经关注该实体,点第二次则取消关注 followMapper.deleteFollowByUserIdAndEntity(userId, entityType, entityId); - log.info("用户已关注该实体,执行取关操作,删除 mysql 记录"); } else { Follow follow = new Follow(); follow.setUserId(userId); @@ -75,7 +52,6 @@ public class FollowService implements CommunityConstant { follow.setEntityId(entityId); follow.setCreateTime(new Date()); followMapper.insertFollow(follow); - log.info("用户尚未关注该实体,执行关注操作,插入 mysql 记录"); } //再对redis进行处理 @@ -91,81 +67,19 @@ public class FollowService implements CommunityConstant { if (hasFollowed) { // 如果用户已经关注该实体,点第二次则取消关注 // 删除数据 - log.info("用户已关注该实体,执行取关操作,删除 redis 记录"); redisOperations.opsForZSet().remove(followeeKey, entityId); redisOperations.opsForZSet().remove(followerKey, userId); } else { // 插入数据 - log.info("用户尚未关注该实体,执行关注操作,插入 redis 记录"); long currentTimeMillis = System.currentTimeMillis(); redisOperations.opsForZSet().add(followeeKey, entityId, currentTimeMillis); redisOperations.opsForZSet().add(followerKey, userId, currentTimeMillis); } - return redisOperations.exec(); // 提交事务 } }); - } -// /** -// * 查询某个用户是否已经关注该实体类型的实体id -// * -// * @param userId -// * @param entityType -// * @param entityId -// * @return 1:已关注,0:未关注 -// */ -// public int findEntityFollowStatus(int userId, int entityType, int entityId){ -// int followStatus = 0; -// // 查询 redis -// String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); -// followStatus = redisTemplate.opsForZSet().score(followeeKey, entityId) != null ? 1 : 0; -// -// if (followStatus == 0) { -// // mysql 中找 -// followStatus = followMapper.countByUserIdAndEntity(userId, entityType, entityId)> 0 ? 1 : 0; -// -// // 找到了之后存入 redis -// if (followStatus == 1) { -// redisTemplate.opsForZSet().add(followeeKey, entityId, System.currentTimeMillis()); -// } -// } -// return followStatus; -// } - - - - - -// /** -// * 取消关注 -// * -// * @param userId -// * @param entityType -// * @param entityId -// */ -// public void unfollow(int userId, int entityType, int entityId) { -// redisTemplate.execute(new SessionCallback() { -// @Override -// public Object execute(RedisOperations redisOperations) throws DataAccessException { -// // 生成 Redis 的 key -// String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); -// String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId); -// -// // 开启事务管理 -// redisOperations.multi(); -// -// // 删除数据 -// redisOperations.opsForZSet().remove(followeeKey, entityId); -// redisOperations.opsForZSet().remove(followerKey, userId); -// -// // 提交事务 -// return redisOperations.exec(); -// } -// }); -// } - /** * 查询某个用户关注的某类型实体的数量 * @@ -174,10 +88,6 @@ public class FollowService implements CommunityConstant { * @return */ public long findFolloweeCount(int userId, int entityType) { -// String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); -// return redisTemplate.opsForZSet().zCard(followeeKey); - - log.info("findFolloweeCount 方法执行"); String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); long count = 0; @@ -185,16 +95,13 @@ public class FollowService implements CommunityConstant { // 先在 redis 中查询 Long num = redisTemplate.opsForZSet().zCard(followeeKey); count = num == null ? 0 : num; - log.info("redis 中查询,count=" + count); } else { // redis中没有,则在 mysql 中查询 List followeeList = followMapper.selectRowsByUserIdAndEntityType(userId, entityType); count = followeeList.size(); - log.info("mysql 中查询,count=" + count); // 找到了之后存入 redis - for(Follow follow : followeeList){ + for (Follow follow : followeeList) { redisTemplate.opsForZSet().add(followeeKey, follow.getEntityId(), follow.getCreateTime().getTime()); - log.info("存入 redis --> "+follow.toString()); } } return count; @@ -208,10 +115,6 @@ public class FollowService implements CommunityConstant { * @return */ public long findFollowerCount(int entityType, int entityId) { -// String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId); -// return redisTemplate.opsForZSet().zCard(followerKey); - - log.info("findFollowerCount 方法执行"); String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId); long count = 0; @@ -219,16 +122,13 @@ public class FollowService implements CommunityConstant { // 先在 redis 中查询 Long num = redisTemplate.opsForZSet().zCard(followerKey); count = num == null ? 0 : num; - log.info("redis 中查询,count=" + count); } else { // redis中没有,则在 mysql 中查询 - List followerList = followMapper.selectRowsByEntityTypeAndEntityId(entityType,entityId); + List followerList = followMapper.selectRowsByEntityTypeAndEntityId(entityType, entityId); count = followerList.size(); - log.info("mysql 中查询,count=" + count); // 找到了之后存入 redis - for(Follow follow : followerList){ + for (Follow follow : followerList) { redisTemplate.opsForZSet().add(followerKey, follow.getUserId(), follow.getCreateTime().getTime()); - log.info("存入 redis --> "+follow.toString()); } } return count; @@ -243,25 +143,18 @@ public class FollowService implements CommunityConstant { * @return */ public boolean hasFollowed(int userId, int entityType, int entityId) { -// String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); -// return redisTemplate.opsForZSet().score(followeeKey, entityId) != null; - - log.info("hasFollowed 方法执行"); String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); boolean hasFollowed = false; if (redisTemplate.hasKey(followeeKey)) { // 先在 redis 中查询 hasFollowed = redisTemplate.opsForZSet().score(followeeKey, entityId) != null; - log.info("redis 中查询,hasFollowed="+hasFollowed); } else { // redis中没有,则在 mysql 中查询 Date createTime = followMapper.selectByUserIdAndEntity(userId, entityType, entityId); - log.info("mysql 中查询,createTime="+createTime); - if(createTime != null){ + if (createTime != null) { hasFollowed = true; // 找到了之后存入 redis redisTemplate.opsForZSet().add(followeeKey, entityId, createTime.getTime()); - log.info("存入 redis"); } } @@ -276,8 +169,7 @@ public class FollowService implements CommunityConstant { * @param entityId * @return */ - public Date findFollowTime(int userId, int entityType, int entityId){ - log.info("findFollowTime 方法执行"); + public Date findFollowTime(int userId, int entityType, int entityId) { String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType); Date followTime = null; @@ -285,14 +177,12 @@ public class FollowService implements CommunityConstant { // 先在 redis 中查询 Double score = redisTemplate.opsForZSet().score(followeeKey, entityId); followTime = new Date(score.longValue()); - log.info("redis 中查询"); - }else { + } else { // redis中没有,则在 mysql 中查询 Date createTime = followMapper.selectByUserIdAndEntity(userId, entityType, entityId); - if (createTime != null){ + if (createTime != null) { followTime = createTime; } - log.info("mysql 中查询"); } return followTime; } @@ -306,39 +196,17 @@ public class FollowService implements CommunityConstant { * @return */ public List> findFollowees(int userId, int offset, int limit) { -// String followeeKey = RedisKeyUtil.getFolloweeKey(userId, ENTITY_TYPE_USER); -// Set targetIds = redisTemplate.opsForZSet().reverseRange(followeeKey, offset, offset + limit - 1); -// if (targetIds == null) { -// return null; -// } -// List> list = new ArrayList<>(); -// for (Integer targetId : targetIds) { -// Map map = new HashMap<>(); -// -// User user = userService.findUserById(targetId); -// map.put("user", user); -// Double score = redisTemplate.opsForZSet().score(followeeKey, targetId); -// map.put("followTime", new Date(score.longValue())); -// -// list.add(map); -// } -// -// return list; - - log.info("findFollowees 方法执行"); String followeeKey = RedisKeyUtil.getFolloweeKey(userId, ENTITY_TYPE_USER); //先查 redis Set targetIds = redisTemplate.opsForZSet().reverseRange(followeeKey, offset, offset + limit - 1); if (targetIds == null) { // redis 中没有,查 mysql - List followeeUsers = followMapper.selectFolloweeUsers(userId, offset, limit); - log.info("redis 中没有,查 mysql"); - if(followeeUsers.size() == 0){ + List followeeUsers = followMapper.selectFolloweeUsers(userId, offset, limit); + if (followeeUsers.size() == 0) { return null; - } - else { + } else { List> list = new ArrayList<>(); - for(User user:followeeUsers){ + for (User user : followeeUsers) { Map map = new HashMap<>(); map.put("user", user); Date followTime = findFollowTime(userId, ENTITY_TYPE_USER, user.getId()); @@ -347,9 +215,8 @@ public class FollowService implements CommunityConstant { } return list; } - }else { + } else { // redis 中有,则直接查 redis - log.info("redis 中有,则直接查 redis"); List> list = new ArrayList<>(); for (Integer targetId : targetIds) { Map map = new HashMap<>(); @@ -362,6 +229,7 @@ public class FollowService implements CommunityConstant { return list; } } + /** * 分页查询某个用户的粉丝(偷个懒,此处没有做对其他实体的粉丝) * @@ -371,40 +239,17 @@ public class FollowService implements CommunityConstant { * @return */ public List> findFollowers(int userId, int offset, int limit) { -// String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER, userId); -// Set targetIds = redisTemplate.opsForZSet().reverseRange(followerKey, offset, offset + limit - 1); -// if (targetIds == null) { -// return null; -// } -// List> list = new ArrayList<>(); -// for (Integer targetId : targetIds) { -// Map map = new HashMap<>(); -// -// User user = userService.findUserById(targetId); -// map.put("user", user); -// Double score = redisTemplate.opsForZSet().score(followerKey, targetId); -// map.put("followTime", new Date(score.longValue())); -// -// list.add(map); -// } -// -// return list; - - log.info("findFollowers 方法执行"); String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER, userId); //先查 redis Set targetIds = redisTemplate.opsForZSet().reverseRange(followerKey, offset, offset + limit - 1); if (targetIds == null) { // redis 中没有,查 mysql - List followerUsers = followMapper.selectFollowerUsers(userId, offset, limit); - log.info("redis 中没有,查 mysql"); - - if(followerUsers.size() == 0){ + List followerUsers = followMapper.selectFollowerUsers(userId, offset, limit); + if (followerUsers.size() == 0) { return null; - } - else { + } else { List> list = new ArrayList<>(); - for(User user:followerUsers){ + for (User user : followerUsers) { Map map = new HashMap<>(); map.put("user", user); // Date followTime = findFollowTime(userId, ENTITY_TYPE_USER, user.getId()); @@ -414,9 +259,8 @@ public class FollowService implements CommunityConstant { } return list; } - }else { + } else { // redis 中有,则直接查 redis - log.info("redis 中有,则直接查 redis"); List> list = new ArrayList<>(); for (Integer targetId : targetIds) { Map map = new HashMap<>(); diff --git a/src/main/java/com/greate/community/service/LikeService.java b/src/main/java/com/greate/community/service/LikeService.java index 096e968..f07d556 100644 --- a/src/main/java/com/greate/community/service/LikeService.java +++ b/src/main/java/com/greate/community/service/LikeService.java @@ -11,6 +11,9 @@ import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.SessionCallback; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Isolation; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; import java.util.Date; @@ -20,9 +23,6 @@ import java.util.Date; @Service public class LikeService implements CommunityConstant { - @Autowired - private RedisTemplate redisTemplate; - @Autowired private LikeMapper likeMapper; @@ -35,9 +35,6 @@ public class LikeService implements CommunityConstant { @Autowired private UserService userService; - @Autowired - private EventProducer eventProducer; - /** * 点赞 * @@ -46,6 +43,7 @@ public class LikeService implements CommunityConstant { * @param entityId 点赞实体 id * @param entityUserId 点赞实体对应用户 id */ + @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED) public void insertLike(int userId, int entityType, int entityId, int entityUserId) { // 判断是否点过赞 int likeStatus = findEntityLikeStatus(userId, entityType, entityId); @@ -99,6 +97,7 @@ public class LikeService implements CommunityConstant { return likeMapper.countLikeByUserIdAndEntity(userId, entityType, entityId) > 0 ? 1 : 0; } + @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED) public int likeEntity(int entityType, int entityId, int entityUserId) { int result = 0; if (entityType == ENTITY_TYPE_POST) { @@ -112,6 +111,7 @@ public class LikeService implements CommunityConstant { return result; } + @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED) public int cancelLikeEntity(int entityType, int entityId, int entityUserId) { int result = 0; if (entityType == ENTITY_TYPE_POST) { -- Gitee From 01520c52f6004a56a247afa2475ff74f8655ef70 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Sat, 5 Mar 2022 13:46:20 +0800 Subject: [PATCH 069/125] update logout --- .../java/com/greate/community/service/UserService.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/greate/community/service/UserService.java b/src/main/java/com/greate/community/service/UserService.java index 9c61bb9..9ae102b 100644 --- a/src/main/java/com/greate/community/service/UserService.java +++ b/src/main/java/com/greate/community/service/UserService.java @@ -207,17 +207,17 @@ public class UserService implements CommunityConstant { } /** - * 用户退出(将凭证状态设为无效) + * 用户退出(删除缓存) * * @param ticket */ public void logout(String ticket) { - // loginTicketMapper.updateStatus(ticket, 1); // 修改(先删除再插入)对应用户在 redis 中的凭证状态 String redisKey = RedisKeyUtil.getTicketKey(ticket); - LoginTicket loginTicket = (LoginTicket) redisTemplate.opsForValue().get(redisKey); - loginTicket.setStatus(1); - redisTemplate.opsForValue().set(redisKey, loginTicket); +// LoginTicket loginTicket = (LoginTicket) redisTemplate.opsForValue().get(redisKey); +// loginTicket.setStatus(1); +// redisTemplate.opsForValue().set(redisKey, loginTicket); + redisTemplate.delete(redisKey); } /** -- Gitee From 5d1c2c5b7e15b15d87c4938e13b9c66ab6412182 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Sat, 5 Mar 2022 14:45:59 +0800 Subject: [PATCH 070/125] separate es env --- .../greate/community/config/AppConfig.java | 28 +++++++++++++++++++ .../greate/community/entity/DiscussPost.java | 26 ++++++++--------- .../resources/application-develop.properties | 1 + .../resources/application-test.properties | 1 + 4 files changed, 43 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/greate/community/config/AppConfig.java diff --git a/src/main/java/com/greate/community/config/AppConfig.java b/src/main/java/com/greate/community/config/AppConfig.java new file mode 100644 index 0000000..55f783e --- /dev/null +++ b/src/main/java/com/greate/community/config/AppConfig.java @@ -0,0 +1,28 @@ +package com.greate.community.config; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +import javax.annotation.PostConstruct; + +@Data +@Slf4j +@Configuration +public class AppConfig { + + public static String env; + + private final Environment environment; + + public AppConfig(Environment environment) { + this.environment = environment; + } + + @PostConstruct + public void init() { + env=environment.getProperty("spring.profiles.active"); + log.info("spring.profiles.active: {}", env); + } +} diff --git a/src/main/java/com/greate/community/entity/DiscussPost.java b/src/main/java/com/greate/community/entity/DiscussPost.java index 63ee760..8a4bce9 100644 --- a/src/main/java/com/greate/community/entity/DiscussPost.java +++ b/src/main/java/com/greate/community/entity/DiscussPost.java @@ -16,43 +16,43 @@ import java.util.Date; */ @Data @ToString -@Document(indexName = "discusspost") -@Mapping(mappingPath= "mapping/discusspost-mapping.json") +@Document(indexName = "discuss-post-#{@appConfig.env}") +@Mapping(mappingPath = "mapping/discusspost-mapping.json") public class DiscussPost { @Id private int id; -// @Field(type = FieldType.Integer) + // @Field(type = FieldType.Integer) private int userId; -// @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart") + // @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart") private String title; -// @Field(type = FieldType.Text, analyzer = " ik_max_word", searchAnalyzer = "ik_smart") + // @Field(type = FieldType.Text, analyzer = " ik_max_word", searchAnalyzer = "ik_smart") private String content; -// @Field(type = FieldType.Text) + // @Field(type = FieldType.Text) private String picUrls; -// @Field(type = FieldType.Integer) + // @Field(type = FieldType.Integer) private int type; -// @Field(type = FieldType.Integer) + // @Field(type = FieldType.Integer) private int status; -// @Field(type = FieldType.Integer) + // @Field(type = FieldType.Integer) private int viewCount; -// @Field(type = FieldType.Integer) + // @Field(type = FieldType.Integer) private int likeCount; -// @Field(type = FieldType.Integer) + // @Field(type = FieldType.Integer) private int commentCount; -// @Field(type = FieldType.Double) + // @Field(type = FieldType.Double) private double score; -// @Field(type = FieldType.Date) + // @Field(type = FieldType.Date) private Date createTime; } diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index 2ad2bf2..a665e92 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -60,6 +60,7 @@ elasticsearch.password = elastic2021. elasticsearch.hostname = es-50b9cgrk.public.tencentelasticsearch.com elasticsearch.port = 9200 elasticsearch.scheme = https +es.index-name.discuss-post = discuss-post-dev # Quartz spring.quartz.job-store-type = jdbc diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties index 47d8d59..c9d1cf4 100644 --- a/src/main/resources/application-test.properties +++ b/src/main/resources/application-test.properties @@ -51,6 +51,7 @@ elasticsearch.password = elastic2021. elasticsearch.hostname = 172.16.0.8 elasticsearch.port = 9200 elasticsearch.scheme = http +es.index-name.discuss-post = discuss-post-test # Quartz spring.quartz.job-store-type = jdbc -- Gitee From 2ca4ad42a6d50c235b3aa1f0ae93b28b9c367558 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Sat, 5 Mar 2022 15:00:59 +0800 Subject: [PATCH 071/125] update sensitive words --- src/main/resources/sensitive-words.txt | 36920 +++++++--------- .../greate/community/ElasticsearchTest.java | 7 +- 2 files changed, 15070 insertions(+), 21857 deletions(-) diff --git a/src/main/resources/sensitive-words.txt b/src/main/resources/sensitive-words.txt index b1bc98a..4a5b21d 100644 --- a/src/main/resources/sensitive-words.txt +++ b/src/main/resources/sensitive-words.txt @@ -1,17591 +1,3 @@ -10八 -香港总部 -颠覆中国政权 -烟草局 -温总理 -文革 -文化部 -文化大革命 -文物局 -文学城 -自由亚州 -自由运动 -对日强硬 -一部分人因年龄或健康原因将不得不退下去 -一党专政 -一党专制 -一贯道 -一国两制 -国际法院 -新疆独 -新疆独立 -找政府评理 -贾庆 -林黄菊 -18大的人事 -政变 -政府 -政局雾里看花 -银行联合管理局 -政权 -正法 -镇压 -政治 -中功 -伊拉克 -伊斯兰 -伊斯兰运动 -中共 -一中一台 -政治反对派 -政治犯 -政治风波 -政治局十八 -政治字眼(如两岸关系等) -郑恩宠 -蒋介石 -中南海 -中南海波澜起伏 -中南海斗争 -中南海高层权利斗争 -中南海惊现东宫小朝廷 -中南海秘闻 -原子能机构 -中共权斗 -中共权利斗争 -中南海权力斗争 -中宣部 -中央 -治军方针定调 -中央军委 -中央派系斗争 -中央团系 -李三共志 -国家安全 -造反 -李克强第五代领导人 -李克强接班人 -国家机密 -国家主要部委 -国军 -国民党 -胡紧掏 -胡锦涛 -胡锦滔 -胡锦淘 -胡景涛 -国民根本大法 -国庆 -非典 -东突厥斯坦伊斯兰运动 -海关总署 -国务院 -国贼 -海洋局 -海外民运 -国资委 -封杀 -东西南北论坛 -分析 -中共派系力量再达成妥协 -反革命 -反攻 -反攻大陆 -反共 -反华 -反恐委员会 -反社会 -游龙商务联盟 -游戏管理员 -反政府 -反目 -优化官员 -应召 -印章 -反日 -反人类 -反腐败 -反封锁 -颠覆中华人民共和国政 -东北独立 -帝国之梦 -帝国主义 -弟大物勃 -北京市亿霖 -布局十八大 -藏独 -党政一把手 -党中央 -党风日下 -邓小平 -邓晓平 -党禁 -党退 -布什 -大纪元 -测绘局 -大陆当局 -分裂 -压迫 -分裂中国 -分裂中华人民共和国 -第5代领导 -第四代 -多党 -第五代领导 -第五代领导人 -第五代领导新星 -第五代中共领导人 -独裁 -独裁政治 -独夫 -独立 -动乱 -北京 -18大 -1717wg.88448.com -北京当局 -绑架 -18da -暗杀 -报警 -北京政权 -暴力 -暴乱 -暴政 -爆炸 -安理会 -安全部 -安全监管 -安全局 -保监会 -保密室 -西藏 -西藏独 -西藏独立 -西藏天葬 -西山会议 -打压 -爱滋 -出卖 -18届 -18届常委 -18届名单 -18届委员 -18届中央 -18权力布局 -18预测 -爱国运动正名 -爱国者同盟 -奥运 -奥运会 -18大的人事安排意见 -18大人事变动 -连战 -两岸关系 -两岸三地论坛 -亡党 -两个中国 -两会 -连准 -秘书长 -密码 -南联盟 -内幕 -深圳国领 -深圳红岭 -年轻高知团系接班 -收货 -收容所 -示威 -世华商务 -事实独立 -廉政大论坛 -柳树中学 -六四 -卖国 -卖国唐捷 -人弹 -人民 -人民报 -人民报讯 -天安门 -天安门录影带 -天安门母亲 -天安门事件 -天安门屠杀 -天安门一代 -末世论 -人民大会堂 -绵恒 -绵恒异议人士 -人民大众 -人民大众时事参考 -人民内情真相 -人民日报 -人民真实 -人民真实报道 -人民真实报告 -人民之声 -人民之声论坛 -人权 -人事变动 -人事布局出手既稳又重 -人事接班 -人体炸弹 -人员安排 -人员变动 -人渣 -人质 -六四民主运动 -天府广场集会 -通信维权 -铁道部 -统独 -统计局 -统战 -美国参考 -美国佬 -美国之音 -台*湾 -台办 -台独 -台盟 -台湾 -台湾独 -台湾独立 -台湾共合国 -台湾狗 -台湾建国运动组织 -台湾联盟 -台湾青年独立联盟 -台湾政论区 -台湾自由联盟 -摊牌要权 -贪官 -贪污犯 -唐人电视台 -讨伐 -讨伐中宣部 -缅甸 -美利坚 -权威主义国家的合法性理论 -全国两会 -蒙独 -蒙古独 -亲美 -亲民党 -亲日 -青天白日旗 -蒙古独立 -六四事件 -六四学生运动 -领事馆 -令狐计划 -同胞书 -令计划 -透支 -突厥斯坦 -涂运普 -屠杀 -团派 -团派政治明星 -推翻 -推翻社会主义制度 -退党 -外汇局 -外交部 -外交论坛 -外交与方略 -外蒙 -外围 -晚年周恩来 -平反 -迫害 -罗蒙马格赛基金会 -十大穷人 -十六大 -十八大 -十八大权力变更 -十八大人事 -十八大人事安排意见 -十八大人事调整 -十八大未来 -十八大预测 -省市换班第五代冒起 -省委大门集合 -省政府大门集合 -十八大政治局 -萨达姆 -萨拉托加 -三个代表 -如何推翻中共 -瑞士金融大学 -上访 -上海帮 -上海孤儿院 -上海垮台 -上海市劳动和社会保障局违规使用社保资金 -社保基金会 -社会主义 -融资 -审计署 -生当作人杰之昨日重现 -十八换血 -十八届 -十八年 -商务部 -商务领航 -十八庆红 -数据中国 -刷卡 -刷卡消费 -双十节 -刘奇葆热门人选 -四川独 -四川独立 -出台 -膏药旗 -高层人事变动 -加拿大皇家骑警 -胡权利瓜分 -胡书记 -胡温 -胡晓炼 -胡耀邦 -胡玉敏 -胡泽君 -胡振民 -胡总书记 -建国党 -检查部 -韩长赋 -韩东方 -韩联潮 -韩正 -韩正降职副市长 -捍卫社会主义共和国 -监管局 -建设部 -僵贼 -僵贼民 -姜春云 -姜大明 -姜洪禄 -姜建清 -姜伟新 -姜异康 -将则民 -江Core -江core.江ze民 -江澤民.江八 -江八点.江独裁 -江蛤蟆.江核心 -江流氓 -江戏子 -江责民 -江则民 -江泽慧江泽林 -江泽民.江贼 -江贼民.江折民 -江猪.江猪媳 -江主 -酱猪媳 -抗日 -抗议 -教养院 -教育部 -老人政治 -公证 -公证处 -共军 -锦涛 -共青团背景 -共铲党 -老江 -联合行动 -联大 -联合国 -联合起诉最高人民法院 -老毛 -老毛子 -积克馆 -共产 -共产党 -回民 -回民暴 -回民 -暴动 -换届隐忧 -共党 -大史 -复转军人 -公关 -公馆 -军长发威 -军事委员会 -军委 -军委主席 -军转安置 -军转干部 -公开批评中央高层领导人 -公开信胡 -公开信胡书记空中民主墙 -鸡毛信文汇 -恐怖份子 -恐怖主义 -纪元 -公投 -理想信念斗争 -持不同政见 -腐败 -从陈良宇倒台看中国政局走势 -周恩来后悔 -周恩来自责 -周刊纪事 -周恩来忏悔 -中央召开北戴河会议决定十八大高层人事 -中国在统一问题上的投降主义 -中国真实内容 -子女任职名单 -咨讯紫阳 -中国政坛“清华帮”盛极而衰 -中国政坛新星中的四大天王 -中国政治新星 -中国泛蓝联盟 -中国复兴论坛 -中国改革年代政治斗争 -西藏论坛 -中国高层权力斗争 -中国高层人事变动解读 -中国六四真相 -中国论坛 -中国媒体十大事件 -中国民主党联合总部 -中国社会的艾滋病 -中国社会进步党 -中国社会论坛 -中国共产党 -中国孤儿院 -中国和平 -中国联通 -中国太子 -中国网通 -中共当局 -中共独裁 -中共反腐风暴大背景揭秘 -中共高层变动:王兆国将任常委或取代贾庆龄 -中共领导人黑幕 -香港明报 -星亚网络影视公司 -中共十八布局 -中共十八大的基层选举 -中共十八大前夕 -中共十八大前夕人事布局出手既稳又重 -中共十八大热门人选 -中共十八热门人选 -中共十八人事 -中共十八人事变动 -中共十八人选 -中国威胁论 -中国问题论坛 -中国移动 -中国移动通信 -中国银联 -18大委员名单 -大中国论坛 -大中华论坛 -18高官互调 -4.25事件 -钟山风雨论坛 -重新评定 -邮政局 -印尼伊斯兰祈祷团 -中央政治局 -中医药局 -40万名车车主名单 -信访局 -信号 -信息产业部 -信用卡 -信用卡空卡 -信用危机 -星相 -版署 -新生网 -新势力 -英雄纪念碑 -九评共产党 -新党 -中华人民正邪 -中华时事 -燕南评论 -央视内部晚会 -中华养生益智功 -中华真实报道 -中华大地思考 -宇明网 -宇宙真理 -语音 -中华大众 -中华讲清 -阿拉 -安南 -东洲 -北韩 -鲜族 -俄国 -民告官 -民国 -民航局 -民进党 -民联 -民意 -民意论坛 -民运 -民阵 -民政部 -民猪 -民主 -民主潮 -民主墙 -民族矛盾 -民族问题 -诺贝尔和平奖 -大法 -大法弟子 -dpp大法 -fa lun -falu -发抡 -发抡功 -洗脑 -下法轮 -发轮 -发伦 -发伦功 -发仑 -发沦 -发纶 -发论 -发论功 -发论公 -发正念 -发囵 -发愣 -发瞟 -罚抡 -罚伦 -罚仑 -罚沦 -罚纶 -罚囵 -筏抡 -筏轮 -筏伦 -筏仑 -筏沦 -筏纶 -筏论 -筏囵 -伐抡 -伐轮 -伐伦 -伐仑 -伐沦 -伐论 -伐囵 -乏抡 -乏轮 -乏伦 -乏仑 -乏沦 -乏纶 -乏论 -乏囵 -阀抡 -阀伦 -阀仑 -阀沦 -阀纶 -阀论 -阀囵 -法 轮 功 -法*功 -法.轮.功 -法L功 -法lun功 -法功 -法会 -法抡 -法抡功 -法轮 -法轮大法 -法轮佛法 -法轮功 -法伦 -法仑 -法沦 -法纶 -法论 -法十轮十功 -法西斯 -法院 -法正 -法谪 -法谪功 -法輪 -法囵 -法愣 -珐.輪功 -珐抡 -珐轮 -珐伦 -珐仑 -珐沦 -五不 -五不争鸣论坛 -五出三进 -五套功法 -邝锦文 -垡抡 -垡轮 -垡伦 -垡仑 -垡沦 -垡纶 -垡论 -垡囵 -茳澤民 -荭志 -闳志 -闵维方 -氵去 -氵去车仑工力 -转法轮 -砝抡 -砝轮 -砝伦 -砝仑 -砝沦 -砝纶 -真、善、忍 -真理教 -真善美 -真善忍 -砝论 -砝囵 -泓志 -屙民 -珐纶 -珐论 -珐囵 -falun -Falundafa -fa轮 -Flg -弟子 -地下教会 -炼功 -梦网洪志 -轮大 -抡功 -轮功 -伦功 -摩门教 -三水法轮 -三唑仑 -天皇 -天怒 -天葬 -车臣 -达赖 -功法 -讲法 -基督 -基督教 -护法 -回教 -教徒 -功友 -大师 -达赖喇嘛 -虹志 -鸿志 -洪传 -贯通两极法 -光祖 -洪吟 -洪哲胜 -洪志 -宏法 -观世音 -宏志 -弘志 -古兰经 -红志 -车库 -车仑 -经文 -东方红时空 -风水宝地 -舆论 -舆论反制 -风雨神州 -自杀手册 -自杀指南 -自已的故事 -自由 -自由民主论坛 -自由网 -自由写作奖 -自制手枪 -自主择业 -宗教压迫 -先天健康法 -阻止中华人民共和国统 -昨日重现 -咨询 -咨讯 -风雨神州论坛 -东方时空 -独立台湾会 -访问链接 -飞扬论坛 -独立中文笔会 -东南西北论谈 -真相 -真象 -侦探设备 -争鸣论坛 -正帮通信公司 -正见 -正邪大决战 -正义党论坛 -北京之春民主论坛 -北美讲坛 -倒陈运动的最大受益人 -反封锁技术 -反腐败论坛 -地下刊物 -恶搞晚会 -北美讲坛 -北美论坛 -地铁十号线塌方 -逊克农场26队 -春夏论坛 -邓颖超日记 -国研新闻邮件 -国色天香网 -春夏之交 -春夏自由论坛 -亚洲周刊 -亚洲自由之声 -博讯 -邓小平和他的儿子 -政坛两黑马 -政坛明日之星 -中國當局 -中朝 -中电信 -中俄边界 -中俄边界新约 -中俄密约 -致胡书记的公开信 -指点江山论坛 -北美自由论坛 -参加者回忆录 -大纪元新闻网 -九-评 -九.评 -九、评 -九—评 -九成 -九成新 -九码 -九评 -新观察论坛 -新华举报 -新华内情 -新华社 -新华通论坛 -大众真人真事 -大家论坛 -新唐人 -新唐人电视台 -新闻办 -新闻封锁 -新语丝 -印尼伊斯兰祈祷团 -北大三角 -地论坛 -9.635 -9评 -中华人民实话实说 -杂志 -E周刊 -安装卫星电视 -代表大会 -论坛 -南大论坛 -南大自由论坛 -强硬发言 -南华早报 -你说我说论坛 -木子论坛 -两会报道 -两会新闻 -轻舟快讯 -热站政论网 -时代论坛 -时事参考 -时事论坛 -万维读者论坛 -统独论坛 -特讯 -世界经济导报 -世界通 -超常科学 -传说的胡曾联手是一种假象 -大纪元 -港澳办 -跨世纪的良心犯 -告全国股民同胞书 -华岳 -华岳时事论坛 -华夏文摘快递 -华语世界论坛 -和平请愿书 -华人媒体 -华通时事论坛 -华夏文摘 -广 闻 -广电局 -广东五元集团 -广告 -广闻 -红潮谎言录 -告全体网民书 -告中国人民解放军广大官兵书 -港料 -大史记 -联总之声 -集会 -集体上访 -讲事实 -要说法 -霍英东临终遗言 -大史纪 -高校群体事件 -传中共中央关于18大的人事安排意见 -安眠酮 -代血浆 -普萘洛尔 -呋塞米 -西布曲明 -testosterone -胰岛素样生长因子 -促红细胞生成素 -地西泮 -尼可刹米 -甲睾酮 -adrenaline -erythropoietin -地奈德 -莫达非尼 -氯噻嗪 -苯巴比妥 -促性腺激素 -泼尼松 -麻黄草 -雄烯二醇 -地塞米松 -tamoxifen -strychnine -androst -新型毒品 -杜冷丁 -兴奋剂 -mdma -海洛因 -海luo因 -heroin -diamorphine -diacetylmorphine -鸦片 -阿芙蓉 -咖啡因 -cocain -三唑仑 -美沙酮 -麻古 -k粉 -凯他敏 -ketamine -冰毒 -苯丙胺 -cannabis -大麻 -爱他死 -氯胺酮 -benzodiazepines -甲基安非他明 -安非他命 -吗啡 -morphine -摇头丸 -迷药 -乖乖粉 -narcotic -麻醉药 -精神药品 -爱女人 -爱液 -按摩棒 -拔出来 -爆草 -包二奶 -暴干 -暴奸 -暴乳 -爆乳 -暴淫 -屄 -被操 -被插 -被干 -逼奸 -仓井空 -插暴 -操逼 -操黑 -操烂 -肏你 -肏死 -操死 -操我 -厕奴 -插比 -插b -插逼 -插进 -插你 -插我 -插阴 -潮吹 -潮喷 -成人电影 -成人论坛 -成人色情 -成人网站 -成人文学 -成人小说 -艳情小说 -成人游戏 -吃精 -赤裸 -抽插 -扌由插 -抽一插 -春药 -大波 -大力抽送 -大乳 -荡妇 -荡女 -盗撮 -多人轮 -发浪 -放尿 -肥逼 -粉穴 -封面女郎 -风月大陆 -干死你 -干穴 -肛交 -肛门 -龟头 -裹本 -国产av -好嫩 -豪乳 -黑逼 -后庭 -后穴 -虎骑 -花花公子 -换妻俱乐部 -黄片 -几吧 -鸡吧 -鸡巴 -鸡奸 -寂寞男 -寂寞女 -妓女 -激情 -集体淫 -奸情 -叫床 -脚交 -金鳞岂是池中物 -金麟岂是池中物 -精液 -就去日 -巨屌 -菊花洞 -菊门 -巨奶 -巨乳 -菊穴 -开苞 -口爆 -口活 -口交 -口射 -口淫 -裤袜 -狂操 -狂插 -浪逼 -浪妇 -浪叫 -浪女 -狼友 -聊性 -流淫 -铃木麻 -凌辱 -漏乳 -露b -乱交 -乱伦 -轮暴 -轮操 -轮奸 -裸陪 -买春 -美逼 -美少妇 -美乳 -美腿 -美穴 -美幼 -秘唇 -迷奸 -密穴 -蜜穴 -蜜液 -摸奶 -摸胸 -母奸 -奈美 -奶子 -男奴 -内射 -嫩逼 -嫩女 -嫩穴 -捏弄 -女优 -炮友 -砲友 -喷精 -屁眼 -品香堂 -前凸后翘 -强jian -强暴 -强奸处女 -情趣用品 -情色 -拳交 -全裸 -群交 -惹火身材 -人妻 -人兽 -日逼 -日烂 -肉棒 -肉逼 -肉唇 -肉洞 -肉缝 -肉棍 -肉茎 -肉具 -揉乳 -肉穴 -肉欲 -乳爆 -乳房 -乳沟 -乳交 -乳头 -三级片 -骚逼 -骚比 -骚女 -骚水 -骚穴 -色逼 -色界 -色猫 -色盟 -色情网站 -色区 -色色 -色诱 -色欲 -色b -少年阿宾 -少修正 -射爽 -射颜 -食精 -释欲 -兽奸 -兽交 -手淫 -兽欲 -熟妇 -熟母 -熟女 -爽片 -爽死我了 -双臀 -死逼 -丝袜 -丝诱 -松岛枫 -酥痒 -汤加丽 -套弄 -体奸 -体位 -舔脚 -舔阴 -调教 -偷欢 -偷拍 -推油 -脱内裤 -文做 -我就色 -无码 -舞女 -无修正 -吸精 -夏川纯 -相奸 -小逼 -校鸡 -小穴 -小xue -写真 -性感妖娆 -性感诱惑 -性虎 -性饥渴 -性技巧 -性交 -性奴 -性虐 -性息 -性欲 -胸推 -穴口 -学生妹 -穴图 -亚情 -颜射 -阳具 -杨思敏 -要射了 -夜勤病栋 -一本道 -一夜欢 -一夜情 -一ye情 -阴部 -淫虫 -阴唇 -淫荡 -阴道 -淫电影 -阴阜 -淫妇 -淫河 -阴核 -阴户 -淫贱 -淫叫 -淫教师 -阴茎 -阴精 -淫浪 -淫媚 -淫糜 -淫魔 -淫母 -淫女 -淫虐 -淫妻 -淫情 -淫色 -淫声浪语 -淫兽学园 -淫书 -淫术炼金士 -淫水 -淫娃 -淫威 -淫亵 -淫样 -淫液 -淫照 -阴b -应召 -幼交 -幼男 -幼女 -欲火 -欲女 -玉女心经 -玉蒲团 -玉乳 -欲仙欲死 -玉穴 -援交 -原味内衣 -援助交际 -张筱雨 -招鸡 -招妓 -中年美妇 -抓胸 -自拍 -自慰 -作爱 -18禁 -99bb -a4u -a4y -adult -amateur -anal -a片 -fuck -gay片 -g点 -g片 -hardcore -h动画 -h动漫 -incest -porn -secom -sexinsex -sm女王 -xiao77 -xing伴侣 -tokyohot -yin荡 -KC短信 -KC嘉年华 -短信 -短信:广告 -短信广告 -短信平台 -短信群发 -小灵通 -短信群发器 -小6灵通 -短信商务广告 -段录定 -无界浏览 -无界浏览器 -无界 -无网界 -无网界浏览 -无帮国 -KC提示 -KC网站 -电信 -UP8新势力 -动5感地带 -白皮书 -UP新势力 -移3动 -移动 -移动公司 -移动集团 -移民 -易达网络卡 -安魂网 -罢工 -罢课 -铃声下载 -纽崔莱七折 -手机复制 -手机铃声 -手机铃声下载 -手机游戏 -神7州行 -网关 -神通加持法 -全1球通 -如6意通 -清仓 -灵动卡 -超市 -答案卫星接收机 -打折机票 -高薪养廉 -考后付款 -佳静安定片 -号 -航班 -航空 -航空母舰 -航空售票 -航天 -号码百事通 -考前发放 -成本价 -诚信通手机商城 -大2众卡 -辅导 -高利贷 -联 通 贵宾 卡 -联4通 -黑庄 -黑马 -黑手党 -黑车 -联通 -联通贵宾卡 -联通商务通 -联总 -联总这声传单 -联总之声传单 -高息贷款 -高干子弟 -恭喜你的号码 -恭喜您的号码 -高干子女 -各个银行全称 -各种发票 -高官 -高官互调 -高官子女 -辅导班 -复式 -喝一送一 -卡号 -复制 -监听王 -传:单 -传单 -旦科 -钓鱼岛 -钓鱼台 -当官靠后台 -党校安插亲信 -传九促三 -客户端非法字符 -刻章 -大麻树脂 -大麻油 -陈宝生 -程凯 -程铁军 -程真 -陈炳德 -陈炳基 -陈车 -陈川平 -陈存根 -戴秉国 -戴海静 -戴相龙 -陈德铭 -陈国令 -董贵山 -董万才 -懂文华 -陈冀平 -冯东海 -冯敏刚 -冯寿淼 -冯素英 -陈际瓦 -陈建国 -陈军 -陈奎元 -陈雷 -傅成玉 -傅申奇 -傅志寰 -傅怡彬 -贾安 -贾庆林 -贾廷安 -贾育台 -贾治邦 -希拉克 -希特勒 -傅雯娟 -符贵 -符强 -符跃兰 -陈良宇 -陈蒙 -陈敏尔 -陈破空 -陈润儿 -陈水扁 -陈文清 -邓楠 -迪里夏提 -陈希 -颜射 -阎明复 -焉荣竹 -严家其 -严家祺 -陈希同 -陈小同 -陈新权 -陈宣良 -陈训秋 -陈一谘 -丁关根 -丁元 -丁子霖 -陈元 -陈政高 -陈至 -李 洪 志 -李安东 -李斌 -李长才 -李长春 -李长江 -李成玉 -李崇禧 -李从军 -李大师 -李登辉 -李法泉 -李刚 -李海峰 -李汉柏 -李鸿忠 -李洪峰 -李洪宽 -李洪志 -李宏志 -李宏治 -李红痔 -李继耐 -李纪恒 -李建国 -于大海 -于浩成 -于起龙 -于幼军 -李金城 -李金章 -李景田 -李康 -李克 -李克强 -李兰菊 -李老师 -李立国 -李禄 -徐邦秦 -徐斌 -徐才厚 -徐粉林 -徐光春 -徐建国 -徐敬业 -徐匡迪 -徐乐江 -徐绍史 -徐守 -徐水良 -徐天亮 -徐一天 -许达哲 -许家屯 -许其亮 -许云昭 -肖爱玲 -肖钢 -肖捷 -肖强 -肖亚庆 -李录 -李买富 -李鹏 -李契克 -李荣融 -李瑞环 -李少民 -李盛霖 -李世明 -李适时 -李淑娴 -李铁映 -李旺阳 -李文斌 -李熙 -李希 -李向东 -李小朋 -李小鹏 -李小雪 -李学举 -李学勇 -李延芝 -李毅中 -李玉赋 -李玉妹 -李源潮 -李月鸟 -李月月鸟 -余欣荣 -余英时 -余远辉 -俞杰 -俞正声 -李兆焯 -李志绥 -李总理 -李总统 -李幛喆 -李岚清 -列宁 -列确 -林保华 -林彪 -林长盛 -林军 -廖锡龙 -林明月 -林慎立 -廖晖 -林树森 -林业局 -林幼芳 -凌锋 -林左鸣 -林樵清 -令狐安 -刘宾深 -刘宾雁 -刘成军 -刘春良 -刘冬冬 -刘刚 -刘国凯 -刘华清 -刘慧 -刘家义 -刘建华 -刘京 -刘俊国 -刘凯中 -刘明康 -刘鹏 -刘奇葆 -刘千石 -刘青 -刘山青 -刘石泉 -刘士贤 -刘士贤司马晋 -刘伟 -刘伟平 -刘文胜 -刘文瑜 -刘晓波 -刘晓江 -刘晓凯 -刘晓竹 -刘晓榕 -刘学普 -刘亚洲 -刘延东 -刘永川 -刘永治 -刘玉浦 -刘玉亭 -刘源 -刘粤军 -刘云山 -刘振来 -刘振起 -刘振亚 -刘志军 -刘淇 -陈至立 -陈子明 -陈总统 -陈左宁 -邓昌友 -邓可人 -邓天生 -邓笑贫 -阿拉法特 -蔡崇国 -蔡继华 -蔡挺 -蔡武 -蔡振华 -艾斯海提·克里木拜 -安立敏 -巴赫 -巴特尔 -巴音 -朝鲁 -白志健 -白春礼 -范长龙 -范印华 -万晓东 -汪梦飞 -汪洋 -汪岷 -王宝森 -王炳章 -王策 -王超华 -王传平 -王丹 -王东明 -王辅臣 -王刚 -王冠中 -王光亚 -王国生 -王涵万 -周强 -周生贤 -周天法 -周旋 -周英 -周永康 -朱保成 -朱成虎 -朱丹 -朱德 -朱嘉明 -朱金基 -朱琳 -朱明国 -朱溶剂 -朱容基 -朱维群 -朱之鑫 -朱总理 -朱镕基 -王和民 -王鸿举 -王洪章 -王沪 -王沪宁 -王华庆 -王华元 -王家瑞 -王建军 -王建平 -王金山 -王进东 -王军涛 -王俊莲 -王乐泉 -王莉莉 -王立英 -王力雄 -王明方 -王荣 -王儒林 -王瑞林 -王润生 -王若望 -王三运 -王胜俊 -王寿祥 -王太华 -王通智 -王万宾 -王为璐 -王维民 -王伟 -王伟光 -王希哲 -王喜斌 -王侠 -王宪魁 -王晓初 -王新宪 -王秀丽 -王旭东 -王学军 -王冶坪 -王毅 -王勇 -王玉普 -王兆国 -王正福 -王正伟 -王志刚 -王忠民 -王岐山 -方励之 -方舟子 -曹长青 -郭伯雄 -郭庚茂 -章虹 -章沁生 -张宝顺 -张博涵 -张伯笠 -张成寅 -张春贤 -张德江 -张钢 -张高丽 -张耕 -张国清 -张海阳 -张宏堡 -张惠新 -张基 -张纪南 -张健 -张建平 -张杰 -张军 -张开双腿 -张连珍 -张林 -张平 -张庆黎 -张庆伟 -张汝成 -张仕波 -张铁健 -张万年 -张伟国 -张文岳 -张先玲 -吴爱 -吴百益 -吴邦国 -吴定富 -吴方城 -吴官正 -吴宏达 -吴弘达 -吴仁华 -吴胜利 -吴双战 -吴新雄 -吴学灿 -吴学璨 -吴仪 -吴玉良 -吴镇南 -吴毓萍 -武吉海 -吾尔开希 -张晓刚 -张晓平 -张小平 -张轩 -张研农 -张阳 -张裔炯 -张毅 -张又侠 -张玉台 -张云川 -张昭富 -张志清 -张中伟 -张左己 -张岱梨 -何德普 -何峰 -何家栋 -何平 -何清涟 -何勇 -郭金龙 -黄局 -黄康生 -晴宜 -黄菊 -黄树贤 -黄献中 -黄翔 -黄兴国 -黄作兴 -黄慈萍 -黄殿中 -魏凤和 -魏家福 -魏京生 -魏礼群 -魏新生 -尉健行 -袁纯清 -袁贵仁 -袁家军 -袁荣祥 -卫留成 -卫生部 -温家宝 -赵爱明 -赵海青 -赵洪祝 -赵克石 -赵乐际 -赵南 -赵品潞 -赵铁锤 -赵宪庚 -赵晓微 -郑义 -郑源 -郑中 -温加饱 -温元凯 -温云松 -邢元敏 -邢铮 -黄华华 -黄祸 -黄建国 -黄晶 -郭罗基 -郭平 -郭声琨 -郭树清 -郭岩华 -郭炎炎 -郭永平 -曹刚川 -杨崇汇 -杨传升 -杨传堂 -杨刚 -杨怀安 -杨焕宁 -杨建利 -杨建亭 -杨洁篪 -杨晶 -杨利民 -杨利伟 -杨士秋 -杨松 -杨巍 -杨衍银 -杨元元 -杨月清 -杨周 -姚月谦 -姚增科 -耶和华 -叶冬松 -叶剑英 -叶青纯 -曹建明 -曹康泰 -曹清 -白恩培 -薄熙来 -白景富 -白军 -白立忱 -白立朴 -白梦 -鲍戈 -鲍彤 -杜导斌 -谢长廷 -谢和平 -谢小庆 -谢旭人 -谢选骏 -谢中之 -辛灏年 -杜恒岩 -杜鹃 -费良勇 -杜青林 -杜学芳 -杜宇新 -杜智富 -贝领 -本.拉登 -不来提不都热西提 -柴玲 -梁保华 -柳斌杰 -楼继伟 -邱学强 -齐墨 -仁吉旺姆 -仁青加 -卢越刚 -马大维 -莫伟强 -申维辰 -任亚平 -蔣彥永 -舒晓琴 -盛华仁 -努尔白克力 -彭枫 -彭清华 -欧泽高 -宋xx -司马晋 -司马义·铁力瓦尔地 -水扁 -史莲喜 -石宗源 -石大华 -司马璐 -司徒华 -宋爱荣 -宋楚瑜 -宋平 -宋平一句话 -宋书元 -宋秀岩 -宋育英 -宋祖英 -苏家屯 -苏荣 -苏绍智 -田成平 -田力普 -田修思 -童世平 -童屹 -童增 -铁凝 -苏士亮 -苏树林 -苏晓康 -孙宝树 -孙春兰 -孙大发 -孙建国 -孙金龙 -孙思敬 -孙晓群 -孙政才 -孙忠同 -汤光中 -汤涛 -唐柏桥 -唐家璇 -唐捷 -陶驷驹 -潘国平 -钦本立 -普京 -尚福林 -尚勇 -邵家健 -穆斯林 -秦光荣 -乔石 -秦晋 -秦银河 -邵明立 -邵琪伟 -沈德咏 -沈浩波 -沈素琍 -沈彤 -沈跃跃 -潘云鹤 -孟建柱 -孟令伟 -孟学农 -聂卫国 -祁建 -钱达 -钱国梁 -钱其琛 -钱运录 -马会 -马凯 -马克思 -罗保铭 -罗干 -毛一鲜 -毛泽东 -毛泽东123 -毛泽东2 -毛贼东 -梅克保 -罗礼诗 -罗清泉 -罗正富 -罗志军 -骆惠宁 -骆琳 -马良骏 -马强 -马三家 -马时敏 -马晓天 -马英九 -马志鹏 -马飚 -马馼 -卢展工 -路甬祥 -鹿心社 -陆兵 -陆浩 -陆委会 -吕京花 -吕秀莲 -吕祖善 -梁光烈 -梁擎墩 -常万全 -克林顿 -雷春美 -东突厥斯坦伊斯兰 -迟浩田 -克劳塞维茨 -迟万春 -仇保兴 -康日新 -康涛杰 -黎安友 -黎阳平 -拉丹 -拉登 -拉姆斯菲尔德 -高瞻 -葛振峰 -金道铭 -金日成 -金书波 -金尧如 -金振吉 -华过锋 -胡春华 -胡绩伟 -胡江 -胡平 -华惠棋 -华建敏 -华莱士 -金正日 -金壮龙 -靖志远 -高自联 -高莺莺 -高强 -高文谦 -焦国标 -焦焕成 -蒋峰 -蒋洁敏 -蒋经国 -蒋文兰 -蒋彦永 -高武生 -付申奇 -连胜德 -贺邦靖 -关卓中 -贺国强 -干以胜 -简鸿章 -回良玉 -江罗 -冠希 -江绵恒 -江棋生 -江青 -恩格斯 -114 -CBD -板楼 -别墅 -车库 -城堡 -成本价 -酬宾 -大降价 -地产 -度假区 -二期 -发售 -房 -房产 -房地产 -房峰辉 -房间 -房型 -房源 -房展 -房折 -风水宝地 -公馆 -公寓 -购房 -豪宅 -号码百事通 -喝一送一 -衡阳万通房产 -户型 -花园 -街铺 -精装 -景观住宅 -均价 -开发 -开盘 -看房 -两限房 -楼盘 -娄义 -买二送一 -买房 -买一送一 -卖车 -卖房 -面积 -名宅 -票据 -平米 -抢购 -求:购 -求购 -全户型 -认购 -三期 -商铺 -商圈 -商业楼 -生态区 -首付 -售楼 -特等奖 -特惠房 -特价 -特卖会 -投注 -旺铺 -威海 -现房 -小户 -小旺铺 -写字楼 -洋房 -样板房 -样板间 -样板间 -一码 -一平 -一期 -一切证件 -一梯两户 -一折起 -优惠 -折上折 -周年庆 -住宅 -装修 -准现房 -租房 -租售 - -第八类 其他: -常劲 -本田 -鲍筒 -拨打 -伴游 -QQ宠物 -本公司2 -世纪中国基金会 -610洗脑班 -帮穷人 -2004年公共服务奖 -2006年十句最真实的谎言 -001工程 -分家在 -大红赤龙七头十角 -第一批下海经商的人富 -俄罗斯 -周年庆 -苗圩 -明斯克号 -清纯 -穷 人 -穷人 -屈万祥 -善恶有报 -汕尾 -生态区 -生肖 -盛雪 -盛雪辛灏年 -师傅 -师父 -石戈 -食捻屎 -使馆 -驶你老母 -驶你母 -试卷 -试题答案 -圣战 -权柄 -全哲洙 -瘸腿帮 -群体灭绝 -燃烧辅助工具 -热比娅 -热线 -忍 -忍无可忍 -明心 -水去车仑 -斯诺 -四级答案 -四联航空 -透视镜 -透视眼镜 -万能钥匙 -万润南 -网管 -网上赚钱 -网特 -网通 -网赚队伍 -往事并不如烟 -威而柔 -威海 -素人 -宿命论 -隧道 -檀鑫 -名山县 -体健貌端 -天鹅之旅 -名师 -慕歌 -木犀地 -穆罕默德 -倪育贤 -年福纯 -捻 -潜在用户 -抢粮记 -龙虎豹 -瞒报 -毛片 -绿色环保手机 -绿色雨 -龙虎豹宋书元 -龙卷风 -领取 -长期 -城堡 -担保 -吹喇叭 -歌 -歌德 -歌功颂德 -高丽棒子 -蛤蟆 -个人崇拜 -看中国 -凯旋 -口蹄疫 -来京上访 -蓝光 -蓝丝带 -举行 -均价 -靖国神社 -警察 -静坐 -揭批书 -接班 -结欠 -结帐 -戒严 -刀林荫 -登辉 -登天梯 -翟渠 -翟小衡 -点金 -东突 -东突厥斯坦 -东土耳其斯坦 -吨 -多维 -二码 -二乙基酰胺 -二注 -发~票 -发财诗 -发改委 -分众 -封从德 -疯狂掠夺大陆股民 -凤凰 -佛展千手法 -戈扬 -鸽派 -工力 -工自联 -共黨 -古怪歌 -管理员 -哈批 -114 -1258 -1259 -12590 -12593 -1 0 1 5 9 -10000 -10010 -10086 -10159 -13423205670 -13725516608 -13875448369 -15112886328 -189 -6-4tianwang -64 -68170802 -6a6.net -7.31 -7.310 -89-64cdjp -8945212 -23条 -259o -381929279 -3P -4-Jun -AV -BJ -CBD -CCTV -CDMA -DICK -Dick -FLG -FOCUSC -FUCK -Fuck -GAMEMASTER -GCD -GameMaster -IP17908 -KEY_TEXT -NMD -QQb -SM -Soccer01.com -TMD -UltraSurf -bignews -Bitch -boxun -Chinaliberal -chinamz -Chinesenewsnet -cnd -Creaders -dafa -Dajiyuan -df'd -Dfdz -die -dpp -Freechina -freedom -Freenet -fuck -fuck your mother -hongzhi -hrichina -huanet -hypermart.net -incest -jiangdongriji -l2590803027 -lihongzhi -ma -making -minghui -minghuinews -nacb -na?ve -nmis -paper64 -peacehall -piao -playboy -renminbao -renmingbao -rfa -safeweb -sex -shit -simple -svdc -taip -tibetalk -triangle -triangleboy -txwq.net -unixbox -ustibet -voa -voachinese -wangce -wstaiji -www -xinsheng -yuming -yy通讯录 -zhengjian -zhengjianwang -zhenshanren -zhuanfalu -zhuanfalun -八九 -八老 -回民吃猪肉 -习近平 -TMD -毛民进党 -妹妹淫水 流 -机吧 -联国 -1989六四 -性爱电影 -李红智 -梁光烈 -巴黎市长 -成人BT -免注册淫色电影 -UltraSurf -鐵血三國志 -性爱图库 -公安 -777黄站 -大龟头顶住嫂嫂的花心深处 -插 穴 射 喷 精液 -兽奸 -PORN -毛可卡因 -阴茎挺进滋润肉洞里在阴户中抽送 -falundafa -三八淫成人网 -发^^轮 -毛江折民 -毛拉登 -免费淫*女A片段 -d7se我淫我电影 -madelove -淫奸美女穴 -美女极品穴 -…快插我淫穴… -乱武天下 -玩穴 -lineageⅡ -居然花钱请人教性爱姿势(组图)免费淫电影a片 -肛交 -go-vern-ment -奸你 -四眼醫生強制飲尿 美巨乳小野悠美第二彈 -坤迈 -高嘉 -兼职女教师 -嫂嫂的穴 -龟头在她的阴道里抽插 -张梅颖 -幼女嫩逼 -meimei的阴蒂 -淫女性息 -强奸35岁处女全过程/淫妹阴毛小穴 -这年头就这样 -阴屄 -贺龙 -酱猪媳 -毛台湾共和国 -欢乐潜水艇 -陰唇 -淫虎大型色站 -免费淫奸黄色电影a片 -drop -免费强奸淫电影 -幸福花園 -老公,他要插进来了 -9JBW -巨乳美女RINA无码第2弹 -十八电影掰穴特写红免费性视频聊天激情少妇图 -新華內情 -meinv嫩穴 -麻黄素 -绝品美女が恍惚颜の绝顶快感 -操逼样 -褻 -日本激情淫穴贴图 -女优 -雞吧 阴茎 插 騷穴 嫩穴 小穴 -錢 國 梁 -巨乳 -fuck温总理 -熱血傳奇 -夜色导航 -風騷淫蕩 -麻黃素 -插阿姨的洞洞舔女朋友的下身 -驶你爸 -轮奸做爱高潮录象 -测试 -赛你老母 -內射 -李岚清 -芬太尼 -日本妹妹 -fuck生春袋 -rf 行会战争 -卫生部 -fuck手机复制 -法论工 -meimei的小屄好痒 -毛干拎娘 -黄色免费淫乱电影 淫女色情图片 -幸福花园 -奸他 -朱狨基 -JPEEN -色情信息 -六岁幼女阴穴近拍 -meimei被操的淫水直流 -粪便 -私人服务器 -master -希特勒 -猥褻 -马卖马屁 -淫B -激情淫色自拍 -mi zhuan -免费淫奸女A片段试看 教你怎样延迟射精18岁以下禁 -又粗又长的肉棒 -新大陆 -吳 方 城 -胡紧套 -肉棒与阴道摩擦 -韩国成人激情淫洞 -丰满小妹的丰褪美腿 嫩得流水的小meimei -淫妻交换 -你说我说论坛 -政治反对派 -聚商 -hang hai shi ji -街头对抗靠 -ㄙㄞ你爸 -淫色导航 -淫乱护士电影 -淫乱狂穴 -吗逼 -蒋中国 -暴政 -香港激情淫影院 -发正念 -坤邁 -抽插18岁处女妹妹淫叫不断 -淫窝窝 -手伸到下体抚mo嫩穴 -中广网 -fuck宋楚瑜 -砍死你 -混 沌决 -神風~ Kamikaze Street Vol。 13 : 里山加与 -婬乱军团 -紮卡維是英雄 -免费午夜激情视频 -曾慶红 -乱伦之淫穴 -国产嫖娼 -淫液下留 -哥哥用力舒服死我了 -騰武 -space -毛你二大爷 -吞精骚妹 -中国真实内容 -新大陸 -天然むすめ 素人~このみ -小泉純一郎 -色情 网 站 导航 -粉红的的奶头粉嫩的阴唇 -色妹妹淫穴 -热血传奇 -天联世纪 -操逼电影 -英雄世纪 -东突,免费淫色情电影 令人喷血的春宫108姿势(组图)18岁禁看 -跑跑卡丁车 -9之游 -淫b -裸 -操车臣 -装逼呢 -地震 -肏meimei的小骚屄 -肉感炮友 -跟妹妹肏穴好舒服 -xi you -反恐委员会 -骡干 -淫液顺着肉棒 -中華民國 -赫鲁晓夫 -狂操小穴 -Tokyo Hot n0252 原田友美 高飞车美人教师精液炸沉 -國產嫖娼 -日本鬼子 -国管局 -svdc -小阴唇 黏液流下 舌头舔进阴道 -中華民国 -系统公告 -meinv视频图情色贴图区成人性光牒 -臭机 -毛天安门事件 -聂荣臻 -淫妻交換 -毛人弹 -徐光春 -屁股 -波霸 -meimei等你大鸡吧来插 -GAN -热站政论网 -免费成人图片 色情meinv做爱meinv小穴写真 -又肥又紧的屄儿 -中國狗 -金山 -小穴不断被顶入 -不倫繼母的性猥褻 -龟头在嫂嫂的小穴穴口研磨 -处女被强迫吃春药后被开苞 -毛洪志 -毛淫语连连 -费良勇 -反封鎖技術 -AV女优 激情小电影 熟女俱乐部 -法轮功靠 -熟女人妻 太太自愿拍片被机射在里面 -mo fa qi bing -届中央政治局委员 -夜聊视频聊天室 -发$$纶 -色网阴道特写强奸33岁处女全过程 -胡新宇 -淫獸學園 -何加棟 -王子杰 -毛看牌软件 -儿子添着妈妈大的阴唇 -淫穴嫩穴 -插meimei小穴 -GCD -Fag -遗言 -目標軟體 -默克尔 -午夜性爱惊魂 -操淫荡护士穴 -可视视频聊天 -恼杀美巨乳meinv~吉川萌 -地 下 教 會 -幼男搞幼女 -蔡庆林 -鸡吧插进肉穴 -紅十字會 -台湾共和国 -团中央 -吴 宏 达 -红顶商人 -丁子霖 -插那吗B -掄功 -激情女优 -稀少罕见的美少女蝴蝶屄 -mm的诱人双峰→免费试看片 -唐柏桥 -阿拉法特 -福莱斯特 -刘云山 -葫蘆案 -情色电影立即看 -鋼管舞 -免费淫色情电影 教你如何鉴别处男处女的方法(组图)18岁禁看 -asiasex -調教 -插深些 -神經病 -狹義道 -肉棒在小穴深初来回抽动 -鸡巴深深地插在妈的阴户里 -点点激情播放性电影 -侧那 -強淫女優 -我的阴茎使劲的抽插她的小穴 -人代会 -性愛 圖庫 -死gd -精子 淫穴 淫液 -周莹 -肉棒插入小穴 -猛地插入了她的肥穴 -联大 -经血 -毛你姥姥的 -chengmingmag -骚BB免费色电影 -薄一波 -宏 法 -腚眼 -淫痴 -口头检查 -日本成人激情论坛 -文化大革命 -民为法执 -達賴 -三级片A片下载观看 -死gm -白肌meinv?琴也 -激情成人网 -用品 -知识 -保健 -抽插21岁处女meimei淫叫不断 -免费淫色情电影 欢迎点击进入观看/林/心如/20岁处女偷拍/免费A。B片 -免费黄色淫秽电影 -小穴流水meimei手指插 -gameline -六四屠杀 -女優 -小B -日本帝國 -法谪功 -人民真实 -伸到老师的小穴里 -潮姫 史上最高の潮吹き女 -日本帝国 -meimei的小阴户 -辣妹狼图~肏穴图 -含住肉棒上下使劲吸吮起来 -百家性大型免费黄站 -陰囊 -輪攻 -精神病 -王策 -小b -巨额骗储 -毛佳静安定片 -鸟gm -骚屄 -TeSt -激情电影免费下载裸体美女乳房图 -日翻 -美臀嫰穴 -毛王兆国 -小卵泡 -日本成人激情网站 -肉棒 好粗啊…… -情色俱乐部美女奸淫。黄色电影裸体电影PP点点激情电影 -數碼精靈 -迅雷下载免费黄色淫乱电影 -6?4靠 -全裸女优 -達赖 -正悟网 -毛小泉纯一郎 -持不同政见 -鸟gM -淫癡 -台湾淫电影 导航 -外•挂 -www。gpchina。net -春色满园淫妻系列 -删 号靠 -美沙酮 -VIP独占~秘密之大乱交(最终话) -blogbaby -中华民国 -阴道里的大肉棒来回抽插 -操草妈 -helper -毛两腿之间 -中国淫女论坛 -48xp。com 电影免费 -亲哥哥……meimei的小穴……舒服死了…… -美国参考 -中华民國 -看棋软件 -操美女穴 -毛海洛因 -淫女俱乐部 -絲襪足交 -淫荡┅好舒服 -GAMEmaster -陈独秀 -淫水愛液 -农村人乱伦事 -女大学生在夜店被朋友轮奸 -拉案 -总书记 -毛毛一鲜 -火热的精液喷射在子宫上 -肉棒捅进阴户里 -香港色情影星美女裸体 -毛性交 -大人の隠れ汤 乱交游戯温泉へようこそ -因特天盟 -肉具 -司馬義?鉄力瓦爾地 -菊花蕾 -INSERT -騷棒 -恋爱盒子OL -颜骑 -騷棍 -bingnews -耿飙 -近亲相奸 背徳愉悦 9 -耿飚 -护法 -韩国身份证 -法院 -san guo qun ying zhuan -福爾摩薩 -筹码 -免费电影現役看護婦 -泄题 -捅她 -毛日Gm -你她馬的 -G。M -一四我 -肥东交警 -Tsubaki House-Triple Shot Vol01校花三姐妹 -大众真人真事 -航空母舰 -喷尿 -CAO NI MA -窝窝色网之家 -毛刘云山 -毛日GM -第七色明星淫欲 -毛李洪志 -G-M -FLG -空中小姐的淫蕩性生活 -淫肉誘惑 -灯草和尚 -方晓日 -肉棒的抽插…。好爽 -挺动我的下体 -国防科工委 -空降 -大奶美逼 -肉逼 -人學生meimei 埼玉援交 vol。2 なな&まい -玉穴 -搔meimei色站大全 -jiaochun -淫荡meinv医生 -抽插35岁处女妹妹淫叫不断 -我操你 -倒臺 -操浪妻淫女 -插的我好爽 -汉 奸 -妖媚熟母 -極品黑絲 -激情网站地址 -…好舒服 奸淫 操 -賣財富 -星战前夜 -毛泽東 -Tora-Tora-Tora Platinum Vol。9 Runa Mikami -fuck新华内情 -一夜激情成人聊天室 -ming yun -曾慶紅 -免费淫色论坛 -日本情色论坛 -品穴 -黄色免费淫奸电影我和女友干爽后再她meimei -makinglove -making -saobi -日本激情淫电影 -激情电影在线观看 -游戏向导 -老师和我做爱好爽 -阴茎插入肉洞里 -ya dian na -NeoSteam -色mm穴激情 -fuck新唐人 -火辣图片 -阴户紧紧包含着肉棒 -發正念 -淫色贴图365 -奇域 -百戰天蟲 -上有网 -跑跑 -毛李铁映 -小B样 -福摩萨 -私—服 -一卡多号 -桃色电影 -只允许法规年龄的人注册 -淫奸处女电影论坛 -浮夸风 -骚妈 -鸡巴插入花心 -salop -美女淫色贴图区 -处女 -插 9p -pussy -六决不 -淫汁飛散大亂交 -情色 美女 -公安机关 -记者 -犯罪嫌疑人 -處女開包 -白虎阴穴 -淫穴贴吧 -又粗又硬的肉棒 -一党独裁 -毛禁书 -售軟體 -骚女 -插 8p -金正日 -骚妻 -網路創世紀 -發$$倫 -毛昏药 -鸡巴……插死我了 -吴 仪 -商务部 -肉棒插入大肉穴 -狂插阿姨穴 -操的我好爽啊……我又要泄┅┅ -百家性大型色 -插 7p -和meimei肏屄 -遊行 -偷电 -龟头粗壮赤红 -管理 -淫荡女医生穴 -官商勾结 -小鸡巴 -插 6p -pp243淫色导航 -foseaon -继母的爱液 -骚妹 -色网阴道特写强奸30岁处女全过程 -中国民主党 -17大 -火药制作 -法仑攻 -明星合成图 -色meimei大型黄站 -中國遊戲中心 -语音激情视频聊天室 -赛福鼎•艾则孜 -(現映社)オバサマ5人 潮吹き絶叫雨あられ! -台湾20岁成人 -媽的B -发**沦 -fuck傻逼 -免费强奸电影 -碩大龜頭緊緊頂著她的阴道 -抽插24岁处女妹妹淫叫不断 -西藏分裂 -56xp。com 电影免费 -邝锦文 -董賤華 -tankbb -毛公安局 -gu long qun xia zhuan -马克思 -午夜成人电影 -penis -群魔色舞 -制服狩 -江Core -千岛湖之旅 -16大 -贛您娘 -大 纪元 -免费淫电影吴宗宪搞笑语录(25禁看) -贱 -六四 -古龍群俠傳 -鮑嶽橋 -打到共产党 -垮臺 -激情淫女小穴 -高潮集錦 -销魂洞 -吃大便 -血腥內幕 -肉唇 -不要将你的精液射进我的小穴了里啊 -罂粟 -吴 官 正 -机八 -台湾獨立 -足球经理 -換妻雜交 -父女姐弟淫乱 -肉棒插入阴户内 -抽插33岁处女meimei淫叫不断 -重题工 -处女心经 -后面插入处女的肉穴 -毛发伦 -小嘴吐出龟头 -監禁陵辱 -大众成人网 -降半旗 -港激情图源成人色情论坛 -長瀨 -支那 -164网址宽频影院网 -毛法轮大法 -儿子的肉棒好大啊 -發^掄 -無碼淫漫 -香港成人淫电影 -众志成城 -G_m -余震 -kamikaze girls 07 Nagisa Sasaki -fils de pute -肉棒嫩逼 -賤 -毛可卡叶 -fuck新闻出版署 -抽插 -肉棒放在阴道口 -打炮 -日穿 -八九民主运动 -靓穴美女 -美骚妇 -fuck信息产业部 -盐酸二乙酰吗啡 -吃鸡巴 -毛烂比 -QQ音速 -媚药少年 -三陪女 -地 下 刊 物 -免费淫乱电影 -胯下呻吟 -阿扁万岁 -欧美淫色贴图网址 -輪暴 -乡巴佬 -轮干 -測試员 -xing ji jia yuan -免费痴女吸精 -他媽地 -鄧穎超 -93bb成人小电影 -毛新闻出版署 -傻比 -那嗎逼 -亚洲无码 -妓女自拍做爱电影 -嫩肉 穴口 舌头 -和親姐姐作愛 -肉棒在小穴四周游移轻撩 -干meinv小穴 -大鸡巴干进meimei的小穴 -激情色 -楊思敏 -蒙巴顿 -宫泽Keito 超美系模特儿引退作 -suck -车仑女干 -天下無雙 -黑手党 -王鹤寿 -温比 -AV女优和平凡男人1日结婚 -强奸免费淫电影 -遊戲幣 -干八个美女的小穴 -毛对日强硬 -Neko GN Vol。1潮姬 史上最高之潮吹少女 -紅燈區 -易當 -大陆娱乐黄站 -色情导航 排行榜 -fuck -护士mm乱淫 -舔鸡巴 -自残 -玉蒲团讯雷下载 -最新n0242 东热RQ大乱交2007 Part1 -五月天 -嫖妓指南 -抽插30岁处女妹妹淫叫不断 -龟头顶住她的花心深处 -宁王府论坛 -拔出來 -八嘎 -屁精 -裸聊合法 -科技精英遇难 -2逼 老逼 -法棆功 -死GD -paper64 -fuck外/挂 -icpcn -冰风传奇 -梵高 -强奸 小穴 -3P -溫家宝 -淋病 -陽具 -偷情網 -江賊民 -天图 -操草拟妈 -免费淫奸女A片段试看 强*十八岁美女护士 -jy2 -hero108 -死GM -毛拍肩神药 -视频脱衣秀亚洲少女韩国无码片 -干你娘 -操出售手枪 -肉棒插进湿润花蕊 -fuck外-挂 -免费免注册淫电影 -色女 -jx2 -温州娱乐鹿城黄站 -四人幫 -亚洲淫色俱乐部免费淫 -溫家寶 -tie xue san guo zhi -魔性的meinv 鈴木麻奈美 -欣赏7感俏護士和医生22潮淫水图 -糞便 -fuck社。会。正。义。力。量 -淫奸妹妹穴 -龟头在阴唇上抽插 -minhui -免费处女淫女下载看电影性开苞 -插你爺爺 -骑士 -如果你未满29周岁请自觉离开。 -许家屯 -火辣圖片 -用骚痒难捺的阴部淫荡地摩擦着粗壮的鸡巴 -干你妈 -LIUSI -激情裸體 -杨建利 -轮 -毛干gm -手记注册日韩5027部激情电影 -毛买卖枪支 -巨乳護士南つかさ20連發中出 -台独靠 -毛你妈逼 -免费dse淫乱 -挥发型迷药 -中央電視臺 -射精时必须注意的几件事 -那嗎錯比 -抽插52岁处女妹妹淫叫不断 -教你怎样延迟射精38岁以下禁免费淫电影a片 -发@@纶 -禽兽集团%少儿禁 -激情淫色贴图导航 -VULVA -张 林 -操鸡 -鸟Gm -日你老母 -毛国家民委 -綠色灵数碼 -江八點 -臀部猛烈的撞击 -輪 -易志熹 -插你爷爷 -懷念十五年前的大學生 -轮奸内射 -李红志 -4f -大龟头顶住她的花心深处 -沾满蜜水又湿又滑柔软的 阴唇 -午夜情色电影 -大卵泡 -64 -老女嫩B -3D西游 -公審江澤民 -淫奸妹妹的屄 -猶太豬 -爽死我了 -小B樣 -鸟GM -共和 -淫电影//现场强奸19岁处女扒开小穴清晰做爱阴道裸体图 -淫穴贴图 -小穴 双手紧抓住 丰臀 -admin -姐姐的肥阴户 -日本激情淫色 -打倒中国共产党 -插入处女的肉穴深处 -成人激情asp电影通道 黄色免费电影 sp色情播放 -3p -俠客天下 -測試員 -淫荡美少女 -张 伟 国 -陈慧琳精品 -你二大爺 -它媽的 -你二大爷 -遊戲新幹線 -10 Little Asians Vol。 14~10人微乳素人娘~ -毛密宗 -露出了娇小鲜嫩的小屄洞 -tian di xuan men -毛色情小电影 -pao pao tang -那嗎瘟比 -嗎啡 -成人激情视频聊天室 -你的小穴好深啊 -免费淫奸女A片段试看 欢迎点击进入观看/林/心如/20岁处女偷拍/免费A。B片 -出售假币 -兒屆中央政治局委員 -毛海洋局 -骑她 -台湾万岁 -毛万税 -毛日gm -kao -14se淫色图片 -插烂meimei小屄 -网管 -肥逼 -做爱视频表演黄色小说 -fuck台湾民国 -扑哧一下鸡吧操进了逼里 -哥哥的肉棒好大啊 -Kamikaze Premium Vol。 8 -本土無碼 -毛日gM -无修正 -fantasyjourney -银行账號 -hrichina -躶 -淫水 …你的大肉棒 -Fku -黄色性交裸体图_做爱贴图性交成人贴图 -英雄世紀 -夢見る大和撫子 Pretty Little Asians Vol。48 -不注册免费淫电影 -18岁禁淫荡小处女 -ggol -美女视频图情色贴图区成人性光牒 -女人 -96 -出售枪支 -毛干gM -tmd -周锋锁 -中国猪 -鸦片 -激情成人电影 -boke -免费激情视频聊天室 -数码精灵 -罌粟 -女也 -激情淫色游戏 -总统号 -毛新闻管制 -钦本立 -四人帮 -插 4p -淫穴贴图论坛 -公告 -粗大的鸡巴穴洞 -操完姐妹操嫂嫂 -国务院 -完美时空 -小嫩穴把大鸡巴包得紧紧的 -龙新民 -足脚交 -注册激情电影 -三八淫 -机叭 -插 5p -十六大 -吗啡碱 -免费mm黄色淫乱电影 -飙车 -又嫩又紧的阴户 -电影下载 -愛的奉獻 -下载免费淫电影 -林心如合成淫照片 林心如淫照片 -淫电影//现场强奸18岁处女扒开小穴清晰做爱阴道裸体图 -香港淫穴裸体图 -苯環利啶 -yuanmingxinsheng -伸入蜜穴 -┅┅手握住我的大肉棒 -踢 -bong -台湾总统 -色网阴道特写强奸21岁处女全过程 -GirlDV热门成人影片 -性虎色网 -插 3p -愛的奉献 -毛狗日的 -怪兽总动员 -本站10018多部激情电影全部免费试看三天 -操黑 -毛司法部 -民政部 -毛丫的 -女乃 -trickster -毛小日本 -肉棒插入阴道里 -操比毛 -半夜我把龟头插进妹妹的深处 -Cs -毛六。四 -林伯渠 -曲线消魂 -爱的乱伦 -乱世三国 -激情淫bb -战国英雄 -bukkake -色屋图片 -未亡人柔肌 -陈军 -鸡巴射出精液  泄了 -毛孙文 -天怒 -斯蒂芬霍金 -黄孟复 -柔软的肉壁紧紧的包著龟头 -網絡公祭 -手淫 -遊戲米果 -脬 -日本成人电影 性生活影片 免费在线成人电影 -旅游局 -本站10002多部激情电影全部免费试看 -肉壶 -免费在线观看 -毛法愣 -X到噴屎尿 -dajiyuan -喪服妻欲望 -日本meimei -转化 -肉棒在子宫口游荡 -日本MM色比图吧 -歡迎G11情色電影院 -鄒家華 -無碼h漫 -朱巨 -Baopi -GY -中国论坛 -独裁 -龟头在阴户抽插 -抽插24岁处女meimei淫叫不断 -在线激情电影 -肉棒舌頭 蜜穴 -雙峰微顫 -有容奶大 -李总统 -操你媽 -GP -你的逼……真紧 -GN -GM -金槍不倒 -藤武 -外挂 -劉曉波 -薄码 -斯诺 -鑫诺 -二B -免费女A片段 -免费淫电影吴宗宪搞笑语录(22禁看) -银民吧 -毛肛门 -讨伐 -少女床上春色销魂 -毛麦角酸 -AV -中国人民志愿军 -……好粗…好舒服 -狂插meimei穴 淫水流 -大使官 -sheng da fu weng -岳武 -捏你鸡巴 -NET -tester -美女偷拍成人小说激情网香港激情图源成人色情论坛脱衣美女做愛 -毛届中央政治局委员 -血腥内幕 -把肉茎抽出插入屁眼里 -wu lin wai shi -帶套肛交 -操你娘 -狗诚 -BI -BC -曹庆泽 -美国成人激情网站 -清纯派meinv可爱的让人想狂干她!【RMVB/195MB】 -信息产业部 -CS -hdw -黑屄 -臺 -免费A片 -肉壁 -51淫色导航 -jiejie的穴好紧啊 -二b -套子 -三级片 -Bc -欧美大乳 -法稐功 -CM -操参事室 -366成人网站 -fuck色情 -强奸处女学妹 -捅他 -ttwg666 -暴淫 -淫妻浪女小说 -性宝贝淫色导航 -现场直播女主持人教你做爱 -日蛋 -MY -耣 -陈功 -法论攻 -漢奸 -李旺阳 -阴唇 -几叭 -军长发威 -阴茎在阴道快感 -亚洲激情淫色贴图 -大唐豪侠 -中国移动联电信午夜激情电影秘密通道 -風騷欲女 -毛郭伯雄 -一九八九年六月四日 -game master -龟头操进处女阴道 -浪少妇和医生疯狂做爱 -狭义道 -毛干你娘 -可愛均整清純派美女可愛均整清純派美女 -虐待 -自慰抠穴 -fuck王八蛋 -机巴 -屌7 -洞抽少妇 -kang zhan -fuck色情服务 -淫网 -星空幻想 -毛反华 -mo你全身 -毛人民银行 -监管局 -视讯情人聊天室 -自杀指南 -外掛 -免费成人影片 -Gm -肏 -毛二屄 -强*十八岁美女护士看完保证你打飞机免费淫电影a片 -捅你 -手伸到儿媳妇下体抚mo嫩穴 -蜜穴裡輕插緩送 -轮功 -meimei的小嫩穴 -中华讲清 -黑客 -肛 -熟女护士 -唐人互动 -bastard bastard -超级诱人销魂表情免费播放变身辣妹 插入妈妈白嫩的诱惑 -联通移动秘密通道情色电影午夜成人电影 -65情网色论坛色情电影 -歡樂性今宵 -J8 -吹萧 -唐人互動 -JB -谭震林 -毛激情电影 -免费淫奸女片 -流蜜汁 -淫聲浪語 -SM插进湿润的小穴 -盛雪 -猛男狂干美女 -發~掄 -美女裸体在线免费淫电影 -feng yun -肉香 -国家分裂 -欧美激情淫色贴图网 -薄碼 -extremeskate -63xp。com 电影免费 -fawanghuihui -龙与地下城 -毛干你妈 -發*淪 -人斩少女3赤裸忍者 -林慎立 -肉棒插入少妇嫩穴 -又肥又大的阴户 -LB -飄流幻境 -厕所盗摄护士jiejie性感 -毛透视眼镜 -兔meimei贴图区 -日b -高潮集锦 -处女的阴道特别紧 -45xp。com 电影免费 -小乳头 -U R靠 -成人电影,黄色电影,色情电影,免费电影试看 -花花公子 -警奴 -朱总理 -偷窥图片 -风骚少妇 -残忍老爸玩我小穴 -UR -本站10010多部激情电影全部免费试看三天 -百家性大型黄色站 -抗曰 -FLG媽B發掄 -免费激情聊天室 -少妇房中自淫,和两勇男玩5P,操得直叫爽 操日本淫女穴 -茎 -朱德 -incest -淫亂熟女 -國家總理 -注册激情电影(切记只允许法规年龄的人注册)注册快感吧!! -里根 -TW -金城安娜-痴女教官NO。7 -犯践 -黃色小說 -强奸轮奸美女视频 -Wg -毛干GM -…好舒服…小穴 -粉嫩人妻在老公面前被人搞 -狂插日韩骚逼打飞机必看 -魔法飞球 -郭 平 -国外激情淫色贴图 -奸淫女老师 -发**抡 -犯踐 -亚洲午夜激情那个电影中心 -运营商 -老毛 -WG -老比 -高岗 -悠遊網 -發$淪 -毛干Gm -李山 -毛基督教 -淫妹阴毛小穴 -老母 -性电影免费在线试看 -清华同方 -毛江独裁 -妹妹被操的淫水直流 -本?拉登 -奶头 -99BBS -嫩穴美女挖嫩穴淫女嫩穴俱乐部 -黄色免费淫乱电影 -亚洲情色套图 -就去日 -fuck外汇局 -日Gm -遇难 -操淫荡meimei穴 -牛顿 -曰本 -激情淫电影 -QB -遇難 -tian zhi lian yu -美女嫩穴 妹穴 亮穴 女人穴 -阿不來提•阿不都熱西提 -肏又大又嫩的屄儿 -j8靠 -日本淫色 -毛乳房 -日GM -huan le qian shui ting -保釣 -肉棒插入小阴户内 -pnisse -【亚洲/无码】Mugen Vol。11 Ai Hazawa羽沢愛!【AVI/ 699MB】 -魔法飛球 -骚妇激情 -我含住他的阴茎 -SM舔穴 -天安门事件 -本站10021多部激情电影全部免费试看 -做爱网有激情自拍裸体 -奸淫电影 -jinyong -监听器 -肛门潮吹 极太合体 原千寻 红音 桜田 -meimei做爱 -百家性大型色站 -西藏独 -成人激情网站 -硬挺 -po tian yi jian -殺你一家 -Sb -色情成人网站 -臺灣島國 -天安門殘案 -allbisexual。com -扮开嫩穴 -SM -婷婷口含鸡巴 -十八代 -搔meimei黄站 -日本成人 -龍圖智庫 -毛反动 -SB -倡议书 -股市民谣 -可待因 -现场强奸18岁处女扒开小穴清晰做爱阴道裸体图 -亚洲成人贴图区论坛 -fuck我妳老爸 -肉棒抵住阴唇 插入 -?(SOD)超天然素材 桐島あゆみ -舌战法庭 -極品波霸 -色97愛 -ERA OF FAITH -给你爽 -周容重 -喪服妻欲望下载 -奸她 -犯賤 -轉法輪 -抗日 -吳 百 益 -退黨 -你它媽的 -毛反共 -发轮 -jiejie的肥阴唇 -gth -49xp。com 电影免费 -午夜成人激情聊天室 -湿淋淋的骚阴道 -毛人大 -大陆娱乐鹿城黄站 -她妈 -snk。ni8。net -苯环已呱啶 -姐姐的嫩阴唇 -摇头玩 -冈峦 -毛口交 -秦青的幸福生活 -亚洲激情无码BT -阴囊 -毛文物局 -delete -色 -赵紫阳 -激情淫色贴图区 -張德江 -肛门 -肉棒用力的抽插着小阴唇 -射进妈妈里面 -成人情色网站 -免费在线黄色小电影 -163网址宽频影院网 -鬼公 -TokyoHot之极品meimei -ㄙㄞ你母 -奶娘 -激情玩穴电影 -苏绍智 -阎安 -错B -肛門 -黑窑奴役 -性爱护士 -泡泡堂 -操臭化西 -ZD -免费淫乱电影下载 -粗大的龟头缓缓磨擦着湿漉漉的阴户 -告全体网民书 -saohuo -在骚穴里抽插著阳具 -urTNND -luan shi san guo -d p p -the world of legend -回良玉 -两会新闻 -銀行帳號 -掌上靈通 -错b -老师的阴道好紧 -免费看三级电影淫电影 -她娘 -在线小淫虫电影 -淫之学妹喷尿射得好高 -1989年6月4日 -毛江猪 -pp点点通 -法伦功 -切七 -哲民 -护士小穴 空姐小穴 -QQ堂 -昏药 -saohuao -操 淫荡 好爽 -meinv主持26小时全天激情热舞 -公务员的工资 -奸夫淫妇 -淫糜 -妹妹的阴户 -喷 射 -免费淫 电影a片。母子淫奸乱轮现场 -強制フェラ 失神セックス -沒有人權 -烏雲其木格 -game MASTER -玉女吹箫的姿势和技巧图 -联总 -丁香大型成人社区 -緊縛淩辱 -人性本色 -政治局 -日本淫电影 -蒋树声 -遊戲發獎員 -母子姦情 -鲍威尔 -fuck退党 -日B -龙洲影院日本娱乐性免费电影 -紧缚凌辱 -妳马的 -AVW FUCK DOWN!最后性 -日你奶奶 -国家安全 -亚洲区人妖射精图最淫人体网站 -fuck驶你娘 -代表大会 -集團熟痴女川奈-南智子-澤宮有希-櫻田由加里4時間 -gM -装B靠 -独占动画~女热大陆 file 2 -駛你娘 -fuck系统公告 -她馬的 -日你爺爺 -gy -天使之恋 -qiangjian -蒋经国 -操妳祖宗 -gn -gm -heatproject -军妓 -臺湾國 -大鸡吧插妹妹 -阴唇阴道 -blowjobs -耶和華 -奶大穴肥多条肉棒难满足 -瞿秋白 -gp -dong fang chuan shuo -saga -藏春阁【全免费】 -发^^论 -JOB -無碼H漫 -yong bing chuan shuo -数通 -中国政府 -用舌头舔着大小阴唇 -他妈的靠 -meinv嫩穴淫水直流 -你奶奶 -dao jian -fuck系统 -毛私-服 -省長 -g8 -平可夫 -肏屄 -老骚货 -省长 -包二奶 -operator -国产骚货 -内射 -搔穴自慰 -项小吉 -那娘老比 -白虎陰穴 -夢城互動 -运营官 -淫电影//教你如何鉴别处男处女的方法 -浴室自拍 -凌辱?妥?学?@~??Δ畏耪n後~ -gamemaste -meteor academy -黑马@SQ Evolution Vol。3 柳濑遥 -日你爷爷 -拉客 -cS -bt -反封锁技术 -集體淫 -流口水啦 -lovebox -六四点击 -亚洲淫色贴图论坛 -18摸 -弟弟淫奸姐姐 -肉棒 高潮 -郝建秀 -毛农业部 -毛塞你公 -騷浪 -杨勇 -毛私/服 -日本激情淫色视屏 -cs -王稼祥 -毛色情 -1001an。com -臭化西 -K粉 -藏独 -法仑工 -抽插46岁处女妹妹淫叫不断 -成人bt -膀胱 -jiaochun -学运 -毛国安局 -抽插47岁处女meimei淫叫不断 -淫奸小姨子穴 -da hua chun qiu -毛虐待 -fuck十五周年 -刘晓竹 -失密 -歡樂時代 -射精 -毛阴部 -不爽不要錢 -爱爱激情电影 -穷逼 -干阿姨小穴 -卖骚 -肉棒插入阿姨 ……爽呀 -傻瓜 -几八 -发论 -au -水从穴里流出来 -奇淫寶鑒 -jinv -做爱淫乱小说 -军委 -毛粮食局 -我和二姨在车上舔 -痴女護士 -厕所盗摄meinv淫穴 -嗎個 -色网址联盟 -抽插婷婷 -时事论坛 -meinv小穴贴图偷拍少女乳房 -賽博先鋒 -BT淫穴 -毛一贯道 -東升 -尚禾 -港澳办 -韩国激情淫色网站 -Mai骚 -身寸米青 -法$$仑 -操妹妹湿穴 -性高潮 -轻轻地抽插著阳具 -插嫩穴 -婷婷激情俱乐部导航 -葵 -关卓中 -鹿城黄站百家性 -毛乳波臀浪 -胴体 -色网阴道特写强奸25岁处女全过程 -小姨子她饱满乳峰上的粉红乳晕 -蝴蝶谷淫图片 -国家领导人 -Reign Of Tera 2 -美穴 -文 革 -新人×ギリギ 七海 -萋 -阿姨的大阴唇 -出墙红杏 -playboy -胸部 -奴隷调教 -我的淫荡老师 -顶级轮奸套图站 -操穴插逼 -藏獨 -免費性愛電影 -阴唇上摩擦着 -凯丰 -久之游 -想插穿她那肥嫩的小骚屄儿 -淫穴自拍 -摸你全身 -陈云 -發@@掄 -戳比 -国民政府 -遺言 -龟头顶住她的阴户 -日本淫荡meimei -item -T。M。D靠 -聖戰 -文九天 -现代情色小说 -梅花网 -jx -婷婷俱乐部 -抽插41岁处女妹妹淫叫不断 -草枝麻 -阳具 -我 操 穴 -毛六四真相 -欢乐性今宵 -杨思敏 -和姐姐淫穴 -老江 -吗啡片 -黄色我该死免费淫奸a片偷拍MM接客宾馆 -超女世界Online -GAMEMASTE -洗钱 -orgasmus -黄蓉舔小龙女的乳头 -色情網站 -叔嫂肉欲 -飘飘 -塞白 -眯眯爱大型黄站 -妹妹陰毛 -色淫成人 -小穴 -成人色情 -大师 -押小 -夜夜色娱乐网 -大肉棒…插我……」 -春城娱乐(淫窝) -骚批 -挺送 肉棒 激烈 撞击 -反社会 -法$$伦 -j8 -肛jiao -抽插著阿姨的淫穴 -免费淫女在线看电影 -中国军用运输机 -機戰 -操逼毛 -jiejie的阴道好紧啊 -肉棒不斷的抽插著她的肉體阴道口 -免注册淫电影 -淫荡少妇被轮奸 -天安門一代 -onlineworms -李师付 -狂插喷爱液 -八九學潮 -jb -赛博先锋 -meng xiang -毛天安门录像带 -張万年 -肉棒插进阴户里 -h站 -干死客服 -不爽不要钱 -日gM -美女淫水狂流 -淫穢 -做爱电影 -免费淫奸女A片段试看 强*十八岁meinv护士看完保证你打飞机 -Test -meinv 淫穴 -peng peng bang -毛鸦片液 -%共產黨爛逼 -丰盈雪白的肌肤、肥嫩饱满的乳房、红晕鲜嫩的小奶头 -wg -完美時空 -黄色文学 -鸡吧插进 -65xp。com 电影免费 -jiba -蘋果日報 -淫穴 -免费成人电影图片 -抽插34岁处女meimei淫叫不断 -臺灣 -新闻办 -官人我要 -大鸡吧插meimei -喷你 -騷水 -wG -meinv鸡吧图 -操母狗 -日本巨乳淫女 -現場直播~女主持人教你做愛 -fuck新手指导员 -天使之戀 -台湾18成人小说 免费成人电影 -王宝森 -賣軟體 -視娘辣妹 -毛妓院 -骚妇掰B -超级乐者 -战牌 -ur -轮大 -江湖 淫娘 -yuming -法$$侖 -鸡歪 -tw -教你怎样延迟射精39岁以下禁免费淫电影a片 -仙境传说 -毛鸦片渣 -不玩了 -骚妇掰b -免费A片观看 -小穴被插的好爽啊 -毛换妻 -和妹妹肏穴 -成人情色导航 -阴户抽插 -抽插34岁处女妹妹淫叫不断 -鲍鱼 -现代学生妹操屄水平真是高 -我上小姨子小说 -拔屄 -唐捷 -阴道抽搐一阵暖流自子宫深处涌向龟头 -抽插21岁处女妹妹淫叫不断 -聚友网络 -sm -淫秽 -拉法叶舰 -sf -观看淫电影 -新疆国 -國家分裂 -梓霖 -sb -小女嫩穴 -把舌头伸入jiejie的 -林伟 -新疆國 -墮淫 -日本素人 -午夜激情美穴贴台湾性福联盟 -手记注册日韩5006部激情电影 -ro -全國人大 -蘇秀文 -诛仙 -毛信息产业部 -毛四川独立 -ri -再奸 -法惀功 -發@淪 -爽女美图美搜性感图涩界成人电影网小小鸟绝色meinv写真图 -lisishijian -轮奸 -毛透视软件 -國民黨 -色慾 -杨周 -何加栋 -肛屄 -肉便器 -屁眼 -毛罗 干 -金发表姨花蕊,少女的狭窄洞口 -System -全身一阵颤抖 大鸡巴 -fuck小肉粒 -騷母 -日gm -淫女乱搞免费三级片 -伸入jiejie裙内 -騷比 -qb -archlord -毛台办 -法$$倫 -毛恶搞晚会 -法囵功 -强奸23岁处女全过程/*妹阴毛小穴 -天安门残案 -大雞巴 -二奶大奖赛 -毛阴道 -李师傅 -色情 -dick吕秀莲 -配合着蜜洞内肉棒的抽插 -我咧干 -恐怖主義 -五月天成人激情网站 -xia yi dao -mannweib -fuck新华社 -獨立 -毛敬国神社 -干x娘 -又大又粗的肉棒 -又深又紧的穴 -抗战 -奸杀美女大学生 -fuck我操你 -毛他妈 -抗戰 -顶进少妇的花心 -疯狂的抽插起来 -makinglove -搶 糧 記 -大麻树脂 -每天24小时循环更新的免费色情内容 -rxjhwg -激情免费电影 -大鸡巴插进她肉洞里 -騷洞 -51xp。com 电影免费 -成人小说 SM 做爱 -肉棒顶的人家小穴好痒 -乱伦之淫骚穴 -操你妈 -传奇3G -netbar -傅鐵山 -姜春云 -招妓 -口含鸡巴 插入阴道 -噗嗤一声滑入阴道 -浩天银科 -窃听器材 -tantra -操陈晓宁 -群奸輪射 -色meimei淫穴 -宋慶齡 -女添男精狂射图 -免费淫色情电影 教你怎样延迟射精18岁以下禁免费淫电影a片 -hun -手记注册日韩5032部激情电影 -达芬奇 -宏象 -六四回忆录 -洪哲胜 -淫荡娇妻打开双腿 -奧巴馬 -夜情 -毛林彪 -抽插54岁处女meimei淫叫不断 -我把艳姨给干了 -tiang tang -口含龟头 -神出鬼没!3个丁字裤辣妹到处袭击肉棒(中文字幕) -妹妹的小穴……舒服死了…… -夫妻多p -caob -肉棒噗嗤一声滑入阴道 -亚洲免费黄网 -阴茎插入少妇阴道 -点击这里试看美女做爱现场 -日本淫穴电影 -成人影院 激情影院 -电视流氓 -香港激情图源成人色情论坛脱衣meinv做愛 -喇嘛 -體奸 -u r靠 -game MASTER -海盗时代 -我和姨在车上干 -赌马 -性生活 -威而柔 -免费淫奸女A片段试看 处女第一次阴道做爱全过程(全套图片) -heatproject -日你爸 -法十轮十功 -大鸡巴插进小穴 -毛你老味 -梅花網 -海明威 -kuaik -混蛋神风流史 -做爱视频 -fuck台办 -无码淫女 -审计署 -教室里淫乱狂搞 -pute -初流出!ロリプリ -人美乳甜屄嫩操起来真爽 -性交内射 -操大逼 -发~~纶 -GC365 -麻醉乙醚 -毛十年动乱 -默哀 -夜色聊人 -处女第一次阴道做爱全过程(全套图片)免费淫电影a片 -鑫諾 -毛血腥图片 -自焚 -62xp。com 电影免费 -毛片空姐的嫩穴裸体明星夜总会小姐贴图 -rxjh -Crazy Fuck : Miki Uehara 上原美纪 -MK 星云 -操逼 -吹簫 -免费淫奸女A片 -an hei zhi men -情色聊天室 -淫奸医生 -vrtank -系統消息 -联易 -希望之声 -淫电影//现场强奸20岁处女扒开小穴清晰做爱阴道裸体图 -GAME master  -断电 -廉政大论坛 -性感meinv淫穴 -经济社会理事会 -成人性交视频 -毛回教 -追查國際 -騷媽 -小唇被他的嘴巴包裹住 -105bb成人小电影 -骚乳 -san guo ce -性戰擂臺 -淫奸女电影直接试看 -删号靠 -性交图 -插的妹妹好爽啊 -性交圖 -發^侖 -voachinese -一夜性网 -露乳 -洪 传 -meng huan zhi xing -淫电影论坛 -凱圖科技 -儿子顶到妈妈的花心 -法仑功 -淫奸meimei电影 -rivals -互友财富 -輪功 -人體攝影 -处女第一次阴道做爱全过程(全套图片) -luan -严家祺 -子宫口吮吸着龟头 -fuck新闻办 -回民人吃猪肉 -吸精 -fuck卫生部 -淫色网站导航 -淫蜜 -小泉纯一郎 -齊藤亞樹 -参事室 -毛反政府 -乱伦之淫穴网 -又粗又长的大肉棒 -泳衣+丝袜~让你销魂舒畅 -免费电影吸精痴女 -短信猫 -大 参 考 -强奸22岁处女全过程/*妹阴毛小穴 -未满19岁的请自行离开 ! -总统的讲话 -淫奸jiejie电影 -痴女/淫乱 看護婦/女医 剃毛/パイパン!【AVI/723MB】 -姐姐的小穴 -情色BT -fag -kang zhan -张榕明 -發論 -洗肠射尿 -品色永远免费淫电影 -赤裸 -他嗎的 -射顏 -激情视频女半夜播放成人节目免费裸体视频 -林心如做爱网有激情自拍裸体图片 -脚交 -淫奸电影 淫色猎暴淫电影 射雕淫女传 风骚小龙女 美女淫女图-小龙女淫女俱乐部影 在线淫电影 -仙侶奇緣 -北美自由论坛 -英雄online -删 号 -香港 -发@@论 -毛干死你 -兩國論 -放荡 -狂插 肥穴 -淫奸小姨论坛 -检察院 -啊……快插啊……小屄要美死了…… -射颜 -争鸣论坛 -公务员工资 -充值 -小姨子她饱满乳峰上的粉红乳晕,金发表姨花蕊 -meimei的淫穴被龟头顶住 -发抡功 -免费注册看免费电影通道 -傅杰 -毛反封锁技术 -penis -掰开少女穴 -肉丝裤袜 -黄易群侠传 -你妈比 -阴沟 -舔我的龟头 -騷妹 -大鸡巴插进妹妹的小穴 -騷妻 -骑他 -大鸡吧插妹妹淫屄 -張 偉 國 -Angel Cosplay Vol。 2 新村爱加贺美由贵 -Tora-Tora Platinum Vol。8 宫泽Keito 完全无修正第二弹 -滕武 -發^倫 -18岁少女破处 -Red Hot Jam Vol。6 露出初体验~Chia -插後庭 -毛伊拉克 -U R靠 -非常漂亮的日本美少女,日起火! -阴水 -欠日 -工作人員 -胡嘉 -50xp。com 电影免费 -騷女 -鹿城大型黄站 -毛老毛子 -龟头用里插入阴道 -装逼 -re xue jiang hu -抢尸 -娄义 -大鸡巴顶进妹妹的花心 -他娘的 -肖强 -押大 -运营人 -毛侨办 -免费淫电影a片 -淫蟲 -早洩 -屄屄特寫 -賣騷 -成人贴图区 -好大的阴户 -李维汉 -裸体插淫穴 -淫驴屯 -免费淫电影吴宗宪搞笑语录(28禁看) -武力统一 -欧美清晰打炮淫乱人妖淫乱图 -shemale -rxwg -gameMASTER -吹箫 -解放军镇压 -三国群英传 -發$$掄 -猛插小护士骚穴 -奸幼 -preteen sex preteen sex -long zu -曹建明 -李红痔 -CAO -穿著PE校服 -成人夜话 -法仑共 -骑你 -法仑公 -共青团员 -砍翻一条街 -aszol -免费淫奸女A片段试看 瞄準她的肉穴插了進去…… -免费成人图片 -放蕩少婦賓館 -gamemy -中国最淫的免费淫图图 -毛天安门一代 -滚那吗老比 -顺着大鸡巴湿淋淋的流下 -媽的騷穴被你插得爽死了 -a片 -清晰內射 -工作人员 -激情玩淫穴电影 -亚洲乱伦之淫穴 -妹妹吸精 -国内动态清样 -骚B贱 -6。4 -贱逼 -阴毛 -浴室乱伦 -毛廁洞 -酥穴 -东热RQ大乱交2007 -舌头舔弄着小穴的内壁 -成人網站 -亚洲互动 -情色艺术天空 -激情淫色下载 -江口美貴 桃咲あい 早乙女みなき 雨宮せつな -欧美成人贴图区 -骚 -黑鲍娇 -插入小姐的嫩穴 -追查国际 -成人色情图片 -台湾成人激情视频聊天室 -免费午夜艳情电影 -欠操 -淫奸………啊 好舒服 -肉慾 -毛伊朗 -抗震救灾 -互舔淫穴 -大比 -抗震救災 -狂插少女的嫩bb -guild wars -潮喷 -我和妹妹肏穴 -陰核 -出售此号靠 -賀龍 -和婶婶做爱 -香港免费黄色淫乱电影 -草擬媽 -淫奸jiejie穴 -eve -毛乳 -無碼長片 -少妇房中自淫,和两勇男玩15P,操得直叫爽 操日本淫女穴 -发~轮 -幹你妈逼 -日本黄色三级短片 -少妇贴图穴论坛 欧美淫色贴图区 -舌头舔着阴核 -强奸17岁少女全过程 -性爱 电影 -午夜免费视频激情聊天室 -fuck外专局 -马凯 -毛基地组织 -……好舒服 舔穴 -教你怎样延迟射精34岁以下禁免费淫电影a片 -干他 -女幹三虧 -妹妹 -中国之春 -超美女优MUGEN EX Vol。 7~浜崎ひめ -transsexuell -發@@綸 -騒 -明星裸体写真图 美女网络视讯三点 -搶劫犯 -法~轮 -淫妻爱好者 -盐酸二乙醯吗啡 -杨怀安 -法$$沦 -大陆免费黄站 -新语丝 -抽头 -毛新疆独立 -騷 -免费淫电影下载地址 -风骚小阿姨 -新闻 -事实独立 -欧美激情穴淫奸 -日本女优 -曹你 -芸能人使い捨てM奴隷DX 聖乃マリア nike 新片! -斑竹 -星際家園 -性奴會 -淫奸meimei论坛 -超爽艳图 -liu xing hu die jian -阎王 -美女视频短片 -臺獨 -法~輪 -毛姣西 -残忍的虐待强奸美丽的淑女 -釋迦牟尼 -放蕩 -洪 傳 -黑社會 -压迫 -联梦 -adult -淫蕩 -母乳と巨乳と淫乱の完熟物語 -那吗错比 -扬振 -潮噴 -干X娘 -fuck私服 -强硬发言 -肉棒插入少妇的阴户内 -台湾青年独立联盟 -温 元 凯 -朱勝文 -肉棍狂插 阴精 -哥哥淫奸妹妹论坛 -法菕功 -干你 -18男人momoB -抽插25岁处女meimei淫叫不断 -践踏中国女性 -輪奸大美女 -龟头通过子宫口直抵花心 -金玉天立 -抢劫犯 -肉棒插入阴道 - 瀬咲るな -g。m -毛叫小姐 -meinv嫩穴 妹穴 亮穴 女人穴 -母亲 -北极冰 -誘姦 -mabinogi -嫵媚挑逗 -meinv与猪性交电影 -水滸Q傳 -亚洲成人激情淫穴 -暗黑之门 -妹妹小穴 -淫奸姐姐论坛 -【亚洲/无码】【极品荡女-宝乃ありか 完結版!】【WMV/358MB】 -幹他 -夜色淫女导航 -嫩穴 狂 插 -操操你 -效忠天皇 -抽插小淫穴 -迷幻藥 -大鸡吧顶进小穴 -少妇房中自淫,和两勇男玩6P,操得直叫爽 操日本淫女穴 -淫妹妹成人情色论坛 -毛连战 -舔吮 乳房 干小穴 -幹您娘 -曰你 -開苞 -吞精 -情色成人视频聊天室 -韩国激情淫色贴图 -pk1937 -淫獣圣戦 XX+圣獣伝 ツインドールズ -肉棒插入meimei的肉缝 -本站10016多部激情电影全部免费试看 -毛洪兴 -去氧麻黄堿或安非他命 -斷电 -毛靖国神社 -紫瑞专业 -毛民政部 -大胆少女 -毛生鸦片 -妳娘 -武林群俠傳 -矽穀動力 -计生委 -张伯笠 -淫荡女生 -地球文明 -淫驢屯 -嫩穴meinv挖嫩穴淫女嫩穴俱乐部 -老瘪三 -和阿姨做爱 -一党专制 -操淫荡少妇穴 操淫荡妹妹穴 操淫荡姐姐穴 -和jiejie肏屄 -美腿 -幼交 -陈毅 -Offgamers -插入姐姐蜜穴 -聚梦 -掌上灵通 -错逼 -淫穴摩擦龟头 -fuck骚 -新华内情 -我就色 -雞女 -操操他 -大鸡巴┅┅太棒了 -笨逼 -淫meimei成人情色论坛 -银行帳号 -鸡巴蜜穴高潮 -雞奸 -毛人民广场 -換妻大會 -亚洲激情影院论坛 -淫虫 -六四屠城 -江油余震 -幹的爽 -我妳老爸 -阿沛 -歡樂潛水艇 -百家性超级淫色图片 -操穴贴图 -淫虐 -张廷发 -免费a片日本淫电影 -被干的喷水的高清图 -刀OL -打砸抢 -牛逼 -我的性启蒙老师 -毛XX -淫色电影网站  -毛推油 -奸情 -滝沢优季 Prisoner Of Love绝爱的监禁牢狱 -…用力干…嫩穴紧插 -东北风情熟女之惑 -阴唇湿润小妹舔乳 -破处 -granado -付申奇 -毛卖党求荣 -大 參 考 -meinv潮吹 -盛华仁 -毛社会主义 -阴穴新玩法 -台湾自由联盟 -fuck孙文 -操淫荡护士 -傻屄 -中国分裂 -淫民激情文学图库专题 -奥巴马 -法**倫 -抽动肉 -現金交易 -超级淫图 -發~侖 -16dy-圖庫 -小穴流出汁液 -毛石进 -screw -老癟三 -陰戶 -日本激情图库脱衣裸体做爱 -手伸到儿媳妇下体抚摸嫩穴 -淫民俱乐部日韩激情片 -情色导航 激情爽电 -調理勞務系 -激情视频在线 -淫妹妹电影论坛 -被奸淫的女教師 -巨乳俏女醫 -ggq -免费淫区隐蔽入口 -雅典娜 -大中华论坛 -深夜進入少女家中玩強奸 -meinv性交极品大片 -玉蒲团玉女心经 -vip在线成人电影 -*法*轮*功* -qq音速 -星蓝妹妹 -fuck洗脑班 -發~倫 -军事委员会 -色中色网址大全 -淫荡 -TABLE -雞吧 -gamegold -想上你 -拉凳 -李金華 -minghui -神話R。Y。L -五星紅旗 -yifeng -18歲淫亂 -迷幻药 -法**侖 -小穴被我操的红肿 -肉棒肉洞 肉缝 -代链 -人民大會堂 -毛强奸 -车仑 -毛烂屌 -日本淫色动画贴图 -巨奶 -好嫩 -女尔 -妈妈 -鰢 -SM援交 -www。ccwcc。cn -溫比 -多维网 -潮吹 -激情在线 -蔣中正 -大肉棍… …干的 …好舒服 -偷情男女 -后面插入处女肉穴深处 -你娘卡好 -laqia -女尻 -情色天堂论坛咪咪情色论坛 -Arisa Kumada -鹿城黄站bt -快活林情色网 -入穴一遊 -淫水翻腾 -激情淫影片 -367成人网站 -女屄 -毛烂屄 - 夏树唯 -混沌诀 -gcd -毛鸡叭 -淫荡的小穴 -阴核 -dh315 -meimei黄站 -*李*洪*志*靠 -淫奸妹妹电影论坛 -色欲 -啊无卵 -酥痒 -蒂巴因 -磨得人家小穴……好用力……好酥 -弟弟淫奸jiejie穴 -免费在线收看淫色电影 -肏又紧又嫩的穴 -美女走光 -日你老娘 -Tokyo Neko ATN-002 東京猫 Vol。 2 星川はるか -官人我要2 -做爱图 -法**伦 -毛私服 -拉手冲 -清晰内射 -干你妈B -台聯 -饿比 -免费a片 -gay -台联 -流星蝴蝶劍 -乱伦熟女网 -gan -叶群 -中国游戏中心 -母亲の结婚生活完全版 -cheng ji si han -17岁处女小阴唇张开 淫水流出图强奸免费淫电影 -無修正 -陷阱超人嘩嘩曼 -雞叭 -大卵子 -奶子 -毛宋楚瑜 -法**仑 -龟头已顺利挣开她紧合的阴唇 -大纪园 -处女穴 阴唇 肉缝 -做爱自拍 -毛毛贼东 -龟儿子 -机机歪歪 -毛破鞋 -吸吮着红嫩的乳头 -月经不调 -shengda -来回去舐她的小穴 -官人我要1 -kele8 -小卵子 -売春婦 -情感视频欣赏 -宋美齡 -社会主义 -毛meimei淫色 -bjzc -法黁功 -舌尖不断在肉缝里上下舔着 -激情论坛 -駛你爸 -性爱图片 -亚洲激情淫洞 -紅衛兵 -欲火焚身 -酥癢 -绵阳 -fuck驶你爸 -肉棒触碰前面的肉穴 -幹死客服 -火辣寫真 -妹妹的淫穴被龟头顶住 -宋美龄 -毛外交部 -jiejie的小穴 -毛毛厕洞 -严方军 -金毛学生妹 -封神傳說 -林心如做爱网有激情自拍裸体 -苯甲基芽子堿 -女优爽图 -乱伦淫穴 -干你妈b -学生爱国运动正名 -舌头伸到妈妈的小穴里 -yuanming喷你 -妹妹阴毛 -和熟睡的妹妹做爱教你一手 -中廣網 -激情淫色电视 -毛日本RING -淫奸小姨子电影 -segame -美女性生活贴图 -马三家 -热 站 政 论 网 -鸟g M -看牌軟體 -生奸内射 -調教虐待 -毛晚年周恩来 -日本激情片论坛 -妹妹的嫩屄 -一九八九六四 -猪容基 -气性坏疽病 -毛塞你娘 -操陈希同 -流星蝴蝶剑 -激情淫穴小妹 -换妻杂交 -戳那吗比 -胸垫 -阿姨和我乱伦理小说 -舌头舔小肉縫 -南蛮子 -张筱雨 -不良詞語@美乳女神RINA(中文字幕) -毛温加宝 -姐姐的嫩穴 mm嫩穴 -fuck上妳 -鸡巴受不了了┅┅喔┅┅好爽┅┅我要泄了┅┅ -近亲相奸 -插淫女小穴 -你老母的 -香港情色俱乐部 -毛温总理 -創意鷹翔 -戴晶 -李 总 统 -激情視頻 -群奸乱交 -钱 国 梁 -國家主席 -日本成人淫色DVD -fvc -聖母 -口肯 -无码精选 -电车之狼 -Shine -大陆黄网导航 -qq自由幻想 -naked naked -绵陽 -鸦片渣 -你全家 -卢福坦 -a片试看 -fy0 -18dy粉红色高跟鞋 -拐卖 -15年纪念日 -毛原子能机构 -jb靠 -吃精 -本站10018多部激情电影全部免费试看 -毛干你妈b -母子做爱 -早泄 -成人a片 -戒急用忍 -西藏問題 -密穴贴图 -fv( -高畫質~ 超絕美貌社長秘書 佐佐木渚沙!【WMV/102MB】 -女幹 -淫B浪女 -释欲 -成人激情导航 -她的阴道好紧啊 -激情影片网站 -fuc -po tian yi jian -白浆四溅 -采花堂 -扒开她的嫩穴 -fuk -免费在线激情电影 -放荡少妇 -女干 -淫腔 -19岁女生主动让男生开苞全过程◥免费黄色电影 -帕巴拉•格列朗杰 -毛多维社 -毛鸡八 -日本成人乱伦 -龟头用力刺入淫穴 -汪东兴 -姐弟淫乱小说 -男女蒲典 -d7se淫色穴图片下载 -曹刚川 -西藏問题 -又大又肥的屄 -淫奸jiejie meimei MM 姨妈 舅妈直到流水 -三K黨 -cdjp李鵬* -毛火棒 -破坏 -fu( -我和jiejie肏穴 -男人本色 -雪白的屁股对着肉棒 -拳交 -舌头舔小肉缝 -仙界傳 -无码无套 -美女 成人 -鸡 -鸠 -毛meimei免费电影 -姚文元 -釋欲 -鸨 -淫荡校妓 -傻子 -六四回憶錄 -毛江择民 -常劲 -馬克思 -CNN -鸡掰 -轮公 -灌滿精液 -电影免费试看片 -巨屌 -暴动 -planetside -BnB -淫奸护士小说 -草你 -色站排行导航 -色女免费黄色小电影 -輪奸 -欢欢娱乐时空 -如此大的肉棒插的小穴快不行了 -发@@轮 -Shit Shit -毛他爹 -soul ultimation nation -少妇被操穴 -Kamikaze Premium Vol。 25:特級神風~榊彩彌 -省長的兒媳婦 -又鸟女干 -毛法轮功 -太子党 -阴道好紧插起来那真是爽极了 -騷卵 -阴茎插入肉洞 -海盜王 -美女主持26小时全天激情热舞 -免费裸女视频聊天 -日死 -看高潮屋 -褲襪 -輪姦 -少年阿宾 -毛妈逼 -四川獨立 -情色成人论坛淫图导航 -巨炮兵團 -無盡的任務 -天暢 -紧紧的小穴 -huan ling you xia -絲襪美腿、痴女、女同 -16dy-图库 -GAME -赛她娘 -回民吃豬肉 -搏客Online -菜B -18dy免费 -新絕代雙驕 -淫色 -党卫兵 -fku -姐姐被插的好爽 -14岁幼女B嫩阴 -耻辱轮奸 -flg -民主黨派 -大东亚共荣 -美丽女教师的性经历 -小淫女 -毛江八点 -熟女家政妇 山本ちづこ -厕所盗摄护士jiejie性感美腿图 肉丝美腿艳情淫欲 -巨炮兵团 -亚洲成人电影 -毛斯大林 -妓女 -弟弟的肉棒好硬啊 -抽插41岁处女meimei淫叫不断 -智凡迪 -毛监听王 -抽插19岁处女meimei淫叫不断 -偷拍 -暴動 -鸦片液 -超级舞者 -周天法 -摇頭丸 -支持達賴 -淫妹妹成人娱乐 -蔣樹聲 -可爱卡通小穴 -插的妈妈的小穴好爽 -海盗王 -红灯区 -日比 -免费在线淫电影 -毛新闻出版 -fuck鲜族 -爛B -嚴雋琪 -欧美淫奸女直接试看 -肉棒插 淫水 -毛人民大会堂 -姐姐和我乱伦理小说 -大煙 -毛红卫兵 -黑马@meinv全身神秘黑让你爽到眼框黑 -民意论坛 -国研室 -又深又紧的阴户 -魔幻森林 -风骚小女孩湿身露体 -fuck上你 -贱女人-淫护士 -大陆淫乱meinv图图片 -逼 -在线播放a级电影 -淫奸小姨子论坛 -肉棒直插花心 -共党 -qq幻想 -抡功 -免费淫电影吴宗宪搞笑语录(26禁看) -北韩 -全 国 两 会 -新西游记 -恥辱醫護免费下载 -扒屄 -swdol -高俊 -卖逼 -重生 -勃不起斯懦夫 -江贼民 -肉棒插在阴道里 -給你爽 -插小穴射了 -操护士穴真爽 -温B -法$$抡 -阴茎被小穴紧紧包住 -zhengqing -冒险岛 -趙紫陽 -抢劫 -母子奸情 -奸染 -鸭店 -欠干 -毛多维网 -cronous -发~~沦 -温b -共军 -欠幹 -骸卒 -姐弟激情淫乱 -like999 -xia ke tian xia -淩辱 -夏赞忠 -男人看的猛爽电影 -手记注册日韩5026部激情电影 -kuai le xi you -尉键行 -法*轮 -毛莫索里尼 -喷精 3p -法@@論 -菜b -qqtang -sanguohx -清华网管 -性虎色網 -发**仑 -拉丹 -洗浴间爽奸白嫩美乳少女 -姐姐的嫩阴户 -5kuai -放蕩少婦 -激情性爱电影观看网 -什么什么大冒险 -天安门一代 -毛泽东 -ㄙㄞ你娘 -嫩穴任我插 爽 -極品波神 -毛东突暴动和独立 -婚外恋 -毛系统 -毛几届中央政治局委员 -huo xian ren wu -共青團員 -台湾盲人美女在家疯狂做爱 -巨商 -毛靠腰 -发**伦 -小穴夹着肉棒摩擦阴道 -变态小日本街头强制脱衣最新加强版多片 -极品成人3gp -傻B江核心 -jiejie和我乱伦理小说 -我操 -淫の方程式 -肉洞 肉棒 肉缝 -群奸亂交 -月卡 -人 民 內 情 真 相 -洗着鸳鸯浴操屄真惬意 -鹿城最新娱乐bt 色情365 -re xue ying hao -天下无双 -狂操 插 干 老板娘 -f u c k -mm激情穴贴图 -騷批 -毛鸟你 -tian zhi lian yu -毛法功 -本站10011多部激情电影全部免费试看 -粗长的大肉棒 -百家性淫网站 -官方工作員 -qi yu -sheng zhan -溫加寶 -苏家屯 -三個呆婊 -美女电影 -100bb成人小电影 -淫逼 -shu ma jing ling -昱泉 -胡平 -啊……阿姨要洩了…… -吗b -中宣部是中国的艾滋病 -亚洲激情淫色电影 -台灣獨立 -精液射入穴中 -张闻天 -哈批 -淫荡妈妈骚姊姊 -阿拉 -奸暴 -塞你老师 -マーメイドになった「恋から」ギャル。岡島優里(全编) -操出售假币 -淫淫电影 -鋼甲洪流 -18岁 青▲学院中学1年生 -鹽酸二氫埃托啡 -luan wu tian xia -处女开苞 -xizang -色网阴道特写强奸22岁处女全过程 -阴道里的大肉棒用力顶着 -生奸內射 -89动乱 -毛伱妈 -淫奸女图片 -百家性大型黄站妹妹 -Tokyo Hot n0249 : 南丽美 菊攻无限中出39连発 -用力扣进小穴 -官方工作员 -环保总局 -hanbiton -你她马的 -地下教会 -毛卖卡 -fuck威而柔 -狂插少妇穴 -装屄呢 -shen qi -fuck水去车仑 -Queen8 社长秘书のパンスト -劳动保障部 -毛售软件 -共鏟黨 -亲哥哥……妹妹的小穴……舒服死了…… -大龟头顶住花心 -林心如掰穴自拍 -笨蛋 -花柳 -法^論 -錢 達 -聊齋艷譚 -fuck台湾党 -本站10001多部激情电影全部免费试看三天 -胡耀邦 -迷歼药 -胡錦涛 -王昊 -文胸 -颜色革命 -粉屄 -精液直射入她的小穴深处 -共匪 -阝月 -塞你老師 -拉皮条 -ttmd -qi ji shi jie -少妇房中自淫,和两勇男玩2P,操得直叫爽 操日本淫女穴 -毛美国佬 -楊震 -李登柱 -我日 -免费在线看淫电影下载 -鹽酸二乙醯嗎啡 -淫奸女护士电影 -插如妈妈肉穴 -肉棍 -华夏Online -手指拨弄着穴口 -劳+教+所 -肉棒 -傻逼靠 -屌西 -淫贱 -抽插22岁处女妹妹淫叫不断 -抵制 -骚浪人妻 -男女交欢 -你操得我更爽 -成克杰 -淫贼 -儿子顶到阿姨的花心 -长身丝袜美女~赤く烂れたマンコが痛 -操小姐b -额尔德尼 -如果你未满23周岁请自觉离开。 -鈤 -恥辱醫護电影在线观看 -hai dao wang -痴meinv醫生松島 -獲救 -刘国凯 -成人A片 -法@輪 -淫货 -男女交歡 -法^^輪 -史玉柱 -無碼絲襪 -阴道里嫩肉把鸡巴包得紧紧 -cnd -政府软弱 -塔利班 -堂品色 永远的免费色堂永远免费 -陈宣良 -妹妹做爱 -a$$hole -大肉棒深深地插 -你马的 -ustibet -教你怎样延迟射精30岁以下禁免费淫电影a片 -杨得志 -聖火 -歡樂城 -毛酱猪媳 -我该死视频做爱 -奸淫护士 -dtfy -7。22 -suck你妈的 -少妇野外淫穴电影 -皇軍 -法@轮 -法^^轮 -毛民航局 -8岁女生主动让男生开苞全过程 -毛董文华 -操你媽的 -江擇民 -剑侠世界 -毛天安门档案 -溫總理 -她NND -hai zhi yue zhang -丁香成人论坛贴图区 -免费淫色meimei电影网 -小逼 -濫交 -淫貨 -姦夫淫婦 -插入阴道里抽插 -发纶 -二B 帝國 -人 民 内 情 真 相 -身寸 -援交自拍 -安全隱秘 -美女出租车内强行进入 -二B 帝国 -杀人 -淫色影院 -婚外戀 -胡紧掏 -孙家正 -连线机 -毛蒋中正 -升达 -bao皮 -操宾周 -吗的 -55xp。com 电影免费 -毛瘸腿帮 -毛国家主要部委 -暴徒 -淫賤 -小穴的淫骚香味┅好爽 -亚洲淫图 -超級舞者 -兽交 -renewal -鸡店 -法^论 -如来 -無碼做愛 -腾讯 -骚女叫春 -程铁军 -成人午夜场 -dong fang chuan shuo -孟建柱 -色97爱 -毛萨达姆 -fuck售ID -fuck驶你母 -李 总 理 -淫女小电影 -晚年周恩來 -黄色情挑艳情小说网骚meimei成人论坛 -meinv嫂子的小骚逼 -法$$掄 -售号 -毛计牌软件 -裸露自拍 -毛是鸡 -Tokyo Hot n0252 : 原田友美 高飞车美人教师精液轰沈 -腳交 -奸一奸 -丫头养的 -ADMIN -wizardsoft -超淫荡丝袜meimei -傻B靠 -做爱 -雞八 -双鞋的故事 -自拍寫真 -共產黨 -美国之音 -插的妈妈好舒服 -帐号 -qi ji -激情影视 -教你怎样延迟射精25岁以下禁免费淫电影a片 -毛国资委 -毕加索 -fuck性交 -大東亞 -哥哥用力舒服死我吧 -tampon -乱伦小说 -b样 -法@@论 -肉欲 -vrtank -外专局 -暴干 -chuan qi -Admin -可愛虎牙學生妹 -政變 -知的障害 -滑湿小屄洞 -如果你未满20周岁请自觉离开。 -發輪 -MADELOVE -无码 -鎷 -日本成人激情短片 -李長春 -baopi -免费成人meinv -舔 b -美女主持24小时全天激情热舞 -爛逼 -王超华 -可哥精 -和meimei肏穴 -小骚屄儿meimei -欲女 -饿b -统计局 -王 秀 麗 -插穴 美穴 ……好爽 -淫奸女护士 -毛迷魂药 -meng huan xi you -八 仙 -石戈 -8 仙靠 -小穴流水妹妹手指插 -波佳达 -免费免注册淫色电影 -成人免费黄电影 -登辉 -饿B -urban-rivals -厦门大游行 -骚卵 -1989 事件 -手记注册日韩5004部激情电影 -激情淫 -生徒胸觸 -手指不断在肉穴扣弄 -毛林业局 -暴幹 -生徒胸触 -zirui -姐姐的小穴被大鸡巴插得好舒服哟 -无套肉棒浓稠内射漂亮屄 -邢铮 -操你老妈 -八九 -群p -尉 健 行 -用舌尖在我的肉棒上舔 -FUCKYOU -顏騎 -嫂嫂淫穴 -fuck外\挂 -受精 -batard -毛干你妈逼 -東突暴動和獨立 -集会 -鸠屎 -抽插 磨蹭 穴 B 逼 -媽個B -大陆鹿城 -和meimei玩插穴 -嘻遊中國 -钱达 -哀悼 -1989#天安门 -骚包 -售卡 -你老母 -藏婦會 -血洒天安门 -性器肛门~原千寻、桜井 -G m -天浴 -x到噴屎尿 -成人18免费电影 -腾人 -zhongguohun -毛她妈的 -姚月谦 -博讯 -色狼 -購金 -强奸19岁处女全过程/*妹阴毛小穴 -G M -胡錦濤 -Tibet独立 -天下貳 -毛花柳 -毛军事委员会 -軍妓 -毛小肉粒 -垃圾游戏靠 -擠母奶 -妈妈的阴道好紧啊 -成人午夜場 -saobi -亚洲激情成人电影 -东洋屄 -天安门母亲 -群P -无须注册淫奸小电影 图片 -插小穴meimei直流水 -鸡吧菊花穴 -騾幹 -江西大余池江中学女教师(绝对真实)」 -援交妹 -强*十八岁美女护士看完保证你打飞机免费电影 -色猫 -月經不調 -木子论坛 -抽叉姐姐 -暴奸 -fuck傻B -法论公 -幹你媽 -抽插45岁处女妹妹淫叫不断 -法论共 -老师干的我好爽 -辽宁女 -台湾成人黄色网站 -Fuck You -安全局 -八仙 -轻轻地抽动著阳具 -妈批 -美乳艷娘 -TENGREN -龟头紧顶她的子宫口 -铀 -發**倫 -亂倫熟女 -大字报 -中国人民解放军 -又嫩又紧的屄 -柯庆施 -操你老娘 -何候华 -黄克诚 -亚洲激情淫电影 -李 祿 -法十輪十功 -美少女FUCK限界大挑戦 -f a l u n -李长春 -PUSSY -信長之野望 -李 禄 -母子乱乱论 -现金交易 -色色成人 -赛妳娘 -抽插42岁处女妹妹淫叫不断 -榮毅仁 -毛黑社会 -毛黑手党 -少女 被 插 -獸欲 -xin mo jie -妖美巨尻物语 - 风间ゆみ -碧香亭 -89运动 -美女主持脱衣 -(國產)視頻-网吧老板玩穴 -肉棒压着阴蒂 -少林傳奇 -毛天安门屠杀 -湿穴 -kai tian -偷拍美穴 -色情排行榜 色情导航 -教养院 -毛人民 -共产 -厕所盗摄美女淫穴 -点击观看*林心如做爱*色情电影*免费淫电影a片 -口内爆射 -日爽 -嫩鲍鱼 -淫奸护士电影试看 -午夜淫电影 -淫水自乐 -最新99bb)有名女优~松岛やや -戈扬 -美女直播做爱 -河利秀失控全裸+深夜成人節目 -都江堰 -DELETE -搔妹妹色站大全 -香港激情图源成人色情论坛脱衣meinv做爱 -fuck四川独立 -裸体贴图香港成人电影网 -可怜系新人美少女甘南三才 -激情淫色贴图 -做爱在线观看 -Kamikaze Girls Vol。29 铃房ありさ -江猪媳 -Red Hot Jam Vol。10 高树圣良 -骚屄儿 -肉洞 -成人性爱视频 电影 聊天室 -去你妈的 -疯狂jiejie淫穴 -Early Melissa Lauren -李志绥 -完蛋操 -鲁迅 -insert -gamemaster -馬英九 -燕玲论坛 -g m -集体性爱 -工力 -鸡巴对准柔软的阴肉缝沟 -肉棒的抽插……干的好爽 -毛乔石 -插meimei淫屄 -法~論 -用他的舌尖舔着我的乳头 -亚洲淫娃 -fuck外_挂 -jiejie和我乱伦理电影 -毛卖国 -SARS -sphincter -台灣國 -肉棒插入meinv的肉缝 -法论功 -西藏 -正悟網 -用你粗大的肉棒 -魅惑巨乳 -台灣国 -性保姆被雇主掀翻在高潮 -陈一谘 -fuck食屎 -達賴喇嘛 -日本RING -fuck台湾独立 -銷售 -强奸19岁处女全过程/淫妹阴毛小穴 -gangbang -毛刘少奇 -草妈 -本站是国家合法电影网请您用手机注册~! -两国论 -风艳阁 -大法 -人肉搜索 -教你怎样延迟射精31岁以下禁免费淫电影a片 -揉阴核与嫩肉 -风骚侍女 -天下贰 -ying xiong shi ji -猛戳阴穴 -腾仁 -大波 -MM屄 -插穴手淫 -毛蒋经国 -布什 -奸淫嫂嫂 -鸡巴 -腾任 -裸陪 -肉沟 -台独分子 -尸虫 -弟弟淫奸熟睡jiejie -小姨和我淫BB小说 -幹你娘 -护士掰开阴道插B -pao pao dao -跟meimei肏穴好舒服 -一夜性網 -李总理 -huan le qian shui ting -17game -小穴淫图 -少妇床上的激情 -顶进她的花蕊 -博訊 -天安门录像带 -牛魔王 -红十字會 -质检局 -一次可看四位meinv同床較勁很可愛的女主角 -骚穴淫液 -抽插19岁处女妹妹淫叫不断 -成人激情影院 -peng peng bang -淫西 -肉棒在乳沟来回猛抽 -哭夭 -吸精少女 -回民暴 -dpp -狂操丰满小姨穴 -明星淫圖 -帝國主義 -将肉棒对准她的穴口 -法^輪 -陰 -贱货 -三级电影网香港色情服务 -红楼美穴肛交淫图 -淫奸电影 淫色猎暴淫电影 -公车奸美女淫奸女电影试看。 -大鸡吧插又肥又嫩的屄儿 -Tora Tora Gold Vol。18 : 冈田さな Sana Okada -你大爷 -明星淫图 -欧美成人帖图区 -你大爺 -少妇房中自淫,和两勇男玩13P,操得直叫爽 操日本淫女穴 -狗操卖逼 - 菊地麗子 -李大師 -懶教 -操你妈靠 -成人自拍 -成人激情电影 -屁蛋 -大纪元 -小穴在上下套动 -丁字裤 -中国留学生--张丽 双插 -silkroad -操雞 -中华大众 -lei ting zhan dui -求救遭拒 -操朝鲜 -强奸少妇 -毛卖号 -发$$沦 -淫奸美女图 淫奸刘亦菲 -毛泽东靠 -鸡巴 嫩穴 嫩肉 -淫色貼圖 -法^轮 -多维社 -無套內射 -李大师 -强奸处女学妹,摄像机拍下强奸阿姨。 -胡錦淘 -幹你媽b -火线任务 -强*十八岁meinv护士看完保证你打飞机免费电影 -fuck信访局 -女学生拍我该死 -无界 -中國共產黨 -移动联通秘密通道 -精液射如妈妈的穴 -法~论 -淫師蕩母 -雞 -日本騷貨 -操达赖 -ボインお姉さんお色気修行! みさき優香 -艾滋 -人民内情真相 -省长儿媳妇 -日本激情淫色文章 -系统讯息 -大陆娱乐免费黄站 -多維週刊 -jin wu shi jie -大卫教 -蝴蝶逼 -激情聊天 -阿扁 -新天翼 -厕所性感meinv清晰淫穴 -17Game -性福联盟 -插那吗比 -日本领事馆 -隂 -信访局 -淫meimei电影 -新光明 -ever quest -名人大道 -毛美利坚 -利瓦伊汉 -滚那吗 -最强美乳初解禁 -歌华 -狂插meimei小穴 -去你妈 -hanbit -摸咪咪 -中国社会论坛 -曾道人 -美女主持25小时全天激情热舞 -毛太子党 -打野炮 -御の二代目 -毛退党 -gun gun qiu -陰屄 -那吗瘟比 -毛台湾狗 -淫电影网 -台盟 -淫乱小穴 -八仙靠 -免费秀聊视舞聊天网 -FLG 妈批 -原子弹 -私!服 -建设部 -中國性愛城 -戀愛盒子 -金枪不倒 -豔婦淫女 -李 總 理 -精子 -风骚淫荡 -Sex Sex -尾行 -手记注册日韩5033部激情电影 -wanwang -Party -欧美激情淫影院 -色女脱衣秀 -独立 -丰盈雪白的肌肤肥嫩饱满的乳房红晕鲜嫩的小奶头 -妈的骚穴 操 穴 逼 -操他妈 -毛你姥 -变态~幼男插嫩屄 -靠 -嫩穴【极品】阴蒂 -姘头 -毛马英九 -成人百強 -chao nv -毛黎阳评 -成人百强 -天游 -六合彩 -妓女自拍 -駛你母 -猪猡 -交換夫妻 -自治机关 -不用注册免费小电影骚b免费色电影免费 -fuck台湾国 -騷屄 -87bb成人小电影 -毛你娘 -萨马兰奇 -温元凯 -開發 -張立昌 -厉无畏 -wangyou99 -嫂狂欢隔壁小弟打手枪 -拉皮條 -免费裸体美女性交电影 -胡錦滔 -傻批 -滥比 -搔妹妹黄站 -网址情色成人大全 -监禁陵辱 -Pink Puncher)Double FACE -你姥姥 -帕巴拉?格列朗傑 -玉杵 -d f d z -愈快乐愈堕落 -传销 -法@@轮 -色情論壇 -Barefoot Confidential 46 -欢城 -你娘咧 -阴茎在殷素素的阴道里抽插 -Voyage -呆比 -恥辱醫護bt下载 -陈水扁 -偷歡 -干姐姐小穴 -投毒杀人 -牛B -fuck靠 -market -法(輪)功 -阴户 -meimei MM激情 -日王 -后备专员 -色情服务 -免费淫色电影 -輪公 -肉棒在阴道内抽插 -毛你妈 -花心成人论坛 -meinv性生活贴图 -免费成人美女 -特派员 -舔她小穴 -大家论坛 -正邪大决战 -世界经济导报 -法@@輪 -裝備展示 -肉棒狂插女人小嫩穴 -手记注册日韩5034部激情电影 -免费午夜爽片 -dse淫乱小说在线看 -舌头舔进阴道 -偷欢 -成人激情爽电影 -艳照 -她妈地 -强奸十八岁美女护士看完保证你打飞机免费电影网站 -梦幻国度 -自拍淫荡骚妇们的性福 -meinv下体淫水直流 -毛王震 -滿洲國 -幼女嫩穴 -六四參加者 -和两勇男玩37P -成人网站导航 -tian long ba bu -在线玩美美免费电影 -法$论 -新疆独 -GM001 -六四风波 -snk。ni8。net -黄菊 -cai hong qi shi -av成人网 -新生网 -扒开她的小穴穴 -氣性壞疽病 -张晓丞 -毛静坐 -biao子 -六四動亂 -乳此動人 -奴事件 -和两勇男玩38P -性交無碼 -admin靠 -滚那吗错比 -法*論 -免费淫电影吴宗宪搞笑语录(24禁看) -针孔偷拍 -熟婦人妻 -fuck新闻管制 -89動亂 -作秀 -插逼清晰图 -手机注册看激情电影 -piss -和两勇男玩39P -rfa -本?拉登 -毛meimei黄站 -米开朗基罗 -温暖湿润的感觉笼罩龟头周围 -本站10015多部激情电影全部免费试看 -核工业基地 -强奸轮奸meinv视频 -wowjingye -自杀手册 -愛圖公園 -集体淫 -鸡巴插进小穴 -两性电影在线免费欣赏 -手分开嫩肉缝 -90bb成人小电影 -肉棒插干她的小穴 -和两勇男玩33P -佛祖 -督察 -强奸41岁处女全过程/淫妹阴毛小穴 -chuang shi ji -狂插美女穴 -罗 干 -chui chui -台独 -郭盈恩挑战性交吉尼斯(对256男)直播全记录 -和两勇男玩34P -卡通动漫meinv淫乱 -mo li bao bei -抽插48岁处女meimei淫叫不断 -插烂她的小屄 -精液射在meimei的子宮 -六四之前 -猛插林心如小穴 -看完保证你打飞机 -肉棒插入美穗子的肉缝 -是雞 -和两勇男玩35P -群交 -粉红的的奶頭粉嫩的阴唇 -香港淫穴 -網捷信 -欽 本 立 -谢中之 -龟头挤进了姐姐的小穴 -花园bt亚洲激情区 -穴淫贴图女人穴贴图穴淫液贴图 -黃菊 -陰穴新玩法 -成人色网 -和两勇男玩36P -幼男做爱meimei做爱 -bi xue qing tian -AV成人影院 -刘俊国 -刘宾深 -毛英雄纪念碑 -教你怎样延迟射精37岁以下禁免费淫电影a片 -操meimei湿穴 -傷亡 -gu long qun xia zhuan -極品白虎 -嘭嘭幫 -amateur -fuck台湾帝国 -陈良宇 -殺手 -娇嫩的蜜穴 肉穴 -help -大鸡巴 干进 小穴 -张开双腿 菊花穴 -龟头挑逗花蕊嫩肉 -穿豹紋的美女,很有野性美。看她咬著肉根就可看出來。 -超級乐者 -大 中 国 论 坛 -十三點 -滥B -亚洲性虐 -手指还插在她的淫穴 -發^^綸 -公安局 -口味稍重 CD2 -社。会。正。义。力。量 -台獨 -毛军国主义 -鹿城黄站小说 -淫亂潮吹 -嘭嘭帮 -九霾 -性战擂台 -强*十八岁meinv护士 看完保证你打飞机 -走向圓满 -足球經理 -维护 -台湾午夜色情小说 -鰻の罪と泥鰌の罪とレズ陵辱 -免费淫奸女A片段试看 少妇扒开阴道图 -一起玩游戏网 -puneta puneta -rmb -操抽你丫的 -快插吧!┅┅快┅┅ -毛台湾国 -法$論 -走向圓滿 -亚洲电影区 -发~~抡 -六四运动 -浪妻淫女 -法制办 -車侖 -性交电影 -淫奸少女穴 -品色堂 -毛去死 -hero -日本骚货 -免费电影欧女乱欲 -白液四溅 -做爱激情小电影 -魔鬼曲線風騷女优青木玲 - FACE 68 -动漫色图 -最淫官员 -muhon -耶稣 -陽痿 -法(輪)功 -看完保证你打飞机免费电影网站 -毛三陪 -操小姨子穴真爽 -陈炳基 -高级卖淫女确实不一般 -黄色 -wowsupplier -肉棒插入美穗子的肉縫 -熟婦騷器 -minpaonews -推油 -用力操舒服死我吧 -肥穴姐姐 -亲爱的快操我的B -耶穌 -民國 -走私 -干出淫水 -騰訊 -欧美无套 -海科數碼 -肥美的阴唇 -Pink Puncher~美熟女淫乱乳娘~Erotica : 友惠 -美护士是男人操屄的目标 -民国 -月經 -da hua zhan guo -鮑彤 -抽插43岁处女妹妹淫叫不断 -怎样延迟射精26岁以下禁 -新生網 -肥嫩的阴部 -中國成人論壇 -网域 -xi you fu mo lu -阴缔 -鸡院 -成人淫伦 -淫荡女医生 -激情网站 -臺灣獨立 -realextreme -fuck傻比 -法~纶 -毛阳精 -鹿城免费黄站 -淫奸小电影 -手记注册日韩5009部激情电影 -南蛮 -怎样延迟射精19岁以下禁 -监察部 -我该死免费色情电影 -国土资源部 -周旋 -普贤 -就去誘惑 -东亚共荣 -操你爸 -紅 色 恐 怖 -AV-熟女 五十路 -故知新 -藤由美 53- -成人激情电影在线播放 -数据中国 -免费淫电影吴宗宪搞笑语录(23禁看) -激情淫洞网站 -龟头挤进了紧窄湿润小嫩穴 -免费淫*黄色电影a片 -吸吮肉棒 -新金瓶梅 -xin jiang hu -卖b -林心如毛片 -捅入meimei的阴道 -zhang chang -大*FA弟*子 -粉嫩粉嫩的小穴 -做爱淫图 -小幼女开处清晰大图 -阳精 -騷B -驶你公 -luan wu tian xia -鳥g M -抽插40岁处女meimei淫叫不断 -沾满了淫 -毛马卖马屁 -卖B -淫女在线看电影 -混乱冒险 -av成人电影网 -海科数码 -温逼 -徐建国案件 -顶进嫂子的花心 -色情激情电影观看 -奴役童工 -媽逼 -顶到妈妈娇嫩的花心 -成人激情网站大全 -抽插 …好刺激……好粗… -fuck天鹅之旅 -情色电影 -国家主席 -毛你妈的 -不用注册免费淫电影 -周鐵農 -本站10004多部激情电影全部免费试看三天 -鸡巴插小穴 -桃园蜜洞 -星际家园 -强制执行 女体崩壊~1 -淫奸女教师穴 -臺灣共產黨 -fuck小泉纯一郎 -發~~論 -中文情色网站 免费母子乱伦 -嗯┅┅嗯┅┅舒服死了……meimei又要丢了 -操吃大便 -小穴流淫水 -李登辉 -毛江贼民 -Homosexual -免费meimei黄色淫乱 -华夏II Online -祁培文 -法**抡 -清秀巨乳学妹校园内被轮奸 -毛温馨 -fuck天安门录像带 -Media -司马晋 -欠人骑 -美女嫩穴淫水直流 -F。L。G -人妻色誘 -毛卖财富 -南京大学法学院 -小比样 -插暴 -鹿城百家性大型黄站 -氵去 -gmworkers -她媽地 -乳霸 -張 宏 堡 -肉棒挤入蜜穴 -淫水涟涟 -他妈靠 -六四之后 -交配 -柔软红嫩的小阴唇 -小嫩雞 -毛国民党 -淫奸姐姐穴 -塞你母 -吸毒 -豬頭 -Government -妈妈屄好痒呀 -愛滋病 -啊… 你弄的我好通啊 不要……不要…… -99Baby Sana Okada in Maid -走向圆滿 -滾滾球 -殺人犯 -天安門慘案 -柔软红嫩的小阴唇紧紧地护住她的阴道口 -165网址宽频影院网 -fuck是鸡 -和两勇男玩30P -走向圆满 -白液四濺 -喔┅┅我又要泄┅┅泄了 -人妻色诱 -法~綸 -護士誘惑 -你以为你装逼就能骗我 -成人导航X色成人导航 -激情淫穴 -秘裂 -幼女开雹 -無毛穴 -张 昭 富 -吴邦国 -政治迫害 -血灑天安門 -hui huang -毛华国锋 -性骚扰 -毛江戏子 -完全免费电影在线看 -和两勇男玩32P -毛迷奸药 -親日 -u r -阳具插入小肉穴 -幼女小嫩穴 -和两勇男玩31P -日本淫荡妹妹 -毛反恐委员会 -激情淫窟 -ON9 -Premium)オトナの変态●稚园 神谷姫 -淫情贴图 -靠夭 -假币 -鸡巴插入蜜穴 -long hun -妹妹的小嫩穴 -jiejie的嫩穴 mm嫩穴 -怎样延迟射精21岁以下禁 -e Idol Vol。19 杏童なつ!【RMVB/698MB】 -完全自由注册看成人电影 -53淫色导航 -李德生 -chong wu wang -fuck神通加持法 -pp点点通色穴激情片 -看牌软件 -朱镕基 -淫女小穴 -Lady Sonia-熟女丝袜 13 -情色影院 -用力狂插骚穴 ┅┅好爽 -罢吃 -将则民 -淫靡 -kqking -八九事件 -少女露嫩穴 少妇嫩穴 meinv的嫩穴 -嫩 流 插 肉 -初中妹妹的小美穴 -法**掄 -双腿夹著我的腰部使我的肉棒进入的更深 -反中游行 -bing feng chuan qi -舔b -哈宝 -阴精 -mo你鸡巴 -大鸡巴小浪穴 -兩個中國 -百纳成人激情影院 -蒙古鞑子 -fuck希拉克 -讓你操 -18歲淫亂 -肏妹妹淫屄 -五奶小青 -可怜卖菜妇 -侠客天下 -毛牛逼 -爱色cc -粉红穴 -舔B -ryl -毛劳+教+所 -美乳 -烂游戏 -性娱情色导航 -野性家庭教師 -网 特 -阴道好紧 -插入jiejie蜜穴 -小MM -中青旅創格 -王胜俊 -亂倫之公公與兒媳的秘密 -阴穴 -jushang -密穴貼圖 -激情MM -学生妹 -粗壯的肉棒插入淫蕩的小穴 -绝对女神 -GAMEMASTER -嫩b -賤逼 -和两勇男玩7P -令人喷血的春宫108姿势(组图)21岁禁看 -游衍 -淫荡护士 -游行 -操B指南 -裸聊 -血腥衝突 -几届中央政治局委员 -紫黛 -勞+教+所 -帝國傳奇 -美体艳姿 -群陰會 -国资委 -快樂西遊 -激情导航 -和两勇男玩6P -小参考 -blueeye -免费观看淫电影 -法*輪 -黃色文學 -姐都快被你搞死了! -和两勇男玩49P -姐弟淫乱 -深喉 Deepthroat This 8 -吾尔开西 -少妇房中自淫,和两勇男玩20P,操得直叫爽 操日本淫女穴 -封杀 -tengren -档案局 -和两勇男玩5P -ㄙㄞ你公 -黄翔 -三挫仑 -刘丽英 -操春药 -超英赶美 -丝路传说 -夫妻俱樂部 -成人淫乱小说 -爛貨 -日本成人激情影院 -鸡巴 淫穴 -jian你 -法轮攻 -反腐败论坛 -圣堂科技 -和两勇男玩4P -毛性欲 -塞你爸 -激情電影 -賣逼 -美腿丝足 -毛奸 -pusium pusium -情色影院 导航 18岁禁看 -meinv主持脱衣 -猪毛 -免费在线淫电影网 -GM -和两勇男玩47P -床上激情淫乱小搔穴 -抽插52岁处女meimei淫叫不断 -肉棒插进肉洞里 -中央政府 -毛你爸 -日本女优8分钟长片 -fuck温家宝 -法^^论 -台湾一夜激情成人聊天室 -台湾 -滾那嗎瘟比 -握住阴茎看准肉洞猛的一下插了进去 -GY -毛发论公 -教你怎样延迟射精35岁以下禁免费淫电影a片 -MM的小穴 -和两勇男玩3P -淫荡少妇穴少妇嫩穴 meinv的嫩穴 -倭寇 -www。zqrl。com -性交淫图 -和两勇男玩48P -罢餐 -大阴唇姐姐 -男女激情淫乱图 林心如合成 -十景缎 -操淫荡少妇 操淫荡meimei 操淫荡jiejie 操淫荡护士 操淫荡 空姐操 老师操女老师 学生操老师 操老师小说 -靖国 -測試 -法$轮 -navyfield -游戏蜗牛 -sex -摸你鸡巴 -和两勇男玩45P -免费淫色情电影 瞄準她的肉穴插了進去…… -毛一鲜 -淫女吃鸡巴 -处女阴道库 -穷b -阴壁肌肉紧紧挤压着棒鸡巴 -無產階級 -聖泉學淫 -史迪威 -fuck体育总局 -mo fa fei qiu -嫩B -法@论 -和两勇男玩46P -激情淫穴网站 -俞正聲 -林果 -陆定一 -國研 -点对点裸聊 -毛希拉克 -操陈功 -成人贴图网站 -毛撒尿 -法$輪 -革命 -小比樣 -罢食 -毛游戏宫理员 -毛巡查员 -妹妹的穴好多水 -北美仙人球碱 -梁擎墩 -manager -揚振 -网捷信 -初二辣妹 -龟头插入肉縫 -李登輝 -一夜九次郎 -狗日靠 -密洞 -色情小电影 -成人色站 -干老师小穴 -胡緊掏 -逼孕套 -專政 -免费淫电影,看完保证你打飞机 -朱琳 -鸡巴便结结实实的插进娇嫩的花蕊 -极品波神 -成人书库 -性欲喘息教師 -淫奸护士jiejie穴 -陽物 -mir3 -测試员 -mi zhuan -全免费淫色情电影 -快活林导航 -你媽逼 -枪决女犯 -一黨 -bitch -日本激情淫穴网站 -三去车仑功 -jiang shan -小穴收缩颤抖著 -十八淫妹电影 -triangle -學生愛國者運動證明 -Gm -毛外专局 -毛妓 -免费淫电影论坛 -方舟子 -露屄 -淫奸女护士电影在线免费观看点击进入 -测試員 -一党专政 -军火价格 -毛李先念 -59xp。com 电影免费 -玉蒲团 -舌尖刮著陰唇上的淫水 -法^^論 -我和小姨淫穴 -激情淫色文章 -屄屄特写 -免费试看片 -我是g和m -掛機 -毛发论功 -如果你未满33周岁请自觉离开。 -它媽地 -meinv孩含双棍玩内射 -金毛穴 -白粉 -游戏宫理员 -毛古方迷香 -他爸爸 -六四动乱 -毛贺龙 -日本淫荡女孩 -狂插 浪穴 -中华人民共和国 -淫水丝袜 -静坐 -玉蒲團 -露阴照 -和两勇男玩9P -rplan -肉棒插得我好爽 -大龟头戳进了子宫里 -斯蒂芬 -法@論 -淫妻的亂交免费在线看 -色情 激情 淫乱 卡通 高潮 -中华人民共和國 -维权 -产权局 -快樂AV -fuck小鸡鸡 -最新两性激情小说 -正清网 -鸡巴顶开花瓣 -本站10019多部激情电影全部免费试看三天 -王瑞林 -湿润的嫩穴中 -和两勇男玩8P -美丽世界 -trannie -六四風波 -聯眾 -干你老母 -毛三级片 -国研 -5街区 -免费视讯meimei -路甬祥 -他媽的 -大麻油 -发**论 -集會 -潤星 -狂插meinv老师 -公车奸meinv淫奸女电影试看。 -我有网 -仁寿警方 -姐姐的阴道好嫩啊 -拉姆斯菲尔德 -真理组织 -日本meinv鲍鱼贴图区 -免费淫色情电影 -干你老比 -天安门档案 -日本mm性激情电影 -發~~輪 -女儿嫩穴操mm嫩穴操女人嫩穴 -又粗又硬的大肉棒 -摸你 -娇小鲜嫩的小屄洞 -欧美激情成人电影 -meimei的嫩阴唇 -独占Princess Collection 若叶 -和jiejie淫穴 -f a l u n d a f a -嫩穴 搔穴 -人妻榨乳 -监狱 -驚天動地 -雞掰 -毛六四事件 -愛田由~(Moodyz)女教師 レイプ 輪姦 -淫乱诊所 -透视眼镜 -熟女護士 -laqia -色网阴道特写强奸23岁处女全过程 -一本道1137~陵辱巨乳~薫まい -個批 -嫩BB -毛你老母 -成人午夜场影院 -美女嫂子的小骚逼 -毛二B -二逼 -誅仙 -shen hua -毛双峰微颤 -假陽具插穴 -天安们母亲运动 -F_U_C_K -尻庇 -發綸 -方励之 -性伦乱小说 -21cn -歐美圖區 -新体操(仮)~妖精达の轮舞曲~ -吗比 -mm屄 -和熟睡的meimei做爱教你一手 -强效失意药 -连続失禁 -扶正肉棒,瞄準她的肉穴插了進去 -搞她 -淫婦自慰 -〓成人写真〓 -新江湖Online -毛奸夫淫妇 -口爆 -毛刘 淇 -shit -彭珮云 -游戏监督员 -色情网址网上视频 -淫奸少女电影 -手机注册电影 -hai dao wang -sw2 -公务员 -毛倭国 -疯狂赛车 -小穴里流 -迟浩田 -淫女淫图淫书淫片 -UR -不卡免费淫电影 -搏客 -亚洲激情淫色贴图网 -毛破坏 -桑拿房的淫乱图片 免费母子淫乱图片 -da hua -快到高潮时,他哭了。 -賓館女郎 -發@@論 -svs -亞洲情色網 -娘餓比 -ㄐ巴 -西游 -jiejie的穴夹的我好紧小说 -趙 紫 陽 -黄色小电影 -┙ -┘ -┛ -成人午夜激情视频聊天室 -从后面插漂亮小穴妹 -┚ -┝ -├ -┟ -┞ -┑ -┐ -┓ -┒ -┕ -干GM的娘 -└ -妳馬的 -┗ -┖ -┈ -毛海关总署 -┉ -┊ -┋ -┌ -┍ -┎ -┏ -━ -│ -┃ -和两勇男玩44P -┄ -┅ -┆ -┇ -和两勇男玩43P -┻ -┺ -┹ -メイド召しませ 第一话 -┸ -┿ -┾ -┽ -┼ -┳ -┲ -東亞病夫 -┱ -9v9e -┰ -弟弟淫奸姐姐穴 -┷ -┶ -┵ -┴ -罢饭 -┪ -┫ -┨ -┩ -射雕淫女传 -┮ -┯ -┬ -qian nian -┭ -┢ -┣ -ci77 -┠ -┡ -┦ -┧ -┤ -拔屄自拍 -┥ -极品成人激情影院 -5街区 -政治封锁 -和两勇男玩42P -日本人淫乱操淫荡少妇操淫荡meimei -司馬義•鉄力瓦爾地 -冯东海 -广东王 -国外美女黄网 美女激情SM处女淫水图台 -╈ -╉ -╊ -╋ -肉棒狠狠插嫩穴 -╄ -╅ -╆ -╇ -毛看牌器 -╀ -Yukata Angel Vol。 1 : 矢崎茜 -╁ -╂ -色mm的嫩穴 -╃ -惹火身材 -日韩妹妹嫩穴淫图 -如果你未满30周岁请自觉离开。 -和两勇男玩41P -色情导航 -02jam -你的鸡吧好大啊干的我好爽哦 -如果你未满31周岁请自觉离开。 -成熟性感大meinv -骚穴 -毛尻 -毛黄色电影 -積存的巨乳妻子積存的巨乳妻子 -抽插32岁处女妹妹淫叫不断 -1000y -淫奸处女穴电影 -茎候佳阴 -毛法仑 -yi wang chuan shuo -Chink Chink -赵晓微 -beijingspring -成人娱乐网 -和两勇男玩40P -艳尻 北原多香子 -剛比樣子 -毛基督 -cao你 -抽插39岁处女妹妹淫叫不断 -fuck托管理事会 -操波霸 -本站所有电影完全免费无需手机注册 -他NND -和meimei做爱 -屄屄 -滚滚球 -毛鸡掰 -賤貨 -人体摄影 -老二在她湿润的阴道口边摩擦 -法*论 -毛轮奸 -淫电影下载论坛 -插我 -欲火 -asgard -jiejie的阴道好嫩啊 -龟头被舔得又麻又痒 -中国问题论坛 -dick -47xp。com 电影免费 -你的小穴好紧┅┅夹┅┅夹得我好舒服 -亚洲免费淫色电影下载 -毛看棋器 -骚屄淫水泛滥 -鬼村 -fagtard fagtard -勃大精深 -亚洲色妹妹 -黑天使 -肉棒插进美穴 -长途汽车上的淫乱乘客 -仆街 -少妇偷情 -賴昌星 -肉棒的抽送 淫乱 用力干 -激情小说 -顶级影片禁书禁图 -客服人員 -制服美妇 -又粗又长的肉棒插入阴道里 -小澤圓(小沢まどか)的退隱作 -血B -激情打炮 -毛高校群体事件 -吮吸小穴 -民主 -lovebox -操淫荡少妇 操淫荡meimei -广电局 -淫荡少妇穴 -残废 -动漫激情淫色 -zhuanfalu -成人午夜电影 -conquer -毛江八 -家庭主妇 翔田千里 志村玲子 -安眠酮 -免费午夜成人影院 -肉棍狂插嫩穴 -Chudi Chudi -毛干妳妈 -毛舔西 -阳痿 -激情成人视频聊天室 -血b -我靠 -淫液不断从穴里流出 -黃金聖水 -金庸群侠转 -ever quest -掰开她的小穴 -gy -日本淫荡电影 -经典免费淫电影下载 -gm -色妹妹乱伦理小说 -moxiang -張 伯 笠 -诱惑视频 -藏青會 -看中国 -李金华 -騷逼 -错那吗逼 -少妇淫心我要看淫心情迷电影淫心情迷电影 -美女 -qiangjian -如果你未满34周岁请自觉离开。 -激情meimei聊天室 -激情美穴 -情色俱乐部meinv奸淫。黄色电影裸体电影PP点点激情电影 -jiejie被插的好爽 -毛窃听器材 -jiejie的阴户好嫩啊 -大鸡吧在她的小嘴抽送 -嘴唇吸小肉缝 -tibet -毛鸡巴 -操78 -yong heng -无套自拍 -在线看淫色电影 -毛烟草局 -嘩嘩曼 - 山咲Chiyuri -屠城 -梦城互动 -meimei嫩穴被狂插 -操测绘局 -xinguangming鸟你 -我操了美丽的女律师 -毛干妳娘 -人民报 -毛枪决现场 -hellgate:london -g。m -无码电影 -毛纠察员 -教你怎样延迟射精28岁以下禁免费淫电影a片 -姐姐的穴好大啊 -王汉斌 -小騷比 -紅十字会 -耶苏 -姐都快被你搞死了 -毛以茎至洞 -怎样延迟射精23岁以下禁 -好弟弟使劲干姐姐 -美女 淫穴 -刘永川 -老人政治 -亞洲有碼 -鄧 笑 貧 -残廢 -前凸后翘 -点击观看*林心如做爱*色情电影*免费淫 电影 -强奸40岁处女全过程/淫妹阴毛小穴 -电影试看片 -fuck他祖宗 -张 钢 -强奸22岁处女全过程/淫妹阴毛小穴 -戴秉囯 -viprxjh -罢工 -白肌美女?琴也 -欧美两性淫乱 -政治协商会议 -毛新生网 -血腥冲突 -他母親 -床上夫妻激情自拍图 -皮條客 -布莱德雷 -天鹅绒活动 -91bb成人小电影 -蕩女 -熟女颜射 -罗礼诗 -法@纶 -哥哥插入我的小穴 -你以为你装屄就能骗我 -dyonline -毛法西斯 -屌妳 -台湾电影网龙游龙洲影院日本娱乐性免费电影在线 -刘 淇 -三个呆婊 -淫术炼金士 -narod。ru -日本大型黄色美女做爱 -欧美淫图 -爱抚淫女的阴户 -台湾午夜色情 -省長兒媳婦 -orgasums -圣角色扮演学园~大泽萌 -做愛 -韩 东 方 -fuck天安门 -美女发春激情在线电影 -法^^纶 -香港激情图源成人色情论坛脱衣美女做爱 -口活 -fuck氵去 -tian xia er -王剛 -卖B发论公 -蒙独 -蕩妹 -kakajb -狂插淫洞 -homosexuel -黄慈萍 -导航色站 -jb -倪育贤 -性爱日记 -meinv穴 -智障 -海盜時代 -bbscity -奇乐网 -肉棒在阴唇上摩擦传来快感 -色情视频聊天 -色狐狸网址 -大波粉B -色情导航 免费色情电影 -靠北 -贱种 -wizard-soft -*法*轮*功*靠 -狂插嫂子穴 -刘伯承 -少妇扒开阴道图 -毛佛教 -第十六次代表 -愛女人 -Red Hot Fetish Collection Vol。41若叶こころ -性奴会 -高校群体事件 -黑社会大姐大性欲很旺盛 -南蠻子 -meng huan guo du -乌云其木格 -激情潮喷 -毛色情电影 -沃尔开西 -大波粉b -激情小說 -妈浪女骚 -淫欧美淫暴 -在线免费观看性感摸特日本性感奶霸图片骚 -亚洲激情论坛 -激插 -18禁 -龟头顺着肉壁插入她的阴户 -阿姨的阴唇好大啊 -批林批孔 -成人激情午夜 -戴秉國 -6月4日 -第7色大型黄色网站 -蒙獨 -姐姐的穴好紧啊 -共產主義 -小嫩逼 -32283 -测绘局 -小浪穴┅大鸡巴 -changeu -pao pao tang -fuck杀人犯 -毛董贱华 -盗电 -一边一国 -罗干 -成人激情免费电影院 -董文华 -韩联潮 -本站10006多部激情电影全部免费试看 -毛光明日报 -免费淫奸女A片段试看 淫电影//少女被强奸到高潮时偷拍小A片 -激情妹妹聊天室 -文化部 -………好舒服喔 -操操你妈屄 -魔力宝贝 -軍國主義 -哭么 -法@綸 -蕩婦 -六四參加者回憶錄 -淫女穴影院 -操达赖喇嘛 -南华早报 -台湾成人免费情色电影 -淫色电影 -殘廢 -毛妳妈的 -十八岁美女护士电影网站 -多维新闻 -操Gm -统治 -偷情 -你的肉棒干 -fuck推油 -毛小鸡鸡 -whore -丁关根 -监督 -大鸡巴坚挺插淫穴 -新疆独立 -i n c e s t -尹庆民 -d7se淫色穴图片和美女发春激情3级片试看 -net -(ATHENA)奥様欲情日記 エプロンをめくって犯して うずく人妻美巨乳スペシャル -网址之家 -野性姐妹花 -法^^綸 -毛洗脑班 -殘废 -外**掛 -夫妇乐园 -亚洲成人激情淫影院 -毛联易互动 -日本激情动漫 -肏穴 -驶你娘 -虎虎虎~淫秽的身体 Tora-Tora Gold Vol。25 : Shizuku Natsukawa -口淫 -东亚病夫 -狂操穴喷出阴精 -zhicheng163 -所盗摄护士jiejie性感美腿图 肉丝美腿艳情淫欲 -来插我 -激情淫洞小说 -江油餘震 -溫B -处女阴道特写爽图 -本站10006多部激情电影全部免费试看三天 -徐才厚 -它NND -ㄐ八 -在线淫穴 -son of bitch -午夜激情电影网 -自由亚洲电台 -kele8 -nabi -操机掰 -毛计生委 -挨球 -贯通两极法 -操GM -狗比 -干妳马 -發$侖 -日本暴淫网 -魔獸幣 -情色成人 -濕了還說不要 -game17 -臭作 -锤锤 -三個代婊 -肉穴 -舔雞巴 -f r e e d o m -温柔女孩操屄竟如此陶醉 -李小朋 -cjsh -色色五月天 -大航海时代 -我扒开了她的阴道 -肉棒插入小姨的肉縫 -淫乱工作 -H動漫 -美女做爱激情电影 -9you -公审李鹏 -sb -美国 -免费淫色强奸电影 -踢踢球 -成人午夜场,吸精痴女护士 -露陰照 -超级色情网站 乱伦色情小说 香港娱乐网黄站 性bt论坛 -feng kuang sai che -奴畜抄 -自拍写真 -Bitch -伊斯蘭 -冰風傳奇 -戳逼 -外**挂 -和两勇男玩50P -抽插29岁处女meimei淫叫不断 -淫之插穴虐待破处流血 -众明星乱淫禁书 -现役看护妇电影下载 -江湖淫娘 -pp244淫色导航 -歇b -赌球 -小泉彩~黑人体内射精连续20发 -它妈的 -钱其琛 -發**掄 -母奸 -內射美婦 -外—挂 -淫女信息 -fuck死gd -nacb -毛抑制剂 -是鸡 -大陆性美女淫穴 -狂操操小小姨穴 -fuck死gm -幼交图嫩女兽交 -混沌诀靠 -情色文學 -鮮族 -中文情色网址导航 -奧美電子 -多党执政 -少妇被鸡吧操 -和两勇男玩52P -情色文学 -含住我的小鸡鸡 -臺灣帝國 -免费淫电影网址大全 -操你祖宗 -龜投 -nabi -meinv护士被奸 -毛塞你老母 -紅火女郎~真央~壓倒性的震撼力~汙染女人的快感 -嫂子的阴道好大啊 -hai dao shi dai -色迷城 -宁王府淫色 -爆草 -受灾 -和两勇男玩51P -受災 -操表妹操 -王冶坪 -梅花屄 -新疆打砸抢 -豬容基 -whoyo -淫荡少女穴 -激情淫色 -穴淫 -贱B -和阿姨淫穴 -香港成人激情影院 -外—掛 -客服人员 -作ai -亞洲淫图 -大膽少女 -黨中央 -干妹妹小穴 -我和小啊姨在车上做 -又肥又嫩的小骚屄儿 -华西列夫斯基 -小平 -和两勇男玩53P -淫穴 大鸡巴干 好爽 -nage -国际足坛五大 -成人激情图库 -毛李弘旨 -嫩B弓虽女干 -客户服务人员 -yuckfou -抽你丫的 -网龙 -龟头碰到子宫口 -988wow -制服美婦 -发**纶 -又大又肥的阴道 -卖软件 -刀online -毛官逼民反 -狂插小穴 -穴海 -秦 晉 -妹妹社区淫色 -秦 晋 -征服小姐 -贱b -非典 -龟投 -战牌靠 -古柯 -羅幹 -Biaozi -淫荡教师穴 -吹喇叭 -大鸡巴顶进meimei的小穴 -淫妇自慰 -套弄鸡巴 -笨屄 -獸奸 -學生愛國運動正名 -激情小浪穴 -法轮工 -淫城乱伦屋 -白嫩meinv穴 -新斷線 -Whitey Whitey -aika -淫水横流 -qqpp -qqr2 -摇头丸 -滚那吗瘟比 -Asian Hot 018 岸田香織 女陰破壊 -KOKESHI COWGIRL Vol。29 石川优季奈 -女人被迷奸的时候也很爽 -新手辅导员 -大鸡巴在她的小嘴抽送 -美女与猪性交电影 -经插进我的穴了 -dfdz -卡通美女淫乱图 -杂种 -repent -買賣 -贝肉 -百家性大型黄站 -穴爽 -激情最新网址 -肉壁包容着鸡吧很舒服啊 -fils de pute -毛分裂祖国 -毛龟孙子 -性無能 -黄色小说 -妹妹淫图 -basterd -毛麻醉乙醚 -花瓣正在潺潺地渗出蜜汁 -我和jiejie的淫乱史 -Clayton Dodge Clayton Dodge -统独 -插妻子小穴 -旅館自拍 -雞巴 -他媽ㄉ王八蛋 -法~~綸 -本站10001多部激情电影全部免费试看 -激情 -李继耐 -毛摩门教 -操插妳 -顾顺章 -牛比靠 -六四参加者 -宏法 -日本激情淫色动画片 -meng huan guo du -基督教 -亀頭 -淫奸表姐论坛 -森田めぐみ 凌辱饲育 -管裏員 -赣江学院 -免费性爱电影 -阴道夹的我好紧 -靠么 -vgbh -李老师 -淫奸表妹 -在线淫影院 -嫩穴 插干 …快插我吧 -Qzone精彩由你而来 -阳物 -香港成人电影网五月成人情色论坛 -美女极品嫩穴 -多黨執政 -毛卖国求荣 -在线免费观看黄片A片 -色情网址网上做爱 -┅┅别再磨了┅┅痒死啦!┅┅快 -renminbao -粗大的肉棒………我受不了 -毒龍舔腳 -爱妻淫穴 -洪 吟 -熟女亂倫 -奸淫……好舒服 -RMB -少妇房中自淫,和两勇男玩17P,操得直叫爽 操日本淫女穴 -淫奸护士姐姐穴 -game -情色电影网站 -錘子 -民主墙 -欧美淫图 成人色情网 -onair -油田总部 -iuiuu -抵制日货 -无网界 -da hua zhan guo -操你老母 -乳頭 -肉簫 -免费成人激情电影 -104bb成人小电影 -JB靠 -姐姐的肥穴 -曹剛川 -淫奸美女 -爽死你淫图 -插入小姨的子宫 -插 护士 -藤人 -猛插 -tong shi tian di -荣誉之战I--钢甲洪流 -你老妹 -jiaochuang -藤仁 -罗富和 -榮譽之戰I--鋼甲洪流 -馒头屄 -氣性坏疽病 -妖艷醫生 -陰毛 -GameMaster -导弹 -春色AV激情片 -18DY性爱电影 -賽你老母 -让你操 -san guo hao xia zhuan -淫女淫洞 -刘澜涛 -老二 -hun luan mao xian -抽插26岁处女妹妹淫叫不断 -欧美淫女在线看电影 -碧雪情天 -亚洲淫色网站 -极品成人A片无码 -肉棒插到花心深处 -毛麻醉枪 -路易 -fuck台独 -莎木online -狂插日本学生妹 -耶蘇 -怪獸總動員 -淫女老师 -脑残 -tengwu -毛鸡奸 -全免费淫电影 -干你良 -街头篮球 -政治打击 -瀨名 -學潮 -露出了娇小鲜嫩的阴道 -吳德 -李禄 -fuck世界日报 -抽插55岁处女妹妹淫叫不断 -毛王昊 -陰水 -fofg媽的 -幹的你 -猫扑 -肉箫 -發*侖 -毛税务总局 -劉奇葆 -騷貨 -山口组 -fuck受虐狂 -易丹轩 -免费淫女看电影网站 -特码 -X妈牛比 -公子开 -日朱骏 -蓬浪 -王子傑 -淫护士 -插妹妹小穴 -minghuinews -手记注册日韩5010部激情电影 -毛李瑞环 -李鹏* -狗B -哥伦布 -许世友 -吴弘达 -好肥的阴户 -97sese -六四事件 -瞒报 -藤任 -群奸 -手指扒开红嫩的阴唇 -tum tum -張朝陽 -毛轮功 -狗b -鹿城最新娱乐小说 -aids -性饥渴 -捏你奶子 -毛性爱 -陳毅 -妹妹黄站 -监听王 -艷舞淫業 -華國鋒 -死亡笔记 -wg武功 -最强美乳おたま初解禁 -成人之家 -免费A片日本淫电影 -無碼精選 -阴茎把子宫顶烂 -最新99bb)有名女优~及川奈央-痴女教师 -魔法奇兵 -你妈了妹 -无界浏览 -錢運錄 -欲望 -捅比 -中青旅创格 -免费试看激情成人电影 -操 gm -比卵 -鸡吧插进肥嫩的小骚屄 -BT激情 -艳星诱惑 -操嫩穴 -日本熟母 -操你大爷 -强奸23岁处女全过程/淫妹阴毛小穴 -中原油田 -监管 -大纪元新闻网 -免费成人情色激情视频聊天 -肉缝 -QQ幻想 -黄祸 -神经病 -干她妈 -插穴图 -GOQO -整根阴茎没入她空虚已久的阴户 -法$$淪 -日本美女吃精图 -发沦 -强奸28岁处女全过程/淫妹阴毛小穴 -法@@綸 -世界都 -毛欢城互动 -95bb成人小电影 -亚洲激情网 -我的小穴好爽 -金瓶梅 -免费在线淫奸mm电影 -月经 -換妻 -毛梅花网 -紫彩乃潮吹赛红音 -马大维 -龟头挤进了jiejie的小穴 -成人色情网站 -毛十八摸 -你它妈的 -私處 -手指对她阴蒂的刺激 -中条英机 -尉健行 -免费电影未亡人柔肌 -国际法院 -王军涛 -賣號 -肛门拳交 -毛受虐狂 -吴德 -銀民吧 -2。23會議 -淫荡少妇穴少妇嫩穴 美女的嫩穴 -教你如何鉴别处男处女的方法(组图)18岁禁看 -操插你妈 -指导员 -少妇房中自淫,和两勇男玩8P,操得直叫爽 操日本淫女穴 -星戰前夜 -干洋妞穴 -遊戲監督員 -毛鸠屎 -travestido -出售此号 -裤袜 -美麗世界 -粗鸡巴 嫩穴 -和妹妹肏屄 -淫乱小说 -毛卵 -台湾18岁成人 -張宏堡 -日本精選無碼DVD -毛杀人犯 -我将肉棒狠狠插入漂亮的老师小淫嘴抽插数十次 -强奸34岁处女全过程/淫妹阴毛小穴 -少妇房中自淫,和两勇男玩19P,操得直叫爽 操日本淫女穴 -淫水横溢 -虎虎虎~ Tora-Tora Platinum Vol。2 : 魔性的meinv 鈴木麻奈美 -操淫荡少妇 操淫荡护士 激情穴贴图 -huo xian ren wu -淫女吃尿 -嫩缝 -外••挂 -fuck舔西 -亞洲淫娃 -人体炸弹 -法^纶 -亲亲小芳 色咪咪论坛 新亲密爱 六月龙盟 人间仙境情色网 -毒品 -发浪 -插妳 -教你怎样延迟射精22岁以下禁免费淫电影a片 -fuck他妈的 -天安门大屠杀 -痛批政法委 -da tang -毛南联盟 -肉縫 -傻卵 -蒋中正 -毛独立 -免费成人A片 -黑省副省長 -封从德 -淫欲日本 -山口組 -黑省副省长 -淫贱妹妹贴图论坛 -發^^論 -淫女浪穴 -内衣模特露点走光 -zhen feng shen -成人激情聊天室 -發@侖 -韓國自拍無碼系列之二) -色情电影 色情排行榜 -毛台独 -妈……你的小穴好插 -原子能机构 -江绵恒 -东西南北论坛 -曼施坦因 -成人激情淫洞网站 -中国孤儿院 -淫色贴图 -胡緊套 -淫魔 -姐姐的屄 -长身丝袜meinv~赤く烂れたマンコが痛 -李老師 -狂插淫荡女护士 -毛玉杵 -亚洲艳情男女图吧 -射屏 -法@@纶 -fuck死GM -学潮 -fuck死GD -瑪雅網 -求你插插我吧好痒 -菜逼 -社科院 -台湾民國 -曾 慶 紅 -法耣功 -外交部 -耶和华 -jin yong qun xia zhuan -傻吊 -tan ke bao bei -勃起 -步飞烟 -骚逼大型成人色站 -Tora Tora Gold Vol。16 香山圣 -教你怎样延迟射精26岁以下禁免费淫电影a片 -淫荡 穴 淫洞 -我淫我色淫色导航 -淫乱小姨子小说 -龜兒子 -令人喷血的春宫108姿势 -法~~纶 -台湾民国 -平成女忍者 奥义中出し陵辱 -法磮功 -毛叶剑英 -溫 元 凱 -猪操 -胡紧涛 -nigga nigga -审查 -龟头压挤阴道 -用劲吸吮咬舐着湿润的穴肉 -k粉 -手记注册日韩5022部激情电影 -少女床上自拍 -狂插日本美女护士 -色mm激情论坛 -嫩縫 -育碧 -李少民 -wowassist -熱 站 政 論 網 -陳曉寧 -毛小泉 -法^綸 -大波波 -江核心 -林长盛 -免费电影 美女电影 -kefu9you -激战 -f_u_c_k -89年的斗争 -廁所偷拍 -完全免费淫电影 -肉棒伸入她的口中 -幼女玩性 -法倫 -Image)ヌーディストGALビーチ -天天干贴图 -小電影 -晚年周恩来 -淫妻的穴 -大鸡巴好趐┅┅趐┅┅快┅┅别揉了 -妈个b -览叫 -咬着龟头 -feng kuang sai che -操操你八辈祖宗 -唐人街情色导航 -成人两性电影 -卖ID -迪里夏提 -毛游行 -午夜电影 -熟女乱伦 -解放軍306醫院 -PP电影 -八九学潮 -┅干的妈好爽 -色情网站 -教你怎样延迟射精18岁以下禁 -meinv口含鸡吧玩内射 -表舅妈与我 -9you -操操gM -走光偷拍 -万里 -色情导航 导航 -specialforce -义解 -sheng da fu weng -無碼淫女 -淫民欧美激情贴图 -好弟弟使劲干jiejie -目标软件 -侬着冈峦 -淫女疯狂偷情 -淫 电影 -老逼 -海洋局 -汪岷 -鹿城娱乐 -毛卖ID -狂插日本少妇 -liu xing hu die jian -露点 -屎妳娘 -fuck傻子 -粉嫩美少女穴让你插 -毛淫 -肉棒在姐姐的阴道里 -操mm嫩穴 -搞他 -甜嫩穴 -民主党派 -大花B -法侖 -插小穴的快感 -狗b新光明 -操操gm -香港色情影星meinv裸体 -瘋狂賽車 -嫩鲍 -狗杂种 -黄片 -zhengjianwang -小姨的穴 -白梦 -黑点 -幹妳馬 -亚洲激情片 -亚洲情色 -日领馆 -毛新闻办 -一本道 -赵海青 -殘疾 -猛干 添 -台湾18dy电影 -yi wang chuan shuo -陈至立 -含屌 -操吃屎 -浪女叫春成人招妓网色性网电影性暴力电影 -fuck吴仪 -人民银行 -午夜激情 -骚洞 -反封锁 -成人激情论坛 -相奸 -國賊 -春光外泻 -插她 -slanglist -法伦 -Red Hot Jam Vol。 藤崎夕凪 -免费电影妖艷醫生 -龟奴 -后庭 -女教師 レイプ 輪姦 -趙 海 青 -民政局 -爆乳家庭教师 -毛傻卵 -绝品meinvが恍惚颜の绝顶快感 -毛邮政局 -外*掛 -卖QQ -免费激情论坛 -艾滋病 -新石器時代 -外/挂 -美女护士被奸 -预审查 -胡乔木 -fuck小泉 -插的jiejie好爽 -mforest -pao pao -熟女顏射 -骚比 -stoneage -亚洲情色淫穴 -狂插日本meinv护士 -骚母 -用手指分开两片肥嫩的阴唇,露出了那娇小鲜嫩的小屄洞 -水扁 -司马璐 -龟头对准菊门 -袁纯清 -插你丫的 -法仑 -雜種 -毛三民主义 -外-挂 -粉红色的大阴唇正紧紧的闭合着 -奸淫空姐 -漂亮。女記者採訪時被逼姦 -星戰情緣 -断電 -屄儿好┅┅好爽!┅┅好舒服!┅┅ -毛性无能 -日逼 -18岁淫乱 -外/掛 -激情淫穴导航 -足腳交 -儿子淫奸jiejie -对著暴露的美穴狂插 -法$$论 -聶榮臻 -草你妈靠 -Bao皮 -三反五反 -龜头 -狂插 -强制浣肠 -淫兽学园 -韩日成人激情电影 -把肉茎舔乾净 -mwo -法沦功 -法婨功 -龟头 -毛恐怖主义 -mxd -天安門母親 -猖妓 -外-掛 -毛傻吊 -朱林 -韩启德 -Heterosexual -色站导航 -大鸡巴顶进妹妹的小穴 -搞你 -你馬的 -妈个B -KAO -法@@掄 -香港激情性爱影院 -練完瑜伽功做?才爽呢(國產3p) -老卵 -变态心魔女仲村 生中出 -骚水 -龜奴 -色情聊天室 -麻痹 -騷穴 -綿阳 -成人圖片 -拉登 -蔣彥永上書 -国贼 -綜聯數碼 -色情五月天 -肉棒插入meimei小穴 -魔域 -羞耻母 -免费成人两性影院 -吴仁华 -老师被干小穴 -抽插56岁处女meimei淫叫不断 -蒋彦永上书 -国外meinv黄网 meinv激情SM处女淫水图台 -性愛圖片 -色情导航 av电影 -牙齿轻咬着阴核 -淫荡姐姐勾引小弟玩操屄 -朱溶剂 -插淫妇骚穴 -李宏志 -邓笑贫 -fuck文化部 -肉棒抽插…不要 -MUGEN EX Vol。4 -她的阴道乳房真美 -毛彭真 -發論功 -煞逼 -台湾成人网站 -阳具插入小穴中 -partita -插入内射 -世界日报 -CCTV -大鸡吧塞进逼里使劲插我 -日本淫妞 -哥哥我爽晕了 -谭绍文 -邻居少妇 干邻居少妇 邻居的少妇 邻居美少妇 操淫荡少妇 -阳具对准她湿润的小穴口 -MUGEN EX Vol。 7~滨崎(MX-07) -烂人 -ㄖ -日本色诱女郎图库激情成人视频聊天室 -Bastard -puSSy puSSy -phuck -去死 -盖世太保 -f a 轮 -admin -三去车仑 -sealonline -鲍岳桥 -毛美国 -情色 激情 美女 穴 -pao pao dao -法~淪 -两性淫乱小说阅读 -完美國際 -发@伦 -天上碑 -胡XX -肉棒 插得太深了 -强奸护士 -连胜德 -免费淫奸女A片段试看 强*十八岁美女护士看完保证你打飞机 -淫穴把整个龟头吸住 -狂操 -青樓 -射入阴道里 -抢 粮 记 -MASTER -女教师家访遭遇体剃毛内射肛交口爆喷尿虐待 -毛人大代表 -蜜汁 舔穴 塞入 -成人论坛导航 -极品金牌素人口交系列 -溫逼 -陽萎 -操操XX -法$$論 -hkhk68 -胸涛乳浪 -亚洲淫色俱乐部 -奴隶调教 -盤古軟體 -网星 -tnnd -毛一夜情 -好爽┅好舒服小骚穴 -网易 -f a 輪 -狂插林心如穴 -綿陽 -西洋美女 -狗成 -368成人网站 -乱伦父女 -國產偷拍 -Gold Angel Vol。7 纹舞らん 可爱 -发@仑 -倒台 -日軍 -性愛插穴 -15年前的“共和国卫士” -又硬又大的肉棒 -插入……大肉棒 -叫春 -台湾小穴自拍护士做爱 -潮吹喷射地狱 不行触摸的喘气 4P肉奴隶中出 -毛卖B -吗的靠 -将手指插入她的穴里 -法@@抡 -抽插20岁处女meimei淫叫不断 -北京之春 -不要!嗯──啊啊、啊啊!” -亚洲激情帖图 -法(轮)功 -轩辕二 -獸交 -毛吴仪 -无码炮图 -大中国论坛 -同房 -美幼 -毛穆斯林 -肉棒就顺着湿滑的阴道口插进去了一半 -cdjp -台灣狗 -哦……再快……小屄要美死丁…… -性色俱乐部 -发$$轮 -zl-fm。com -倫功 -女学生嫩B -外@挂 -风尘劫 -fuck他马的 -自民党 -毛一中一台 -毛吕秀莲 -青天白日旗 -t2dk -骚浪 -封神 -58xp。com 电影免费 -大鸡巴用力的往小穴里面狠插 -陵辱面接4人淫乱娘 -earthciv -春藥 -毛罗干 -庆 红 -她的阴道好深啊 -本站10020多部激情电影全部免费试看 -鸡8 -和阿姨作爱 -nnd -地藏 -九評 -毛卖QQ -操藏独 -淫语连连 -賤種 -如果你未满19周岁请自觉离开。 -戳那吗逼 -18摸 -插的meimei流淫水 -三去车侖 -臭机八 -膏药旗 -GAME MASTER -jiang wang -外?挂 -日本激情电影 -qqtang -柳下惠 -。gm -莖候佳陰 -令人喷血的春宫108姿势(组图)22岁禁看 -猪头 -让我操高潮淫水一直流溅 -新闻管制 -無界流覽 -外?掛 -好大的阴户啊 -性感动感美女日本幼少女性感写真 -援助交际 -亚洲激情影院 -陰蒂 -强奸38岁处女全过程/淫妹阴毛小穴 -成人电影 淫穴嫩穴骚穴 -海之乐章 -小骚娘们的小嫩骚屄 -89风波 -蔣彥勇 -c a o靠 -我日靠 -玫瑰园 -鸡巴对准穴口猛地插进去 -嫩鮑 -毛滚 -毛管理员 -亞洲瘋情 -4-Jun -淫奸表姐 -在线淫电影 看完保证你打飞机 -淫水狂喷 -万钢 -肉茎 -外@掛 -好……小……小骚穴 -發倫功 -……好爽喲 插穴 -fuck傻屄 -操插你 -ri ni ma -亲美 -日本激情淫影院 -ayawawa -日你妈啦逼 -免费黄色淫电影一社会男子在宾馆里强奸一 -如果你未满27周岁请自觉离开。 -台湾成人黄色电影 -老兵 -大鸡巴插小穴 -八九年那个春夏之交 -卖号靠 -小穴疯狂地吮吸着我的阳精 -援助交際 -青楼 -三去车仑工力 -18dy村妓 -本站10008多部激情电影全部免费试看 -tui tui xia -胸濤乳浪 -毛国土资源部 -骚棍 -刘华清 -盗窃犯 -手指抠肉洞 肉缝 -骚棒 -强奸美女狂插处女阴道 -大跃进 -插淫屄 -毛贱逼 -陰阜高聳 -月光宝盒 -周六性吧 -儿子的肉棒好长啊 -红色的小穴 -下贱 -梦幻之星 -本站10011多部激情电影全部免费试看三天 -tianxungame -抽插51岁处女妹妹淫叫不断 -VIP激情成人电影 -89暴乱 -三级电影淫电影艳情电影 -毛穆罕默德 -杀手 -處女 -坐脸 -淫水爱液 -辅助程序 -純情尤物由美(中文字幕) -鸡巴抽插好……爽 -25dy淫色贴图 -民警当副院长 -肉莖 -杨巍 -運营者 -鸡芭 -婊子养的 -我湿淋淋的阴道 -陷阱超人哗哗曼 -欧美成人漫画贴图区 -壓制 -如果你未满35周岁请自觉离开。 -和平演变 -ji zhan -爱神之传奇 -狗操 -lastchaos -她的阴户好嫩啊 -meimei的穴好紧 -鄒德威 -法$纶 -教你怎样延迟射精32岁以下禁免费淫电影a片 -妓女靠 -肉棒狠狠地插进小淫穴中 -刷钱 -淫穴电影 -毛氵去 -龟头插小穴 -MAKELOVE -机掰 -毛舆论钳制 -啊┅┅用力┅┅用力插烂我的淫穴 -下賤 -meimei的嫩阴户 -来干 -明星捐款 -毛卖比 -粗制吗啡 -插进 小穴 嫩穴 -新手輔導員 -Tora Tora Gold Vol。15 香山圣 -海洛因 -杨帆 -温馨 -毛他母亲 -meinv极品嫩穴 -龟头顶破了处女膜 -口內爆射 -龟头插进了小穴 -悲惨-双胞胎一起被奸 -红十字会 -365情色网 -靠你妈 -meimei的阴唇好嫩啊 -玉乳 -法*綸 -小屄又湿又滑 -王丹 -少女被强奸到高潮时偷拍小A片免费淫电影a片 -淫乱插穴好爽 -懶趴 -淫浪少妇和医生疯狂做爱 -操操Gm -淫电影//教你怎样延迟射精 -呂秀蓮 -风骚欲女爽爽网 -情色图片成人小说 -虐奴 -陰莖 -教你怎样延迟射精41岁以下禁免费淫电影a片 -插 干姐姐 好爽 -淫色贴图小说 -狂插老师穴 -大*FA 弟*子 -8 仙 -大 中 國 論 壇 -操操GM -屙民 -完美国际 -猛將 -猛将 -色情小说 BT限制级电影 -激情淫穴小站 -美女淫图 -無碼體驗 -不像我讓你打~ -cctv -露毛 -项怀诚 -刘青 -成人午夜剧场 -老土 -50zhou -把我的穴插烂了 -睪丸 -一元激情电影 -46xp。com 电影免费 -鹿城娱乐情色 -wan wang zhi wang -抽插27岁处女meimei淫叫不断 -中天萬方 -代理 -亮穴 -机战 -成人 激情 淫 另类 -狗日 -欧美做爱 -香港激情淫色贴图网 -发^仑 -台幣 -狂插处女穴 -巡府媳 -国家主要部委 -台湾独立 -色网阴道特写强奸24岁处女全过程 -幸运抽奖管理小组 -jue dui nv shen -东方红时空 -迷姦雙胞妹妹 -龟头挤进了她的阴道 -毛东亚病夫 -成人免费 -免费成人图片 色情美女做爱美女小穴写真 -Groove Party -我跟妹妹肏穴 -性之站 -去你媽的 -台湾十八两性电影 -獨占動畫~肛門 1~長谷川 -好紧的阴道啊 -淫色全免费 -抠穴 -陰茎 -痛经 -杨元元 -操XX -日本黄色电影 -餘震 -本站10007多部激情电影全部免费试看三天 -成人激情性爱电影 -大鸡吧插人阴户 -毛鸦片 -色mm激情图片 -吃屎 -睡着的武神 -發$$綸 -用肥嫩的小穴套弄着我的阳具 -毛吗啡 -包pi -拒绝食堂 -谢非 -毛淫靡 -討伐 -疯狂jiejie教弟弟小说 -妹妹乱伦理淫穴 -情色视频聊天 -se淫乱姐姐小说 -法*纶 -鹿城黄站 -無網界 -李 錄 -三角裤 -Kao -吊子 -六月四日 -情色天崖 -丝诱 -成人 激情 淫乱 另类 高潮 -发抡 -十五周年 -都市2046 -抽插37岁处女妹妹淫叫不断 -林保华 -狗日的 -乳腺 -讨伐中宣部 -發~~綸 -89暴亂 -法崘功 -佛教 -淫奸少妇论坛 -文革 -日本免费激情学生美 -圣泉学淫 -成人情色论坛导航 -黄色网站 -日本天皇 -基督基督教 -Pajawa Pajawa -色mm穴激情图片 -残疾 -抽插26岁处女meimei淫叫不断 -张春桥 -反社會 -林樵清 -反攻 -少女激情自拍 -屄毛 -FLG妈B发抡 -亚洲淫穴电影 -舔屁眼 -18淫书 -剑网2 -日本激情淫色下载 -剑网3 -插穴淫图 -猛干 -劉延東 -精液射在妹妹的子宮 -我日你妈 -mo li bao bei -Tibet国 -wan mei shi jie -你老味 -『第一爽图区』 -用舌头舔着他的马 眼 -民族 -災区 -激情美女贴图九九情色 -青 天 白 日 旗 -強制飲尿便器小野悠美 -毛明慧网 -江山 -18dy电影 -操曹刚川 -未满20岁的请自行离开 ! -中機電 -大鸡巴插进了的小穴 -灾区 -raycity -日本激情淫色影院 -很黄很暴力 -災區 -小犬蠢一狼 -王勝俊 -纳粹 -17岁处女小阴唇张开 -老味 -藏独靠 -宋书元 -外$掛 -万维读者论坛 -下身 -瘟B -銷魂洞 -Anal Asspirations 7 -親 美 -毛卖淫 -小穴被插 -灾區 -寫真 -高级应招女 -肉棍子 -发^伦 -毛唐家璇 -抽插53岁处女妹妹淫叫不断 -情色成人基地 -連続失禁 -外*挂 -空姐护士淫荡图片 淫荡女护士 淫荡少妇穴 -guild wars -在线免费观看性感mo特日本性感奶霸图片骚 -瘟b -反日 -教你如何鉴别处男处女的方法(组图)18岁禁看免费淫电影a片 -皮條 -臺灣黨 -百家乐 -又长又大的肉棒 -潮吹喷射地狱 不行触mo的喘气 4P肉奴隶中出 -61xp。com 电影免费 -风雨神州论坛 -麥角酸二乙基醯胺 -骚b -钓鱼台 -虎虎虎~ Tora-Tora Platinum Vol。2 : 魔性的美女 鈴木麻奈美 -山本 -男人阁-套图站 -陸肆 -我和姐姐 -李录 -裸體少婦 -毛密洞 -淫乱熟女 -幹你媽逼 -抽插23岁处女meimei淫叫不断 -毛meimei贴图区 -毛东突组织 -美女激情视频聊天室 -春药 -鸡吧阴茎插嫩穴小穴 -同床 -賽維創世 -奸杀meinv大学生 -放荡少妇宾馆 -轩辕剑 -比毛 -游戏指导员 -fuck驶你公 -回民暴動 -一面做愛 -娇小鲜嫩的小屄 -温家保 -biaozi -毛体育总局 -代开发票 -18成人网 -屌毛 -手记注册日韩5007部激情电影 -教你怎样延迟射精29岁以下禁免费淫电影a片 -毛手机复制 -黃片 -龟头缓慢地从我的阴道中戳入拉出 -少妇房中自淫,和两勇男玩12P,操得直叫爽 操日本淫女穴 -meinv主持27小时全天激情热舞 -骚B -手机注册激情网站 -手记注册日韩5016部激情电影 -信不信我撞死你 -十年动乱 -毛宋祖英 -沦功 -激情潮噴 -大鸡巴紧紧的插穴 -……插的……好舒服 -法$綸 -浪女淫水 -车牌反光 -两岸关系 -操gm -meimei的小穴好紧啊 -神甲奇兵 -淫乱jiejie小说 -掰开嫩穴 淫液 -gun gun qiu -贱bi -肏姐姐屄 -纪念松岛MM引退大作-松岛枫合集4 -爽穴 -淫护士小说 -比水 -她的阴道真紧 -王刚 -毛骚B -發浪 -東熱空姐 -免费在线成人电影 -免费淫色电影网站 -超恶い状态10人の俗人たち -睾丸 -免费淫女骚穴在线看电影 -操gM -com流氓 -皮条 -回民暴动 -流出大量淫水 -淫乱 爽电影 -淫奸女教师 -台湾帝国 -银行账号 -东土耳其斯坦 -on9 -毛胡锦涛 -飞扬论坛 -激情动漫成人 -Marc Dorcel)Jesse & Jenna expertes du vice -王克 -如果你未满24周岁请自觉离开。 -亚洲淫色 -琼浆玉液 -司马义•铁力瓦尔地 -靠你媽 -干的爽 -援交 -美女网站脱衣美女百分百作爱 -赛维创世 -百海 -抽插到高潮 -两腿之间 -王八 -哥哥的大肉棒 -扒开她的嫩阴道 -免费桃色电影不需注册 -六四運動 -点击观看*林心如做爱*色情电影 -熱血英豪 -三级淫水写真 -掩埋 -麦叫酸 -于浩成 -日本情色电影 -寇晓伟 -外$挂 -毛胡锦淘 -wg99 -先奸后杀 -惊天动地 -毛圣女峰 -游戏发奖员 -问道 -性感誘惑 -發淪 -一码中特 -坦克寶貝 -臺灣建國 -moxiang -要色色 -气象局 -女儿的阴道好大啊 -fuck賣.國 -TENGWU -18Chinese Japanese AV Girls -倭国 -毛三个代婊 -王兆国 -阿姨的阴户好肥啊 -白烂 -和两勇男玩18P -張 昭 富 -屠杀 -社會主義 -免费淫色情电影 20岁女大学生被强#(组图)全过程 -姐姐的阴户 -成人淫图 -王兆國 -醬豬媳 -狼友 -情色导航 -台湾盲人meinv在家疯狂做爱 -錯比 -外~挂 -中宣部是中國的愛滋病 -18岁少女处夜激情性爱电影 -毛六?四 -和两勇男玩17P -taip -择民 -淫色贴图导航 -魔幣 -淫电影//教你如何鉴别处男处女的方法(组图)18岁禁看 -cnouc -鳳舞天驕 -GAME master -梦~ 总辑篇-GONZO Vol。 4 Rio -代练 -倚天 -手记注册日韩5025部激情电影 -操插深些 -激情淫穴影院 -抽插27岁处女妹妹淫叫不断 -娘饿比 -威而钢 -150m。com -法@@沦 -射爽 -巨灵神 -成人网我该死免费视频 -fuck税务总局 -娘個比 -入穴一游 -猥亵 -89風波 -肛門噴水 -wen dao -劲舞 -和两勇男玩19P -张大权 -jhwg -bt淫色电影 -绿色环保手机 -毛阴蒂 -中国共产党 -在线免费淫电影 -陈蒙 -sex -野雞 -好粗的大肉棒 -插那吗逼 -da hai zhan -张 志 清 -射雕淫女传9 -李洪 -王兆囯 -游戏管理员 -私立淫乱学园 完全版(中文字幕) -好硬的大肉棒 -胡緊濤 -我和女大学生在公共汽车上做爱 -教你怎样延迟射精20岁以下禁免费淫电影a片 -jiejie的肥穴 -jie tou lan qiu -小穴套着鸡巴 -ma chang da heng -免费淫电影吴宗宪搞笑语录(19禁看) -毛温家宝 -胡喬木 -卖淫 -又嫩又紧的穴 -j8 -告全體線民書 -毛妳娘的 -日本激情漫画贴图 -武林外轉 -狂插小浪妹 -盜撮 -大B私服 -抽插36岁处女meimei淫叫不断 -遲浩田 -快乐到死 -乳丰穴嫩激情性电影 -jhsz -浪穴被你插得爽死了 -法**淪 -老师含住我的小弟弟 -運營組 -毛倭寇 -淫絲蕩襪 -武林外转 -毛工商局 -泡沫经济 -傅作義 -大史 -信息 -新黨 -新幹線 -宫泽Keito无修正第二弹 -u r靠 -rape -鸡鸡插入穴嫩 -精液浴 -发廊 -彈 劾 -极景 -干骚女 -強姦犯 -meimei的大阴唇好嫩啊 -綠色數码 -毛硬挺 -狂插美女护士小说 -凸肉优 -龟头插入肉洞里 -和两勇男玩10P -滥逼 -少妇小穴被操的很爽 -谋略高手 -用我的舌头刮着她的阴蒂 -long yu di xia cheng -一对熟女间的性虐游戏 -极品嫩穴 淫穴嫩穴 扒开嫩穴 抚摩她的嫩穴 -妹妹的穴好紧 -恐怖份子 -放蕩熟女 -双龙入洞 -弟弟的肉棒好大啊 -游龙在线 -法**沦 -腾武 -长长的肉棒插进我的阴道里 -毛叫床 -捅我 -品色堂永远免费开放注册中 -本站10020多部激情电影全部免费试看三天 -装B -淫水直流 -xzhonline -淫奸meimei的屄 -fuck温家保 -阿姨的肥阴唇 -Gold Angel Vol。8 仲村りお -免费黄色淫奸电影3级片a片手握着我的大鸡巴 -湿了还说不要 -吸精痴女护士 -香港激情图源成人色情论坛脱衣美女做愛 -杀你全家 -插妹妹淫屄 -自制手枪 -jiba -操b指南 -手机激情淫色网址 -盗撮 -av电影 色情导航 -毛托管理事会 -美女野兽做爱淫图 -赖昌星 -hong bao shi -无需手机注册激情电影 -又顶到我的子宫 -和两勇男玩12P -就去诱惑 -舔奶 -戳那吗B -汕頭頻傳擄童割器官 -口射 -民族分裂 -裸体小姐作爱视频彩福联盟社区 大奶妹脱 -龜公 -放荡少女少妇 -台湾免费淫电影 -11月更新成人导航 -master -亚洲激情meimei -mixmaster -钟山风雨论坛 -alod -全国人大 -和两勇男玩11P -ora-Tora Gold Vol。4~~ささきふう香~~92cm G罩杯美爆乳 -法^沦 -我与网吧老板娘 -makelove -毛新闻出版总署 -密穴 -dragon -27dy淫色贴图 -十八岁禁入电影 -WEB牌戰 -The Best by Private 71: The Best Little Horny Asians -和两勇男玩14P -龟公 -毛你爷爷的 -奸淫电车 -包皮 -厕所盗摄护士jiejie -舌头穴 -毛贱货 -淫奸阿姨论坛 -毛僵贼民 -淫奸小姨子 -滾那嗎B -itembay -和两勇男玩13P -台湾成人19贴图 -肉棒好粗 插 -韩光 -熟女護士亂舞 -痴美女醫生松島 -豐唇豔姬 -吗啡 -基督 -经典炮图 -日片罕见3P加肛交 -爱液 -全家死光光 -和两勇男玩16P -屄……爽死……了……嗯……嗯……快……快 -精选明星扒b图 -灵游记 -運营組 -淫液沾满阴道 -做爱大全 -田纪雲 -毛仆街 -cdjp李鹏* -大鸡巴干妹妹 -ti ti qiu -色情 导航 -三民主义 -毛阴茎 -公告消息 -私¥服 -毛一国两制 -和两勇男玩15P -jiao chun -贩毒 -igxe -情色导航 激情爽电影 -插入蜜穴 -毛嫩b -作爱 -阴茎插小穴 -高級逼 -美少婦 -射精女皇系列Ladies In Lust -高潮 -fuck外 挂 -免费激情网 -淫液从密穴 骚穴 嫩逼里流出来 -氢弹 -俄罗斯美少女惨遭蹂躏-嫩的不能再嫩 -漂亮女站着撒尿躺下被操 -發$$論 -朝天穴 -创世之子猎艳之旅 -阴茎被火热而湿润的阴道所包含着 -毛嫩B -毛六-四 -jinku -劍俠情緣OnlineII -蒋彦永 -av貼圖 -激情 电影 -陈良 -MM视频聊天室 -叫床 -沙僧 -萬里 -中国激情淫色贴图 -12岁处女开包现场 -gang jia hong liu -髙潮 -中俄边界 -欲望成人3GP视频 -虎虎虎~ Tora-Tora Platinum Vol。1 金沢文子 -挂机 -毛发抡 -呆卵 -毛六。四 -外卦 -肉棒插入风骚少妇穴 -MM嫩穴 -少妇房中自淫,和两勇男玩3P,操得直叫爽 操日本淫女穴 -正清網 -好紧的阴户 -被10个猛男轮奸草得血直流 -情欲奸岳母 -林文漪 -狂插处女穴 淫水流 -情色導航 -激情套图 -倖存 -pussy -發掄功 -民意 -吳 官 正 -一面打電話給現任男友 -運營组 -操女人穴 色情贴图 性交贴图 -白石ひより-完全攻略 -狗娘 -新疆獨立 -邓 笑 贫 -陰締 -mland -下體 -插进鲜嫩的小穴 -你爺 -fuck尉健行 -迷魂药 -你爸 -mai骚 -科洛斯 -淫色俱乐部 -小嫩鸡 -红 色 恐 怖 -张昭富 -你爷 -奇淫宝鉴 -韩桂芝 -18dy淫间道 -勁舞 -午夜免费爽电影 -发愣 -大陆激情淫穴小说 -汕尾事件 -严家其 -粗大肉棒插入蜜穴 -103bb成人小电影 -最牛钉子户 -强奸21岁处女全过程/淫妹阴毛小穴 -干少妇小穴 -信号拦截器 -舔吮她的阴唇 -嫩穴狂插还流水 -zhan guo ying xiong -圣角色扮演学园 -色图乡 -a$shole -暴力虐待 -轮盘赌 -網龍 -艳乳 -淫奸熟睡的妈妈亚洲床上色情图库少女做爱 -杨林 -弟弟淫奸熟睡姐姐 -蝴蝶谷黄站 -又硬又粗的肉棒 -陽精 -Dick -法~~論 -变态 -毛二乙基酰胺 -爱滋 -日本成人激情 -fuck他母亲 -makelove -法@淪 -操淫荡 极品嫩穴操淫荡少妇 -抽插43岁处女meimei淫叫不断 -迅雷下载免费淫乱电影 -絲襪高跟 -春夏自由论坛 -20岁女大学生被强#(组图)全过程 -插他 -骚逼小姨 -抵制奥运 -全 國 兩 會 -观看淫电影 看完保证你打飞机 -汉奸 -美女嫩穴 -未满18岁的请自行离开 ! -日本成人激情淫穴 -封神榜 -操meimei -裙下風光 -两岸三地论坛 -牛B,牛比 -阳萎 -激情成人影院 -肉棒在阴道中疯狂抽射 -毛狗b -首長 -臺幣 -大会堂 -喔…快…爽死 -暴操淫荡小妹妹 -免费性爱电影网 -免費偷窺網 -窩窩客 -淫B浪穴 -强奸犯 -首长 -哪有a片 百万美女贴图夫妻激情免费视频 -又肥又紧的屄 -李宏旨 -xi you fu mo lu -避孕套 -黄色免费电影美女 -孫逸仙 -张伟国 -教你怎样延迟射精18岁以下禁 免费淫 电影a片 -新石器时代 -毛田纪云 -激情视频聊天论坛 -藏青社 -陰精 -RED HOT IDOL Vol。3 Concentrated Sex : 山咲舞 Mai Yamasaki 4 -成人激情asp电影通道 -乳此絲襪 -大鸡吧插meimei淫屄 -干您娘 -On Air -你他媽的 -淫水从穴门流出 -弟弟摸姐姐胸部小说 -密碼 -阿旺晋美 -嫩bb -日本無碼o ~幼齒女學生 -法^^淪 -G。M -吸毒犯 -三个代表 -綠色數碼 -温家宝 -肉棒插入子宫 -快干我!快干我┅┅我要被干 -我含着阴茎 -插你 -龔學平 -jinv -联众 -朱容基 -全球公審江澤民 -岡巒 -雞巴暴脹 -激情淫色网站导航 -抽插36岁处女妹妹淫叫不断 -MUGEN EX Vol。3 魅惑美少女 : 小日向葵 有码女优首度无码隆重登场 -复员 -激情裸聊 -亚洲淫影院 -欧美两性淫乱图片 -小雞巴 -穴口挤出淫水 -她的小穴插了进去 -porn -毛信访局 -外~掛 -比样 -運營者 -法~~论 -聚丰 -新绝代双骄 -手指插的进小淫穴 -肥嫩的阴穴 -捏弄 -联合国 -黃色影視 -倚天屠龙别记 殷素素 -蒙古達子 -阴蒂 -mythos -狂插 鸡巴狂插 -完全免费淫色电影 -美騷婦 -台湾 18 成人网 -弟弟淫奸jiejie论坛 -淫奸熟睡的妈妈 -窃听器 -独夫 -免费色情激情电影网站 -三級片 -eqsf -温家寶 -艳情小说 -fuck王乐泉 -外\挂 -鎮壓 -fuck温馨 -女友下班后被别人献花接走给操了 -抽插46岁处女meimei淫叫不断 -操你八辈祖宗 -中机电 -世界日報 -插你娘 -情色六月天mm淫乱 -39CK -王八蛋 -xinsheng -血逼 -裙下风光 -自慰 -下流地帶 -鸡巴插进了的小穴 -小泉 -亚洲/无码 -fuck小穴 -熟女乱伦联盟 -下流地带 -阴茎 -爱国者 -贼民 -哥白尼 -賤B -校园激情淫色 -爽女美图 -大便 -12次下跪 -王太華 -魏 新 生 -乳此动人 -淫亂軍團 -冈村宁次 -臺灣民國 -和条友做爱 -扒穴 -www。gpchina。com。cn -cao靠 -田紀云 -舔屄 -誘色uu -肏又嫩又紧的穴 -嫩穴肉縫 -賣B -985985 -txsanguo -美女主持27小时全天激情热舞 -干你媽b -流星學院 -少女嫩穴被插出血 -昏迷 -和两勇男玩29P -毛伊斯兰 -se淫乱jiejie小说 -舔舔私处meimei嗷嗷叫 -陆肆 -狗屁 -马的 -狂操搔逼妈妈 -狗屎 -炮友 -骚妹爽图 -阿芙蓉 -mbs -鸡巴 插 嫩穴 -刘少奇 -週六性吧 -做ai -AV女优 -阴莖 -日本激情淫穴电影 -吴仪 -毛反日 -挖挂 -愛妻淫穴 -淫荡老师穴 -无网界浏览 -18男人摸摸B -生命奇迹 -毛佛祖 -┅舒服死大鸡巴插 -舐她的小穴 -激情淫色视屏 -发~~仑 -淫奸处女穴论坛 -色空寺 -臺灣民国 -靖国神社 -毛学潮 -廖承志 -插你媽 -换妻 -meimei乱伦理淫穴 -崔英杰 -桃園蜜洞 -嫩逼 -他ㄇㄉ -大龟头在花心深处 -爆乳美脚RQ中出し鬼輪姦-- 森高レナ -爱的奉獻 -捅进了她的阴道 -台湾女人裸体贴图 -戴红 -毛观世音 -喷雾型迷药 -抽插31岁处女meimei淫叫不断 -王辅臣 -sm女王 -春光外瀉 -大学骚乱 -苯甲醯甲荃芽子堿 -啊雅娃娃 -二乙基酰胺 -牛比 -亚洲激情 贴图区 -黑白无常 -fuck性爱 -本站10003多部激情电影全部免费试看三天 -发~~伦 -性飢渴 -惹火自拍 -黄色免费超级淫图 -大乳 -美女插穴 -毛厕洞 -林彪 -极品成人电影 -和两勇男玩24P -傅铁山 -粗长的肉棒粉嫩的玉门里进出 -日本淫图 -龔学平 -幹GM -ㄐ掰 -军民冲突 -法~沦 -人肉 -萬鋼 -淫水流出图强*免费淫电影 -刘千石 -免费淫电影吴宗宪搞笑语录(18禁看) -哗哗曼 -性爱 图库 -共产主义 -抽插18岁处女meimei淫叫不断 -九评 -乱伦淫书丝袜淫图 -和两勇男玩23P -毛后庭 -免费淫奸女A片段试看 令人喷血的春宫108姿势(组图)18岁禁看 -小姐打飞机 -华通时事论坛 -迷姦雙胞meimei -免费淫奸黄色电影 -美少妇 -和两勇男玩22P -計牌軟體 -激情XXX电影( -徐匡迪 -生孩子没屁眼 -全球公审江泽民 -我草 -色弟弟 -无码片 -国民党万岁 -伸入姐姐裙内 -(盗摄)女子公共澡堂! -avi免费淫电影下载 -onewg -她妈的 -和两勇男玩21P -成人色网站 -少女一丝不挂做爱淫水直流! -爱的奉献 -朱毛 -亚洲黄站 -近親相姦 -点卡 -刘正荣 -开放杂志 -嫩穴肉缝 -妹妹等你大鸡吧来插 -毛客服 -肥西 -meimei┅┅爽快┅┅死了 -护士穴 -luan shi san guo -pp点点激情播放 -斧头镰刀 -胸罩 -公车淫奸meimei -裸聊日本成人电影 -毛狂操你全家 -日本淫色贴图区 -meinv做爱激情电影 -毛拉姆斯菲尔德 -淫奸嫂子穴 -和两勇男玩28P -胡主席 -三陪 -烂鸟 -(SOD)芸能人 範田紗の超高級ソープ嬢 -小骚比 -下阴 -桑國衛 -蔵獨 -遊戲管理者 -ying xiong wang zuo -弟弟mojiejie胸部小说 -盛大富翁 -台湾成人18贴图 -手记注册日韩5013部激情电影 -圣者无敌 -和两勇男玩27P -天主教 -龟头 磨蹭 插入 小嫩穴 -淫穴 夹 好爽 -弟弟淫奸jiejie -炼功 -免费淫奸女A片 -江八 -俏臀摄魄 -操薄一波 -作爱聚会 -和两勇男玩26P -cheng ji si han -品香堂 -李雪峰 -下陰 -kjking -近親相奸 -如果你未满32周岁请自觉离开。 -复制 -赣您娘 -驶你母 -貝肉 -國產AV -操操你妈 -365情色 -台湾身份证 -毛新义安 -肉棒在小穴里好爽 -濫比 -和两勇男玩25P -白癡 -吳邦國 -成人黄色电影 -毛台湾党 -我考 -於天瑞 -zlywy -漏B -插入內射 -國家領導人 -NND -肉棒刺入我的小穴 -免费淫奸女A片段试看 令人喷血的春宫108姿势 -册那娘饿比 -Poon Poon -法~~轮 -流星学院 -毛妈卖妈屁 -值勤 -打砲 -无关键词(导航搜索) -國軍 -鸡巴 嫩穴 淫荡 -SUCK -依星 -淫蕩 大雞巴 嫩穴 -simple -falundafa -亚洲激情妹妹 -大肉茎插进小肉洞 -毛亲民党 -國 賊 -教你怎样延迟射精33岁以下禁免费淫电影a片 -cabal -小姐打飛機 -黄色免费电影 -政治犯 -温家堡 -法$$纶 -wgpj -歡迎G12情色電影院 -倒塌 -NPC -手记注册日韩5015部激情电影 -唐人電視臺 -淫民俱乐部和meinv发春激情3级片试看 -滥货 -廖锡龙 -多人轮 -dse淫乱小姨小说 -13点 -海盗的悠闲生活 -公子冲 -偷情 乱伦 -狗干 -野外操B更刺激 -法^淪 -cao b -狗幹 -贱比 -老鸨 -凸肉優 -T。M。D -狂插meinv穴 -吞精騷妹 -发$仑 -新闻出版署 -白痴 -插 干jiejie 好爽 -妈的b -保监会 -美乳鬥豔 -滚那吗B -多人輪 -fuck王兆国 -笨比 -卖比 -操淫荡少妇 操淫荡妹妹 操淫荡姐姐 操淫荡护士 操淫荡 空姐操 老师操女老师 学生操老师 操老师小说 -妹妹美图网 -斐得勒 -娇妻偷欢超爽日本电影 -Red Hot Fetish Collection Vol。30 森田めぐみ -久遊 -和两勇男玩20P -杨月清 -成人午夜 -高文谦 -RI NI MA -激情爽电影,夜夜最消魂! -色网联盟 -吳儀 -zhengjian皮条 -超淫荡丝袜妹妹 -毛二逼 -YOUXIKA -妈的B -佳静安定片 -14se淫色图片 免费vagaa电影 免费电影 -NMD -毛恩格斯 -寂寞自摸 -生命奇跡 -欧美激情淫色贴图区 -新任教师の淫行物语 -610辦公室 -Red Hot Fetish 纹舞らん--スケパン刑事 -基地組織 -学生妹meinv在野外偷情 -援助交易 -23dy淫色贴图 -吳邦囯 -爷爷 -自拍 -法~~輪 -BlowJobs -学生暴动 -淫荡少妇露逼自拍 -梦幻西游 -郭 羅 基 -齐墨 -吾爾開希 -cao ni ma -幻靈遊俠 -fuck投毒杀人 -何候華 -雞歪 -手记注册日韩5000部激情电影 -激情玩穴网 -妹妹的嫩阴唇 -butthole -爸爸 -毛妳老母的 -管理员 -金酷 -meimei的屄 -马场大亨 -肉棒插入穴中 -学联 -淫荡妈妈之办公室助理 -发$伦 -计生风暴 -外_掛 -毛买财富 -肉蒲团 -挑战 -发*仑 -做爱爽图 -法$$綸 -tian zhi you xia -tom在线 -t2dk -taobao靠 -插你妈 -母子乱伦 -东条英机 -杨振 -周百刚 -毛主席复活 -亞洲互動 -站前留學 外國人英語會話教師的癡態紀錄 (3月作品) -浓浓的精液喷入了子宫 -mir -極品奶妹 -肉蒲團 -发$$论 -吞食天地 -中华养生益智功 -用手指玩弄着阴户 -法@@淪 -Biao子 -堕淫 -代練 -f_u_c_k -亲吻小屄 -Himiko 010 Riko Kurusu 来栖! 中出 -日本第一av女优武藤兰被10男糟蹋全记录1小时 -操濫妳那騷穴 -制服诱惑 -精液榨取 -毛澤東 -ALERT -cha你 -外_挂 -2。23会议 -boxun -產黨 -网爱 -陈破空 -管理員 -Pink Puncher~生中出SEX Ais Cumshot Inside Sex !! : 姬野爱 -色网阴道特写强奸31岁处女全过程 -操淫荡护士 操淫荡 空姐操 -壮汉给纯情处女开苞 -fa轮 -政府無能 -去你的 -黄色影视 -熟妇骚器 -斷電 -天安門事件 -毛吴官正 -毛食捻屎 -红楼绮梦 -asktao -毛发正念 -香港顶极淫片 -臺灣共和國 -色區 -色区 -网特 -外\掛 -小澤瑪利亞~~誘惑色情 -盐酸二氢埃托啡 -免费淫电影网址 -劍俠世界 -bt成人 -帝国主义 -大龟头碰到阴户底部最敏感的地方 -66xp。com 电影免费 -强*十八岁美女护士 看完保证你打飞机 -三唑仑 -成人图片 -zhengjian皮條 -李昌 -大肉棒干我的小穴和屁眼 -钓鱼岛 -吳 宏 達 -前凸後翹 -306醫院 -气性壞疽病 -戴相龙 -发*伦 -那嗎B -那娘错比 -21世纪中国基金会 -long hun -毛干七八 -插穴 -rxjhhvip -強姦物語 逢乃 -黑鮑娇 -老虎机 -fuck -蒋介石 -乱伦熟睡的jiejie -就去色色 -爆炸 -毛狗日 -六四死難者 -meinv -肉棒顶到花心 -Tora-Tora Platinum Vol。11 持田茜 -赵南 -毛社科院 -亚洲淫色图 -来爽我 -肉棒插进阴户内 -沈彤 -大鸡巴操得我好爽啊 -干阿姨的骚穴 -韓啟德 -推推俠 -在线清晰日本超爽mm毛 -好紧的小穴 -meinv视频短片 -苏晓康 -滕文生 -操射 -淫荡女mm的嫩穴 老师嫩穴 -sm调教 -郭 岩 華 -美乳看護學生 -毛胡耀邦 -netdream -幹死你 -何 德 普 -陰部 -柴玲 -毛死gd -免费淫奸女A片段 -插烂妹妹小屄 -外陰 -銀行帳号 -操草你妈 -两性午夜激情电影 -fuck售软件 -跳大神 -毛死gm -毛生孩子没屁眼 -汤光中 -日你妈啦屄 -推推侠 -小穴好紧 -女做爱光盘亚洲 -色魔 -天鹅绒行动 -发*沦 -乱伦熟睡的姐姐 -淫奸妹妹论坛 -香港GHB水 -高潮白漿 -淫色成人网址导航 -jing tian dong di -干老师的穴好爽 -色鬼 -和少妇做爱好爽 -法^倫 -震级 -万岁 -澳洲光明网 -淫洞 贴图 -一夜情交友 -咪咪圖片 -street of EROS 07 -street of EROS 08 -发~抡 -国产幼女屄屄套图 -淫女床上的自慰 -圓滿 -毛江泽民 -姐弟激情淫色 -狗城 -非常三国 -Red Hot Jam Vol。6 Chiaの露出初体験 -黄色图片 -20岁女大学生被强#(组图)全过程免费淫 电影 -好色妹妹电影做爱论坛 -bukake -平反六四 -非常三國 -姐姐的阴唇好大啊 -最淫成人贴图区 -da qing di guo -fuck吴 仪 -小鸡鸡 -成人网站 -fuck社会主义 -肉棒 ……好舒服喔 -圓满 -邪恶的党 -阴部翻过来看超拽 -千年 -张钢 -meinv插穴 -掰穴皮卡丘 -免注册台湾18dy -弟弟的大肉棒 -三国策 -WANZ)强制猥亵 非合法ドラッグ -妹妹的阴道真紧 -毛妈批 -东突暴动和独立 -精液射进小姨的子宫 -舔舐着阴道内壁 -少女免费激情电影 -毛皮条 -鹿城激情淫色贴图 -強制浣腸 -操打炮 -毛身份生成器 -毛睾丸 -法^侖 -红卫兵 -操抽插 -美仙子 美乳+美腳 天中梨子 -o2jam -免费淫奸女A片段试看 20岁女大学生被强#(组图)全过程 -生殖器 -小穴任由大鸡吧来回抽插 -美脚残酷物语膣壁浸透汁 -毛强效失意药 -處女小穴 阴毛 -淫奸处女 -yutong -亂武天下 -乱伦 -幹砲 -西游伏魔录 -和妈妈玩插穴 -萨斯 -大胆出位 -meretriz -毛肉洞 -大衛教 -黃色網站 -发$沦 -秘密調教凌辱 -fuck西藏独立 -三句硬话 -澳洲光明網 -快活林黄站 -fuck煞逼 -免费黄色网站电影 -幹你良 -hotsex -買月卡 -LineageⅡ -熱血江湖 -去妳妈 -日韩meimei嫩穴淫图 -乳交 -在线激情电影 - 会员注册 -fuck台湾共产党 -美體豔姿 -毛精子 -蠢猪 -mm美图 -女友坊 -肉棒快速抽插 -林心如做爱*色情电影*免费淫电影a片 -林肯 -淫乱军团 -法^伦 -毛小乳头 -中國 -免费淫 电影 -好色cc -台湾色色导航 -毛澤东 -抚弄后插入小穴 -中国 -淫奸电影 -推翻 -vaameline -日本美女图库 -亚洲成人激情影院 -超级樂者 -毛阳具 -抽插50岁处女meimei淫叫不断 -连邦 -露穴 -激情文学区 暴乳母娘 国外淫色贴图网址 -DICK -卖。国 -淫乱秘史 -台湾裸体贴图成人免费电影 -男人最爱的淫图 -裸体少妇 -mm美圖 -di guo chuan qi -乱交 -如果你未满22周岁请自觉离开。 -不用注册淫电影网站 -肉棒好粗 -天安門屠殺 -黄色免费电影meinv -内射魅惑の美少女精液滋滋往外冒 -肉棒插入嘴 -絲路傳說 -天閹 -毛弓虽女干 -蒸汽幻想 -林业局 -新唐人電視臺 -毛孙逸仙 -李 旺 阳 -操屄 -毛丫头养的 -妹妹的屄好紧啊 -Gold Angel Vol。8 Super Erotic Girl : Rio Nakamura 仲村りお -操陈水扁 -我和小姨淫 -姚依林 -你的小穴好温暖… -群阴会 -遊戲指導員 -毛国务院 -两个中国 -毛工力 -妹妞露穴 -毛枪决女犯 -在线淫洞影院 -操尼 -thsale -最新娱乐黄站 -处女性开苞 -孤儿 -pk1937 -毛片 -発射 -成人午夜激情电影 -发@沦 -装屄 -金发表姨子的鲜嫩蜜穴 -恋爱盒子 -台湾成人23贴图 -凯图科技 -九評共產黨 -RED HOT JAM 7 Eeos Note 姬崎水希 -aion -江折民 -肉棒插入肥肥的淫道 -孤兒 -粗大的龟头 -黄色漫画 -王涵万 -圆满 -台湾党 -插婷婷小穴 -奸淫少妇穴 -天安门惨案 -疯狂抽插嫩穴 -日本淫色贴图 -肉棒插进蜜穴 -天阉 -meinv激情性交射精电影 -2逼靠 -那吗B -李 旺 陽 -香港成人色网址大全 -爛比 -法^仑 -总理 -妳媽的 -圆滿 -unixbox -肉棒的抽插淫荡少妇穴 -军转 -欧美成人激情网站 -毛日你娘 -抽插25岁处女妹妹淫叫不断 -毛新党 -被老师强奸的小初中生 -手记注册日韩5018部激情电影 -黄色免费电影淫电影在快要射精时迅速地将 -慰安婦 -高麗棒子 -姐的嫩阴道 -顶到花蕊 -Ttmd -Gate To Heavens -压/无码 -棒阴道好痒痒 -弟弟的肉棒好粗 -用力刺激小穴 -干小姐小穴 -taobao -我的小屄儿好痒 -阴道图片 -私**服 -sars -张震 -性交課 -免费淫虫在线看电影 -麻醉钢枪 -强奸29岁处女全过程/淫妹阴毛小穴 -性爱擂台 -激情 少女 成人论坛 乱伦 -星際online -柯慶施 -法^^沦 -真理教 -中国美女淫色贴图 -gc365 -21cn -高潮白浆 -人民報 -成人午夜激情聊天室 -毛日你妈 -幹穴 -精子射到妈妈的穴里 -毛狗操 -中宣部 -毛佛展千手法 -王希哲 -妈妈你的穴好紧 -摩门教 -龙虎 -操淫荡妹妹穴 -妈个比 -GM美国 -血洒 -美利坚 -淫meimei电影论坛 -wai gua -血洗 -中天万方 -┅┅妈舒服死了 -GM美國 -毛金日成 -龟头抵制花心顶住子宫口 -李 少 民 -亚洲贴图区月宫 -狂插 嫩穴 -搜狐 -meinv主持24小时全天激情热舞 -勾魂少妇 -caoB -勾魂少婦 -KISS -免费在线淫电影欣赏 -Red Hot Idol Vol 1 -毛六四 -蒙古达子 -干炮插穴 -冊那 -解放军306医院 -共产党靠 -肉棒插入浪穴 -to173 -外@@掛 -性病 -女儿的阴道好嫩啊 -免费淫电影a片。母子淫*乱轮现场看扶正肉棒 -香港免费淫电影 -上妳 -毛苹果日报 -范田紗~120%!H喜不自禁住在一起日記 -阴茎把淫穴塞满 -教你怎样延迟射精18岁以下禁免费淫电影a片 -Priston Tale -先审后贴 -卓奥 -soma -K他命 -李文斌 -钦 本 立 -卓奧 -奥运 -新诗年鉴 -globalrescue -免费淫色电影下载 -压制 -淫荡家族群体性交 -meinv激情视频聊天室 -干全家 -互联经纬 -脫衣舞 -吴 百 益 -藏妇会 -分家在 -毛美国之音 -933cn -五星红旗 -插你老母 -淫奸护士穴 -鸡吧刺入她肛门 -中国娱乐黄站 -骚浪淫水的小屄儿 -麥角酸二乙基酰胺 -qi ji shi jie -色色连 -龍與地下城 -社。會。正。義。力。量 -弓雖 -慰安妇 -嗯…… 啊… 不要停…… 啊…… 插的再深一点… -yxzbw -奧運 -干穴 -指点江山论坛 -幼男做爱妹妹做爱 -淫奸阿姨穴 -八九风波 -白小姐 -毛董建华 -毛外\挂 -错那吗比 -pp241淫色导航 -毛外汇局 -假阳具插穴 -艳妇淫女 -本站10002多部激情电影全部免费试看三天 -哥哥淫奸meimei穴 -交换夫妻 -兴奋剂 -风月大陆 -东正教 -扎卡维是英雄 -成人电影 -無碼炮圖 -法功 -淫水嫩穴 -國 家 安 全 -靈遊記 -毛迷歼药 -弓虽女干 -亚洲成人激情视频 -94bb成人小电影 -家庭乱伦小说 -mforest -圣母 -马巧珍 -毛外_挂 -情报 -创网 -册那 -可爱双胞胎美幼少女的性趣[亚无][402mb] -毛铁道部 -game588 -大鸡巴狠狠插进了她那又肥又嫩的小骚屄儿 -高治联 -二穴中出 -无码体验 -汶川 -实现你的幻想 -塞你公 -外@@挂 -日本18淫电影网 -咪咪图片 -情色谷 -奸淫护士穴 -卡通美女淫色贴图 -剑网 -发^抡 -口交 -自由民主论坛 -扒开她两扇阴唇 -免注册在线淫电影 -反党 -毛死GD -大血比 -kqking -泄密 -骚鸡 -淫荡痴女贴图 -幹你老母 -一邊一國 -成人色情网站初中女生偷拍 -毛死GM -dick呂秀蓮 -発妻 -外教上课迟到就挨操 -fuck射精 -幹你老比 -mm乱淫自拍图片 -激情淫色mp3 -儿子的肉棒顶到妈妈的花心 -毛狂操 -水浒 -爱女人 -新华社 -71776 -法@倫 -垃圾游戏 -……浪穴……大肉棍 -巴赫 -分裂 -毛李登辉 -pp点点激情 -淫色搔女网 -鸡巴对准淫穴 -毛李红志 -淫女穴 -美乳斗艳 -毛天鹅之旅 -凌辱 -勁爆 -狗卵 -nana无修正AV女优ハメ撮り -弟大物勃 -北京当局 -天天干貼圖 -戴 相 龍 -88jb -roi world -共和国卫士 -fuck审计署 -汇款 -反共 -领取 -游戏橘子 -性交课 -煙膏 -大鸡巴干meimei -六合采 -anal -分裂国家 -姐弟淫乱还玩3P -毛系统公告 -法*功 -免费妹妹黄色淫乱电影 -淫賤少女 -光之國度 -火麻 -戴 相 龙 -騷妹妹 -金鱗豈是池中物 -男女激情淫乱图片穴 -肉把鸡巴包得紧紧 -東北xx網 -closeupsof。us -洪传 -受虐狂 -毛警匪一家 -毛龟公 -操操蛋 -毛睾 -毛五星红旗 -拉姆斯菲爾德 -fuck西藏天葬 -狗狼養的 -買春 -fuck王岐山 -免费淫色情电影 教你怎样延迟射精18岁以下禁 -阴道图打手枪专用 -媽媽的 -又肥又紧的阴道 -高清性愛 -淫奸处女电影 -克林顿 -办理证件 -毛发抡功 -毛傻比 -成人图片导航 -激爽电影VIP会员注册区 -刀剑•英雄 -色情工厂 -ji女 -不要注册激情免费电影 -系统 -午夜成人场 -陳水扁 -你媽的 -毛煞逼 -納粹 -毛游戏管理员 -毛性虐待 -康生 -超級樂者 -雞8 -亚洲成人午夜场 -fuck王刚 -注册通道看情色电影 -色网阴道特写强奸26岁处女全过程 -布雷尔 -受傷 -gamemaster -人妻交换 -抽插29岁处女妹妹淫叫不断 -乱伦都市 -fuck系统讯息 -受伤 -olgad -淫妻浪女 -男人若妻夢交 -秦晋 -Tokyo Hot n0156~160合集收藏版 -操淫荡少妇 -戈万钧 -wg886 -捅逼 -走光 -Suck -父女激情淫色 -操你八輩祖宗 -毛何候华 -保卫台湾 -肉棒插蜜穴 -抽插53岁处女meimei淫叫不断 -白虎嫩B -达尔富尔 -毛阴唇 -法@侖 -政协 -激情自拍小电影 -趙 曉 微 -政協 -抽插55岁处女meimei淫叫不断 -高橋英4套片合共 -少妇自慰 -狗剩 -操淫荡少妇 操淫荡妹妹 -白虎嫩b -儿子淫奸姐姐 -八九民运 -毛升达毕业证 -被幹 -王炳章 -助理 -卵子 -本拉登 -翘臀嫩穴 -被干 -毛肉棒 -哥哥干的人家好舒服啊 -沧澜曲 -月宫套图社 -法lun功 -教你怎样延迟射精36岁以下禁免费淫电影a片 -操mm穴交 -陰門 -催情药 -中华 -激情淫影院 -日本灌肠 -suck你媽的 -在线淫电影,免费淫色情电影 -激情四川方言版 -高 潮 喷精 -姦淫電車 -姬胜德 -蔣經國 -我你老板 -韓正 -手记注册日韩5012部激情电影 -李 月 月 鳥 -人妻交換 -前网 -transexual -低價金幣 -台湾成人24贴图 -hardcore -女儿淫奸妈妈穴 -日本顶级淫片 -摸擦小肥穴 -卡卡金币 -14色se成人站 -性学教授 -小阴唇被鸡巴猛的塞进去 -法@伦 -龙腾工作室 -妳老母的 -李紅志 -現役看護婦 -毛肉棍 -大鸡巴插入肉穴 -8。9 -軍民衝突 -中功 -精品性交图 -瑞士金融大学 -系统消息 -邻居美少妇 操淫荡少妇 -成人色情导航 -完全免费在线淫电影 看完保证你打飞机 -色狼俱乐部 -滾那嗎老比 -孫中山 -陰阜 -淫电影//居然花钱请人教性爱姿势(组图) -可卡因 -色情电影 -张林 -税务总局 -meinv淫图 -qqyinsu -mystina -淫图新社区 -鲍戈 -妈妈嫩穴…痒 -血比 -piao liu huan jing -天之煉獄 -顏射 -午夜激情妹妹 -馬巧珍 -姑妈的阴道好紧啊 -处女开包 -现役看护妇 -亞洲性虐 -法@仑 -日你全家 -她媽的 -發~~掄 -去她妈 -姐姐的阴道好紧啊 -分裂國家 -毛淫荡 -365 sex -毛联合国 -…你的穴太紧了 -tie jia zheng xiong -招鸡 -久遊網 -fuck倭寇 -本站10022多部激情电影全部免费试看 -大 史 记 -若叶~Princess Collection(1163) -极品波霸 -丁香社区 -发仑 -张志清 -毛钱其琛 -特种部队 -狠狠地肏 -丁香社區 -李 月 月 鸟 -┅我要泄了┅┅喔 -无毛穴 -camon -王 冶 坪 -操我 -金鳞岂是池中物 -发伦 -hai dao shi dai -long yu di xia cheng -干七八 -毛高丽棒子 -天骄 -ezgaming -日本灌腸 -X媽牛比 -少妇的骚穴淫液 -你的大鸡巴好粗 -成人激情论坛导航 -李洪智 -狗养 -赤匪 -xin chang zhi ye wang -劲爆 -处女淫荡色情网址大全 -混 沌决靠 -陳雲 -美女小穴贴图偷拍少女乳房 -江独裁 -lihongzhi -小乳頭 -大话战国 -性色社区 -淫荡俱乐部 -街头对抗 -母子乱伦之淫穴 -兆鸿 -敬國神社 -杜鲁门 -毛回民暴动 -扎卡维 -国家总理 -那吗老比 -賽妳阿母 -天龍八部 -法腀功 -比的 -台獨分子 -鲍彤 -六四平暴 -野合 -酥胸誘惑 -大法弟子 -公审江泽民 -可卡叶 -韓啓德 -毛江主席 -光之国度 -在线免费激情裸聊 -搞B -拿破仑 -法西斯 -赤化 -政变 -AV足球賽11男VS11女大對決 -毛环保总局 -洞洞淫水清晰大图 -针对台湾 -独立台湾会 -儿子顶到姐姐的花心 -傭兵傳說 -懆您娘 -四海龙女 -发^^仑 -帳號 -领土 -穴图 -xing kong huan xiang -webgame。com。cn -色链 -杨尚昆 -阴唇 黏液流下 -粗大的鸡巴插入穴洞 -強姦處女 -东升 -法*倫 -現役看護婦下载 -圣火 -办理文凭 -公交车上操女大学生 -强暴 -淫荡女护士 -穴圖 -少妇房中自淫,和两勇男玩1P,操得直叫爽 操日本淫女穴 -亚洲午夜成人影院中心 -快克 -三K党 -克林頓 -护士脱衣图台湾激情电影 -免费淫电影 看完保证你打飞机 -fuck网管 -少妇嫩穴扒开嫩穴扒开嫩穴 -pcik -薩達姆 -色情小说 -手记注册日韩5023部激情电影 -成人电影免费成人电影 -法国 -发^^伦 -激情成人淫片 -妳她妈的 -人大代表大會 -成人论坛 -張震 -逼你老母 -李 文 斌 -操日本淫女穴 -精蟲 -中共 -毛三陪女 -啊……快插啊……小屄美死了 -陳奎元 -大波騷婦 -小骚洞 蜜穴 -本。拉登 -成人导航 -黑星女侠 -纪登奎 -毛管理人员 -牛逼靠 -刘亦菲淫阴道流血色片 -懆您妈 -发**轮 -黄色免费淫乱电影强奸片 -毛共匪 -扒开嫩穴 抚摩她的嫩穴 下身也不停的抽插着 -rxjhvip -ハイパー×潮吹きハイパ 麻美ゆま -U/R靠 -媽B -habbo -japansweet -dekaron -淫色小说网短片色情 -阿扁萬歲 -香港激情淫色区 -鸡巴插进娇嫩的花蕊 -法*侖 -阿姨的阴道好大啊 -兆鴻 -u r靠 -妈逼 -情色照片 -紧穴 -神州天戈 -瞳-饮精地狱!监禁无限中出 -哥哥使劲插我 -野鸡 -贺国强 -強暴 -毛看棋软件 -免注册淫电影爱的色放 -血腥图片 -民航局 -処女強奪3穴串挿輪姦 -毛日你 -53xp。com 电影免费 -法$倫 -操那吗比 -鹽酸二氢埃托啡 -射进小穴 -粗硬大肉棍… 抽动…好舒服 -本站10013多部激情电影全部免费试看三天 -视频聊天导航 -騷婦掰B -模拟机 -乳此丝袜 -掰穴打洞 -死全家 -法^^抡 -偷情宝鉴 -安南 -58jb -傻× -吴方城 -宋楚瑜 -森水Cocoa -立即登陆观看激情爽片 -上海孤儿院 -强奸 -肉棒噗嗤一声插入阴道 -工自联 -日本成人贴图区论坛 -午夜剧场成人视频聊天 -淫荡美眉就喜欢玩男人 -做愛寫真集 -阴道 -直操她嘴射精 -强奸44岁处女全过程/淫妹阴毛小穴 -xing zuan wu yu -project -淫水四益 -阴茎在子宫口游荡 -淫水絲襪 -幹炮 -人民币 -公车淫奸jiejie -装逼靠 -小穴被大鸡吧胀的好痒 -卡弗蒂 -色狼论坛 -免费淫色贴图 -烂逼 -中南海 -昝愛宗 -骚穴怒放 -毛他妈的 -干进妹妹的小穴 -鸡巴用力深度插入 -淫奸jiejie论坛 -媽比 -姐弟激情淫秽 -计牌软件 -伊拉克 -成人影視 -下载黄色淫乱电影 -都市乱伦 -日本情色淫电影 -垮台 -VIP特区 激情在线 -fgmtv -肉棒深深插入纖弱的肉洞裡 -青天白日 -feng wu tian jiao -鹿城娛樂 -傻b -穴居人淫色贴图 -共黨 -B博士 -新魔界 -封神传说 -東方資通 -免费在线淫电影网站 -宾馆女郎 -性感肉丝 -中共中央中华人民共和国 -毛多维新闻 -打倒中國共產黨 -caobi -18dy影院 -舔哥哥鸡巴 -情妇 -杨白冰 -成人影视 -清纯派美女可爱的让人想狂干她!【RMVB/195MB】 -hero108 -淫语痴女 -大 史 記 -日你妈靠 -色天堂18禁 -毛淫货 -眾志成城 -肉棒狂插好爽 插我 -華夏II Online -干爆 -华建敏 -毛淫贱 -你妈靠 -少女被强奸到高潮时偷拍小A片 -毛肉棍子 -街頭籃球 -毛人代会 -他吗的 -韓桂芝 -人民幣 -自由亚洲 -湿润的花蕊 -jiejie的小穴被大鸡巴插得好舒服哟 -毛发轮 -靠母 -發~~淪 -法鯩功 -厕所偷拍 -強姦 -欧美淫乱美女论坛 清晰的窥阴图 -六四参加者回忆录 -大粗肉棒插入阴户 -本站10014多部激情电影全部免费试看 -四清 -FUCK -qeeloo -江氏 -达赖 -台湾分裂 -肏我的小屄 -卫生棉条真人使用图 -李弘旨 -色情淫图 -做愛自拍 -mm在线电影a片3级片 -极欲燃烧 -中国人都在上的四大当 -东热空姐 -儿届中央政治局委员 -操穴喷水 -fuck十八摸 -金币网 -杀人犯 -校花沉沦记 -少妇野外淫穴 -免费淫色妹妹电影 -干炮 -叼你 -插在小穴里的肉棒 -吴百益 -功夫online -teen -真三國無雙OL -免费淫奸女A片段试看 教你如何鉴别处男处女的方法(组图)18岁禁看 -肉棒在阴道内喷射 -梦中的女孩 -怎样延迟射精25岁以下禁 -testicle -非洲 -肉棒深入花心 -天皇陛下 -bignews -色妹妹大型黄站 -哲 民 -淫奸少女贴图淫奸女护士贴图淫暴亚洲 -破鞋 -賣淫 -地震局 -暴行白書女 -好死不如赖活着 -自由亞洲 -mm电影小片段试看免费淫影片 -体育总局 -达賴 -fuck威而钢 -天安门屠城 -免费激情电影 爽电影 -激情书屋男女做爱片段 -幼齿 -迷藥 -灼热的龟头紧顶住柔嫩的菊花口 -朱蒙 -午夜激爽电影网【成人电影色区】 -歐美無套 -毛外-挂 -鸡巴狠狠插入娇嫩夹紧的阴道中 -馬萬祺 -淫色电影论坛 -safeweb -SpecialForce -曰GM -紅頂商人 -肉棒深插 -狗乘 -丝袜淫妇 -咪咪情色 -私服 -傻B -hun luan mao xian -淫乱金发meinv -亂世三國 -阴部 -插嫩穴 淫水流 -玩弄她的骚屄嫩肉 -幹bi -你姥姥的 -爽爽爽台湾成人贴图 -曰Gm -毛外/挂 -《金瓶梅》的巨著 -插我 用力插 好爽 -webgame。com。cn靠 -无码内射 -淫荡痴女 -大鸡吧寸寸深入直顶她小屄的花心 -女同志淫乱贴图 -性爱频道 -激情淫色动画片 -操你全家 -掌上书城 -毛妓女 -毛水去车仑 -操操 -英雄纪念碑 -双峰微颤 -妹妹穴 -教你怎样延迟射精19岁以下禁免费淫电影a片 -毛国际法院 -毛黄 菊 -大鸡巴顶进meimei的花心 -nigger nigger -磕药 -情報 -wg17173 -买卖枪支 -強衛 -fuck五星红旗 -哥哥的肉棒好长啊 -专制 -火線任務 -幸运抽奖 -洗脑班 -教你怎样延迟射精24岁以下禁免费淫电影a片 -毛胡紧套 -塞你娘 -灭绝罪 -尖阁列岛 -龙 虎 门 -舔的下体湿润阴毛 -丽春苑 -陈晓宁 -乳 -骚屄娘们儿 -发~沦 -激情热舞 -prostituta -禁断少女 -老少乱伦 -hang hai shi ji -激情小电影 -幹妳媽 -手记注册日韩5001部激情电影 -郑万通 -成人小說 -强奸30岁处女全过程/淫妹阴毛小穴 -狂操你全家 -按摩棒 -台湾成人21贴图 -孫家正 -郑源 -美女口含鸡吧玩内射 -赛你娘 -小电影免费看高潮屋贴图做爱视频表演 -日本美女鲍鱼贴图区 -av贴图 -民主潮 -(人妻。com)人妻の情事2 夫以外の男に中出しされた妻たち -装备展示 -婷婷淫色贴图 -做爱视频下载 -毛切七 -鹿城色妹妹大型黄站 -106bb成人小电影 -中国大型免费成人黄色图片区 -毛牛比 -操博讯 -免费免注册淫电影 -姨妈和我乱伦理小说 -猛插小嫩穴 -台湾成人视频聊天 -meinv激情SM处女淫水 -雪山狮子 -民猪 -豖者 -錢其琛 -毛官商勾结 -台灣倫亂網 -天之游侠 -美女穴 -煞筆 -黄色靠 -freenet -毛贾庆林 -开房 -操催情药 -怀念十五年前的大学生 -冰锋 -mankind -子宮 -本站10017多部激情电影全部免费试看 -子宫 -次郎 -吕秀莲 -玩3p色链 -希拉克 -特別公告 -煞笔 -youxika -吸精痴女 -你把妈的穴穴插满了 -一夜情 -肉缝 小肉穴 -仆 -sealonline -巡查员 -回民 -毛王八蛋 -mierda -大麻 -xin chang zhi ye wang -激情解码两性电影 -亞洲風暴情色 -交通部 -毛狗屁 -赛妳阿母 -狂插meimei穴 -毛毛XX -对日强硬 -五月四日 -遗精 -毛狗屎 -毛温家保 -洪兴 -弓雖女幹 -轮流执政 -發掄 -流亡 -操大*FA弟*子 -最大的性虐待及另類性生活網站 -粉嫩淫臀 -韩国三级电影 -无码做爱 -反华 -欧美激情淫色贴图 -淫东方 -淫語痴女 -nude nude -新唐人电视台 -毛奶子 -毛军委 -毛新光明 -叛党 -法^^掄 -毛王岐山 -民进党 -廖晖 -香港激情论坛 -黃易群俠傳 -qi xia -李沛瑶 -王洪文 -ling tu -龟头顶在花心深处 -丁字褲翹臀 -廖暉 -又骚又大的屄 -姣西 -巡查員 -激情淫穴小说 -信长之野望 -六四死难者 -姐姐的阴户好嫩啊 -免费成人电影 -驶你老师 -美女下体淫水直流 -口交靠 -小姨令我射了好几次 -极品奶妹 -淫戰群P -毛鸡芭 -毛严方军 -林心如做爱网 -兩腿之間 -那嗎老比 -干爽 -坐庄 -三国群英传OL -烂货 -免费淫奸女A片段试看 强*十八岁meinv护士 -和姐姐肏屄 -成人小说 -幹妳娘 -天天情色 -磕藥 -干牠 -反動 -色书库 -六。四事件 -13點 -反动 -epochtime -厕奴 -女醫師過度輪姦陰道麻痺+大量中出強制飲尿小便斗 -鸡巴插入肉洞 -教你怎样延迟射精21岁以下禁免费淫电影a片 -佣兵传说 -foutre -mao xian dao -親 日 -發**綸 -弹 劾 -silkroad -厕所盗摄护士姐姐性感美腿图 肉丝美腿艳情淫欲 -十年動亂 -漢 奸 -萬歲 -毛军妓 -百家性黄站 -家乐福 -田紀雲 -又猛插几下 -儿子淫奸jiejie穴 -王永生将军 -本站10016多部激情电影全部免费试看三天 -jiejie的阴户 -si lu chuan shuo -美女激情SM处女淫水 -大揭露 -于大海 -操大便 -粗大的肉棒 -盛大 -弟大勿勃 -李兰菊 -阴道口湿淋淋的 -家庭乱伦 -少妇操尿穴 -東突 -本站10015多部激情电影全部免费试看三天 -大富翁 -捐款名单 -毛胡乔木 -口圭 -将肉棒插在阴道里面 -討伐中宣部 -淫meimei成人娱乐 -fuck傻吊 -米青 -ghost -大 紀元 -藏青会 -反人类 -吾爾開西 -又肥又嫩的阴户 -政治協商會議 -日本激情淫影片下载 -劍俠情緣 -遊戲蝸牛 -它妈地 -又骚又淫的屄 -Kamikaze Girls Vol。 27高清晰版本 -Archlord -爆操 -皮条客 -免费淫奸女护士图片 -淘宝靠 -儿子淫奸姐姐穴 -肉棒狂插流出淫液 -丁元 -淫民激情文学图库 -龟头直抵子宫口 -远程偷拍 -bt淫色电影免费下载 -meimei淫图 -国产无码 -操林 -毛斧头镰刀 -淫阴贴图 -fuck you -法~倫 -古龙群侠传 -共产党 -星鑽物語 -淫水狂流 -白立忱 -抽插33岁处女妹妹淫叫不断 -毛王太华 -毛龟头 -aids -一中一台 -带练 -fuck天安门一代 -一党 -操meinv穴 -张万年 -神淚 -激情成人午夜 -99bb成人小电影 -毛他祖宗 -那娘瘟比 -粉穴嫩逼 -粉嫩粉嫩的小穴流水 -精液喷射小穴 -勁舞團 -死刑枪毙 -至淫绝地 -农业部 -fuck fuck -扶不起的阿斗 -插后庭 -淫荡美女医生 -meimei的穴好多水 -和阿姨玩插穴游戏 -看棋軟體 -石首 -公審李鵬 -洛奇 -密传 -真主 -手指用力扣进小穴 -阴茎被肉壁紧紧的夹着 -毛驶你老母 -淫液流入穴 -姊姊的小骚屄 -无疆界 -雨星网 -东亚 -apex -性感美女淫穴 -阴唇 口含鸡巴 -艾森豪威尔 -淫液顺着肉洞流下 -日本激情淫穴片 -自插小穴 -urban -自慰摳穴 -一根材激情五月天 -毛狗娘 -极品激情电影 -干 …插我的穴 -美女鸡吧图 -韩日成人激情影院 -硕大的肉棒 -夢~ Pure Idol Vol。 20 : 望月なな -色情电影免费看 -毛外—挂 -军国主义 -淫乱姐姐小说 -hacking -在线淫电影 免费淫奸女A片段试看 -操护士的穴 -自拍美穴 -成人黄色网站 -不玩了靠 -上海帮 -啊 ……用你的鸡吧插我 -法~侖 -叛國 -学生爱国者运动 -婁義 -日本淫色动画片 -粗……肉洞 -挺进小穴 -强奸25岁处女全过程/*妹阴毛小穴 -倚天二 -叛国 -大鸡巴 用力地干 -wg666 -莲花逼 -毛监察部 -操大东亚共荣 -将肉棒插进她身体的最深处 -夫妻俱乐部 -欧美淫乱meinv论坛 清晰的窥阴图 -戳B -狼族淫色群交蜜穴 -fuck圣女峰 -台湾建国运动组织 -黑鬼 -wulin2 -抽插49岁处女meimei淫叫不断 -一股滚热的精液从插得紫红的龟头马眼里激射而出 -淫电影 强*十八岁meinv护士看完保证你打飞机 -fuck文物局 -国家机密 -婷婷激情俱乐部 -保密局 -1989 事件 -英雄王座 -肉棒狂插 浪穴 嫩穴 -毛发论 -肉棒顶开阴唇 -男女激情电影 -它爸爸 -情色藝術天空 -Red Hot Fetish Collection Vol。 34 : Saito真央 -激情淫色网站 -下作 -日韩淫女电影 -龟头在阴道里抽插 -下体 -meinv发春激情在线电影 -行房 -shao lin chuan qi -爆乳娘 -大东亚 -曰gM -上你 -哥哥粗大的肉棒 -我漂亮的老师狗爬式做爱现场 -戳b -傅作义 -发展研究中心 -系統管理員 -奶頭 -七五事件 -曰gm -法愣 -干进她穴内的龟头 -LIHONGZHI -陰部特寫 -插进少女粉红阴道 -Fuck -生春袋 -素人娘 -抽插31岁处女妹妹淫叫不断 -MAKINGLOVE -羅富和 -ㄙㄞ你老师 -色meimei乱伦理小说 -enculer -スクールガール 直美 -母子淫奸乱轮现场看 -猛嫩穴把肉棒包得紧紧 - Maki -儿子的大肉棒 -妹妹的嫩阴户 -jian xia qing yuan -毛蒙古独立 -靠爸 -淫师荡母 -延迟射精 -露B -发奖使者 -YGBH -激情网址导航 -女馬 -嗎逼 -狂插淫洞 明星陰穴 -karma -淫护士电影 -啊呀娃娃 -毛联易 -りすぎ家庭教師 ほしのキララ -震級 -露b -52淫色导航 -足球經理線上 -学生与警察 -海盜王ONLINE -大使馆 -Kamikaze Girls Vol。30-中野美奈 -香港激情淫电影 -帶练 -Tora-Tora Platinum Vol。11 S级圣女 持田茜 -熟妇人妻 -淫电影 -小穴……好爽 菊穴 -多维周刊 -古方迷香 -中华真实报道 -又大又硬的肉棒 -高校暴乱 -匯款 -白虎少妇 -色猫情色论坛 -刘宾雁 -你媽比 -侦探设备 -好长的肉棒 -乔冠华 -法~伦 -黄色三级片 -蔡崇国 -jianghu -温加宝 -学习班 -chuan shuo -反革命暴亂 -插妈妈的小穴 -lei ting zhan dui -濫B -发^沦 -废物 -李瑞環 -mo huan sen lin -唐家璇 -又鳥女幹 -www。qq965。com -运营长 -台湾成人22贴图 -阴阜 -刚发育好的处女就这么被干 -歇逼 -本站可能有不适合未成年人观看的内容 -噴精 -穴门美女图库 -蜜穴贴图 -淫奸mm电影 -护士诱惑 -郭罗基 -放尿 -放屁 -成人在线免费淫电影 -狂风暴雨 -不举 -法~仑 -星钻物语 -它妈 -shaolincn -鲜族 -阴门 -三夫妻结伴旅游换妻大乱交 -淫民激情文学图库欣赏 -反革命暴乱 -毛我操你 -毛欢城 -劍俠情緣II -mo擦小肥穴 -值勤帳號 -淫虎成人导航 -エロい女中出し20連発姫野愛 -淫奸小姨电影 -本站绝无任何形式木马病毒 -骚姐乱伦 -無套自拍 -白虎少婦 -test -毛麻醉药 -wu jin de ren wu -粗大的阴茎与紧窄的阴道壁之间的剧烈磨擦 -jiejie的嫩阴唇 -賣比 -張榕明 -口合 -慰春情 -偷窥无罪 -幼男 -凌锋 -xyd -黃色電影 -offgamers -贞操 -迅雷下载淫乱电影 -xyj -陰道 -盐酸二氫埃托啡 -台办 -姫野爱 -バコバコ风俗 W指名 遥めぐみ×美优千奈 A -賤比 -xyq -夫妻激情自拍图 -歡迎G10情色電影院 -插B -洪吟 -看单亲妈妈给儿子的性启蒙 -坦克宝贝 -性交靠 -ma chang da heng -懂文华 -售软件 -國權 -雞芭 -毛公安 -放荡熟女 -肉穴肥肥的裹着阴茎 -激情裸体 -抠 插 磨蹭 穴 -性免费电影 -黄色做爱电影 -西藏喇嘛 -六四以後 -插b -劍網 -王从吾 -麻醉药 -烫的大鸡巴在小穴里来回抽插 -免费视频裸聊 -丰满的视频聊天主持 -熊焱 -大鸡巴 插 少妇 -性爱 -处女膜 -吗个 -Pure Idol Vol。20 望月なな !【RMVB/543MB】 -和嫂嫂淫穴 -网络创世纪 -everstar -狂插妹妹穴 -小騷貨 -砍翻一條街 -操插gm -厕所盗摄护士姐姐 -李瑞环 -插你全家 -广电 -popkart -第九城市 -鬼畜輪奸 -fuck傻卵 -插小穴妹妹直流水 -出售账号 -迷药 -婷婷激情网 -肉棒插入又大又深的穴 -瘟比 -我使劲快速抽插龟头好麻 -插入她的搔B爽死了 -肉摩擦她处女的肉穴深处 -纶功 -插妹妹图 -外 挂 -激情淫贴图网 -狂插护士穴 -吮吸肉棒 -毛一党专制 -午夜情人 -BIAOZI -fei chang san guo -我操靠 -陈昌智 -操操逼 -妓院 -huan ling you xia -阳具在她的蜜穴里抽插 -卖国求荣 -他马的 -熊炎 -香港激情淫色贴图区 -8仙靠 -女马 -亲 美 -毛喷你 -大众成人网站 -捅进她的阴道 -政府无能 -姐姐被轮奸 -舌頭穴 -新闻出版总署 -催眠悪用集団轮奸30连発 -骚嫩的蜜穴紧紧地裹着大鸡巴 -操插gM -TTMD -Pink Puncher Premium Angel 光咲玲奈 -李洪志 -立花里子のレズビアン母乳M女コレクション -八九風波 -西藏獨立 -日本无码成人电影 -阿片烟 -大陆鹿城黄站 -操护士 -杭州二元 -共铲党 -激情淫色论坛 -激情淫穴小少妇 -法錀功 -亚洲色meimei -hellgate -www。gpchina。com。cn -王沪宁 -狂操空姐 -毛高校骚乱 -世模 -法轮功 -仙劍 -xiao yu er yu hua wu que -騷雞 -卫生巾 -fofg妈的 -干妳妈 -chinesenewsweek -彭佩云 -六-四 -淫meimei -粗硬 大 龟头 狂插 -rjwg -喷 -幹拎娘 -feng shen bang -教育部 -婷婷淫女小说 -荣毅仁 -Apexsoft -什麼什麼大冒險 -shen zhou tian ge -抽插小穴 -8仙 -豔照門 -仙剑 -臭西化 -熟母 -d7se淫色贴图 -騷B熟女 -免费淫电影在线观看 -H淫乱乳娘 Tora Tora Gold Vol。23 星之雪 -法@掄 -homosexuell -豬操 -江猪 -新義安 -万淫堂 -令人喷血的春宫108姿势(组图)19岁禁看 -BT亚洲无码影片 -肉棒小浪穴┅ -爱幼阁 -布莱尔 -JHSZ -lastchaos -臺灣狗 -打手槍 -不良少女日记 -淫荡的嫂子 -爹娘 -宁王府淫图导航 -成人图库,操女人穴,色情贴图,性交贴图,操MM穴,超级淫图 -嘉联 -肉棒顶入小穴口 -你色吗 -干妳娘 -稻生美纪 - miki -做愛電影 -女儿的阴道好紧啊 -操妳妈 -歪逼 -淫水四濺 -激情淫色贴图论坛 -我受不了啦!┅┅好勇猛的鸡巴 -冉英 -免费午夜电影 -毛台湾帝国 -黄家骁 -抽插39岁处女meimei淫叫不断 -狗狼养的 -六。四 -builtfree。org -張 林 -美国小姐淫荡舔乳照 -大力丸 -炮友之家 -色情网站 色情导航 -干一干 -好嫩的屄啊 -免费淫色电影论坛 -網管 -毛射精 -歡歡娛樂時空 -毛西藏独立 -激情 乱伦 性 -asshole -人大代表 -h站靠 -浪叫 -mei li shi jie -法抡功 -逼痒 -情兽 -mo huan sen lin -夏夏娱乐免费黄站 -免费淫色情电影 免费淫奸女A片段试看 -法轮大法 -林心如特级片 -你弄得阿姨爽死了 -毛膏药旗 -麗春苑 -狂乳激揺 -钱 达 -緊穴 -超美少女系列 蛯原舞 -本站10019多部激情电影全部免费试看 -激情电影 -宾周 -激情成人桃色电影 -爸干得你┅┅舒服 -台湾情色網 -在乳房和阴道摸弄 -美乳美穴 -大史记 -女卫生间盗摄图 -淫水四溅 -MAD MAD -毛去你妈的 -毛李宏旨 -毛妳马的 -免费黄色电影/色情电影/激情电影/黄色电影/我该死/A片 -乌兰夫 -肉棒精液淫液阴精 -免费淫色影院 -肉棒好粗啊 -清華同方 -花和尚成人论坛 成娱情色导航 -摸你雞巴 -劉少奇 -flyfff -日本激情片 -怎么能知道女性手淫过 -大龟头顶住了她的花心深处 -巨骚 -干X -小泉恶搞 -大肉棒插入阴户内 -給處女開苞 -新聞出版署 -插护士穴真爽 -金瓶梅4 -弓虽 -黑逼 -金瓶梅5 -こどもの时间VOL。1-7 -內衣 -金瓶梅1 -妹妹的阴道好紧啊 -金瓶梅2 -六。四 -金瓶梅3 -18岁以下禁 -亚洲穴贴图激情自拍穴 -曲線消魂 -毛经社理事会 -法(轮)功 -淫女教师小说 -枪淫少妇 -巨騷 -本站10021多部激情电影全部免费试看三天 -牛头马面 -日本av女优 -bastard -逼癢 -伦乱小说大全 -亚洲美女 -三极试看片 -少妇自淫 -欠骑 -鄭萬通 -淫水橫溢 -肉棒插进子宫了 -毛阴户 -Baichi -又紧又嫩的屄儿 -大型黄站 -bankai -huang yi qun xia zhuan -毛塞白 -激情黄色在线 -傻鳥 -fuck新疆独立 -基地组织 -抽插47岁处女妹妹淫叫不断 -meinv穴自拍 -二屄 -妈卖妈屁 -操车仑 -吊 -回教 -大鸡吧来回抽插着小穴 -毛克林顿 -牲口 -事屎 -fuck透视眼镜 -mo yu -毛可待因 -爱图公园 -六四民運 -黃色漫畫 -朱骏 -毛傻屄 -干机掰 -媽的 -毛日他娘 -U-R -卫星遭黑客攻击 -抢火炬 -吳 邦 國 -少婦偷情 -MUGEN EX VOL 9 人体喷泉!强烈な潮吹きホール!(MX-09) -贱人 -jiangdongriji -色网阴道特写强奸32岁处女全过程 -在线黄色电影 -毛发展研究中心 -成人激情视频聊天室秘密入口 -东条 -东方传说 -色聊人午夜激情聊天 -巨炮肉穴 -老师的淫液 -wetback -手记注册日韩5029部激情电影 -龟头抽插小穴 -TMD -周總理 -乳峰 -fuck我干 -毛马克思 -成人导航网 -聯 總 -姫辱 -乳房急促而有节奏的起伏着 -操他 -毛耶和华 -肥嫩嫩的大陰唇粉紅色的小陰唇 -操插Gm -运营 -zu qiu jing li -裹本 -一边一国独裁 -朝鲜 -插你爸 -色网阴道特写强奸28岁处女全过程 -娇妻超市被奸 -张 伯 笠 -射了 -肉棒 乱伦 肉洞 -东京物语Vol。 3 优质美少女 -龟头在阴道中抽插 -大鸡吧狠狠插进了她那又肥又嫩的小骚屄儿 -二奶大赛 -操插GM -98bb成人小电影 -雞院 -摸陰蒂 -wtf -激情淫少女穴 -打飞机 -操得直叫爽 -妈个老比 -f r e e n e t -阴阜高耸 -强奸20岁处女全过程/*妹阴毛小穴 -天鹅之旅 -淫影院论坛 -铁道部 -丰满肥大有阴唇湿润了 -红宝石 -六四民运 -唐人电视台 -打手枪 -di qiu wen ming -现场做爱偷拍电影 -欧美乱淫贴图 -宮路ナオミ - 美腳★角度 (超美) -wyd -毛骡干 -淫荡少妇白洁 -麻醉枪 -法抡 -Sex -每日公告 -T浓厚中出FUCK Red Hot Fetish Collection Vol。44 : 夏川Saya -六四平反 -顶到阿姨的花心 -歡迎G9情色電影院 -娘b -法*掄 -射你 -发^^抡 -山本五十六 -如果你未满26周岁请自觉离开。 -tian yi zhi lian -淫荡女护士 淫荡少妇穴 -淫奸护士论坛 -乳尻 -色情工廠 -棒插到妈妈的穴里 -xin shi qi -遊戲送獎員 -fuck售号 -中國政府 -娘B -激情淫色小穴 -tiao zhan -抽插淫水 -毛肛 -劍網2 -劍網3 -無碼無套 -phuc -妈的靠 -烟膏 -乳尖 -成人午夜影院 -魔兽金库 -droiyan -雞雞 -强奸24岁处女全过程/淫妹阴毛小穴 -大波骚妇 -少妇扒开阴道图-淫賤少女阴唇特写图免费淫电影a片 -淫水橫流 -色电影 -fuck唐家璇 -西藏天葬 -极品激情影院 -狗娘养的 -食捻屎 -又硬又大的肉棒插入阴户 -程真 -天之炼狱 -龟头在她的阴户里抽插 -仑功 -魔兽金币 -kan66免费电影 -顶级学妹美穴淫图 -地震捐款 -巨乳俏女医 -捐款名單 -美女含双棍玩内射 -luanshi -賣國 -san guo -正見網 -转法轮 -发@@仑 -六四以后 -吳桂賢 -开粉红小阴唇 -日本大型黄色meinv做爱 -發~輪 -台灣豬 -亚洲激情淫贴图 -南联盟 -寻仙 -淫水淋湿的阴毛 -亂倫熟女網 -肉棒捅入阴道里 -淫荡小护士 -fuck社保基金会 -大陆性meinv淫穴 -童屹 -操布雷尔 -毛想上你 -风骚小护士 -朝鮮 -tian jiao -@sshole靠 -cha你 -带链 -厕所盗摄护士姐姐性感 -龟头狂插肉洞 -亚洲激情淫搔穴贴图 -fuck外挂 -毛情色 -李弘志 -法@抡 -骆 冰 淫 传 -泡365免费电影 -董建華 -处女流水淫图 -草你媽 -小浪穴 插死 人家了 -台湾 18 成人网站 -淫色网址导航 -剃毛 -毛老母 -朱駿 -Groove -羞恥母 -淫浪女 淫妻浪女 于东 浪女淫叫 淫妻……漫画 淫色贴图东方淫色 -遺忘傳說 -汽车爆炸案 -看棋器 -抽插50岁处女妹妹淫叫不断 -插比 -張梅穎 -萬人暴 -法掄 -激情淫色贴图网址 -红海湾 -本站10010多部激情电影全部免费试看 -wstaiji -cunt cunt -粉红色的小嫩逼淫 -妈要吃你的肉棒 -操你奶奶 -jin wu shi jie -董必武 -狡猾的风水相师 -粗挺的阴茎上沾满了处子的鲜血 -性器 -插gm -蓋世太保 -U/R -阿姨的阴道好大 -上海交警 -林榮一 -癡乳 -性感妖娆 -肥嫩的阴唇 -妹妹嫩穴被狂插 -哥哥使劲插我 爽死了 啊 啊 -外交论坛 -毛妹妹免费电影 -梁保华 -发@@伦 -毛小穴 -插gM -99bb -托管理事会 -Fuzz Vol11 Ririko Asahina 朝日奈りりこ 加藤つばさ -1989#事件 -骚妹妹 -母子淫奸乱轮现场看,瞄準她的肉穴插了進去…… -扬震 -韦国清 -成人激情电影通道 -湿淋淋的阴道被肉棒插出血 -河 殤 -夏夏娱乐 黄站电影 -淫民俱乐部做爱顶级 -激情淫咪咪贴图区 -毛检察院 -东京热5月新片 -癟三 -瘋狂抽送 -華夏Online -小泽玛丽亚7~淫乱的肉体 -淫少妇 -鸡巴靠 -免费视频激情聊天室 -台湾18黄网亚洲华人bbs性论坛 -毛窃听器 -美国淫女在线看电影欣赏mm乱淫自拍图片 -賓周 -河 殇 -胡景涛 -WEB战牌靠 -東京熱最受歡迎長腿meinv~藤澤安奈~腿長人又漂亮 -激凸走光 -法~~掄 -操女人穴 -干的你 -魔性的美女 鈴木麻奈美 -强制执行 女体崩壊~YUU Vol。1 -孙文 -草你娘 -令人喷血的春宫108姿势(组图)18岁禁看 -四我周 -毛摇头玩 -fuck四人帮 -午夜的诱惑网友自拍 -少女艳星诱惑色图 -国权 -法$抡 -BT无码区 激情电影 -干八个meinv的小穴 -免费淫爆影片 -电监会 -劳拉 -山西黑砖窑 -mimi淫色贴图 -大海战II -shaiya -毛肉壁 -深愛色色 -mo jian -meimei的阴道好嫩啊 -狂插meinv护士小说 -毛台联 -粮食局 -口爆吞精 -经社理事会 -20dy淫色贴图 -sanguohx -淫色贴图网 -小便 -性感妖嬈 -少儿不宜 -公媳乱 -毛独立台湾会 -蒋震文 -扒开嫩穴 -大龟头在我的阴道口来回磨擦 -發^輪 -淫奸姐姐小说 -台湾黄色成人电影 -草你妈 -日本姐弟乱伦小说 -阿姨的阴户好紧 -免费成人激情视频聊天 -公媳亂 -少女被插 -婷婷成人激情网站 -21dy淫色贴图 -奶大屄肥 -黃色圖片 -李鵬 -狗雜種 -免費A片 -淫荡贵妇 -獨立臺灣會 -奇淫的老板娘 -meimei穴 -fuck生孩子没屁眼 -温暖的冬夜老师拼命亲吻我 -免费电影 成人电影 激情电影 -肉棒抽插……的爽死了 -feng shen -圣战 -台湾政论区 -朱胜文 -dekaron -恶搞晚会 -吾尔开希 -钱运录 -秦真 -Tora Tora Gold Vol。24~伊泽夕 -插 10p -高自联 -du shi 2046 -毛经济社会理事会 -操陈至立 -爆乳人妻 -迷奸药 -狂插处女血流不止! -童顏巨乳 -饱满的乳房肥嫩的阴唇又肥又嫩的小骚屄儿 -操财政部 -智能H3 -毛国研室 -北大三角地论坛 -民联 -财政部 -热血江湖 -发~仑 -大鸡巴干进妹妹的小穴 -舆论钳制 -bi样 -品嘗不倫主婦 -插 11p -小姨子穴 -粉嫩小淫穴 -铁血三国志 -无尽的任务 -捅入她的阴道里 -白立朴 -妹妹 MM激情 -帶链 -婊子靠 -肉棒乱插 好舒服 -霍金 -meinv出租车内强行进入 -fuck死全家 -猛舔她的肥穴 -扉之陰 -操大法 -插 12p -尋仙 -又粗又大的肉棒 -江八点 -李至伦 -张磊 -petrealm -淫奸meimei电影论坛 -阿弥陀佛 -台湾建国 -莫伟强 -免费淫电影,免费淫色情电影 -馬万祺 -Gold Angel Vol。7 Super Erotic Girl : Ran Monbu 紋舞らん -插 14p -激情淫片 -哥哥淫奸妹妹穴 -插 13p -本站10012多部激情电影全部免费试看 -宋平 -你爺爺的 -发~伦 -成人色情网 -姐弟激情淫影片 -毛傻子 -大龟头顶住子宫深处 -干GM -王文京 -洪志 -内衣 -接班 -九评共产党 -中共/中共中央 -乳射 -插 15p -大花逼 -濕身誘惑 -手记注册日韩5020部激情电影 -教室炉轮奸精液过剰注入 若月秋穂 -真 善 忍 -美媚穴贴图 -杀你一家 -又大又嫩的穴 -淫乱电影 -【亚洲/无码】【生奸中出无套内射-相沢、夏樹、 美月遥】【AVI/1220MB】 -脱衣舞 -淫色电影免费在线观看 -日本激情淫 -艳舞淫业 -强奸17岁处女全过程 -法$掄 -淫奸电影少妇扒开阴道 -杜冷丁 -肉棒插入肉缝 -你它马的 -扒开嫩阴道 -法*抡 -Ninn Worx - Fem LAmour -liu xing xue yuan -邪教 -俏臀攝魄 -徐邦秦 -奴隸調教 -淫水漣漣 -無碼 -少妇房中自淫,和两勇男玩9P,操得直叫爽 操日本淫女穴 -操你 -transsexual -口含鸡巴 -KEFU -国安局 -淫电影//处女第一次阴道做爱全过程(全套图片) -淫妻乱交 -免费色情电影 -林心如淫电影 -色meimei成人论 -热血英豪 -mes couilles -U R -内裤 -幹GM -干鸡 -光通 -毛麻醉钢枪 -毛社。会。正。义。力。量 -bt 色情工厂 -华盛顿 -Jiaochun -扉之阴 -Yellows Vol。2 女体天国 2 天然素人娘18人 -毛共产主义 -龟孙子 -赵 紫 阳 -專制 -淫奸meinv图 淫奸刘亦菲 -毛特别公告 -urban靠 -av成人 -日韩成人激情电影 -h r i c h i n a -她奶奶的 -激情淫贴图 -朱嘉明 -快感 -食屎 -毛国防部 -露逼 -transsexuel -骚货 -活动管理员 -任弼时 -ctracer -大妈油 -情色小电影 -宁王府导航 -强奸林心如扒开阴道 -周铁农 -插你祖宗 -ai滋 -溫泉室的男女 -淫屄儿 -胡景濤 -射进女儿的屁眼里 -fuck透视软件 -舔她的花蕊 -我和小少妇乱伦理淫穴 -PP一点通 - 成人电影 -母子交歡 -天安門大屠殺 -日本卡通淫色动画片 -公车淫奸姐姐 -大陆淫乱美女图图片 -無界 -嗎b -鬼畜轮奸 -让我的肉棒缓缓的插进潮湿饥饿的娇嫩的肉洞里 -炮打中宣部 -于永波 -走资派 -內褲 -网游久久金币 -性奴 -成人文學 -明斯克号 -操吹箫 -精液喷涌而出 -毛日X妈 -六月four日 -骚姐姐 -毛外挂 -宝德 -成人文学 -轮盘机 -华义 -三個代表 -系統公告 -免费成人激情视频聊天室 -日本黄色小电影 -da tang hao xia -中央电视台 -插少女阴道 -抽插 捅 挺 阴唇 处女膜 -母子交欢 -中国天使成人网我该死免费视频 -江獨裁 -滾那嗎 -毛懒教 -丁關根 -国产偷拍 -肉棒弄得湿溜溜的 -猪聋畸 -全裸 -楊帆 -卐 -刘全喜 -满洲国 -毛普京 -疯狂抽送 -SEX -區 -淫电影//少妇扒开阴道图-淫賤少女阴唇特写图 -猪毛1 -卵 -89bb成人小电影 -中国meinv淫色贴图 -傻鸟 -抗震 -大紀元 -剛比 -Tokyo Hot n0188 田中爱 -毛国民党万岁 -和护士jiejie淫穴 -操你妈屄 -毛屁眼 -小穴插的紧紧 -淫穴淫水流 -張 志 清 -55sss偷拍区 -55sss偷拍區 -脱内裤 -發~論 -媽祖 -毛卖逼 -插 操 干 骚穴 嫩穴 小穴 密穴 淫水流 -兔meimei色色贴图区 -功 -毛夜情 -宁王府成人论坛导航 -岩崎 Sky Angel Vol。27 -天地玄門 -淫荡口交 -www。gpchina。net -聚友網路 -摩門教 -他馬的 -个批 -賣卡 -专政 -人妻熟女 -小骚穴┅┅好舒服 -64xp。com 电影免费 -操陈毅 -安息 -蜜穴肉棒肉縫 -少妇大穴VS驴吊 -把舌头伸入姐姐的 -發~~倫 -日本免费黄站 -一黨獨裁 -於永波 -64事件 -tranny -郭平 -肛門拳交 -毛强硬发言 -務 -法车仑工力 -輪流執政 -法~~抡 -灨你娘 -動 -我讓朋友強姦我的小姨子 -大城舞衣子(有碼無碼)大合輯~~~超優!!(可分開下載哦!!!) -操妳娘 -通知 -合成淫色贴图 -Qqyinsu -fuck晚年周恩来 -小穴┅┅好棒┅┅好爽 -孔雀王 -操医生小穴 -淫妹妹电影 -强奸42岁处女全过程/淫妹阴毛小穴 -妈逼靠 -lineage2 -大肉棒刺入肉穴 -吴桂贤 -成人激情视频聊天 -GMworker -segame -阴道好肥啊 -Taiwan国 -neosteam -日本淫色电影 -joyxy -色情靠 -無毛美少女 -毛王乐泉 -小魚兒與花無缺 -中宣部是中国社会的艾滋病 -乳头 -epochtimes -河殇 -插GM -女秘书做爱吞精图 -少妇房中自淫,和两勇男玩14P,操得直叫爽 操日本淫女穴 -黑五类 -毛法(轮)功 -厲無畏 -摩力遊 -店長推薦最新強片Sky Angel Vol。43最新強片 -操妹妹 -杨震 -發**論 -法轮公 -爽图网 -出售账号靠 -法轮共 -穴太紧了 插进 -你他妈的 -毛神通加持法 -毛我干 -免费操小姨子 操小姨 -性欲 -voa -含 肉棒 插 小穴 -潘金莲全传 -发改委 -今晚我把表姐操上了 -欧美激情 -天天任我淫 -网址大全 -mo shou shi jie -阿沛•阿旺晋美 -够酷GOQO -统独论坛 -毛阝月 -激情淫色故事 -fuck新闻出版 -打飛機 -操妳媽 -佛展千手法 -龙 虎 门靠 -欧美暴淫 rsync 月宫成人贴图区 -国产AV -chinesenewsnet -xin xi you ji -jin yong qun xia zhuan -插Gm -啊……我的小屄……给你……肏得好……舒服……啊 -金新月 -靓穴meinv -feltch -幹全家 -中共中央 -操那嗎逼 -子女任职名单 -卖卡 -谷牧 -幹逼 -東方傳說online -無需刷卡 -俞正声 -淫穴小说 -台湾成人25贴图 -梅毒 -騷浪美女 -致幻劑 -法沦 -毛乡巴佬 -自由亚州 -黄色做爱小说 -成人激情影视区在线视频脱衣服 -game master -昝爱宗 -歐美大乳 -淫秽小电影 -致幻剂 -法輪功 -肥嫩的小骚屄儿阴部 -meinv淫色贴图区 -弟弟粗大的肉棒 -人民代表大会 -天地玄门 -圣女峰 -成人激情电影网 -worms -臭b -大……鸡巴……操得……很……很……舒服 -淫奸jiejie -江择民 -xiao77 -baichi -大亂交 -农村公公与媳妇乱伦 -曾 庆 红 -超激情电影快速注册 在线观看爽!爽!爽!! -干部 -毛水利部 -恥辱醫護免费 -风骚女秘书 -我也要泄了 -操产权局 -毛国管局 -法~掄 -浪婦 -肏妹妹屄 -毛投毒杀人 -搖頭丸 -庆红 -看着有点舍不得操 -89學潮 -亚洲激情 -法@@仑 -伦理淫穴小说 -阿呀娃娃 -tian xia wu shuang -姘頭 -Itsuka_part2 -劲暴 -毛三唑仑 -性交自拍 -无码做爱淫图 -撒尿 -好紧的阴道 -妹妹的小阴户 -火辣辣免费爽片 -火辣写真 -人也 -大清帝国 -用手指分开两片肥嫩的阴唇 -肉棒插入妹妹小穴 -傲神傳 -毛徐光春 -她妈靠 -自由亞州 -姨妈的肥阴唇 -1989 天安門 -法*淪 -强 奸 -免费淫奸女A片段试看 少妇扒开阴道图-淫賤少女阴唇特写图 -1989 天安门 -挺着硬梆梆的肉棒 -干逼 -網路公祭 -欧女乱欲 -kart -骚姨妈 -5jq -电影小片段试看免费淫影片 -红月 -賣幣 -一夜情聊天室 -天安门屠杀 -龚学平 -六四之後 -毛哈批 -嫂嫂我要 -鞭王 -最淫熟女网 -肉棒插入淫荡少妇穴 -陰道圖片 -後庭 -把精液射进我的小穴里 -亚洲激情淫色网址 -huang yi qun xia zhuan -韩正 -邓力群 -性交贴图 -乱伦淫书成人网 -三级片看美国女人的性交 -莫索里尼 -sheng zhe wu di -淫逼嫩穴清晰图 -主席 -恥辱醫護 -奇侠XIAH -屙 -人代 -四川 -手记注册日韩5030部激情电影 -操女人嫩穴 -總書記 -毛游戏发奖员 -總理 -屍 -妈妈美穴 -屌 -福尔摩萨 -屎 -屄 -男女激情淫影片播放 -淫女刮毛 -尿 -乱伦禁书 -尻 -毒販 -少妇房中自淫,和两勇男玩0P,操得直叫爽 操日本淫女穴 -激情日本电影_成人情色电影_成人小电影 -meimei淫水 流 -卢跃刚 -余英时 -tianji -激情做爱色情淫妇做爱 -經血 -密宗 -美女偷拍成人小说激情网 -亚洲成人激情 -神话R。Y。L -毛卫生部 -polla -共*党 -日九城 -卡通动漫美女淫乱 -毛胡主席 -台湾共产党 -UR靠 -先烈的电话 -反日活动 -毛贺国强 -台湾国 -抽插48岁处女妹妹淫叫不断 -射 -捏你雞巴 -fuck温加宝 -疆独 -李師父 -护士淫乱 -新唐人 -插得好爽啊 -发@抡 -任你淫 -鄧小平 -小骚货 -周鉄農 -两片暗紅的陰唇一張一合 -soundofhope -幼逼 -熟美婦淫交實錄 -美少妇的哀羞 -硕大龟头紧紧顶著她的阴道 -肉洞深处不断地蠕动 -盘古软件 -王秀丽 -淫乱色情小说 -fuck王昊 -24dy淫色贴图 -安拉 -卖号 -星光伴我淫 -和姐姐插穴 -共軍 -午夜激情免费电影免费看激情小电影 -zhuanfalun -打倒中国 -激情贴图 -淫荡妖艳女医生 -少妇做爱小说 -核潜艇 -原千寻~白领迷奸 Finger Charm -怎样延迟射精20岁以下禁 -毛网管 -qq视频脱衣秀亚洲少女韩国无码片 -淫奸姐姐 -亦凡 -肉棒插入肉穴 -法@沦 -恐怖分子 -干meimei小穴 -毒贩 -水浒Q传 -167网址宽频影院网 -日本激情免费小电影 -(无)导航网站连接 -李大钊 -SOD 厳选!残虐レイプ集 -帝国传奇 -薑春雲 -你他马的 -赵 晓 微 -毛多维周刊 -免费meimei黄色淫乱电影 -法淪 -草拟妈 -疆獨 -如果你未满18周岁请自觉离开。 -日韩淫乱美女图 -滾那嗎錯比 -GAME MASTER -人民之声论坛 -se中国 -厕所盗摄meinv -光明日报 -fuck统计局 -毛高俊 -他妈地 -蒙古独立 -鐵甲爭雄 -日本情色无码光碟 -搞比 -劳改 -大肉棒插进我的肉屄 -如果你未满25周岁请自觉离开。 -動漫色圖 -看牌器 -性感乳娘 -新人调教 Red Hot Jam Vol。9彻底调教凌辱人靓逼美 -情色成人大全 -淫荡的妈妈8淫荡护士9淫荡空姐 -海天英雄传 -好紧的屄 -9之遊 -鹿城百家性大型网站 -爽你 -全国两会 -成人视频 -武雷 -大乱交 -欲仙欲死 -干你媽逼 -淫奸护士穴论坛 -好朋友 -身份生成器 -法@@倫 -欧洲男女激情淫乱穴 mm贴图网 -明慧網 -52xp。com 电影免费 -mei li shi jie -阴道夹裹住阴茎 -卖淫女全过程 -未满21岁的请自行离开 ! -民航 -操小姨子 -淫奸小姨淫水流 -毛联大 -强奸20岁处女全过程/淫妹阴毛小穴 -日本有码 -毛威而柔 -fuck王太华 -那吗逼 -免费看三级电影淫电影艳情电影 -拉案) - -搞死 -毛六合彩 -64動亂 -arcane -欧美靓穴小小论坛帖图母子姐弟淫……男男激情欧美淫贴图 -下载淫电影 -淫电影艳情电影 -起义 -骚B熟女 -贾育台 -张伟华 -富人与农民工 -毛台湾共产党 -金日成 -法$沦 -性愛擂臺 -新聞出版總署 -免费黄色淫秽 -Lady Sonia-熟女絲襪 3 -司馬義?鐵力瓦爾地 -东京热 n0151 工藤裕子 美丽子宫大精液轮奸教室 -日本有碼 -百家性大型黄站meimei -又解开乳罩 ┅鸡巴 -黑手黨 -赌博 -造爱 -龟毛 -豔照 -赛他娘 -免费情色电影情色五月天 -毛售号 -阳具在他的穴里大幅抽插 -客报 -宁王府 -亚洲激情淫影院 -薛伟 -肏肉~X屄爽歪歪 -强奸大奶嫩逼meinv -毛王宝森 -屌七 -淫奸妹妹电影 -苯丙胺 -法碖功 -中华时事 -遊戲管理員 -红楼 绮梦 -素人著エロ俱樂部 こももちゃん -办公室性欲 -大肉棒在妈妈的阴道 -朱熔基 -毛审计署 -fuckyou -怎样免费看淫电影 -毛世界日报 -插姐妹小穴 -meteor academy -胡锦濤 -色情 娱乐 导航 -风骚女友浴室放荡 -ㄙㄞ你老母 -Mysupersales -小穴里抽插 -網络公祭 -糖糖小穴 -八路 -售ID -小泽玛丽亚~闷绝痉挛无限制潮吹 -毛阴核 -AYAWAWA -干jiejie小穴 -fuck倭国 -强奸43岁处女全过程/淫妹阴毛小穴 -劫机 -黎阳评 -集體性愛 -大j8 -少妇激情电影 -解放軍鎮壓 -国产av -龚學平 -fuck无界浏览器 -幹 -美国成人激情淫洞网站 -开苞 -干 -骚b熟女 -浪妇 -嫩穴 小穴 花心 -wu lin wai zhuan -三去車仑 -幹死CS -浪女 -fuck十年动乱 -性交 -法*沦 -傳奇3G -旅馆自拍 -粉饰太平 -少妇房中自淫,和两勇男玩18P,操得直叫爽 操日本淫女穴 -独裁政治 -淫妇周艳茹和儿子的性战 -毛特码 -奥马尔 -高校骚乱 -毛驶你老师 -法@@伦 -小嫩穴贴图 -法~~淪 -欢乐数码 -统战 -马良骏 -苯環已哌啶 -工商局 -法~抡 -絲襪寫真 -免费淫奸女直接试看 -手机注册色情电影网站 -美國之音 -江八条 -淫荡女优放荡插逼 -妹妹的大阴户 -大 纪 元 -超性感裸体艳舞 孔裏唾梦 DANCE 2 アナリズ现场收音 -九城 -成人片 -幾芭 -罗 干 -绵恒 -laghaim -10 Little Asians Vol。 14 -@sshole -把你的小穴夹紧……用力…… -总局 -天安門 -mo fa qi bing -不得入内 -不用注册免费淫 电影 -小姨子的阴道好紧啊 -d7se淫色穴图片和meinv发春激情3级片试看 -幹死GM -强奸33岁处女全过程/淫妹阴毛小穴 -GameMaste -淫奸阿姨电影 -插入 嫩穴 -正见网 -法$淪 -法@@侖 -bedclip。com -jing tian dong di -插死你 -公车淫奸妹妹 -teensexy -一夜情异物插穴性爱网 -暗黑之門:倫敦 -成人激情色情电影 -亲情淫乱 -骚逼 -粗肉棒 大鸡巴 -淫奸女同事穴 -9城 -劳教 -我就去色 -林心如被疯狂轮奸 -在线淫电影网站 -天安门 -尸体 -舌头在小穴周围舔弄 -郭岩华 -肉棒插进了湿湿的阴道 -淫奸姐姐 妹妹 MM 姨妈 舅妈直到流水 -性佣 -免费淫水流 -彩虹骑士 -天安門屠城 -ling you ji -法^掄 -歡迎光臨亞洲瘋情 -游戏道 -無碼小處女 -龟头顶开阴户 -周子玉 -凤舞天骄 -刀劍?英雄 -破天一劍 -淫荡少妇 -老騷比 -台湾19岁成人 -棉条 -陳希同 -肛门喷水 -dafa -强奸46岁处女全过程/淫妹阴毛小穴 -NPC靠 -畜生 -大陆温州鹿城黄站 -王子淫传 -親民黨 -re xue jiang hu -奸 -E块冒险 -升天 -余秋里 -爆吧 -biaozi -未成年人禁入 -毛短信群发器 -蔣彥永 -射奶 -fuck台联 -毛欲火焚身 -破天一剑 -成人影院 -欲仙欲浪 -徐向前 -发论公 -干妈妈的小穴穴 -功法 -counselor -廁所盜攝 -fuck外交部 -三去車侖 -我和网吧老板娘 -胡锦淘 -365淫色贴图 -QQtang -检查 -免费淫 色电影 -妈 -meimei嫩穴 -毛你大爷 -TMD靠 -密室淫行 -靠背 -日本激情淫骚穴 -干 淫洞 -嗑药 -fuck兴奋剂 -官方 -强奸17岁处女全过程/淫妹阴毛小穴 -小穴好爽 -泽民 -妓 -蜜穴被阴茎插入 -劉伯承 -游戏管理员1 -鸡巴全根没入 阴道 -姦 -淫色宝贝导航 -禽獸 -明慧网 -jiejie -的 -嫩穴 -床上激情自拍图 -6。4 -完美世界 -透視軟體 -瞄準她的肉穴插了進去…… -merde -江罗 -WG武功 -A片大放送 -用手指挖她的小穴,弄得她娇喘连连 -哦……你插的好深啊……又顶到我的子宫……啊 -毛燕玲论坛 -肏meimei淫屄 -香港成人激情论坛 -吴宏达 -毛肛交 -死刑过程 -李师父 -妹妹的阴唇好嫩啊 -卖国 -遊龍線上 -姘 -免费品嘗不倫主婦 -抽插28岁处女meimei淫叫不断 -皇军 -操吹喇叭 -捅B -毛鸟gM -婷婷激情淫液 -六四以前 -大肉棒插进了她的体内 -用舌头对着阴道阴蒂等地方用力地舔着 -毛发奖使者 -毛我日你 -萬稅 -测拿 -本站10005多部激情电影全部免费试看 -荡妖艳女医生 -chinamz -fuck希望之声 -淫电影//令人喷血的春宫108姿势(组图)18岁禁看 -幼女口交 -嫩穴 -屍体 -狂插嫩穴 浪穴 骚穴 -宗教 -meimei小穴好紧 -madelove -阴道深处 -天安門事件1989 -郁慕明 -建国党 -外$$挂 -fuck小乳头 -fuck天安门屠杀 -慈善会 -国外A片电影-美国色情电影一点点激情下载 -性愛 -偷窺圖片 -毛驶你爸 -免费成人聊天室 -jiejie的嫩阴户 -胡启立 -apexon -激情淫色漫画论坛 -亚洲成人激情网站 -falun -qi shi -素人初撮り生中出し 观月雏乃 -去氧麻黃碱或安非他命 -强奸18岁处女全过程/*妹阴毛小穴 -免费淫乱卡通动画片 -淫荡家教 -性傭 -张萬年 -365成人贴图 -毛黄菊 -44lian色站大全 -亞甲二氧基甲基安非他明 -情色图片 -少妇白洁 -床上功夫 -日本淫荡少妇 -毛公安部 -江core -亚洲meinv -幼女情色论坛 -积克馆 -鸡巴插肉缝 淫荡 小穴 -舔着两片湿润的阴唇 -反人民 -龙洲影院日本娱乐性免费 -萨拉托加 -焚烧 -胡锦滔 -金瓶梅情色網 -坐台 -父亲 -淫蕩貴婦 -发论功 -tui tui xia -插入妈妈的穴好爽 -肉棒插入乱伦射精 -婷婷成人激情淫洞 -万润南 -老师嫩穴 极品嫩穴 淫穴嫩穴 -戀愛盒子OL -性息 -逼樣 -大话西游 -彭真 -干丰满少妇 -買幣 -干妳老母 -掰穴 -鸡巴猛插 -江八條 -插进小穴射了 -新人调教 Red Hot Jam Vol。9 Myuu -毛奸你 -恐怖主义 -领导 -勁樂 -性爱插穴 -你呀的鸡巴长歪了吧 -採花堂 -毛鸟gm -干一家 -性情 -宋庆龄 -十三点 -反政府 -姐姐和我乱伦理电影 -异见人士 -淫荡┅插 小穴 -法~~沦 -少妇房中自淫 -韩 联 潮 -youxia -短信群发器 -發倫 -毛孙中山 -爱图公园论坛 -butthead -毛希望之声 -客服 -六?四 -wowcaifu -Ezgaming -絲襪 -富豪们的疯狂做/爱方式 -肏烂你的屄 -成人小电影 -天安门录影带 -少妇 -皓宇互動 -狂舔少妇两腿之间 -jie tou lan qiu -操婊 -365情色小说 -淫乱护士激情电影 -肏meimei屄 -PENIS -大奶骚女 -f l g -招雞 -亂交 -孕 -免费黄色淫乱电影 -日本风骚女电影 -皓宇互动 -法^^侖 -你爷爷的 -在线观看淫电影 -弟弟的肉棒又粗又大 -Red Hot Fetish Collection Vol。28 -肉棒又粗又大少女又痛又爽 -少修正 -被操 -女老板一丝不挂躺在我身边 -阻无通畅 -骚妇露逼 -meng huan xi you -和親jiejie作愛 -見到這個美女就會有性欲 -把肉棒抽出来 -咬着她的奶头干了她 -在线淫电影 -几芭 -H动漫 -laghaim -無需入會 -幻灵游侠 -毛商务部 -貞操 -日本淫色漫画 淫色少妇小说 淫色少妇 -tmd -品色激情电影 -fuck特码 -……好舒服 ……好爽 -大鸡巴 -肉棒抽出她嘴中 -林心如色情贴图 性交贴图 -发$抡 -曰gM -任建新 -毛贱 -GAMEMASTER -鑽插 -肉棒插进来肉穴 -妈妈挺动雪白的肥臀 -鸡巴顶在女儿的嫩穴 -李紅智 -大型色站 -新鄭和 -U-R靠 -中央 -和妹妹玩插穴 -翹臀嫩逼 -在线激情淫电影 -乳此丰满 -针扎 -法^^仑 -勁暴 -蒙尘药 -張筱雨 -毛胡紧掏 -舔她的小洞洞 -免费淫奸女A片段试看 欢迎点击进入观看/林/心如/20岁处女偷拍 -鞭神 -免费淫色meimei电影 -免费成人娱乐電影 -小骚逼 -Tora Tora Gold Vol。23 : ほしのゆき Yuki Hoshino -鸡鸡 -法^^伦 -性交极品大片 美腿少妇 -共榮圈 -学生淫图 -毛鬼村 -毛塞你老师 -毛淫秽 -89学潮 -毛色情服务 -弟弟淫奸姐姐论坛 -阎明复 -Tmd -淫色护士小说 淫色故事 淫色文章 -熟睡中的妹妹 -强*十八岁meinv护士看完保证你打飞机免费电影网站 -外$$掛 -性教育片-性教育电影 -劉淇 -snatch -全球华人春节联欢晚会 -毛湿透的内裤 -中奖 -日本av -精子射到姐姐的穴里 -账号 -公车上干女司机 -学生爱国者运动证明 -他奶奶的 -貓撲 -娘 -北川 -shine -jian xia qing yuan -偷窥拍摄 -颜射 -夏夏小说黄站 -注册免费淫电影 -曹长青 -Red Hot Jam Vol。8 让你用子宫感觉 藤崎夕凪 -干的好爽……要爽死我了 -盜竊犯 -敢坐飞机吗 -damn -美国凯德 -damm -操她妈 -百家性大型bt黄站 -娼 -李建國 -宁王府成人导航 -survivalproject -李建国 -海底水中插屄~Aqua Sex -李淑娴 -毛教育部 -劲樂 -都市情爱乱伦淫妻古典武侠制服明星性爱宝典24式教材 -毛阴水 -师春生 -动漫激情淫色贴图 -发伦功 -好大的肉棒 -发*抡 -少女bb图 -64动乱 -不斷收緊陰道來吞噬我的龟头 -婊 -神通加持法 -MM被干小穴 -甲基苯丙胺 -教師禁斷接吻 -胡锦涛 -强奸meinv狂插处女阴道 -免费色情电影 强奸小说 -操淫荡 空姐 -浴尿 -处女性开苞 免费黄色淫乱电影bt下载试看 -操她 -被插 -神雕外传之郭襄 -公公狂操儿媳妇小穴 -102bb成人小电影 -婬 -幹機掰 -kai tian -溫傢寳 -少妇操b图 操农村少妇 少妇操尿图 -征服 -n0255 三国冬子 - 不用厌牝中出し廃弃処分 _k7 -苯甲酰甲荃芽子堿 -毛阴毛 -市長 -抽插44岁处女meimei淫叫不断 -周恩來 -市长 -东南西北论谈 -媽 -發侖 -大 紀 元 新 聞 網 -再用力插…。啊 -狂插小浪穴 -┅插┅小穴┅插我 -新石器 -13点靠 -公交车上淫乱小穴狂插 -女死囚 -干小蜜洞 -操妳 -輪奸大meinv -毛枪支弹药 -钱国梁 -一个事实 -操妻 -毛李宏志 -www。gpchina。com -亂倫 -日本淫虫在线看电影 -問道 -淫亂 -毛王刚 -heterosexuell -毛江猪媳 -嫖 -法^抡 -h动漫 -五不 -江澤民 -淫乱 -赵洪祝 -法^^倫 -倚天屠龙别记 -98bb -西藏独立 -靠腰 -蒋彦勇 -逼毛 -華義 -淫书 -上床 -广闻 -血灑 -你色嗎 -毛吴邦国 -握着他的鸡巴上下套弄 -六四周年祭 -淫液流入 -administrator -肉棒狂插嫩穴 -san guo yan yi -巨乳meinvRINA无码第2弹 -董建华 -crazyspeed -去妳的 -AV女优-杏子 -封淫 Sky Angel Vol。50 宫泽Keito 超美系模特儿初无修正引退纪念作 -淫女 喷精 -骚浪美女 -毛卖。国 -迅雷下载免费黄色淫乱电影 免费淫奸女A片段 -毛江青 -成人情色贴图 -51yxb -大粗鸡巴插进小穴 -毛回回 -日韩免费午夜电影 -道教 -鸡巴在她的阴道里抽插 -毛国防科工委 -中国社会进步党 -姐弟淫穴小说 -爆乳 -世紀天成 -淫丝荡袜 -丫的 -毛骚逼 -大鸡吧插进阴道 -lateinos -阿兵哥艳遇录 -逼样 -出租汽车罢工 -成人激情 -哥哥淫奸meimei论坛 -digimagics -本站10003多部激情电影全部免费试看 -烂游戏靠 -淫*女电影片段试看 -彭德懷 -曰 -毛乳交 -阿兵哥言语录 -王震 -日本淫蕩孕婦 -天皇 -格老子 -塞你老母 -Jap Jap -日死你 -大鸡巴在她的蜜穴里抽插 -日屄 -免费台湾18电影 -日本淫乱漫画图片 欧美母子淫乱图片 -中华人民实话实说 -huanet -车臣 -幸存 -淪功 -阿里布达年代记 -小穴 肉棒 插穴用力插 -紅 燈 區 -全免费淫色电影 -抽插22岁处女meimei淫叫不断 -功夫小子 -香港激情淫色影院 -女教師赤版免费下载 -成人 性爱 -迷奸系列 -法輪大法 -在乳房和阴道mo弄 -婊zi -发@论 -带套肛交 -毛售ID -强奸大奶嫩逼美女 -现金 -操布莱尔 -18dy淫色贴图 -淫花宫色女中心 -欢迎点击进入观看/林/心如/20岁处女偷拍/免费A。B片 -无毛美少女 -精水 -国产熟女做爱深喉肛交无码 -濫逼 -屌鸠 -张立昌 -干它 -嫩B弓雖女幹 -激情淫色文章论坛 -幼女狗交 -私#服 -花样性交 -劲乐 -無網界流覽 -郭伯雄 -男人若妻夢交下载 -厕所盗摄meinv性感 -做雞 -教你如何延迟射精 -FUCK YOU -艷情小說 -小电影 -亲日 -太監 -太监 -黑鲍娇 -梅德韦杰夫 -欧美尤物炮图图库 -臭西 -发$轮 -想不到的黑幕 -色狼論壇 -20岁处女偷拍/免费A。B片 -乳沟 -私%服 -法蜦功 -中华大地 -生成身份证 - Kurumi -欧美清晰打炮能看的淫乱 -毛神经病 -没有人权 -孙中山 -妈的穴让你插 -幼妓 -色猪猪成人导航 -(現映社)女の最強は30代エロ真っ只中 -應招 -冰毒 -hai tian ying xiong zhuan -那媽 -強姦你 -毛恐怖份子 -达癞 -神風痴女生中出!【MKV/767MB】 -隐窝窝 -免费偷窥网 -妈比 -宋任穷 -街头扒衣 -非常不错的人妻轮奸 -SM女王 -姦淫未成年的小女护士 -情色 -台湾岛国 -精液射进小穴里到了高潮 -jiejie的肥阴户 -鸡巴插进穴 -Q币 -欣赏特级毛片pp 点点毛片 meinv毛片 大陆毛片 -万税 -三个代婊 -窝窝客 -毛三个呆婊 -那可汀 -禽兽 -rivals靠 -干老师的穴 -奸淫 -台湾是主权国家 -操操比 -操那吗逼 -賣党求榮 -嫩嫩 小肉缝 小肉穴 -少女被操喷精图 -抽插20岁处女妹妹淫叫不断 -人學生妹妹 埼玉援交 vol。2 なな&まい -色魔堂电影论坛 -丁香欧美成人贴图区 -僵賊民 -教派 -本 -骚女淫频乐园 -免费淫电影下载 -姦情 -幹她 -运营者 -强奸meinv -多維社 -毛高校暴乱 -日本女优激情电影 -四川独立 -颜射自拍 -嫩女~嫩屄~插的红肿喷浆 -誘惑視頻 -私*服 -fuck天皇陛下 -熟婦 -讲法 -郭 罗 基 -阴茎在我阴道里急速抽送 -多位东热女优参演 -幹七八 -免费淫电影 -鸡吧勃起插入阴道 -他母亲 - 七海りあ -插的小穴都流水了 -动乱 -回民吃猪肉 -套牌 -激情人体18禁 -liu xing xue yuan -狂插meimei的小穴 -fuck吴官正 -發~綸 -幹妳 -piao liu huan jing -kk粉 -毛上妳 -幼女性交 -謝長廷 -挺动阿姨雪白肥臂 -册那娘比 -强奸39岁处女全过程/淫妹阴毛小穴 -幼女 -日X妈 -大奶騷女 -向忠发 -中公網 -愛幼閣 -曾庆紅 -欧美淫色贴图 -MUGEN EX Vol。 8 美脚痴女 红音まい -我和meimei肏穴 -性福联盟 淫宝贝导航 -私/服 -日X 妈 -法**論 -扒光 -操布什 -那妈 -Alod -私-服 -苏兆征 -身障 -system -六月联盟 -色情电影 免费电影 成人影院 -淫水翻騰 -强奸美女 -xian jing chuan shuo -干妳 -航海世纪 -六四點擊 -a 片成人免费激情小电影 -宁王府娱乐 -真三国无双OL -陈慕华 -真孔雀王 -消息 -yeeplay -操 -东突 -毛鸟GM -淫穴兽交 -胡锦涛靠 -蔡和森 -痴乳 -干娘 -风骚护士 -东方互通 -少妇 淫穴 -4。25 -阴茎在子宫喷射黏液 -阴部特写 -毛鸟Gm -高丽樸 -我也要泄了┅┅喔 -大 紀 元 -人权 -免费淫电影吴宗宪搞笑语录(27禁看) -通用娼婦 -peachall -神婆 -成人聊天室 -onlineworms -成人漫畫 -国军 -一夜情的免费电影 -15768 -欧美激情淫电影 -日她 -红嫩的小肉穴 -黄金圣水 -日本激情淫穴 -Tokyo Hot n0248 菊池奈津美 本物RQ体内汁注入22连发六月联 -勁乐 -江戲子 -做爱图片 -蒋彦勇上书 -我奸 -狂插荡护士 -Administrator -美神ルナ Runa Mikami -毛傻逼 -瘸腿幫 -李铁映 -操淫荡少妇穴 操淫荡meimei穴 操淫荡jiejie穴 -騷浪人妻 -登 辉 -毛军长发威 -水利部 -法轮大法靠 -婷婷淫色 -臀部 -丰唇艳姬 -嗎的 -BT色工厂 -川岛芳子 -淫叫 -布朗 -中年美婦 -本站10007多部激情电影全部免费试看 -阴道好紧啊 -外~~挂 -淫民堂 -道县公安 -孙逸仙 -merde -CUP爆乳家庭教师 -fuck商务部 -成人漫画 -小姨子淫色导航 -MM激情视频聊天 -台湾情色香港顶级淫片 -毛妹妹淫色 -游戏管理者 -少妇房中自淫,和两勇男玩7P,操得直叫爽 操日本淫女穴 -22park -抢粮记 -午夜激情宽频影院 -插屁眼 -反革命 -干她 -我和jiejie -小骚屄儿妹妹 -极品做爱套图 -强奸你 -东社 -钢管舞 -江湖使者 -僕街 -支持台湾 -婷婷激情小说 -毛生春袋 -爷爷顶到嫂子的花心 -天畅 -新疆分裂 -Kefu -搖头丸 -战场 -打倒 -法**论 -毛胡紧涛 -強姦媽媽…肉缝 -乳溝 -610办公室 -苯比 -发$$抡 -大奶头 -祖宗 -中公网 -韩杼滨 -登 輝 -毛私—服 -Rape -亚洲最大激情电影 -6-4tianwang -小嫩穴流血了 流水了 -eight仙靠 -刘文胜 -又长粗的肉棒 -i3hun -好嫩的阴户 -挺入阴道 -董贱华 -…你的鸡巴 用力干 -亚洲激情淫少妇贴图 -回回 -李作鹏 -瘸腿帮 -徐水良 -日 -自由门 -阴茎挺进狭窄的阴户 -日本激情视频聊天室 -好色meimei电影做爱论坛 -歡迎G8情色電影院 -妹妹小穴好紧 -嚮導 -屍體 -wow520 -张 万 年 -網星艾尼克斯 -淫穴电影网 -八九年那個春夏之交 -wangce -武林群侠传 -恼杀美巨乳美女~吉川萌 -肉棒沾满了唾液 -成人 激情 性爱 午夜 高潮 情色 -MUGEN EX Vol。4 吉川萌 -抑制剂 -舆论反制 -亞洲自然超可愛美巨乳 -幼图 -毛强奸犯 -77bbb -極景 -男男激情影院 -外~~掛 -淫欲世家 -…好棒啊……好舒服 -何勇 -毛广电局 -幼圖 -小屄儿里又暖又紧 -亚洲激情淫色文章 -waigua -日本小泉 -观世音 -奸污 -江流氓 -meimei的嫩屄 -asgard -jiejie被轮奸 -18dy免费观看 -免费放淫电影**日本高校女生性交 -销售 -好紧的屄啊 -祁建 -18岁少女处夜激情性爱电影下载中心 -美神ルナ -毛系统讯息 -Kamikaze Girls Vol。 30~中野美奈 -阴道夹的好紧 -发*论 -嫩穴把肉棒包得紧紧 -太王四神记 -航海世紀 -freedom -午夜激情美穴 -K姐 -激情淫乱图片穴欧美男人淫色贴图 -麦司卡林 -铁甲争雄 -舔脚 -馬場大亨 -eight仙 -电影 -┻┼ -地下刊物 -鬼轮奸 -操赤匪 -民运 -插入meimei穴中 -免费电影 -文殊 -联合国大会 -淫色释放贴图 -性交吞精 -肉棒插入湿淋淋的肉洞 -三民主義 -田纪云 -麦角酸二乙基酰胺 -淫奸处女论坛 -8?9靠 -日本成人激情电影 -fuck湿透的内裤 -欧美激情淫色下载 -发$论 -阿姨的阴道好紧啊 -星战情缘 -fuck升达毕业证 -周恩来 -pangya -赤龙剑心 -天之遊俠 -wow711 -免费bb电影 -naive -野性家庭女教师 -抽 -母女雙飛 -舔腳 -黄色电影 -囘良玉 -sh!t -wg9996 -針孔偷拍 -毛妈B -我淫我色导航 -免费淫色情电影 处女第一次阴道做爱全过程(全套图片) -私?服 -突破封锁 -伟哥 -張萬年 -操戳你 -同性恋 -少妇房中自淫,和两勇男玩3P,操得直叫爽 -asshole -TNND -沈阳公安 -娼妓 -娼妇 -我日你 -Kamikaze Girls Vol。29 : Arisa Suzufusa -党中央 -毛嫖客 -色界 -經典炮圖 -吴 邦 国 -令人喷血的春宫108姿势(组图)20岁禁看 -ha bao -激情电影免费下载裸体meinv乳房图 -幹妳老母 -射了还说要 -镇压 -安纳咖 -成人電影 -bastard -出售神符 -大鸡巴 干进 花心 -美女潮吹 -吴 方 城 -買財富 -黄色激情电影 -午夜激情电影 -掰开MM嫩穴 -鸡吧顶住阴道口 -戳 -日本性爱电影 -穿豹紋的meinv,很有野性美。看她咬著肉根就可看出來。 -黑毛屄 -meinv电影 -日本人淫乱操淫荡少妇操淫荡妹妹 -性欲喘息女教師 -尼克松 -李 瑞 環 -夫妻作爱电影 -ASS李弘旨 -肉棒插入肉洞 -幾巴 -光線 -妹妹张开双腿等你操  -色网阴道特写强奸27岁处女全过程 -插淫穴的快感 -操腫 -瓦良格 -你是鴨 -賣ID -免费激情电影 -操丰满小穴 -新手指导员 -小嘴吞吐的肉棒 -拦截器 -batard -东北独立 -petgirl -肏jiejie屄 -日X 媽 -喷精 -本站的免费成人电影 -草嫣 -少妇床上欲火难耐自mo图 -作弊器 -操淫女穴贴图 -强奸36岁处女全过程/淫妹阴毛小穴 -镇压学生 -毛鸡鸡 -插 -免费淫电影网站 -劲舞世界 -小姨的嫩阴道 -裸体meimei林心如穴 -不需付费的色情电影 -淫电影//令人喷血的春宫108姿势 -弟弟的肉棒好长啊 -剛癟三 -仙境傳說 -李月月鸟 -乱伦小荡妇 -联 总 -最新一本道~超级名模系列第13弹 : 真乃瞳 -成人免费影院 -掯 -轻舟快讯 -硅谷动力 -草的你媽 -湿淋淋的阴道 -SM处女淫水图 -久游 -臭鸡巴 -掛 -Paki Paki -绕过封锁 -午夜成人 -玩逼 -mysupersales -魔兽世界 -保证你打飞机 -香港激情片色情工厂直播香港彩福联盟激情 -玛雅网 -發^綸 -激情黄色电影 -毛国家主席 -Gamemanger -足球经理在线 -无套内射 -捻 -毛共狗 -干干 -百家性大型黄站视频 -蜜洞 -激情3级片试看 -鸡毛信文汇 -宁王府成人 -FLG 媽批 -张小平 -针孔摄像机 -避孕 -野性家庭女教師 -法* -免费顶级欲图禁片 -26dy淫色贴图 -同性戀 -肉棒狂插穴口 ┅好爽┅┅ -鸟你 -毛蒙独 -天安门母亲运动 -fuck石进 -干妈妈的爽 -马英九 -Client Server -人大常委 -以及家人 -步非烟 -干保姆小穴 -我幹 -da hang hai -双十节 -我干 -葫芦案 -本站10013多部激情电影全部免费试看 -免费淫色电影-无需注册 -淫骚穴电影 -搓揉裸露在外的那对奶子 -你是鸡 -你是鸭 -去氧麻黄碱或安非他命 -钻插 -淫奸meimei穴 -中年美妇 -李 瑞 环 -挂 -抽插32岁处女meimei淫叫不断 -淫乱潮吹 -168www -DJMAX -慾火 -午夜影院秘密通道_免费不需注册看电影 -毛妹妹黄站 -江豬媳 -伦功 -和护士姐姐淫穴 -meinv淫水狂流 -鲜嫩蜜穴 -烂b -两性激情电影 -香港激情淫色贴图 -felch -999日本妹 -母子淫奸乱轮现场看……扶正肉棒 -李先念 -xinguangming -废墟 -小灵通 -吸精痴女護士 -中文搜性網 -黄色免费淫电影网 -苏秀文 -魂online -夜色城 -老师小穴 -烂B -他妈ㄉ王八蛋 -18岁女生主动让男生开苞全过程◥免费黄色电影 -國民黨萬歲 -……太舒服了 淫肉穴 -日本激情淫色贴图 -网络公祭 -猛烈 挺送 肉棒 激烈 撞击 -毛华建敏 -激情视频聊天 -肉棒插入骚穴 -邓颖超 -肉棒好大啊 -賣QQ -淫电影免费在线观看 -发~纶 -奇迹世界 -联易互动 -十七大 -fuck想上你 -chi long jian xin -毛吗啡片 -操少妇嫩穴 -白漿四濺 -原味絲襪 -刘晓波 -他奶奶 -酣乐欣 -示威 -狂插儿媳妇的阴道 -李克強 -李克强 -刘士贤 -駛你老師 -妩媚挑逗 -天翼之鏈 -美女吞精 -东热美女一个比一个强 -运营组 -台湾成人电影 -特别公告 -仙界传 -jiejie的穴好大啊 -福摩薩 -大鸡巴 插入 肉缝 -强奸25岁处女全过程/淫妹阴毛小穴 -狂插妹妹的小穴 -阿雅娃娃 -夫妻3p -少妇扒开阴道图-淫賤少女阴唇特写图 -fuck台湾共和国 -抽插54岁处女妹妹淫叫不断 -江则民 -熟妇 -免费dse淫乱图片 -懒教 -成人免费电影 -毛威而钢 -淫电影//教你怎样延迟射精18岁以下禁免费淫电影a片 -亞無碼 -买财富 -操成人片 -法× -新手指導員 -淫声浪语 -剛度 -李 嵐 清 -熟女 -又大又嫩的阴户 -江戏子 -干他妈 -久游网 -淫色少妇狗小说大全 -性 -淫图淫片全部免费 -TOM在线 -剑侠情缘II -DROP -┅大力插┅大鸡巴 -MM的小嫩穴 -BASTARD -台湾狗 -Parade Vol。57:巨乳絞りボンデージ -用你的阴茎插我的阴道 -鴉片 -fuck乡巴佬 -咪咪色界 -service -社会院 -最淫大陆成人贴图电影区 处女一丝不挂自慰图片 -台湾身材一流美女楼梯性爱 -插你奶奶 -台湾独 -淫民激情文学图库下载淫民激情文学图库专题 -毛驶你母 -88科技 -流氓 -淫奸少妇穴 -顶级乱伦高潮淫水 -普京 -毛靠 -免费妹妹黄色淫乱 -风水 -女教师禽兽轮奸陷阱 -亚洲有码 -X到喷屎尿 -毛賊東 -赵 海 青 -李 淑 嫻 -六月聯盟 -動亂 -中獎 -天翼之链 -ucdao -a4y -a4u -家庭教师は女子校生 藤沢美歩 -大史纪 -操陈良宇 -海天英雄傳 -bxqt -鹿城娱乐成人俱乐部 -射 精 -朱容雞 -kuaik -刚比样子 -处女淫水图台湾女人裸 -falun -毛胡XX -刘山青 -兔妹妹贴图区 -動乱 -大肉棒 -愛液橫流 -最新成人激情电影网站 -女干三亏 -di guo chuan qi -撅起大白腚 -fuck社科院 -操肿 -濫貨 -學生妹 -强奸32岁处女全过程/淫妹阴毛小穴 -大阳具从后面插入她的小穴 -賀國強 -亲民党 -龟头喷射出浓浓的精液 -淫亂工作 -陆委会 -免费淫色妹妹电影网 -毛发改委 -淫圖 -KeFu -苏振华 -老b -(Waap)女教師 盗撮 - 志保 -荡女 -萨达姆 -操婊子 -万王之王 -earthciv -傻逼 -毛傻B -亚洲激情淫穴 -淫图 -夠酷GOQO -大鸡吧在小穴内壁摩擦 -老B -要射了 -肉棒已经整根插入穴中 -大众色情成人网 -網 特 -fuck双峰微颤 -操肏 -光宇華夏 -江山美人志 -ボディフェティッシュ 桜子 DVDISO -tian shi -毛干妳老母 -∪R靠 -赵小明 -慰 -中文搜性网 -毛青天白日 -民運 -黄 菊 -毛监管局 -抽插30岁处女meimei淫叫不断 -李月月鳥 -在线淫电影 淫奸电影 黄色电影 -慾 -龟头 花心 骚屄 -毛希特勒 -dragonheart -救災 -救灾 -午夜成人影院 -日韩淫女 -他干 -童颜巨乳 -淫女论坛 -精子射到jiejie的穴里 -鸡巴小穴 -手伸到两腿间 -法埨功 -私\服 -荡妹 -插白洁小穴 -鸡八 -露點 -免费成人十八影院 -消滅共產黨 -黄永胜 -肉缝 嫩嫩 -整个龟头插入小穴 -干尼 -淫女贴图区 -濕透的內褲 -lineage2 -男女激情淫影片图片 -枪支弹药 -肉棒插入 嫩穴 -荡妇 -风雨神州 -麦克阿瑟 -银行帳號 -礼品机 -把大龟头对准她的阴道口 -妹妹的阴蒂 -光线 -馬凱 -妹妹骚图 -毛迷药 -淫妞 -大鸡巴好粗… -免注册淫电影在线观看 -賤人 -萬淫堂 -萬王之王 -你的小穴好紧 -及びタイトル ?(Calen)セーラー服とマシンガン 柚木ティナ -wu jin de ren wu -粉穴 -全免激情聊天室 -毛食屎 -父女激情淫色文章 -戳你 -肮脏美学 -揉搓淫骚穴 -22dy淫色贴图 -淫妻 -他奶娘的 -姦染 -天纵 -minhui -鳥gm -淫妹 -ray-city -下载免费淫色强奸电影 -宇明网 -卫星接收器 -媚藥少年 -郑义 -毛卖软件 -遊戲新斷線 -淫间道 -爽mm -黄色免费淫电影母子淫奸电影 -李鹏 -淫姐 -陈总统 -群交亂舞 -内射美妇 -摸阴蒂 -去他妈 -抽叉jiejie -亚情 -淫电影//少女被强奸到高潮时偷拍小A片 -布雷爾 -淫娃 -18禁-空中小姐的淫荡性生活(无码)。 -欧美淫图片 咪咪爱论坛 -智冠 -淫乱金发美女 -他妈 -蒙古獨立 -新郑和 -官逼民反 -李 淑 娴 -内测帐号 -做鸡 -meinv含双棍玩内射 -騷婦露逼 -發^論 -嫩穴里他的鸡巴 -蔓ぺ -Waigua -偷拍掰开阴唇做爱 -性无能 -做鸭 -天縱 -fuck私\服 -龌龊 -我淫我色网站 -meimei的阴道好紧啊 -遥想当年春衫薄 -毛共产党 -社保基金会 -天堂2 -抽插49岁处女妹妹淫叫不断 -輪子功 -政治避难 -买春 -法*輪*功 -消息公告 -民進黨 -street of EROS 07 小泉リカ -webmaster -俄罗斯 -水去车仑 -毛天安门 -Mugen Vol。11 Ai Hazawa羽沢愛!【AVI/ 699MB】 -淫婦 -婊子 -肉棒猛烈拔插 -荡母淫儿 -精液射入了她的体内 -色图专区 -fofg -mes couilles -女激情淫影片下载 -107bb成人小电影 -谭政 -亞情 -吕京花 -淫妹妹贴图 -身份证生成 -101bb成人小电影 -觀世音 -滚 -滛 -鷄巴 -手记注册日韩5002部激情电影 -干死你 -服务管理 -渡口 -毛回良玉 -又黑又粗长的鸡巴 -f r e e c h i n a -鸡巴插入拔出 真舒服 -瘪三 -欧美激情淫色 -电影淫电影艳情电影 -毛妈祖 -最新黄站 -龟头抽插很紧的处女阴道 -fuck卖.国 -龟头 插进 阴户 -她马的 -悔过书 -shyt -日他娘 -少妇床上欲火难耐自摸图 -毛法轮 -性感诱惑 -毛死全家 -张潮阳 -阴茎在我的肉洞中抽送着 -核武器 -写真 -性虐待 -成人贴图区论坛 -WEB战牌 -fuck新生网 -发^轮 -性免費電影 -激情meinv贴图九九情色 -教你怎样延迟射精23岁以下禁免费淫电影a片 -成人网址导航 -Painful Groins Getting Pounded : Akira Shiratori 白鸟あきら -mo你 -中华人民正邪 -抽B淫穴 -∪R -xin jue dai shuang jiao -伍凡 -(Tokyo Neko) Tokyo Neko GN Vol。1 Ibuki XVID+Ogg -淫人情色导航 -sm調教 -毛社保基金会 -妹妹的阴唇好大啊 -大鸡巴 大肉棒狂插嫩穴 -中央军委 -释迦牟尼 -大阴唇jiejie -柯賜海 -干Gm -煞笔靠 -常委 -邱会作 -fuck他爹 -天天免费成人 -做鴨 -水去车侖 -操蛋 -穴门meinv图库 -現金 -管里员 -干GM -发~论 -鸡叭 -阴唇阴道大图三级 -連戰 -性视频聊天图幼女日屄视频脱衣聊天室明星 -易当 -jiejie的阴唇好大啊 -幾八 -淫乱图片 -所盗摄护士姐姐性感美腿图 肉丝美腿艳情淫欲 -淫色BT娱乐导航 -干勒 -徐和柴学友 -肉缝 蜜穴 肉棒 -流淫 -混亂冒險 -毛人体炸弹 -刘杰 -半夜我把龟头插进meimei的深处 -江西田园置业集团 -豆豆秀 -手记注册日韩5014部激情电影 -淘宝 -干小姨子小穴 -性趣 -亚洲成人情色网站 -你妈的 -EVENT -国外A片电影 -胡耀帮 -淫奴 -法陯功 -淫女 -锤子 -淫奸 -钱 其 琛 -龟头插进 -少妇被强奸密穴流水 -肉棒插入美女的肉缝 -hellgate:london -抽插42岁处女meimei淫叫不断 -白嫩騷婦 -jiangshan -淫妇 -大鸡吧操小逼 -傳銷 -王润生 -免费看淫电影 -淫奸熟睡小姨子 -MUGEN EX Vol。7 濱崎(MX-07) -毛刘淇 -邹家华 -湿透的内裤 -乳房 小穴 鸡巴 -干入 -肉棒插进阴道里 -濕了還說要 -成人色情乱伦影院 -激情淫色合成贴图 -一本道~松下美里 -插入穴 爽 -redmoon -毛鮑 -┅┅啊┅┅好舒服啊 -kjking -meimei社区淫色 -Red Hot Jam 9 ミュウの新人调教 -李贵鲜 -妳妈的 -港澳成人午夜激情 -免费淫 电影a片 -桃色 -傅申奇 -毛李岚清 -毛傅鹏 -插入媽媽…肉缝 -中華人民共和國 -di qiu wen ming -八老 -膏藥旗 -她的小屄不紧 -中華人民共和国 -鸡吧 -桃色星期五 -putain -群交乱舞 -fuck我日 -邓发 -毛摇头丸 -baichi -漢娃娃 -BLOW -遺囑 -騷B賤 -外 挂 -Mix Studio Vol。 7女医 -妹妹的小淫穴 -在线免费成人电影 -moyu -淫屄 -卡斯特罗 -达赖喇嘛 -草的你妈 -李立三 -d7se -厕所盗摄 -女教師赤版 -人弹 -27军军长 -gong fu xiao zi -高丽棒子 -肉棒在jiejie的阴道里 -遗忘传说 -愛滋 -天聯世紀 -KOKESHI COWGIRL Vol。24 炎的10番勝負2 前編 : 工藤Hatsumi -美国激情淫色网站 -幼女淫图 -法綸 -成熟性感大美女 -cao -根正苗红 -诱色uu -好爽 -大阳具 -shen zhi ling yu -彭珮雲 -黄色淫乱电影 -江豬 -干到 -大乳頭 -xian jie zhuan -本站10008多部激情电影全部免费试看三天 -谋杀 -津瑞 -6。4事件 -国家民委 -【亚洲/无码】极品女优-姬野愛!【RMVB/488MB】 -日韩免费成人电影 -mao xian dao -猛男狂干meinv -值勤帐号 -老骚比 -毛江核心 -女教师淫乱课堂 -懶叫 -造愛 -urban-rivals靠 -日批 -大話西遊 -tie jia zheng xiong -护士嫩穴扒开嫩穴嫩穴 -遺嘱 -毛疆独 -天安們母親運動 -毛旅游局 -桃色 激情电影 -5173 -强奸26岁处女全过程/*妹阴毛小穴 -銀行账號 -goqo -巨乳素人 -色色 -毛淫毛 -幹你 -陳總統 -pp点点激情片播放 -他娘 -毛骚 -妹妹騷圖 -洱 -邓小平 -永恒之塔 -三国豪侠传 -%共产党烂逼 -妹妹的小屄好痒 -乳暈 -fuck我操 -僵贼 -姐姐的小屄 -布希 -彩票机 -激情貼圖 -智傲 -明星裸体写真图 meinv网络视讯三点 -淫告白 -插穴止痒 -梦幻情人射了10次的强片 -支持达賴 -刘延东 -毛蒙尘药 -发^^沦 -拔出来 -绿色數碼 -熟女玩3P内射来满足欲望 -fosaon -發~~侖 -發@輪 -精液射进妈妈穴里面 -乳晕 -鸡巴受不了了┅┅要泄 -完全免费在线淫电影? -插 小姐 -teen sexy -楊振 -毛蒙古达子 -毛淫水 -义母 -他媽 -禁书 -最新 Queen8 无修正素人 -多维 -米田共 -锦天 -少林传奇 -乳波臀浪 -吃雞巴 -凸点装 -大力抽送 -极品黑丝 -绿色數码 -安非他命 -高莺莺 -毛港澳办 -猛烈的挺送、肉体激烈的撞击 -支持达赖 -习仲勋 -脸盘美身材好就是屄丑点 -39仓Ku -roiworld -插穴止癢 -淫 -淪 -肏妹妹的小骚屄 -强*十八岁meinv护士看完保证你打飞机免费淫电影a片 -系统管理员 -在线淫色电影 -天安门英雄纪念碑 -儿子添着妈妈肥大湿润阴唇 -免费电影 meinv电影 -绿色数碼 -她的阴道好紧 -日本激情淫色贴图区 -午夜场 -暴亂 -图片不爽你砍我 -fuck邪教 -白嫩丰腴的大腿掰开成大字形,肥嫩的小骚屄儿 -无码长片 -亚洲成人网 鹿城最新娱乐网 -tian shang bei -添 穴 两腿间 -和阿姨乱伦 -龙虎靠 -手记注册日韩5035部激情电影 -抽插45岁处女meimei淫叫不断 -發^^倫 -現貨 -淫*女电影片段试看淫mm -365激情淫色贴图 -cocksucker cocksucker -情色导航 成人电影 -毛老逼 -激情淫色文章网站 -日本AV女優 -毛法*轮*功 -3p炮图 -性感动感meinv日本幼少女性感写真 -鳥Gm -搜神记 -60xp。com 电影免费 -歡樂數碼 -黄色情挑艳情小说网骚妹妹成人论坛 -淫語連連 -苏东解体 -日你九城 -色男淫女 -顏射自拍 -暴乱 -润星 -台湾身材一流meinv楼梯性爱 -暴乳 -文物局 -鳥GM -tnnd -痴女吸精 -免费操小姨子 操小姨 操小姐图片 操小姐小说 操小姐自拍 按摩洗浴操小姐 操外国小姐b -zhenshanren -真封神 -时代论坛 -海之樂章 -小日本 -shen me shen me da mao xian -毛上你 -仿真假钞 -亚洲**联盟激情视频 免费下载做爱图片 -她爸爸 -新华通论坛 -保證很像學生妹 -好大的阴唇 -应召 -絲襪淫婦 -鸡吧猛的抽插嫩穴 -popoming -操日风骚少妇穴 -黎安友 -淫荡护士穴 -fuck小日本 -毛我日 -綸功 -马时敏 -hua hua man -狂插儿媳 -三级小电影 -性爱电影网 -公车淫奸女学生 -1989天安门 -激情色情 -台湾女人裸体贴图香港成人电影网 -亞洲色 -温州鹿城成人网 -使劲插我啊 -东北xx网 -蕾丝内裤被龟头顶穿 -发@@抡 -艳照門 -则民 -射了還說要 -淫女嫩穴图 -Duty Vol 50背徳の近亲相奸 -劳动教养所 -人大 -潘国平 -朱可夫元帅 -军民血腥冲突 -免费淫奸女A片段试看 20岁女大学生被强 -免费观看美女裸体贴图 -輪奸內射 -西遊伏魔錄 -毛淫欲 -meinv极品穴 -毛鸡 -舔西 -绿色数码 -毛鸠 -pp242淫色导航 -a片/A片下载/毛片/毛片下载 -毛江Core -sofben sofben -淫水也流湿了我干进她穴内的龟头 -干bi -暴操淫荡小meimei -管里 -民阵 -卖财富 -runstar -逼孕 -麦角酸二乙基醯胺 -死 -毛天皇陛下 -自由之門 -日本娱乐性免费电影在线 -又肥又大的穴 -刚比 -中國分裂 -SYSTEM -电影免费试看 -仙侣奇缘 -中国大学 高清女厕盗拍 vol。01 -K房 -视频自拍 -独占动画~潮崎~高校女教师陵辱1+2 -免费聊天室 -刚瘪三 -騷女叫春 -成人社区 -党主席 -西藏问題 -成人社區 -中國恐怖組織 -fei chang san guo -手记注册日韩5024部激情电影 -sperm -三国世纪 -毛鲍 -chinaliberal -阴精喷向龟头 -少妇房中自淫,和两勇男玩16P,操得直叫爽 操日本淫女穴 -sm援交 -幹x娘 -辉煌 -下注 -mo xiang -强奸45岁处女全过程/淫妹阴毛小穴 -女巨乳女教師 -翘臀嫩逼 -新闻出版 -錯B -捅进她的阴道里 -bitch -抽插38岁处女meimei淫叫不断 -艳照门 -巡查 -吸精小少女 -89-64cdjp -干gM -淫秽男女激情淫乱 -hanbitsoft -西藏问题 -18岁处女床上开苞 -more -白虎小穴 -bukakke -欢乐城美国在线 咪咪爱论坛 -香港马会 -嫩穴狂插直到痉挛 -李 岚 清 -人大代表大会 -毛日本鬼子 -午夜激情情色网 -肉棒进入肉洞 -自由之门 -caobi -fuck王震 -肉棍干騷婦 -啊 啊 啊 好哥哥 -日本meinv图库 -毛强卫 -淫奸少妇电影 -墨索里尼 -免费免注册在线看电影 -交媾 -東北獨立 -法纶 -肉棒的抽插 ……啊 -下流 -色网阴道特写强奸29岁处女全过程 -礼品 -发^论 -品色永远免费堂pin6 meinv发春激情3级片试看 -兔妹妹色色贴图区 -叶剑英 -乱伦+都市+制服 -q币 -毛懂文华 -二五互联 -发@轮 -姦汙 -高丽棒 -國家機密 -毛肉缝 -yuanming -干gm -紅月 -淫水大量流出 -metin -由喜贵 -谢长廷 -三去車侖工力 -大鸡巴插进meimei的小穴 -二五互聯 -娇妻超市被奸,淫荡妈妈之办公室助理 -江贼 -鸡吧插到嫩穴 -久之遊 -美女激情性交射精电影 -买春堂 -奴隷女教師-女尻狩り 吉野あゆみ -淫蕩少婦好色老師 -gate to heavens -册老 -麦角酸 -他祖宗 -fuck新光明 -操蠢猪 -88bb成人小电影 -fuck铁道部 -欢乐城 -亮屄 -大唐风云 -宋祖英 -傅全有 -神之领域 -龟头插入淫荡少妇 -混沌靠 -巧淫奸戏 -……媽的騷穴癢死了 -發$輪 -幾叭 -蒙哥马利 -大话春秋 -一股淫液从肉洞喷出 -淫荡少妇穴 操淫荡少妇 -曾培炎 -kefu -花心大型色站 -meinv偷拍成人小说激情网 -断水 -干啦 -冊老 -官方管理者 -xian jing chuan shuo -免费注册激情视频聊天 -transvestite -性情中人 -刘凯中 -狂插空姐 -操冰毒 -妹妹的大阴唇好嫩啊 -毛我操 -日本AV女优 -抽插37岁处女meimei淫叫不断 -湿了 -毛吴 仪 -伤亡 -售號 -朱容鸡 -日韩淫乱meinv图 -酥胸诱惑 -lian ai he zi -法**輪 -含着龟头 -分裂祖國 -meng huan zhi xing -Tora-Tora-Tora Vol。22 : 冬月ひな -Ji女 -淫水和精液浸濡的小穴里 -秘密通道 -fuck驶你老母 -烂比 -新视野工作室 -狂操小姐 -分裂祖国 -陈随便 -鲍鱼贴图妖色成年网电影 -大哥 等等 我尿完后 再给你干肉穴 -操b -学生妹同男友夜晚做爱并轮插 -hypermart。net -狂插妹妹穴 淫水流 -巧淫奸戲 -fuck水利部 -何德普 -成人午夜激情 -操B -海盗王ONLINE -ying xiong wang zuo -遗囑 -毛抢劫 -大東亞共榮 -*李*洪*志* -辛灏年 -保证你打飞机免费电影网站 -kaixuan -毛新唐人 -發*輪 -AV OPEN)(TOD129)近亲3姐妹狂乱夜 -尸體 -别他妈的装 -fuck私—服 -虎虎虎~变态心Tora Tora Gold Vol。17 : Mako Takeda -一贯道 -fuck宋祖英 -台灣民國 -肉棒插入阴户 -J-Girl 双穴~水原 小笠原崎 -妈的 -值勤账号 -屎你娘 -试看片 -妳她媽的 -出售手枪 -喵的 -365免费情色网欢欢成人娱乐 -fuck天安门档案 -逼奸 -鸡巴磨得舒服 -遗嘱 -白嫩美女穴 -fuck私-服 -灌满精液 -桑国卫 -操妳全家 -玖玖金币 -your mom your mom -creaders -搞大肚婆爽+口交泻水淫图 -温馨提示 -张 宏 堡 -斷水 -人妻 -shit -我和姐姐肏穴 -如果你未满21周岁请自觉离开。 -中国威胁论 -方毅 -肉棒插入 -法**轮 -舆论 -斯大林 -Aids -ling you ji -插的妹妹流淫水 -瓜娃子 -jing ling -賣月卡 -刘淇 -你他馬的 -发*轮 -鸡奸 -王俊博 -鸡女 -乳房 -僵贼民 -公务员调资 -制服美少女 鮎川なお -新聞管制 -fuck私/服 -毛他马的 -阴壁的嫩肉夹得我非常舒服 -淫店 -黄色淫电影/大幅的陰毛覆蓋著她的迷人洞 -Tokyo Hot n0232 : 真宫梨沙子 -西哈努克 -莎士比亚 -明慧 -台灣民国 -硕大的龟头 -黄 菊 -毛吗啡碱 -操你爷爷 -renmingbao -meimei的屄好紧啊 -分裂中国 -日本 -欢城互动 -57xp。com 电影免费 -消灭共产党 -个人资料 -王 秀 丽 -UPDATE -分裂中國 -调教 -天安門檔案 -日本顶级淫女 -傅鹏 -68wow -无产阶级 -贾廷安 -bt免费淫电影下载 -毛交通部 -高丽朴 -偷操嫂嫂 -mm要我使劲插它的穴 -鲜红小嫩屄被群奸真可惜 -du shi 2046 -妈b -喬石 -Lateinos -严隽琪 -淫穴 大鸡巴 -狂插我的小嫩穴 -街上钓个漂亮马子回家玩 -meinv主持25小时全天激情热舞 -輿論鉗制 -服務管理 -蒋正华 -遭警察殴打 -本拉丹 -房事 -妈B -美女性交极品大片 -红肿的小穴摩弄 -跨下呻吟 -毛骚货 -插小穴 -大腿 -啊…我的亲丈夫…用他的手…插…啊…啊…进了人家的小穴 -最新一本道)超正MODEL系列 仲里愛 -精液 -红 灯 区 -希望online -天然むすめ~08-15 素人むすめたち -拍卖官 -新浪 -qq堂 -peacehall -肉棒……插死浪穴了 -快操我快操我的小B电影 -把阴户内塞得满满 -预测 -大肉棒干进小穴 -鄧朴方 -大幅的陰毛覆蓋著她的迷人洞 -教你怎样延迟射精40岁以下禁免费淫电影a片 -19dy淫色贴图 -少女露嫩穴 少妇嫩穴 美女的嫩穴 -徐建國案件 -龟头插入阴唇 -appie -玉女心經 -罗荣桓 -精液喷射在子宫上 -又粘又湿的阴户 -弹劾 -日韩激情电影 -發@@倫 -巨乳女教師 -迷奸熟妇怎样抚摩女性的私处更刺激 -午夜激情剧场 -瞳 -黄大仙 -法**綸 -我和她 -扒开淫女的骚逼 -b毛 -Obama -發~淪 -龟头插入蜜穴 -共荣圈 -肉穴 大鸡巴 ……骚穴 -发$纶 -毛民运 -恥辱醫護下载 -快乐AV -邮政局 -我和小姨子 -插嫩逼 -李洪宽 -操小穴 -哪有a片 百万meinv贴图夫妻激情免费视频 -如何推翻中共 -血洗天安門 -渣波波 -李兆焯 -公安部 -表姐含我小鸡鸡 -中蕐 -情色淫电影 -herogame -騷乳 -AIDS -教你怎样延迟射精27岁以下禁免费淫电影a片 -妹妹┅┅爽快┅┅死了 -毛毛泽东 -神泣 -dick -戴海静 -ASS -神泪 -打倒中华人民共和国 -视频 -枪决现场 -刀剑 -成人禁书 -插入穴爽死了 -保钓 -fuck食捻屎 -骯髒美學 -釣魚島 -干……干我……用力地干我…… -毛西藏天葬 -免费色站 -毛干你 -开天 -手机复制 -毛兴奋剂 -SHIT -89六四 -淫情 -金尧如 -雪腿玉胯 -(Nadeshiko)夢の超高級癒し系Wおでかけソープ嬢 完全版 -干嫂子 -法溣功 -NEWSPACE -狂插秘书穴 -Kamikaze Girls Vol。23 : Haruka Kaede 枫はるか -可愛均整清純派meinv可愛均整清純派meinv -韩天石 -吸吮套弄了起来 -奥美电子 -眯 -免费台湾18 电影 -东方资通 -gan你 -騷小浪女 -無碼電影 -我和老板娘 -淫穴更紧紧将我的肉棒吸住 -fuck他妈 -男女激情图片 -國家安全 -浴室亂倫 -虎门靠 -megaone。com -cronous -叼你媽 -毛狗卵 -牛鬼蛇神 -冊那娘餓比 -儂著岡巒 -睾 -我要性交 -将肉棒插入漂亮的老师小淫嘴抽插数十次 -群奸轮射 -全球第一淫图城 -san guo hao xia zhuan -夜夜色大型网站 -龍陽 -毛靠你妈 -bing feng chuan qi -fuck我日你 -洗腦班 -fuck吴邦国 -groove party -贾庆林 -娇嫩的小阴核 -mo fa fei qiu -福呵定 -毛肉穴 -穆斯林 -虎騎 -疯狂的抽插 -敬国神社 -kong que wang -zhen kong que wang -干死GM -徐炳慧 -肉棍 嫩穴 肉洞 -操大B -手记注册日韩5028部激情电影 -meimei美图网 -妹妹的屄 -母子乱淫贴图 -色咪咪 -干比 -毛十五周年 -生孩子沒屁眼 -退役 -情色激情论坛 -性虐 -B -免费成人午夜电影 -日本淫贴图 淫妻贴图 -性虎 -阴茎被她紧紧地夹住感到肉洞急促地收缩 -居家女人的淫荡性事 -温州黄站 -抽插56岁处女妹妹淫叫不断 -华岳时事论坛 -儿子粗大的肉棒 -淫电影 强*十八岁美女护士看完保证你打飞机 -b -张开的小阴唇 -李小鹏 -玉女心经 -毛机八 -家人一起凌辱母亲和叔母 -激情成人乐园 -xia ke tian xia -rape -盛宣鳴 -黄色淫穴电影 -乘骑按摩 -xin zheng he -壮汉给纯情处女开苞见血 -應召 -免费淫色情电影 淫电影//少女被强奸到高潮时偷拍小A片 -台湾18成人网站 -本土无码 -賣B發論公 -司徒华 -apesoft -温总理 -迷人阴部护士meimei也疯狂 -情獸 -智能H3 -骚妹妹成人导航 -作愛 -古龙 -抽插28岁处女妹妹淫叫不断 -神汉 -美丽素女の性游戏 -色网阴道特写强奸35岁处女全过程 -新西遊記 -西藏國 -回民人吃豬肉 -干死CS -反攻大陆 -证监会 -西藏国 -杜智富 -毛塞你爸 -毛气象局 -反攻大陸 -又大又紧的阴户 -激情成人聊天室 -秘书自慰被偷拍 -C N -金三角 -一夜欢 -妈妈的 -强卫 -毛邪教 -胡志明 -狂插小嫩穴 -咪咪爱大型黄站 -东热meinv一个比一个强 -迷人小穴好紧好湿 -蝉童 -免费台湾激情片 -Trickster -激情淫色贴图网 -发*纶 -18歲少女 -情色电影注册观看 -小穴夹的我好紧 -撒切尔 -hua xia -江泽慧 -中国性爱城 -騰仁 -空中小姐的淫荡性生活 -一夜歡 -干死 -以茎至洞 -亲 日 -品色永远免费堂pin6 美女发春激情3级片试看 -王太华 -磨蹭阴道阴毛 -妹的穴 -两会报道 -毛工作人员 -你妈逼 -fuck斯大林 -淫色bb贴图 -無碼彩圖 -於幼軍 -内挂 -精液射进她的小洞 -慶 紅 -日本插穴 -hongzhi -懒8 -淫电影//富豪们的疯狂做/爱方式 -新党 -免费淫奸女A片段试看 母子淫奸乱轮现场看…… -淫荡少妇激情自拍 成人激情 -免费成人两性电影 -抽插大淫穴 -邹德威 -飘流幻境 -语句 -大FA弟子 -小淫穴 -淫奸秘书电影 -剑侠情缘OnlineII -SKY宫泽Keito 超美系模特儿初无修正引退纪念作 -毛反革命 -龟头插入少妇阴道 -手记注册日韩5031部激情电影 -黃孟複 -盛宣鸣 -疯狂姐姐淫穴 -wg8800 -上访 -壓迫 -大B -王乐泉 -tta2 -运營组 -人民代表大會 -刘军 -愛色cc -博白县 -抽插35岁处女meimei淫叫不断 -死亡人數 -李鐵映 -鹽酸二乙酰吗啡 -毛淫叫 -丝袜 -connard -popkart -天安门事件1989 -处女小穴 -成人爽电影网站 -MM的诱人双峰 -9游 -超强护士团 -东方传说online -他爹 -政府 -怎样延迟射精22岁以下禁 -代炼 -午夜影院 -十八dy毛电影 BTA片 免费激爽电影 -美穴張開貼圖區 -毛南蛮子 -两性小说 -尖閣列島 -如果你未满28周岁请自觉离开。 -精液喷入穴 -项英 -林心如合成淫照图片林心如淫照图片 -脫內褲 -肉棒 小穴里抽送 -丝袜高跟 -淫女炮圖 -金泽辰 -畜 -穆罕默德 -我跟meimei肏穴 -本站10000多部激情电影全部免费试看三天 -日本meinv吃精图 -秋本純菜 -操日本淫女 -helbreath -粉红嫩穴 鲍鱼嫩穴=3 -粉红嫩穴 鲍鱼嫩穴=1 -抽插51岁处女meimei淫叫不断 -粉红嫩穴 鲍鱼嫩穴=2 -天晴数码 -倪志福 -万晓东 -色色婷婷 -(最新一本道)独占动画~薰~陵辱巨乳 -手伸到下体抚摸嫩穴 -八 仙靠 -儿子的肉棒好硬 -本站10000多部激情电影全部免费试看 -sm舔穴 -人民代表 -素人之中的极品漂亮妹 -小癟三 -feng wu tian jiao -大血B -刘刚 -成人激情淫影院 -爽女美图美搜性感图涩界成人电影网小小鸟绝色美女写真图 -用舌尖插着阴道口 -我占有了妈妈和阿姨 -情色六月天 人间仙境情色网 -xin shi qi -熟女网爱记 -姐姐的穴夹的我好紧小说 -乱淫自拍图片 -俄国 -操比 -淫女炮图 -运營者 -TokyoHot之极品妹妹 -ttee -毛新华社 -天晴數碼 -610办公室靠 -陈伯达 -赤裸天使 -虎骑 -台聯黨 -毛龟儿子 -白嫩骚妇 -毛傅作义 -小穴的周围不断地缠绵着 -台湾18成人 -毛尉健行 -阿姨的穴┅好爽 -韩东方 -媽個老比 -毛毛主席 -tth2 -和jiejie插穴 -華建敏 -精童 -毛李长春 -香港两性激情文学区 -fuck身份生成器 -死亡人数 -插入妹妹穴中 -狂操淫荡女 -干你妈逼 -华语世界论坛 -天葬 -pet520 -夫妻自拍 -色诱 -毛文化部 -秦基伟 -宋xx -陈锡联 -山不过来 -逃亡艳旅 -11。xp。com成人影院 -meimei小穴 -激情裸聊 性爱电影 -BT成人无码 -血洗天安门 -人妻做爱 -fuck新党 -可憐賣菜婦 -遊戲宮理員 -情色 激情 meinv 穴 -mir3 -湿了还说要 -zhengjian -免费裸体meinv性交电影 -洗腸射尿 -gang jia hong liu -诱惑女教师 -dick dick -顶到了欣虹阴道最深处 -zheng qi huan xiang -阿罗约 -口交放尿 -连战 -…好深啊…操我 插我 -da hua chun qiu -b样 -性福源亚洲激情 -中国恐怖组织 -温家宝靠 -乳罩 -meimei吸精 -操死 -色聊激情视屏聊天室 -戰國英雄 -蔣介石 -海关总署 -帶炼 -姦淫 -懒八 -午夜免费成人黄色 -妈祖 -农民伯伯乡下妹 -强奸十八岁meinv护士看完保证你打飞机免费电影网站 -U R靠 -風豔閣 -lihongzhi -玉蒲团 玉女心经 -王力雄 -lian ai he zi -阿姨的阴户好大啊 -jiaochuang -淫奸少女论坛 -新金瓶梅成人片 -B毛 -香港激情夜 -香港激情淫穴 -草芝麻 -大 史 紀 -网星艾尼克斯 -淫奸meinv穴 -meimei张开双腿等你操  -舔逼 -wg2222 -毛妹妹贴图区 -龜頭 -装备演示 -浩天銀科 -hai zhi yue zhang -知障 -fuck希特勒 -援交薄碼 -処女 -欣赏特级毛片pp 点点毛片 美女毛片 大陆毛片 -激情电影在线注册 -免费我该死淫水流出图 -淫女与猪乱搞图 -女良 -郭 岩 华 -龟头插入少妇 -激情视频 -懶八 -星际online -人民大会堂 -发^^纶 -韩国成人激情影院 -金庸群侠传 -粉紅穴 -毛驶你娘 -操狗 -插穴好舒服 -好爽……顶得好深啊…… -龟頭 -駭客 -毛劳动保障部 -丁字裤翘臀 -虎门 -色成人 -可卡葉 -51vip -纠察员 -遊戲橘子 -儂著卵拋 -黑马@美女全身神秘黑让你爽到眼框黑 -淫战群p -毛黄色小电影 -肉棒在阴道口游荡 -你的 嫩穴 好粗 -basterd -肉淫器吞精 -食精 -强奸24岁处女全过程/*妹阴毛小穴 -钢甲洪流 -松花江污染 -免費成人網站 -騷包 -淫战群P -叫小姐 -诱惑骚妹 -人妖@Lady Sonia-熟女丝袜 12 -林心如做爱网有激情 -操嫂嫂 -淫乱的女老板 -肏穴好舒服 -激情淫色电影 -獸 -老少亂倫 -成人淫穴导航 -老毛子 -你祖宗 -毛乳头 -体育练习场盗撮スポーツジム(4カメ洋式) -插meimei图 -膣穴大陵辱 松岛 -籐原紀香Norika Fujiwara SEX -錯那嗎逼 -獨 -精童欲女 -高级逼 -李 總 統 -新四 -mingpaonews -成人 -淫肉诱惑 -毛烂逼 -┅插┅小穴 肉缝 -粉紅愛液 -浪女自慰诱惑你操 -nnd= -魏新生 -援交薄码 -免费操小姨子 操小姨 操小姐图片 -狗養 -操爽 -日你祖宗 -少妇淫图电影网 -免费激情影院 -毒龙舔脚 -上山下乡 -busterd busterd -狗娘養的 -警匪一家 -15年前的“共和國衛士” -激情聊天室 -大话 -厕所盗摄美女 -丁香成人社區 -穴里嫩肉把鸡巴包得紧紧 -日韩成人电影 -sex大型色站 -胡总书记 -操爛 -去氧麻黃堿或安非他命 -闹事 -梦遗 -彭冲 -本站10014多部激情电影全部免费试看三天 -抽插38岁处女妹妹淫叫不断 -激爱贴图 加西激情中文网 -女性私处锻炼法 -哥哥 -操 -我的穴 -税力 -裝備演示 -毛叫鸡 -好大阴户 -陈永贵 -流淫水 -操mm穴 -asshole asshole -免费淫电影吴宗宪搞笑语录(20禁看) -丁香成人社区 -粗大肉棒从后面插入 -插進 -妳娘的 -free style -插逼 -撒泡尿 -秘书的大乱交 -手记注册日韩5005部激情电影 -学生妹美女在野外偷情 -赵品潞 -坐台的 -无码H漫 -rong yao -毛鲜族 -祭日 -吳官正 -口含住鸡巴 精液 -成人午夜激情视频 -色狼小說 -扒开小穴 -激情淫色组图 -捐赠排行 -ygbh -見到這個meinv就會有性欲 -as$hole -总裁 -菊花洞 -黄色免费淫奸电影我和女友干爽后再她妹妹 -运營組 -裸体妹妹林心如穴 -蘚鮑 -愛液 -Transformaition 栗田Hiromi -插进 -疯狂姐姐教弟弟小说 -轮流干 -365成人网站 -删号 -阿姨的小穴 -伊朗 -guang zhi guo du -肉棒全部插入 -少妇房中自淫,和两勇男玩11P,操得直叫爽 操日本淫女穴 -淫meimei贴图 -戴维教 -亚洲成人无码 -台湾成人20贴图 -大肉棒……好粗 -牙齿轻咬他的龟头 -免费淫奸女A片段试看 居然花钱请人教性爱姿势(组图) -小瘪三 -午夜激情meimei -毛寇晓伟 -手机注册看性爱电影 -肉棒插入妹妹的肉缝 -快乐西游 -fuck司法部 -百家性大型娱乐黄站 -爛 -林心如做爱我该死快乐情感乐园 -大b -毛联合国大会 -ke luo si -剑侠情缘 -原味丝袜 -sars -日你 -肉棒摩擦她屁眼里的嫩肉 -淫女露穴 -禦の二代目 -收缩的阴道中抽出肉棒 -爱液横流 -然后 -爽 -jiao chuang -wu hun -san guo qun ying zhuan -嗎比 -江青 -成人激情淫论坛 -懒叫 -神曲 -洗脑 -完全免费在线淫电影 -发$$仑 -女人被干小穴 -淫电影网站 -欢乐时代 -翹臀嫩穴 -程凯 -機巴 -国 贼 -三P -骆冰淫传 -政治局常委 -肉棒插肉缝 -大龟头顶紧子宫口 -法$$轮 -毛妈的 -香港顶级淫片 -韩日成人午夜激情电影 -fuck新闻出版总署 -免费注册 试看50部 -抽插23岁处女妹妹淫叫不断 -毛共青团员 -操烂 -湿身诱惑 -干爹的龟头 -华夏文摘 -日他 -狂插妹妹小穴 -抽插40岁处女妹妹淫叫不断 -Shit -自慰女學生廁所偷拍in Toilet 1 -北京xx网 -日你媽 -谢选骏 -色情电影 卡通 成人 av 少女 -非常诱惑 -6。4事件 -狂插美女老师 -淫奸meinv -夜话紫禁城 -臺灣國 -bo ke -中國豬 -激情bt亚洲区 -国产经典 - 4级红楼梦!【wm/113MB】 -操草的你妈 -白莲教 -妈妈的穴 -開天 -涵涵 -大 史 纪 -教你怎样延迟射精42岁以下禁免费淫电影a片 -ping guo pai -法$$輪 -燕玲論壇 -迷奸 -淫民俱乐部和美女发春激情3级片试看 -诺亚 -教徒 -央视内部晚会 -操粗制吗啡 -浪穴 肉缝 嫩穴 -强奸26岁处女全过程/淫妹阴毛小穴 -大阴唇夹着大龟头 -拍肩神药 -cunt -肉棒 用力 肉縫 -淫書 -幹比 -travesti -魏京生 -墨香 -網域 -毛狗养 -王志珍 -毛耶苏 -一国两制 -江ze民 -劲舞团 -毛主席 -東突組織 -大 纪 元 新 闻 网 -222se图片 -三p -四川独 -齷齪 -成人激情性爱电影网 -暗黑之门:伦敦 -jiejie的屄 -本站10009多部激情电影全部免费试看三天 -人妻自拍 -操出售枪支 -靖國神社 -易玩网 -不注册淫电影 -高清性爱 -毛发伦功 -allsexpages -OL美女街上遥控震动A -日本人 -piao piao -法车仑功 -天龙八部 -干汝 -班禅 -新华举报 -幹死 -fuck王宝森 -毛私\服 -毛全国人大 -真善忍 -server -re xue ying hao -捐贈排行 -肉棒插到妈子宫 ┅┅爽死了 -台湾男女激情淫乱小说 -激情 少女 成人论坛 乱伦 强奸 -免费淫奸女A片段试看 教你怎样延迟射精18岁以下禁免费淫电影a片 -无界浏览器 -热比娅 -淫荡jiejie勾引小弟玩操屄 -國產騷貨 -瓜婆娘 -移彩联合 -开着摩托干了岳母 -红色恐怖 -神出鬼没!3个丁字裤辣妹到处袭击肉棒(中文字幕 -迫害 -毛穴贴图 -亚洲激情淫色网站 -烂 -淫荡老师 -小姨子的小嫩屄 -create -亚洲激情BT -省长的儿媳妇 -苹果日报 -xian lv qi yuan -于天瑞 -鸡吧在肉洞里四处搅动 -中医药局 -16大 -手记注册日韩5008部激情电影 -肉棒 插 穴 -江主席 -发@@沦 -阴小撕大 -毛台湾民国 -泡泡岛 -大鸡巴狠插小穴 -成人电影网站 -柔阴术 -勁舞世界 -淫样 -正义党论坛 -啊……我的小屄……给你……肏得好……舒服…… -强*十八岁美女护士看完保证你打飞机免费电影网站 -一黨專制 -深爱色色 -a级电影 -情色 性息 -乳此豐滿 -166网址宽频影院网 -慈善會 -xinguangming鳥你 -无码丝袜 -onhave -猛力的抽送大肉棒 -falu -空姐性交 -妈妈帮儿子套动着 -meinv野兽做爱淫图 -vulva -求自己的爸爸和她干 -乳波臀娘 -色狼小说 -肥穴jiejie -灾 -獨裁 -裸体做爱 -将阴茎尽根插入 -毛刘军 -摳穴 -龟头用力刺入阴道 -王樂泉 -周永康 -成人网站排行榜 -儿子淫奸妈妈穴 -肉棒 用力 肉缝 -淫乱护士 -六四真相 -客户服务人人员 -地 下 教 会 -tw18 -含鳥 -手记注册日韩5011部激情电影 -发$$伦 -小鱼儿与花无缺 -叼你妈 -紧致小穴抽插 -B样 -摩力游 -蓮花逼 -大肉棒插入湿湿的肉缝 -异议人士 -懶8 -dou dou -娘比 -本站10005多部激情电影全部免费试看三天 -插阴茎 -三国演义 -毛统计局 -法侖功 -北京xx網 -奶罩 -hai tian ying xiong zhuan -三级图片论坛禁自拍偷拍论坛日本黄色三级 -guai shou zong dong yuan -地富反坏右 -96bb成人小电影 -meimei的大阴户 -信仰 -迫奸 -sheng zhe wu di -牛B靠 -色女乳房阴道 -麥司卡林 -毛李鹏* -多維新聞 -嫩女 -tian shi zhi lian -妹妹嫩穴 -点击这里试看meinv做爱现场 -世维会 -嫩奶 -小日本爆撮中国女子大生vol。01 -乔石 -fuck you -豪乳 -習近平 -三去仑功 -高麗朴 -avatar -成人激情淫穴影院 -hong yue -免费在线淫电影下载 -大陆娱乐最新黄站 -龙虎豹 -嫖客 -大逼 -操那吗B -超毛大鲍 -我和少妇 -现代艳帝传奇 -realexterme -操表姐 -朝倉Riho !【RMVB/405MB】 -光宇华夏 -淫棍 -shen jia qi bing -陈希同 -发廊性息 -百家性大型黄站网址 -湿湿的阴户不断地在大鸡巴上磨擦 -日你妈 -干进meimei的小穴 -Tora Tora Gold Vol。14 星野みく -手记注册日韩5003部激情电影 -嘻游中国 -俪影蝎心 -佈雷爾 -小雞雞 -網易 -猛插表姐 -64yl -母子淫*乱轮现场看扶正肉棒 -法論 -網星 -大 史 -┅你的大肉棒┅┅好粗 -于幼军 -美マンの極意 : 相原梨花 -43lian色站大全 -台湾ye77 -肉棒里插肉洞 -亚甲二氧基甲基安非他明 -人民 -TEsT -中国成人论坛 -几巴 -免费免注册在线淫电影 -人民日报 -体奸 -我淫我色 -meinv直播做爱 -Bi样 -性感肉絲 -李嵐清 -美女高潮 -儿子顶到jiejie的花心 -强奸37岁处女全过程/淫妹阴毛小穴 -黄色激情论坛 -淫女乱伦小说 -小穴被阴茎插的好痛 -少妇淫心我要看淫心 -wan wang zhi wang -免费黄色电影 -私处 -爱巢滴水 -嫐屄 -给女人快速达高潮的秘密 -淫奸jiejie小说 -欧洲极品性交图片 -下三烂 -氵去车仑工力 -色网阴道特写强奸36岁处女全过程 -骚妹阴道 -裙内偷拍 -往事追忆录 -廁奴 -他妈的 -床上的淫荡少女 -本站10012多部激情电影全部免费试看三天 -轮奸做爱高潮 -enculer -毛烂货 -情色导航色情排行榜大陆黄网导航免费成人电影 -少妇淫乱小说 -丰满小妹的丰褪美腿 嫩得流水的小妹妹 -306医院 -nmis -金伯帆 -a片 -超毛大鮑 -17爱网 -升达毕业证 -J-spot PA-39 -東洋屄 -色网阴道特写强奸20岁处女全过程 -本站10009多部激情电影全部免费试看 -插在妈妈嫩嫩的小肉穴 -猛操狂射 -外汇局 -淫奸教师论坛 -卡通meinv淫色贴图 -手记注册日韩5021部激情电影 -鸡巴暴胀 -学自联 -日内瓦金融 -夜總會 -法*轮*功 -造反 -夏夏娱乐黄站 乱伦熟女网 -林心如做爱网有激情自拍 -野外性交 -身体障害者 -肉棒插护士穴骚穴 -好硬的肉棒 -肉棒插入小穴里 -狂插学生妹 -鹿城最新导航 -张朝阳 -肉棒淫水嫩穴 -叫雞 -蔣正華 -c a o -处女第一次阴道做爱全过程 -淫乱激情电影网站 -火棒 -色窝窝网之家 -幹一家 -江則民 -通告 -东突组织 -濕穴 -亚洲情色网 -嫖娼 -大海戰II -freechina -干美女小穴 -新闻封锁 -高麗棒 -18dy -毛俞正声 -秘唇 -淫色五月天 -42lian色站大全 -fuck驶你老师 -淫樣 -下三濫 -毛建设部 -极品白虎 -毛列宁 -肉棒狂插小嫩B -远志明 -淫色论坛 -亚洲淫色贴图365 -下载免费淫电影淫穴流 -法论 -東條英機 -肥穴自拍 -发骚 -法谪 -六四屠殺 -奶挺臀翹 -mabinogi -济南建设路 -韓 東 方 -g片 -駛你老母 -spikegirls -日你娘 -系統 -淫色少妇做爱淫穴流 -情色 meinv -公安机关 -记者 -犯罪嫌疑人 -*法*輪*功* -侖功 -强奸17岁处女全过程/*妹阴毛小穴 -奶挺臀翘 -肉棍干骚妇 -强奸18岁处女全过程/淫妹阴毛小穴 -淫穴内好痒 -激情午夜 -兽欲 -fuck万税 -厕所盗摄美女性感 -石进 -meimei的阴唇好大啊 -法~~仑 -ai滋 -你奶 -中国复兴论坛 -妈**菊花穴 -恩格斯 -鬼輪奸 -Kamikaze_Girls_Vol。12 -黃 菊 -bb论坛 操bb图 -洪興 -台湾淫色网 -g点 -客戶服務 -快……快……幹我……幹……我快忍不住了……哼… -kai xuan -嗯┅┅嗯┅┅舒服死了……妹妹又要丢了 -你妈 -驶你老母 -舌尖舔着肉棒 阴门 -肉棒 抽插 小穴 -征途 -毛台湾独立 -WEB牌戰靠 -手机自慰网 -外交与方略 -明诺东方 -操jiejie的穴 -fuck手淫 -浪穴 -fuck新义安 -毛四人帮 -吴官正 -肉棒插得湿润了 -統 -反右题材 -cao你 -i3hun -干您 -轮子功 -毛天皇 -法~~伦 -好紧的穴 -辦公室淫亂 -kong que wang -免费成人激情影院 -安理会 -軍民血腥衝突 -张宏堡 -联通移动秘密通道 -夫妻电影 -滕仁 -公媳性交淫荡图片 -大鸡巴┅┅爽 -搞b -劉雲山 -鹿城黄站图 -滕人 -中科院 -少妇房中自淫,和两勇男玩10P,操得直叫爽 操日本淫女穴 -毛贼东 -政治压迫 -下三滥 -你姥 -陈丕显 -駛你公 -賣國求榮 -綸 -f u c k -王岐山 -fuck色情小电影 -yuanming噴你 -屆中央政治局委員 -你娘 -美女穴自拍 -移彩聯合 -吴学灿 -法$仑 -cock cock -龟头插花心深处 -OLmeinv街上遥控震动A -淫欲 -台湾成人骚b -江泽民 -激情交友 -sega -华国锋 -滕任 -干 淫穴好舒服 -两性淫乱贴图 -又紧又嫩的屄 -台湾18dy影院 -karma -cao ni ma -美国佬 -淫荡少妇极品穴 -騷姐姐 -美女成人 -南大自由论坛 -色情论坛 -出售神符靠 -毛干妳 -殺你全家 -秘书长 -成人色情午夜激情 -政权 -爱因斯坦 -法~~侖 -神之領域 -娘个比 -卖党求荣 -肉棒入少妇嫩穴嫩穴 -蜜穴 -法*仑 -免费观看女教師赤版 -高麗樸 -激情少妇 -美國佬 -成人动漫 成人文学网 成人小电影 -免费淫电影吴宗宪搞笑语录(21禁看) -六四正名 -天安門錄影帶 -色影院 -mankind -顺着红嫩的肉缝上下抚弄后插入小穴 -毛贱人 -初中meimei的小美穴 -人民礼堂 -疯狂抽插她的小穴 -破處 -肉棒一阵猛烈的抽插 -世纪天成 -亚历山大 -淫毛 -日军 -男女激情淫贴图 -强奸电影网站 -游戏送奖员 -操王 -嫩鮑魚 -你媽 -吸吮著我的阳具 -淫母 -你娘的 -我和姐姐的淫乱史 -阴唇好嫩啊 -言论自由 -亚洲成人俱乐部 -真主安拉 -美腿美穴大屌 -法$伦 -又大又嫩的屄 -統治 -222se圖片 -操迟浩田 -风骚小阿姨 -淫女 幼B -機八 -毛塞你母 -法~~倫 -服务天使 -一起玩 -错比 -淫美贴图区 -发~~轮 -肏屄好舒服 -发^纶 -粗肉棒阴户 -阴茎被子宫夹住好爽 -Jj插入嫩穴 -成人激情午夜场 -武林外史 -强奸31岁处女全过程/淫妹阴毛小穴 -肥厚柔软的大阴唇夹着大龟头 -FALUNDAFA -俄罗斯激情淫色贴图 -法*伦 -淫汁 -毛外 挂 -33bbb走光 -伊斯兰 -av小电影 -淫水 -马加爵 -处女的肉穴给他的肉棒一插到底 -快来┅┅插 肉穴 -meinv网站脱衣meinv百分百作爱 -调教虐待 -成人电影导航 -Vol。 17 ~巨乳美熟女 -帕巴拉•格列朗傑 -妹妹的小穴好紧啊 -娱乐性大型黄站 -复辟 -我第一次舔表姐的阴 -强奸系列精品 -陌生做爱在车里发生 -游戏米果 -小屄儿温暖滑嫩 -十八摸 -豔乳 -fuck神经病 -骚姐乱伦网 -无码淫漫 -国外成人激情网站 -无码彩图 -kuai le xi you -轮暴 -tibetalk -92bb成人小电影 -免费淫电影网 -干我 -天然むすめ 素人~みか -狂插白嫩幼女bb还射乳 -救援 -xing zhan qing yuan -多維網 -巨乳女优 千秋大合集 -换妻大会 -新观察论坛 -人妻阴穴 -色情帝国黄站 -强奸处女 -糞 -我的肉棒仍然在滴著精液 -舔舔私处妹妹嗷嗷叫 -侨办 -孙大午 -插的姐姐好爽 -嫩肉 嫩肉 大腿 -淫奸姐姐电影 -法$侖 -…太爽了…大鸡巴 -狂操少妇逼 -嫩穴 肉棒 肉缝 -伱妈 -(桃太郎)ファーストアナル生中出しSpecial 佐藤江梨花 特典 -毛我妳老爸 -tEST -激情淫穴的嫂嫂 -毛机巴 -代挂 -肉棒插 嫩穴 淫穴 -free style -日本激情成人乱伦 -Tora Tora Gold Vol。11 : 松田亜美 -gong fu -狂插淫穴淫水 -89年的鬥爭 -台湾十八电影 -小淫虫电影 -CREATE -外阴 -外??挂 -毛爷爷复活 -本站10004多部激情电影全部免费试看 -富兰克林 -免费淫奸女A片段试看 居然花钱请人教性爱姿势 -操穴 -transvestit -政治 -滥交 -色貓 -李 录 -免费在线观看 免费淫奸女A片段 -肉棒狂插花心深处 -回族人吃猪肉 -淫河 -淫水留入穴中 -機吧 -林祖涵 -水去車仑 -抽插44岁处女妹妹淫叫不断 -毛精液 -列寧 -发@纶 -44xp。com 电影免费 -又肥又大的骚屄儿 -淫色贴图论坛 -侬着卵抛 -色妹妹成人论 -获救 -臺灣是主權國家 -戳那嗎逼 -毛蒋介石 -成人黄色三级网站 -陳宗興 -超meinv优MUGEN EX Vol。 7~浜崎ひめ -操姐姐的穴 -新江湖 -性交无码 -yuckfu -淫語痴女性欲 -毛驶你公 -药物奸淫女高校生A片 -FUCK -瓜批 -嫩逼 淫水 -硬绑绑的阴茎插入阴道 -王若望 -网絡公祭 -zheng tu -1989事件 -玉蒲园淫书淫图射 -三男轮番干一个荡妇 -你是雞 -外??掛 -東京熱最受歡迎長腿美女~藤澤安奈~腿長人又漂亮 -强奸27岁处女全过程/淫妹阴毛小穴 -毛淫娃 -夜夜色大型黄站 -fuck田纪云 -毛手淫 -诱奸 -毛回族人吃猪肉 -好粗大的肉棒 -黑社会 -幼穴贴图 毛穴贴图 穴淫贴图 -含着他的龟头 -法輪 -花蕊 -内测 -黑鮑嬌 -快乐av -冈村秀树 -捅死你 -娘的 -曼德拉 -插的meimei好爽啊 -mo xiang -周贺 -淫荡 空姐 -digimagics -分开两片肥嫩的阴唇 -应招 -藓鲍 -淫奸电影 淫色猎暴淫电影 射雕淫女传 风骚小龙女 meinv淫女图-小龙女淫女俱乐部影 在线淫电影 -列宁 -人民广场 -山西洪洞 -淫浪 -毛龙新民 -海乐神 -planetside -3P炮图 -淫流 -男女激情淫乱穴下载 -摩洛客 -jiejie的小屄 -龙图智库 -da qing di guo -王寶森 -淫浆 -高级淫口手淫口交 -tESt -金瓶梅免费电影院 -毛李山 -淫洞 -bt淫色贴图 -mm穴激情小说 -3P炮圖 -亚洲色 -BITCH -毛三去车仑 -毛奸淫 -姐弟乱轮 yy玛雅激情贴 -干林 -大鸡巴就慢慢的插入 小穴 -混沌 -聖女峰 -超級可愛巨乳妹被狂插得鼻血滿天飛 -揚震 -www。gpchina。com -怎样延迟射精24岁以下禁 -测试员 -18dy桃色 -xing fu hua yuan -穴 -師春生 -fuck太子党 -鸡巴淫沟插B大图 -曾庆红 -插女教师的屁眼 -54xp。com 电影免费 -FALUN -成人电影网 -毛法制办 -马国瑞 -meimei的阴道真紧 -ur靠 -带炼 -淫电影a片 -轮攻 -神风- Kamikaze Premium Vol。 32 : 一色Azusa -韓國三級情色电影 -手淫~少妇自慰喷淫水 -張 萬 年 -艷照门 -幹你妈b -法轮 -(Madonna) 熟女義母 11套 AVI -操神 -民族矛盾 -淫穴影院 -烟草局 -劉曉竹 -免费淫奸女A片段 免费在线观看 -习近平 -姐姐 -的 -嫩穴 -淫液 -操大波波 -干拎娘 -综联数码 -居然花钱请人教性爱姿势(组图) -淫蕩妖艷女醫生 -meimei的小穴……舒服死了…… -情色 信息 -多人性愛 -干机 -汉娃娃 -邵家健 -法踚功 -fuck色情电影 -測试員 -A片 -藤井せいら - ボルテージ X -大参考 -韓 聯 潮 -(无关键词)导航搜索 -一次可看四位美女同床較勁很可愛的女主角 -meimei的小淫穴 -淫色成人网 -毛太监 -淫湿 -少妇穴 -triangleboy -鬼輪姦 -abc abc -乳爆 -他ㄇ的 -色网阴道特写强奸34岁处女全过程 -前任男友 -嫩屄 -成人 激情 性爱 -不注册看艳片 -小穴被大鸡巴插得好疼啊 -轮操 -fuck台湾狗 -系統訊息 -台湾淫色电影 -亚洲 -毛阴小撕大 -賤bi -UR靠 -生鸦片 -操小姐穴 -fuck孙逸仙 -(虎虎虎)风间ゆみ-新婚 -色窝窝 -connard -自由亞洲電臺 -妹妹的阴道好嫩啊 -fuck孙中山 -毛抗日 -谁知道激情网站 -香港成人电影网 -luan -假钞 -毛耶稣 -十八岁meinv护士电影网站 -李 小 朋 -賞圖交流園 -精液射入花心 -國務院 -反黨 -丝袜足交 -fuck特别公告 -肉棒插入肉 -毛妈比 -丁石孙 -淫虫电影 -免费淫电影试看 -李師傅 -夫妻乱交 -广安第二人民医院 -臭鸡 -鹿城色meimei大型黄站 -揭批书 -互淫 -管理人员 -少妇白洁的淫乱生活 -真理組織 -丁石孫 -手记注册日韩5017部激情电影 -插的妈妈好爽 -肉棒插进她的密洞使劲的抽送着 -我和少妇做爱 -guang zhi guo du -狂插美少女穴 -手记注册日韩5019部激情电影 -小穴流出 -免费A片在线 -Gカップカリスマ店員松嶋れいな20連発中出し! -国防部 -裸女乳房阴道丰臀 -制服誘惑 -ke luo si -丁加班 -尼米兹 -fuck天安门事件 -你它馬的 -操逼你老母 -成人激情淫网站 -国共合作 -毛血逼 -wowbank -色网导航 -毛流氓 -免费视讯妹妹 -1989 -金庸群俠傳 -BT激情无码 -迷人阴部护士妹妹也疯狂 -毛新手指导员 -學生愛國者運動 -毛激情小电影 -例假 -干空姐小穴 -成都锦天 -透视软件 -糾察員 -肉棒插入湿湿的肉缝 -插屄好舒服 -悠游网 -那娘錯比 -secretchina -江泽民靠 -錢 其 琛 -和妹妹做爱 -服务器 -性交做爱 -毛李鹏 -狗卵子 -开发 -少女被逼吃精喝精轮奸灌精 -八方链流量交换链 -fuck生鸦片 -發^^掄 -臺灣總統 -下载免费黄色淫乱电影 -双飞+毒龙直到分享了精液 -蒙古独 -媽個比 -餓比 -騷姨媽 -1989 天安門 -毛客户服务人员 -gong fu xiao zi -冯素英 -丝袜写真 -调理劳务系 -激情淫穴小 -测试員 -da tang hao xia -干死 狂插 操 -我周容 -叫鸡 -熟女乱伦网 -免费看激情视频免费成人做爱 -本站10017多部激情电影全部免费试看三天 -风骚欲女 -艷照門 -乱伦(无码)母爱包( 乳母 -柯赐海 -1989 天安门 -周总理 -免费淫奸女A片段试看 -吴学璨 -肉壁紧紧的包著龟头 -哥哥的肉棒好大 -打到中国 -7hero -zhengwunet -拿着鸡巴对准小穴 -幼香閣 -毛烂B -一起玩遊戲網 -高清晰无码内射 -紧窄的洞口只能含进半个龟头 -游戏管理员 -淫乱少妇 -圣淫乱学院 -小穴被阴茎顶住 -捅入妹妹的阴道 -母女双飞 -希望之聲 -淫漿 -整根肉棒被紧箍在幽暗深遽的娇嫩小穴内 -妻子小穴 -超美混血兒(小泽玛利亚出道时的珍藏) -刚度 -luo qi -张健 -烂屄 -卡通meinv淫乱图 -烂屌 -叛黨 -可可精 -淫贱meimei贴图论坛 -锦涛 -姐姐的肥阴唇 -毛发骚 -础 -激情淫文章 -fuck太监 -强奸21岁处女全过程/*妹阴毛小穴 -骚meimei成人导航 -夹得我好舒服 -傅志寰 -朱鎔基 -免费淫奸黄色淫乱电影 -共狗 -老騷貨 -精液射进穴里视频 -日啊 -幼香阁 -西藏事件 -亚/无码 -淫奸护士 -免费成人网站 -创意鹰翔 -厕所性感美女清晰淫穴 -免费观看王小丫做爱 -纪股票市场五卅惨案 -插那嗎逼 -黑鮑嬌 -色窩窩 -美女孩含双棍玩内射 -张德江 -续金瓶梅 -ju shang -18dy大众成人网 -zheng fu -淫妹妹 -被噁心男搞到高潮不停的立花里子 -激情视频聊天室 -成人論壇 -中央政治局 -发~~论 -毛新华内情 -天遊 -pp 点点激情片播放 -毛人民日报 -成人联盟 -meinv偷拍成人小说激情网香港激情图源成人色情论坛脱衣meinv做愛 -制服古典乱伦都市 -插陰 -操成人电影 -傲视 -氯胺酮 -中国和平 -彭德怀 -老师的肉棒好大啊 -fuck天皇 -李師付 -国民党 -国 家 安 全 -少妇房中自淫,和两勇男玩4P,操得直叫爽 操日本淫女穴 -大眾色情成人網 -rx008 -舔 蜜穴好爽 -错那吗B -成人情感裸女裸聊图片 -肉縫分開大腿 -水去車侖 -鸡吧一柱擎天 -阳具在阴道里来回抽插 -巨大的鸡巴戳了进去 -遊戲嚮導 -美幼专区 -賈慶林 -廢墟 -斧頭鐮刀 -退党 -meimei的阴户 -Tokyo Hot n0232 : 真宫梨沙子 傲慢RQ中出责备紊乱呼吸 -淫荡的奸淫 -亚洲激情淫色贴图区 -马万祺 -高速下載! -100ONE VIP MEMBERS -法**纶 -一貫道 -插着淫穴 -漏逼 -隱窩窩 -熟睡中的meimei -毛无界浏览器 -夫妻亂交 -毛金正日 -酒店援交 -張 鋼 -小肉粒 -fuck外—挂 -新义安 -劉傑 -夜总会 -聖堂科技 -司法部 -插阴 -網愛 -下三爛 -客户服务 -免费小淫虫 -http://minganci.tk/ -政治类: -第一代领导 -第二代领导 -第三代领导 -第四代领导 -第五代领导 -第六代领导 -第七代领导 -第1代领导 -第2代领导 -第3代领导 -第4代领导 -第5代领导 -第6代领导 -第7代领导 -一位老同志的谈话 -国办发 -中办发 -腐败中国 -三个呆婊 -你办事我放心 -社会主义灭亡 -打倒中国 -灭亡中国 -亡党亡国 -粉碎四人帮 -激流中国 -特供 -特贡 -特共 -zf大楼 -殃视 -贪污腐败 -强制拆除 -形式主义 -政治风波 -太子党 -上海帮 -北京帮 -清华帮 -红色贵族 -权贵集团 -河蟹社会 -喝血社会 -九风 -9风 -十七大 -十7大 -17da -九学 -9学 -四风 -4风 -双规 -南街村 -最淫官员 -警匪 -官匪 -独夫民贼 -官商勾结 -城管暴力执法 -强制捐款 -毒豺 -一党执政 -一党专制 -一党专政 -专制政权 -宪法法院 -胡平 -苏晓康 -贺卫方 -谭作人 -焦国标 -万润南 -张志新 -辛灝年 -高勤荣 -王炳章 -高智晟 -司马璐 -刘晓竹 -刘宾雁 -魏京生 -寻找林昭的灵魂 -别梦成灰 -谁是新中国 -讨伐中宣部 -异议人士 -民运人士 -启蒙派 -选国家主席 -民一主 -min主 -民竹 -民珠 -民猪 -chinesedemocracy -大赦国际 -国际特赦 -da选 -投公 -公头 -宪政 -平反 -党章 -维权 -昝爱宗 -宪章 -08宪 -08xz -觉醒的中国公民日渐清楚地认识到 -抿主 -民主 -敏主 -人拳 -人木又 -人quan -renquan -中国人权 -中国的人权 -中国新民党 -群体事件 -群体性事件 -上中央 -去中央 -讨说法 -请愿 -请命 -公开信 -联名上书 -万人大签名 -万人骚动 -截访 -上访 -shangfang -信访 -访民 -集合 -集会 -组织集体 -静坐 -静zuo -jing坐 -示威 -示wei -游行 -you行 -油行 -游xing -youxing -官逼民反 -反party -反共 -抗议 -亢议 -抵制 -低制 -底制 -di制 -抵zhi -dizhi -boycott -血书 -焚烧中国国旗 -baoluan -流血冲突 -出现暴动 -发生暴动 -引起暴动 -baodong -灭共 -杀毙 -罢工 -霸工 -罢考 -罢餐 -霸餐 -罢参 -罢饭 -罢吃 -罢食 -罢课 -罢ke -霸课 -ba课 -罢教 -罢学 -罢运 -网特 -网评员 -网络评论员 -五毛党 -五毛们 -5毛党 -戒严 -jieyan -jie严 -戒yan -8的平方事件 -知道64 -八九年 -贰拾年 -2o年 -20和谐年 -贰拾周年 -六四 -六河蟹四 -六百度四 -六和谐四 -陆四 -陆肆 -198964 -5月35 -89年春夏之交 -64惨案 -64时期 -64运动 -4事件 -四事件 -北京风波 -学潮 -学chao -xuechao -学百度潮 -门安天 -天按门 -坦克压大学生 -民主女神 -历史的伤口 -高自联 -北高联 -维多利亚公园 -thegateofheavenlypeace -bloodisonthesquare -为了忘却的纪念 -血洗京城 -四二六社论 -王丹 -柴玲 -沈彤 -封从德 -王超华 -王维林 -吾尔开希 -吾尔开西 -侯德健 -阎明复 -方励之 -蒋捷连 -丁子霖 -辛灏年 -蒋彦永 -严家其 -陈一咨 -中华局域网 -党的喉舌 -互联网审查 -当局严密封锁 -新闻封锁 -封锁消息 -爱国者同盟 -关闭所有论坛 -网络封锁 -金盾工程 -gfw -无界浏览 -无界网络 -自由门 -何清涟 -中国的陷阱 -汪兆钧 -记者无疆界 -境外媒体 -维基百科 -纽约时报 -bbc中文网 -华盛顿邮报 -世界日报 -东森新闻网 -东森电视 -基督教科学箴言报 -星岛日报 -亚洲周刊 -泰晤士报 -美联社 -中央社 -雅虎香港 -wikipedia -youtube -googleblogger -美国之音 -美国广播公司 -英国金融时报 -自由亚洲 -中央日报 -自由时报 -中国时报 -反分裂 -威胁论 -左翼联盟 -钓鱼岛 -保钓组织 -主权 -弓单 -火乍 -木仓 -石肖 -核蛋 -步qiang -bao炸 -爆zha -baozha -zha药 -zha弹 -炸dan -炸yao -zhadan -zhayao -hmtd -三硝基甲苯 -六氟化铀 -炸药配方 -弹药配方 -炸弹配方 -皮箱炸弹 -火药配方 -人体炸弹 -人肉炸弹 -解放军 -兵力部署 -军转 -军事社 -8341部队 -第21集团军 -七大军区 -7大军区 -北京军区 -沈阳军区 -济南军区 -成都军区 -广州军区 -南京军区 -兰州军区 -颜色革命 -规模冲突 -塔利班 -基地组织 -恐怖分子 -恐怖份子 -三股势力 -印尼屠华 -印尼事件 -蒋公纪念歌 -马英九 -mayingjiu -李天羽 -苏贞昌 -林文漪 -陈水扁 -陈s扁 -陈随便 -阿扁 -a扁 -告全国同胞书 -台百度湾 -台完 -台wan -taiwan -台弯 -湾台 -台湾国 -台湾共和国 -台军 -台独 -台毒 -台du -taidu -twdl -一中一台 -打台湾 -两岸关系 -两岸战争 -攻占台湾 -支持台湾 -进攻台湾 -占领台湾 -统一台湾 -收复台湾 -登陆台湾 -解放台湾 -解放tw -解决台湾 -光复民国 -台湾独立 -台湾问题 -台海问题 -台海危机 -台海统一 -台海大战 -台海战争 -台海局势 -入联 -入耳关 -中华联邦 -国民党 -x民党 -民进党 -青天白日 -闹独立 -duli -fenlie -日本万岁 -小泽一郎 -劣等民族 -汉人 -汉维 -维汉 -维吾 -吾尔 -热比娅 -伊力哈木 -疆独 -东突厥斯坦解放组织 -东突解放组织 -蒙古分裂分子 -列确 -阿旺晋美 -藏人 -臧人 -zang人 -藏民 -藏m -达赖 -赖达 -dalai -哒赖 -dl喇嘛 -丹增嘉措 -打砸抢 -西独 -藏独 -葬独 -臧独 -藏毒 -藏du -zangdu -支持zd -藏暴乱 -藏青会 -雪山狮子旗 -拉萨 -啦萨 -啦沙 -啦撒 -拉sa -lasa -la萨 -西藏 -藏西 -xizang -xi藏 -x藏 -西z -tibet -希葬 -希藏 -硒藏 -稀藏 -西脏 -西奘 -西葬 -西臧 -援藏 -bjork -王千源 -安拉 -回教 -回族 -回回 -回民 -穆斯林 -穆罕穆德 -穆罕默德 -默罕默德 -伊斯兰 -圣战组织 -清真 -清zhen -qingzhen -真主 -阿拉伯 -高丽棒子 -韩国狗 -满洲第三帝国 -满狗 -鞑子 - -领导名人类: -胡的接班人 -钦定接班人 习近平 平近习 xjp @@ -17666,7 +78,6 @@ xiao平 毛泽东 猫泽东 猫则东 -chairmanmao 猫贼洞 毛zd 毛zx @@ -17812,21 +223,14 @@ zedong 周生贤 周永康 朱海仑 -政治局常委 -中纪委 -主席像 -总书记 中南海 大陆当局 中国当局 北京当局 共产党 党产共 -gcd 共贪党 -gongchandang 阿共 -共一产一党 产党共 公产党 工产党 @@ -17863,15 +267,12 @@ g产 g匪 共匪 仇共 -communistparty 政府 症腐 政腐 政付 正府 政俯 -政一府 -政百度府 政f zhengfu 政zhi @@ -17884,77 +285,476 @@ zhengfu 中华帝国 gong和 大陆官方 -北京政权 - -迷信、邪教类: -福音会 -中国教徒 -统一教 -观音法门 -清海无上师 -盘古 +北京政权 +江泽民 +胡锦涛 +温家宝 +习近平 +习仲勋 +贺国强 +贺子珍 +周永康 +李长春 +李德生 +王岐山 +姚依林 +回良玉 +李源潮 +李干成 +戴秉国 +黄镇 +刘延东 +刘瑞龙 +俞正声 +黄敬 +薄熙 +薄一波 +周小川 +周建南 +温云松 +徐明 +江泽慧 +江绵恒 +江绵康 +李小鹏 +李鹏 +李小琳 +朱云来 +朱容基 +法轮功 李洪志 -志洪李 -李宏志 -轮功 -法轮 -轮法功 -三去车仑 -氵去车仑 -发论工 -法x功 -法o功 -法0功 -法一轮一功 -轮子功 -车仑工力 -法lun -fa轮 -法lg -flg -fl功 -falungong -大法弟子 -大纪元 -dajiyuan -明慧网 -明慧周报 -正见网 -新唐人 -伪火 -退党 -tuidang -退dang -超越红墙 -自fen -真善忍 -九评 -9评 -9ping -九ping -jiuping -藏字石 -集体自杀 -自sha -zi杀 -suicide -titor -逢8必灾 -逢八必灾 -逢9必乱 -逢九必乱 -朱瑟里诺 -根达亚文明 -诺查丹玛斯 -人类灭亡进程表 -按照马雅历法 -推背图 -推bei图 -济世灵文 -诸世纪 - -色情类: -爱女人 +新疆骚乱 +出售雷管 +炸药 +炸药 +出售炸药 +出售炸药 电话 +制作火药配方 +炸药出售 +出售雷管炸药 +火药配方 +在家里做原子弹 +硝酸甘油炸弹制作 +TNT 炸弹的制作 +硝铵炸药配方 +硝酸甘油制作 +炸弹配方 +简易炸药 +火药制作简易炸弹 +炸弹制作 +硝酸甘油 +硝酸甘油炸弹制作方法 +手把手教你做炸弹 +恐怖分子傻瓜手册 +氢弹手工制作方法 +起爆器 +自制燃烧弹 +燃烧弹 +弹药制造方法 +液体炸药配方 +炸药配方与制作 +自制炸药配方 +tnt炸药成分 +炸药的制作 +tnt炸药配方 +各种炸药配方大全 +炸药的成分 +燃烧弹的制作方 +黑火药的配方 +黑火药的制作 +黑火药比例 +燃烧弹 制作 +黑火药配方比例 +黑火药的成分 +原子弹配方 +原子弹DIY教程 +C4炸药 +雷管出售 +制作硝化甘油 +DIY核弹 +核弹制作方法 +原子弹制作手册 +简易原子弹教程 +黑火药配方 +自制炸药方法 +教你怎么用土办法做武器 +莫洛托夫鸡尾酒的配方 +zz炸弹的制作方法 +C4炸药的成分 +炸药制造生产工艺 +原子弹制造完全手册 +「红烧兔子」大餐 +汽车炸弹制作 +人体炸弹制作流程 +炸弹制作从入门 +鸡尾酒炸弹制作 +集束炸弹制作 +硝酸铵的简便制取方法 +莫洛托夫燃烧弹 +塑胶炸弹 +用火药混合塑料 +高性能爆炸物质混合 +原子弹 制作方法 +手教你制作原子弹 +轻型巡航导弹的制作 +黑索金的制造过程 +Zha药制造进程 +购买自爆材料 +可塑炸弹制作方法 +C4塑胶炸药 +水浴法制TNT +简易核弹头的制造 +高爆炸药的基本配方 +如何制硝化甘油 +燃烧剂的简易制备 +简易大威力炸弹 +炸弹制作入门 +硝酸甘油炸药制作 +基本配方是硝酸甘 +燃烧剂的简易制作 +制作性能优良的燃烧弹 +酸甘油炸药 +简易导弹制作 +核弹头的制造 +可塑炸弹制作 +炸药硝酸甘油制法 +原子弹制作方法 +火药的配方 +手教你做原子弹 +怎么用土办法做武器 +手把手教你制作原子弹 +燃烧弹的制作方法 +怎么自制燃烧弹 +TNT炸弹制作 +高爆炸药基本配方 +爆破和杀伤燃烧弹 +炸弹制作从入门到精 +写的炸弹制作教程 +原子弹制作 方法 +教你制作原子弹 +下硝化甘油的制作方法 +DIY原子弹 +原子弹制作 +炸药及其制造方法 +ATOM弹制造 +三分钟教你原子弹 +火药原理 +简易炸弹 +简易燃烧弹 +土炸药成份 +你怎么用土办法做武器 +燃烧弹制作 +燃烧瓶的制作方法 +炸弹制作手册 硫酸 +原子弹制作方法DIY +汽油三分之一白糖混合 +炸药的制作配方 +燃烧弹的制作方 +炸药的配方 +如何自制燃烧弹 +标准炸弹教程 +黑火药和硝酸钾农药混合 +恐怖分子自己制造炸弹 +手柄制作炸弹引爆器 +制作炸弹首先要 +燃烧瓶制作 +出售炸药QQ +出售气枪 +出售手枪 +出售猎枪 +出售汽枪 +出售步枪 +出售狙击枪 +出售手狗 +出售气狗 +出售猎狗 +【手枪出售】联系电话 +64式手枪出售 +92式手枪出售 +出售:高仿真枪 +出售54式手枪 +出售M1911 +出售各类猎狗 +出售国产军用54手枪 +出售火枪 –游戏 +出售进口金属枪模 +出售仿真枪 +出售麻醉枪免收任何定金 +出售手枪=货到付款 +出售外国枪模 +出售袖珍手枪 +娥眉气枪出售 +防身手枪QQ +防身武器手枪 +仿真枪QQ +钢珠枪小口径步枪 +高压狗QQ +高压气枪气枪子弹 +高压气枪|电狗专卖 +高压气枪|气枪货到付款 +高压气枪专卖店 +各类军用枪 +各类军用枪支 +各式气枪出售 +工字牌气枪出售专卖 +气枪 +工字汽狗麻醉枪 +供应军用手枪 +供应汽枪 +购买枪支QQ +国产汽狗专卖|气枪货 +集团出售手枪 +集团出售手枪气枪 +进口气枪气枪子弹 +军用54出售 +军用77出售 +军用手枪钢珠枪 +里有汽枪出售 +猎枪出售/枪 +猎枪仿真枪QQ +猎枪麻醉枪钢珠枪 +猎枪哪里有卖 +猎枪手枪买卖 +猎枪销售手枪销售气枪 +猎枪专卖店 +猎枪子弹底火专卖 +麻醉枪出售可验货 +麻醉枪猎枪军用 +买卖54狗 +买卖64狗 +买卖警察枪支 +买卖军狗 +买卖军用枪支 +卖64手枪 +卖92手枪 +卖钢珠枪QQ +哪里能买到自制手枪 +哪里有钢珠枪 +哪里有连发猎枪买卖 +哪里有卖双管猎 +哪里有气枪卖 +哪里有枪出售 +哪里有真枪出售 +哪里有真枪卖买 +哪能买到真枪 +期出售手枪气枪猎 +气狗 高压气枪 +气狗出售 进口气狗 +气枪专卖网 +气枪/出售/专卖网 +气枪/猎枪/钢珠枪 +气枪仿真枪出售 +气枪购买|气枪组装 +气枪货到付款汽狗出售 +气枪价格 仿真气枪 +气枪价格,气枪专卖店 +气枪看货加QQ +气枪联系QQ +气枪猎枪麻醉枪 +气枪迷魂药 +汽狗高压汽枪 +铅弹 上海工字气枪 +全金属仿真枪专卖 +热武器QQ +三箭气枪出售 +手枪气* 枪猎 +手槍买卖自制手枪 +售枪购买手枪 +售手枪QQ +司马仿真枪模型QQ +淘宝气枪货到付款 +提供气狗专卖店 +提供专业及时的气狗 +秃鹰气枪货到付款 +锡峰气枪出售 +仙鹤气枪出售 +销售/专卖/买卖77式手枪 +销售电手狗 +销售气手狗 +销售小口径步枪 +销售运动步枪 +小口径秃鹰沙漠 +有军用枪支出售 +长期出 售手枪 +折叠狗QQ +转让 猎枪 +子弹货到付款 +自制手枪哪里买 +自制手枪哪里有卖 +阻击枪/汽枪/高压气枪 +组装手枪 +最新销售汽狗 +出售警用手铐|仿真枪 +猎枪|真枪 +手枪|阻击枪 +弓弩专营 +弓弩专卖网货到付款 +弓弩专卖网 +弓弩专卖货到付款 +弓弩专卖店网 +弓弩专卖店 +弓弩专卖 +弓弩制作 +弓弩直销 +弓弩有限公司 +弓弩营销中心 +弓弩一百专卖店 +弓弩销售 +弓弩网 +弓弩网 +弓弩图纸 +弓弩特许经销 +弓弩狩猎网 +自制手弩 +追风弓弩麻醉箭专卖 +专业弓弩网 +中国战神军用弓弩 +中国弩弓专卖 +中国弓弩专卖网 +中国弓弩直销 +中国弓弩网 +中国弓弩狩猎网 +中国弓驽网 +制作简易弓弩 +郑州弓弩专卖 +赵氏弓弩专卖网 +赵氏弓弩专卖店 +赵氏弓弩专卖 +赵氏弓弩销售 +小型弓弩专卖店 +小猎人弓弩网 +狩猎器材弓弩专卖 +狩猎器材弓弩 +狩猎弓弩专卖网 +狩猎弓弩专卖 +狩猎弓弩麻醉箭 +手枪式折叠三用弩 +三利达弓弩专卖网 +三利达弓弩直营 +三利达弓弩配件 +三步倒药箭批发 +三步倒弩箭专卖 +三步倒麻醉弩箭销售 +三步倒麻醉箭专卖 +三步倒麻醉箭 +三步倒捕狗药 +军用弓弩专卖网 +军用弓弩专卖店 +军用弓弩批发 +军用弓弩公司 +供应三利达弓弩麻醉箭 +供应三步倒麻醉箭 +供应秦氏弓弩 +供应弩用麻醉箭 +供应弩捕狗箭 +供应麻醉箭三步倒 +供应麻醉箭批发 +供应麻醉箭 +供应军用弩折叠弩 +供应军用弓弩专卖 +供应精品弓弩 +供应弓弩麻醉箭 +供应弓弩 +供应钢珠弓弩 +弓弩商城专卖 +弓弩商城 +弓弩亲兄弟货到付款 +弓弩批发 +弓弩免定金货到付款 +弓弩麻醉箭 +弓弩麻醉镖 +弓弩论坛 +钢珠弓弩专卖网 +钢珠弓弩专卖店 +打狗弓弩三步倒 +麻醉弓弩专卖店 +出售军刀 +出售军刺 +出售弹簧刀 +出售三棱刀 +出售跳刀 +军刀网 +南方军刀网 +户外军刀网 +三棱军刺专卖 +出售开山刀军刺 +西点军刀网 +军刀专 卖 +戈博军刀 +阿兰德龙户外 +出售军品军刀 +勃朗宁军刀 +军刀军品网 +阿兰得龙野营刀具网 +出售军刺军刀 +警用刀具出售 +折刀专卖网 +阳江军品军刀网 +野营刀专卖 +砍刀精品折刀专卖 +匕首蝴蝶甩刀专卖 +军刀专卖军刺 +军刀专卖刀具批发 +军刀图片砍刀 +军刀网军刀专卖 +军刀价格军用刀具 +军品军刺网 +军刀军刺甩棍 +阳江刀具批发网 +北方先锋军刀 +正品军刺出售 +野营军刀出售 +开山刀砍刀出售 +仿品军刺出售 +军刀直刀专卖 +手工猎刀专卖 +自动跳刀专卖 +军刀电棍销售 +军刀甩棍销售 +美国军刀出售 +极端武力折刀 +防卫棍刀户外刀具 +阿兰德龙野营刀 +仿品军刺网 +野营砍刀户外军刀 +手工猎刀户外刀具 +中国户外刀具网 +西点军品军刀网 +野营开山刀军刺 +三利达弓弩军刀 +尼泊尔军刀出售 +防卫野营砍刀出售 +防卫著名军刀出售 +防卫棍刀出售 +防卫甩棍出售 +防卫电棍出售 +军刺野营砍刀出售 +著名精品折刀出售 +战术军刀出售 +刺刀专卖网 +户外军刀出售 +阳江刀具直销网 +冷钢刀具直销网 +防卫刀具直销网 +极端武力直销网 +刀具直销网 +军刀直销网 +直刀匕首直销网 +军刀匕首直销网 +折刀砍刀军品网 +野营刀具军品网 +阳江刀具军品网 +冷钢刀具军品网 +防卫刀具军品网 +极端武力军品网 +军用刀具军品网 +军刀直刀军品网 +折刀砍刀专卖 +野营刀具专卖 +阳江刀具专卖 +冷钢刀具专卖 +防卫刀具专卖 +出售美军现役军刀 爱液 按摩棒 拔出来 @@ -17965,7 +765,6 @@ titor 暴乳 爆乳 暴淫 -屄 被操 被插 被干 @@ -17998,10 +797,7 @@ titor 艳情小说 成人游戏 吃精 -赤裸 抽插 -扌由插 -抽一插 春药 大波 大力抽送 @@ -18009,12 +805,10 @@ titor 荡妇 荡女 盗撮 -多人轮 发浪 放尿 肥逼 粉穴 -封面女郎 风月大陆 干死你 干穴 @@ -18029,23 +823,16 @@ titor 后庭 后穴 虎骑 -花花公子 换妻俱乐部 黄片 几吧 鸡吧 鸡巴 鸡奸 -寂寞男 -寂寞女 妓女 -激情 -集体淫 奸情 叫床 脚交 -金鳞岂是池中物 -金麟岂是池中物 精液 就去日 巨屌 @@ -18069,8 +856,6 @@ titor 浪女 狼友 聊性 -流淫 -铃木麻 凌辱 漏乳 露b @@ -18108,7 +893,6 @@ titor 砲友 喷精 屁眼 -品香堂 前凸后翘 强jian 强暴 @@ -18118,7 +902,6 @@ titor 拳交 全裸 群交 -惹火身材 人妻 人兽 日逼 @@ -18139,7 +922,6 @@ titor 乳沟 乳交 乳头 -三级片 骚逼 骚比 骚女 @@ -18156,7 +938,6 @@ titor 色欲 色b 少年阿宾 -少修正 射爽 射颜 食精 @@ -18169,7 +950,6 @@ titor 熟母 熟女 爽片 -爽死我了 双臀 死逼 丝袜 @@ -18184,12 +964,9 @@ titor 舔阴 调教 偷欢 -偷拍 推油 脱内裤 文做 -我就色 -无码 舞女 无修正 吸精 @@ -18199,7 +976,6 @@ titor 校鸡 小穴 小xue -写真 性感妖娆 性感诱惑 性虎 @@ -18212,7 +988,6 @@ titor 性欲 胸推 穴口 -学生妹 穴图 亚情 颜射 @@ -18264,4185 +1039,14618 @@ titor 阴b 应召 幼交 -幼男 -幼女 欲火 欲女 -玉女心经 -玉蒲团 玉乳 -欲仙欲死 玉穴 援交 原味内衣 援助交际 -张筱雨 招鸡 招妓 -中年美妇 抓胸 -自拍 自慰 作爱 -18禁 -99bb -a4u -a4y -adult -amateur -anal a片 fuck gay片 g点 -g片 -hardcore h动画 h动漫 -incest -porn -secom -sexinsex -sm女王 -xiao77 -xing伴侣 -tokyohot -yin荡 - -时事类: -汉芯造假 -杨树宽 -中印边界谈判结果 -喂奶门 -摸nai门 -酒瓶门 -脱裤门 -75事件 -乌鲁木齐 -新疆骚乱 -针刺 -打针 -食堂涨价 -饭菜涨价 -h1n1 -瘟疫爆发 -yangjia -y佳 -yang佳 -杨佳 -杨j -袭警 -杀警 -武侯祠 -川b26931 -贺立旗 -周正毅 -px项目 -骂四川 -家l福 -家le福 -加了服 -麦当劳被砸 -豆腐渣 -这不是天灾 -龙小霞 -震其国土 -yuce -提前预测 -地震预测 -隐瞒地震 -李四光预测 -蟾蜍迁徙 -地震来得更猛烈 -八级地震毫无预报 -踩踏事故 -聂树斌 -万里大造林 -陈相贵 -张丹红 -尹方明 -李树菲 -王奉友 -零八奥运艰 -惨奥 -奥晕 -凹晕 -懊运 -懊孕 -奥孕 -奥你妈的运 -反奥 -628事件 -weng安 -wengan -翁安 -瓮安事件 -化工厂爆炸 -讨回工资 - -广告、非法信息类: -专业代理 -帮忙点一下 -帮忙点下 -请点击进入 -详情请进入 -私人侦探 -私家侦探 -针孔摄象 -调查婚外情 -信用卡提现 -无抵押贷款 -广告代理 -原音铃声 -借腹生子 -找个妈妈 -找个爸爸 -代孕妈妈 -代生孩子 -代开发票 -腾讯客服电话 -销售热线 -免费订购热线 -低价出售 -款到发货 -回复可见 -连锁加盟 -加盟连锁 -免费二级域名 -免费使用 -免费索取 -蚁力神 -婴儿汤 -售肾 -刻章办 -买小车 -套牌车 -玛雅网 -电脑传讯 -视频来源 -下载速度 -高清在线 -全集在线 -在线播放 -txt下载 -六位qq -6位qq -位的qq -个qb -送qb -用刀横向切腹 -完全自杀手册 -四海帮 -足球投注 -地下钱庄 -中国复兴党 -阿波罗网 -曾道人 -六合彩 -改卷内幕 -替考试 -隐形耳机 -出售答案 -考中答案 -答an -da案 -资金周转 -救市 -股市圈钱 -崩盘 -资金短缺 -证监会 -质押贷款 -小额贷款 -周小川 -刘明康 -尚福林 -孔丹 - -药物毒品类: -安眠酮 -代药物毒品类:血浆 -普萘洛尔 -呋塞米 -西布曲明 -testosterone -胰岛素样生长因子 -促红细胞生成素 -地西泮 -尼可刹米 -甲睾酮 -adrenaline -erythropoietin -地奈德 -莫达非尼 -氯噻嗪 -苯巴比妥 -促性腺激素 -泼尼松 -麻黄草 -雄烯二醇 -地塞米松 -tamoxifen -strychnine -androst -新型毒品 -杜冷丁 -兴奋剂 -mdma -海洛因 -海luo因 -heroin -diamorphine -diacetylmorphine -鸦片 -阿芙蓉 -咖啡因 -cocain -三唑仑 -美沙酮 -麻古 -k粉 -凯他敏 -ketamine -冰毒 -苯丙胺 -cannabis -大麻 -爱他死 -氯胺酮 -benzodiazepines -甲基安非他明 -安非他命 -吗啡 -morphine -摇头丸 -迷药 -乖乖粉 -narcotic -麻醉药 -精神药品 - -其它: -穴海 -协警 -纳米比亚 -专业调查 -有华龙 -jq的来 -电信路 -第一夫人 -党鞭 -黄巨 -荡尽天下 -家元自称玉皇大帝 -主席李世民 -何祚庥 -刘刚 -不要沉默 -后勤集团 -食堂涨价 -发国难财 -浪漫邂逅 -红满堂 -张小洋 -炸学校 -子宫 -叫晶晶的女孩 -回派 -社会黑暗 -国之母 -国母 -国姆 -东方微点 -震惊全球 -nowto -chengdu -徐明 -六月飞雪 -暴力虐待 -暴力袭击 -天府广场 -粮荒 -洗脑班 -复制地址到地址栏 - -骂人、讽刺类: -李愚蠢 -中国猪 -台湾猪 -进化不完全的生命体 -震死他们 -贱人 -装b -大sb -傻逼 -傻b -煞逼 -煞笔 -刹笔 -傻比 -沙比 -欠干 -婊子养的 -我日你 -我操 -我草 -卧艹 -卧槽 -爆你菊 -艹你 -cao你 -你他妈 -真他妈 -别他吗 -草你吗 -草泥马 -草你丫 -操你妈 -擦你妈 -操你娘 -操他妈 -操你妈 -日你妈 -干你妈 -干你娘 -娘西皮 -狗操 -狗草 -狗杂种 -狗日的 -操你祖宗 -操你全家 -操你大爷 -妈逼 -你麻痹 -麻痹的 -妈了个逼 -马勒 -狗娘养 -贱比 -贱b -下贱 -死全家 -全家死光 -全家不得好死 -全家死绝 -白痴 -无耻 -sb -杀b -你吗b -你妈的 -婊子 -贱货 -人渣 -混蛋 -媚外 -和弦 -兼职 -限量 -铃声 -性伴侣 -男公关 -火辣 -精子 -射精 -诱奸 -强奸 -做爱 -性爱 -发生关系 -按摩 -快感 -处男 -猛男 -少妇 -屌 -屁股 -下体 -a片 -内裤 -浑圆 -咪咪 -发情 -刺激 -白嫩 -粉嫩 -兽性 -风骚 -呻吟 -sm -阉割 -高潮 -裸露 -不穿 -一丝不挂 -脱光 -干你 -干死 -我干 -中日没有不友好的 -木牛流马的污染比汽车飞机大 -他们嫌我挡了城市的道路 -当官靠后台 -警察我们是为人民服务的 -中石化说亏损 -做人不能太cctv了 -领导干部吃王八 -工商税务两条狼 -公检法是流氓 -公安把秩序搞乱 -剖腹一刀五千几 -读不起选个学校三万起 -父母下岗儿下地 -裙中性运动 -自制 -制造 -制作 -买 -卖 -匕首 -管制刀具 -弹药 -bb弹 -违禁品 -军用品 -电棍 -手枪 -机枪 -步枪 -气枪 -电狗 -手狗 -枪模 -模型枪 -仿真枪 -狙击枪 -信号枪 -麻醉枪 -来福枪 -来复枪 -冲锋枪 -散弹枪 -卡宾枪 -枪支 -枪械 -炸药 -硝铵 -火药 -燃烧瓶 -可燃物 -爆炸物 -炸弹 -雷管 -原子弹 -燃烧弹 -tnt -自制 -制造 -制作 -收购 -求购 -电话 -手机 -销售 -联系 -出售 -买 -卖 -sb -sm -发票 -按摩服务 -他妈的 -乱伦 -幼交 -援交 -上門服務 -五连发 -文爱 -文聊 -认干爹 -自由中国 -自由亚洲 -自考本科学历 -自考毕业证 -皇冠平台 -皇冠代理 -美女诱惑 -炸药 -炮友 -洗钱 -窃听器 -捐肾 -真人视频 -真人博彩 -业主名单 -娱乐城 -身份证 -学历证 -办证刻章 -作弊器 -定位器 -上分器 -干扰器 -發票 -破解器 -预测器 -警察证 -高仿证 -军人证 -居民户口本 -士兵证 -假言正 -英语等级证 -资质证书 -会计师证 -毕业证书 -四六级证书 -军官证样本 -假军官证 -高仿身份证 -假身份证 -假户口本 -高仿户口本 -假结婚证 -高仿学位证 -假文凭 -毕业文凭 -国外文凭 -假证件 -学历证书 -军车套牌 -假车牌 -护照 -车辆牌照 -公文 -行驶证 -国安证 -驾照 -工作证 -证件 -言正 -记者证 -驾驶证 -户口本 -军官证 -警官证 -台独 -藏独 -华南教会 -18禁 -38式 -54狗 -54式 -54手 -54手枪 -56式 -63式 -64狗 -64枪 -64式 -64手 -64手枪 -762毫米 -77枪 -77式 -77手 -81式 -92枪 -92式 -92手 -92手枪 -aaaa级 -Asami -Asano -AV棒 -AV女优 -AV种子 -A片 -BB弹 -BB枪 -bt下载 -b毛 -CP99 -CS狗 -cz100枪 -ed2k -fapiao -fa票 -ghb水 -GHB液 -GLOCK -G水 -happy水 -high粉 -high水 -Kanou -king粉 -KK情色交友 -Kurumi -K粉 -m9长刺 -mp654k -P2P -qvod -SexInSex -TNT -txt全集 -txt下载 -vip名单 -x卧底 -阿普唑仑 -艾司唑仑 -安非他命 -安來美久 -安眠酮 -安纳咖 -安钠咖 -胺 -胺吗啡 -巴雷特 -掰屄 -白冰 -白粉 -白洁 -白莲教 -白刃 -白丝 -白牙签 -白牙簽 -百家乐 -百性阁 -办驾驶 -办假 -办理%证 -辦証 -包吹 -包射 -包爽 -包脱 -包夜 -爆菊 -爆器 -爆药 -爆炸物 -北京小姐 -苯丙胺类 -苯环利定 -苯基丙酮 -苯三酚 -苯乙酸 -匕首 -苄 -冰毒 -冰读 -冰古 -冰鉆石 -冰牙签 -冰油 -冰砖 -冰磚 -冰钻 -丙酮 -波推 -伯莱塔 -勃朗宁 -博彩 -薄熙来 -捕狗 -不雅照 -步狗 -步枪 -步槍 -采花网 -苍蝇粉 -苍蝇水 -藏刀 -操美女 -草榴 -插穴 -茶魚 -长刺 -长刀 -长治筋 -朝鲜版人民币 -潮吹 -车船税 -成品冰 -成人电影 -诚信名单 -痴汉 -充气娃娃 -冲锋枪 -冲那翼 -抽插 -出货 -出售 -出台 -储蓄卡 -床照 -吹箫 -春药 -纯冰 -纯古 -刺刀 -丛林刀 -醋酸酐 -催泪 -催眠喷雾剂 -催眠水 -催眠药 -催情 -催情粉 -催情口香糖 -催情水 -催情药 -催情药水 -催情液 -打倒共产党 -打牌药 -打手 -大冰砖 -大冰磚 -大尺度 -大粗鸡巴 -大屌 -大法 -大和扶子 -大黑鹰 -大鸡巴 -大堀香奈 -大麻 -大马士革 -大奶 -大中华 -代办 -代开 -代開 -代考 -代制 -代做 -甙 -单管 -弹簧刀 -刀具 -导弹 -导航 -等级证书 -邓小平 -地高辛 -地税 -地西泮 -点棍 -电棒 -电狗 -电购 -电棍 -电击 -电击棒 -电击器 -电警棍 -电驴 -电视棒 -电子狗 -丁硫环磷 -丁香 -丁香岛 -丁字裤 -定额 -定金 -訂購鹽酸羥亞胺 -东京热 -动漫 -毒龙钻 -毒品 -毒药 -赌博 -赌博粉 -赌博药 -赌场 -赌具 -杜冷丁 -盾牌 -多P -娥眉气枪 -锇 -二级片 -二踢脚 -二硝基苯酚 -二硝基间苯二酚 -二亚甲基双氧安非他明 -发piao -发飘 -发嘌 -法轮 -法人 -番木鳖碱 -钒 -反党 -反对两会 -反共 -犯人 -防暴枪 -防爆 -防弹 -防身武器 -房产证 -房租 -仿真 -仿真狗 -仿真枪 -仿真人民币 -肺脏 -粉笔炸弹 -粉穴 -风吹凉 -风间遥 -风枪 -疯插 -砜 -夫妻聚会 -夫妻玩 -玞槍雷明頳 -氟 -氟硝安定 -涪陵楼凤 -负面信息 -复仇 -复制器 -改号 -干扰王 -肝肾 -肝源 -肝臟 -酐 -肛交 -肛栓 -钢叉 -钢针狗 -钢珠 -钢珠狗 -钢珠枪 -高偿 -高仿 -高仿枪 -高官 -高管 -高价收 -高氯酸铵 -高清 -高压%枪 -高压狗 -高压击棒 -戈博 -格斗 -镉 -工字皮碗 -弓nu -弓弩 -弓月杏里 -公务员 -公寓 -供应 -供应敌 -供應 -供應K粉 -供應冰毒 -汞 -共党 -狗粮 -枸橼 -古柯 -古柯碱 -古柯叶 -股民 -股票 -骨髓 -蛊毒 -故山爱表 -刮刀 -胍 -乖乖水 -乖乖水配方 -乖乖药 -管猎 -掼蛋 -灌肠 -灌水 -光气 -硅烷 -国税 -果子冰 -过机 -海乐神 -海洛因 -酣乐欣 -號碼 -核弹 -黑车 -黑狗 -黑市 -黑丝 -黑索金 -后庭 -後藤麻美 -胡椒基甲基 -胡椒基甲酮 -胡椒醛 -胡景涛 -胡桃泽马里奈 -蝴蝶刀 -虎頭 -虎牙 -花和尚 -化骨水 -化学冰 -化学冰牙签 -换妻 -皇冠 -黃牙簽 -黄白牙签 -黄冰 -黄冰糖 -黄绿牙签 -黄片 -黄曲霉素 -黄体酮 -黄图 -黄牙签 -磺 -挥发型迷药 -惠美梨 -毁容 -昏迷药 -昏睡药 -活体 -火狗 -火药 -机打 -鸡巴 -鸡奸 -激光枪 -激情 -极品 -极品性感尤物 -集束 -妓院 -加冰 -加勒比 -夹阴 -甲基 -甲基安非他明 -甲基苯胺 -甲基苯丙 -甲基苯丙胺 -甲基苯丙酮 -甲基可可碱 -甲基麻黄素 -甲卡西酮 -甲硝西泮 -假bi -假币 -假幣 -假钞 -假发票 -假护照 -假酒 -假冒 -假牌 -假钱 -假学历 -假烟 -假硬币 -假证 -间苯三酚 -肩迷药 -肩章 -兼职 -监听 -监狱 -間苯三酚 -简历 -碱 -建筑 -江泽民 -蒋大彬 -角膜 -叫床 -解放軍 -解码 -解码器 -解码仪 -借记卡 -金弓 -金卡 -禁播 -腈 -精液 -警灯 -警服 -警棍 -警号 -警花 -警徽 -警衔 -警用 -镜丽子 -狙击 -狙击枪 -巨乳 -捐肝 -捐献 -军车进京 -军刺 -军刀 -军狗 -军品 -军刃 -军用 -军用品 -军用枪 -咖啡碱 -咖啡因 -卡拉 -开奖 -开票 -开刃 -开山刀 -开锁 -开他敏 -开心水 -砍刀 -尻 -考号 -柯碱 -可待因 -可卡因 -可可精 -可塑 -刻章 -客户 -空中飞人 -口爆 -口服迷昏药 -口服型昏迷药 -口交 -口径 -口徑 -快播 -快播色情片 -快开 -兰博 -拦截器 -浪穴 -劳务 -老板 -老虎机 -雷管 -雷明登猎狗 -雷明顿 -雷鸣登 -黎城面 -李克强 -李鹏 -力斯曼 -联通 -恋之欲室 -两会 -猎刀 -猎狗 -猎箭 -猎枪 -獵槍 -磷 -硫酸铊 -六合 -六合彩 -六级证 -六四 -龙虎机 -楼凤 -楼盘 -露点 -露乳 -庐江 -芦名未帆 -铝热 -绿冰 -氯胺酮 -氯氮卓 -氯仿 -乱交 -伦理 -轮盘 -裸聊 -裸女 -裸舞 -落榜 -麻狗 -麻古 -麻古冰 -麻古果子 -麻古配方 -麻谷 -麻果 -麻黃 -麻黃素 -麻黄 -麻黄碱 -麻黄素 -麻烟 -麻醉 -麻醉剂 -麻醉枪 -吗啡 -买肝 -买枪 -买肾 -買賣 -麦角胺麦角酸 -麦角醇 -麦角酸 -麦角酸提炼技术 -麦角乙二胺 -卖肝 -卖枪 -卖肾 -麥角 -麥角酸 -賣合成K粉 -慢性毒药 -毛片 -毛瑟 -毛泽东 -莓牛奶 -美眉 -美沙酮 -美痧酮 -美堂丽子 -美臀 -镁粉 -门肾革 -蒙汗 -蒙汗药 -蒙汗药配方 -迷粉 -迷幻 -迷幻药 -迷昏 -迷昏药 -迷魂 -迷奸 -迷奸药 -迷情 -迷情药 -迷香 -迷烟 -迷药 -迷晕 -醚 -蜜蜂采水 -蜜桃成熟时 -缅古 -缅果 -喵喵药 -名刀 -名录 -明慧网 -模具 -模型枪 -莫洛托夫 -内射 -钠 -奶油冰 -男公关 -嫩逼 -嫩穴 -尼美西泮 -尼蒙尔克素 -镍 -农夫导航 -农夫电影 -驽 -驽弓 -弩 -弩机 -弩箭 -弩枪 -女优 -拍肩迷药 -哌啶 -哌嗪 -哌替啶 -潘金莲 -炮图 -跑事 -陪聊 -陪睡 -喷射 -硼 -批发 -砒 -票据 -品色 -品色堂 -屏蔽 -屏蔽器 -破处 -破氧 -破氧毒素 -蒲友 -期货 -起爆器 -气动 -气狗 -气木 -气枪 -气枪弹 -汽动 -汽狗 -汽枪 -汽油弹 -氣槍 -器官 -铅弹 -签证 -前阴 -鉆石冰 -潜伏者 -潜水刀 -枪刺 -枪猎 -枪模 -枪手 -枪支 -槍 -槍袋 -槍琯 -槍管 -槍箱 -强奸 -强奸水 -强奸丸 -强开 -羟 -羟亚胺 -羥亞胺 -橋本杏子 -窃听 -青蒿素 -青楼十二房 -氢弹 -氢化可的松 -清债 -清帐 -情蛊 -情色 -氰 -氰化 -氰化钙 -氰化汞 -氰化钾 -氰化钠 -氰化物 -求生刀 -巯 -曲马多 -去氧 -全钢刀 -全集 -全裸 -全套服务 -醛 -群p -群交 -燃烧 -燃烧弹 -燃烧剂 -燃烧瓶 -热武器 -人民币 -人皮 -人兽 -人体器官 -人妖 -仁科百华 -仁科百華 -任意号码 -日本avbt下载 -日韩无码 -日韩有码 -揉奶 -肉棒 -肉洞 -肉棍 -肉蒲团 -肉穴 -如月可怜 -乳交 -赛马会 -赛馬会 -三级片 -三箭 -三箭氣 -三棱 -三棱刀 -三利达 -三连发 -三氯甲烷 -三陪小姐 -三唑 -三唑仑 -三唑侖 -散弹枪 -桑拿 -骚B -骚屄 -骚逼 -骚冰 -骚妹 -骚女 -骚穴 -扫描枪 -色狗 -色情 -色情片 -色情五月天 -色色 -色图 -色淫 -色友 -色中色 -杀人 -杀手 -杀它 -沙菲片 -沙林 -山心恨 -山猪 -删贴 -商务 -上门 -上门按摩 -上门服务 -少妇 -少妇白洁 -舌尖漫游 -射钉 -射钉枪 -射鱼弩 -身份信息 -身份證 -砷 -深喉 -深圳小姐 -神仙水 -神仙糖 -肾源 -肾臟 -胂 -腎源 -生源 失身粉 -失身水 -失忆粉 -失忆水 -失忆药 -十八大 -十八小妹自拍網 -十字锁 -视频聊天 -视频下载 -视频秀 -视讯 -收藏品 -收购 -收购肝 -收购肾 -手島優 -手弓弩 -手狗 -手机变号 -手铐 -手拉AWP -手拉鸡 -手榴弹 -手弩 -手枪 -兽交 -兽兽 -售冰毒 -售假币 -售假钞 -售假护照 -售假酒 -售假钱 -售假学历 -售假烟 -售假硬币 -售假证 -售考前答案 -售考试答案 -售枪 -售套牌车 -售走私车 -书记 -熟女 -熟女镇 -数据库 -刷Q币 -甩刀 -甩棍 -双飞 -双管 -爽图 -水晶冰 -水军 -税据 -税票 -税票代 -丝足 -私服 -私家侦探 -私拍 -私售 -四号白粉 -四季彩香 -四六级 -四氢吡喃酮 -素人 -速水恋 -铊 -铊盐 -羰 -套牌 -套现 -特警 -特码 -特码网 -特殊服务 -替考 -天安门事件 -舔阴 -跳刀 -貼圖 -听话水 -听话药 -听话药水 -通信录 -通讯录 -酮 -筒见友 -偷拍 -头盔 -投注 -透视 -透视眼镜 -秃鹰 -秃鹰气枪 -土仿狗 -推油 -臀推 -托福 -脱氧麻黄素 -脱衣 -弯刀冷钢 -烷 -晚乙子爱 -万能钥匙 -王民生 -网络投注 -伪币 -伪钞 -卫星天线 -温家宝 -温切斯特 -文凭 -我爱我色 -无码 -无政府 -吴邦国 -無碼 -午夜 -武力 -武器 -武士 -武士刀 -戊基 -西班牙苍蝇粉 -西班牙苍蝇水 -烯 -锡纸 -习近平 -酰 -相思红娘 -香烟型昏迷药 -香烟型迷 -香烟型迷药 -消音器 -逍遥视频 -逍遥游论坛 -硝胺 -硝化 -硝化甘油 -硝化纤 -硝甲西泮 -硝酸 -硝酸铵 -硝酸甘 -硝酸甘油 -硝酸钾 -硝酸铊 -销案 -销魂 -銷售 -銷售K粉 -小冰砖 -小冰磚 -小飞狼 -小黑豹 -小姐服务 -小姐上门 -小口径 -小穴 -新车保险 -信息 -信用卡 -型弩 -性爱 -性愛世代 -性吧 -性服务 -性交电影 -性派对 -性图 -性息 -性用品 -性之图 -胸摧 -胸推 -学潮 -学生妹 -学生证 -学位证 -学运 -寻芳 -寻欢 -迅雷下载 -牙签冰 -牙签果 -雅照 -亚热 -亚洲 -盐羟亚胺 -盐酸 -盐酸氯 -盐酸氯胺酮 -盐酸哌替啶 -盐酸羟亚胺 -盐酸曲马多 -盐酸曲马多片 -颜射 -鹽酸 -鹽酸羥亞胺 -艳旅 -艳门 -艳舞 -艳舞女 -艳星 -艳照 -阳具 -洋妞 -陽菜 -搖頭糖 -搖頭丸 -摇头糖 -摇头丸 -夜场 -夜猫网 -夜色撩人 -夜淫 -一本道 -一品楼 -一夜情 -一夜晴 -一字型 -怡红院 -乙醚 -易容 -淫 -淫荡 -淫洞 -淫妇 -淫秽 -淫叫 -淫乱 -淫民 -淫妻 -淫人 -淫色 -淫图 -淫网 -淫穴 -淫液 -淫汁 -银行卡 -银行卡复制 -銀行卡 -引爆器 -隐形 -印钞机 -印花税 -罂 -罂粟 -硬币 -硬幣 -铀 -有偿 -有码 -幼升小 -玉女心经 -玉蒲团 -御花 -慾望技能 -原子弹 -援助妹 -云南情蛊药 -芸能人 -曾道人 -增值税 -赠卵 -炸弹 -炸藥 -战刀 -战狗 -战术 -掌心雷 -招嫖 -找鸡 -找小姐 -找鸭 -找洋 -折刀 -折叠狗 -折叠军 -折叠弩 -针孔 -针孔摄像头 -真城丽美 -真钱 -真枪 -真实文凭 -整人药 -证历 -证券 -证书 -政法 -政府 -执业 -直销 -直销财税 -职称证 -职业打手 -职業殺手 -植物冰 -指定號碼 -指纹膜 -指纹套 -酯 -制作K粉 -制作冰毒 -致幻 -致幻剂 -製作K粉 -製作冰毒 -中出 -中介 -中考 -种子下载 -重刺 -周恩来 -朱&鸡 -朱&基 -朱&雞 -朱&毛 -朱&茸 -朱&溶 -朱&蓉 -朱&榕 -朱&熔 -朱&瑢 -朱&融 -朱荣基 -朱容基 -助考 -爪刀 -专八 -专六 -专卖 -专门供应 -专业发帖 -专业开票 -专用弩 -转让 -追债 -姿丽子 -资格 -资格证 -子弹 -子彈 -自焚 -自慰器 -走私狗 -足交 -钻石冰 -钻石冰糖 -左轮 -左旋麻黄素 -左旋素 -作弊 -作弊工具 -作训 -做爱表演 -占中 -普选 -卖假军官证 -卖高仿身份证 -提供假文凭 -卖资质证书 -提供言正 -卖驾驶证 -办理四六级证书 -当面交易英语等级证 -当面交易居民户口本 -提供假身份证 -当面交易假结婚证 -当面交易驾照 -供应学历证书 -供应户口本 -卖高仿户口本 -做假车牌 -做驾照 -办理护照 -做高仿身份证 -做假文凭 -售行驶证 -办理假户口本 -当面交易车辆牌照 -售假军官证 -售工作证 -提供身份证 -当面交易军官证样本 -售警察证 -卖行驶证 -做假结婚证 -售言正 -做军车套牌 -当面交易高仿学位证 -做行驶证 -售四六级证书 -办理国安证 -卖驾照 -做高仿户口本 -卖工作证 -做假言正 -做车辆牌照 -办理高仿身份证 -做护照 -售军人证 -售护照 -提供军官证样本 -卖英语等级证 -供应毕业文凭 -做假身份证 -当面交易言正 -提供学历证书 -提供国外文凭 -做国外文凭 -办理军官证样本 -供应警官证 -做学历证书 -卖证件 -卖假证件 -卖假车牌 -办理英语等级证 -卖警察证 -卖车辆牌照 -办理记者证 -提供警察证 -做户口本 -提供证件 -办理驾照 -售士兵证 -提供驾驶证 -办理高仿户口本 -提供假证件 -办理国外文凭 -当面交易学历证书 -做假户口本 -做军官证 -供应记者证 -售高仿身份证 -当面交易四六级证书 -当面交易高仿户口本 -当面交易会计师证 -供应护照 -做军官证样本 -供应国外文凭 -卖军人证 -提供行驶证 -办理居民户口本 -卖四六级证书 -售军车套牌 -卖国安证 -提供假车牌 -供应公文 -卖言正 -提供士兵证 -售英语等级证 -提供高仿学位证 -办理高仿证 -当面交易军人证 -办理车辆牌照 -卖假言正 -提供毕业文凭 -供应国安证 -做四六级证书 -办理假文凭 -当面交易高仿身份证 -办理行驶证 -售假文凭 -供应警察证 -售假结婚证 -卖假户口本 -卖身份证 -做英语等级证 -卖毕业文凭 -办理警察证 -当面交易军车套牌 -办理高仿学位证 -售假车牌 -当面交易国安证 -供应资质证书 -做证件 -提供毕业证书 -供应工作证 -办理军车套牌 -提供高仿证 -当面交易国外文凭 -做会计师证 -售军官证 -卖毕业证书 -卖假结婚证 -办理户口本 -卖军车套牌 -当面交易户口本 -当面交易身份证 -供应证件 -售高仿户口本 -办理毕业证书 -售会计师证 -占领中环 -戴耀廷 -中大集会 -催泪弹 -泛民主派 -拉黑布游行 -学界罢课 -香港中环 -香港民主 -香港大学生 -华信民 -习会成为末代总书记吗 -习总日记 -张澜澜 -习氏 -习总书记 -apec会议扰民指数 -新疆暴恐分子会议期间发动袭击 -北京6万警察严正待命 -习近平治国新书 -apec安保盘点 -农历十一黄金周 -雾都堵城优惠假 -天赐良假 -当面交易记者证 -供应行驶证 -办理假证件 -当面交易护照 -供应高仿证 -售国外文凭 -卖公文 -供应言正 -办理假结婚证 -供应军官证 -供应高仿户口本 -做工作证 -售毕业文凭 -售军官证样本 -卖户口本 -供应假户口本 -办理公文 -提供高仿户口本 -供应军人证 -当面交易假身份证 -售公文 -提供驾照 -供应英语等级证 -做言正 -办理会计师证 -售驾照 -提供记者证 -当面交易假车牌 -售居民户口本 -提供居民户口本 -卖国外文凭 -做资质证书 -做高仿学位证 -办理假言正 -做警官证 -当面交易毕业文凭 -售毕业证书 -当面交易军官证 -供应假身份证 -做士兵证 -做记者证 -售记者证 -提供假结婚证 -办理证件 -卖会计师证 -售证件 -卖士兵证 -提供车辆牌照 -当面交易证件 -当面交易工作证 -提供英语等级证 -供应高仿学位证 -卖军官证 -供应车辆牌照 -供应会计师证 -办理驾驶证 -卖护照 -提供国安证 -供应士兵证 -供应假军官证 -卖警官证 -做国安证 -供应假车牌 -供应假言正 -售高仿证 -当面交易警官证 -当面交易驾驶证 -提供假户口本 -卖高仿学位证 -做高仿证 -提供假言正 -售学历证书 -供应四六级证书 -办理军官证 -供应军车套牌 -当面交易假证件 -售身份证 -售驾驶证 -供应高仿身份证 -办理工作证 -当面交易假户口本 -做警察证 -卖军官证样本 -办理假军官证 -当面交易假军官证 -供应驾照 -供应驾驶证 -供应毕业证书 -供应假文凭 -做公文 -办理毕业文凭 -做驾驶证 -办理军人证 -售假证件 -当面交易高仿证 -供应军官证样本 -提供军官证 -售车辆牌照 -售高仿学位证 -提供护照 -办理学历证书 -办理假车牌 -供应假结婚证 -提供警官证 -办理假身份证 -卖学历证书 -提供军车套牌 -供应身份证 -提供资质证书 -做假证件 -卖假文凭 -当面交易士兵证 -办理资质证书 -做军人证 -办理言正 -当面交易假言正 -提供军人证 -供应假证件 -做身份证 -卖居民户口本 -当面交易公文 -提供公文 -做毕业证书 -当面交易毕业证书 -当面交易假文凭 -售假身份证 -办理身份证 -做假军官证 -卖记者证 -提供假军官证 -办理士兵证 -售资质证书 -当面交易行驶证 -做居民户口本 -提供会计师证 -售警官证 -售假言正 -当面交易资质证书 -卖高仿证 -做毕业文凭 -提供工作证 -提供户口本 -售户口本 -当面交易警察证 -售假户口本 -供应居民户口本 -售国安证 -提供高仿身份证 -1325723052 -love-cindy -love—cindy -辣妈群 -加V -加v -加V信 -加v信 -加WX -加wx -扣扣 -V信群 -v信群 -加扣 -\+V -\+v -兼直 -兼执 -兼之 -蒹职 -蒹直 -蒹只 -蒹之 -诚招代理 -招代理 -诚聘 -诚聘代理 -小鈤工 -工貲鈤洁 -手\.木几 -賺零 -淘宝刷单 -wechat -淘宝 -天猫 -夭貓 -刷单 -拍单 -\+q -\+qq -\+Q -\+QQ -蒹耳只 -兼耳只 -威訫 -兼職 -蒹職 -网兼 -兼\.只\.招\.聘 -兼\.直\.招\.聘 -蒹\.直\.招\.聘 -蒹\.只\.招\.聘 -珈扣 -缣埴傢 -代购 -微商 -V商 -v商 -ruoxianlove -唯一扣 -详情扣 -有意扣 -有意加扣 -详请扣 -详请扣 -兼职扣 -简直扣 -煎直扣 -在家赚 -看扣 -看q -看Q -看空间 -微店 -微点 -空闲时间 -日结 -兼1职 -唯一加 -详情加 -有意加 -详请加 -详请加 -兼职加 -简直加 -煎直加 -在。家。赚。 -看。扣 -看。q -看。Q -看。空。间 -微。店 -微。点 -空。闲。时。间 -日。结 -兼。职 -兼2职 -唯一家 -详情家 -有意家 -有意家q -详请家 -详请家 -兼职家 -简直家 -煎直家 -在\.家\.赚\. -看\.扣 -看\.q -看\.Q -看\.空\.间 -微\.店 -微\.点 -空\.闲\.时\.间 -日\.结 -兼\.职 -兼3职 -唯一q -详情Q -有意q -有意加q -详请q -详请q -兼职q -简直q -煎直q -在,家,赚 -看,扣 -看,q -看,Q -看,空,间 -微,店 -微,点 -空,闲,时,间 -日,结 -兼,职 -兼4职 -唯一Q -详情Q -有意Q -有意加Q -详请Q -详请Q -兼职Q -简直Q -煎直Q -在,家,赚 -看,扣 -看,q -看,Q -看,空,间 -微,店 -微,点 -空,闲,时,间 -日,结 -兼\*职 -兼5职 -唯一抠 -详情抠 -有意抠 -有意加抠 -详请抠 -详请抠 -兼职抠 -简直抠 -煎直抠 -兼@职 -兼6职 -唯一口 -详情口 -有意口 -有意加口 -详请口 -详请口 -兼职口 -简直口 -煎直口 -兼#职 -兼7职 -唯一寇 -详情寇 -有意寇 -有意加寇 -详请寇 -详请寇 -兼职寇 -简直寇 -煎直寇 -兼¥职 -兼¥职 -兼8职 -唯一蔻 -详情蔻 -有意蔻 -有意加蔻 -详请蔻 -详请蔻 -兼职蔻 -简直蔻 -煎直蔻 -兼%职 -兼9职 -兼&职 -兼\*职 -在家赚钱 -在jia赚钱 -在家zhuan钱 -在家赚qian -在家赚money -意者加我扣 -意者加扣 -意者加我抠 -意者加我寇 -意者加我蔻 -意者加抠 -意者加寇 -意者加蔻 -意加扣 -意加抠 -意加寇 -意加蔻 -\/天 -空jian -kong间 -kong jian -陶宝 -陶bao -tao宝 -兼zhi -jian职 -傔职 -傔zhi -傔,职 -傔。职 -傔、职 -傔,职 -傔\?职 -傔?职 -傔!职 -傔!职 -傔@职 -傔职# -傔#职 -傔¥职 -傔¥职 -傔$职 -傔%职 -傔\^职 -傔&职 -傔\*职 -傔’职 -傔”职 -傔\职 -傔\.职 -工资即时结算 -50-200不等 -在家也能赚奶粉钱 -在家也能赚钱 -在家能赚奶粉钱 -在家能赚钱 -工资日结 -工资每日结算 -加我Q -加我QQ -监职 -监,职 -监,职 -监。职 -监\.职 -监\?职 -监?职 -监!职 -监!职 -监@职 -监#职 -监$职 -监%职 -监\^职 -监&职 -监\*职 -监~职 -监1职 -监2职 -监3职 -监4职 -监5职 -监6职 -监7职 -监8职 -监9职 -加口 -不限时间 -不限地点 -不限时间和地点 -日算 -日,算 -日,算 -日。算 -日\.算 -50-100不等 -50-200不等 -50-150不等 -10-200不等 -50到100不等 -50到200不等 -50到150不等 -100到200不等 -聘口 -聘扣 -聘抠 -聘叩 -聘寇 -聘蔻 -手机挣米 -手机挣钱 -手机赚米 -手机赚钱 -赚钱 -挣钱 -兼职扣 -兼职Q -兼职q -兼职抠 -兼职叩 -兼职寇 -兼职蔻 -蒹职 -简直Q -简直q -简直抠 -简直扣 -简直家兼职寇 -兼职寇 -简直加 -联系方式 -联系Q -联系q -联系寇 -联系扣 -联系叩 -联系抠 -加Q -加q -加口 -加抠 -加寇 -加叩 -加扣 -加蔻 -兼职加 -兼职家 -煎直扣 -煎直加 -煎直家 -煎直抠 -煎直扣 -煎直寇 -煎直蔻 -煎直Q -煎直q -煎直口 -在·家·赚 -看·扣 -看·q -看·Q -看·空·间 -微·店 -微·点 -空·闲·时·间 -日·结 -微一 -微二 -微三 -微四 -微五 -微六 -微七 -微八 -微九 -微1 -微2 -微3 -微4 -微5 -微6 -微7 -微8 -微9 -薇一 -薇二 -薇三 -薇四 -薇五 -薇六 -薇七 -薇八 -薇九 -薇1 -薇2 -薇3 -薇4 -薇5 -薇6 -薇7 -薇8 -薇9 -天结 -天,结 -天。结 -天,结 -天\.结 -天?结 -天\?结 -天\/结 -天!结 -天@结 -天#结 -天¥结 -天¥结 -天%结 -天\^结 -天&结 -天\*结 -天-结 -天\[结 -天\]结 -天【结 -天】结 -天·结 -天:结 -天;结 -天~结 -天_结 -天—结 -日结 -日,结 -日。结 -日,结 -日\.结 -日?结 -日\?结 -日\/结 -日!结 -日@结 -日#结 -日¥结 -日¥结 -日%结 -日\^结 -日&结 -日\*结 -日-结 -日\[结 -日\]结 -日【结 -日】结 -日·结 -日:结 -日;结 -日~结 -日_结 -日—结 -日入 -日,入 -日。入 -日,入 -日\.入 -日?入 -日\?入 -日\/入 -日!入 -日@入 -日#入 -日¥入 -日¥入 -日%入 -日\^入 -日&入 -日\*入 -日-入 -日\[入 -日\]入 -日【入 -日】入 -日·入 -日:入 -日;入 -日~入 -日_入 -日—入 -\+我 -\+,我 -\+。我 -\+,我 -\+\.我 -\+?我 -\+\?我 -\+\/我 -\+!我 -\+@我 -\+#我 -\+¥我 -\+¥我 -\+%我 -\+\^我 -\+&我 -\+\*我 -\+-我 -\+\[我 -\+\]我 -\+【我 -\+】我 -\+·我 -\+:我 -\+;我 -\+~我 -\+_我 -\+—我 -蔻蔻 -蔻,蔻 -蔻。蔻 -蔻,蔻 -蔻\.蔻 -蔻?蔻 -蔻\?蔻 -蔻\/蔻 -蔻!蔻 -蔻@蔻 -蔻#蔻 -蔻¥蔻 -蔻¥蔻 -蔻%蔻 -蔻\^蔻 -蔻&蔻 -蔻\*蔻 -蔻-蔻 -蔻\[蔻 -蔻\]蔻 -蔻【蔻 -蔻】蔻 -蔻·蔻 -蔻:蔻 -蔻;蔻 -蔻~蔻 -蔻_蔻 -蔻—蔻 -代购 -代,购 -代。购 -代,购 -代\.购 -代?购 -代\?购 -代\/购 -代!购 -代@购 -代#购 -代¥购 -代¥购 -代%购 -代\^购 -代&购 -代\*购 -代-购 -代\[购 -代\]购 -代【购 -代】购 -代·购 -代:购 -代;购 -代~购 -代_购 -代—购 -傔职 -傔,职 -傔。职 -傔,职 -傔\.职 -傔?职 -傔\?职 -傔\/职 -傔!职 -傔@职 -傔#职 -傔¥职 -傔¥职 -傔%职 -傔\^职 -傔&职 -傔\*职 -傔-职 -傔\[职 -傔\]职 -傔【职 -傔】职 -傔·职 -傔:职 -傔;职 -傔~职 -傔_职 -傔—职 -诚聘 -诚,聘 -诚聘 -诚,聘 -诚\.聘 -诚?聘 -诚\?聘 -诚\/聘 -诚!聘 -诚@聘 -诚#聘 -诚¥聘 -诚¥聘 -诚%聘 -诚\^聘 -诚&聘 -诚\*聘 -诚-聘 -诚\[聘 -诚\]聘 -诚【聘 -诚】聘 -诚·聘 -诚:聘 -诚;聘 -诚~聘 -诚_聘 -诚—聘 -尖值 -尖,值 -尖。值 -尖,值 -尖\.值 -尖?值 -尖\?值 -尖\/值 -尖!值 -尖@值 -尖#值 -尖¥值 -尖¥值 -尖%值 -尖\^值 -尖&值 -尖\*值 -尖-值 -尖\[值 -尖\]值 -尖【值 -尖】值 -尖·值 -尖:值 -尖;值 -尖~值 -尖_值 -尖—值 -招募 -招,募 -招。募 -招,募 -招\.募 -招?募 -招募 -招\/募 -招!募 -招@募 -招#募 -招¥募 -招¥募 -招%募 -招\^募 -招&募 -招\*募 -招-募 -招\[募 -招\]募 -招募 -招募 -招募 -招募 -招募 -招募 -招募 -招募 -jian职 -jian,职 -jian。职 -jian,职 -jian\.职 -jian?职 -jian职 -jian\/职 -jian!职 -jian@职 -jian#职 -jian¥职 -jian¥职 -jian%职 -jian\^职 -jian&职 -jian\*职 -jian-职 -jian\[职 -jian\]职 -jian【职 -jian】职 -jian·职 -jian:职 -jian;职 -jian~职 -jian_职 -jian—职 -兼zhi -兼,zhi -兼。zhi -兼,zhi -兼\.zhi -兼?zhi -兼zhi -兼\/zhi -兼!zhi -兼@zhi -兼#zhi -兼¥zhi -兼¥zhi -兼%zhi -兼\^zhi -兼&zhi -兼\*zhi -兼-zhi -兼\[zhi -兼\]zhi -兼【zhi -兼】zhi -兼·zhi -兼:zhi -兼;zhi -兼~zhi -兼_zhi -兼—zhi -缣耳只 -兼耳只 -傔耳只 -工資曰結 -抠1 -抠2 -抠3 -抠4 -抠5 -抠6 -抠7 -抠8 -抠9 -抠 -口1 -口2 -口3 -口4 -口5 -口6 -口7 -口8 -口9 -口 -蔻1 -蔻2 -蔻3 -蔻4 -蔻5 -蔻6 -蔻7 -蔻8 -蔻9 -蔻 -扣1 -扣2 -扣3 -扣4 -扣5 -扣6 -扣7 -扣8 -扣9 -扣 -寇1 -寇2 -寇3 -寇4 -寇5 -寇6 -寇7 -寇8 -寇9 -寇 -抠1 -抠,1 -抠。1 -抠,1 -抠\.1 -抠?1 -抠\?1 -抠\/1 -抠!1 -抠@1 -抠#1 -抠¥1 -抠%1 -抠\^1 -抠&1 -抠\*1 -抠-1 -抠\[1 -抠\]1 -抠【1 -抠】1 -抠·1 -抠:1 -抠;1 -抠~1 -抠_1 -抠—1 -抠\:1 -抠!1 -口1 -口,1 -口。1 -口,1 -口\.1 -口?1 -口\?1 -口\/1 -口!1 -口@1 -口#1 -口¥1 -口%1 -口\^1 -口&1 -口\*1 -口-1 -口\[1 -口\]1 -口【1 -口】1 -口·1 -口:1 -口;1 -口~1 -口_1 -口—1 -口\:1 -口!1 -蔻1 -蔻,1 -蔻。1 -蔻,1 -蔻\.1 -蔻?1 -蔻\?1 -蔻\/1 -蔻!1 -蔻@1 -蔻#1 -蔻¥1 -蔻%1 -蔻\^1 -蔻&1 -蔻\*1 -蔻-1 -蔻\[1 -蔻\]1 -蔻【1 -蔻】1 -蔻·1 -蔻:1 -蔻;1 -蔻~1 -蔻_1 -蔻—1 -蔻\:1 -蔻!1 -扣1 -扣,1 -扣。1 -扣,1 -扣\.1 -扣?1 -扣\?1 -扣\/1 -扣!1 -扣@1 -扣#1 -扣¥1 -扣%1 -扣\^1 -扣&1 -扣\*1 -扣-1 -扣\[1 -扣\]1 -扣【1 -扣】1 -扣·1 -扣:1 -扣;1 -扣~1 -扣_1 -扣—1 -扣\:1 -扣!1 -寇1 -寇,1 -寇。1 -寇,1 -寇\.1 -寇?1 -寇\?1 -寇\/1 -寇!1 -寇@1 -寇#1 -寇¥1 -寇%1 -寇\^1 -寇&1 -寇\*1 -寇-1 -寇\[1 -寇\]1 -寇【1 -寇】1 -寇·1 -寇:1 -寇;1 -寇~1 -寇_1 -寇—1 -寇\:1 -寇!1 -抠2 -抠,2 -抠。2 -抠,2 -抠\.2 -抠?2 -抠\?2 -抠\/2 -抠!2 -抠@2 -抠#2 -抠¥2 -抠%2 -抠\^2 -抠&2 -抠\*2 -抠-2 -抠\[2 -抠\]2 -抠【2 -抠】2 -抠·2 -抠:2 -抠;2 -抠~2 -抠_2 -抠—2 -抠\:2 -抠!2 -口2 -口,2 -口。2 -口,2 -口\.2 -口?2 -口\?2 -口\/2 -口!2 -口@2 -口#2 -口¥2 -口%2 -口\^2 -口&2 -口\*2 -口-2 -口\[2 -口\]2 -口【2 -口】2 -口·2 -口:2 -口;2 -口~2 -口_2 -口—2 -口\:2 -口!2 -蔻2 -蔻,2 -蔻。2 -蔻,2 -蔻\.2 -蔻?2 -蔻\?2 -蔻\/2 -蔻!2 -蔻@2 -蔻#2 -蔻¥2 -蔻%2 -蔻\^2 -蔻&2 -蔻\*2 -蔻-2 -蔻\[2 -蔻\]2 -蔻【2 -蔻】2 -蔻·2 -蔻:2 -蔻;2 -蔻~2 -蔻_2 -蔻—2 -蔻\:2 -蔻!2 -扣2 -扣,2 -扣。2 -扣,2 -扣\.2 -扣?2 -扣\?2 -扣\/2 -扣!2 -扣@2 -扣#2 -扣¥2 -扣%2 -扣\^2 -扣&2 -扣\*2 -扣-2 -扣\[2 -扣\]2 -扣【2 -扣】2 -扣·2 -扣:2 -扣;2 -扣~2 -扣_2 -扣—2 -扣\:2 -扣!2 -寇2 -寇,2 -寇。2 -寇,2 -寇\.2 -寇?2 -寇\?2 -寇\/2 -寇!2 -寇@2 -寇#2 -寇¥2 -寇%2 -寇\^2 -寇&2 -寇\*2 -寇-2 -寇\[2 -寇\]2 -寇【2 -寇】2 -寇·2 -寇:2 -寇;2 -寇~2 -寇_2 -寇—2 -寇\:2 -寇!2 -抠3 -抠,3 -抠。3 -抠,3 -抠\.3 -抠?3 -抠\?3 -抠\/3 -抠!3 -抠@3 -抠#3 -抠¥3 -抠%3 -抠\^3 -抠&3 -抠\*3 -抠-3 -抠\[3 -抠\]3 -抠【3 -抠】3 -抠·3 -抠:3 -抠;3 -抠~3 -抠_3 -抠—3 -抠\:3 -抠!3 -口3 -口,3 -口。3 -口,3 -口\.3 -口?3 -口\?3 -口\/3 -口!3 -口@3 -口#3 -口¥3 -口%3 -口\^3 -口&3 -口\*3 -口-3 -口\[3 -口\]3 -口【3 -口】3 -口·3 -口:3 -口;3 -口~3 -口_3 -口—3 -口\:3 -口!3 -蔻3 -蔻,3 -蔻。3 -蔻,3 -蔻\.3 -蔻?3 -蔻\?3 -蔻\/3 -蔻!3 -蔻@3 -蔻#3 -蔻¥3 -蔻%3 -蔻\^3 -蔻&3 -蔻\*3 -蔻-3 -蔻\[3 -蔻\]3 -蔻【3 -蔻】3 -蔻·3 -蔻:3 -蔻;3 -蔻~3 -蔻_3 -蔻—3 -蔻\:3 -蔻!3 -扣3 -扣,3 -扣。3 -扣,3 -扣\.3 -扣?3 -扣\?3 -扣\/3 -扣!3 -扣@3 -扣#3 -扣¥3 -扣%3 -扣\^3 -扣&3 -扣\*3 -扣-3 -扣\[3 -扣\]3 -扣【3 -扣】3 -扣·3 -扣:3 -扣;3 -扣~3 -扣_3 -扣—3 -扣\:3 -扣!3 -寇3 -寇,3 -寇。3 -寇,3 -寇\.3 -寇?3 -寇\?3 -寇\/3 -寇!3 -寇@3 -寇#3 -寇¥3 -寇%3 -寇\^3 -寇&3 -寇\*3 -寇-3 -寇\[3 -寇\]3 -寇【3 -寇】3 -寇·3 -寇:3 -寇;3 -寇~3 -寇_3 -寇—3 -寇\:3 -寇!3 -抠4 -抠,4 -抠。4 -抠,4 -抠\.4 -抠?4 -抠\?4 -抠\/4 -抠!4 -抠@4 -抠#4 -抠¥4 -抠%4 -抠\^4 -抠&4 -抠\*4 -抠-4 -抠\[4 -抠\]4 -抠【4 -抠】4 -抠·4 -抠:4 -抠;4 -抠~4 -抠_4 -抠—4 -抠\:4 -抠!4 -口4 -口,4 -口。4 -口,4 -口\.4 -口?4 -口\?4 -口\/4 -口!4 -口@4 -口#4 -口¥4 -口%4 -口\^4 -口&4 -口\*4 -口-4 -口\[4 -口\]4 -口【4 -口】4 -口·4 -口:4 -口;4 -口~4 -口_4 -口—4 -口\:4 -口!4 -蔻4 -蔻,4 -蔻。4 -蔻,4 -蔻\.4 -蔻?4 -蔻\?4 -蔻\/4 -蔻!4 -蔻@4 -蔻#4 -蔻¥4 -蔻%4 -蔻\^4 -蔻&4 -蔻\*4 -蔻-4 -蔻\[4 -蔻\]4 -蔻【4 -蔻】4 -蔻·4 -蔻:4 -蔻;4 -蔻~4 -蔻_4 -蔻—4 -蔻\:4 -蔻!4 -扣4 -扣,4 -扣。4 -扣,4 -扣\.4 -扣?4 -扣\?4 -扣\/4 -扣!4 -扣@4 -扣#4 -扣¥4 -扣%4 -扣\^4 -扣&4 -扣\*4 -扣-4 -扣\[4 -扣\]4 -扣【4 -扣】4 -扣·4 -扣:4 -扣;4 -扣~4 -扣_4 -扣—4 -扣\:4 -扣!4 -寇4 -寇,4 -寇。4 -寇,4 -寇\.4 -寇?4 -寇\?4 -寇\/4 -寇!4 -寇@4 -寇#4 -寇¥4 -寇%4 -寇\^4 -寇&4 -寇\*4 -寇-4 -寇\[4 -寇\]4 -寇【4 -寇】4 -寇·4 -寇:4 -寇;4 -寇~4 -寇_4 -寇—4 -寇\:4 -寇!4 -抠5 -抠,5 -抠。5 -抠,5 -抠\.5 -抠?5 -抠\?5 -抠\/5 -抠!5 -抠@5 -抠#5 -抠¥5 -抠%5 -抠\^5 -抠&5 -抠\*5 -抠-5 -抠\[5 -抠\]5 -抠【5 -抠】5 -抠·5 -抠:5 -抠;5 -抠~5 -抠_5 -抠—5 -抠\:5 -抠!5 -口5 -口,5 -口。5 -口,5 -口\.5 -口?5 -口\?5 -口\/5 -口!5 -口@5 -口#5 -口¥5 -口%5 -口\^5 -口&5 -口\*5 -口-5 -口\[5 -口\]5 -口【5 -口】5 -口·5 -口:5 -口;5 -口~5 -口_5 -口—5 -口\:5 -口!5 -蔻5 -蔻,5 -蔻。5 -蔻,5 -蔻\.5 -蔻?5 -蔻\?5 -蔻\/5 -蔻!5 -蔻@5 -蔻#5 -蔻¥5 -蔻%5 -蔻\^5 -蔻&5 -蔻\*5 -蔻-5 -蔻\[5 -蔻\]5 -蔻【5 -蔻】5 -蔻·5 -蔻:5 -蔻;5 -蔻~5 -蔻_5 -蔻—5 -蔻\:5 -蔻!5 -扣5 -扣,5 -扣。5 -扣,5 -扣\.5 -扣?5 -扣\?5 -扣\/5 -扣!5 -扣@5 -扣#5 -扣¥5 -扣%5 -扣\^5 -扣&5 -扣\*5 -扣-5 -扣\[5 -扣\]5 -扣【5 -扣】5 -扣·5 -扣:5 -扣;5 -扣~5 -扣_5 -扣—5 -扣\:5 -扣!5 -寇5 -寇,5 -寇。5 -寇,5 -寇\.5 -寇?5 -寇\?5 -寇\/5 -寇!5 -寇@5 -寇#5 -寇¥5 -寇%5 -寇\^5 -寇&5 -寇\*5 -寇-5 -寇\[5 -寇\]5 -寇【5 -寇】5 -寇·5 -寇:5 -寇;5 -寇~5 -寇_5 -寇—5 -寇\:5 -寇!5 -抠6 -抠,6 -抠。6 -抠,6 -抠\.6 -抠?6 -抠\?6 -抠\/6 -抠!6 -抠@6 -抠#6 -抠¥6 -抠%6 -抠\^6 -抠&6 -抠\*6 -抠-6 -抠\[6 -抠\]6 -抠【6 -抠】6 -抠·6 -抠:6 -抠;6 -抠~6 -抠_6 -抠—6 -抠\:6 -抠!6 -口6 -口,6 -口。6 -口,6 -口\.6 -口?6 -口\?6 -口\/6 -口!6 -口@6 -口#6 -口¥6 -口%6 -口\^6 -口&6 -口\*6 -口-6 -口\[6 -口\]6 -口【6 -口】6 -口·6 -口:6 -口;6 -口~6 -口_6 -口—6 -口\:6 -口!6 -蔻6 -蔻,6 -蔻。6 -蔻,6 -蔻\.6 -蔻?6 -蔻\?6 -蔻\/6 -蔻!6 -蔻@6 -蔻#6 -蔻¥6 -蔻%6 -蔻\^6 -蔻&6 -蔻\*6 -蔻-6 -蔻\[6 -蔻\]6 -蔻【6 -蔻】6 -蔻·6 -蔻:6 -蔻;6 -蔻~6 -蔻_6 -蔻—6 -蔻\:6 -蔻!6 -扣6 -扣,6 -扣。6 -扣,6 -扣\.6 -扣?6 -扣\?6 -扣\/6 -扣!6 -扣@6 -扣#6 -扣¥6 -扣%6 -扣\^6 -扣&6 -扣\*6 -扣-6 -扣\[6 -扣\]6 -扣【6 -扣】6 -扣·6 -扣:6 -扣;6 -扣~6 -扣_6 -扣—6 -扣\:6 -扣!6 -寇6 -寇,6 -寇。6 -寇,6 -寇\.6 -寇?6 -寇\?6 -寇\/6 -寇!6 -寇@6 -寇#6 -寇¥6 -寇%6 -寇\^6 -寇&6 -寇\*6 -寇-6 -寇\[6 -寇\]6 -寇【6 -寇】6 -寇·6 -寇:6 -寇;6 -寇~6 -寇_6 -寇—6 -寇\:6 -寇!6 -抠7 -抠,7 -抠。7 -抠,7 -抠\.7 -抠?7 -抠\?7 -抠\/7 -抠!7 -抠@7 -抠#7 -抠¥7 -抠%7 -抠\^7 -抠&7 -抠\*7 -抠-7 -抠\[7 -抠\]7 -抠【7 -抠】7 -抠·7 -抠:7 -抠;7 -抠~7 -抠_7 -抠—7 -抠\:7 -抠!7 -口7 -口,7 -口。7 -口,7 -口\.7 -口?7 -口\?7 -口\/7 -口!7 -口@7 -口#7 -口¥7 -口%7 -口\^7 -口&7 -口\*7 -口-7 -口\[7 -口\]7 -口【7 -口】7 -口·7 -口:7 -口;7 -口~7 -口_7 -口—7 -口\:7 -口!7 -蔻7 -蔻,7 -蔻。7 -蔻,7 -蔻\.7 -蔻?7 -蔻\?7 -蔻\/7 -蔻!7 -蔻@7 -蔻#7 -蔻¥7 -蔻%7 -蔻\^7 -蔻&7 -蔻\*7 -蔻-7 -蔻\[7 -蔻\]7 -蔻【7 -蔻】7 -蔻·7 -蔻:7 -蔻;7 -蔻~7 -蔻_7 -蔻—7 -蔻\:7 -蔻!7 -扣7 -扣,7 -扣。7 -扣,7 -扣\.7 -扣?7 -扣\?7 -扣\/7 -扣!7 -扣@7 -扣#7 -扣¥7 -扣%7 -扣\^7 -扣&7 -扣\*7 -扣-7 -扣\[7 -扣\]7 -扣【7 -扣】7 -扣·7 -扣:7 -扣;7 -扣~7 -扣_7 -扣—7 -扣\:7 -扣!7 -寇7 -寇,7 -寇。7 -寇,7 -寇\.7 -寇?7 -寇\?7 -寇\/7 -寇!7 -寇@7 -寇#7 -寇¥7 -寇%7 -寇\^7 -寇&7 -寇\*7 -寇-7 -寇\[7 -寇\]7 -寇【7 -寇】7 -寇·7 -寇:7 -寇;7 -寇~7 -寇_7 -寇—7 -寇\:7 -寇!7 -抠8 -抠,8 -抠。8 -抠,8 -抠\.8 -抠?8 -抠\?8 -抠\/8 -抠!8 -抠@8 -抠#8 -抠¥8 -抠%8 -抠\^8 -抠&8 -抠\*8 -抠-8 -抠\[8 -抠\]8 -抠【8 -抠】8 -抠·8 -抠:8 -抠;8 -抠~8 -抠_8 -抠—8 -抠\:8 -抠!8 -口8 -口,8 -口。8 -口,8 -口\.8 -口?8 -口\?8 -口\/8 -口!8 -口@8 -口#8 -口¥8 -口%8 -口\^8 -口&8 -口\*8 -口-8 -口\[8 -口\]8 -口【8 -口】8 -口·8 -口:8 -口;8 -口~8 -口_8 -口—8 -口\:8 -口!8 -蔻8 -蔻,8 -蔻。8 -蔻,8 -蔻\.8 -蔻?8 -蔻\?8 -蔻\/8 -蔻!8 -蔻@8 -蔻#8 -蔻¥8 -蔻%8 -蔻\^8 -蔻&8 -蔻\*8 -蔻-8 -蔻\[8 -蔻\]8 -蔻【8 -蔻】8 -蔻·8 -蔻:8 -蔻;8 -蔻~8 -蔻_8 -蔻—8 -蔻\:8 -蔻!8 -扣8 -扣,8 -扣。8 -扣,8 -扣\.8 -扣?8 -扣\?8 -扣\/8 -扣!8 -扣@8 -扣#8 -扣¥8 -扣%8 -扣\^8 -扣&8 -扣\*8 -扣-8 -扣\[8 -扣\]8 -扣【8 -扣】8 -扣·8 -扣:8 -扣;8 -扣~8 -扣_8 -扣—8 -扣\:8 -扣!8 -寇8 -寇,8 -寇。8 -寇,8 -寇\.8 -寇?8 -寇\?8 -寇\/8 -寇!8 -寇@8 -寇#8 -寇¥8 -寇%8 -寇\^8 -寇&8 -寇\*8 -寇-8 -寇\[8 -寇\]8 -寇【8 -寇】8 -寇·8 -寇:8 -寇;8 -寇~8 -寇_8 -寇—8 -寇\:8 -寇!8 -抠9 -抠,9 -抠。9 -抠,9 -抠\.9 -抠?9 -抠\?9 -抠\/9 -抠!9 -抠@9 -抠#9 -抠¥9 -抠%9 -抠\^9 -抠&9 -抠\*9 -抠-9 -抠\[9 -抠\]9 -抠【9 -抠】9 -抠·9 -抠:9 -抠;9 -抠~9 -抠_9 -抠—9 -抠\:9 -抠!9 -口9 -口,9 -口。9 -口,9 -口\.9 -口?9 -口\?9 -口\/9 -口!9 -口@9 -口#9 -口¥9 -口%9 -口\^9 -口&9 -口\*9 -口-9 -口\[9 -口\]9 -口【9 -口】9 -口·9 -口:9 -口;9 -口~9 -口_9 -口—9 -口\:9 -口!9 -蔻9 -蔻,9 -蔻。9 -蔻,9 -蔻\.9 -蔻?9 -蔻\?9 -蔻\/9 -蔻!9 -蔻@9 -蔻#9 -蔻¥9 -蔻%9 -蔻\^9 -蔻&9 -蔻\*9 -蔻-9 -蔻\[9 -蔻\]9 -蔻【9 -蔻】9 -蔻·9 -蔻:9 -蔻;9 -蔻~9 -蔻_9 -蔻—9 -蔻\:9 -蔻!9 -扣9 -扣,9 -扣。9 -扣,9 -扣\.9 -扣?9 -扣\?9 -扣\/9 -扣!9 -扣@9 -扣#9 -扣¥9 -扣%9 -扣\^9 -扣&9 -扣\*9 -扣-9 -扣\[9 -扣\]9 -扣【9 -扣】9 -扣·9 -扣:9 -扣;9 -扣~9 -扣_9 -扣—9 -扣\:9 -扣!9 -寇9 -寇,9 -寇。9 -寇,9 -寇\.9 -寇?9 -寇\?9 -寇\/9 -寇!9 -寇@9 -寇#9 -寇¥9 -寇%9 -寇\^9 -寇&9 -寇\*9 -寇-9 -寇\[9 -寇\]9 -寇【9 -寇】9 -寇·9 -寇:9 -寇;9 -寇~9 -寇_9 -寇—9 -寇\:9 -寇!9 -jianzhi +淫荡自慰器 +000.2011wyt.com +000.bbexe.cn +0000-qq.cn +00000-qq.cn +0008-qq.cn +000wyt.com +001.bbexe.cn +001fans.com +002.la +00333.cn +005.70o2.cn +006001.com +0073d.cn +007wyt.com +008.kweilai.cn +008.qq8625.cn +008.renyi1.cn +008.wangwang1.cn +008.youyiv.cn +008.zhifong.cn +00852555.cn +00852tm888.com +008567.cn +00ad.3322.org +00ooll.cn +00pp00.360yyy.8800.org +00zzd.2288.org +010246.com +010268.com +010389.com +010488.com +0105568.cn +01058789.com +0106658.cn +0106677.cn +0108686.cn +0108818.cn +010899.com +0109079.com +0109888.cn +010caipiao.com +010kys.com +010zgcp.com +0111152.3322.org +01324.cn +01696.com +022.70o2.cn +023tvb.us +02lh.info +03.xiezhen.co.cc +0303.tok77.org +0303.tok88.com +0303.tok99.com +030999.com +031520.cn +0322.tok77.org +0322.tok88.com +0322.tok99.com +03988.cn +039999.com +0451fck.com +051.tok88.com +0518pw.cn +0519pw.cn +05cctv.cn +05qqvip.com +06000.cn +061.tok88.com +06713.buo.cc +06qy.3322.or +06qy.3322.org +0718.88mw.com +07212.com +0757110.com +07797.com +07dp.com +07yin.com +08053.80uoxp.com +0810.6600.org +08318.cn +08cpw.com +08zs.com +09-yahoo.cn +0916ss.3322.org +0920ss.3322.org +0926gx.kmip.net +09edy.com +09xss.cn +0e1p.9966.org +0iyhhtr.cn +0kdy.cn +0ni9o1s3feu60.cn +0nly18.com +0os0d.cn +0osaee.cn +1.114central.com +1.12008.com.cn +1.1234llll.com +1.138dh.info +1.17nnn.com +1.17qin.com +1.1ddxx.com +1.222233.com +1.27nnn.com +1.32cs.com +1.333mi.com +1.33aaaa.com +1.33lc.com +1.42nnn.com +1.444mi.com +1.444mi.net +1.44aaaa.com +1.44l.info +1.4ddxx.com +1.522sm.com +1.551mi.com +1.555mi.com +1.555mi.net +1.666mi.com +1.66aaaa.com +1.7sy.info +1.82nnn.com +1.82yyy.com +1.88888wyt.com +1.95622.com +1.97wuyue.com +1.97xxb.info +1.99game.info +1.a.dirty-boy.cn +1.addd.cz.cc +1.ajehe.info +1.al1pay6.com.cn +1.bbsmaya.com +1.boksx.com +1.ccw12.com +1.clxwe.com +1.csly.info +1.ctrl.fajujohiv.cn +1.cy265.info +1.damimi.info +1.dd9b.com +1.doxws.com +1.dxjyh.com +1.exksc.com +1.fuwxh.com +1.ganbobo.com +1.google-credit.cn +1.googlelianmeng.9966.org +1.hxut.net +1.ixwsy.com +1.jianlingwg.com +1.jinfuren.info +1.kekese.com +1.mestferrit.co.cc +1.mishi.info +1.mumudy.com +1.ourlamb.info +1.putuan.info +1.qinqin.info +1.qqenet.com +1.recruter.cz8.ru +1.sao16.com +1.selaoda.net +1.sese137.com +1.sewo.8866.org +1.sewo.9966.org +1.sexdao.info +1.shelang.us +1.so8.us +1.sqwyl.com +1.tianshi2000.info +1.ubersexy.su +1.uuav.info +1.wori.us +1.wwwddd.net +1.xdizhi.info +1.xiaoxiao77.com +1.ys38.com +1.yxnjs.com +1.zjcbbs.info +10.fyg.cc +10.gdvd.cn +10.wowoke.us +1000.dnsxy.cn +10000-vip08.cn +10000.25690.cn +10000ww51.cn +100488.cn +10086feix.cn +100amateurvideos.com +1010hh.3322.org +1014gx3.6600.org +10233.cn +1031218.3322.org +10569.nznz.net +105qngkk.863computer.org.cn +107jj.cn +10qqgn.cn +10r.cssa.c0m.at +10wk.cn +11-j.somee.com +11-qq.com +11.57mao.com +11.iii97.com +11.yf3e.com +110.770304123.cn +1100xx.com +110abc.sdsawwds.info +111.21site.info +111.365blog.info +111.bbexe.cn +111.jqtop.com +111.qa222.8866.org +111.sdfsdg.3322.org +1111.daima-daima.cn +1111111.aiqiusese.3322.org +1111dnf.kmip.net +111cao.com +111hs.com +111mimi.com +111yi.com +1122444.com +1122aa.3322.org +1123886.3322.org +113.6600.org +115252.com +11748.com +117cp.com +117la.cn +118099.com +119abc.cn +11a.17site.info +11dgef.cn +11fdsftf.cn +11fwg.8866.org +11ggl.2288.org +11sdasew.cn +11vcv.2288.org +11vereb.8866.org +12-2005-search.com +12.meimei855.cn +12.yifi8.cn +1200dk.cn +1204gx1.6600.org +12102.com +12138.info +121ip.cn +122.770304123.cn +122.zzso.cn +122j.cn +122odkufnanta.3322.org +123-987.3322.org +123.kukankan.com +123.sd22ddd.cn +123.tang3344.cn +123.ww22ff.cn +1232355.8866.org +1234.888888ok.com.cn +1234.q161.com +123408.com +123456qweasdzxcrfv.7766.org +123456sad.3322.org +1234cao.8888ye.com +1234ye.com +123555662.6600.org +123896.com +123945.com +123cp.com.cn +123dd.info +123fengliu.cn +123ktv.info +123rruy75.cn +12580dianying-google-http-baidu-com.lanqiuhuo.info +126.123fga.cn +126vip2009.cn +127136.com +128388.com +128828.cn +12888.cc +129aof.3322.or +12ccx12.3322.org +12ff.a125.xunbiz.com +12hxajx.zij.yaq.58ui.90cj.wcs.500caipiao.com.cn +12smm.com +12ss52.3322.org +12wds.cn +12yuefen.3322.org +131111.com +13117485397.baidu.google.soso.yahoo.sina.sohu.taobao.com.woyinwose.info +1314bblc.com +1314r.3322.org +13278.com +1335122.ggg365.info +1335666.ggg365.info +1336592.ggg365.info +134xxoo.6600.org +135008.cn +1355188.org.cn +135se.com +136138.net +13894.com +138978.com +138cp.cn +138xxoo.com +139ads.sdsawwds.info +13fsfs.baidushisbnndbuyaoqian.cn +13kvlts.cn +13opd.com +13vv.3322.org +13you9.cn +14.meimei855.cn +14360.3322.org +146.xdwan.cn +14647.cn +147gh0.3322.org +147xxoo.com +14sel.com +14ssaacaa.cn +14xxoo.com +150gho.3322.org +150wyt.com +1515.net +151down.3322.org +1520ai.kmip.net +152down.3322.org +1541005.28002010.34414.com +159xxoo.com +15abo.com +15hamei.3322.org +16207.nznz.net +163.123fga.cn +1633.in +163cp.com +163e.fx.to +163rfg.com +163wangri.net +163wyt.com +163xxoo.com +163zn-dh-com.top.to +164wyt.com +165se.com +166999.com +166cai.com +168.123fga.cn +1688xungou.com +169.123fga.cn +169xxoo.com +16june.notlong.com +16w.just360.mo.cn +17.173sese.net +17.17selang.com +17173jw.com +173wyt.com +174.37.82.9-static.reverse.softlayer.com +174mm.com +17598.800z.net +1777.hk +17abo.com +17bose.com +17cmm.com +17ebook.com +17gby.com +17l73.search.yx1l.cn +17nnn.com +18.w88w8w.cn +18022009.com +180cpw.cn +18237.800z.net +1859yhu.qa111.8866.org +186.my319.info +186cctv.com +187asdiebfgs.3322.org +188.gck6.cn +188218.com +188966.com +188bt.com +189go.cn +18jlurp.co.cc +18mm.azzwg.cn +18xxx.ns2go.com +18yuy.com +19079.800z.net +190zn001.6600.org +191188.com +1919mnd.3322.org +192988.com +192ee.com +192ee.info +192ee.us +192jb.info +192lj.info +192mm.info +192qj.info +192se.info +192ss.info +19334.com +19743.yfyf.net +198148.com +19ccc.com +19eee.com +19p2p.xdns.eu +19selang.com +19vvv.com +1a123.com +1ct.3322.org +1d.2288.org +1d407.hp.ipc.la +1d865.ld.tcp.cc +1foxfiisa.com +1h2l3g.3322.org +1hougong.info +1j7g.3322.org +1j9x.3322.org +1l1l1l.3322.org +1love11.3322.org +1newsreport.ne +1nid.3322.org +1o9o.3322.org +1oo86.net +1sese.info +1seweq.cn +1sexin18.com +1www.4qqxx.com +1wx3ff.3322.org +1wyl.com +1x7c.3322.org +1xin1yi.com +1y5hrg7.8866.org +1z.2288.org +1zhifu.10.cname.in +2.1234llll.com +2.17nnn.com +2.18bt.info +2.1xiao77.com +2.27nnn.com +2.51qs.info +2.555mi.com +2.666mi.com +2.66aaaa.com +2.7k.cc +2.82nnn.com +2.82yyy.com +2.99dizhi.cn +2.axiao77.com +2.axwdd.com +2.bbs99.info +2.bbslc.com +2.boksx.com +2.clxwe.com +2.cnswz.info +2.csly.info +2.cxzzd.com +2.dingxiang.biz +2.doxws.com +2.dushiyuan.info +2.exksc.com +2.fuwxh.com +2.ganbobo.com +2.googlelianmeng.9966.org +2.hixiao77.com +2.hupxw.com +2.ixwsy.com +2.jinfuren.info +2.sewo.9966.org +2.sqwyl.com +2.wwwddd.net +2.xinba.info +2.yxnjs.com +2008.fang8.com.cn +20080808888.com.cn +2008222.com +2009-taobao.com +2009-yahoo.xxcfd.cn +2009.renxian114.cn +200909.cn +200912172002.2288.org +200988qq.cn +2009999.com +2009cctv61.cn +2009cctvk.com +2009download-best-soft.com +2009fv.cn +2009fxfd.cn +2009fxmx.cn +2009fxvc.cn +2009kabasiji.com +2009qa.cn +2009qq888.cn +2009qqcom.cn +2009sina.eu.kz +2009t.8qbe.cn +2009v8.cn +2009viv.cn +2010.zdfdgf.3322.org +201001.8866.org +201001.9966.org +2010down.cn +2010qqvip.com +2010xi.pq.to +2011.ttdk2.com +2012qq.baoze.com +202.sscq4f.com +20285.com +2046yxwcom.tzsx229.2666.com.cn +208188.com +209678.cn +20gan.com +20mx20.3322.org +2121hjk.3322.org +213122.lerqu.com +2133.01j.info +218318.cn +21899zz.tk +22.bbexe.cn +22.pzwm.info +221331.net +221441.com +221441.net +221607da1227.camilium.net +222.gamealitysa.com +2222-qq.cn +2222xb.com +222mi.com +22ccc.info +22ccdde.3322.org +22ee.8866.org +22ger.cn +22kk22.3322.org +22lax.3322.org +22ndbest.googlepages.com +22qsw.com +22saew23.cn +22woool.cn +230it.cn +232323244333.3322.org +233game.cn +234315.cn +234444.com +234871938123.cn +234ijdcbgakf.3322.org +234oaidnhtkd.3322.org +239168.com +23bi.com +23dnfwg.com +23fffb.3322.org +23oyes.3322.org +23weer.778652.com +23weg.bnr56.cn +2493.kjhds.info +24dd24.3322.org +24gao.com +2502.nznz.net +2537.800z.net +255188.cn +258255924.dns8zy3.cn +2586.twgg.org +258ak.com +258wyt.com +25isese.com +260555.com +263267850085.movie2new.in +263388.com +265cai.com +265uu.com +268788.com +26889.net +269988.cn +26c26.3322.org +26gao.com +2783ueiiw.cn +27d27.3322.org +27nnn.com +27x27.3322.org +280wyt.com +282850.cn +28365365.com +28773.cn +289363.ctc-w159.dns.com.cn +28a.3322.org +28bxg.com +28fa.net +28gan.com +28xxc.3322.org +29017.com +297gan.info +29cao.com +29v.3322.org +2aaxx.com +2aini.kmip.net +2asxswww.cn +2b.mainpage.cc +2b.perfectexe.com +2b.yigeyuming.com +2bxbx2.3322.org +2d2d2dsd.3322.org +2f6l966.2288.org +2fa.3322.org +2fcc.com +2ijdi.cn +2jjxx.com +2jsc.cn +2m2m.kmip.net +2nid.3322.org +2ok.cz.cc +2qtw.cn +2r2r2r2.cn +2sacv5h.3322.org +2scf.com +2vd.benpao2020.com +2wdqwdqw.cn +2x3x4x5x6x7x8.count.xj.cn +3-45654.54654.354354.357.65685.info +3.1234llll.com +3.1666x.com +3.32cs.com +3.567dx.com +3.ajehe.info +3.axiao77.com +3.axwdd.com +3.boksx.com +3.clxwe.com +3.cnswz.info +3.ctrl.fajujohiv.cn +3.cxzzd.com +3.dx22.info +3.exksc.com +3.fuwxh.com +3.ganbobo.com +3.hixiao77.com +3.honghua.info +3.hupxw.com +3.ixwsy.com +3.kkmm8.com +3.meng3130.cn +3.sejie2000.info +3.sesebbs.info +3.sewo.8866.org +3.sewo.9966.org +3.wo99bbs.info +3.wwwddd.net +3040500.cn +306888.cn +30776.com +308268.cn +308cp.com +308gg.cn +30ju.notlong.com +30mm.azzwg.cn +311113.com +31441.com +318555.com +318x.com +31t.3322.org +3219fon221.mobi +321xxoo.com +322188.com +32325daa.cn +326g.com +32dfdaadfe.3322.org +32gvdvbnn.6600.org +32j.3322.org +32veb.cn +33.aregular.info +330h54.6600.org +3310.net.cn +331888.com +332255.com +332336.com +3328gp.com +332998.com +333013.com +3333-qq.cn +3333xb.com +333dert2.3322.org +333ds.7766.org +333gdre.8866.org +333mi.com +333mmm.360yyy.8800.org +3355688.cn +3355hh.360yyy.8800.org +335889.com +3374.com +33aaaa.com +33hrhec.7766.org +33sf54.cn +33vcv.2288.org +33we3v.2288.org +340.9966.org +3421sadf.waa.91haomm.com +343.boolans.com +3432333.7766.org +3432343.8800.org +3433333.3322.org +34567wyt.cn +345866.cn +345xb.com +34618.com +34gao.com +350088.com +35465543.com +35523.3322.org +356755.3322.org +360.94makelove.com.cn +360.be.ma +360.c99b.cn +360.cdd1.com +360.cn.97sewo.3322.org +360.hrbxld.com +360.qc.cx +360.xl.cx +360.zik.dj +360caonima01.3322.org +360ccccc.se0.3322.org +360cn.com.risinimenma360.9966.org +360cn.se0.3322.org +360gan.com +360gg.wyt2021.net +360loveme.3322.org +360safae.cn +360safe.9966.org +360safebox.9966.org +360sb.3322.org +360se.ay199os.8866.org +360woaini.8800.org +360xxoo.com +36186.cn +36366.info +365.gogogoav.com +365.kv900.com +365.tv190.com +365.tv660.com +365dizhi.com +365ggg.info +368618.com +369bo.com +36O.8866.org +36cn.com.risinimenma360.9966.org +36du2.fde1.cn +3736ff.cn +37588.com.cn +37renti.com +38.azzwg.cn +38.us.to +3838738.com +3838cp.com +3872.qrqr.net +388-qq.cn +388488.com +38jjj.com +38xxoo.com +38zu-cn +38zu.cn +38zz.info +39807.com +39av.com +39cq.net +39sese.com +3D2666.cn +3as45sad4f5.3322.org +3b.iwillhavebigdick.com +3b3.org +3ba3h.cn +3bomb.com +3color3.com +3d0099.cn +3d1212.com +3d166.com +3d3188.com +3d3868.com +3d479.com +3d4888.net +3d49.cn +3d5000.com +3d546.cn +3d55.com +3d5688.com +3d5805.cn +3d6555.com +3d670.cn +3d7778.cn +3d818.com +3d827.com +3d8568.com +3d8848.com +3d8886.com +3d90.com +3d908.cn +3d917.com +3d9206.cn +3d9369.com +3d9698.cn +3daaaaa.cn +3dc989.com +3dchina.cc +3dcp98.com +3dcplt.com +3ddmm.com +3dfrr2.cn +3dlt.cc +3dw328.com +3e5a2.redguarder8.com +3eifj.cn +3ggt.kmip.net +3gh56g.8866.org +3gmyku.com +3god.net +3gqqchaoren.com +3m.vpsvip.com +3mrazi.cn +3ok.cz.cc +3ons.cn +3qsa.cn +3qyl.com +3rdsddsd.7766.org +3sa11111111111dwawq.cn +3tk.3322.org +3w.08ai.info +3y.2288.org +4.1234llll.com +4.33lc.com +4.aicbbs.info +4.bbs99.info +4.ctrl.fajujohiv.cn +4.cy265.info +4.daqinbbs.info +4.emodao.us +4.exksc.com +4.hxut.net +4.ixwsy.com +4.jinfuren.info +4.languifang.info +4.mimihuayuan.info +4.mishi.info +4.pinsetang.info +4.wwwddd.net +4.xiaoyaogong.info +4.xinbali.info +4.yuelai.info +4000se.com +400kg.bolapaqir.net +40556.Com +417nono.azzwg.cn +419500cu.www7.910idc.com +41nnn.com +426199.139.hostcn.cn +4321.888888ok.com.cn +432432ddsd.8866.org +43254543534.9966.org +432ddsds33232.8866.org +4332.kjhds.info +43453dsafdfa.cn +435434535.3322.org +43iii.2288.org +444.nyny1111.com +44411ffaa.cn +444mi.com +44559.cn +44aaaa.com +44ghe.cn +44hrhec.7766.org +44l.info +44uuu.com +44wen.com +4523er.cn +4534rr232323.cn +454126.8800.org +45476.com +455900.cn +456.as22456.cn +456.ds11aa.cn +456.ee22456.cn +456.grime456.com +456.qq22456.cn +456.ww11456.cn +456.ww22456.cn +456229.net +45678.org +456cao.com +456sese.net +456sese.web.fc2.com +456ss.cn +45nnn.com +46.3388a.cn +46.765321.info +46603.com +466555.com +4666888.com +46yh676.6600.org +47528.cn +47565.normanokj.info +47822.cn +47ybnzo.o.o.il.vlfk.os.972wyt.com +485800.com +488cp.com +4897.kjhds.info +48gan.com +4918.hk +4961.3322.org +496649.com +4aaxx.com +4ddxx.com +4fcsqda.cn +4gaga.3322.org +4gameranking.com +4gghh.com +4go2com.net +4go4i9n76ttwd.cn +4grb.cn +4inlove.mooo.com +4j3j.cn +4max.pl +4meganet.com +4n.jqmxnn.cn +4p.qqtv.me +4r.3322.org +4sel.com +4selang.com +4sx2.cn +4t34t.56jrr.cn +4t6nhh.6600.org +4utraffic.cc +4utraffic.com +4utraffic.org +4wowgold.com +4y553r7.8866.org +4y5jhg.8866.org +5-qq.com.h001.51mydns.cn +5.2008hhg.com +5.baigong2000.info +5.dushiyuan.info +5.lamb2000.info +5.mishi.info +5.sesebbs.info +5.ts2000.info +5.usmonk.info +5.xintianxia.info +5000se.com +500xxoo.com +503999.com +506google.3322.org +507google.3322.org +50checkingyourtraffic.com +50wu.cn +51.kkpp8.com +51.tok77.com +51000qq.241.host.gomeidc.net +511google.3322.org +5138.kjhds.info +5151kan.net +5151li.cn +516j.3322.org +519google.3322.org +51ecpss.com +51momo.woy3.cn +51momo.zx3k.cn +51she.info +51vv9.cn +51vvc.cn +51xcn.bee.pl +5203389.9966.org +520883.com +520spmm.cn +520zhidao.cn +521dx.com +521wyt.com +522dx.com +522google.3322.org +522wyt.com +523google.3322.org +524485072.cn +5252b.com +5252bb.com +5252bo.net +5252se.dh086.cn +52833.com +52bo52bo.com +52sax.cn +52ssss.net +52x52.net +5328606.ONS5.COM +533377.com +535488.cn +538788.com +53aaa.com.cn +53cao.com +53efe53.cn +53gan.com +53kkk.x-wyws.com +53kkk.xl111.com +54057.cn +54271.com +5435433.8866.org +5435434.2288.org +5435646.2288.org +549885.3322.org +54dj3.cn +54g.qa222.8866.org +54sese.com +55.sewo.9966.org +55.yhs1234567.3322.org +550575555.3322.org +5513.900y.net +55356.cn +554313.3322.org +555.afsdff.3322.org +5555.qq.121.9988996.qq-baidu-vip.cn +555555666655.yhs12345.3322.org +555666888.com +55566884.3322.org +555bfdghf1.3322.org +555cpw.com +555gdre.8866.org +555mi.com +555mi.net +555ttyy.cn +5566456.com +5566456.net +556tv3.com +558-qq.cn +558q.cn +55crw.com +55rrew.3322.org +5617.3322.org +56238.com +563f235.cn +56665568822.8866.org +566699.com +56749.cn +56780.ss.la +567890.ss.la +567dx.com +568166.com +56gvdfg444.2288.org +57.97ye.com +57379.myokj.info +577666.com +578008.cn +578la.com +57rb.com +57yin.com +58.w88w8w.cn +580.dnf5.com +580999.com +58410.normanokj.info +586388.com +588.gck6.cn +588.xhv2.cn +588456.com +58fcw.cn +59-34-198-113.3322.org +5900.kjhds.info +5918.8866.org +591rb.com +59579.cn +59659.cn +5971s.cn +59ukjff.9966.org +5b.jqm5b.cn +5bn2.cn +5bqq.net +5dsa4d.cn +5gegre5.8866.org +5iav.net +5iqqmm.com +5jyss.com +5l2o8.com +5l7mm.com +5pam.3322.org +5qqcc.com +5r3xq1.cz.cc +5sads33.cn +5sese.info +5t434ffss.3322.org +5t8.tv707.info +5u454.8866.org +5u66j.cn +5we5.com +5wwdd.com +5yttrre.cn +6.000wyt.com +6.csly.info +6.morok2000.info +6.moviesgolden.com +6.sejie2000.info +6.sl2000.info +600906.com +600925.com +602hh.cn +6070.9966.org +60gan.com +61-cctv2.com +61222.com +61av.com +626028.cn +628388.com +62ai.com +62moo.cn +63188.com.cn +633999.com +6366.kjhds.info +63ke.com +6413.kkgg.net +644888.com +64838.com +64xxx.com +654.qrqr.net +655705.com +655996.cn +658wy.com +65gao.com +65gd.cn +65uttt.cn +66.qq99.in +66.sewo.9966.org +6610.net +661789.com +6618.kgkg.net +661cn.com +66289.com +666.dclsba.com +666.qaqa125.8866.org +6660-qq.cn +666089.com +666128.com +666135.com +666158.cn +666345.cn +66655666.com +6666.qb.121.9988996.qq-baidu-vip.cn +666665.cn +666828.com +666mi.com +666she.com +666ssss33.3322.org +667669.tk +668-baidu.cn +668.xhv2.cn +6680668.com +668hn.cn +66aaaa.com +66aaaaaa.com +66cc.7766.org +66cp.net +66du.co.cc +66hhcc.com +66ki.cn +66qsw.com +66rfw3wv.8866.org +66tt.com +66uu.info +66yttrre.cn +677b.com +678012.com +678zf.org +67gao.com +67htyg.8866.org +67i11.cn +67ss123.cn +688cp.com +688hk.com +689cp.cn +68bi.cn +68s78.cn +69113.com +69818.cn +69mmhh.com +6f3h.3322.org +6g.q7sp.com +6hbf5.cn +6ihrh.cn +6ik76.8866.org +6mxx.com +6nnnn.com +6nxx.com +6se6420.co.cc +6see.com +6u666.com +6xx8.com +6y71.3322.org +6zg.8800.org +7-7.746.45654.5454.5467.45.5043.info +7-ya.com.ua +7.meimei855.cn +700.222mi.net +700006.com +7000se.com +700wyt.com +702kill360.3322.org +70622.com +70checkingyourtraffic.com +70kxw.com +70sss.com +710wyt.com +71701.bestxx.info +717337.3322.org +721kirkctbartol.cx.cc +722.pqpq.net +72287477.3322.org +727266eee.3322.org +731273265.520815.com +733xxoo.com +73dnf.cn +73hs.com +74315.218218.06la.com.cn +74395.normanokj.info +7461.kjhds.info +74zw.com +752s.cn +753.qqnn.net +75693.normanokj.info +757qwerty.ru +76.97qingse.com +76323.com +76456.com +765.brainchip.biz +7694.800z.net +76kjgh.7766.org +76nnn.com +76uj6j.8866.org +770772.com +771567.cn +771588.cn +771588.com +7758258se.3322.org +776148.134180.3366dns.com +777.444mi.com +777951.com +7788-99.3322.org +778998.com +778xx.com +77cpw.com +77gh44.9966.org +77pic.com +77pw.com +77ww.3322.org +77ww.dxlove.net +77yyj.8866.org +78.x9k.info +780070.134207.3366dns.com +783456788839.cn +787675.com +787999.com +788-qq.cn +78824.com +788520.com +789cp.com +78pao.com +7926.kjhds.info +79ort45nu5aaa.3322.org +79ort45nu5aaa.dyndns.org +79ort45nu5aaa.dyndns.tv +79ort45nu5aaa.selfip.net +79ort45nu5aaa.vicp.cc +7addition.info +7bs5nfzfkp8q8.cn +7crw.com +7ddxx.com +7dnfwg.com +7ggrr55.8866.org +7hero.lianmeng2010.com +7ikaya.com +7lovr.cn +7qusi.3322.org +7sdy.com +7sese.info +7tttc.jjkkdd55.cn +7y.3322.org +7yt.us +7zju2l82i2zhz.cn +8.2009iii.com +8.23cao.com +8.acbbs.biz +8.bluesky02.cn +8.mymonk.net +80077.net +800810down.cn +800cai.com +800cpw.cn +800ddz.com +809678.cn +80ssx.cn +810wyt.com +816868.com +816xx.com +82346.com +828qq.cn +82nnn.com +82yyy.com +8336f.cn +83377.com.cn +8358.kjhds.info +83gedg.8866.org +83xx.info +844666.com +8475.770304123.cn +849628.3322.org +84gao.com +84gho.3322.org +84ry.cn +84u9wb2hsh4p6.cn +854fr5r.8866.org +855858.com +856333.cn +857.e2d.mydoudizhu.cn +857695.3322.org +858581816.go.qqcft.cn +85gov.cn +85l6.com +85rrr.com +865558.com +866nu.cn +87006.cn +871cc.cn +87ai.info +87kyt.8866.org +87xs.8866.org +88.perfectexe.com +881666.com +881882.com +881kk.com +884666.com +88512.cn +8862.fileave.com +8866ctv.com +88777.info +888.46se.com +888.67sese.com +888.843call.cn +888.97qingse.com +8880.cc +8884.cc +8884.ss.la +888579.com +88881121223888.rulvbobingainimadeqiu.3322.org +888859.cn +8888877777.com +8888se.com +8888ye.com +888cao.com +888cpw.com +888k7.com +8899456.com +889sese.cn +88cai.com +88qingse.com +88u88.3322.org +88xiaoshi.3322.org +88yutur.8866.org +88zka.3322.org +893d.com +896699.cn +89777.net +898222.com +898655.com +899099.com +899266.com +89dx.com +89nnn.com +8c02.ppyyuu.cn +8ddfx.cn +8dfgdsgh.3322.org +8ejsuea.cn +8ekdje.cn +8f8el3l.cn +8geg655.8866.org +8gggg.com +8ggre5.8866.org +8gtu.com +8j4gg.cn +8lz4.cn +8man4.3322.org +8man5.3322.org +8n20.aabbcc258.cn +8now.info +8oy4t.8866.org +8q00q0.2288.org +8q00q2.2288.org +8q00q3.8866.org +8q00q9.8800.org +8q01q9.3322.org +8q03q9.8800.org +8q06q9.8866.org +8q07q9.9966.org +8qqcc.com +8u78.36tt.3322.org +8uuu.36tt.3322.org +8y10.ppccss.cn +8yyxx.com +9.5252se.name +9.ctrl.fajujohiv.cn +9.kisskissus.com +9.lcyl.info +9.product8.cn +9.yanzhaomen.tv +900788.com +900wcp.cn +901s.count.xj.cn +902a9.3322.org +90337.com +90954.mysxc.info +90hou.count.xj.cn +911955.com +911av.com +913ain.com +91555.tw.cn +9158.999999998.com +91665.com +919a5.3322.org +91cmm.com +91k.us +91porn.aa.am +91porn.com +91pz.com +91rbr.com +91rpp.com +91wav.com +922088.cn +922788.com +928x.cn +929767.com +92d.cz.cc +92sesese.cn +92tc.net +92union.com +92xoxo.6600.org +92xxoo.6600.org +92xxoo.cn +92xxoo.com +92xxoo.org +93485163126841.19855.info +93i9u9.cn +93nnn.com +93san.com +93ui2i.cn +93wx2009qq.cn +941bb.com +944443.com +945s.com +9481.3322.org +9495.in +94gao.com +951ac.cn +951ax.cn +9527idc.vicp.net +9534google.jefhhe.com +954ger.8866.org +9553dc.cn +95fere5.8866.org +95selang.com +95wen.com +9649.kgkg.net +966543.8866.org +96862.mysxc.info +9687.kjhds.info +97-97gan.com +97.163wyt.com +97.235wyt.com +97.38fang.com +97.44wen.com +97.48gan.com +97.533dx.com +97.700wyt.com +97.710wyt.com +97.810wyt.com +97.972wyt.com +97.97ye.com +97.aafang.com +97.ggfang.com +97.niwyt.com +97.rxingdh.info +97.sao86.com +97.sao94.com +97.sao95.com +97.tongletang.net +97.wytmimi.com +97.x-wyws.com +97.zenggao.cc +970av.com +970xxoo.com +97530.cn +977789.com +978555.com +978989.com +97ai97ai.co.cc +97cao97cao.1stfreehosting.com +97de.com +97gan.in +97gan.ttcrw.com +97khp.com +97mama.com +97mimi.com +97p1mm.com +97piao.com +97plmm.com +97qingse.com +97rib.com +97se97gan97se.info +97sexsexbaidu.info +97smm.3322.org +97ssl.cn +97ssw.222mi.net +97ssw.40sese.com +97ssw.67sese.com +97ssw.97bose.com +97sw.aa.am +97sw.cz.cc +97sw.don.tw +97sw.oo.lv +97sw.twbbs.org +97sw.twgg.org +97url.com +97wen.com +97wenwen.com +97wuyue.jijiyy521.cn +97xxoo.com +981777.com +982.9966.org +9821g9.cn +983211.vicp.net +983h2.cn +985528.cn +98577.mygodgod.com +988ddz.com +988wyt.com +989788.com +9899.cn +99.17vvv.org +9906688.com +9914w.cn +991567.cn +991gooegleoe1.3322.org +9934.info +9949.cc +996733.net +997wyt.com +999538945.com +999jjj.com +999ok.kmip.net +99dxdx.com +99j4.org +99kap.com +99kou.com +99plmm.com +99se.8800.org +99uiiu2.cn +99xjw.com +99xxbbbcc.36tt.3322.org +9ba.info +9bse.3322.org +9buu.com +9cmm.921k.com +9cmm.com +9eevip.cn +9gghh.com +9ikd.3322.org +9jjxx.com +9kb.3322.org +9ke8.com +9kq.3322.org +9kss.com +9mckde3.cn +9nnnn.com +9owe2211.cn +9qqcc.com +9qqxx.com +9sba.cn +9sese.info +9smm.com +9soldo.info +9ssdd.com +9v2.3322.org +9wxx.com +9x2x25.cn +9xddw2.cn +9xxoobbcc.3322.org +9xxx33.cn -jian,zhi -jian。zhi -jian,zhi -jian\.zhi -jian?zhi -jian\?zhi -jian\/zhi -jian!zhi -jian@zhi -jian#zhi -jian¥zhi -jian%zhi -jian\^zhi -jian&zhi -jian\*zhi -jian-zhi -jian\[zhi -jian\]zhi -jian【zhi -jian】zhi -jian·zhi -jian:zhi -jian;zhi -jian~zhi -jian_zhi -jian—zhi -jian\:zhi -jian!zhi \ No newline at end of file +Ac.qvxd.info +BSDY.INFO +CUIQING.NET.CN +QQtt588.cn +Qvod.Down.vbn5.cn +Searchportal.yousee.com +Vip-tbof.cn +WWW.CUIQING.NET.CN +YSDY.ORG +a-pp.110mb.com +a.07ss.com +a.11didi.com +a.12c.cn +a.12yue.info +a.13sel.com +a.14sel.com +a.222mi.com +a.22niu.com +a.30niu.com +a.333mi.com +a.33lian.org +a.33niu.com +a.369bo.com +a.40sese.com +a.44386.com +a.44didi.com +a.44hu.com +a.44mao.com +a.46se.com +a.4qqbb.com +a.521wyt.com +a.57bi.com +a.5x7x.com +a.654se.com +a.67qssky.com +a.67sese.com +a.6x3x.com +a.77xxoo.info +a.94383.com +a.94saomm.com +a.94ses.com +a.95622.com +a.95bb.info +a.97aibo.com +a.97wuyue.com +a.97xxmm.com +a.9k6k.com +a.aa1b2.com +a.aa88567.cn +a.aihuawd.com +a.aiqi.info +a.avdy8.com +a.boboxxx.com +a.brsqb.cn +a.cao11.com +a.cao55.com +a.ccw12.com +a.cdd1.com +a.com +a.dlzyjx.com +a.f5nn.com +a.f6nn.com +a.f8e4.com +a.ffqqq.net +a.kaixinfou1.com +a.kiji884w.cn +a.kkqqq.net +a.liao7749.com +a.liaobamm.com +a.liaojiewo.com +a.link8.net.ru +a.lxwar.com +a.moneymoney888.com +a.naxieren99.com +a.ncw.meibu.com +a.niwyt.com +a.oye333.com +a.paowyt.com +a.qqav.info +a.qs512.com +a.release.51edm.net +a.rtbn2.cn +a.salemxm.co.cc +a.se94se.info +a.sun003.com +a.tongletang.net +a.tuxiao77.info +a.ugu123.com +a.update.51edm.net +a.uuzhijia.info +a.wuc9.com +a.wuyuepk.com +a.wymfw.org +a.xc38.com +a.xc82.com +a.xin7778.com +a.xsjsb.coyo.eu +a.xyxy.info +a.yese.biz +a05.xfbfgw.com +a0691.w01.rste.info +a09230.917.rste.info +a09250.917.rste.info +a0v.org +a1.518js.com +a1.igr5s.com +a1.lxwar.com +a1.nvyouba.cn +a1.pzxz8.com +a113.9966.org +a114.9966.org +a119.9966.org +a1baidu.cn +a1r.zhao123.info +a1s.9966.org +a2.364736.com +a2.lvguihua.com +a212hx.blog.163.com +a222.dnf5.com +a24913.kingstable.com.cn +a2dg2o.cn +a3.666pz.info +a3.lvguihua.com +a3815.kingstable.com.cn +a3ny.8866.org +a5l.at +a6.666pz.info +a63714.kingstable.com.cn +a654321.cn +a66253.kingstable.com.cn +a6633.net +a6ga6.cn +a6tt4.114anhui.com +a777.dnf5.com +a88q.cn +a89iiuapxjh.in +aa.1791xx.com +aa.17qin.info +aa.32ps.com +aa.40sese.com +aa.555mi.com +aa.978kk.com +aa.beijingxx7.com +aa.brsqb.cn +aa.daodan8.com +aa.kaixinfou1.com +aa.mimiadd.info +aa.niwyt.com +aa.tok77.org +aa.tok88.com +aa1.xorg.pl +aa1100.2288.org +aa2233.2288.org +aa234.info +aa33fer.8866.org +aa345.7766.org +aa434g.8866.org +aa44.qq66.in +aa88567.poloi999.cn +aa88x.2288.org +aa8pp.3322.org +aaa.1wbl.com +aaa.97qingse.com +aaa.aff11.cn +aaa.delete8527.cn +aaa.hao17178.com +aaa.kop536.cn +aaa.michael67.cn +aaa.setupian.info +aaa.tok99.com +aaa.vggfrf.cn +aaa.woyaosao.com +aaaa6.kmddns.com +aaaaa.fileave.com +aaaaa.haoma-haoma-gg.cn +aaaqqq.haoma-haoma-vip-buy.655.net.ru +aacompliance.com +aad.tok99.com +aaddka.3322.org +aadserv.com +aaf.xnum.cn +aafang.com +aag.xnum.cn +aagao.com +aah.xnum.cn +aaphonecard.com +aar.bij.pl +aarocket.com +aas.tok99.com +aasantarita.com +aasese.com +aaskereia-online.de +aau.bij.pl +aawekq.grandisecurity11.com +aaz.bee.pl +ab.ie222.com +ab1.x7js.com +aba.bee.pl +aba.bij.pl +aba.dns0755.net +abaozhuce.cn +abc.geglete.cn +abcaaaaaabcd.rulvbobingainimadeqiu.3322.org +abcabbaaabcd.rulvbobingainimadeqiu.3322.org +abe.dns0755.net +abe.nna.cc +abf.8866.org +abf.nna.cc +abg.nna.cc +abh.dns0755.net +abh.nna.cc +abi.dns0755.net +abi.nna.cc +abitsystem.com +abj.8866.org +abk.8866.org +abk.dns0755.net +ablegang.com +ableh.biz +abminute.com +abn.dns0755.net +abo.dns0755.net +abodeflash-vol82.co.tv +abonlinelive.com +abools.net +abp.dns0755.net +abretor.com +abt.dns0755.net +ac.qvoz.info +acc.dns0755.net +acctv6.s130.288idc.com +acd.dns0755.net +acerprotection.com +acesofts.info +acg.dns0755.net +acr.dns0755.net +acsawwn22.info +act.dns0755.net +act365.com +actionb.3322.org +active.b2b.hc360.com +acu.dns0755.net +acv.dns0755.net +acx.ht.cx +acz.dns0755.net +ad.1048101621.cn +ad.13ybx.com +ad.2112111.com +ad.51595.com +ad.ad58.info +ad.ghura.pl +ad.googlesyndications.co.cc +ad.hskpp.cn +ad.inewsweek.cn +ad.keyrvn.co.cc +ad.mydown.org.cn +ad.mydz99.com +ad.nu99.com +ad.suoie.cn +ad.tok77.org +ad.tok88.com +ad.vrbrothers.com +ad.wdtx.net +ad.xxvb.info +ad123.info +ad6.bb9922.cn +ad6.e-quan.com +ad79.co.kr +ad999.8800.org +adafapa.cx.cc +adcavern.com +add.917wan.cn +addictionprones.info +addobeflashplayer.net +addononline.com +addvertseense.co.uk +adekniep.info +adenpshabvf.com +adeui.com +adgob.3322.org +adgorge.com +adjee2.zoomshare.com +admin.bbexe.cn +admin1.w51.9410.com +admin6.net +adnfd.3322.org +adobe-flash-04.co.tv +adobe-flashplayer-install.com +adobe-v011.co.tv +adobecodec-01.co.tv +adobenew-exe.co.tv +adordota.com +adorelyric.com +adorepoem.com +adoresongs.com +adriano121922.sites.uol.com.br +ads.20-12.cn +ads.20-14.cn +ads.hanju123.com +ads31.3322.org +ads56.qq995c.cn +ads6.dctgz.cn +adsa.sv3.swe23.cn +adsms.1oo86.net +adsms.itodo.cn +adult-cube.net +adult-loop.com +adult-sex-games.com +adult.oo.lv +adultping.net +adv.blinw.com +advancedwebanalytic.com +adventurewaspos.com +advertisingassistants.info +adviceswarning.com +advicewarning.com +adware2010.com +adware2011.com +adwarecheck.com +adwareguard.net +adwareprofesional.com +adwareprofessional.org +adx.2288.org +aeefdar34.3322.org +aeo5p.cn +aerostuff.ru +aeu.bij.pl +aeu44ry.cn +aez.bij.pl +afedewascet.com +afi.bij.pl +afra5.com +afrijam.co.za +aft.bij.pl +afx.bij.pl +ag268.com +agjt1h.cn +agkiws.com +agl.3-a.net +agn6m.cn +agofa.cn +ags.bij.pl +agu588.com +ahqqs.mazpunet.cn +ahthja.info +ahudswww.cn +ahulafertagov.com +ai.132xxoo.com +ai.321cao.com +ai.345xxoo.com +ai.523xxoo.com +ai.567xxoo.com +ai.720xxoo.com +ai.920xxoo.com +ai.970xxoo.com +ai.wyt95.com +ai8k.com +aibabamama.vicp.net +aibiwang.com +aiicakep.fileave.com +ailbay.com +ailuo8.com +ailyes.3322.org +aimic-groupllc.asia +aimic-groupllc.at +aimic-groupllc.cc +ainihb.cn +ainikv.cn +ainiln.cn +ainioo.cn +ainirr.cn +ainiuu.cn +aiom-sdo.cn +aion-sd0.com +aion.mmsdo.com +aion.oosdo.com +aion.rysdo.com +aion.sdoao.com +aion.sdomo.com +aion.sdosn.com +aionj.com +aionyy.com +aiouosd.com +aisee.1stfreehosting.com +aisese.lookin.at +aixisnew.cn +aiyanxinxi.com +aj.tg.niux88.com +aj68.com +ajas.ath.cx +ajg.htmi2.com +ajjyes.3322.org +ajjyes.cn +ak-da.cn +ak47.x10hosting.com +ak477.8800.org +aka.3-a.net +akdnf.com +aksajans.com +aksldhtiaads.8866.org +al2mckdf520.cn +alan.p9555.cn +alananlaw.com +alexa.houdao.org.ru +alfafoxx.com +alhatester.com +alien333.mine.nu +aligate32.com +alimcma.3322.org +all11oa.xxnz315.com +allavers.org +alleips.com +allfilesstorage.com +allfree-games.com +allsoftportal.com +alltime.vn +alltj.lltjxx.cn +allyourguide.cn +alnnama.3322.org +altipesa.com +alww-ts.cn +am-qq.com +am7788.com +am855.91mt.com +amadox.nl +amateurmovies.in +amerika.by +amforacalistro.info +amjc.3322.org +aml.ch.ma +amnepofig.ru +anaeldating.nl +analytics.google.com.server.main.updates.25-com.cn +analytics.hosting24.com +analytics.prosecures.com +analyticsadvanced.com +anampohui.cn +anayamand.cx.cc +anc-news.ru +andazin.ru +andromalen.cx.cc +andy.cd +anella2009.dominiotemporario.com +anet123.com +ang.3-a.net +animalelectricity.info +animalthemes.info +anjing.ignorelist.com +anlim.pp.ua +annbortakimcastollvivi.c0m.li +annil.8866.org +anotherdomainname.in +anq.3-a.net +anten3.zoomshare.com +anti-malware-scanner.com +anti-virus-professional.com +antiabusee0ffice.com +antimalware-pro-scan.com +antimalwareguardplus.com +antispyware-scan.net +antivirplus2009.com +antivirus-live.com +antivirus-powerful-scan.com +antivirus-test-xp.com +antivirus-upd.co.cc +antivirus360-protection.com +antiviruspc-update.com +antiviruspcfullscan.com +antivirusplus09.com +antivirusplus2010.com +antiviruspowerfulscanner.com +antivirusxp09.com +antivirusxppro2009.com +anyong.maya777.com +anysns.com +anz.3-a.net +ao29w8mv02.3322.org +aokdjfnuansj29.3322.org +aplusdrivingca.com +apm.3-a.net +apple.9655.info +apple.skincaremiracle.info +apsight.ru +apteki-optima.com +aq-anquan.com.cn +aq-qq-server.3322.org +aq.dna.service.tcenceni.com +aq.qq.com.dna.gci-bin.cn +aq.qq.com.inuscver.cn.la +aq.qq.com.tencent-cw.com +aq.qqsercvice.com +aquan-qq.com +aquarius.myvnc.com +aquila-divorce-recovery.co.uk +aramategroup-first.cc +arclane.com +ardhmeria-juaj.com +arhetector.com +armmobilya.com +arphia.com +arplgm.cn +arquivostop.webcindario.com +arsofcaribion.com +art3d.ar.funpic.de +artificiallanguages.info +artvol.com +ary-neigeborn.com +as.tok77.net +as.tok88.com +as03.youggon11.com +as1.tvb.dtdns.net +as66118518.3322.org +asa.2288.org +asc20.com +asd.xl.cx +asd12.com +asd9wea.3322.org +asdawe.cn +asdd.etowns.net +asdf.52zy.com +asdf.dnf5.com +asdfadgtyuyipfgjns.cx.cc +asdgfqws29.3322.org +asdkdfg.3322.org +asdklj.cn +asdrewwyqs7.3322.org +asdwdwdq.cn +asdww2322.cn +asdzxc.com +asdzxczq.cn +ase1d.cn +asfabdsksaf.2g513d.info +asm32.9966.org +asmoights.com +asp.3-a.net +assets.qqhe.com +astl.vicp.net +astrumavrpro.com +asuslasrnt.com +aswaqweb.com +asxe.info +at.asr8.com +atfa.qqww.us +atiqad.cn +atorat.be +au-qq.com +au4399.91mt.com +auctene1-taobao.com +auctian1.taobaow1.cn +auctiom1-taobao.com.cn +auction1-ta0oba0.cn +auction1.baotit.cn +auction1.baottg.cn +auction1.taobiee.cn +auctionsstockbroker.info +augbbs.cn +auto1.zbinfo.net +autodoregison.ru +autowines.info +av-39.com +av-best.info +av-updates.cx.cc +av.1234av.com +av.17abo.com +av.17gby.com +av.18abo.com +av.19selang.com +av.2009ai.com +av.369xb.com +av.511av.com +av.5jyss.com +av.9292se.com +av.94aq.cn +av.95ai.com +av.9gaoav.com +av.9kss.com +av.bluesky08.cn +av.gaoav77.info +av.mmt1.com +av.mv57.com +av.segg.info +av.ss99ss.info +av006.com +av112233.com +av361.com +av4321.us +avapian.com +avas.3322.org +avast.bbgg88pp88.cn +avast.llooppookkk.cn +avast.maxjust444.cn +avast.maxjust999.cn +avdvd.xxss.info +avdy8.com +ave1.cn +ave2.cn +ave3.cn +averi-idite-nah.com +aveylpa.cn +avg.nna.cc +avipa.3322.org +avlang.com +avlang.net +avmeinvtu.cn +avonlineprotection.com +avotion1-paipai.com +avse.sewytwang.info +avsteel.cn +avzhan1.3322.org +awebunitra.com +awesomemedsnoble.com +awfgzd.webcindario.com +awwwsdvd.cn +ax8888.go.3322.org +axnqswzbfj.cn +ay521.com +ayahaha.36tt.3322.org +azqqdv.cn +aztnc.net +azulydo.cn +azureus-installer.ivefound.com +azwyt.com +b.222mi.net +b.22niu.com +b.40sese.com +b.44b4.com +b.44ygc.com +b.551xxy.com +b.5x7x.com +b.66green.com +b.6x3x.com +b.94saomm.com +b.97wuyue.com +b.aa1b2.com +b.dfg54.cn +b.dgf32.cn +b.g3u4g.net +b.gde46.cn +b.goo1.info +b.hge56.cn +b.hrt45.cn +b.jqdg.info +b.jtg76.cn +b.jtv86.cn +b.mimiaa.biz +b.misswe88.cn +b.moneymoney888.com +b.ncw.meibu.com +b.nmbrx.com +b.open2009.net +b.oye333.com +b.paowyt.com +b.qq5030.cn +b.qsjyy.com +b.sejj.info +b.tt535.net.cn +b.tuxiao77.com +b.vv49.com +b.wuc9.com +b.wuyuepk.com +b.ww898.com +b.x1k.info +b.xc82.com +b.xiao77luntan.name +b.xin7778.com +b.xppclapgirl.com +b.xx7.in +b.xxoozjz.com +b.yinbbs.com +b.yiyeqing.us +b0gel.webs.com +b18zfufycvaaa.3322.org +b2c.28bxg.com +b38.4dq.com +b3g8.com +b44.4dq.com +b45.4dq.com +b46.6600.org +b47.4dq.com +b48.4dq.com +b50.6600.org +b6tt4.114anhui.com +b7p.ru +ba.bahw.cn +baa.xnum.cn +bab.xnum.cn +babi2008.com +babi2009.com +babynamesoft.cn +bad.xnum.cn +badf3.cn +badu3.8866.org +bae.xnum.cn +bag.xnum.cn +bahw.cn +baibai3.8866.org +baidmn.cn +baidu-baiguo2.cn +baidu-baiguo4.cn +baidu.07ss.com +baidu.40sese.com +baidu.97bose.com +baidu.com.n8y09r.1688.com.020of8.siwazuzoai.info +baidu.uicp.net +baidu.x0day.com +baidu.ycq2009.cn +baidu12baidu.3322.org +baidu2ha1.cn +baidu811.8866.org +baidu812.8866.org +baidu8122.9966.org +baidu813.8866.org +baidu814.8866.org +baidu815.8866.org +baidu821.8866.org +baidu8221.8866.org +baidu824.8866.org +baidu8255.8866.org +baidu826.8866.org +baidu828.8866.org +baidu829.8866.org +baiduandgoogle.jefhhe.com +baiduasp.web194.dns911.cn +baiduav.cn +baidubb1.vip137.2hezu.net +baiduduyou5.cn +baidugoogle.jefhhe.com +baiduhaigg.3322.org +baiduhao2.3322.org +baiduhao3.3322.org +baiduhaoshuang.3322.org +baidujkjkua.cn +baidumusic.3322.org +baidusab.cn +baidusib.cn +baidutdsasda.cn +baikeqi.com +bak.x0day.com +bakgm.0752huida.com +balamall.cn +balegion.com +balismart.com +bandwithcheckstart.com +bangboys.3322.org +bannerads08.com +bao-2009.cn +baokv.cn +baronessan.se +basdzsdas.com +basesrv.net +bashen.xhhow4.com +batechpro.net +batmanrobinho.com +bayuexue.com +bb.2015wyt.net +bb.297gan.info +bb.59yl.com +bb.iwillhavebigdick.com +bb.lsqbb.cn +bb.ok8uuer5.cn +bb.xxoozjz.com +bb2011.xoom.it +bb2233.2288.org +bb6oo.cn +bb88x.2288.org +bbaforyou.net +bbb.sesebb.info +bbb.xnum.cn +bbb258963.7766.org +bbb454g5.8866.org +bbbbtvv.cn +bbbddss1.3322.org +bbbfffqqq.cn +bbc.xnum.cn +bbdp.ihppefss.cn +bbdu.3322.org +bbg1.cn +bbg2.cn +bbg3.cn +bbg7.cn +bbg8.cn +bbg9.cn +bbj.118bbs.com +bbk.xl.cx +bbkkdd.cn +bbs.236z.com +bbs.335999.com +bbs.40web.com +bbs.5566456.cn +bbs.5hua9.cn +bbs.5ifit.com +bbs.67ss123.cn +bbs.9277.cc +bbs.97xxb.info +bbs.av82.com +bbs.av9000.com +bbs.avboxx.com +bbs.ccwb.net +bbs.cntuw.com +bbs.coatingol.com +bbs.guo360.co.cc +bbs.gz7c.com +bbs.hk000.com +bbs.hksxs.cn +bbs.huarencheng.com +bbs.iyn.com.cn +bbs.kafans.cn +bbs.keyruns.co.cc +bbs.lllfff.com +bbs.pxtang.cn +bbs.ruixingshadu.co.cc +bbs.sh000.com +bbs.smartet.com +bbs.smtsd.com +bbs.texnet.com.cn +bbs.tu456.com +bbs.wowshell.com +bbs.xcdx169.net +bbs2.mapeak.com +bbs2.mooo.com +bbs32.3322.org +bbs7.onlygb.com +bbsmaya.com +bbspopkart.tianctly.com +bbspopkart.tianicly.com +bbssddk.cn +bbssifu.cn +bbxx.kkkooo888.cn +bc.kuaiche.com +bccccdssse3.7766.org +bd.china0473.cn +bd334.91mt.com +bdcoast.com +bdet222.info +bea.ihyiiref.cn +beautywithbeads.com +bebookfunk.com +bedayton.com +beeblebrox.org +befud.com +beijingse.net +beike001.5d6d.com +beiyong50.3322.org +beq.3-a.net +bertlicy.com +best-soft-4youcomp.com +best222.info +bestadore.com +bestanti-virusscan.com +bestantivirusremover2008.com +bestexeworld.com +bestkind.ru +bestlitediscover.cn +bestlive-tv.cn +bestloadexe.com +bestlotron.cn +bestlovelong.com +bestofvideos2010online.net +bestvido.info +bet.netsh.com +beta.stsc.co.kr +betstarwager.cn +bexazyj.cn +bexo.2288.org +bf2ed.cn +bfahfmpyga.net +bfef03165g.bm.84.bmusahost.info +bflang.com +bfycw.cn +bgi.3-a.net +bha.vedns.com +bhhtessd.cn +bhj4w.com +bhxm.com +bi99chervud.co.cc +biao.jijiyy1144.cn +bidstrafen.com +big.1155o.cn +bigdron.com +bigfindtopguide.cn +bigfooot178.com +bigtitzsarena.com +bigumnh.com +bigxxx.d4rc.ne +bigzalupen.ru +billingpayment.net +bind.ppplllooo.cn +binolpix.com +bisque110.com +bitanalytics.cn +bitschoonerop.com +bj00852.com +bj7744.cn +bj788.com +bj868.com +bjblackhorse003.com.cn +bjcp333.com +bjcp5.com +bjcp88.com +bjcpw8.cn +bjfc3d.5d6d.com +bjp315.com +bjydzq.com +bjyinghaiwei.com +bl.donglink.cn +bla.08zs.com +black-cash.com +blackfuril.ru +blackmovies.fileave.com +blietron.com +blog.cnfol.com +blog.e23.cn +blog.ishenmo.com +blog.medicaljustice.com +blog.niupan.com +blog.qlolo.com +blog.qq.com.web-games.vip.6haoma.qm.echat.org.ru +blog.sina-2009vip.cn +blog.sina.com.cn.jdg5.cn +blog.tahidromos.com +blog20fc2.com +bloog-aranking.com +bluedisk.ru +bm-3c.cn +bmaxtow.t35.com +bmp.25u.com +bmw7x.cn +bmwsdd.cn +bn2z.cn +bn55fdswdd.3322.org +bnbnnn.cn +bnr56.cn +bntn6.cn +bo.1234vv.com +bo.25isese.com +bo.2hhhh.net +bo.bo73.com +bo.sao16.com +bo.sb333.org +bo2288.com +bo33bo.com +bobo.1aaxx.com +bobo.1gghh.com +bobo.1qqcc.com +bobo.1wwzz.com +bobo.1zzxx.com +bobo.20niu.com +bobo.2222ye.com +bobo.2aaxx.com +bobo.2ffdd.com +bobo.2gghh.com +bobo.2qqcc.com +bobo.2zzxx.com +bobo.3333xb.com +bobo.33isese.com +bobo.33xjw.com +bobo.345xb.com +bobo.3aaxx.com +bobo.3gghh.com +bobo.3qqcc.com +bobo.3qqxx.com +bobo.3zzxx.com +bobo.4444ye.com +bobo.44hu.com +bobo.44niu.com +bobo.4ffdd.com +bobo.4gghh.com +bobo.4qqbb.com +bobo.4qqcc.com +bobo.4qquu.com +bobo.4qqww.com +bobo.53gan.com +bobo.55isese.com +bobo.567dx.com +bobo.591cao.com +bobo.5ffdd.com +bobo.5gghh.com +bobo.5qqcc.com +bobo.5qquu.com +bobo.5qqxx.com +bobo.5wwdd.com +bobo.67gao.com +bobo.6ffdd.com +bobo.6gghh.com +bobo.6qqcc.com +bobo.6qqxx.com +bobo.70sss.com +bobo.77niu.com +bobo.78ai.com +bobo.7aaxx.com +bobo.7ffdd.com +bobo.7gghh.com +bobo.7qqcc.com +bobo.7qqxx.com +bobo.815xx.com +bobo.816se.com +bobo.816xx.com +bobo.8ffdd.com +bobo.8qqcc.com +bobo.8qqxx.com +bobo.91rbb.com +bobo.97bose.com +bobo.97boy.com +bobo.97gxx.com +bobo.97qingse.com +bobo.97ts.com +bobo.97yes.com +bobo.99xjw.com +bobo.9gghh.com +bobo.9qqcc.com +bobo.9qqxx.com +bobo.f6nn.com +bobo.gaoav.com +bobo.h3nn.com +bobo.sao69.com +bobo.sao86.com +bobo.sao96.com +bobo.sqwyl.com +bobo.wyt09.com +bobo.xvc19.com +bobo11.zxq.net +bobobase.com +boboboke.cn +bobosuper.3322.org +bobunium.com +bofangqi.6gg.cn +bojatools.avx.pl +bolapaqir.com +bolapaqir.net +bolbos.co.cc +bonwe2.9966.org +boob.perfectexe.com +book001.3322.org +book009.3322.org +book010.3322.org +book1.semao.org +boss.myfilehostings.net +botalive.com +botconnect.cn +botlife.cn +botnetdown.gicp.net +boutique-world.com +bowyt.com +boxprint.qipim.ru +boyuo.cn +boyybo.com +bp.olofyj.ru +bqtuhwhm.ce.ms +bravox002.hpg.ig.com.br +brbg.ru +brentwood28451.cx.cc +brochure.printing.usdic123.cn +broths.info +brrtydwsw.cn +brunorep.com.br +bs.hnxccz.com +bsd.ch.ma +bsea.3322.org +bsht.com +bt.1234bt.com +bt.369bb.com +bt.55isese.com +bt.aisex.in +bt.aisexbbs.com +bt.haodifang6.com +bt.laoselang.org +bt.yazhoubt.net +bt9.5qzone.net +btcgww.ttqipai.com +btyxw.cn +bu8057.91mt.com +buburuzka.com +buckhavenranch.com +budddaa234.cn +bulkbaginfo.cn +bum-biz.com +bumbiz543112.com +busan.cefkorea.org +business-networks.info +businesssecuritytool.com +buteralksaweda.com +buterbrodio.ru +bux3.3322.org +buyvideo.info +buzai.ignorelist.com +buzmsh.3322.org +bv7869.91mt.com +bvgg6.cn +bw818.com +bwla.3322.org +bxmbaqqd9.cn +bybyybyb.com +byebye2_88l.126gz.com +byggrex.se +bynrtv.cn +bytenetcom.cn +bzefowum.cn +bzsiyu.3322.org +c-0p.cn +c-bp.cn +c.33gan.com +c.40sese.com +c.5qqbb.com +c.67sese.com +c.7toot.cn +c.8883.ss.la +c.aa1b2.com +c.adminbbs.info +c.bbslc.com +c.count.xj.cn +c.dew7f.cn +c.hifou.net +c.link88.be +c.mimi100.info +c.nec8.cn +c.oye333.com +c.sfilm.com +c.tds52.cn +c.tdw63.cn +c.tes85.cn +c.veryxx.com +c.wauee.com +c.xin7778.com +c0812.2288.org +c0DSm.com +c0decub.com +c0jm.com +c0py.6600.org +c1.09466.net +c1.ko115.com +c1.link88.be +c11.31113.cn +c11.7d2b.com +c1212c.cn +c14.xorg.pl +c1518.drleeuk.com +c1519.drleeuk.com +c1520.noipx.com +c2.cr173.com +c26.31113.cn +c270377132.v2.0515114.com +c31.31113.cn +c5p.at +c5rvegg.8866.org +c7h.ru +ca424.91mt.com +caaf.ru +cachedownload.casniobellini.com +cacrazy.com +cadadad.cn +cai08.cn +cai113.cn +cai158.com +cai315.com +cai388.cn +cai800.com +cai99.net +caipiao12315.com +caipiao128.com +caipiao3456.cn +caipiao568.com +caipiao777.cn +caipiao899.com +caipiaoguanli.cn +caipiaoguanlizongju.cn +caipiaoyucewang.com +camposceola.com +cansini2.3322.org +cao360.vu.cx +cao88.com +caob521.3322.org +caomeihong.cn +caomeihongwer.cn +caomeihongyu.cn +caomeihongzx.cn +caperiod.com +carball.in +card-taobao.com +carsmodele.kit.net +carvalho0622.hpg.com.br +cashtor.net +casino.688365.com +casualhopperois.com +cauib.cn +cav.be.ma +cav.qc.cx +cav.xl.cx +cazkafuq.cn +cb.worldnewseye.com +cbc.tgdue.net +cbchance.com +cbcpw.cn +cbg163yw.com +cbngrupo.net +cbphase.com +cc.0776sw.cn +cc.188bt.com +cc.mmso11.com +cc.qqhsda.cn +cc1.9966.org +cc1.gogototos.info +cc1100.2288.org +cc250.517800.cn +cc45gr4g.8866.org +cc55f.8866.org +cc77vv.8866.org +cc88x.2288.org +ccav.sarl.tk +ccc.360yyy.8800.org +ccc.770304123.cn +ccc.aiseba.net +ccc.billlez.cn +ccc.dasege.net +ccc.mm83.info +ccc0529.3322.org +ccc213.517800.cn +ccc454g5.8866.org +cccbbbb.cn +ccccasx.9966.org +cccoo7.com +cccssdv3.3322.org +ccctvv.com +cch1.cn +cch2.cn +cciv.3322.org +cciv584.com +ccj1.cn +ccj3.cn +ccj5.cn +ccj7.cn +ccjjvvdd.7766.org +cck1.cn +cck3.cn +ccm.99oi.com +ccnbtv03.com +ccndk822.cn +ccrr518.com +ccsskkk.cn +cct327.com +ccttvv7.info +cctv-3658.com +cctv-c3.cn +cctv-com.cn +cctv-feixin.cn +cctv-t3.cn +cctv-u886.cn +cctv-viplx.cn +cctv.58cq.com +cctv0061.com +cctv01.usaweb3.1-host.com.cn +cctv1563.cn +cctv1691.com +cctv177.cn +cctv2-lyong.cn +cctv2008.bibil0.cn +cctv268.cn +cctv2ly09.cn +cctv3-0.cn +cctv3-05.cn +cctv3-09.cn +cctv33s5.com +cctv347.cn +cctv381.com +cctv383.com +cctv3dv.com +cctv3e.com +cctv3e324.com +cctv3fei61.com +cctv3fqq.com +cctv3jh.com +cctv3kb3.com +cctv3r.com +cctv3tao.com +cctv3vip.com +cctv3vs.cn +cctv3w61.cn +cctv3wcq.com +cctv3wxz.com +cctv601.com +cctv6029.com +cctv603.cn +cctv615.cn +cctv6608.com +cctv6ic.cn +cctv982.cn +cctv9933.tk +cctvaar.cn +cctvb8.3322.org +cctvddx.com +cctvddy.com +cctvdt.cn +cctveg.cn +cctvko3.com +cctvn2.cn +cctvq10.com +cctvv.xl.cx +cctvx.cc +cctvy2.cn +ccu.118bbs.com +ccutv61.com +ccv004.com +ccv1201.com +ccw12.com +ccxx.killhhh.cn +ccytv3.com +cddzfx.com +cde.2020wyt.com +cde.ss.la +cdew32dsw.cn +cdf.odwould.cn +cdfgge.net +cdn.download.sweetim.com +cdn.dsultra.com +cebbgnk.com +cebbxnk.com +cebistro.com +ceewe3w2.cn +celine.9966.org +ceqdfg.3322.org +ces-hunter.com +ceshikl.7766.org +cevalterng.com +cfile202.uf.daum.net +cfkvqhaxhvfp.com +cfq58.cn +cfqq1.com +cfqqd.com +cfqqm.com +cfqqo.com +cfqqqc.com +cfqqr.com +cfqqy.com +cfrsc.com +cfx8.cn +cfy.2288.org +cg77.fileave.com +cgi.ebay.com.jghtyu.com +cgi35.plala.or.jp +cgx0577.3322.org +cha.91mt.com +chaber.9966.org +chaik.110mb.com +chamboy.com +champtube2009.com +changhuatrame.com +chani990.cn +channellili3.com +chao56yang.xxnz315.com +charles726.hongyun99.com +chat.baidu.com.youku.com.qq.com.grtjgjdgjjg.kansepian.info +checkrapport.com +chengang.www65.cnidc.cn +chengrenys.com +chengyijy.cn +chesterhousedomain.cn +chhuslfffu.com +chigmail.com +chikilav.co.cc +china2003.cn +china60.wauee.com +chinadowns.wdxiazai.com.cn +chinafucaiwang.com +chinamobilet.cn +chinaseohome.com +chinchoi.cn +chinese-8.cn +chinesedoublec.com +chirnsideandren.cx.cc +chnrun.com +chomai.in +chomikuj.pl +chongyang15.3322.org +chrissale.co.uk +christmasornies.com +christybonham118.com +chrr2.6600.org +chuguanghui.3322.org +chugui.info +chulaiba.net +chunan.9966.org +ciline.cn +ciro062.hpg.com.br +citistep.info +city-movie.com +city.2019wyt.net +ciygqn.gicp.net +cj.8le8le.com +cj.mychina1.cn +cj11.5qs.info +cj3.isee5.com +cj9.4w9.info +cjdmekwa.com +ckc01.hdhdv.cn +ckdkj.cn +cks01.3322.org +ckt0.cn +ckt1.cn +ckt3.cn +ckt4.cn +ckt5.cn +ckt6.cn +ckt9.cn +ckw.114org.com +cl77.9966.org +classmates.profile.management.user-qvrh4skwm.controlupdatedpanel.com +classmates.profile.process.user-9quqg56is.installationsupdates.com +classmates.profile.secureconnection.user-bxkm1kc6n.resetyourvideoplayer.com +clc2007.nenu.edu.cn +clearclips.com +click-my-download.info +click.hopeun.com +client.trackups.org +client.upsclients.net +clipan.net +clocks.net.au +cltsi.info +club.2222xb.com +club.9istyle.com +cm.21cnhr.com +cm2.kmip.net +cmscenter.xywy.com +cn.31bb.info +cn.34bb.info +cn.71bb.info +cn.adultpark.org +cn.daxia123.cn +cn.golcyl.info +cn.yahoo.com.22885.info +cn49228.chinaw3.com +cnabc.info +cncp8.com +cncsyahoo.in +cnj.25u.com +cnksp.cn +cnlpaltogo.tg +cnn.get-download.info +cnn.vn.cx +cnn.vu.cx +cnnic.ch.ma +cnnic.ht.cx +cnnic.xl.cx +cnnmp.net +cnnncccn.cn +cntv3.com3.tw +cnwww.av190.com +cnzz0.kmip.net +cnzz1.kmip.net +cnzz4.9966.org +cobami.org +cobband.com +cock.8866.org +coco5.9966.org +cocoexe.8gcc.com +cod7-blackops.info +code.979797.com +code.aiqianming.cn +code.feichang71.com +code.ikaokaoni.cn +code.keyrunn.co.cc +code.woainame.cn +code01.qvodplus04.cn +code02.qvodplus04.cn +code12.onetad.com +code13.yicpc.com +codecxpvista.com +codyreseller.com +cofqc.cn +cokux.com +cold-track.net +coloer.biz +colopin.cn +com12l.3322.org +combicorm.com +come068.3322.org +comeandgivethat.net +comfortplusmaroc.blog4ever.com +coming-to2.cx.cc +commada.cn +comment.131xxoo.com +comment.147xxoo.com +comment.789xxoo.com +community.xxx.com +computername.51mudi.com +computeronlinescan.com +condoms-shop.com +config.iwillhavesexygirls.com +config.koreamessenger.com +config.perfectexe.com +config.qyule.com +conn.lachezvos.com +consolewaspogad.com +conusil.cn +cool.perfectexe.com +coower.com +core2980.mylivejournalchanel.com +coss.fileave.com +counnter.cn +count.ce32s.com +count.jk136.com +count.key5188.com +count.koreaeat.com +count.qqkuyou.cn +count.wemv.net +count.xj.cn +cp00001.cn +cp0005.com +cp007008.cn +cp01.com +cp02.net +cp0968.com +cp1128.cn +cp1155.cn +cp1181.cn +cp1238.com +cp1358.com +cp137.com +cp16666.cn +cp1718.com +cp1838.com +cp2003.cn +cp20110705.vicp.net +cp222.com +cp23456.com +cp2626.cn +cp285.com +cp28668.cn +cp287.com +cp2878.cn +cp3112.com +cp3118.com +cp328.cn +cp3377.com +cp34568.cn +cp3500.cn +cp3578.cn +cp3777.com +cp38388.cn +cp386.com +cp3885.cn +cp4858.com +cp49.net +cp52.net +cp5275.com +cp55125.com +cp555.net +cp5559.com +cp565.com +cp5666.com +cp5668.cn +cp5700.cn +cp5858.com +cp61.com +cp6222.com +cp6288.cn +cp658658.com +cp6595.cn +cp66668.cn +cp67666.com +cp6785.com +cp6k.cn +cp7333.com +cp75998.cn +cp780.com +cp7870.cn +cp790.cn +cp80998.cn +cp8258.cn +cp8595.cn +cp88.cc +cp88128.com +cp8838.com +cp884.com +cp8855.cn +cp8868.com +cp8877.com +cp928.com +cp93.cn +cp965.com +cp9898.cn +cp9955.com +cp9968.com +cp99785.cn +cpa.crdy.org +cpanel7.amhosting.com +cpc.retege.cn +cpc.xuebi2000.cn +cpfc8.com +cpm.234y.com +cpm.uoyoo.cn +cpm2.dn888.com +cpmusicpub.com +cpqwyczx.com +cpteam.podzone.net +cpw008.com +cpw010.com +cpw0688.cn +cpw133.com +cpw1828.com +cpw285.cn +cpw6658.cn +cpw6677.cn +cpw7777.cn +cpw888.com +cpw90.cn +cpw9460.com +cpw9928.cn +cpw999.com +cpwcn.com +cpwoeo.com +cpycwz.com +cpyzw.com +cpz99.cn +cpzggfw.com +cpzlw.cn +cpzxyc.com +cq5566.com +cqfywg.cn +cqgj1573.8866.org +cqodezuz.cn +cr.wyt2022.net +crabindusty.ru +cracker-g0g0li.a.gp +crash-cxim.cn +crediar.no-ip.com +criminal-vb6ers.one-crew.net +crm.9966dh.com +crmd.2288.org +cros.0134.cn +crowledblade.com +crqbz.cn +crr.dfs2.cn +crsa1.cn +crton.cr.funpic.org +crzjcn.cn +crzy.mv59.com +cs-download-16.info +cs.nsdy.com +csa22eeq.cn +csol.2009.com +csol.2009n.org +csol.xxkk.net +csol2032.com +csol3036.com +csolai.com +csolao.com +csolen.com +csolre.com +csolrv.com +csolss.com +csoltiancity.105.80000web.com.cn +csolx.cn +css.be.ma +css.sarl.tk +css.xpdowns.com +css2.viens.la +css3.viens.la +csson.qc.cx +csteenhoff.com +ctrip.2288.org +ctv3rt.com +cuimage.cn +cuixiao.w2.dh52.com +cukerbuker.com +cumhisite.com +cumtubeforyou.com +currencyis.com +custom4all.info +cutaiamortgagegroup.cn +cutalot.cn +cutheatergroup.cn +cuu812.8866.org +cuu815.8866.org +cv1z.3322.org +cvbkjh.in +cvmjk.com +cvxcbc2345.3322.org +cw389.com +cwa7214.org +cxhk.net +cxim-way.cn +cximnik.cn +cxpr.net +cxxxmz.ttqipai.com +cyberorchid.net +cykjwhfangao.w65.idccenter.net +cyswlj.b121.53dns.com +czxcz.cn +czxczq.cn +d.0143.cn +d.15587.com +d.364736.com +d.5ding.com +d.aa1b2.com +d.aidws.com +d.aloxx.com +d.azzwg.cn +d.bgsew.com +d.bnksw.com +d.brsqb.cn +d.caxiao77.com +d.cdwsx.com +d.cndydy.com +d.cxdde.com +d.dingxiang.biz +d.dnf01.com +d.doinw.com +d.dstsett.cn +d.eddxx.com +d.fgddx.com +d.game163.in +d.gddxw.com +d.hhdwx.com +d.iamcome.in +d.img001.com +d.iopqw.com +d.kele55.com +d.khtgf.cn +d.kkkmfdy.com +d.koreaeat.com +d.ksxwa.com +d.kv5h.cn +d.lnxwy.com +d.mxxio.com +d.myhhg.com +d.ndxwq.com +d.nkwxs.com +d.oixka.com +d.opqxn.com +d.oye333.com +d.perfectexe.com +d.ppgghh1.com +d.se94se.com +d.shasanguo.com +d.uds4.com +d.weixk.com +d.wixww.com +d.wuc8.com +d.xiaoshuojingling.com +d.xin7778.com +d.xwsfx.com +d.ydopx.com +d1.456363.com +d1.456783.com +d1.456783.comr +d1.741239.com +d1.7dwz.com +d1.ad58.info +d1.csygg.com +d1.downxia.net +d1.fsfe9.com +d1.gov9988.com +d1.hf3y5.com +d1.it3s5.com +d1.tianxiaba.net +d1.vv04.info +d1.xiazhai8.net +d10gc.cn +d1229.4s.citymotors.com.cn +d147.8866.org +d1f2.3322.org +d1gix.net +d2.364736.com +d2.csygg.com +d2.downxia.net +d2.fsfe9.com +d2.gov9988.com +d212dddw.cn +d3.456363.com +d3.456783.com +d3.ayxz.com +d3.downxia.net +d3.kkkmfdy.com +d3.pstang.net +d4.downxia.net +d45parog.net +d4ee004.cn +d5.456363.com +d5.it3s5.com +d5g5l.cn +d5hsr.cn +d7kj7.cn +d9.456363.com +d9.hf3y5.com +d9.it3s5.com +d9mmmm.7766.org +daclaudio.altervista.org +dada.qqqg.us +dadaing.97ganxxoo.cn +dadxx.info +dahkbb.3322.org +daidai22.3322.org +daikao88.com +daimtraders.com +daledalebien.net +dalu.biz.tm +daluf.web.fc2.com +damdang.vn +dan098.sv5.swe23.cn +danni.maya777.com +dao.newfc.us +daoijd.8800.org +daotaopiao.bet66.cn +daoye.he.cn +daoye.nm.cn +daoye.sh.cn +dap.qc.cx +darkslim.cn +darthvader777.com +dasasugus.com +dasd22e.cn +dasd322111.cn +dasda11d.cn +dasdww2.cn +dasemei.cn +dashao18.2288.org +data-fix.net +data.66660.com +data.zongbing.com +data1.yoou8.com +data2.92taojin.com +database.wolf-lander.info +davtraff.com +db.ms.kr +db5bj.tk +db9qq.cn +dbckbkscw.cn +dbs-softportal.com +dbsjxuvijx.net +dbtte.com +dcc.rqq888.cn +dcctvee.com +dce6728f.7d5592b7.gswz877.cn +dchinao.cn +dd.pingak.com +dd.qzgsl.com +dd.zxcvbnmzxcvbnm.com +dd1100.2288.org +dd1xx.com +dd22gg.2288.org +dd2xx.3322.org +dd2xx.com +dd3xx.com +dd3xx.net +dd444.ycff.com +dd5xx.com +dd6s.zhuhc.cn +dd88x.2288.org +dda530e7c3716983.net +ddbbddbbdbbbdbdd.cn +ddd.37kuku.com +ddd.66qsw.com +ddd.dasege.net +ddd.ds22aa.cn +dddd2.com +dddddsaa.cn +ddddsss12.cn +ddddsss123.cn +dddl.754245.com +dddsewqq.cn +ddhh-sdh001.cn +ddi.xorg.pl +ddjjswqq.info +ddk1.cn +ddk2200.com +ddk3.cn +ddl.974671.com +ddl.ur36d.com +ddll.in +ddos.9cdn.com +ddos.llooiijj.cn +ddos.tyd8.com +ddos365.3322.org +ddoszdani.cn +ddqqbo.dll-down.cn +ddsccweww.2288.org +ddsshjhaiiwiieieie2222.cn +ddtfff.ru +ddtl.me +ddv.sarl.tk +ddv.xorg.pl +ddvvbb.cn +ddxx.llooiijj.cn +ddxx123.com +deabak.com +dealsforfun.com +debbank.com +decreasein.net +deeexf2.3322.org +deewoo.net +defaf663.110mb.com +deihc88.h12.idcyh.com +delaizoloto.cn +denegbolshe.net +denirulz.org +denz.fileave.com +deping.3322.org +detcentral.cn +detguide.cn +detypyr.co.cc +devi56.co.cc +devilsoul.cn +df0x.54.pl +df4g5ew4wt.3322.org +df54yhd.3322.org +dfdfg443.cn +dfdsaf.dnf-1100.com +dfetb.cn +dffzfcv.cn +dfgdtyret.8866.org +dfghs.cn +dfgkkl.cn +dfgxhjodncz.com +dfhg.info +dfhjfd731.cn +dfjgh.cn +dfjhgasdf.cz.cc +dfsa3dd.8800.org +dfsaddfdcc.6600.org +dfsafdsa32.cn +dfsafdsafd.2288.org +dfsefyt23.open2009.net +dfvbww.cn +dfzqgf.com +dg.jwl.woniu.com +dgv9b.cn +dh.41119.cn +dh.97meitu.info +dh.cn3.cn +dh.dh818.info +dh.dsege.com +dh.fi5.us +dh1.765321.info +dh2011yahoo-com.top.to +dhgfnj221.3322.org +dhl.ezxjy.com +dhvbznxdex.net +di2059.91mt.com +dia1.cn +dianping.timedg.com +dibgibxg.com +dick.perfectexe.com +digimoduleded.com +dildi.net +diqu.3322.org +diretoria1.net +discount4biz.info +disk.e165.com +diuaw1.7766.org +divinemeb.com +dj.520mmxx.com +dj.crxx.org +djieplsk.ru +djly88.com +djmy123.cx.cc +dklife001.freehostia.com +dknrv.cn +dkny.9966.org +dkud2.3322.org +dl.51mmm.info +dl.9sv.cn +dl.ad58.info +dl.caimaobuy.com +dl.cjr001.com +dl.down-china.cn +dl.down-sogou.cn +dl.down-taobao.cn +dl.down-tudou.cn +dl.guarddog2009.com +dl.kaka1l.com +dl.kanlink.cn +dl.qvodaac.com +dl.qvodax.cn +dl.qvoden.cn +dl.qvodiiu.com +dl.qvodir.cn +dl.sanhaostreet.com +dl.shuangfei.info +dl.vv01.info +dl.vv03.info +dl.youbak.com +dl02.softdown-load.com.cn +dl3.kanlela.com +dl4.kanlela.com +dl6.kanlela.com +dl8899.3322.org +dlhost1.new-hua.com.cn +dll.perfectoptimizer.com +dlplayer.aiavba.com +dlq.zljtl8.com +dlqlb.3322.org +dls.donglink.cn +dlsg09.com +dlsmg.cn +dmj.2288.org +dmy.2288.org +dn-down.3322.org +dn.imsetup.cn +dn9726.91mt.com +dnd.zhuangyang.cc +dnf-pp.com +dnf.17xj.cn +dnf.71bao.net +dnf111.dnfcom.com +dnf2020.com +dnf27.com +dnf3pk.com +dnf820.com +dnfa-qq.com +dnfcf.com +dnfcx.com +dnfda.cn +dnfdnf.com.cn +dnfgqq.com +dnfkobe.cn +dnflipin.cn +dnfmori.com +dnfmx.com +dnfqq.net +dnfqq2009.host166.ftp18.cn +dnfqq66.cn +dnftj.cn +dnfuv.cn +dnfweb.008.net +dnfxi.com +dnfzc.com +dns.8f8q.cn +dns.dmy2.com +dns.htmlvista.com +dns.o0oq.cn +dns5.8866.org +dnsfailurecheck.com +dnsresl-105-18.com +dnsresl-125-18.cc +dnuos.ru +dnusax.com +dnxingcheng.com +do.cvpoo.com +do.eDNS.biz +doceesalgados.net.br +docmer.net +documento.zapto.org +doeik.fuyss.com +doflolab.cn +dog.93bb.info +dogvod.6600.org +dollstories.com +dom.xz22.com +dom11z.cn +domain191.org +domainameat.cc +domainperline.com +domenzmonz.cn +don.b1du.net +donrodriguez.cz.cc +dop.rta.mi.th +dorops.golf-au-maroc.com +dosame.com +doshoping.cn +doublcclick.3322.org +doubletest4411.com +doudou.diyad.cn +down.114anhui.com +down.114graph.com +down.199h.com +down.20730.com +down.24.cnnicidc.com +down.27-net.com +down.3333dh.cn +down.49558.cn +down.5201819.info +down.520lmm.com +down.92rmm.com +down.97199.com +down.97sp.info +down.98qvod.com +down.9978.net +down.9flasher.com +down.9iwawa.com +down.ba-lal-aba.info +down.baisou123.com +down.darkshellnew.com +down.dby2.cn +down.ddos163.cn +down.ddosor.cn +down.dllqvod.cn +down.dmy2.com +down.duomi.com +down.emoney.cn +down.emstock.com.cn +down.eurccc.cn +down.feel2day.com +down.fengfan666.com +down.games520.cn +down.haodown123.com +down.huhawang.com +down.ipk.cn +down.jk155.com +down.kkjie.com +down.kxso.com +down.langlangdoor.com +down.lm555.cn +down.my227.com +down.ongameworld.com +down.online25.info +down.p2pplay.com +down.playboyshop.info +down.privacyboan.com +down.ptlang.cn +down.pudown.com +down.q7sp.com +down.qq1ive.cn +down.qvod.cby6.cn +down.qvod.gdy8.cn +down.qvod.gny6.cn +down.qvod.ww7z.cn +down.qvod2.net +down.qvodlink.com +down.ring3.info +down.rtba.info +down.safedown.info +down.sexymn.info +down.shineyu.net +down.soft999.info +down.softnews.cn +down.ttqipai.com +down.vbuv.cn +down.vippin.cn +down.vrbrothers.com +down.wan555.com +down.wo001.com +down.zhao123.info +down.zxqczx.com +down013611.cdn.5cnd.com +down1.57px.com +down1.jdyou.com +down1.jpdesk.com +down1.mgxf.net +down140818.cdn.5cnd.com +down153958.cdn.5cnd.com +down160724.cdn.5cnd.com +down202540.cdn.5cnd.com +down215953.cdn.5cnd.com +down234548.cdn.5cnd.com +down3.alibaba99.com +down3.emstock.com.cn +down414.zqoner.com +down8.catmaomao.com +downc.clud33.com +downes.xixihache.info +download.antispywarebot.com +download.av-best.info +download.cleaner2009solution.com +download.favorit-network.com +download.juvepoland.com +download.kuniun.com +download.live-player.com +download.qvod-setup.com +download.qvodown.com +download.seemao.com.cn +download.setup.xinruicn.com +download.tkgame.com +download.wagabb.com +download.youbak.com +download11.subo.me +download13.subo.me +download21.subo.me +download4.aaa234.com +downloadavr14.com +downloadavr3.com +downloadpoint.cn +dowqvod.3322.org +dpamv.asian-eve.com +dq2345.91mt.com +dqdq2.com +dqgh.hljgh.org +drag0nx.com +dramaserials.com +drb33en334a.com +drghwaweg45j4i6u3q32fg2h.com +drstore1.com +drugstoreclimb.com +drugsugandazs.com +ds.84ny.com +ds3gj.cn +dsa2e.3322.org +dsa33dcdc.2288.org +dsa3edccsdsd.6600.org +dsa4l.cn +dsadas12332132.cn +dsade332.cn +dsadfcc.8866.org +dsadsccc44.9966.org +dsadshadhsa11220.cn +dsaeww2.cn +dsaeww4.cn +dsafdsa3232.8800.org +dsafsa.daslxzcewralrocjn.cn +dsee4322.cn +dsews.com +dsfdfe44.8866.org +dsfrtr5465.3322.org +dsg3aeg.cn +dsh.yxdlq.com +dskf.3322.org +dstsettx.cn +dsz123.cn +duklin.againstfear.com +dunhill.9966.org +duoteba.com +duowan-wowbox.com +dushiqingyuan.3322.org +dvd.av-39.com +dw.mtsou.com +dw2.azm8.com +dweer.klkl111.8866.org +dwnsft027.co.cc +dx.1155k.cn +dx.1234ye.com +dx.1ggmm.com +dx.2012avi.com +dx.8es.cn +dx.97tu.info +dx.jqqdx.cn +dx5.97sky.cn +dxnight.com +dxxq.uqc.cn +dxyxl.3322.org +dxz.974671.com +dy.1234bt.com +dy.339.la +dy.51qs.info +dy.93iii.com +dy.theokj.info +dy3839.cn +dy61.com +dynamic-load-zone.com +dz.haodifang5.com +dzenhottoo.cc +dzu.2288.org +dzupdates.com +dzw.2288.org +e-exchanger.ir +e-mail-google.co.cc +e.1.20532858.com +e.fissare.net +e.kx747.com +e.luo68.com +e.oye333.com +e.playuu.com +e.wuc8.com +e.xin7778.com +e05.njkfq.com +e11.88mw.com +e11.9966.org +e11.cxe95.com +e14.newux.com +e192.51vip.biz +e192.dns0755.net +e1ag1j.cn +e246e.7ab93.haojob0714.cn +e3.96pk.com +e37z.cn +e58z.cn +e5ea77f.7b1d9e3.mydoudizhu.cn +e5t.7777tt.com +e5t.wo123.info +e6t.3322.org +e6tt4.114anhui.com +e8.96pk.com +e82037107274c108affec9e25f65d6c4.info +eacips.fuyis.com +ealo.net +eapusher.dice.se +earlyship.ru +easystarwars.cz.cc +eat.c029.com +eazydn.com +ebebguere.com +eco-multimedia.com +ecomint.com +ecpss.banzhu.net +ecpss.sh.cn +ecpsschina.com +edajuu.blogginhell.com +edanez.110mb.com +edit1china.cn +ee.bww5.cn +ee00oo.cn +ee00r.2288.org +ee1100.2288.org +ee2233.2288.org +ee345.7766.org +ee44ee.com +ee4hgrg.8866.org +eee.202online.inf +eee.ww22ddd.cn +eee.wyt94.com +eeee345s.3322.org +eelcd5.info +eewqere.3322.org +eey88.cn +efdgy.in +eftpsid0387333.ru +eg2thg.cn +eger4.cn +egwtq.91mt.com +ei8i.cn +eimhuwyt.com +einoyy.net +ej2470.91mt.com +ejiwu9987.cn +ekabu.ipq.co +ekite.korqukuw.cn +ekopu.yonluzog.cn +ekosto1091.co.za +electrovichada.com +elfah.net +elitemovie.cn +elleamoda.it +elods.cn +elsanto-disco.com.ar +emailsupports.com +emozzio.emozzio.com +en.bjork2.com +en.demisetoken.com +enerclima.pt +english.uctube.cn +enjnzdfmts.cn +ep2011.91mt.com +epeiy.com +epvp.net +eqrocksthemall.com +er.dgr35.cn +er.dhe45.cn +er.dhw45.cn +er.gdr43.cn +er.kye57.cn +er.kye68.cn +er.lye68.cn +er.shr34.cn +ercedesmox.com +erdda.3322.org +erdfy.cn +erfu23.cn +erichware.com +ero.absms.ru +erqrer322.cn +errekhxzerr.co.cc +errors.9966.org.wwvv.us +errors.9966.org +errorsweeper.com +erstesdes.org +ert5321.cn +ertubredxcong.com +ertws.cn +erutiye.cn +escarlletjonson.web.br.com +esdd.3322.org +eseort-5173.com.cn +esli.tw +esnacker.com +essentialgeneva.com +est8991.3322.org +eteweb.gg.p.355656.com.cn +etyet.com +eurogeotour.ru +eurolink.3322.org +eurotds.biz +euy.loo168.net.cn +evelica.com +ever6scan.com +evildeadbrazil.t5.com.br +ewqdqwd32.cn +ewrfdgy.cn +ex.jpdesk.com +ex0.in +exampro.cz.cc +exe-center.com +exe-file-boom.com +exe-soft-portal.com +exe.146843.com +exe.amg777.com +exe3.perfectexe.com +exe316.com +exe4.perfectexe.com +exemagonline.com +exepub3.com +exes.fileave.com +exesuperload.com +exhibition.maya777.com +exp0se.us +explab.cn +extra-turbo.com +extralargevideos.com +extratopupgrade.ru +exzo.info +f.8f4efd.cn +f.8tf44.cn +f.98tdw.cn +f.9de4t.cn +f.9u5trf.cn +f.9ung5.cn +f.9yc8.co.cc +f.baiyici.cn +f.frew2.cn +f.rrtg43.cn +f.wuc8.com +f1.ad58.info +f1.hf3y5.com +f1uq1dfi3qkcm.cn +f1y.in +f3jiy.cn +f3tyu.2288.org +f5nn.com +f6m.7777tt.com +f7.30.5546.static.theplanet.com +f8a.ru +f98.xorg.pl +f9a.at +fa0010.com +fa4l.3322.org +fabycac.co.cc +facai88.x169.zgsj.net +facebook-surprise-cvsa.tk +facebook-surprise-mkwr.tk +facebook-surprise4mf.tk +facebook-surprise4mg.tk +fafa8caca.3322.org +fajin.v21.19821122.com +fajujohiv.cn +fak888.cn +fangspde.cn +fantastictools.com +fanyusheng.3322.org +faq.ht.cx +faretransy.com +fartunaall.ru +fast-antimalware-scanner.com +fastantivirus09.com +fastgoal.ru +faszcx.cn +favoclick.com +fawewe8f.cn +fb-imgs.com +fbcfqtufgdw.com +fc03.com +fc151.cn +fc178.com +fc3d558.com +fc56588.cn +fc5688.com +fc5688.net +fc5868.cn +fc5898.cn +fc6188.cn +fc661.net +fc6666.com +fc689.cn +fc8089.cn +fc8788.cn +fc98.net +fc998.com +fcai128.cn +fcd.t3.to +fceaw.cn +fcp56.cn +fcp88.cn +fcuked.me.uk +fcw688.com +fdaty.cn +fdccdf333.7766.org +fdg5.cn +fdgf22dg.6600.org +fdgggg.cn +fdr.mikece.cn +fdsa3324324.8866.org +fdsa332dd.3322.org +fdsaf34543sdfds.cn +fdsafdsa3322.9966.org +fdsf2fneg.3322.org +fdsfdscvdfde4.6600.org +fdsfse.7766.org +fdsgdfgh.2288.org +fdvdv.cn +fechiizonshiteita-taihendayo.net +feelingabc.3322.org +feelingchoin.cn +fefewcdz32.3322.org +fei2009xin.cn +feichangyemen.cn +feifan1.8866.org +feilia.3322.org +feiting.to.7766.org +feixin.979797.net +feixin.to.8800.org +feixin23.cn +feixin333.uqc.cn +feixin5.uqc.cn +feixin566.cn +feixin57.cn +feixin591.cn +feixin60.cn +feixin688.cn +feixingcctv3.com +feixini2009.cn +feixink09.cn +feixinky.cn +feixinte.com +feixintt.cn +feixiy.cn +feixn2009g.cn +feixxwinhuposheqingyilongbo.xmntu.com +feiyu0002.3322.org +feiyuhen.it.idccname.info +fenda20.com +fengying.52qqbicom.cn +ferrari03.8866.org +ferrari03.9966.org +ferrari07.2288.org +ferrari10.6600.org +fest-movie-tube.info +fetion-cctv.cn +fetion.to.7766.org +fetion006.com.cn +fetion2009a.cn +fetion5.com.cn +fetionc.com +fetiond.com +fetionh.com.cn +fetionm.com +fetionu.com.cn +fetionxi.cn +fetioy.com.cn +fewd.com5.tw +fewf.qa444.8866.org +fewfwee.cn +fewwe322.cn +ff.c5c3.com +ff02.nstest.co.cc +ff1112.2288.org +ff1jil1.net +ff33fer.8866.org +ff3d.cn +ff88.dyndns.info +ff99zz.9966.org +ffajxqq.info +ffda444.3322.org +fff.dasege.com +fff0530.3322.org +fffddd11.cn +ffohs.com +fg4yjv.cn +fgbnhj.myokj.info +fghhff.cn +fghjk1.9966.org +fgsdg.3322.org +fguiop.cn +fhod.3322.org +fhportal.com +fieso.cn +fifa-09.cn +fifthz.info +fighterarcade.com +figureframeez.com +fiio.8800.org +file.28bxg.com +file.plusbag.net +fileden.com +filefixpro.com +files.drbobah.com +filesareaonline.in +filescentrals-2010.net +filoups.info +findbigwords.cn +findfriendmail7.com +firefoxantiscam.com +firstwork.info +fj.btplay.net +fjlys520.3322.org +fk360.2016wyt.net +fkmm.3322.org +fkqdmy4sfyraa.3322.org +fl0809.cn +fl567.com +flash-03.co.tv +flashspan.net +flashzoo.net +flc258.cn +flcp12.com +flcp1588.com +flcp315.com +flcp413.com +flcp5088.com +flcp56.com +flcp6688.com +flcp678.cn +flcp688.com +flcp8848.com +flcpglzx.com +flczlw.cn +flog.bestvirusremover2008.com +flowersagents.com +flxh.2288.org +fm881.cqwin.com +fo-qq.cn +followme.name +foqffo.cn +foqij.cn +for11.3322.org +fordana.cz.cc +formauxilium.it +formoff.ru +forum.5721.net +forum.d99q.cn +forum.zsnews.cn +forxxxvideos.com +fotos134.fileave.com +fotoshare-2dknc.com +fotosimagenes.fileave.com +foxxpriv.ru +fqq1.cn +fqzs.thevalentineparty.com +frantsuzik.com +frasertooper.com +free-crack-4you.com +free-full.com +free-games-rapidshare.com +free-ipodtouch.com +free-pornvideo.cz.cc +free.7host06.com +free1122.info +freecastingus.cn +freedom3.cn +freedownloadsz.weebly.com +freeep.cn +freefileshop.com +freehqhardmovies.info +freejyfc19.info +freetraxdlyatebya.ru +freett.com +freetubexxxvids.com +freezdec.ru +fregiv.ttqipai.com +frontdesk003.51mudi.com +froot.nl +fs2dfs.3322.org +fs45fd.cn +fs5k.spaces.live.com +fsd3fds.3322.org +fsdbc.cn +fsgnfjh123.3322.org +ft5yj.com +ft916.8800.org +ft917.3322.org +ftp.scarlet.be +ftp4sales.cn +fu456.com +fu678.com +fucai3dtuku.com +fucai66.cn +fuck.ss.la +fuckrav.9966.org +fucn.ch.ma +fullantispywareonlinescane.com +fullantispywareproscan.com +funky-soft.org +funloveonline.com +funnyvalentinessite.com +funso8.com +fuoqlasdx.dnsdojo.org +futjap.net +futurepay.info +fuy88.cn +fvbvbrt.2288.org +fwef222.cn +fwefr43.cn +fx.pq.to +fx2009jj.cn +fxcctv-2b.cn +fxctz.com +fxok.cn +fxtn5.com +fyg.cc +fyivbrl3b0dyf.cn +fymuqah.co.cc +fyowf.cn +fz8866.com +fzl111.at.ua +fzxhkj.3322.org +g-i-o.de +g.63577.com +g.abcd1123.info +g.ad159.com +g.chinaih.com +g.fds7.cn +g.gff87.cn +g.igf85.cn +g.iht2.cn +g.mymonk.net +g.nbr8.com +g.nvh56.cn +g.ohr9.cn +g.ojg76.cn +g.qling.com +g.qv778.com +g.semm99.com +g.topguang.com +g.uds4.com +g.uye123.com +g.vbd57.cn +g.wuc8.com +g.yfe5.cn +g1.sdw2j.com +g11.t2s8.com +g1476.cn +g1a1e.cn +g3mobi.com +g459h.8866.org +g4k4h.cn +g6tt4.114anhui.com +g9e9g.cn +gae1hasdf.cn +gaehh.info +galeon.com +game.373ka.com +game.685faiudeme.com +game.ad1111.com +game.guo360.co.cc +game.iciba.com +game.tdwan.com +game116.game456io.com +game158.info +gameboys.hpg.ig.com.br +gamedl2.2it.in +gamesky.frankwuhahawu.info +gan.132xxoo.com +gan.345xxoo.com +gan.456xxoo.com +gan.567xxoo.com +gan.678xxoo.com +gan.789xxoo.com +gan.920xxoo.com +gan.970xxoo.com +gan.wawyt.com +ganbb.tv +ganxi123.com.cn +gaoav.com +gaosiwi.cn +gaott.com +gaqwd.cn +garabeza30.ru +garant.ivano-frankivsk.ua +gate.corsgate.com +gate55.info +gayaccess.com +gaywang1069.com +gbgbkkk.3322.org +gbv.nna.cc +gd1di.cn +gd8bb.cn +gda.nna.cc +gday.3322.org +gdb.cztv.tv +gdfgdfgdgdfgdfg.in.ua +gdny168.com +gdqtq.com +ge3uy.cn +geerrge.com +geh-ins.kz +generalantivirus.com +gesbank.iasoft.es +get-money-now.net +get.111kuht.cn +get.faces-profile.com +get.flashactivex.com +get.my12.info +get.setheo.com +get.tztv.info +gf2ube.com +gfdfr.cn +gfr24.com +gfrjk.cn +gg.999321.net +gg.jjmmmmm.cn +gg.kum51.cn +gg.onegreen.net +gg.pin6.biz +gg.ttttdll.cn +gg.woyinwos.cn +gg1816.91mt.com +gg1z.com +gg4.24gao.com +ggdown.8800.org +ggdown.8866.org +ggdwon.7766.org +ggg.2013wyt.com +ggg.360yyy.8800.org +ggg444.com +gghjy.3322.org +gghy7785.xw2.cdn9.info +ggjbjb.cctvmtvgtvilv.com +ggjbjb.cctvmtvgtvitv.com +ggmm123q.3322.org +ggool.org.cn +ggvod.jjmmmmm.cn +ggy.nenu.edu.cn +ggzhichen.od8.58idc.cn +gh3028.91mt.com +ghbrty.3322.org +ghost.adf3.cn +ghostusers.info +ghterwa.com +ghytujk.8866.org +giaine.com +gianttoplocate.cn +gianttopnano.cn +gidaju.netfirms.com +gidromash.cn +gift369.cn +giftsdo.com +giga-track.net +giljl.cn +giordano.9966.org +giperk.jino.ru +gir88e.net +girlfired.d821e.cn +giuetuhje.com +give.cl +giwkvn.ttqipai.com +gizliilimlerhazinesi.com +gizmatool.net +gj.13ybx.com +gjhhgjghjhkj.3322.org +gjy.nna.cc +gkiot.cn +gkl.nna.cc +gkpm.3322.org +gleette.com +globalinstrument.com.cn +globalstube2009.com +globalypages.com +globantispyware.com +gm.adsl8899.cn +gm.asdy77.cn +gmailservices.com +gmajem.x10.mx +gmakj.com +gmdzgs.cn +gnfdt.cn +gnpsg.cn +go-download.in +go-porntube.info +go.chacha01.cn +go.chacha03.cn +go.chajian01.cn +go.chajian03.cn +go.dudu05.cn +go.gongfu01.cn +go.gongfu02.cn +go.gongfu03.cn +go.iu-yt.info +go.jianjian02.cn +go.jianjian03.cn +go.keke01.cn +go.keke02.cn +go.keke03.cn +go.keke05.cn +go.moxii.cn +go.okjtoday.info +go.thesxc.info +go2000.cn +go5v.cn +go888.host2.5v55.com +goal98.netsh.com/bbs/281810 +goasi.cn +gogo2me.net +gogobuisness.ru +gohaen.info +going-wide.net +goldenoudhproperties.com +goldenstorm.net +goldlave.cn +goldmaniac.com +goloe-video.com +good-week.cn +good.gd +goodboomer.com +goodhao1.3322.org +goodtraff.ru +googl-analisys.com +googl-status.com +googl.ch.ma +google-analaba.cn +google-analabb.cn +google-analabc.cn +google-analitycs.lijg.ru +google-analystiks.com +google-analytics.pbtgr.ru +google-anlabc.cn +google-traff.cn +google.cjhd.name +google.cn.baidu.se-av.info +google.googlee10.cn +google.googlee4.cn +google.maniyakat.cn +google.nsp99.com +google2.9966.org +google7.9966.org +google8.9966.org +googlead2.3322.org +googlean.info +googleandbaidu.jefhhe.com +googlebots.cn +googlefuckbaidu.jefhhe.com +googlenum5.3322.org +gop.ccidnet.com +gopheisstoo.cc +gosalerbas.com +gospel-force.com +gotothefile.com +gougom.cn +gougouoo.3322.org +gova.eloec.com +gp1168.com +gp2121.com +gp355.com +gp4678.com +gp6066.com +gp608.com +gp6611.com +gp6700.com +gp8668.com +gpdyj.com +gpeee.com +gpm.xunleihf.cn +gps.785634.com +gpt0.ru +gpwg.ws +gq.zuobai.com +gq8g.cn +gqbzdg.reportradio.com +granata282.cn +great-film-tvs.info +greatinstant.net +greatsalesgroup.com +greatsalestax.com +greattubeamps.com +greenflor.cn +greensinkod.com +grensulle.nl +grobotron.cn +grtour.com.cn +gruzzilla.com +gs33ah5a.9966.org +gsdrkyuio.gicp.net +gt5ev.cn +gtc123.com +gtpq.info +gtrgrt4.cn +gu05.com +gu6t76f7d2.c.28ads.com +guagua.cn +guanlis.cn +gudao8888.3322.org +gugato00.110mb.com +gugeuio.3322.org +guilin.fl28.com +gulapercatovka.com +gun2u.in +guojiacaip.cn +guojiacaipiaowang.cn +guojiacaipiaowang.com +gusuoo.7766.org +gvb.nna.cc +gvod.kkjjuuii.cn +gwafknp.cn +gx.dh8866.com +gx.gx-ruanjian.com +gxxhye.com +gyahjy.cn +gyl.nna.cc +gzhuineng.com +gzlezent.3322.org +h.09466.net +h.hnr7.cn +h.kfd8.cn +h.kjl7.cn +h.lgt6.cn +h.ltf8.cn +h.luv5.cn +h.mkg7.cn +h.mm96.info +h.myhotbag.info +h.qrx0.cn +h.uyi6.cn +h.wuc8.com +h.zxr5.cn +h0tabi4.net +h1.dgfg4.com +h1.ripway.com +h65uj.8866.org +h8ae8.cn +ha.setup.xinruicn.com +ha10020.ww.stx8.com +ha7054.91mt.com +haa.ss.la +habbometox2.altervista.org +habrion.cn +hack-wolf.vicp.net +hacker110.lunqun.com +hacker999.lunqun.com +hackhound.org.uk +hackyzq.cn +haea.3322.org +haha.3ehk.cn +haha.d0uwan.cn +haha8080.3322.org +haha888l.com +haha999b.com +hahagua1.8866.org +haibo.16f.cn +haiertl.3322.org +haitunwan.txmh.net +hao.128xxoo.com +hao.132xxoo.com +hao.133xxoo.com +hao.134xxoo.com +hao.147xxoo.com +hao.20aabb.com +hao.22aabb.com +hao.230xxoo.com +hao.234xxoo.com +hao.235xxoo.com +hao.23aabb.com +hao.256xxoo.com +hao.25isese.com +hao.29smm.com +hao.320xxoo.com +hao.321cao.com +hao.321xxoo.com +hao.330xxoo.com +hao.33xxoo.com +hao.345xxoo.com +hao.365xxoo.com +hao.440xxoo.com +hao.456xxoo.com +hao.512xxoo.com +hao.523xxoo.com +hao.550xxoo.com +hao.567xxoo.com +hao.600xxoo.com +hao.64xxoo.com +hao.678xxoo.com +hao.71xxxx.com +hao.72xxxx.com +hao.74xxxx.com +hao.770xxoo.com +hao.789xxoo.com +hao.815xx.com +hao.880xxoo.com +hao.920xxoo.com +hao.92xxoo.com +hao.92xxoo.org +hao.97tu.info +hao.97wen.net +hao.aaa234.com +hao.jiuku123.com +hao.thenv.info +hao.tongletang.net +hao.wyt95.com +hao123.985465.net +hao123.lian88.com +hao123.usa.hxh8.net +hao253.com +hao3636.cn +hao413.net +hao8.idckj.com +haodasoft.cn +haohao19823.cn +haohaobo.org +haojianting.cn +haojianting88.cn +haojiemeng.com +haoma.qq.com.baidu.com.qq.qq.com.qq.q.q.qq.qqhao.qq.qqhaoma2.cn +haoma.qq.com.baidu.com.qq.qq.com.qqhaoma2.cn:81 +haoma.qq.com.vip-baidu-qq.kaokaonimen.cn +haoss123.qqwweee6666.cn +haoxia18.com +happy-fxs.com +happy.smslt.com +happyfarms.cn +happyqqfarm.cn +hasffert.com +have.dd4747.com +havha.net +havvha.com +havvvha.com +hayatimrap.com +hbbb.com.au +hbk.xorg.pl +hbnbf.3322.org +hbq.xorg.pl +hbshendan.3322.org +hby1991.3322.org +hd4ok.cn +hdfrtret.8800.org +hdjfskh.net +hdkyt.cn +hdteste.kit.net +he.agojvoxnam.net +health.maya777.com +healthbynet.net +heathen.cc +heidhakfhfa.cn +heima.com +heimaking.com +heiyewuzhe.cn +hellh.net +hello123.net.ua +help-fund.com +helpj.3322.org +helpless.tk +helpmypconline.net +hengshui01.cn +hengwei.maya777.com +henxin1.com +heqiuyan.cn +hero3.8800.org +hers.com.hk +hewj.co.cc +heyjoy.cn +hezuo818.cn +hf5d.3322.org +hfcga88.com.cn +hfs.ava364.cn +hg6888.com +hgtr3.com +hh.qvod-50.com +hh.vipjh.com +hh1396.com +hh445f.8866.org +hh8.ss.la +hhcun.com +hhggff.cn +hhhhdd123.3322.org +hhhhhhh1.klkl333.8866.org +hhhhzzzss.cn +hhhjjjj.cn +hhhwwq.cn +hhj2.cn +hhj5.cn +hhj7.cn +hhj8.cn +hhj9.cn +hhn.ss.la +hhqvod.cn +hhsssee.cn +hi.52kuaibo.info +hi098.sv9.swe23.cn +hi5-imgs.com +hiapj.cn +hideomechanic.com +hifgejig.cn +hincerpi.cc +historycontext.cn +hiveone.com +hj8ur.cn +hjkio.com +hjlzhy.3322.org +hjm7.3322.org +hjvip-wpj.cn +hjyuw2.com +hk558.com +hk626.com +hk6669.com +hksxs.net +hkzxyy.com.cn +hlong86b.517800.cn +hm.zjjt18.com +hmbcompn123.com +hmdoor.3322.org +hme.3-a.net +hmily.lljjoouu.cn +hmily.zjjt18.com +hmshop.biz +hmv-mov.com +hn.yigeyuming.com +hnbc2.cn +hnhack123.ww.ybdns.org +hoho-2.cn +hohoha.3322.org +home-china.net +home.adultpark.org +home.ttymq.com +homepage2.index.ru168.cn +hong100.cn +hongheng.66yj.com +hongse88.com +hongzhuang.maya777.com +hookbaes.cn +hopely.com.cn +hopetrade.info +horrys.in +host.u2m.ru +hot-plays.com +hot44.kmip.net +hotel818.com +hotgras.in +hotlean.com +hotmail3.com +hotpic.7poo.com +hotsummerstaff.ru +hotxxxtubevideo.com +hou2.6600.org +hougong520.com +houlai.ignorelist.com +houtai.185555.com +houtai.60o.org +houyuhuzhouyuhu.com.cn +howard19820909.com.cn +hp.xiazhai8.net +hp2-qq.cn +hp3qvb.in +hp540.weedns.com +hqcenter.cabmrec.com +hqviewworldmy2.com +hr2p1y.cx.cc +hsdfhh32131231.3322.org +hsdgrt.3322.org +hsey.info +hsjs.qqww.us +hslm.stvpn.com +hsw123.cn +hsxw.net +htest1.3322.org +htiwg.cn +html.cicitv.in +htsrh.info +http://www.game163.in +htxz.wdjpq.net +hu280.3322.org +hua23.com +huadan311.3322.org +huafeichzh1002.com +huaiyi023.8866.org +huang.huanghuang.info +huanghuangs.8866.org +huangpian.biz +huangsewangzhan1.net +huangsidianying.cn +hub.colo.owned.hu +hudieer.com +hueiwu.cn +hugebestbuys.cn +hulala1.vicp.net +humirajustice.com +hunymepi.hotbox.ru +huo119.com +huodong28.cn +huodong58.cn +huodong69.cn +huojianghj.cn +hupugivuz.com +huwysur.co.cc +huxiang11.3322.org +huxiaocw.com +hwomiale.ru +hx22mmo.2tianya.com +hxc7jitg7k57e.cn +hxcx.org +hxx7.cn +hypertds.com +hyu7fd.com +hzhan.com +i.egooad.cn +i.listage.info +i.wuc8.com +i18o.cn +i31.net.ru +i3219.cn +i4q4i.cn +iamchinese.info +ibank.cahoot.com.servlet-session-9476.mdot.be +ibewareofdanger.com +ibmwyt7.imbbs.in +ican.count.xj.cn +id-yahoo.com.cn +idast9ri.notlong.com +idc.ce.net.cn +idc.gzce.cn +idc.zhuyy.com +ideo-pomp.com +idunef.cn +ie.findsiteonline.info +ie1.bv123.com +ieopen.yhgames.com +iexx.com +iggoole.cn +igooddeal.com +igorhhasy.ru +igoudix.cn +ihateyouroma.com +ihogedi.cn +ihon.vagtafak.cn +ihoo.fireworkspoint.com +ihuqoyr.cn +ii.derquda.com +ii.ebatmoyhuy.com +ii.kakzhe.com +iio00.3322.org +iioossddxx.3322.org +iis.dengyan520.com +iis.mo.cn +iitem-taobao.com.cn +ij1452.91mt.com +ij544j.3322.org +ij55ar.cn +ijaheuw.cn +ijakony.cn +ijesiam.cn +ijn22.rfvv0080.cn +ijuebka.cn +ijuoxe.cn +ilovefzl.ilovefzl.com.cn +image.perfectexe.com +image20.dyndns.info +imagecake.cn +imagehut3.cn +imagehut4.cn +imagenes.fileave.com +images.fotos033.pochta.ru +images.xunzhifu.com +imagescolor.com +imagesi.jstv.com +imagesvista.com +imb.usai.info +img.bniss.com +img.downbt.com +img.doyo.cn +img.egoooad.com +img001.com +img003.com +img006.com +img1.5tu8.com +img1.sfilm.com +img2.51wan.com +imgbaidu.pp-tv.com +imqq.com +imso3rry.count.xj.cn +in6cs.com +ina4id.com +inb4it.com +inc1.ht.cx +incas.co.kr +incon.ch.ma +incon.hobby-site.org +indah1.webs.com +index.5944.net +index333.com +indiborge.com +infi.8800.org +infinitilancer.cn +info.pc2.cc +info.tb82.com +info.update.klzhe.com +ingclip.com +inkel-xmastrees.com +inld.adsoft.name +inline477.info +innermelodie.net +inrwycgkg.cn +install.5cnd.com +install.8800.org +installz.cn +intes.3322.org +intsteds2.cn +inztion.com +iooup.com +iowhi.cn +ip.yihaha.org +ip213.com +ipdown.poloi999.cn +iphone4.17pfa.com +iphoneate.in +iphonetw.com.cn +ipkipk.3322.org +iq-qq.com +iq-tech.biz +irisjard.o2switch.net +ironpunch.com +isof.susubbs.com +ispscenter.com +ispspartners.com +issdy.com +item.taobao.com-eu.us +item.taobao.com-hhm.mu.la +item.taobao.com-hosting.co.cc +item.taobao.com.oowiieoir.com +item.taobao.com.qrenjk.tk +item.taobao.com.weiioiu.com +item.taobao.coml.feikch.cn +item.taobao.mecao-s.tk +item.taobao.seiaero.co.cc +itevm-taobao.com +itgm-taobao.com +itme.taobao.com-iiy.info +itme.taobao.free.web.minhaoweb.cn +itorkadflione.com +itromet.com +itsyouronline.cn +iu7se.cn +iuhu.8866.org +iuuym.breakingnewsltd.com +iw.asr8.com +iwtube.freewebhostx.com +ixpqq70.s888.aabbk8.cn +iytgfvcxs.com +izonetxt.webng.com +j0hnx3r.org +j1s2.cn +j3e3o.cn +j50lo.cn +j6j65.cn +j6k6k.33rff.cn +j7723.cn +j8j88j.3322.org +jabber-vk.ru +jabber911.com +jaded-brutality.com +jamesfans.cn +japanesegirl8.com +jatrja.com +jav-mov.com +javaigjo.com +javaupdateserv.com +jaybta.9966.org +jbillu.net +jbl.trcwoman.info +jck.9981ly.com +jd.jobvudix.cn +jdblade.cn +jdccn.com +jdem.cz +jeepvihecle.shop.co +jeiuei82872.cn +jf.xxyudi.cn +jfg1.3322.org +jgh-mail163.co.cc +jgh5d.3322.org +jgy79j.3322.org +jh3v3.cn +jhgyuty.cn +jiafang8.com +jiahe8888.3322.org +jiangxing.3322.org +jianzhulaw.gotoip4.com +jiayifan.cn +jiba360.3322.org +jibamao221.3322.org +jidoe.cn +jiekefa8d.info +jievj.cn +jifen-taobao.com +jiieiu.cn +jiji.cd +jili.t35.com +jimkey.in +jin.2020wyt.net +jindome.cn +jingdianys.cn +jingliu.3322.org +jinke668.com +jinniou6.vicp.net +jinniou9.vicp.net +jinshanduba.org +jinzhuangzhuang.cn +jiqingdianying.info +jiqingliaotianshi.com +jiqingmm.com.cn +jiqingpianseqingpian.dingxiang.dailiba.net +jiqingroom.cn +jis2.3322.org +jiudian.568.com +jiuqugan.byethost5.com +jiuqusee.8866.org +jiuquwen.net +jj.pin6.biz +jjckr.com +jjio.8866.org +jjj.2012wyt.com +jjjaaa1.cn +jjjjyayayaya.3322.org +jjjt3t4.8866.org +jjqi88x1.8866.org +jjxp1.cn +jjxp22.cn +jjyy.jjyy.hi.cn +jk.258wyt.com +jk0.info +jkasd.8800.org +jkjjkk.cn +jkk.tw +jkrr.3322.org +jksdwil.cn +jkuis.cn +jl.chura.pl +jmbioanalises.com.br +jmghys.cn +jmp1.5166.info +jmp8.5166.info +jmp9.5166.info +jnby.9966.org +jnjhjyy.cn +jnnzitang.3322.org +jnyfjju.3322.org +job.cust.edu.cn +job.icxo.com +jobstopfil.biz +jockeybbs.cn +join.celebritymixup.com +join.disgraced18.com +join.gagthatgranny.com +join.pornprosnetwork.com +jornalglobo.tempsite.ws +josecure.com +joyshion.170.cnnicidc.com +jp.93bb.info +jp1334.91mt.com +jpg.cv1l.com +jptj.pc2.cc +jq.25gao.com +jqdy.6600.org +jqqj.cn +jqspz.cn +jrx88.9966.org +js-wr28.com +js.23xxoo.com +js.bestlovelong.com +js.mumayi.net +js.union001.com +js.zcool.cc +jsani.cn +jt8700.cn +jtjdi.cn +jtse.info +judoinfo.com +jujll.3322.org +juk7ik.3322.org +julionejurmon.com +julybbs.com +jun.wuming100.com +jun88.9966.org +jupitermotors.com.au +justimportant.com +justnewleft.ru +juuz.org +juyg.8800.org +jw961.cn +jwieiuu.cn +jx3.bigfoot-l78.com.cn +jx5178.3322.org +jxox.8800.org +jytip.cn +jytok.tk +jz2009jx.com +jz926.3322.org +jzxm1.3322.org +k.5x7x.com +k.6xx8.com +k.77xx77.cn +k.99xx99.cn +k.9ss8.com +k.kekese.com +k.kghh2.cn +k.perfectexe.com +k.qq16800.com +k.yidianse.com +k001.2288.org +k17mm.3322.org +k2uy.cn +k767.com +k927.9559cck.cn +kaba.979797.net +kaba.duozz.com +kai.ppvsrs.com +kaixin-200.com +kaixin8080.com +kaj11mv122i.com +kak2.u2m.ru +kakgezaebalsha.com +kaksosatblog.info +kakzhe.com +kamz.net +kan.sewytwang.info +kan03.9966.org +kan05.9966.org +kan06.9966.org +kan08.9966.org +kan31ni.cn +kansez.cn +kanshou1.3322.org +kaokaoni-iq.110860.cn +kaokaoni.sh.cn +kaoshi.qingchun001.cn +kaosini123.3322.org +kapa8080.com +karioni.net +kasperskiy-huesos.com +kaspersky.ccfish.cn +kat15.com +kav.9iwawa.com +kav6.9966.org +kazirnayatema.cn +kcot.3322.org +kcs.cn +kdddaber.com +kdf21.2288.org +kdx.gvc86.cn +kdx.kds85.cn +kdx.kfg86.cn +kdx.khf84.cn +kdx.ldc86.cn +kdx.sxd65.cn +keailou.adwa23.com +kede.hpg.ig.com.br +kef-yahoo.com +kekese.com +kel.2012avi.com +kendall-web-lab.com +keowo.cn +kepko.net +kertenkelereklam.com +kestiny.com +kewyr82.cn +key.91mt.com +keybizz.org +keyru.01lm.com +kf-yahoo.com +kghytghu.cn +kghytgv.cn +kghytgvbn.cn +kh76t.3322.org +khoi3n.3322.org +kied.9966.org +kievsk.com +kikimm.com +kill52000.com +killavp.9966.org +kindbaby.ru +kingdol.com +kingkinglove.tk +kingstar.3322.org +kiopldid.net +kioytrfd.com +kiskecaq.cn +kisos.cn +kissfromde.cn +kissnimadehaoma.2288.org +kiwiwi.me +kj33ijfek.cn +kj88hg.3322.org +kj8l.kmip.net +kjasoi.cn +kjbdr.in +kjhur.cn +kjkkkk.cn +kjy6fj.3322.org +kk.8x8s.com +kk.a.5d6d.net +kk.henhao321.cn +kk.hh51888.cn +kk.lelewyt.cn +kk48.com +kka.qingchun-meinv.cn +kkaa.dns0755.net +kkaabb.w19.dvbbs.net +kkac.dns0755.net +kkaf.dns0755.net +kkaj.dns0755.net +kkak.dns0755.net +kkan.dns0755.net +kkbobo.net +kkbyl.com +kkdft.cn +kkk1.co.cc +kkk3452.3322.org +kkkipmm.3322.org +kkkk789.8866.org +kkkppptt.cn +kkloirr.3322.org +kkxv.in +kkxx.wowdnfs.com +kl1314.91mt.com +klawesd.cn +klikvp.cn +klingerlawcenter.com +kliuresd.7766.org +kllm04.cn +kloyndvrot.info +kmcc.send4u.co.kr +kmdl101.com +kmm.ss.la +kmm58.com +kmwo.3322.org +knownsec.8800.org +ko.807090.cn +ko.abcdnf.com +kobra5.net +kojd.9966.org +kokkosik.com +kol-development.com +koliartoge.com +kolinhopewaqs.com +koliopewaqs.com +komojoke.cn +kor-programms.com +kotycnt.info +kout.tbag.info +koxx.2288.org +kpaxikey.cn +kpizuyuw.cn +kruisverheffingbrugge.be +ksn.a1974.wrs.mcboo.com +ksss.us +kt4lwumfhjb7a.cn +ktlzkz.bofisifax.cn +ku.perfectexe.com +ku1.installstorm.com +ku4000.cn +kuaiboba.com +kuaile358.3322.org +kuaileshanyang.cn +kuaim009.cn +kugoux032.hs3mmt.com +kukerq.com +kumogroup.cn +kunzhasheng.com.cn +kurtz-media.com +kusika.ru +kusika911.ru +kuwaityah.100free.com +kvf.dns0755.net +kwaada.info +kx111.cn +kxkx.thesswws.com +kybbt.cn +kyhug1.cn +kytickabila.com +kzvi4iiutr11e.cn +l-ai.cn +l.2010wyt.com +l.94saomm.com +l.bugxue.com +l.sog369.com +l.uye123.com +l11l10oo0.qaqa126.8866.org +l2-life.ru +l3ie445b.cn +l9l9i.cn +l9sk.com +la113.cn +la2slash.ru +la5252.2288.org +ladh.cz.cc +lafastfind.com +lagunabich.cn +laibuji.w528e.cn +laikaha.cn +lailai11.3322.org +lalafafa123369.midea.gx.cn +lalocationmanager.com +langke.bad.mn +langke.fw.nu +langke.shit.la +langma.w110.badudns.cc +langmm.us.to +langqun1.com +langye.vicp.net +lanuevaeradeldesarrollo.com +laoding.net +laogong.info +last-videos-online.com +lastcountb.com +lastcountc.com +laverdad.0fees.net +lawd.poloi999.cn +lazzarimages.com +lb.mainpage.cc +lb.perfectexe.com +lciejqe.cn +le_1.520xz.com +leakstar.com +leawo.cn +leoe.3322.org +leonardandself.com +lesso.ppeb.tk +leus.akpe.name +lf9886.91mt.com +lgbincolar.com +lhhhh112.3322.org +li.5lsf.com.cn +li1l.3322.org +li28.vicp.net +li3bn.3322.org +lian.10000ip.cn +liao.577renti.cn +liao.w4.8868.in +lieshazhe.com +likesondemand.com +lilj.us +linbiao.9966.org +linda.lucas232.pochta.ru +linezing.8800.org +lingluanqi.cn +lingqi-taobao.com +link.veexx.com +link2.topwyt.com +link666.info +linkmater.com +linofoster.com +linshi1.8888168.cn +linuxcostablanca.com +lir.nna.cc +lishi.maya777.com +list.9bic.net +list.htmi3.com +litedownloadseek.cn +liteonlineantivirusscan.com +litetoplocatesite.cn +liteurl.com +litianyi.down.lv-n.cn +liudidi.9966.org +liugirl.cn +liuhecai.cc +liushizhounian.qqxuexiao.com +liuyang.h19.y733.cn +liuyang03.l123.e80888.com +liveantimalwarequickscnan.com +liveantivirusscanner.com +livenv.co.cc +livestar.info +liy.nna.cc +liyongcctv.com +liz.8866.org +lizhao5.cn +lj.mir2180.com +lj3q.biz +lj8jl.3322.org +lkbbs.mba.org.cn +lkji9.cn +lky.nna.cc +ll.2015wyt.com +ll.9981ly.com +ll.pin6.biz +ll.wwooaini88.com +llest.taoibaa.cn +lllfff.com +llst.taoibcc.cn +llst.taoibes.cn +llu76hg.9966.org +llwa.3322.org +lly9.com +lm.registear.info +lmok1234xing.w239.dns911.cn +lndns1.cncmax.cn +lndns10.cncmax.cn +lndns2.cncmax.cn +lndns3.cncmax.cn +lndns4.cncmax.cn +lndns5.cncmax.cn +lndns6.cncmax.cn +lndns7.cncmax.cn +lndns8.cncmax.cn +lndns9.cncmax.cn +lnfcjcy.gov.cn +lnt888.3322.org +lo1j.8800.org +lo9988.cn +load.ddos.loadcode.meibu.com +loaddasig.com +loading.own.cz +lock8.vicp.net +lodfewpleaser.com +log.adsence.co.kr +log.y5z.info +login.ageofrappelz.com +logixoft.com +lonelywifehookup.com +longyitiaov7.cn +look.ikik.cn +look1314.cn +lookjh.com +lopaman.com +lorentil.cn +los.nna.cc +loskut.cn +lousecn.cn +love-yes.wyt91.com +love.cankj.cn +loveh.sv2.sgedns.cn +loveing.count.xj.cn +loveuu.org.cn +lovexe04.9966.org +loveyou.wwooaini88 +lowprice-meds.net +loyal-porno.com +loyaltube10.com +lp36.net +lpifip.ttqipai.com +lscode.3322.org +lsn.qc.cx +lso022.cn +lso02aq.cn +lsowje12.cn +lswjs.com +ltnc.info +ltterd0x.cn +luceng.com +lucheng.us +luck1144.cn +luckweb.8866.org +lucyy.8800.org +lujiji.com +luoliao999.cn +luoliaomeinv.cn +luoliaow.com +luort.com +lvjht.eu +lwawa.cn +ly.40sese.com +lyboidomen.cn +lydfyy.pway.cn +lzey.3322.org +lzwd.3322.org +m-qq.com +m.3992929.com +m.99081.com +m.daodan8.com +m.ebankpay.info +m.ef44ee.cn +m.efessd.cn +m.fesfwe.cn +m.few32.cn +m.gegea4e.cn +m.gegeree.cn +m.kekese.com +m.sfs3wws.cn +m.wuc8.com +m.yidianse.com +m1.bzbattery.cn +m1300.co.cc +m1n2.cn +m2121.cn +m3.mesuo.net +m4.servik.com +m468.3322.org +m6mm.info +ma.dy6655.cn +ma118.com +maaroto.com +mac.ak737.cn +mac.rompoliy.cn +madaboutvisuals.com +magzepterl.com +mai2828.3322.org +mail.com.sina-va.cn +mail.ntplastics.com +mail.qq.com.wwvv.us +mail.you8x.com +mail13years.co.cc +mail2011ghjuyfbnghrtdcbhxcv.tk +mailobaolavajato.gratix.com.br +mailssrvs.com +mailvip1-6-3.cn +mailwbg4.com +main15052009.com +makotoro.com +malware-live-pro-scanv1.com +malwox.biz +mama.jijiyy4444.cn +man4polis.com +manawork.83.dnscnc.com +maopian.cc +maopian.in +maosixin.3322.org +marcopolo.uk.net +marhe.org +mariwield.cz.cc +martuz.cn +mashrooms.cn +masterip.vicp.net +masterjue.5166.info +masterwanker.com +masturbation.sexpornok.com +maxho.ru +maximmusprobivus.com +maxiu.vicp.cc +maya777.com +mb17173.9966.org +mbd2.org +mbmbmb.9966.org +mbr0.cn +mbr1.cn +mbr2.cn +mbr3.cn +mbr5.cn +mbr7.cn +mbr8.cn +mbr9.cn +mck36.3322.org +mcxb.34689.tk +mdown.12222.f.yygczx.com +mdown.13710.f.yygczx.com +mdown.28655.f.yygczx.com +mdown.35586.f.yygczx.com +mdown.59905.f.yygczx.com +mdown.61233.f.yygczx.com +mdown.76216.f.yygczx.com +mdown.78554.f.yygczx.com +mdown.88098.f.yygczx.com +mdown.98884.f.yygczx.com +me.mapbar.com +me.mike-about.com +mebel.by.ru.fqwerz.cn +media4me.9f.com +mediashares.in +medplaceok.com +meelith.com +mefa.ws +megamindonline.com +megavipsite.cn +meimei.9966.org +meinv.bbgg.hb.cn +meinv.qqwweee777.cn +meinv11.kmip.net +meinv8.web.fc2.com +meinvfans.com +meinvluoliao.cn +meirr20.com +meixing.web.fc2.com +mejac.com +members.lycos.co.uk +members.multimania.co.uk +mercadoabc.com.br +metago.cn +meter.6600.org +metinbl.youdns2.com +meur.com.cn +mev.qqbmfe.cn +mewgost.com +mexab.com +mf6gy4lj79ny5.cn +mfc45.cn +mggg07.cn +mggyu.info +mh-2.gnet.ba +mh.3gali.com +mhg65.3322.org +mhzxz.com +microsoft-2010mail.com +microsoft08.9966.org +microsoft11.8800.org +microsoft17.7766.org +microsoft23.9966.org +microsoft28.6600.org +microsoftinc.fileave.com +microsoftmediaplayer.net +microsupdates.com +midbomb.ru +mildtune.ru +miliardov.com +milla6814.wol.bz +milllk.com +milneqexgu.cn +miltonmoon.com +mimaer.3322.org +mimi.15kav.info +mimi.semei7.cn +mimi1818.cn +mimibn.cn +mimicom.web.fc2.com +mimisese.com +mingyunhujiaozhuanyi.net.cn +minisearch.co.kr +mir.sdomi.cn +mir2.sdo.mx +mir2.sdoma.cn +mir2.sdorm.cn +mir2.snd0.com +mirh2.com +mirs.sh.cn +mirxc.com +missing-codecs.net +mister-f.com +miumiu.9966.org +mjh8.cn +mjisuvrmthr.com +mjjia.cn +mk.cxaaaa.cn +mkchess.com +mlkiu78.cn +mm.20tu.com +mm.24gao.com +mm.280wyt.com +mm.3992929.com +mm.40sese.com +mm.6x3x.com +mm.700wyt.com +mm.8x2x.com +mm.97gan2.info +mm.aa88567.cn +mm.kuaibo.name +mm.meng3130.com +mm.niuniujidid.com +mm.qeshow.com +mm.sqwyl.com +mm.tt88567.cn +mm.uu88567.cn +mm.www.11wyg.com +mm16.net +mm214.com +mm22.kmip.net +mm520mm.com +mmbase.bbgg88pp.cn +mmc.ss.la +mmdeai.3322.org +mmgongyu.info +mmhouse.me +mml1.com +mmm.40sese.com +mmmbsbt.co.cc +mmmmkkkss.cn +mmpp123.com +mmpp147.com +mmpp258.com +mmpp321.com +mmpp456.com +mmpp654.com +mmshipin.web.fc2.com +mmsifu.cn +mmv88.info +mmwwrrqq.3322.org +mmwyt.qqwweee1155.cn +mmxxmmm.cn +mmxxqq.3322.org +mn.clsdwn.biz +mnxi2.3322.org +mo-s.cn +mo.997wyt.com +mo171.cn +moban2.8866.org +mobileauto1.com +modirdred.cx.cc +modularpoint.com +mohotwrxst.info +momowo123.3322.org +mon.qc.cx +moneymoney888.com +monkey-squad.net +montlimal.co.cc +moonnight.3322.org +more-info-here.net +morph1um.mo.funpic.de +mostpopularscan.com +motodicas.co.cc +moumom.cn +movenestecobra.ru +movie-rapidshare.com +movie.boy007.com +movie.joy.cn +movie2new.in +moviesgolden.com +mp3.iciba.com +mp3musicsool.ru +mp6dj.9966.org +mrp4xspei.cmtwo.cn +msg.tmhacker.com +mshadow.cc +msiensa.cn +msms5200.com +msn.youbak.com +msnpicspace.com +mstoolonline.com +mstrh4.cn +mstsc2005.com +msvbvm50.com +mswconsultingllc.net +mt3pvkfmpi7de.cn +mtv2.9966.org +mtv4.9966.org +mu2010.com +mufrr5432.cn +multiplexphone.com +mumalian.50webs.com +muralzinho.com.br +music.163wgw.com +music.168987.com +music.dailiba.net +music.pankti.info +musicmobi.com.cn +mutant-star.net +muttergh.com +mv.2009ai.com +mv.77abo.com +mvpq1.6600.org +mvpqq.6600.org +mvt.1s.fr +mvt.c0m.at +mvt.c4.fr +mvt.ch.ma +mvt.vu.cx +mvt.ze.tc +mx3920.91mt.com +mxdlj.com +mxhe.vb3e.cn +my-correios.com +my-exe-profile.com +my-socks.info +my.me-1.info +my.qqhe.com +my111.info +myaa.kmip.net +myac.dns0755.net +myac.kmip.net +myae.kmip.net +myaj.kmip.net +myak.dns0755.net +myal.dns0755.net +myan.dns0755.net +myantivirusplus.com +myaq.dns0755.net +myar.dns0755.net +myart-gallery.com +myat.dns0755.net +mybesttube.cn +mybig-xxx.com +mybox-xxx.narod2.ru +mychina1.cn +mycnav.info +mydocs.3322.org +myfile.100free.com +myhaf.xijrikit.cn +myhealtharea.cn +myhealtharea.net +myico3.3322.org +mymathtutor.com +mymir.sdo.evils.in +mymir.sdo1.cn +mymir.sdq.name +myndomain.info +myoneads.info +mypage12.com +mypics.fileave.com +mypoints.kr +myringtonemaker.net +mys88.cn +mysamsungapps.net +mysangu.cn +myselfhere.com +myskynet.info +mysurprise2011.com +mytoolls.3322.org +mytop-xxx.com +mytotalscanner17.com +myud.jiakao.net.cn +mzm139ss888.com +n.4000se.com +n.breaknews.com +n0m0n4.3322.org +n0m0n5.3322.org +n0m0n7.3322.org +n6th7.cn +n97.6600.org +n97.7766.org +nahyu.org +name.lm555.cn +nanomx.net +naranjasdor.com +nawpaz8svzxaa.3322.org +nb.09202.com +nb2sw.cn +nbadata.9966.org +nbbfrdfsfe.8800.org +nbdmm.3322.org +nbnb1111.com +nbtj.114anhui.com +ndt.110mb.com +neenos.cn +nenastiya.cn +nengcaoni.bet66.cn +nenoos.com +neon2011d.cx.cc +nepaxek-domain.cn +netspond.com +neverttols.com +new.2019wyt.com +new.91mt.com +new.gdvd.cn +new.glksw1099.net +new.kkbm99ghfi.com.cn +new.kkbm99ghfp.com.cn +new.new-hua.com.cn +newcode1.shendu.cc +newflashmedia.net +newhtm.com +newpluginsflash.ne +news.21npc.com +news.2duche.com +news.3gmobile.hk +news.85580000.com +news.mbqb.org +news.zhike.com +newss.gr +newxxxvideos.in +nexuw.com +nfdns1.cncmax.cn +nfdns10.cncmax.cn +nfdns2.cncmax.cn +nfdns3.cncmax.cn +nfdns4.cncmax.cn +nfdns5.cncmax.cn +nfdns6.cncmax.cn +nfdns7.cncmax.cn +nfdns8.cncmax.cn +nfdns9.cncmax.cn +ngfres.com +ngjk34.net +ngy56hgjf.3322.org +ngytrd.com +nhjuy1.com +nhy655.3322.org +nhy7d.3322.org +nhy7ubgv.114anhui.com +nhyy888.3322.org +ni0.ss.la +nia.xnum.cn +niaiwo234.3322.org +nib.xnum.cn +nickiminajbuttexsposed.com +nicozion001.net +nidhsaiodhswiwi11222.cn +nifeng03.3322.org +niggals.com +nihao.soke123.com. +nihaoma2.Cn +niouniou.qqwweee555.cn +nisferylos.com +nisim-tw.com +nitrotros.com +niudoudou.com +niuniu.38xjw.com +niuniu3.cn +niuniujidi-wang.cn +nizhuya.3322.org +nje0.cn +nje1.cn +nje2.cn +nje3.cn +nje4.cn +nje5.cn +nje6.cn +nje7.cn +nje8.cn +njfr.klkl111.8866.org +nju7yd.3322.org +njyw.njenet.net.cn +nlkjxy.hebeinu.edu.cn +nm11df.cn +nmgzlt.cn +nmll.3322.org +nn.22niu.com +nn.44didi.com +nn.7000se.com +nn.hh88567.cn +nn.nf +nnd323.cn +nnjd.net +nnjidi.com +nnn.2013wyt.net +nnndcmy.3322.org +nnnndddaa.cn +nnnono.cn +nnw169.info +nnyp.net.cn +no1.vv01.info +no135.3322.org +nochedebuenosaires.com +nonamedomain.in +nonoes.cn +nonoss.cn +noordnabliocul.hopto.org +north9.info +northcoastweb.com +nosatorabumb.com +noski5.com +note4scan.info +notepad2.info +noticias.rangdhanubuilders.com +noticias.terra.microfin360.net +notstopavplis.ru +novaestruturaescoladedanca.com +novasourefest.com.br +novatoriz.cn +now.gnmbc.co.kr +noyes.9966.org +nqrl.in +nr54eg.8866.org +ns.ipp.com.ru +ns1.vv05.info +ns123.com.cn +nsp.fr.ht +ntrjj.cn +nu2bd.3322.org +nujaneznal.cn +nusatorkaleprovis.com +nuuo21.cn +nv3587.91mt.com +nvidiaupdate.net +nw323.91mt.com +nyelec.tcl.com +nyny1010.com +nyyjpf.bestusablog.com +o-ap.cn +o-bp.cn +o.9cdn.com +o.CAIPIAOYUCE.INFO +o.hope2012.info +o.registear.info +o00oo00oo.qvod659.cn +o0o0il1i0o.9bic.net +o0o0il1i0o.htmi3.com +o2le.cn +o4a0o0.3322.org +o753159.fileave.com +oa.dfac.com +obama2welcome.ru +obcrwtkoyus.com +oc00co.cn +occg.com.cn +od32qjx6meqos.cn +odn45qa555l.com +oemsoftdownloads.com +office-download.org +office.podzone.org +office3.ze.tc +office4.ze.tc +officea.flnet.org +officeon.ch.ma +officeon.venez.fr +officeon.viens.la +officeupdates0.com +ofuxicotv.com +ogli.org +ogzhnsltk.com +ohjsi.cibjumip.cn +ohyes88.com +oiasd.cn +oitqq.17nu.net +oiuhfww.cn +ojajo.3322.org +ok-j.info +ok-taobao.com +ok.abcdnf.com +ok.paofangwuyuetian.info +ok.qvodiii.com +ok.ruanle88.cn +ok1.dy7t.com +ok131.com +ok881210.8866.org +okgogogo.net.ru +okiloi123.3322.org +okm4.org +okokkk.cn +ol.132639.com +ol7617.91mt.com +old.suburbs510.com +olwcqw.3322.org +om163mo.c.la +omega.86biao.com +omg-funny-i-gotcha.com +omidan.net +ona.hco.cc +oneant.ru +oneboy.ru +onelun.cn +oneplace-all-exe.com +onestar5.com +onewedhost.com +oni.hco.cc +oninc.ze.tc +online-media-archive.net +online-xp-antivir.com +online.guo360.co.cc +online.trktvs.ru +onlineadvert.net.in +onlineanalytics.cn +onlinecheckping.com +onlinescanweb.com +onlinescanxppro.com +onlinesexy.ru +onpress.com.sg +onsese.com +oo2200.com +oo993op.cn +ookx.3322.org +ooo7.3322.org +opexti.cn +opiqwd98.cn +opiumaslt.com +opopop14.cx.cc +oppe.6600.org +oqq1.cn +orbabuleska.com +orerss.3322.org +org-edu.ru +orgololorialni.cn +osdxx66.7788j.info +ou.sdo.com +oungholman.com +ourfaceb00k.com +ourrgame.com +ourtulip.ru +ovkanubergan.com +owen376376.9.400dns.info +oxmu.7766.org +oy4b-oykb.ru +oymomahon.com +ozoneiphone.ru +oztime.asia +p.94saomm.com +p.99081.com +p.cpm9v.cn +p.yocc.net +p0umob9k2g7mp.cn +p1.dy37.com +p1.images22.51img1.com +p1.ksharuan.cn +p1.ujde90s.info +p1.ywe0080.cn +p2.images22.51img1.com +p2p456.cn +p3.images22.51img1.com +p5.highsms.com +p7keflvui9fkl.cn +p7ld.cn +p8.9iwawa.com +p8p8p8.com +paganinihttpdown.go.3322.org +pagead3.googlesyndications.co.cc +pagead4.googlesyndications.co.cc +pagesuploader.net +pak.qq6893.cn +palacemoon.com +panjian982.86data.cn +pao44.com +paobar.com +paokars.cn +paokw.cn +paolouzi.kmip.net +paonk.cn +papampam.net +para-maranhao.com.br +pardokkate.com +parishiltonporno1z.com +parkelec.co.kr +parking.139app.3322.org +parlor.maya777.com +pazpirvabm.cn +pc-antispypro.com +pc.yyq111.com +pcantivirusscanner.com +pcb.uub.cc +pcikpt.vicp.net +pconguard.com +pcsecuslnk.com +pctv3.com +pda.buo.cc +pdl.lcn.cc +pdl.stream.aol.com +pds.adncommerce.com +pearlpearl.com.br +pefpuklkoyl.com +peke18.laweb.es +peke18.notengodominio.com +perejopa.com +perfectteam.org +perlamutratoro.com +pes.mv121.cn +phaizeipeu.ru +phaypal.com +philippinegovernment.info.tm +phonezero.com.br +photics.cn +photobucket.gcfmv.org +photos-google.com +pic-facebook.com +pic.2bj.cn +pic.360gan.com +pic.iwillhavesexygirls.com +pic.nnsese.com +pic.qvod.com +pic1.images-yite.cn +pic1.picav.net +picomarkets.ru +piensaingles.com +pillowcasetze.com +ping600.info +pingan3.3322.org +pink-alubum.com +pj1188.com +pjkb.info +pk235.us +pkpk.net.cn +placepillshunt.com +planet55x.com +play.ikpass.com +play.letian160.com +play.mezoka.com +play.qvod882.cn +play.rn35.com +play.unionsky.cn +playgay.cn +playx.ch.ma +please-click.cn +plimd.net +plmmtp.com +plskababaverygood.com +plum-6vbev2.com +pmtracking01.com +pn-cctv.cn +podaritemne.spb.ru +poemail-xx.com +poiujhnbg.com +pokemon.monkeyserve.com +poker500.ro +pokov.com +polecreekmeadows.com +pon00dslll.com +pop.vcx6.cn +pop3.123fga.cn +popej.cn +popingred.com +popkarrt.cn +popkartianc1ty.8m8m.info +popopo2.com +poppka.net +popu.16768.com +popupserf.cn +porgacig.cn +porno-tube-x.com +pornoguzeli.net +pornostrana.com +posadaladesmera.es +posmi.net +postcards.org.oeqweah.cn +postmaster.fileave.com +postmaster.web31.f3.k8.com.br +povg.info +powerup-host.com +poxz.net +pozeml.com +pozemle.cn +pp.aloneong.info +pp10.info +pp4aq.2288.org +pp5888.cn +pp6789.com +pp6aq.8800.org +pp8dd.3322.org +pp99bb.cn +ppa.hco.cc +ppa77.cn +ppcc.mz008.cn +ppcmbo.com +ppd.hco.cc +ppd8tt.3322.org +ppe.hco.cc +ppe.uub.cc +ppf.uub.cc +ppg.uub.cc +ppi.uz4.net +ppp.asaicache.com +ppp.qa111.8866.org +ppp456.com +pppphhhss.cn +pps.bestuusee.info +ppt.th.gs +ppvod2010.cn +ppyk8.com +pqrservrflmosqr.biz +premiumnonfat.cn +presentes.com.cn +prinfolgs.com +priorityzero.us +private.awardspace.us +priztersmon.com +procto.cn +product4.cn +progene.info +programstoremovespyware.com +promed-net.com +promixgroup.cn +promo-park.ru +promo.dollarrevenue.com +promotetruth.org +pronettools.com +proobizz.cc +prorom.cn +prororo7.net +protectedsky.info +protecton-antivirus-scan.com +protectyourpc.cn +proventrack.com +providensdue.com +provis.es +proxyrent.net +ps.kaixinfou1.com +ps08.info +pt930.9966.org +pubruluk.co.cc +pulaseskanovios.com +punaduce.com +pure-download-new.net +pureask.com +put.ghura.pl +pvden.com +pvden.net +pw.88mw.com +pxjsxx.com +pzyou.us +q.4bh.info +q.94saomm.com +q.cptiandi.net +q.fgjg1.cn +q.fgjg4.cn +q.nje1.cn +q.nje2.cn +q.ssoo.us +q.sssae.us +q10000q.s69.zgsj.net +q132.cn +q1dfg.cn +q1wqwq22.cn +q1x.ru +q2009q.com +q2010-vipa.com +q2bf0fzvjb5ca.cn +q3b.ru +q5688.cn +q5wq.cn +q766.com +q9sx.cn +qazwsx1618.w189.dvbbs.net +qb.vip.com.go.qq-net-com.cn +qccggz.com +qcd127.com +qd.netkill.com.cn +qdcchg.com +qdffg.cn +qdledo.8866.org +qdvod.dcv2.cn +qefmlpdqncz.com +qer67.com +qergyhuk.co.cc +qert.coconia.net +qew16.us +qgnghx2qa.cmtwo.cn +qhf9.cn +qhjcwfbqthr.com +qhuc1.51vip.biz +qhuc5.51vip.biz +qhuc7.51vip.biz +qiaiuja.com +qilongji-vip1.cn +qing.qsnook.com +qingse99.3322.org +qingsewuyuetian.97bobo.biz +qingss.3322.org +qiqijis.com +qiryom.xefpudel.cn +qiselink.cn +qisex.info +qiu1984.2288.org +qizi123.ww.ybdns.org +qizin.net +qjdiejs.cn +qjvod.3322.org +qk102.com +qkankan.6gg.cn +qkyygo.com +qm.freevnbc.info +qnk.smartsalesgroup.com +qnq61.cn +qo4.net +qozkcab.t3.to +qq-09vip.com +qq-1.info +qq-2009-vip.cn +qq-2009tx.com +qq-2009vp.cn +qq-2009vv.cn +qq-216.cn +qq-a2009.cn +qq-anquan.com +qq-fgj.cn +qq-ksa.cn +qq-qq10n.cn +qq-tt09.cn +qq-vip55.cn +qq-vj6.cn +qq-x666.cn +qq.10zn.cn +qq.18i16.net +qq.265lian.com +qq.344aa.com +qq.388huh.in +qq.61-3.com +qq.7622.cn +qq.94makelove.cn +qq.94makelove.com.cn +qq.9800qq.in +qq.com.aaadmin5.com +qq.com.gfdgg.in +qq.com.liiw.info +qq.com.lioh.info +qq.com.oiue.info +qq.com.qqck.net.cn +qq.com.qqlsf.cn +qq.com.uiol.info +qq.g0olle.net +qq.geams.tk +qq.hlsli.info +qq.hriakcypavo.com +qq.ok673.cn +qq.pp216.cn +qq.qbqb.us +qq.qczc521.cn +qq.qqkk.us +qq.qqq58.cn +qq.qqqg.us +qq.qqse8.com +qq.qqww.us +qq.s132.288idc.com +qq.sbwanwan.com +qq.ssoo.us +qq.sssae.us +qq.tencent-im.uc.gd +qq.tx2009qq.com +qq.vip.com.go.qq-net-com.cn +qq.wfj1.cn +qq.wwmei.com +qq01.cptiandi.com +qq08d74.cn +qq10.cc +qq1000.vip8.idcidcidc.com +qq10000-vip.cn +qq10000a.com +qq10000ky.cn +qq10000w.com +qq10000ww.com +qq10c.net +qq10txx.com +qq12345.kmip.net +qq168.six6.net +qq1918.cn +qq199vip.cn +qq2008jkc.cn +qq200909.com.cn +qq2009d.cn +qq2009ds3.w223.bizcn.com +qq2009et.com +qq2009nd.cn +qq2009vip.net.cn +qq2009yx.com +qq2010szn.com +qq2010vip.org +qq2629.com +qq284.cn +qq29.cn +qq2xxd.org +qq33fsdwds.3322.org +qq3698.cn +qq548.com +qq5577.com +qq56.os.io +qq5658.com +qq6.xhv2.cn +qq6523.cn +qq6686.cn +qq68.org +qq68.sov.cc +qq6988.com +qq7.xhv2.cn +qq7579.cn +qq8586.cn +qq86666.cn +qq8868.com +qq8899.002.szflw.com +qq8d8.cn +qq9.en.st +qq949023.free2.iisiisiis.com +qqad2009.cn +qqajkluioy.3322.org +qqaoc.com +qqaon.com +qqaou.com +qqaov.com +qqavc.cn +qqazxc.cn +qqb1gaio.3322.org +qqb45.cn +qqbjut.cn +qqbnpd.cn +qqbo.bobo7588.cn +qqbov.cn +qqbrtr.cn +qqc2009qq.cn +qqc51.cn +qqcej.cn +qqcj.6x.to +qqcmts.cn +qqcoa.com +qqcs2009.cn +qqcv2009.cn +qqcvxv.cn +qqdddggg.cn +qqddzznn.8866.org +qqdede.cn +qqdesd.cn +qqdnf00.cn +qqdnf22.cn +qqdnfqq.com +qqee334.cn +qqeetu.cn +qqekq.cn +qqen10000.in +qqeype.cn +qqf222.cn +qqfarmb.cn +qqfarmd.cn +qqfarme.cn +qqfarmg.cn +qqfarmr.cn +qqfarmw.cn +qqfarmx.cn +qqfarmy.cn +qqfc8.cn +qqfmh.com +qqfof.com +qqfrw.cn +qqfzl520.my3gb.com +qqgame.1010zz.cn +qqgamelogo.cn +qqgkw.cn +qqh2009.com +qqhsv.cn +qqhuii.cn +qqhx.uugua.cn +qqhyt.cn +qqhz2009.cn +qqi199.cn +qqjchh.cn +qqjhn.cn +qqjiang.com +qqju.org +qqk2009.com +qqkikc.cn +qqkk009.cn +qqkkkq.cn +qqkskr.cn +qqksy.com +qqkuyou.cn +qql10.cn +qql5z.cn +qqm.name +qqnae.com +qqo68.cn +qqokip.com +qqokq.com +qqomc.cn +qqootv.cn +qqoov.com +qqpcj.cn +qqpkz.com +qqq10.cn +qqq325698.7766.org +qqqeeeww.cn +qqqk2.cn +qqqq2009.com +qqqqkkkss.cn +qqrgb.cn +qqsevice.com.cn +qqsg.ok.to +qqsp09.cn +qqsxq42.cn +qqszn.cn +qqt10zn.cn +qqtce.cn +qqtouxiang.keaiq.com +qqtq.open2009.net +qqtrrt.com.cn +qqtrtr.cn +qqttb8.com +qqttgt.cn +qqtvzb.9966.org +qqtwwt.cn +qqtx-10.com +qqtx10.com +qqtxk.com +qqtxun.cn +qqtxvip9.com +qquamy.cn +qquc.0130.6464.cn +qqupm.cn +qquude.cn +qquxv2.cn +qqv0088.com.cn +qqv8v.com +qqvds.cn +qqvip.2.dns111.cn +qqvip.org +qqvip009.com +qqvip168.com +qqvip2.cn +qqvip2010k.com +qqvip26.cn +qqvip315.com +qqvip33.cn +qqvip510.com +qqvip520.com +qqvip668.com +qqvip678.cn +qqvip8.com +qqvip911.com +qqviphls.cn +qqvipo.usa58.net +qqvipqqcom.cn +qqvong.cn +qqvv2009.cn +qqvvzv.cn +qqwangqq.info +qqwbaokaw.com +qqwet.com +qqwp2009.cn +qqws2009.cn +qqwt2009.cn +qqxs6.cn +qqxsz.net.cn +qqxuy.cn +qqxy.yss8090.com +qqxzu.com +qqyf09.cn +qqyterf.cn +qqzaj.com +qqzc01.cn +qqzock.cn +qqzsfd.cn +qqzxcjklhgy.3322.org +qqzzxxaass.3322.org +qsbt.3322.org +qscdfdda.cn +qsre355.7788d.info +qsxdeww.cn +qt0955.cn +qtfee.com +qtorifik.cn +qtq178.cn +qtxqq.cn +qtxw48.cn +qu1q.cn +quakearena32.ru +qualitymedsdoor.com +quanj2ia.count.xj.cn +quaybooks.co.uk +quickwebplayer.com +qunfazone.cn +qutaoba.com +quu.wqiu.x.eki.ssk.os.972wyt.com +qvod-8.cn +qvod-bobo.237yud.cn +qvod.15wyt.com +qvod.6w969.com +qvod.8q10.cn +qvod.com-2.cn +qvod.down.vbn5.cn +qvod.down.xzx6.cn +qvod.dyshy.com +qvod.play.fde1.cn +qvod.thesswws.com +qvod.xxoo888.cn +qvod.y2y2dfa.cn +qvod088.com +qvod1.info +qvod28.cn +qvod80.cn +qvodabc.info +qvodbo.2288.org +qvodoo.2288.org +qvoev323.cn +qw.qqsiv.com +qw18.cn +qw2009k.cn +qwdghu.com +qwedasertafoas.com +qwertx.cn +qwerty-soft.com +qwjzd.cn +qwoir.cn +qwr1.cn +qwr2.cn +qwr3.cn +qwr7.cn +qwr8.cn +qwu4.cn +qwuyf.cn +qwweea.cn +qwwxr.cn +qwwz.free.mingyao.net +qxqx.7766.org +qy.aj5n.cn +qy.bh2g.cn +qy.dh5k.cn +qy.fn6k.cn +qy.fr3d.cn +qy.jr5c.cn +qy.jr7i.cn +qy.kv5h.cn +qy.ln5g.cn +qy.sg3j.cn +qy.sj6k.cn +qy.vd4s.cn +qywm.3322.org +qyyjly.com +qzone.com.games-web.haoma.qq.vip.buy.665.net.ru +qzone3.7766.org +qzt56.com +r.4bh.info +r.cmst.info +r.game2.cn +r.mybestyouxi.cn +r.tlinee.com.cn +r02.3322.org +r03.3322.org +r04.3322.org +r06.3322.org +r07.3322.org +r1.xwsfx.com +r13.3322.org +r14.3322.org +r1fywoi3dphaa.3322.org +r2.xwsfx.com +r22.9966.org +r25281.nb.host192-168-1-2.com +r25319.nb.host-domain-lookup.com +r3.xwsfx.com +r36.3322.org +r4ca.3322.org +r4ikm.cn +r5p9.cn +r8b8b.cn +r8r88.5166.info +r99u.cn +ra.qqqg.us +ra03.k9f4.com +rabbityzp.3322.org +rabc.5166.info +radio.pybao.net +radiobelea.ro +radiosci.info +raernb.cn +ral.bc.ca +rammhz.co.cc +rapid-antivir2009.com +rapidsystemsend.ru +rav.q766.com +rav7.9966.org +ravelotti.cn +rbav.net +rbmatt.sites.uol.com.br +rbrtys.com +rc.r-c.co.kr +rcsdo.com +rd007.com +rdgrty.cn +re.myppskk.info +re11a.com +realemotions.ru +reallypulse.com +realmovs.net +rec.cztv.tv +recharger.cz.cc +record.orangebeartv.com +recover88888.com +redbool.cn +reddii.ru +reg.86ksz.cn +reg.sstv.me +reg.zqgame.com +regclean.com +regvac.com +reishus.de +rekrute.net +remote.vip8.htidc.com +renbenfengliu.com +renbense.com +rende-128-k15.com +rene-xl.bzctoons.net +renrenwang.me +rep.s-zone.com +reportsystem32.com +res.9dzc.com +resev.ru +retrobaziliona.com +reverse.kz +rewdsds333.8866.org +rewqsddq.t35.com +rews.ss.la +rfrzs.com +rftgyh890.8866.org +rh4df.cn +rhgfee.cn +rhlnrw.cn +ri.pigqq.net +ribenchengren.com +riblo21zone.xorg.pl +riconah.biz +ridgear.com +ringtonesjam.com +riwanlaobrilaoli44.3322.org +rncocnspr44va.cn +rnljm.3322.org +robera.info +robingood.beeglover.cn +rolex.com.copperbody.com +rolex.com.kickclean.com +roxy-man.ru +rpg.2288.org +rpt2.21civ.com +rqfrakxc.ignorelist.com +rqq1.cn +rrr784512.7766.org +rrrkkk.com +rrrrffff.cn +rrrrggggg.cn +rrrrpppkk.cn +rrrtttccc.cn +rss-lenta-news.ru +rss.4816.info +rt.x9k.info +rt163.info +rt212.cn +rtfsti.com +rtgma.com +rtyesxc.cn +rtyop.cn +ru.coolnuff.com +rubos.in +rufeng18.3322.org +rufengbie13.3322.org +rufengbie4.3322.or +rufengbie6.3322.org +ruler-p2p.com +runa.fileave.com +runescapesr.com +russia.9966.org +ruyi-8.cn +rw.nxonline.info +rweuio.cn +rx11.086327.com +rx11.u2h6n.com +rx11.wt7i8.cn +rx11.zy8s3.cn +rz12.135831.com +rz12.8u9i.com +rzsdo.com +s.3f4wws.cn +s.78zzz.com +s.79cc.com +s.90ccc.com +s.97qingse.com +s.dfseww.cn +s.freww2.cn +s.gdgr3e.cn +s.rdeg42.cn +s.registear.info +s.sos0.net +s08u.dns8zy2.cn +s0l1ng3n.com +s1.jud4g.com +s10248s0s.tzsx226.2666.com.cn +s11.uwb4.com +s15.b387yh3uyh.3322.org +s1system.com +s23.b387yh3uyh.3322.org +s234.8866.org +s3.bengbeng1.3322.org +s32.5201821.info +s3221sss3.cn +s33.idc.xpli.cn +s51.cnzz-c.cn +s581.3322.org +s8.syooo.cn +s9k3.com +sa13.a2j9x.com +sa13.t12hg.com +sa222111.cn +saasasasas.3322.org +sadasdwq.cn +sado01jd9.cn +sadsae3.cn +sadw222.cn +safe.eloer.cn +safe.sucop.info +saferew3.8866.org +safgr4.3322.orgn +sag11.9966.org +sag34.3322.org +sam-43.dns0755.net +sankygz.com +sanxing05.cn +sanxingkk.cn +sao96.com +sasezdfg.cn +satel09ws.co.cc +sathalf.com +saturnosistema.com.br +saur.sfwffres.cn +sauter.no +sawt-gharb.com +sb.degreesbuy.com +sb.dnfwg1.info +sb.perfectexe.com +sb.ymlsw.cn +sb173.com +sb2079.91mt.com +sb360.ymlsw.cn +sbl123.3322.org +sblfc.com +sbu0.8800.org +sc.ag008.com +sc7w.cn +scaizq.cn +scaner-file.tk +scaner-rip.tk +scaner-sbite.tk +scanprime.com +scantoolsite.com +scanw.3322.org +scanw.8800.org +scanw.8866.org +schear.serveftp.com +scundf.sudacc.com +scw666.com +scw678.cn +sdade333.6600.org +sdagfsaf.3322.org +sdd.ss.la +sddssy.gahkjiwehwekf87w234jkljfi324538hiofu889234h2jkhioiui023j4kj.cn +sdelaem.cn +sdeorkqo1.cn +sder44.net +sderfg.com +sdewax.cn +sdff54g.3322.org +sdfkjberkjw351rmsdfk.narod.ru +sdfsdf33.cn +sdfsdg.3322.org +sdfxcvb.cn +sdgdfgbe.3322.org +sdgggh.cn +sdjhgj.cn +sdjnha.com +sdkjgndfjnf.ru +sdnmro.cn +sdo.aionom.com +sdo.ms +sdomxd.cn +sdoovip.com +sds3222.cn +sdsdkj.net +sdse12345.cn +sdyy.info +se.0512pw.com.cn +se.0573web.com.cn +se.07ss.com +se.1234cao.com +se.1234ee.com +se.1234kk.com +se.1234mmm.com +se.1234nnn.com +se.1234see.com +se.1234sese.com +se.1234wyt.com +se.123haobaidu.com +se.123sese.info +se.125wyt.com +se.12smm.com +se.163wyt.com +se.17gby.com +se.18rb.com +se.1aaxx.com +se.1ffdd.com +se.1gghh.com +se.1qingse.com +se.1qqcc.com +se.1qqww.com +se.1ssdd.com +se.2009ai.com +se.22caomm.com +se.234pao.com +se.235wyt.com +se.25isese.com +se.280wyt.com +se.28gan.com +se.29cao.com +se.29smm.com +se.2aaxx.com +se.2ffdd.com +se.2gghh.com +se.2qqcc.com +se.2ssdd.com +se.2tyjq.com +se.30sss.com +se.33isese.com +se.33xxoo.com +se.34gao.com +se.35aa.com +se.360gan.com +se.369bo.com +se.3aaxx.com +se.3gghh.com +se.3jjxx.com +se.3qqcc.com +se.3qquu.com +se.3ssdd.com +se.3zzxx.com +se.44wen.com +se.44xxoo.com +se.456pao.com +se.46se.com +se.48gan.com +se.4aaxx.com +se.4ffdd.com +se.4gghh.com +se.4ggxx.com +se.4jjxx.com +se.4qqcc.com +se.4qqww.com +se.500wyt.com +se.52xxoo.info +se.552se.com +se.555mi.com +se.55crw.com +se.55isese.com +se.567nba.com +se.57bi.com +se.57mao.com +se.57rb.com +se.58gan.com +se.5ffdd.com +se.5jjxx.com +se.5jyss.com +se.5qqbb.com +se.5qqcc.com +se.5qqww.com +se.5wwdd.com +se.5zzxx.com +se.6322.info +se.66qsw.com +se.67gao.com +se.67sese.com +se.6aaxx.com +se.6bbss.com +se.6ffdd.com +se.6zzxx.com +se.700wyt.com +se.70kxw.com +se.710wyt.com +se.766jj.com +se.789pao.com +se.789rt.com +se.7aaxx.com +se.7crw.com +se.7ffdd.com +se.7gghh.com +se.810wyt.com +se.816xx.com +se.833kxw.com +se.85rrr.com +se.8gghh.com +se.8qqxx.com +se.91rbr.com +se.92xxoo.com +se.940wyt.com +se.941uu.com +se.94gao.com +se.970xxoo.com +se.971sese.com +se.97bose.com +se.97gb.info +se.97ibobo.info +se.97ise.info +se.97pw.com +se.97sewyt.info +se.97tu.info +se.97wen.name +se.97xo.info +se.97xxb.com +se.97yes.com +se.988wyt.com +se.997wyt.com +se.99xjw.com +se.9gghh.com +se.9kss.com +se.9qqcc.com +se.9qqxx.com +se.a6633.net +se.aafang.com +se.ai8k.com +se.aise11.com +se.alwyt.com +se.av-av.info +se.baikm.info +se.beijingxx8.com +se.cao78.com +se.chengrenwang.biz +se.ggfang.com +se.goolge1.com +se.jiuquse.net +se.kaixinfou1.com +se.kk66.info +se.molong.net +se.niwyt.com +se.nrfang.net +se.pao44.com +se.qingwuyuetian.info +se.qswyt.in +se.sao16.com +se.sao79.com +se.sao94.com +se.sao96.com +se.se-sese.net +se.se7yt.cn/Apian +se.se7yt.cn +se.semeimei.org +se.seqingwang.net +se.sexdy7.com +se.smm3.com +se.smm9.com +se.sqwyt.im +se.sqwyt.us +se.tswyue.cn +se.ugu123.com +se.woyaoxingjiaowang.net.cn +se.wyt.im +se.wyt765.com +se.wyt94.com +se.wyt97.com +se.xingjiaow.com +se.xxbo999.com +se.xxgg999.com +se.yuyu611.info +se.zglcai.com +se11.info +se11se.net +se12se.com +se13se.com +se13se.net +se14se.net +se15.zy8s3.cn +se15se.com +se18mm.com +se192.info +se2.bxhost.com +se288.com +se3.abisp.cn +se53se.net +se54se.com +search.97xxoo.com +search.hopto.org +search.ok365.com +searchbad.org +searchfindbuild.org +searchnexus.info +searchopt7.com +searchshrine.info +sebobo.info +seclabnet.cn +secure-suite.net +securedbizcenter1.cn +securedvirusscan.com +securerealy.com +secureshelldownload.com +securesystemupdates.com +security.canadatvsite.com +securitysystemupdates.com +securitytestinternetguide.com +see8.web.fc2.com +seemimi.net +seesun.web.fc2.com +seexn.cn +seibb.com +selang777.com +selang8.info +selang888.com +seman8.freehostia.com +sendspace-free.com +seo.2020sila.com +seo.hi72.com +seocom.name +seofon.net +sepian9.co.cc +seqing.sdjzw.cn +seqingwang.net +seqingwangzhan.org +sercile-aq.tk +sertuddh33jf.com +serv.ahau.edu.cn +server.3653.com +server38.2010player.info +server911.ch +service-mms.ru +serviceexe.com +servupdate.cn +serw.clicksor.com +sese.bencibo.cn +sese.rentihome.com +sese123.280xxoo.com +sese123.us +sese97.0d.0a.jioo.32625.net.cn +sesecom.3322.org +sesedh.web.fc2.com +seselu.com +sesemmse.3322.org +sesese.y145c.cn +sesesese.bengbengliuliang.3322.org +seset.com +setao.info +setup.97bobo999.cn +setup.ov-v.com +setup.regclean.com +sevorond.com +sewo.9966.org +sex369info.spaces.live.com +sex4you.crazynet.org +sex52sex.com +sex52sex.net +sexa.k3w.ddisk.net +sexba.3322.org +sexba.budu.cc +sexba.cz.cc +sexba.nu.mu +sexbases.cn +sexbo66.com +sexdy7.com +sexho.com +sexkoj.info +sexkok.info +sexku.fw.nu +sexofvideo.com +sexxse.com +sexyhub3.com +sexykurven.com +sezse.info +sf018.com +sf107.com +sfdght.com +sfera163.ru +sg.youluna.com +sg165.9966.org +sghvegpsbvf.com +shabi.coolnuff.com +shangav.com +shangshan.w990.vhostgo.com +shangxin.a.lunqun.com +share-home.net +sharetechnology.cn +sharplink.ru +shashayuqi.cn +shbxgp.com +she48.com +shecpss.com +shengun.web.dns12580.com +shenlong168.com +shezmint.com +shier41.ww.stx8.com +shion5.80.cnnicidc.com +shipin39.cn +ships.ath.cx +shit.sjhf4gh.net +shkens.net +shmysheros.9966.org +shop.colorful.cn +shop.taobao359009580.com +shop86.biz +shop888369.sutao.net +shopgroov.net +shoujiqianming.com +showabout.com +sht.bestbreakingfree.com +shuihu.miduo.com +shup.com +shutte.cn +shwalbbolzen.cx.cc +sidejets.co.cc +sile.qvod658.cn +silvaluizsilva.50webs.com +silvecoolg.com +silver-metscorp.com +sim.whu.edu.cn +simswarmsad.com +sina.ch.ma +sina.hd-2009.com.cn +sina.jiahuiqc.com +sina12-wb.tk +sina12sina.3322.org +sinaccc.cn +sinahdong.163.to +sinatv.cn.to +sinawpp.com.cn +singlioo.w3.cqgod.com +sinomedical.cn +sitedrugsproper.com +siteiscool.com +sitespacesexe.com +siwa.40web.com +siwamm.net.cn +siwowz.com +six49.com +sj1j1.cn +sj899.cn +sjfdhw395t.com +sk01.9966.org +sky.greatsalesgroup.com +skyll2010.3322.org +skystels.com +skyway3.com +sl.hzau.edu.cn +sl0rd.codzs.com +slalaka.biz +sleepatnight.cn +sll9026.cn +slllj4.cn +slqqv.com +slzzcom.com +smartcanadianseat.com +smartermedshop.com +smdl1.3322.org +smile-me.net +sms.qingchun001.cn +smskb.com +smwy.siwang2010.com +smxx.zjhyedu.cn +smy.qingchun001.cn +snl.qc.cx +snow.happynews1.com +so.021.org +so.nje0.cn +so11.cn +so8.sc.cn +sobov.com +soch001.info +socks5service.cn +sockslab.net +soft-rapidshare.net +soft.24417.cn +soft.9ptv.org +soft.go2000.org +soft17.vvnow.info +soft7.7747.net +softupdate09.com +software-clicks.com +sohu.com.dianlao120.cn +sohu.go.8866.org +sohubox.cn +soirnf.ttqipai.com +solocherry.ru +some-files-online.com +somev.ru +soonusee.com +sopingi.web.id +sos.77box.com +soveroste.com +sp.cpushpop.com +sp.demisetoken.com +sp99123.cn +space.cachefly.net +space11.webcindario.com +space2009city.cn +spafeixin.cn +spalian.maya777.com +spdown.9966.org +spfkr.com +spfpratinendfggtone.net +sphusa.com +spicyhappy.com +spillupdate.com +spiralarc.com +spjiaoyou.com +spkwo.thecoupondiscount.com +spl.kerrq.com +splsystema.net +splts.com +sportextreme57.ru +sportsbay.cn +sporttoday.cn +spw-fighter.com +spysystemcom.cn +sql.55gg.com +sqq1.cn +sqtcjk.zekifirek.cn +sqwyt.48gan.com +sqwyt.88fv.com +sqwyt.917xxoo.com +srwfe.9966.org +ss.9k6k.com +ss.likekong.com +ss.sssae.us +ss52s.com +ss52ss.com +ss52ss.net +sseae.com +ssee88.com +sshsex.info +ssl.netfacil.th.im +ssq001.com +ssq007.com +ssq234.cn +ssq585.com +sss.2010wyt.net +sss.ses99s.cn +sssaaa1.3322.org +ssss.66qsw.com +ssss1a.cn +ssun.dddwfft.com +st1.cndwn.cn +stabilityinternet.com +staciegonzalez.com +stallvars-2.cn +stamset.com +starfuckers-celebrity.blogspot.com +starlage.com +stashbox.org +stat-googlecom.cz.cc +stat.wauee.com +statd.3322.org +static.512xxoo.com +static.880xxoo.com +static.nimp.org +static.xy.5pk.com +static2011online-search.in +staticdne.9966.org +staticdnf.9966.org +statst.in +statviewa.9966.org +statviewb.9966.org +stb.cnool.net +steklo-bel.by +stereo.si +stervtut.net +stonegrouphotels.com +stooi.cn +stop.count.xj.cn +stoper_2049.126gz.com +storemedswarm.com +stph.sfwffres.cn +strandednaked.com +strategiesrecruiting.com +streamcentral.ueuo.com +street-info.com +stroika-pro.ru +sts-tegisters.com +studiaweb.com +suba555.com +subtrontext.ueuo.com +sucop.zxapian.cn +sugfufcipc.cn +suhi4hr.net +suifeng03.7766.org +sunbin5.web25.badudns.cc +sundaymold.ru +sunplantlog.com +sunziduoduo.3322.org +super-tube-all.com +superkroliks.com +superprivatens.co.cr +suppliestubes.com +supra.zhuangyang.cc +sureyou.net +surprise-knsme.tk +suspended-domain.ru +suzuka3.fileave.com +svelin.com +svtube.cn +sw2.cn +sweetblondies.com +sweyes.co.cc +sxgfjg.3322.org +sxm1.net +sxp0.co.cc +sxtz.com +sxxoo.2ir.ir +sy2.perfectexe.com +sylicomservicious.com +syngoo.cn +syqzqq5.info +sys.postfolkovs.ru +sysconsolutions.co.za +system-codec.com +system-processes.com +systemcheckingdesk.cz.cc +systemxp.3322.org +szai.com +szbzkzgs.com +szhi01.3322.org +szwke.cn +t.1stcngame.com +t.1stwebgame.com +t.37lai.com +t.gameyule.com +t.gocsgo.com +t.jiuyaoyouxi.com +t.see-something.cn +t.sina163.info +t.xx7.in +t0x50tyu4xz.3322.org +t1eayoft9226b.cn +t3hrf.cn +t53f.cn +t7010.cn +ta0bao.w139.5kweb.cn +takau.org +taobao-2010s.com +taobao-g53.cn +taobao.0851.info +taobao.0931.info +taobao.h8.osv.cn +taobao.ht.cx +taobao.lylwc.com +taobao1.w3.dh52.com +taobao359009580.com +taobaog40.cn +taobaovip-n.cn +taobaovn6.cn +taosebb.com +taowaaini10.8866.org +tax3.cn +taxlt.tk +tb0102-vip.cn +tbao9.6600.org +tbdfr.cn +tbttbt.cn +tc.lianmeng2010.com +tc908.com +tcpaidui.com +tcw.firmsure.com +tdxs.info +tec.c4.fr +tec.ch.ma +techmastersofct.com +techscantrafficc.co.cc +tedowyhubal.com +temp-biz.cn +temp.ismydns.com.cn +temqay.com +tencenl.in +tengxun-2009qq.cn +tengxun001.3.53dns.com +tes10.com +test.52comnetcn.com +test.yyvvttcc.cn +test1.9966.org +test2.9966.org +test2a1f.ch.ma +test6666.w99.1860php.com +testednewpartner.com +testweb.sanguosha.com +text56men.xxnz315.com +tfuwzch.cn +tfyxffnacsc.com +tg.01lm.com +tg2.duolegame.com +tg26.subo.me +tghggg.cn +th16388.com +thaexp.cn +thaisn.com +thankyou1.count.xj.cn +thebloggin.net +thecamsnow.net +thecelebrityorgy.com +theexefile.com +theflower.9966.org +thehitek.com +theinternethustler.com +thejobscentral.com +thejordantoday.com +thelinkcolnmarkviiclub.org +theloadarea.in +theoschepens.nl +thesecuritytools.com +theson.com.cn +thespeeddate.ru +thetubeach.notlong.com +thetubeamps.com +theuniquetraveller.info +theyaredead.net +theyourown.cn +thezonecentral.in +thinkpadus.cc +thobandis.cx.cc +tiancheng.w1.cdndata.com +tiancity.b.bname.us +tiancity.eu.kz +tianclity.com +tiancty.3e3e.info +tianjincn.cn +tianya.risinimenma360.9966.org +tianya1.risinimenma360.9966.org +tianya2.360cn.8800.org +tibia-mc.net +timeforfuck.com +timewhich.net +timoxinn.cn +tingting2.com +tingtingjidi.com +tingv.ru +tintraffic.cn +tiondapulkat.com +tiotroussox4.cx.cc +tipdzlk.tk +titanzone.free.fr +titlea65477.kingstable.com.cn +titledown.safedown.info +titlejc5274.91mt.com +titlemdown.12222.f.yygczx.com +titlemdown.28655.f.yygczx.com +titlemdown.29965.f.yygczx.com +titlemdown.59905.f.yygczx.com +titlemdown.60555.f.yygczx.com +titlemdown.68514.f.yygczx.com +titlemdown.88098.f.yygczx.com +titlemdown.98884.f.yygczx.com +titlerinima.3602becool.info +titletitlekl1314.91mt.com +titletitlemdown.61233.f.yygczx.com +titletitlemdown.87703.f.yygczx.com +titletitlevl3767.91mt.com +titlew.exiazai.info +titlew.exiclickazai.info +titlexz.dhilly2018net.info +titlexz.likesoftssite.info +titlexz.newxiazaibacn.info +titlexz.save-17173.info +titlexz.thecocodowns.info +tj.114anhui.com +tj.37698.com +tj.5lla.com.cn +tj.gan3377.com +tj.gan3399.com +tj.gan7788.com +tj.hh88567.cn +tj.o0oq.cn +tj.qqxtup.cn +tj.wdjpq.net +tjt12wg223s.com +tk066.com +tk49.com +tl.houdao.org.ru +tlcho0.www7.910idc.com +tlp.yaofu.cn +tlshs.com +tm15.tvb.vu.cx +to.hyebbs.com +to2.5cnd.com +toinobv.3322.org +tompedurante.com +ton77.biz +tongji520.com +tonglve.cn +toolscan4.com +toomore.cn +top.n9a.info +top.rxcrw.com +top.veeww.com +top.veexx.com +top100videoz.com +top2010movietrailers.info +top568.info +topbannersystem.com +topic.xywy.com +topmeds10.com +topwale.com +tornrubberpants.com +tosbing.info +toshare.kr +toto.qvod774.cn +tougao.jxcn.cn +tourege.in +toushi360.com +tq-88.cn +tqyb.960960.net +track.wyzo.com +tracker.likedevil.com +trade.96963.com +trafficcworkparty.co.cc +traffka.eu +tragedia1.fileave.com +travelsw.cn +trenmeirland.ru +trenublo.com +trsgom.info +trucount3001.com +trumpetlicks.com +trunu.cn +trustgame.cn +tryourteam.cn +trysmartbank.cn +tse99.info +tsgd.w6.dh52.com +tsts168.com +tt.1k6.info +tt.765321.info +tt.cc88567.cn +tt.dd88567.cn +tt.ddvip.cn +tt.dx22.info +tt.ff88567.cn +tt.kkmm8.com +tt00oo.3322.org +tt01.cptiandi.net +tt1155.com +tt1tt.3322.org +tt4bbc.8866.org +tt628.cn +tt7.in +tt99lov.cn +ttc88.cn +ttdown.wg137.com +ttejk.cn +ttfghv.3322.org +ttfghvas.3322.org +ttnokia66.7766.org +ttt20091124.info +ttt258.com +ttttg.com.cn +ttttggggg.cn +ttttj.com.cn +ttttr.com.cn +ttttssspp.cn +ttw123.cn +ttyy.wowdnfs.com +tu-21.cn +tu456.com +tuan.zzw.cn +tube1820.com +tubeololo.org +tubesockvideo.com +tuk.qqfdde.cn +tuksaliz.com +tukuba.cn +turkinke.com +turkish.fileave.com +tutubest.com +tuuv07.cn +tv.sex168.me +tv.sex88.info +tv.smgbb.cn +tv5168.com +tvb5.6600.org +tvs8.tvb.c4.fr +twaute.com +twmicrosoft.com +two.natnatraoi.com +two.xthost.info +twqvod.com +tx-qq.com +tx28.vipjh.com +tx77uuaa.baootaoo.com +tx88hnhn.aoomenymail.com +tx9128.3322.org +txqq-009.cn +txqq10000-vip.cn +txqq2009-vip.cn +txqq2009vipx.cn +txqqyw.cn +txt.114Graph.com +txt.114central.com +txt.3ul2.cn +txt.amg777.com +txt.bhssd.com +txt.efgvd.com +txt.hsdee.com +txt.ioxxm.com +txt.iuyxc.com +txt.kadwo.com +txt.kxwwi.com +txt.loawd.com +txt.naiws.com +txt.opxxw.com +txt.uuxns.com +ty-vipo.info +tyane.cn +tyfddd.cn +tyher.gicp.net +tysduqqii.in +tyty.9yz.com.cn +tyujghj.cn +tz.67sese.com +tz.vugtamiw.cn +u.3399my.com +u.5136688.com +u.987255.com +u.9lwan.com +u.dfg8.cn +u.dhs4.cn +u.eds9.cn +u.fse7.cn +u.gpask.cn +u.ijs3.cn +u.light2012.info +u.lookforhosting.com +u.ted5.cn +u.utd4.cn +u.xhyydingbi.cn +u.yrd7.cn +u.yrd9.cn +u.ytd3.cn +u0.9e7fs.com +u0.d7n9.com +u0.hux7.com +u1.739292.com +u1.dtw360.com +u1.ed3t.com +u1.hux7.com +u1.make369.com +u1.s8f3.com +u1.t2ui.com +u1.wgcn8.com +u2.1369888.com +u2.1369zz.com +u2.739292.com +u2.9e7fs.com +u2.d7n9.com +u2.dtw360.com +u2.ed3t.com +u2.hux7.com +u2.make369.com +u2.s8f3.com +u2.wgcn8.com +u2168cn.3013.cn +u2ef323_g12d4v.hotel400.com +u3.739292.com +u3.9e7fs.com +u3.d7n9.com +u3.dtw360.com +u3.ed3t.com +u3.hux7.com +u3.make369.com +u3.muu998.com +u3.ovfr6.com +u3.s8f3.com +u3.wgcn8.com +u3h.ru +u3w.ru +u4.739292.com +u4.hux7.com +u5.hux7.com +u6.hux7.com +u66.us +u6u45.cn +u7.9e7fs.com +u7.d7n9.com +u7.hux7.com +u7.qvodze.com +u7.wgcn8.com +u8.1369888.com +u8.1369zz.com +u8.739292.com +u8.9e7fs.com +u8.d7n9.com +u8.ggov88.com +u8.hux7.com +u8.make369.com +u8.wgcn8.com +u89u.gnway.net +u9.1369888.com +u9.1369zz.com +u9.739292.com +u9.9e7fs.com +u9.d7n9.com +u9.dtw360.com +u9.ed3t.com +u9.hux7.com +u9.make369.com +u9.muu998.com +u9.s8f3.com +u9.swa5a.com +u9.wgcn8.com +ua46235362346.co.cc +uade.3322.org +uaerup.com +ubaddavis.haokan456.cn +ubcvesuuthr.com +uc.yi71.com +ucezl.cn +ucitip.net.in +uday.2288.org +udvyv.cn +ufo1.com +ufy9g1.chinaw3.com +ughjjk.8866.org +ugochaves.com +uh174299.ukrdomen.com +uhajokvfalesko.com +ui.buo.cc +uiefdd.3322.org +uiiooo656.8866.org +uin1.cn +uin5.cn +uiterbunagoretas.com +ujiklo321.8866.org +ujixuwrubvf.com +uk.thesswws.com +uk9otweuef39gmqt787if2uz.net +ukboox.cn +ukiuty.8800.org +ukks.aa118.uicp.cn +ukpuzzle.com +ukwirex.info +ukyerb3.3322.org +ul8581.91mt.com +ulibertagolionas.com +ullll.com.cn +um3156.91mt.com +umx1.worldadult.biz +un-limitedgaming.co.cc +un04.com +union.996116.cn +union.9966dh.com +union.procto.cn +union.souyes.com +union.wangye173.com +unionpic.boodvd.cn +unlock0452.cn +unovt.com +uone2.com +uoxz.info +up.cj-vv.cn +up.cndydy.com +up.fanv.cn +up.notepad7.com +up.s0so.net +up.spiritsoft.cn +up1.visualwork.kr +up4.kuwan8.com +upagent99.biz +upd-windows-microsoft.cn +update.17guagua.net +update.371.net +update.firepackets.org +update.heishatu.cn +update.imqzone.com +update.keepprivacy.co.kr +update.kele55.com +update.microsoft.com.herrjuy.vu +update.microsoft.com.hilli.com.mx +update.microsoft.com.ijlkij.com +update.protectone.co.kr +update.qixi55.com +update.qvod2.net +update.qvod988.cn +update.shuwhyyu.com +update.ut-com.cn +update.yese55.com +update1.pc2.cc +update1.winprotection-suite.com +update2.winprotection-suite.com +update3.cn +updater.rv.ua +updates.advert-network.com +upinosatoretr.com +upload.octopus-multimedia.be +upload4all.ru +upnext.info +upononjob.cn +upop.ru +uporntube08.com +upppp.com.cn +upup.21civ.com +upwap.org +uquiezeese.ru +urj0.cn +url.cjr001.com +urteewe.com +us.cnn.com +us18.ru +usa-yabao.com +usagene.com +usaufo1.vicp.cc +usaufo2.vicp.cc +usaufo7.vicp.cc +usaufo8.vicp.cc +usaufo9.vicp.cc +use55.fdzsshee.10dig.net +user.qqhe.com +userzeus.com +usrvnu.ru +uszers.cn +ut-game-sina.com.cn +utidg.cn +utionakertu.com +utrcg.cn +utt-sina.com.cn +uu.kanlink.cn +uu12.2288.org +uu163.web.fc2.com +uu77.info +uu814.8866.org +uusee.6600.org +uuxns.com +uvxmedia.info +uws8.cn +uyfdbmh.3322.org +uyjjk8.x2w.cdn9.info +v.169.net +v.31261109.com +v.40sese.com +v.54ed4.cn +v.591sese.com +v.6t65r.cn +v.6te43.cn +v.7rw3r.cn +v.9vcpp.cn +v.bfgr5.cn +v.bluesky01.cn +v.fr63t.cn +v.gxtv.cn +v.hot177.com +v.htmlvista.com +v.qsjyy.com +v.soft28.com +v.versw.cn +v.vv49.com +v.yao63.com +v00d00.org +v2d.3322.org +v2ww022.cn +v5tg.3322.org +v6-askdk01.cn +vabrm.cn +vae.nna.cc +valentinred.info +vantmy001.com +varzo.webs.com +vastramworldwide.com +vatind0.com +vava40.9966.org +vavation.5944v.net +vbdf23.xicp.cn +vbmcom.com +vc.zaqaab.cn +vcdywer.cn +vcup.in +vda.uuzu.com +vdir.kz +vdsvcsa.3322.org +vdswrt.com +ve7370.91mt.com +vegaspoker24.com +velewr1rst.com +vente-directe-2010.com +verfer.com +verifyed-exearchive.com +versace.9966.org +vert4.cn +vertierogovq.net +verysighn.net +veuo.cn +vfegt342.3322.org +vftyheww.cn +vfvfvf.e632a.cn +vfyte.com +viautytdsfs.cz.cc +video-file.com +video-news.cn +video-trailers.net +video.baidu.com.111mm.co.cc +video.classmates.interstitialcontrol.message-c1ra1cs1.informationcareerbuilder.com +video.falrede.ru +video.urlservice.cn +video22505.fileave.com +videofiless.net +videokinos-xxx.ru +videoplugs.net +videos-e-fotos.webcindario.com +videos.dgshippingbd.org +videovideoparty.info +vidquick.info +view.wmusic.cn +viksamon.com +vinuko.de +viorfjoj-1.com +vip-cc1.cn +vip-em.cn +vip-tb22.cn +vip.114.graph.com +vip.132xxoo.com +vip.133xxoo.com +vip.134xxoo.com +vip.230xxoo.com +vip.320xxoo.com +vip.330xxoo.com +vip.333ty.com +vip.345xxoo.com +vip.440xxoo.com +vip.456xxoo.com +vip.500xxoo.co +vip.523xxoo.com +vip.550xxoo.com +vip.567xxoo.com +vip.64xxoo.com +vip.676566.cn +vip.700xxoo.com +vip.77169.com +vip.77kxw.com +vip.800xxoo.com +vip.86ksz.cn +vip.880xxoo.com +vip.900xxoo.com +vip.970xxoo.com +vip.990xxoo.com +vip.9bic.net +vip.av.86ksz.cn +vip.av112233.com +vip.dob3.cn +vip.gg55.com +vip.hj11.info +vip.htmi2.com +vip.htmi3.com +vip.jmcatv.com.cn +vip.qq.wz12.com +vip.v989.com +vip.wg611.com +vip1s2.3322.org +vip250.3322.org +vip4y.3322.org +vip748.3322.org +vip762.3322.org +vip81705.3322.org +vip872.3322.org +vip8fetion.com +vipcctv-2.cn +viper.0870sw.cn +viper.8gcc.com +viper.eloer.cn +vipfq.com +vipoos2.3322.org +vippif.net +vipqqhaomajingcai.friend-qq-com.cn +vipsexxxpornogo.ru +vipsine.com +vipyahoo-cm.co.cc +virtus76.narod2.ru +viruscn.9966.org +virusus.9966.org +visioncomunicaciones.cl +visualizar18.dominiotemporario.com +vitaminki.co.cc +vjccc.com +vk-88.ru +vkontaktex.com +vkt55wg666r.com +vkylchat.cn +vlaamsbelang.be +vo.ismydns.com.cn +vod.97de.com +vod.df2t.cn +vod.hhsese.com +vod.seset.com +vod.tv190.com +vod123.8866.org +vod21cn.chinafada.com +vofe.3322.org +vokcrash.com +vooiwuuei-2.com +vph.qfqf.co.cc +vpn318.cn +vpsvip.com +vqq1.cn +vrera.com +vrotemuch.com +vsalso-dkgj1.com +vsdfscv890.8866.org +vsedlysna.ru +vsz6iesdwe1aa.3322.org +vty8p.cn +vv.cnetindex.com +vv.cnn +vv00.qq88.in +vv0vv.3322.org +vv1.114jk.com +vv9999.cn +vvbggtr.cn +vvbggtr.cnn +vvf43rfewdw.8800.org +vvk3.cn +vvk5.cn +vvk7.cn +vvk9.cn +vvv888.3322.org +vwwew33.2288.org +vwwx17.cn +vytf.com.cn +w.4edg.cn +w.63d4.cn +w.6tg7.cn +w.7k7kjs.cn +w.7u8f.cn +w.807090.cn +w.9981ly.com +w.asdf456.cn +w.b1du.net +w.c66o.cn +w.cdd1.com +w.dw324.cn +w.exgif.com +w.fa1232.cn +w.fds32.cn +w.gg8721.cn +w.guo360.co.cc +w.hhh345.cn +w.huy87.cn +w.jsguangji.cn +w.mh8888.cn +w.mi2123.cn +w.mi5663.cn +w.muu998.com +w.qqnetcn.cn +w.qqstup.cn +w.qqtenet.cn +w.que567.cn +w.ri2326.cn +w.rich-9you.net.cn +w.siyou.org.cn +w.sog0u.co.cc +w.sre43.cn +w.sxxsnp3.cn +w.t3d5u.com +w.taogu.org.cn +w.toyony.com.cn +w.ustocn.com.cn +w.ut99889.com +w.vabcn.com.cn +w.vcmart.com.cn +w.vesaweb.com.cn +w.wesy67.com +w.xt918.com +w.zhufeng01.cn +w.zxcvbnmjkl.com +w01.fac7y.com +w05.fac7y.com +w1.123dcy.com +w1.163.com7w.com +w1.6yh4.com +w1.7777ee.com +w1.849jfg.com +w1.a2d6n.com +w1.akc8.com +w1.awyeg.com +w1.ccw12.com +w1.dddddd32.com +w1.dgfg4.com +w1.e4w5y.com +w1.fsdfe.com +w1.getdew.com +w1.iioo4567.com +w1.klkl111.8866.org +w1.mygg369.com +w1.qmisjww.cn +w1.rd7y.com +w1.ur36d.com +w1.win9987.com +w1.youxi.qq275.com +w1.ys8c.com +w10255.s4.needidc.net +w11.4g2s.com +w11.adada2.com +w11.s8m1.com +w1zzz.com +w2.6yh4.com +w2.7777ee.com +w2.awyeg.com +w2.dddddd32.com +w2.kabicao.com +w2.rd7y.com +w2.tv889.net +w2.ur36d.com +w2dge.cn +w2if.cn +w3.6yh4.com +w3.7777ee.com +w3.849jfg.com +w3.awyeg.com +w3.dddddd32.com +w3.rd7y.com +w3.ur36d.com +w3.youxi.qq275.com +w347302.s98.ufhosted.com +w4.bafang.cc +w5.123dcy.com +w5.akc8.com +w5.klkl111.8866.org +w5.ys8c.com +w55433.s21.chinaccnet.cn +w8.6yh4.com +w8.7777ee.com +w8.849jfg.com +w8.abcdnf.com +w8.awyeg.com +w8.dddddd32.com +w8.rd7y.com +w8.ur36d.com +w9.163.com7w.com +w9.6yh4.com +w9.7777ee.com +w9.849jfg.com +w9.akc8.com +w9.awyeg.com +w9.fsdfe.com +w9.getdew.com +w9.hwr46.cn +w9.rd7y.com +w9.ur36d.com +w9.win9987.com +wa-vip.com +waasdf.cn +wadw221.cn +waiouosd.com +wan886.com +wandashan.3322.org +wang.andy.cd +wang321.cn +wangdz.hongyun99.com +wangluo110.net +wanprofit.net +wantfinest.com +watafiti.com +watch-video.cn +watchepisodes.cn +wau.xzz2.com +wawnet.net +wbrj2009.3322.org +wc86.com +wd163.t3.to +wdb.8800.org +weak09.8udns2.cn +web-can.tk +web-soft2011pc.eu +web.9981ly.com +web.9bic.net +web.abcd1123.info +web.adminmimi.com.cn +web.cplnn.com +web.dnf3600.cn +web.guangpeer.cn +web.htmi2.com +web.htmi3.com +web.kfc.ha.cn +web.msx-1.info +web.nba1001.net +web.reg.md +web0622155.w201.dns558.com +web1.plscdn.com +web3.fimmu.com +web99222840.web159.dikavan.net +webalfa.cn +webasebox.info +webdizz.biz +webdportal.lgg.ru +webnews2009.nm.ru +webscansecurepc.com +websnewmails.tk +websoftb.3322.org +websscan.com +webvideo-files.com +webyeeworx.com +wedfxc.cn +wefaef.qa444.8866.org +weibo899.in +weishz.cn +weiwei520.vip.sina.com +welcome1.zj.vnet.cn +welcomeone.cn +welovetweet.com +welovewarez.com +wenyixuan.3322.org +weoad.cn +wer1234.cn +werttrew.com +wervaferganiota.com +werwer233.cn +westpres.info +westray.info +wetpussygames.com +wetv.7766.org +wetxty.cn +wew2223.cn +wf3gr.8800.org +wg.d1club.com +wg1185.cn +wg828.com +wg879.cn +wgg.6d2n.com +wgkkz.com +wgsqwr.7788j.info +wh.cztv.tv +wh2ye.2288.org +wh88.25u.com +whist-club.de +whitebiz.cn +whitesharksdesigns.com +whjiadian.com +whzi.sv1.swedns.cn +wi126.com +wi1919.3322.org +wi66db.cn +wii.per-line.cn +win-downloading-updates-server.com +win-pc-defender.com +win2009update.servehttp.com +winddk.ch.ma +windoss2009.3322.org +windowsp.3322.org +windowssp.7766.org +winggo.co.kr +winpc-antivirus.com +winpcdown09.com +winpcdown10.com +winpcdown99.com +wintotersstal.cz.cc +winupd.net +winxp7server.com +wiseguydigital.com +wissjjee80.hh.h001.33wdd.cn +wj-asys.com +wjfy.xinhuawangluo.com +wjsnben.9966.org +wlwz.13sin.com +wm.1kfie.cn +wm.245a34.cn +wm.2e7860.cn +wm.5fqwf.cn +wm.7udij.cn +wm.888b123.cn +wm.8iopi.cn +wm.8ld2.cn +wm.990248.cn +wm.99c342.cn +wm.9wfij.cn +wm.dk127.cn +wm.ds4ijf.cn +wm.ds5iop.cn +wm.egjee.cn +wm.ki2ip.cn +wm.mnv3.cn +wm.mnvk8.cn +wm.qq12300.com +wm.yxnjs.com +wm2118.5d6d.com +wm5588.com +wm7.semonk.com +wm8798.3322.org +wmdag3fd.3322.org +wmg.dfg34.cn +wmg.dsa32.cn +wmg.dsg67.cn +wmg.gfg53.cn +wmg.hdd32.cn +wmgade.3322.org +wmno1.vvie.net +wmurl.cn +wmwl88.3322.org +wn.163.to +wo.40sese.com +wo.48gan.com +wo8.ss.la +woaini1f.3322.org +woaini23456.com +woaini520.web003.boothost.com +wocaohaofan.ns1.v588.com +wodetxta.com +wofxx.com +wojiazaidongbei.cn +wokaaa.count.xj.cn +wolfsd.9966.org +wolfsd04.9966.org +woool.sdo.tc +wootryp.com +woqyymmptn.cn +wori1.8800.org +wori2244.3322.org +worldnews-video.com +worldnewsmagazines.org +worlds-of-tubes.com +worldtracknews.com +wow.3gali.com +wow.games520.cn +wow.mopgame.co.cc +wow.pcikchina.org +wow00.6600.org +wowbox-duowan.com +woweuroper.wo.ohost.de +wowfv.cn +wowoke.us +wowshe1l.com +woyaoxingjiaowang.net.cn +wq6.h001.9host.net +wqe3r223.cn +wqedqwdqw.cn +wqerae.cn +wqq1.cn +wqt1.cn +wr.54s.com +wr.dhr36.cn +wr.ghe46.cn +wr.gjr45.cn +wr.hef46.cn +wr.jft57.cn +wr.jkt57.cn +wr.kug78.cn +wr.sfg47.cn +wr323e2e2.cn +wretch.go.3322.org +ws-qq.com +ws071121.3322.org +wscksuka.cz.cc +wud.qc.cx +wungrp.com +wut99.cn +wuxifdc.cn +wuyedy.com +wv3211.91mt.com +wvg0.cn +wvg1.cn +wvg2.cn +wvg3.cn +wvg4.cn +wvg5.cn +wvg6.cn +wvg7.cn +wvg8.cn +wvg9.cn +wvlk.j.hz.syb.apfvl.450q.cn +wvw.86819.com +ww.360cn.8800.org +ww.455900.cn +ww.95selang.com +ww.97qingse.com +ww.97xxoo.com +ww.aisewyt.cn +ww.anjiake.com +ww.dfgerw.com +ww.guo360.co.cc +ww.jxliao8.com +ww.lelewyt.cn +ww.mtxa.net +ww.ppkok.cn +ww.ruixingshadu.co.cc +ww.wyt365.cn +ww.wytzt.cn +ww1.egu8c.com +ww1.uws3y.com +ww2.ajdkijejjf.info +ww3.89dx.com +ww3.niupan.com +ww898.com +ww8ww.3322.org +ww9.egu8c.com +wwaa4.7766.org +wwcctv3.com +wwd.fa4fs.com +wweesss444.com +wwhh88.com +wwl.abcdnf.com +wwm.ons22.com +wws.mobiec.net +wwttoo2.3322.org +wwv.79mm.in +wwv.cz3.net +wwv.diyou.net +wwv.gazei.com +www-avasthome.com +www-ksdx.com-com-www-sddxf.org- +www-np.wilndocuments.info +www-qq.net +www-qqcom.cn +www-sina.net +www-txqq.cn +www.0000-qq.cn +www.0001666.com +www.000wyt.com +www.002.la +www.005001.com +www.006555.com +www.0070007.com +www.007001.com +www.0073d.cn +www.007557.cn +www.007788.net +www.007wyt.com +www.00852555.cn +www.00852tm888.com +www.00856.com +www.008567.cn +www.0088woool.com +www.009001.com +www.009188.cn +www.00aaa.com +www.00mml.com +www.00ri.com +www.00tt.info +www.010223.com +www.010246.com +www.010268.com +www.010389.com +www.010488.com +www.0105568.cn +www.01058789.com +www.0106658.cn +www.0106677.cn +www.0108818.cn +www.010885.com +www.010898.com +www.010899.com +www.0109079.com +www.0109888.cn +www.010caipiao.com +www.010cpgfw.com +www.010cpw.cn +www.010gay.com +www.010zgcp.com +www.01285.com +www.01696.com +www.0202.cn.im. +www.020tongsheng.com +www.021print.com +www.023tvb.us +www.027shanshi.com +www.030033.com +www.031520.cn +www.033200.com +www.03345.cn +www.03988.cn +www.039999.com +www.050101.com +www.0523buy.com.cn +www.0551pop.com +www.056777.com +www.0575sos.cn +www.0579ly.cn +www.0592001.com +www.0595fushi.cn +www.05cctv.cn +www.06767.com +www.068cp.com +www.06jisj.cn +www.06wyt.com +www.0739ktv.cn +www.0749.com +www.0750car.net.cn +www.07dp.com +www.07yin.com +www.08318.cn +www.083999.com +www.08578.com +www.088299.cn +www.088gp.com +www.08cpw.com +www.08tm.com +www.0914114.cn +www.096888.com +www.09qq8.cn +www.0ule365.co +www.1.66aaaa.com +www.1.82yyy.com +www.10000-tenxu.cn +www.10000-txrqq.cn +www.10000-vip08.cn +www.10000kp.cn +www.10000qone.cn +www.10086feix.cn +www.100gsoft.cn +www.100yyy.com +www.10233.cn +www.103333.com +www.10555.com +www.1069.gs +www.108ri.com +www.10cao.com +www.10nnn.com +www.10qq.info +www.10qqgn.cn +www.10qqtx.com +www.10wk.cn +www.10year-qq.com +www.10years-qq.com +www.11-qq.com +www.110139.com +www.110568.cn +www.110xxoo.com +www.11117777.com +www.1111wyt.com +www.111ball.com +www.111cao.com +www.111hs.com +www.111mimi.com +www.111she.com +www.113111.com +www.1149.cn +www.114980.com +www.114baines.com +www.114hx.com +www.114lla.cn +www.114oldest.com +www.114tz.net +www.11500w.cn +www.115252.com +www.116228.cn +www.116889.com +www.11748.com +www.117cp.com +www.118cp.net +www.118cpw.com +www.119sf.com +www.11ip.info +www.11kfc.cc +www.11sss.name +www.11tt.info +www.120500.com +www.120yxb.com +www.12102.com +www.12102.net +www.12138.info +www.12162.net +www.121g.cn +www.123088.com +www.123188.com +www.123311.com +www.1234.la +www.1234666.com +www.1234cao.com +www.1234vv.com +www.1234ye.com +www.123896.com +www.123cp.com.cn +www.123fengliu.cn +www.123m.info +www.123mmbb.cn +www.12567788.cn +www.125828.cn +www.125wyt.com +www.126rtys.com +www.127136.com +www.12766.com.cn +www.128388.com +www.128828.cn +www.12888.cc +www.128hk.cn +www.12966.com.cn +www.12uc.com +www.1300li.com +www.13015.com +www.131111.com +www.13131.info +www.13278.com +www.133737.cn +www.134135.info +www.136138.net +www.1366.hk +www.137377.com +www.137998.com. +www.13894.com +www.138978.com +www.138cp.cn +www.138xxoo.com +www.139139.info +www.139339.com +www.13kvlts.cn +www.13you9.cn +www.141mm.com +www.1424314.cn +www.147xxoo.com +www.14sel.com +www.150688.com +www.1551777.com +www.156056.cn +www.156gps.com +www.158bk.cn +www.158yoxi.cn +www.15cr.info +www.1601800.com +www.160666.com +www.163187.com +www.1632wa.com +www.163cp.com +www.163dcf.com +www.163dji.com +www.163dsa.com +www.163fdr.com +www.163hdf.com +www.163ht3.com +www.163in.com +www.163iop.com +www.163jki.com +www.163kkj.com +www.163llc.com +www.163lmg.com +www.163mkl.com +www.163niu.cn +www.163rfg.com +www.163sq2.com +www.163uyt.com +www.163wangri.net +www.163wyt.com +www.163xxoo.com +www.163yip.cn +www.164wyt.com +www.165se.com +www.166cai.com +www.166kk.com +www.166m.info +www.166pp.com +www.166wg.net.cn +www.166wg.org +www.1685678.cn +www.1688nba.com +www.1688xungou.com +www.168csol.com +www.168oo.com +www.168rnb.cn +www.169s.com +www.169xxoo.com +www.16hao123.cn +www.16years-qq.cn +www.17173jw.com +www.1717v.cn +www.172se.net +www.1735s.com +www.173wyt.com +www.174mm.com +www.178bigfoot.cn +www.178sifu.cn +www.17abo.com +www.17bobo.com +www.17bose.com +www.17cmm.com +www.17ebook.com +www.17gan.net +www.17guagua.com +www.17lianwu.com +www.17lkdy.cn +www.17luoliao.cn +www.17nnn.com +www.17oye.cn +www.180666.com +www.18095.com +www.180cpw.cn +www.180vip.cn +www.1813355.com +www.181csol.com +www.18481.com +www.186gp.com +www.188180.com +www.188218.com +www.188389.cn +www.188466.cn +www.188558.com +www.188cai.com +www.188m.info +www.188ri.com +www.189go.cn +www.18abo.com +www.18film.com.vip.shixuntv.com +www.18hp.com +www.18kmm.cn +www.18lxkl.com +www.18vipmm.cn +www.18yuy.com +www.18yyq.cn +www.19099.com.cn +www.191188.cn +www.191188.com +www.191av.cn +www.192988.com +www.192ee.com +www.192ee.info +www.192ee.us +www.192jb.info +www.192lj.info +www.192mm.info +www.192qj.info +www.192se.info +www.192ss.info +www.19399.com.cn +www.197ri.cn +www.1991x.cn +www.199580.com +www.199pp.com +www.19ccc.com +www.19eee.com +www.19vvv.com +www.1bpao.com +www.1caoni.com +www.1ddkk.com +www.1eevu.cn +www.1ggmm.com +www.1ggss.com +www.1hhhh.net +www.1hougong.info +www.1kk2.cn +www.1qingse.com +www.1qqxx.com +www.1rrrr.com +www.1s2d3.cn +www.1sese.info +www.1setu.cn +www.1ttpp.com +www.1wyl.com +www.1zzxx.com +www.2008.366ent.com +www.2008jike.cn +www.2008mengqing.cn +www.2008okqq.cn +www.200909.cn +www.2009123.com +www.200988qq.cn +www.2009aaaa.cn +www.2009av.com +www.2009cctvk.com +www.2009dddd.cn +www.2009eeee.cn +www.2009ey.cn +www.2009fxfd.cn +www.2009fxmx.cn +www.2009fxvc.cn +www.2009iiii.cn +www.2009llll.cn +www.2009mmmm.cn +www.2009qqqq.cn +www.2009rrrr.cn +www.2009uuuu.cn +www.2009vip-qq.com +www.2009yct.cn +www.2009yt.cn +www.2010down.cn +www.2010hotmail.com +www.2011ou.com +www.20285.com +www.20730.com +www.20761788.info +www.208688.com +www.209678.cn +www.20bbb.com +www.20gan.com +www.2121888.com +www.2121a.com +www.212444.cn +www.212666.com +www.2144w.com +www.2159.net.cn +www.218318.cn +www.21885188.cn +www.218999.com +www.21909.net +www.21aog.com +www.2211cn.com +www.22132.com +www.221331.net +www.221441.com +www.222-leifeng.com +www.222112.com +www.222233.com +www.2222xb.com +www.2222ye.com +www.222324.com +www.223688.com +www.22409.com +www.22425.com +www.227226.com +www.227667.com +www.2277.cc +www.228228.net +www.228448.com +www.228cp.com +www.2298.cn +www.229899.cn +www.22ccc-22ccc-22ccc.cn +www.22ip.info +www.22qsw.com +www.22sese.com +www.22tt.info +www.230it.cn +www.231yy.cn +www.233488.cn +www.23406.com +www.23406.hk.cn +www.234315.cn +www.234444.com +www.235wyt.com +www.236236.info +www.237777.com +www.238111.com +www.238555.com +www.23899.com.cn +www.239168.com +www.23bi.com +www.23key.com +www.23ma.net +www.23zb.com +www.240666.cn +www.2476.com +www.24773.com +www.24ddd.com +www.2510s.cn +www.2525245.cn +www.255188.cn +www.258ak.com +www.258mn.com +www.258wyt.com +www.25aa.info +www.25heike.cn +www.25isese.com +www.25sys25.cn +www.26044.com +www.260555.com +www.260666.com +www.26199.com.cn +www.263388.com +www.2637.cn +www.265bb.cn +www.265cai.com +www.268788.com +www.26889.net +www.268bz.cn +www.269988.cn +www.26b.cn +www.26dh.cn +www.26gao.com +www.276388.com +www.27nnn.com +www.280wyt.com +www.280xxoo.com +www.281288.com +www.2815.net.cn +www.283168261.cn +www.28365365.com +www.2839.net.cn +www.288-suncity.com +www.288880.com +www.28fcw.cn +www.28gan.com +www.29017.com +www.295858.com +www.297gan.info +www.299578.com +www.29cao.com +www.29smm.com +www.2a8k.cn +www.2aaxx.com +www.2bj.cn +www.2c2d.cn +www.2ddxx.net +www.2fcc.com +www.2ffdd.com +www.2gvn.cn +www.2hhhh.net +www.2kkkk.com +www.2leet.net +www.2n3.cn +www.2qqxx.com +www.2qvod.cn +www.2rbi.cn +www.2ttss.com +www.2y4y.com +www.2yp.com +www.2yxb.cn +www.3-666.net +www.3000dooo.info +www.300444.com +www.300dnf.cn +www.301888.com +www.30197.com +www.302688.com +www.3040500.cn +www.30408.com +www.306307.com +www.30686.com +www.306888.cn +www.306888.com +www.30776.com +www.308268.cn +www.308633.cn +www.308cp.com +www.30986.com +www.3110.cn +www.3110508.com +www.311113.cn +www.311113.net +www.311422.com.6804.cn +www.311998.cn +www.313333.com +www.31441.com +www.315358.cn +www.315safe.com +www.315uu.com +www.318418.com +www.318555.com +www.318zq.cn +www.3197.net.cn +www.321adf3.cn +www.321hack.com +www.321so.net +www.322188.com +www.322922.com +www.323777.com +www.323kk.cn +www.329s.cn +www.32xxoo.com +www.330331.com +www.330337.com +www.331888.com +www.332255.com +www.332258.cn +www.3328gp.com +www.332dh.com +www.332pay.com +www.333013.com +www.3333-qq.cn +www.3333.xb.com +www.3333xb.com +www.3337888.com +www.333958.cn +www.333ci.com +www.333mi.net +www.333she.com +www.335578.cn +www.335889.com +www.3374.com +www.337668.com +www.3388cpw.cn +www.339980.cn +www.33aaaa.com +www.33cp.com.cn +www.33ip.info +www.33isese.com +www.33k6.com +www.33mao.com +www.3434y.com +www.34414.com +www.344aa.com +www.34508.com +www.345198.com +www.34531.com +www.34555.net +www.34567wyt.cn +www.345866.cn +www.345dnf.com +www.345xb.com +www.34618.com +www.34819.com +www.34gao.com +www.350088.com +www.3567.com +www.358359.com +www.358458.com +www.35dh.com +www.360.he.cn +www.360cn.8800.org +www.360gan.com +www.360haowan.cn +www.360safae.cn +www.360sb.in +www.360wb.co.cc. +www.360xxoo.com +www.36186.cn +www.361safae.cn +www.361tushu.cn +www.365bobo.com +www.365j.com +www.365wz.net +www.365xx.info +www.365yingyuan.com +www.366555.cn +www.368618.com +www.369555.com +www.369bo.com +www.373888.com +www.377678.com +www.37kuku.com +www.37renti.com +www.3800hx.com +www.383567.com +www.3838cp.com +www.38517.co.cc +www.388088.com +www.388488.com +www.388tt.com +www.38995.com +www.38jjj.com +www.38sz.info +www.38to.cn +www.38xxoo.com +www.38zz.info +www.39155.com +www.3939508.com +www.395666.com +www.39807.com +www.398k.cn +www.39928.com +www.39av.com +www.39avdvd.com +www.39gan.com +www.39sese.com +www.39xingfu.cn +www.3D2666.cn +www.3aaxx.com +www.3cctv610.com +www.3d0099.cn +www.3d1118.cn +www.3d1212.com +www.3d1567.cn +www.3d1866.cn +www.3d257257.co.cc +www.3d2618.com +www.3d3123.com +www.3d3188.com +www.3d33399.cn +www.3d355.com +www.3d3555.cn +www.3d3567.cn +www.3d3868.com +www.3d446.com +www.3d4888.net +www.3d49.cn +www.3d5000.com +www.3d5088.com +www.3d538.com +www.3d545.cn +www.3d546.cn +www.3d55.com +www.3d55688.cn +www.3d5688.com +www.3d5805.cn +www.3d606.cn +www.3d6555.com +www.3d668.com +www.3d670.cn +www.3d68123.cn +www.3d6848.cn +www.3d755.com +www.3d7778.cn +www.3d818.com +www.3d82.cn +www.3d827.com +www.3d8558.com +www.3d8568.com +www.3d8678.cn +www.3d8848.com +www.3d8886.com +www.3d896.cn +www.3d8k.com +www.3d90.com +www.3d908.cn +www.3d9369.com +www.3d9698.cn +www.3d9808.cn +www.3dc88.com +www.3dc928.cn +www.3dc978.cn +www.3dc989.com +www.3dcp777.cn +www.3dcp98.com +www.3dcplt.com +www.3dd666.cn +www.3ddmm.com +www.3ddyy.com +www.3dlt.cc +www.3dw328.com +www.3dw678.cn +www.3e4.info +www.3gghh.com +www.3ggss.com +www.3gp8.info +www.3gri.com +www.3hpec.com +www.3ons.cn +www.3qjc.com +www.3wyt.com +www.3zzxx.com +www.4000se.com +www.400333.com +www.40sese.com +www.419.com.cn +www.41nnn.com +www.42253.cn +www.424288.cn +www.4252.net +www.432001.com +www.43232.cn +www.435888.com +www.4368.net +www.43pu5.com +www.440140.com +www.440xxoo.com +www.44356.com +www.44411ffaa.cn +www.444224.com +www.444334.com +www.44456.com +www.444mi.com +www.44559.cn +www.4455abc.com +www.44737.cn +www.44789.com +www.44987.com +www.44aaaa.com +www.44fang.com +www.44jm.com +www.44niu.com +www.44uuu.com +www.44wen.com +www.452333.cn +www.454666.com +www.45476.com +www.456166.com +www.456258.cn +www.45666.com +www.456cao.com +www.456kill.com +www.456sese.net +www.456t.com +www.456xxoo.com +www.45765.com +www.45ka.com +www.45nnn.com +www.466555.com +www.466588.com +www.4666888.com +www.46se.com +www.4749.com +www.47822.cn +www.47rt.cn +www.47wyt.org +www.47yz.com +www.485800.com +www.488889.com +www.488898.com +www.488cp.com +www.48aa.com +www.48gan.com +www.4947.com +www.4950.com.cn +www.496649.com +www.49cai.com +www.49x7.com +www.4aaxx.com +www.4apao.com +www.4bit.cn +www.4ddxx.com +www.4gameranking.com +www.4gghh.com +www.4ggss.com +www.4jjxx.com +www.4ljsll.cn +www.4qqcc.com +www.4qquu.com +www.4selang.com +www.4slllj.cn +www.4vpao.com +www.4woool.com +www.4zzxx.com +www.5000se.com +www.500180.com +www.500988.co.cc. +www.500kxw.com +www.500wancp.com +www.503999.cn +www.503999.com +www.508508.net +www.50wu.cn +www.50zhong.com +www.5109520.com.cn +www.511222.tk +www.51208.my03.com +www.512xxoo.com +www.5151kan.net +www.5158au.com +www.516u.com +www.51787.com +www.518648.com +www.5188cc.cn +www.51avv.cn +www.51backup.cn +www.51bobo.info +www.51ecpss.com +www.51fang.cn +www.51fjw.com.cn +www.51gouwu.net +www.51hot.net +www.51jtq.com +www.51juben.com.cn +www.51kaokaoni.cn +www.51sedy.com +www.51she.info +www.51vv9.cn +www.51vvc.cn +www.51xj.org +www.51xyxi.mobi +www.520011.com +www.520883.com +www.520jiqing.com +www.520spmm.cn +www.520zhidao.cn +www.521dx.com +www.521mg.com +www.521wyt.com +www.522dx.com +www.522wyt.com +www.523sp.com +www.524485072.cn +www.525252.info +www.5252bb.com +www.5252bb.net +www.5252bo.net +www.5252se.com +www.5253.com +www.5263.net.cn +www.52833.com +www.528cp.com +www.52dp.com +www.52fa.net +www.52k6.com +www.52keer.cn +www.52mmnet.com +www.52pjwg.com +www.52sax.cn +www.52sbb.com +www.52ssss.net +www.52windows7.org.cn +www.52x52.net +www.52ysbbs.cn +www.530o.com +www.53299.com.cn +www.535488.cn +www.536999.com +www.538788.com +www.538899.com +www.539238.com +www.53cao.com +www.53kkk1.info +www.54-54.net +www.54057.cn +www.54271.com +www.5454xx.com +www.5460w.cn +www.547086.cn +www.54jjk.tk +www.54sese.com +www.54tz.com +www.550015.com +www.5500595.com +www.55235.com +www.55240.com +www.55299.net +www.552wg.cn +www.55356.cn +www.555447.cn +www.5555cp.com +www.555666888.com +www.5556777.com +www.555775.com +www.555cpw.com +www.555mi.com +www.556389.com +www.5566456.cn +www.5566456.com +www.5566456.net +www.5566555.com +www.5566y.com +www.556tv3.com +www.558789.com +www.558989.com +www.559168.com +www.5594.info +www.559cp.cn +www.55crw.com +www.55isese.com +www.55kb.com +www.55pp.com +www.5617.com.cn +www.562345.com +www.56238.com +www.566699.com +www.567086.com +www.5671567.cn +www.567158.com +www.567868.com +www.5678dy.com +www.567dx.com +www.568166.com +www.56850.com +www.568589.cn +www.568998.com +www.569666.cn +www.56abc.com +www.56guaji.com +www.57506.com +www.577666.com +www.578008.cn +www.57877.com +www.57dh.com.cn +www.57px.com +www.57qn.cn +www.57rb.com +www.57xxoo.com +www.57yin.com +www.580518.com +www.580999.com +www.585877.com +www.586388.com +www.586888.com +www.587cp.cn +www.588699.com +www.588gup.cn +www.588ym.cn +www.589889.com +www.58fcw.cn +www.590999.com +www.591cao.com +www.591rb.com +www.592lv.cn +www.59579.cn +www.59659.cn +www.5971s.cn +www.59869.com +www.598se.com +www.599123.com +www.599188.com +www.5b5b5b.com +www.5cdcd.cn +www.5d6g.cn +www.5ffdd.com +www.5ggss.com +www.5iav.net +www.5ibcc.com +www.5iqqmm.com +www.5k5588.cn +www.5l7mm.com +www.5letes.hu +www.5qqcc.com +www.5sese.info +www.5wwdd.com +www.5xni.com +www.5xse.com +www.5yaogao.cn +www.6006.cc +www.60788.com +www.60bbb.com +www.60gan.com +www.60sys60.cn +www.61118.com +www.61222.com +www.613388.com +www.618658.com +www.61av.com +www.61rr.com +www.61t-cctv3.cn +www.625588.com +www.626028.cn +www.628388.com +www.62ai.com +www.62moo.cn +www.630kt.com +www.633999.com +www.63966.com.cn +www.63aaa.com +www.63gps.com +www.63ke.com +www.642g.com +www.644888.com +www.648.cc +www.64838.com +www.64down.com +www.64xxoo.com +www.64xxx.com +www.651111.com +www.651x.cn +www.65465.cn +www.65488.com +www.654888.com +www.654v.com +www.655705.com +www.655996.cn +www.658658.cn +www.658wy.com +www.65gao.com +www.661662.com +www.661789.com +www.661cn.com +www.66289.com +www.662dy.com +www.663sh.cn +www.66468.com +www.665578.com +www.665959.com +www.665995.com +www.666089.com +www.666135.com +www.666158.cn +www.666300.com +www.666345.cn +www.66655666.com +www.666559.com +www.666665.cn +www.66666ball.net +www.666786.com +www.666828.com +www.666980.cn +www.666dx.com +www.666mi.com +www.666she.com +www.66704.com +www.6676.com +www.667669.tk +www.6680668.com +www.668118.com +www.668660.org +www.668662.com +www.6686666.com +www.668hn.cn +www.669119.com +www.66917.com +www.66aaaa.com +www.66bv.com +www.66cp.net +www.66green.com +www.66hhcc.com +www.66qsw.com +www.66sq.com +www.66uu.info +www.66xb.com +www.66zb.com +www.677b.com +www.678766.com +www.678886.com +www.679668.com +www.67gao.com +www.67pp.com +www.68146.cn +www.68262.com +www.686236.com +www.6869kk.cn +www.688365.com +www.688788.com +www.688cp.com +www.688hk.com +www.68bi.cn +www.68caipiao.com +www.68dnf.cn +www.68la.com +www.68s78.cn +www.69113.com +www.69818.cn +www.698598.cn +www.699677.cn +www.6999gp.com +www.699ai.com +www.69mmhh.com +www.6dudu.com +www.6ffdd.com +www.6ggss.com +www.6h98.com +www.6k-taobao.com +www.6k58.com +www.6mxx.com +www.6nnnn.com +www.6nxx.com +www.6oo7.cn +www.6qqxx.com +www.6see.com +www.6ttss.com +www.6u666.com +www.6xx8.com +www.6yy9.cn +www.6zzxx.com +www.700006.com +www.7000se.com +www.700333.com +www.700800900.com +www.700wg.com +www.700wyt.com +www.700xxoo.com +www.700yy.com +www.703sese.cn +www.704sese.cn +www.705sese.cn +www.70622.com +www.706sese.cn +www.707sese.cn +www.708sese.cn +www.709999.com +www.709sese.cn +www.70chun.com +www.70gan.com +www.70kxw.com +www.710sese.cn +www.710wyt.com +www.711999.com +www.711sese.cn +www.712666.com +www.712999.com +www.712sese.cn +www.71388.com.cn +www.713sese.cn +www.714sese.cn +www.715sese.cn +www.7185.com +www.71wen.com +www.7241.cn +www.72988.com.cn +www.72hk.net +www.732999.com +www.733768.com +www.733xxoo.com +www.738888.com +www.73dnf.cn +www.73hs.com +www.747678.com +www.74tube.com +www.74zw.com +www.750888.com +www.752s.cn +www.757677.com +www.757855.com +www.75ea.com +www.75hk.net +www.760999.com +www.76323.com +www.76456.com +www.766cp.cn +www.766jj.com +www.76nnn.com +www.76yu.com +www.770048.co.cc +www.770156.cn +www.770772.com +www.771234.net +www.771567.cn +www.771588.cn +www.771588.com +www.774x.com +www.776886.com +www.776la.com +www.777060.com5.tw +www.777456.com +www.777559.com +www.777618.com +www.777655.com +www.77767.net +www.7777788888.com +www.777799.com +www.777kkk.com +www.777mi.net +www.778998.com +www.77cpw.com +www.77wyt77wyt.info +www.780666.com +www.78478.cn +www.785566.com +www.787571.cn +www.787675.com +www.78777.cn +www.7878678.com +www.787999.com +www.78824.com +www.788520.com +www.788998.com +www.788ty.com +www.789654.com +www.789977.com +www.789bb.com +www.789cp.com +www.78aaa.com +www.78ai.com +www.78dnfwg.com +www.78hk.net +www.78pao.com +www.78sds.info +www.78xmm.cn +www.78zzz.com +www.79288.com.cn +www.79388.com.cn +www.79456.cn +www.798cp.cn +www.79cc.com +www.79kk.cn +www.7aaaa.com +www.7aaxx.com +www.7crw.com +www.7ddxx.com +www.7dnfwg.com +www.7f7f.com +www.7gan.org +www.7hacker.com +www.7qqxx.com +www.7sese.info +www.7stk.com +www.7vse.cn +www.7yt.us +www.7yyxx.com +www.7zzxx.com +www.800658.com +www.80077.net +www.800810down.cn +www.800868.tk +www.800cai.com +www.800cpw.cn +www.800made.cn +www.802888.com +www.80335.cn +www.803456.com +www.8066188.cn +www.807066.com +www.808.hk +www.8080tm.com +www.808889.com +www.809678.cn +www.80hack.com +www.80kfc.com +www.80ssx.cn +www.810wyt.com +www.811858.com +www.811mama.cn +www.812666.com +www.81444.com +www.81543.cn +www.816868.com +www.816xx.com +www.82190.cn +www.82277.com.cn +www.825555.com +www.828789.com +www.82890.com +www.82nnn.com +www.82yyy.com +www.830580.com +www.8336.cn +www.8336f.cn +www.83396.com +www.833v.com +www.835666.cn +www.835gp.com +www.837666.cn +www.83xx.info +www.84166.com +www.8420.cn +www.844666.com +www.846666.com +www.84777666.com +www.84882.com +www.84bb.info +www.84gao.com +www.84ry.cn +www.84sel.com +www.853368.co.cc +www.855688.com +www.85580000.com +www.855858.com +www.855dnf.com +www.856333.cn +www.85659.com +www.856778.com +www.858188.com +www.85gov.cn +www.85l6.com +www.85rrr.com +www.860217.cn +www.864868.com +www.865558.com +www.866155.com +www.866nu.cn +www.866pp.com +www.868111.cn +www.868555.cn +www.8687.cn +www.8688cp.cn +www.87006.cn +www.87066.com +www.870877.com +www.87093.com +www.876679.cn +www.87722.com.cn +www.877577.com +www.877677.com +www.8788se.cn +www.87919.com +www.87ai.info +www.87sd.info +www.880667.com +www.8809.org +www.880990.net +www.881099.com +www.881212.com +www.881855.com +www.881882.com +www.881928.com +www.881kk.com +www.88233.com +www.88374.com +www.8839e.info +www.884666.com +www.884886.com +www.88512.cn +www.8866ctv.com +www.88685.com +www.88688qq.cn +www.886cpw.cn +www.886wyt.com +www.8877gp.com +www.8877gpw.com +www.8880.cc +www.8882888.cn +www.888383.com +www.8885.cc +www.888558.cn +www.888579.com +www.888765.cn +www.888859.cn +www.888879.com +www.888897.cn +www.8888ye.com +www.888cpw.com +www.888crown.org +www.888mao.com +www.8899456.com +www.889sese.cn +www.889wg.com +www.88dy.com +www.88fv.com +www.88ob.com +www.89008.com.cn +www.89189.com +www.893d.com +www.89494.com +www.895555.com +www.89777.net +www.898222.com +www.898655.com +www.899.hk +www.899099.com +www.89dx.com +www.89nnn.com +www.8apao.com +www.8as.cn +www.8gggg.com +www.8ggss.com +www.8lz4.cn +www.8n8m.com +www.8now.info +www.8qqcc.com +www.8qqxx.com +www.8tqq.com +www.8w888.com +www.8wt.com +www.8yyxx.com +www.900788.com +www.900990.cn +www.900wcp.cn +www.900xxoo.com +www.901001.com +www.90337.com +www.907888.com +www.908345.com +www.908866.com +www.908r.cn +www.90ca.cn +www.90ccc.com +www.90hk.com +www.90se.com +www.91-china.cn +www.911angers.tk +www.911av.com +www.911kxw.com +www.911mama.cn +www.913ain.com +www.91555.tw.cn +www.91555h.cn +www.91665.com +www.919500.com +www.91bbb.com +www.91cmm.com +www.91cvc.com +www.91goodman.cn +www.91k.us +www.91lele.com +www.91mt.com +www.91pz.com +www.91qianming.cn +www.91qsf.com +www.91rpp.com +www.91wav.com +www.91xf.info +www.91youa.com +www.920mm.com +www.922088.cn +www.922588.com +www.92388.com.cn +www.927k.com +www.927mm.com +www.928875.com +www.929767.com +www.92ddd.com +www.92hsf.com +www.92selang.com +www.92sezhu.cn +www.92tc.net +www.92union.com +www.92xxoo.cn +www.92xxoo.com +www.92xxoo.org.cn +www.92xxoo.org +www.9312530.cn +www.932888.com +www.9348.cn +www.9384.com +www.939777.com +www.939mm.com +www.93iii.com +www.93nnn.com +www.93san.com +www.93wx2009qq.cn +www.944443.com +www.945s.com +www.94950.cn +www.950188.cn +www.951ac.cn +www.951ax.cn +www.95559nj.com.cn +www.95selang.com +www.9623.net.cn +www.96363.com +www.969798.com +www.97.ggfang.com +www.970xxoo.com +www.97288.com.cn +www.97388.com.cn +www.97530.cn +www.977088.com +www.977788.com +www.977789.com +www.977ai.com +www.978555.com +www.978989.com +www.978jse.com +www.97980.com +www.979c.com +www.97auto.cn +www.97bobo-com.cn +www.97bobo.biz +www.97bobo.gd.cn +www.97bose.com +www.97gan.in +www.97isese.com +www.97ixxoo.com +www.97khp.com +www.97mimi.com +www.97niu.com +www.97ob.net +www.97p1mm.com +www.97piao.com +www.97qingse.com +www.97rmm.com +www.97sese100.cn +www.97sesex.info +www.97ssl.cn +www.97ttvk.com +www.97url.com +www.97wen.com +www.97wenwen.com +www.97xjsese.cn +www.97xxmm.com +www.97xxoo-97xxoo.com.cn +www.97xxoocom.co.cc +www.97xxxx.com +www.97yyy.com +www.9800ok.cn +www.98067.com +www.980wyt.com +www.981777.com +www.982999.com +www.985656.com +www.988wyt.com +www.989788.com +www.9899.cn +www.989dh.com +www.98kao.com +www.98selang.com +www.98tcw.com +www.990118.com +www.9906688.com +www.99099.info +www.991567.cn +www.991699.com +www.991kk.com +www.991mi.com +www.991mi.net +www.9934.info +www.9947.com +www.9949.cc +www.995tk.com +www.995tk.net +www.996333.com +www.996tk.com +www.997wyt.com +www.998qf.com +www.999009.com +www.999049.com +www.9991man.cn +www.99940.cn +www.999600.com +www.99966678.cn +www.999908.com +www.9999q.com +www.9999qb.com +www.999fu.cn +www.999mimi.net +www.999nxd.cn +www.99bbsgame.com +www.99cpa.com +www.99day.info +www.99du.cc +www.99kap.com +www.99ooo.com +www.99ur.cn +www.99xjw.com +www.99zw.cn +www.9aaa.com +www.9ady.com +www.9arne465.com +www.9bse.cn +www.9buu.com +www.9cmm.com +www.9eevip.cn +www.9ene456.com +www.9fangj.cn +www.9ffdd.com +www.9gan.info +www.9gghh.com +www.9ggss.com +www.9jjxx.com +www.9jwp.cn +www.9k6k.com +www.9kav.info +www.9kss.com +www.9nnnn.com +www.9phpasp.cn +www.9qqcc.com +www.9qqxx.com +www.9sba.cn +www.9sese.info +www.9smm.com +www.9ssdd.com +www.9tshop.com +www.9wxx.com +www.9xp.net +www.9zzxx.com +www.CbCdef.Cn +www.a-fish.com.tw +www.a5ak.com +www.a6633.net +www.a88b88.com +www.aa1312.cn +www.aa234.info +www.aaa444.com +www.aaaaaaaaaaaaaaaaa.cn +www.aaccssd23.cn +www.aafang.com +www.aagao.com +www.aasbea.com +www.abccef.cn +www.abcdaf.cn +www.abflt.lt +www.abg03.com +www.ablank.cn +www.accexx.in +www.acsawwn22.info +www.actualspy.com +www.ad1111.com +www.admin6.net +www.adobe-acrobat-software.org +www.adobe-flashplayer-install.com +www.adobe-reader-software.com +www.adsitelo.com +www.adtemplocentral.org +www.adult-kohaku.com +www.adult-sex-games.com +www.adult2009.cn +www.adware2010.com +www.adware2011.com +www.adwareprofesional.com +www.adwareprofessional.org +www.aeo123.cn +www.agitoscuiaba.com.br +www.ahava.lt +www.ahezi.info +www.ahsai.com +www.ahyywz.com +www.ai.8888se.com +www.ai678.com +www.aicis.it +www.aihuawd.com +www.ailiao.cc +www.ailiaotian.com +www.ailuo8.com +www.ailyes.3322.org +www.ailyes.cn +www.aimm5.com +www.aionbug.cn +www.aioncon.com +www.aiongames.com +www.aionnews.com +www.aionnsdo.com +www.aionnsdoo.com +www.aionsnd.com +www.aionsndo.cn +www.aionvip8.com +www.aionwwgg.com +www.aionyy.com +www.airenti.net +www.aisex.com +www.aiyiyeqing.com +www.aj68.com +www.ak7c.com +www.ak88888.com +www.akdnf.com +www.al1pay5.com.cn +www.al1pay9.com.cn +www.alangce.cn +www.alexqsoft.com +www.alfafoxx.com +www.alibabalpc.cn +www.almasto.net +www.am-qq.com +www.am171.cn +www.am7788.com +www.amateurmovies.in +www.amcdrrkorea.org +www.anboshi.cn +www.andy.cd +www.angantivirus-2009.com +www.angdajigou.cn +www.annil.8866.org +www.anqn.com +www.anti-virus-professional.com +www.antivirusstudioware2010.com +www.antoniolc.com +www.aoao1.com +www.aoao2.com +www.aoao3.com +www.aobux.cn +www.aomeiad.com +www.apetube.com +www.apoot.com.cn +www.app518.com +www.appdlzone.com +www.apple4-cn.net +www.applekj.cn +www.aq-anquan.com.cn +www.aqay.cn +www.aqbo.cn +www.aquan-qq.com +www.arhjfgjdrf.cn +www.artcar.com.tr +www.artsandcrafts.co.uk +www.as87a.info +www.as9999.com +www.asdfadfrr.cn +www.asdfgsdfgsdf.cn +www.asdzxc.com +www.asialinks.com +www.asjew.cn +www.aspia.cn +www.asslad.com +www.asvod.com +www.ataobao.com +www.atioqe.cn +www.attbooter.com +www.atzone.com.tw +www.au-qq.com +www.auction1-ta0oba0.cn +www.auctlva.com +www.augbbs.cn +www.automaticyaran.com +www.av-000.cn +www.av-39.com +www.av-check.org +www.av006.com +www.av020.cn +www.av112233.com +www.av140.com +www.av190.com +www.av2003.com +www.av22.us +www.av32.com +www.av361.com +www.av66.us +www.av88.us +www.avapian.com +www.avdown.com +www.avdy8.com +www.avkezhan.com +www.avne.cn +www.awrtys.com +www.axmeinv.cn +www.aysqqz.com +www.azf2.cn +www.aznylsf.cn +www.azwyt.com +www.b0888.com +www.b533.com +www.b9you.com +www.baareeq.com +www.babi2009.com +www.baby-baby-baby.cc +www.baby178.com +www.badoink.com +www.bai33.com +www.baidu-nwllas.cn +www.baidu.com.bingdu.baidu-shadu.cn +www.baidu.com.dalianhuan.cn +www.baidu.com.du.jiu7se.cn +www.baidu.com.googgle.shadu28738.jiu7se.cn +www.baidu.com.google.cn.avyou.co.cc +www.baidu.com.google.cn.sese111.co.cc +www.baidu.com.google.cn.tudou.com.baidu.comskldjfkljsidure.p2p6.com +www.baidu.com.google.jiu7se.cn +www.baidu.com.huangse.video.huazhonghua.com.cn +www.baidu.com.huangsedianying.china-brands.cn +www.baidu.com.huangsedianying.mobile-bpm.cn +www.baidu.com.huangsedianying.sdjzw.cn +www.baidu.com.huangsedianying.xingye.sx.cn +www.baidu.com.jqdy.hsdy.liangtuan.cn +www.baidu.com.movie.google.com.v.21cn.fsgsddk566585fdjhdu559594hfghjdgkdcom.tudou.com.zhong- +www.baidu.com.shadu.iufhsifnsodjhviuebfisdgufi.hbcuysgefijbni.fijehifubeifvub.jiu7se.cn +www.baidu.com.shadu.ttghjdgsdtesyt.gtuturt47kjgfs.bhbfgseiuufyftd.ukydrtsgkugiudutdcgch.yjfutdtdikhkjgkgj.j +www.baidu.com.shadu2.jiu7se.cn +www.baidu.com.shadu7.baidu-shadu.cn +www.baidu.com.wwvv.us +www.baidu.com.youku.com.qq.com.grtjgjdgjjg.kansepian.info +www.baidu.huangsedianying.china-brands.cn +www.baidu.us.wwvv.us +www.baidu1s4.com +www.baidu2ed.com +www.baidu8.org +www.baiduav.cn +www.baiduawj.com +www.baidudel.com +www.baidudfe.com +www.baiduduyou5.cn +www.baidufafafa.com +www.baidujdf.com +www.baidujk4.com +www.baidujpf.com +www.baiduksw.com +www.baidulo0.com +www.baidulop.com +www.baiduop0.com +www.baiduotr.com +www.baidupn.cn +www.baiduree.com +www.baidusw3.com +www.baiduswf.com +www.baidusxc.com +www.baidutdc.com +www.baidutdsasda.cn +www.baiduter.com +www.baidutrg.com +www.baiduw2e.com +www.baiduwda.com +www.baiduwfv.com +www.baiduxzs.com +www.baiduyte.com +www.bairr.com +www.baishiketong.com +www.baixin6.cn +www.bangbull.com +www.bankofamerica.com.srv_18392.kijjerf.vc +www.bao-2009.cn +www.baokv.cn +www.baomaaa.cn +www.barasvidahi.com +www.barbour-club.com +www.bastakigroup.com +www.batch29.com +www.bauldelsado.com +www.bayuexue.com +www.bb2211.cn +www.bb3s.cn +www.bb8769.cn +www.bbbbtvv.cn +www.bbbl5.cn +www.bbdnf.com +www.bbdyeekd.cn +www.bbylw.com +www.bdgxq.cn +www.bdjs.net +www.beauty3.cn +www.beeg.com +www.beisin88.com +www.bem1010.pagebr.com +www.benchibaoma.net +www.bencibo.cn +www.bengchiaa.cn +www.bengchibb.cn +www.bengchicc.cn +www.bengchidd.cn +www.bengchiee.cn +www.bengchiff.cn +www.bengchigg.cn +www.bengchihh.cn +www.bengchiii.cn +www.bengchijj.cn +www.bengchikk.cn +www.bengchill.cn +www.bengchimm.cn +www.bengchinn.cn +www.bengchioo.cn +www.bengchipp.cn +www.bengchiqq.cn +www.bengchirr.cn +www.bengchiss.cn +www.bengchitt.cn +www.bengchiuu.cn +www.bengchivv.cn +www.bengchiww.cn +www.bengchixx.cn +www.bengchizz.cn +www.bestcnedu.cn +www.bestspywarescanner.net +www.bestvideo.it +www.bestwaytour.com +www.bet2008.cc +www.bet866.com +www.betppp.com +www.bets365.com.cn +www.between-legs.com +www.bexley.cn +www.beyondmv.com +www.bf2e.cn +www.bflang.com +www.bg5460.cn +www.bg5566.cn +www.bg6119.cn +www.bg8028.cn +www.bgfw6.cn +www.bigfooot178.com +www.bigtopfindsite.cn +www.bigtube.com +www.bind88.com +www.binlayer.com +www.binlida.com +www.bj-qunar.com +www.bj00852.com +www.bj7744.cn +www.bj788.com +www.bj868.com +www.bjcaipiaowang.cn +www.bjcp333.com +www.bjcp5.com +www.bjcp543.com +www.bjcp8.com +www.bjcp88.com +www.bjcpw8.cn +www.bjflcaipiao.com +www.bjhh.cn +www.bjlanjingling.com +www.bjsjwmz.com +www.bjydzq.com +www.bjyzhs.com.cn +www.bjzdmx.com +www.bjzhcw.cn +www.bl1088.com +www.blackpass.com +www.blog-view.cn +www.blogg.propos.no +www.blowmeupbig.com +www.blueren.cn +www.bm357.cn +www.bnret.com +www.bo33bo.com +www.bobo.3ggss.com +www.bobo.8yyxx.com +www.bobobase.com +www.boboboke.cn +www.bobopinso.com +www.boboplay.com +www.boboyingba.cn +www.boccz.com +www.bocqy.com +www.bolezhan.cn +www.bombermix.com.br +www.bowyt.com +www.boyybo.com +www.bpdddd.cn +www.bqssf.com +www.bradenso.info +www.brans.pl +www.brazzilmag.com +www.brickcity.net +www.brickhousebetty.net +www.britney4u.8k.com +www.bs360.zik.dj +www.bsdy.org +www.bshdx.cn.im +www.bsjhc.com +www.bspop.gov.cn +www.bszyxy.cn +www.btf8.com +www.btpkwg.com +www.btupload.com +www.bubu888.com +www.budddaa234.cn +www.bufenli.com +www.bugo24.com +www.buhuang.com +www.bukeneng.com +www.buxhere.com +www.buxns.com +www.buy-hk.com +www.buzios.com.br +www.bvbmm.cn +www.bvi16.com +www.bw818.com +www.bwmxd.cn +www.byby.cc +www.byeserver.com +www.byideale.com.br +www.bzf6.com +www.bzjcx.net.cn +www.bznylsf.cn +www.c133.cn +www.c41840.com +www.c588.com +www.c8885.com +www.cBcdef.cn +www.caderm.org +www.cai08.cn +www.cai113.cn +www.cai12378.cn +www.cai158.com +www.cai385.com +www.cai508.com +www.cai800.com +www.cai886.com +www.cai99.net +www.caifu5678.cn +www.caifu5689.cn +www.caip111.cn +www.caip998.cn +www.caipiao12315.com +www.caipiao128.com +www.caipiao238.cn +www.caipiao5166.cn +www.caipiao5166.cnn +www.caipiao568.com +www.caipiao688.com +www.caipiao777.cn +www.caipiao899.com +www.caipiaoguanli.cn +www.caipiaoguanlizongju.cn +www.caipiaoyucewang.com +www.caixaseguranca.com +www.calt.com.cn +www.camporeal.edu.br +www.canclvr.com +www.cao88.com +www.caod.info +www.caoliu.com +www.caoliu.name +www.carloon.cn +www.casanaweb.com +www.catideal.com.cn +www.cbcpw.cn +www.cbg163jg.com +www.cbt8.cn +www.cccap.org.cn +www.ccctvv.com +www.ccgglm.com +www.cciv584.com +www.ccnbtv03.com +www.ccrr2233.com +www.ccswzx1.cn +www.ccswzx10.cn +www.ccswzx2.cn +www.ccswzx3.cn +www.ccswzx4.cn +www.ccswzx5.cn +www.ccswzx6.cn +www.ccswzx7.cn +www.ccswzx8.cn +www.cct327.com +www.ccttv.qc.cx +www.cctv-3658.com +www.cctv-com.cn +www.cctv-feixin.cn +www.cctv-t3.cn +www.cctv-u886.cn +www.cctv-viple.cn +www.cctv-viplx.cn +www.cctv.vipa5.cn +www.cctv0061.com +www.cctv1008.com.cn +www.cctv1563.cn +www.cctv1691.com +www.cctv177.cn +www.cctv2-1.com +www.cctv2-tv3.cn +www.cctv268.cn +www.cctv2ly09.cn +www.cctv2x61.cn +www.cctv3-05.cn +www.cctv3-09.cn +www.cctv3-oo.com +www.cctv3-t61.cn +www.cctv3.pl +www.cctv3318.com +www.cctv33s5.com +www.cctv33u.com +www.cctv347.cn +www.cctv35.net +www.cctv35cc.com +www.cctv383.com +www.cctv3e324.com +www.cctv3fqq.com +www.cctv3kb3.com +www.cctv3r.com +www.cctv3v97.com +www.cctv3vs.cn +www.cctv3wcq.com +www.cctv601.com +www.cctv6029.com +www.cctv603.cn +www.cctv61-kefu.cn +www.cctv61-kefu5.cn +www.cctv615.cn +www.cctv6608.com +www.cctv6ic.cn +www.cctv789.cn +www.cctv791.com +www.cctv8241.cn +www.cctv972.com +www.cctv982.cn +www.cctvaar.cn +www.cctvb.net +www.cctvbw.cn +www.cctvcai.com +www.cctvddx.com +www.cctvddy.com +www.cctvdt.cn +www.cctveg.cn +www.cctvko3.com +www.cctvn2.cn +www.cctvq10.com +www.cctvx.cc +www.cctvy2.cn +www.cctw.info +www.ccv1201.com +www.ccvt3c.com +www.ccwx3.com +www.ccytv3.com +www.cebbgnk.com +www.cenpak.net +www.cfanim.cn +www.cfqq1.com +www.cfqqd.com +www.cfqqm.com +www.cfqqo.com +www.cfqqqc.com +www.cfqqtt.com +www.cfwgxz.cn +www.cgplayer.com +www.ch2009mx.cn +www.chadnf.cn +www.chainway-litex.com +www.chaogu518.com +www.chaparroagricola.com +www.chatdesin.com +www.cheaprxdrugstore.net +www.cheapwang.cn +www.checkj.s.pe +www.chen4.com +www.chenglongmy.cn +www.chengrendh.com +www.chengrenliaotianshi.com +www.chengrenshipin.com +www.chengrenwang3.info +www.chengyijy.cn +www.chibitw.com +www.china2003.cn +www.chinaboji.net +www.chinacity8.cn +www.chinacotton.net +www.chinad9.cn +www.chinafucaiwang.com +www.chinamobilet.cn +www.chinaqddf.com +www.chinasongzhuang.cn +www.chinastamps.com.cn +www.chinayoudao.cn +www.chkadw.com +www.chnpe.com +www.chuangshenhua.com +www.chuanqi-bug.cn +www.chuanqi-bug.com.cn +www.chuenjielianhuanwanhui.cn +www.chugui.info +www.chunyao88.tk +www.ciline.cn +www.cince1999.com +www.cioc.ac.cn +www.citi.org.za +www.cizzp.com +www.ckios0.com +www.ckqws.info +www.classicmature.com +www.cloverat.com +www.cltsi.info +www.cn-talent.net +www.cnbattle-blizzard.com +www.cncp8.com +www.cncpgfw.com +www.cndbsm.com +www.cnebc.info +www.cnhack.cn +www.cnhztz.com +www.cnkankan.com +www.cnku1616.cn.119118.com.dnspowered.cn3.cn +www.cnnmq.com +www.cnpt.com.cn +www.cnrobot.net +www.cnscut.cn +www.cobband.com +www.cobiny.cn +www.cocoachina.com +www.com525.cn +www.comfarmz.cn +www.config73.com +www.coolck.com +www.coolergas.com +www.cp00001.cn +www.cp0005.com +www.cp003.com +www.cp007008.cn +www.cp01.com +www.cp0118.cn +www.cp02.net +www.cp0577.cn +www.cp05777.cn +www.cp0968.com +www.cp110.com +www.cp1128.cn +www.cp1155.cn +www.cp1181.cn +www.cp1222.cn +www.cp1238.com +www.cp1358.com +www.cp137.com +www.cp141.com +www.cp16666.cn +www.cp1689.com +www.cp1718.com +www.cp1838.com +www.cp196.com +www.cp1968.com +www.cp1991.cn +www.cp2003.cn +www.cp222.com +www.cp229.com +www.cp23456.com +www.cp255.com +www.cp258.com +www.cp259.com +www.cp2638.com +www.cp284.cn +www.cp285.com +www.cp28668.cn +www.cp2868.com +www.cp287.com +www.cp2878.cn +www.cp3108.cn +www.cp3112.com +www.cp3118.com +www.cp3259.cn +www.cp328.cn +www.cp33.net +www.cp33678.cn +www.cp3389.cn +www.cp34568.cn +www.cp3500.cn +www.cp3555.com +www.cp3578.cn +www.cp3668.cn +www.cp3777.com +www.cp378.com +www.cp386.com +www.cp3877.com +www.cp3885.cn +www.cp437.cn +www.cp4858.com +www.cp4868.cn +www.cp49.net +www.cp52.com +www.cp52.net +www.cp5275.com +www.cp53.com +www.cp55125.com +www.cp555.net +www.cp5559.com +www.cp5648.com +www.cp565.com +www.cp5666.com +www.cp5668.cn +www.cp5700.cn +www.cp5768.com +www.cp5858.com +www.cp6009.cn +www.cp608.com +www.cp6158.cn +www.cp6168.com +www.cp6222.com +www.cp6288.cn +www.cp639.com +www.cp648.com +www.cp658658.com +www.cp6595.cn +www.cp66123.cn +www.cp666123.co.cc +www.cp66665.cn +www.cp6677.net +www.cp67666.com +www.cp6785.com +www.cp6889.com +www.cp6k.cn +www.cp728.com +www.cp7333.com +www.cp756.cn +www.cp75998.cn +www.cp7689.cn +www.cp780.com +www.cp7870.cn +www.cp789.cn +www.cp790.cn +www.cp7900.cn +www.cp8199.cn +www.cp8258.cn +www.cp8266.com +www.cp8595.cn +www.cp8789.cn +www.cp88.cc +www.cp88128.com +www.cp8838.com +www.cp884.com +www.cp8855.cn +www.cp8868.com +www.cp8877.com +www.cp888.cc +www.cp888.net +www.cp899.net +www.cp93.cn +www.cp965.com +www.cp96888.cn +www.cp9898.cn +www.cp9955.com +www.cp9968.com +www.cp99785.cn +www.cpfc8.com +www.cplnn.com +www.cpqwyczx.com +www.cptitan.com +www.cpw001.net +www.cpw0011.cn +www.cpw008.com +www.cpw010.com +www.cpw0688.cn +www.cpw133.com +www.cpw1828.com +www.cpw285.cn +www.cpw560.com +www.cpw598.com +www.cpw6658.cn +www.cpw6677.cn +www.cpw678.cn +www.cpw6788.tk. +www.cpw777.com +www.cpw7777.cn +www.cpw788.com +www.cpw833.cn +www.cpw888.com +www.cpw90.cn +www.cpw929.cn +www.cpwcn.com +www.cpwoeo.com +www.cpycwz.com +www.cpyzw.com +www.cpz99.cn +www.cpzggfw.com +www.cpzlw.cn +www.cpzxyc.com +www.cq5566.com +www.cqgj.net +www.cqsanse.cn +www.cqwh888.com +www.cqytdb.com +www.crcr99.com +www.crjiaoyou.cn +www.crjq8.com +www.crzjcn.cn +www.cslmnet.org +www.csol2032.com +www.csol208.com +www.csol3036.com +www.csolae.com +www.csolai.com +www.csolao.com +www.csolcl.com +www.csolen.com +www.csoln.cn +www.csolre.com +www.csolrv.com +www.csolss.com +www.csolx.cn +www.css1.cn +www.ct5588.com +www.ctv3rt.com +www.cuiqingy.cn +www.custseek.com +www.cutalot.cn +www.cvbdohdrgyr.cn +www.cvbnmdgesc.cn +www.cvbsdrdxfse.cn +www.cw389.com +www.cxgst.cn +www.cxkx.gov.cn +www.cy074.cn +www.cychaye.com +www.cyhxian52.net.cn +www.cykj88.com +www.czgfy.com +www.czmtv.net +www.cznylsf.cn +www.cztvu.ah163.net +www.czxcdz.com +www.da123.cc +www.dachannels.com +www.dadxx.info +www.dahuaeducation.cn +www.dajiba.net +www.danjiyou.com +www.daodao123.info +www.daoye.nm.cn +www.dasemei.cn +www.dazhu18.cn +www.db1128.com +www.db168.tk. +www.dd1xx.com +www.dd2xx.com +www.dd3xx.com +www.dd3xx.net +www.dd4000.cn +www.dd5688.com +www.dd5xx.com +www.dd80.net +www.dd88567.cn +www.ddddxxx12.cn +www.ddddxxx13.cn +www.ddddxxx14.cn +www.ddk1.cn +www.ddk3.cn +www.ddkoo.com +www.ddosgj.cn +www.ddoszdani.cn +www.ddqun.com +www.ddroomabartcc.com +www.ddssss.com +www.ddxx123.com +www.ddzj168.com +www.deadhouse.ru +www.deal4properties.com +www.debbank.com +www.debug73.com +www.deftec.gr +www.degtn118.cn.im +www.delmadang.com +www.densmail.com +www.deoda.cn +www.depilo.hpg.com.br +www.depobank.ru +www.derquda.com +www.df008.com +www.df35.info +www.dfcgnhdcbgdser.cn +www.dfetb.cn +www.dfhg.info +www.dfhjmfgergfds.cn +www.dfrtgssf.cn +www.dfsgsdfgvsfvswe.cn +www.dfzqgf.com +www.dgbda.net +www.dgmeifeng.cn +www.dh004.com +www.dh008.com +www.dh2011yahoo-com.top.to +www.dh2288.com +www.dh234.com +www.dhfast.com +www.diandianse.cn +www.diaoyu.org +www.diariodafranca.com.br +www.diddk.com +www.dielo.com.br +www.diguo180.com +www.dimorphothec.com +www.dingdingyouhui.com +www.dinyao.com +www.dir4you.org +www.disneyphoto.com.tw +www.divinemeb.com +www.djkk1.com +www.dlsmg.cn +www.dnf-gg.cn +www.dnf01.com +www.dnf2020.com +www.dnf25.com +www.dnf27.com +www.dnf3g.com +www.dnf3pk.com +www.dnf444.com +www.dnf5.com +www.dnf518.com +www.dnf57.com +www.dnf69.com +www.dnf72.cn +www.dnf7q.info +www.dnfQQ09.com +www.dnfaaa.cn +www.dnfcd.com +www.dnfcx.com +www.dnfda.cn +www.dnfdm.cn +www.dnffa.cn +www.dnfgame09.com +www.dnfgqq.com +www.dnfguiguiwg.com +www.dnfiqq.cn +www.dnfjp.com.cn +www.dnflipin.cn +www.dnflw.com +www.dnfmh.com +www.dnfmx.com +www.dnfoo.com +www.dnfqd.com +www.dnfqj.com +www.dnfqq.net +www.dnfqq66.cn +www.dnfqqss.com +www.dnfqqy.com +www.dnfso.com +www.dnfsqq.com +www.dnfst.com +www.dnftj.cn +www.dnfui.cn +www.dnfup.cn +www.dnfuv.cn +www.dnfvip.com +www.dnfvqq.com +www.dnfvs.cn +www.dnfwanshou.com +www.dnfwe.com +www.dnfwg9.cn +www.dnfxi.com +www.dnfxqq.com +www.dnfxy.cn +www.dnfys.com +www.dnfzc.com +www.dnusax.com +www.dnxingcheng.com +www.do.eDNS.biz +www.do94.cn +www.doopx.com +www.dougade-ero.com +www.down2sun.cn +www.down988.cn +www.downloaddirect.com +www.downloadporn.com +www.downloads-123.com +www.dq86.com +www.drpcclean.com +www.ds345.cn +www.dsb66.com +www.dsftherth45.cn +www.dtw163.tk +www.duczz.com +www.dujijishu.com +www.dukeba.com +www.dunaferriskola.hu +www.duohaochi.com +www.duote.com.rentiniubi.cn +www.dvcchatt.org +www.dvdcraze.tv +www.dwfuzhu.cn +www.dwjxn.com +www.dwwt.com +www.dxbbs3.info +www.dxbbs4.com +www.dxdxdh.cn +www.dxlove.net +www.dxnight.com +www.dxsq.info +www.dxtp.org +www.dxyyy.cn +www.dy2004.com +www.dy3369.cn +www.dy581.cn +www.dy61.com +www.dyj5588.com +www.dyxp.net +www.dyzhu.net +www.dz-ly.com +www.dzfl.net +www.dzhgpw.com +www.dzhzqw.com +www.e-onlyou.cn +www.e23.la +www.e3e4.net.cn +www.e5566.cn +www.e9oo.com +www.echnet.com.cn +www.ecpss.sh.cn +www.ecpsschina.com +www.ecpsspay.com +www.ecpsspayment.com +www.ediltermo.com +www.edolnet.com +www.ee23.cn +www.ee250.cn +www.efqqq.cn +www.egqposhbad.cn +www.elang888.com +www.ems-danbao.cn +www.emxdj.com +www.entpk.com +www.envoidefichier.com +www.eoper.com +www.epbrd.info +www.eqw009.cn +www.eraidea.com +www.eresmor.com +www.eretukyig.cn +www.ergdfg.cn +www.eryfghfdc.cn +www.es86.com +www.etoro.com +www.etrtetret.cn +www.eweerwerre.cn +www.ewonda.com +www.ewvi.info +www.expireddomaingains.com +www.eyx8.com +www.eznylsf.cn +www.f007007.cn +www.f17f.cn +www.f21f2.com +www.f4nn.com +www.f5nn.com +www.f6nn.com +www.f7nn.com +www.fabu5.com +www.facai500.cn +www.faceb000king.com +www.faceb00ks.net +www.facebook.sercaag.com +www.falaliaa.cn +www.falalibb.cn +www.falalicc.cn +www.falalidd.cn +www.falaliee.cn +www.falaliff.cn +www.falaligg.cn +www.falalihh.cn +www.falaliii.cn +www.falalijj.cn +www.falalikk.cn +www.falalill.cn +www.falalimm.cn +www.falalinn.cn +www.falalioo.cn +www.falalipp.cn +www.falaliqq.cn +www.falalirr.cn +www.falaliss.cn +www.falalitt.cn +www.falaliuu.cn +www.falalivv.cn +www.falaliww.cn +www.falalixx.cn +www.falaliyy.cn +www.falalizz.cn +www.fangspde.cn +www.fangyouw.com +www.fangzhengzq.cn +www.fanv.cn +www.fapiao186.com +www.farmgirls.com +www.farmho.com +www.fast-download-base-free.com +www.fatormais.com.br +www.fc010.net +www.fc1108.cn +www.fc151.cn +www.fc238.cn +www.fc3289.cn +www.fc398.cn +www.fc3d1512.cn +www.fc3d558.com +www.fc3dcp.com +www.fc56588.cn +www.fc5688.com +www.fc5688.net +www.fc5868.cn +www.fc5898.cn +www.fc6188.cn +www.fc6558.com +www.fc661.net +www.fc6621.cn +www.fc6666.com +www.fc6745.cn +www.fc6790.cn +www.fc689.cn +www.fc755.co.cc +www.fc779.com +www.fc7821.cn +www.fc8089.cn +www.fc900.com.cn +www.fc9056.cn +www.fc95566.com +www.fc98.net +www.fc9966.cn +www.fc998.net +www.fcai128.cn +www.fccp1188.cn +www.fcgfw.com +www.fcp666.cn +www.fcp88.cn +www.fctuku.com +www.fcw838.cn +www.fd521.com +www.fdasfadf.cn +www.fdsdffdfsf.cn +www.fdvdv.cn +www.fec-edu.com +www.fei2009xin.cn +www.fei4.cn +www.feifeijh.cn +www.feikuo.com +www.feiq18.com +www.feitncn.com +www.feixin2.com +www.feixin22.cn +www.feixin23.cn +www.feixin566.cn +www.feixin591.cn +www.feixin60.cn +www.feixin688.cn +www.feixinex.cn +www.feixingcctv3.com +www.feixinhd.cn +www.feixini2009.cn +www.feixink09.cn +www.feixinky.cn +www.feixinte.com +www.feixiy.cn +www.feiyoung.com +www.feiyu68.com +www.feizhu.co.cc +www.fenghuashi.com +www.fengliutianxia.info +www.fengnimabi360.cn +www.fenhei.com +www.fenhi.com +www.fenxin-cctv.com +www.fetiod.com.cn +www.fetioe.com.cn +www.fetion-cctv.cn +www.fetion5.com.cn +www.fetionc.com +www.fetionh.com.cn +www.fetionm.com +www.fetionu.com.cn +www.fetionxi.cn +www.fetioy.com.cn +www.fetoin.ha.cn +www.ff3d.cn +www.ff989.com +www.ffmxd.cn +www.ffo2009.cn +www.ffohs.com +www.ffszk.com +www.fg998.com +www.fgetchr.cn +www.fghndrgse.cn +www.fghnjmdgrse.cn +www.fghrdfa.cn +www.fhnfff.cn +www.fieldscom.com +www.fiepe.org.br +www.file119.net +www.fjc001.com +www.fjhjhjhj.cn +www.fjmj.org.cn +www.fjzzfm.com +www.fl0018.cn +www.fl0809.cn +www.fl567.com +www.flc258.cn +www.flc8811.cn +www.flc99.cn +www.flcp1000.com +www.flcp12.com +www.flcp160.com +www.flcp258555.com +www.flcp315.com +www.flcp413.com +www.flcp5088.com +www.flcp550.com +www.flcp601.com +www.flcp668.cn +www.flcp6688.com +www.flcp6699.cn +www.flcp678.cn +www.flcp688.com +www.flcp8848.com +www.flcp907.com +www.flcpglzx.cn +www.flcpglzx.com +www.flczlw.cn +www.flczx.cn +www.floodad.com +www.florons.com.cn +www.flytube.com +www.fm5.cn +www.fmsoft.ru +www.folan.cn +www.foqffo.cn +www.formatron.com.mx +www.foxempire.com +www.foyue.com.cn +www.fqng.com +www.fqq1.cn +www.frandistribuidora01.com +www.free18.net +www.freeholiday.com.cn +www.freenew.net +www.freesexmovie69.com +www.freeteenpass.com +www.freetimedigital.com +www.friskyfarms.com +www.frt7k.com +www.frutascecas.kit.net +www.fssu.cn +www.fsus.cn +www.ftw333.com +www.fu456.com +www.fu678.com +www.fucai3dtuku.com +www.fucai5555.cn +www.fucai66.cn +www.fuckallnight.com +www.fuckyoubitch.com +www.fudanspine.com +www.fulicaipiao.com +www.fulldls.com +www.funny8.net +www.funso8.com +www.fuqikl.info +www.fuqiw.com +www.fuy88.cn +www.fxcctv-2b.cn +www.fxctz.com +www.fxok.cn +www.fxxx114.com +www.fxxzdown.cn +www.fy2h.com +www.fyazp.info +www.fyedit.cn +www.fznylsf.cn +www.fzvoggz.cn +www.g1476.cn +www.g51s.cn +www.g8g5.cn +www.gaime456.in +www.galdv.net +www.gambrellstreet.org +www.gameangel.com +www.gamecj.com +www.gamei98.com +www.gamemaill.com +www.games520.cn +www.gamezprogram.net +www.gannan.cc +www.ganyici.com +www.gaoav.com +www.gaomimi.info +www.gaone456.com +www.garne45b.org +www.gawjgz110.cn +www.gay6910.com +www.gaygg.com +www.gayjj.com +www.gcw58.cn +www.gdqtq.com +www.gdservices91.com +www.ge388.cn +www.gelgorbizi.com +www.gempop.com +www.genwjq.com +www.geocities.com +www.geshigongcang.com +www.get49.net +www.getbackupandrunning.com +www.gezihk.com +www.gfhhkip.com +www.gfzdw.cn +www.gfzq99.com +www.gg0987.cn +www.gg3572.cn +www.gg6781.cn +www.gg8765.cn +www.ggama456.com +www.ggdaohang.com +www.ggmm543.cn +www.ghfdgdf.cn +www.ghfdghgdghd.cn +www.ghjkghyftb.cn +www.ghmgfbdsfve.cn +www.giftsdo.com +www.girlooo.cn +www.gj338.com +www.gjcpycw.com +www.gjgp8.com +www.gk99.com.tw +www.glintsun.com +www.global-hotel.com.cn +www.gloi.org +www.gm-kj.cn +www.gm2468.cn +www.gmaill.com +www.gmakj.com +www.gmdzgs.cn +www.gnpsg.cn +www.go2000.cc +www.go2000.cn +www.go2000.com +www.go8abc.com +www.goc-163.tk +www.goggle.com +www.gohispanomedia.com +www.gongfusky.com +www.good0632.cn +www.good1685.cn +www.good2016.cn +www.good2056.cn +www.good2698.cn +www.good5296.cn +www.good6368.cn +www.good7389.cn +www.goodgirlsbadguys.com +www.goodhao188.com +www.goodnewsdigital.com +www.goodweblist.info +www.google76t.com +www.googleasv.com +www.googleasw.com +www.googlecai.com +www.googleccf.com +www.googleclg.com +www.googled3r.com +www.googlejhf.com +www.googlejpo.com +www.googlem7k.com +www.googlemki.com +www.googlertf.com +www.googles0f.com +www.googlesd.com +www.googlezxc.com +www.goqi.org +www.gp022.com +www.gp1168.com +www.gp12345678.com +www.gp1678.com +www.gp1728.com +www.gp1958.com +www.gp2121.com +www.gp357.com +www.gp4678.com +www.gp4868.com +www.gp510.com +www.gp5288.com +www.gp54321.com +www.gp6066.com +www.gp608.com +www.gp661.com +www.gp6611.com +www.gp6656.com +www.gp6700.com +www.gp796.com +www.gp7979.com +www.gp800800.com +www.gp8668.com +www.gp890.com +www.gp891.com +www.gpccc.net +www.gpccdd.com +www.gpdyj.com +www.gpw689.com +www.gpw858.cn +www.grgbkdsd.com +www.grodno-online.com +www.grtour.com.cn +www.gs618.com +www.gsdiwejs.org.39xn.cn +www.gshouse.com.cn +www.gsxxf-315.cn +www.gszk.net +www.gtx888.com +www.gu05.com +www.gu589.com +www.guangzhouyuqi.com +www.guaptelnet.com.br +www.gufanyao.com +www.guihuo.wo.tc +www.gulkan.net +www.guo360.co.cc +www.guojiacaip.cn +www.guojiacaipiaowang.cn +www.guojiacaipiaowang.com +www.guping123.com +www.guset.cn +www.gutter.com +www.gwnfj.info +www.gx518.com +www.gxingp.com +www.gyahjy.cn +www.gyyxzjig.com +www.gzhhy.com +www.gznylsf.cn +www.gzruxin.com +www.gzsksj.com +www.gzxguan.com +www.h101qq.cn +www.h13qq.cn +www.h3210.com +www.h337.cn +www.h8h8h8.cn +www.h952.cn +www.habajuva.net +www.haci23.com +www.hackjx.com +www.hackon-line.cn +www.hackrootkit.com +www.hackyzq.cn +www.haha888l.com +www.haha999b.com +www.haidaowan.net +www.hailunpiano.com +www.hainane.info +www.hambd.com +www.hangzhou-anmo.com +www.hao.se.97xxoo.com +www.hao1176.cn +www.hao123.com.wwvv.us +www.hao253.com +www.hao3176.cn +www.hao3832.cn +www.hao3956.cn +www.haobaobe.cn +www.haodasoft.cn +www.haoha123.com +www.haohaobo.org +www.haojianting.cn +www.haojianting88.cn +www.haojiemeng.com +www.haojilm.com +www.haoleav.com +www.haolekk.com +www.haomir.com +www.haoo.cn +www.haopda.com.cn +www.haorenti8.cn +www.haosecc1.com.cn +www.haowanbaba.cn +www.haozg.cn +www.happyeo.com +www.haraka.ne +www.hardsextube.com +www.hb600.com +www.hbhfz.com +www.hbsfhg.com +www.hbzc88.com +www.hddvd520.com +www.hdmhzx.com +www.healthbeyond2000.co.nz +www.heihaahhuo.net +www.heima.com +www.heimaking.com +www.hellh.net +www.hellokav.cn +www.helpless.tk +www.henemair.co.kr +www.heqiuyan.cn +www.hesxs.cn +www.hfbus.cn +www.hfzq559.cn +www.hg6888.com +www.hh1396.com +www.hh2266.com +www.hh5657.cn +www.hhc3.com +www.hhcun.com +www.hhdgzs.cn +www.hhmm88.com +www.hi44.com +www.hiboon.com +www.hidatabase.cn +www.highest-developments.com +www.himi.co.kr +www.hizippo.com +www.hjsdjcn.com +www.hjvip-wpj.cn +www.hk000.com +www.hk0000.com +www.hk117.com +www.hk2266.com +www.hk5066.com +www.hk558.com +www.hk60888.cn +www.hk633.com +www.hkball.net.ru +www.hkerbase.cn +www.hkjc.com.190290.cn +www.hkk.cc +www.hkvip888.com +www.hkying.cn +www.hkzj520.com +www.hlp2p.com +www.hnctcm.com.cn +www.hnksbj.com +www.hnqysf.cn +www.hoho-2.cn +www.hoho-3.cn +www.hong100.cn +www.honghaier.co.cc +www.honghuachengrenwang.com +www.hongyun99.com +www.host800.com +www.hotel-plus.ru +www.hotgome.net +www.hotlinkfiles.com +www.hotmail-live-box.com +www.hotmail_hd.com +www.houdao8.cn +www.hougong520.com +www.houseware-tf.com +www.hrb93.gov.cn +www.hryspaa.cn +www.hryspab.cn +www.hryspac.cn +www.hryspad.cn +www.hryspae.cn +www.hryspaf.cn +www.hryspag.cn +www.hryspah.cn +www.hryspai.cn +www.hryspaj.cn +www.hryspak.cn +www.hryspal.cn +www.hryspam.cn +www.hryspan.cn +www.hryspap.cn +www.hryspar.cn +www.hryspas.cn +www.hryspat.cn +www.hryspau.cn +www.hryspaw.cn +www.hryspax.cn +www.hryspay.cn +www.hryspaz.cn +www.hs-kj.com.cn +www.hshsy.cn +www.hsqyj.com.cn +www.hsxw.net +www.ht788.com +www.hthexhe.co.cc +www.htklit.com +www.htm5.co.cc +www.htm6.co.cc +www.htmlvista.com +www.htqq4.cn +www.huaihuaren.com +www.huangguanhlg.com +www.huangpian.biz +www.huangsewangzhan.net +www.huangsewangzhan1.net +www.huangsezhan.cn +www.huangsidianying.cn +www.hudieer.com +www.huichunbao.cn +www.hulucon.com +www.humanmed.org +www.hummmt.cn +www.hunanc25.com +www.huodong6.cn +www.huxiaocw.com +www.huynavpokq.cn +www.huzuhez.co.cc +www.hw14.com +www.hx799.com +www.hxiawp.com +www.hyaiwl.name +www.hynno8744.cn +www.hyqp168.com +www.hzbzkz168.com.cn +www.hzhan.com +www.hznylsf.cn +www.i-site.ph +www.i4ani.net +www.i8844.cn +www.iac55.cn +www.icbc-bj.com +www.icbc.com.cn.bj-ov.com +www.icd-fibres.com +www.ichunai.us +www.icvss.com +www.idc789.cn +www.idownsoft.com +www.idunef.cn +www.ie7.com.cn +www.iesuper.com +www.ifcil.fr +www.ifotosnet.xpg.com.br +www.igirona.com +www.igoudix.cn +www.ihogedi.cn +www.ihuqoyr.cn +www.ii1199.cn +www.iiiland.us +www.iimm8.com +www.ijaheuw.cn +www.ijakony.cn +www.ijesiam.cn +www.ijuebka.cn +www.ijuoxe.cn +www.ilovefati.org +www.ilunli.com +www.im900.com +www.img-o.com +www.indeks.edu.pl +www.infectada.net +www.informatik-lehren.de +www.instantspywareremoval.com +www.intelinet-global.com +www.ioluil.cn +www.ioobo.cn +www.ip9you.com +www.iphone-4.net +www.iphone4-ios.net +www.iphonetw.com.cn +www.ipp.co.kr +www.ipshougou.com +www.iq-qq.com +www.iroe.ru +www.is55.com +www.is999.net +www.iseway.com.cn +www.issdy.com +www.it-xyw.com +www.itemx-taobao.com.cn +www.itewm-taobao.com +www.itonghui.com +www.iuqhywiy.cn +www.iuwhdagf.cn +www.iwt.cn +www.ixxoo.info +www.iy09.cn +www.izche.com +www.j5ss.com +www.j823.com +www.jambaboo.com +www.japan.edu.ms +www.japanesegirl8.com +www.jbncxx.cn +www.jbwxw.com +www.jc5a.com +www.jd315.net +www.jd9k.cn +www.jdblade.cn +www.jdccn.com +www.jdcmmc.com +www.jdmoli.cn +www.jeh-vip.cn +www.jeutl.info +www.jgfgdd.cn +www.jggddi.cn +www.jggddn.cn +www.jggdds.cn +www.jhanfang.com +www.ji-u.cn +www.ji11.cn +www.jianpu.cn +www.jiaozuo1.cn +www.jiaxinshuma168.com +www.jiazisheying.com +www.jiba360.cn +www.jiegt.cn +www.jifacaitan.net +www.jiji.cd +www.jinbhuvish.com +www.jindouxiang.com +www.jingdianys.cn +www.jingshida.com.cn +www.jinke668.com +www.jinwanlove.cn +www.jipinla.com +www.jipinmeinv.com +www.jiqingdianying.info +www.jiqingliaotian.info +www.jiqingliaotianshi.com +www.jiqingll.com +www.jiqingmm.com.cn +www.jiqingpian.com +www.jiqingroom.cn +www.jiqingshequ.cn +www.jisome.info +www.jiuaipk.cn +www.jiuku123.com +www.jiuqubobo.com.cn +www.jiuqubobo.info +www.jiuquga.cn +www.jiuqumama.com +www.jiuquwen.net +www.jj911.com +www.jlttc.com +www.jnlt.com +www.jor9.com +www.jp1.cn +www.jpjspro.com +www.jpsdo.com +www.jpyd95013.com +www.jq3838.cn +www.jq5y.com +www.jqdy222.cn +www.jqroom.cn +www.jqspz.cn +www.jrtz.cc +www.jsjj56.com +www.jt8700.cn +www.jtse.info +www.juditrade.com +www.jump1.info +www.juxing55.com +www.jx2dbtwg.com +www.jx3wg.com +www.jxcgc.com +www.jxj100.com +www.jxjlwg.net +www.jxsj-bug.cn +www.jxsj-bug.com.cn +www.jxzxhq.com +www.jyfish.com +www.jytip.cn +www.jyxsh.com.cn +www.jzfgj.com +www.jzll-2.cn +www.jzll-3.cn +www.jzll-4.cn +www.jzll-5.cn +www.jzll-6.cn +www.jzll-7.cn +www.jzll-8.cn +www.jzll-9.cn +www.k-bmc.co.kr +www.k-fc.cn +www.k4329.com +www.k73kd83.cn +www.k767.com +www.k78k.cn +www.k96.net +www.ka29.cn +www.kadhp.org +www.kaeverak.com +www.kagemanden.com +www.kaikaiyan.com +www.kaiyve.com +www.kanaalxxx.nl +www.kanghuashipin.com +www.kanseke.com +www.kaokao-ni.net +www.kaokaoni.org +www.kaolabao.net +www.kapege.de +www.kazanovshina.ru +www.kb123.net +www.kcpoint.com +www.kdfly.cn +www.kecke.com +www.kefu368.com +www.kegod.cn +www.kekese.com +www.kele55.com +www.kelkee.com +www.kemosi.com +www.keniushadu.com +www.keppeo.com +www.kerestedjian.com +www.keyrvn.co.cc +www.keyunion.com +www.khgggdd.cn +www.khkjgkjgkjkgj.cn +www.khlyb.cn +www.killman.net +www.kills-people.com +www.kinkyceleb.com +www.kiraabc.com +www.kk4000.cn +www.kk48.com +www.kk5799.com +www.kk66.info +www.kk6677.com +www.kkaoni.com +www.kkbyl.com +www.kkgame.cn +www.kkk666.com +www.kkkerw.com +www.kkmm8.com +www.kknew.com.cn +www.klpic.com +www.kmeimei.com +www.kmm58.com +www.knulnu.cn +www.ko118.cn +www.kolinhopewaqs.com +www.kookmin.or.kr +www.korfd.ru +www.kortech.cn +www.kssedu.com +www.ktx7.com +www.ku255.com +www.ku256.com +www.ku4000.cn +www.kuaiboav.com +www.kuaiboba.com +www.kuaileixiaoz.cn +www.kuailetianya88.cn +www.kuku530.com +www.l4jsll.cn +www.l63.hk.cn +www.l63.ln.cn +www.ladcw.com +www.ladyfzl.com +www.laikaha.cn +www.lailaib.com +www.lamebring.com +www.landmarklondon.mobi +www.lang34.com +www.langameclan.com +www.langke.xxl.st +www.langqun1.com +www.laoding.net +www.laohtc.lefora.com +www.laoquanwater.com +www.laosilaisi.net +www.lazys.ca +www.leadpod.net +www.leawo.cn +www.lele444.com +www.lelerenti.com +www.lesbo6.com +www.lf288.cn +www.lg899.cn +www.lh448.cn +www.lh6878.com +www.lhc.gs +www.lhc3.com +www.lhc520.com +www.lhnjjr.cn +www.lhzqgs.cn +www.li-520.cn +www.liaoliaoxing.com +www.liaooo.com +www.lifepop.com +www.liguoflower.com +www.lihegp.com +www.likevid.com +www.likez.cn +www.lineageev.com +www.lingluanqi.cn +www.liningzx.com +www.link-run.com +www.link76.cn +www.link78.cn +www.lioncl.com +www.listentoworld.com.cn +www.litree.com +www.liugirl.cn +www.liyi99.com +www.liyongcctv.com +www.lizuonan.com +www.lj4sll.cn +www.ljsl4l.cn +www.ljsll4.cn +www.lkjdlfior.cn +www.ll0011.cn +www.ll80.com +www.llanolacsa.com +www.lm125.cn +www.lmok123.com +www.lnyy.com.cn +www.loginllve.com +www.lonelywifehookup.com +www.look1314.cn +www.louyue.com +www.love2068.cn +www.love6068.cn +www.loveliao.info +www.lover98.net +www.lqhehf.cn +www.lrpvc.info +www.lsrc.cn +www.lstj.gov.cn +www.luceng.com +www.lucheng.us +www.luckffxi.com +www.lulu558.com +www.lunliyy.cn +www.luoliao.name +www.luoliao520.cn +www.luoliao999.cn +www.luoliaoluoliao.cn +www.luoliaomeinv.cn +www.luoliaow.com +www.luoliaoz.com +www.luort.com +www.luotiliaotianshi.com +www.luye-pharm-wh.com +www.lvsexiazai.com +www.lwstats.com +www.lz136432911.com +www.lz1520.cn +www.lzlpk.com +www.m-qq.com +www.m17mm.cn +www.m1n2.cn +www.m2121.cn +www.m6mm.info +www.m7m8.com +www.m7n8.com +www.maihaoqq.com +www.mailh2011.info +www.maluca01.kit.net +www.maluca02.kit.net +www.maluca03.kit.net +www.mama00.cn +www.mama01.cn +www.mamasanta.com +www.mandodns.com +www.maopian.cc +www.maopian.in +www.maotuzi.cn +www.marco-mty.com.mx +www.marrento.com +www.massz.cn +www.masterbationlounge.com +www.masterwanker.com +www.maxsex.mobi +www.maya777.com +www.maybao888.com +www.mb171.cn +www.mccarron.com +www.mchongsheng.cn +www.meeons.cn +www.megac1jck.com +www.meifuwang.org +www.meijite.com +www.meimei21.com +www.meimei860.cn +www.meimeiliaot.com +www.meinvfans.com +www.meinvluoliao.cn +www.meinvml.cn +www.meisetu.com +www.meiwoku.com +www.meme.hi.cn +www.memebbs.info +www.mengqinie.com.cn +www.menoss.cn +www.meonns.cn +www.meonss.cn +www.mg-bz.cn +www.mggyu.info +www.mh48.com +www.mhzxwg2009.cn +www.mhzxz.com +www.mianhuatanghg.com.cn +www.micirugiaencolombia.com +www.micro-chip.ru +www.microscoop.net +www.microsoft.com.v6.js.update.menyaju.cn +www.microsoft2010.com +www.midi-cn.3322.org +www.midiabrasil3d.com.br +www.miga-golf.com +www.miisex.com +www.milehighhomefinder.com +www.milfx.com +www.mimiadd.info +www.mimivip.com +www.minfly.com +www.mingchesf.cn +www.mir2.sdoma.cn +www.mir2home.com.cn +www.mir2sdo.biz +www.mirh2.com +www.mirs.sh.cn +www.mirs4.com +www.mirwow.com +www.mirxc.com +www.mise5.com +www.miss1096.cn +www.miss2225.cn +www.miss5082.cn +www.miss5520.cn +www.miss6208.cn +www.miss8621.cn +www.miss8862.cn +www.miteksns.co.rs +www.mk55.cn +www.mkftft.cn +www.mm-go.cn +www.mm135.com +www.mm16.net +www.mm80.info +www.mm92se.com +www.mm9860.cn +www.mm9w.cn +www.mmc2009.com +www.mmeiwo.com +www.mmhouse.me +www.mmok88.cn +www.mmpao.com +www.mmpp123.com +www.mmpp147.com +www.mmpp258.com +www.mmpp321.com +www.mmpp456.com +www.mmpp654.com +www.mmv88.info +www.mmxxmmm.cn +www.mneeos.cn +www.mo171.cn +www.mobile-bpm.cn +www.moenos.cn +www.moeoes.cn +www.moloky.com +www.moltbedesigns.com +www.monalisa.com.cn +www.moneymoney888.com +www.moshoujinglingchaijan.cn +www.mote55.com +www.moto8.cn +www.moumom.cn +www.moviegator.com +www.moyusifu.org +www.mqianming.cn +www.mrbsd.org +www.mrmf.cn +www.mrpee.net +www.msncleaner.co.cc +www.msnhk.cn +www.msnkit.com +www.msnshe11.cn +www.msrre.com +www.mtgextranet.com +www.mtvye.com +www.mtxa.net +www.musicmoa.net +www.mv190.com +www.mv700.com +www.mxd-sdo.cn +www.mxd78.cn +www.mxdlj.com +www.my-correios.com +www.my-web-pills.com +www.my111.inf +www.my12593.cn +www.mygoshop.com +www.mykeylogger.com +www.mymir1.com +www.mymisdo.com +www.myr9.com +www.myroitracking.com +www.mysamsungapps.net +www.mysnda.com +www.mytaose.com +www.mytubebr.com +www.mywhitecoat.com +www.mz708.com +www.mznylsf.cn +www.n4no014.cn +www.n688.cn +www.naked-big-boobs.com +www.nanabuy.com +www.nancaibook.com +www.naoweisuo.cn +www.naturewater.cn +www.nb121.cn +www.nba0809.com +www.nba788.com +www.nbbb8.cn +www.nbcxbz168.cn +www.nbodin.cn +www.nbqqqq.cn +www.neenos.cn +www.neilshirley.com +www.nek-vb.net +www.nengbang.cn +www.nengmm.cn +www.nenoos.com +www.neonpx.cn +www.nerashti.net +www.netej.com +www.neverland.com.pl +www.new-mrcash.net +www.newaw.net +www.neweed.org +www.newforum.co.kr +www.newfree-tech.com +www.newhtm.com +www.newpartyworld.com +www.news-serasa.org +www.newsexvids.com +www.newsreach.cn +www.nexcomexpo.com +www.nhweilin.com.cn +www.niaila.com +www.niggals.com +www.niudoudou.com +www.niuniu3.cn +www.niuniujd.org.cn +www.niuxuzu.cn +www.niwyt.com +www.niwyt1.com +www.niwyt2.com +www.niyaobuyao.cn +www.njjkl.cn +www.njpfw.com +www.nmgsk.com +www.nnd323.cn +www.nnjd.com +www.nnjidi.com +www.nnnndddaa.cn +www.nnradio.cn +www.nnxyhotel.com +www.nnyp.net.cn +www.no216.com +www.nonoes.cn +www.nonoss.cn +www.nopao.com +www.nosenn.cn +www.noseon.cn +www.nosesn.cn +www.nosnnn.cn +www.nosnsn.cn +www.nosoen.cn +www.nososn.cn +www.nossnn.cn +www.nosssn.cn +www.nvshiyouxian.cn +www.nxmtv.info +www.ny1988.com +www.nyrs.info +www.nyzfyey.com +www.nznylsf.cn +www.o2vip.cn +www.o5op015.cn +www.ocudyv.tawkocaf.cn +www.oezf.cn +www.ofdgdfgdfges.com.br +www.office-2010.net.cn +www.ohsn.org +www.oilland.net +www.ok131.com +www.ok135.cn +www.ok8uuer5.cn +www.okda8.cn +www.okireng.com +www.okok3dw.cn +www.okokss.com +www.om163mo.c.la +www.om7890.com +www.om999.com +www.omeyasweb.com +www.on65.cn +www.on86.com +www.onlinedown98.cn +www.ons5.com +www.ons55.cn +www.onsec.net.cn +www.onsese.com +www.oomeinv.cn +www.oorrh.info +www.oqq1.cn +www.oracamminiamoeretti.com +www.ottogi.co.kr +www.ou1e360.com +www.ouaoe.cn +www.ouaom.cn +www.oueas.cn +www.oueaz.cn +www.oule365.me +www.ouqq.cn +www.ournature.net +www.ourxin.com +www.ovle365.net +www.owdmi.info +www.oznylsf.cn +www.p2p6.com +www.p8p8p8.com +www.pacificenglish.cn +www.pagesinventory.com +www.pakkw.com +www.palacemoon.com +www.palsuelo.com +www.panties3.com +www.pao44.com +www.paokars.cn +www.paokw.cn +www.paonk.cn +www.papbofeb.cn +www.pas-163.com +www.patpatball.com +www.patrickcadona.com +www.pbcplanningcongress.org +www.pcca4.cn +www.pcdown.cc +www.pcmfw.com +www.pconguard.com +www.pcpeixun.cn +www.pcsecuretools.com +www.pctv3.com +www.pcwinrar.com +www.pczx.net +www.pdaxyz.com +www.pereca2009.com +www.perkins-westrac.com +www.peruvianfood.com +www.petdoso.com +www.petrohr.com +www.pglaz.info +www.pgpc.org.cn +www.phgczx.cn +www.photics.cn +www.photoman.net.cn +www.pilt24.pri.ee +www.ping600.info +www.pink-dragon.net +www.pinksologirls.com +www.pinsef.cn +www.piypay.cn +www.pj1188.com +www.pkupe.com +www.platinumchina.com +www.playgay.cn +www.playsomedota.com +www.playsushi.com +www.plmmtp.com +www.pm789.info +www.pnnnn.com.cn +www.poderseducao.com.br +www.pokergame.90op.com +www.poloi999.cn +www.popej.cn +www.popezz.cn +www.popkarrt.cn +www.popkart88.cn +www.popkgt.com +www.pornourl.tv +www.pornvideotv.net +www.postcards.org.oeqweah.cn +www.pot9.cn +www.powow.com +www.pp10.info +www.pp1234.cn +www.pp2030.cn +www.pp312321.info +www.pp5888.cn +www.pp6789.com +www.ppddd.com.cn +www.ppebdwer.cn +www.ppfff.com.cn +www.ppggg.com.cn +www.ppp456.com +www.ppppg.com.cn +www.pppph.com.cn +www.ppppj.com.cn +www.ppuupp.cn +www.ppyycs.com +www.pqmxd.cn +www.presentes.com.cn +www.procto.cn +www.ps08.info +www.ps8.com.br +www.psf163.tk +www.psycho.net.cn +www.ptttt.com.cn +www.pu.org.cn +www.pupiledu.com +www.pushmold.com +www.pybao.net +www.pyjgf.com +www.pzyou.us +www.q11411.cn +www.q2009q.com +www.q2010.us +www.q531.com +www.q5688.cn +www.q766.com +www.q7788.com +www.q9sx.cn +www.qbzlzl.cn +www.qchat.org +www.qclangroup.com +www.qdffg.cn +www.qdvideo.com +www.qeshowmm.cn +www.qew16.us +www.qh658.com +www.qhf9.cn +www.qia13.in +www.qiaiuja.com +www.qian888.cn +www.qichee.com +www.qin58.cn +www.qingdaosenhui.com +www.qingsebb.com +www.qingsemm.com +www.qiqijs.com +www.qiselink.cn +www.qisex.info +www.qiu7.cn +www.qixi55.com +www.qiyi5p.com +www.qjvod.3322.org +www.qk102.com +www.qkrt.cn +www.qlshyyjt.com +www.qmdnf.cn +www.qmsss.cn +www.qnq61.cn +www.qo4.net +www.qovd.info +www.qpbay.com +www.qpppp.com.cn +www.qq-09vip.com +www.qq-1169.cn +www.qq-1778.cn +www.qq-2009tx.com +www.qq-2009vp.cn +www.qq-216.cn +www.qq-5516.cn +www.qq-a2009.cn +www.qq-anquan.com +www.qq-anqun.com.cn +www.qq-chong.com +www.qq-l.com +www.qq-tt09.cn +www.qq-vip55.cn +www.qq-vj9.cn +www.qq-x123.cn +www.qq-x666.cn +www.qq.com.aaadmin5.com +www.qq.com.acsue.info +www.qq.com.cctv39.info +www.qq.com.csole.com +www.qq.com.euoa.info +www.qq.com.fu8510.com +www.qq.com.holzz.info +www.qq.com.indxed.cn +www.qq.com.iooe.info +www.qq.com.j8uj.cn +www.qq.com.kau9.cn +www.qq.com.liiw.info +www.qq.com.lioh.info +www.qq.com.nbv5.info +www.qq.com.oddu.info +www.qq.com.oiue.info +www.qq.com.qq2009m.cn +www.qq.com.qqlgs.org +www.qq.com.qqlms.cn +www.qq.com.qqu2009.cn +www.qq.com.uiol.info +www.qq.com.vip.pojff.info +www.qq.com.vip.tytt66.net +www.qq.com.yoirr.info +www.qq.ok673.cn +www.qq.qpacg.com +www.qq08d74.cn +www.qq0y.cn +www.qq10000.cc +www.qq10000a.com +www.qq10000w.com +www.qq10000ww.com +www.qq10003.com +www.qq10nian.com +www.qq10txx.com +www.qq12358.cn +www.qq163vip.cn +www.qq1918.cn +www.qq200909.com.cn +www.qq2009et.com +www.qq2009gp.cn +www.qq2009hh.cn +www.qq2009mm.cn +www.qq2009ts.cn +www.qq2009tx99.cn +www.qq2009vip.net.cn +www.qq2009yx.com +www.qq2010qq.cn +www.qq2011txa.com +www.qq2629.com +www.qq29.cn +www.qq2xxd.org +www.qq35x.cn +www.qq3726.cn +www.qq501a.cn +www.qq518d.cn +www.qq518u.cn +www.qq51x.cn +www.qq548.com +www.qq54k.cn +www.qq5557.cn +www.qq56.os.io +www.qq5658.com +www.qq6.ac.cn +www.qq61a.cn +www.qq62k.cn +www.qq63x.cn +www.qq652.info +www.qq65w.cn +www.qq65x.cn +www.qq6686.cn +www.qq66w.cn +www.qq689.com +www.qq690.com +www.qq6988.com +www.qq7579.cn +www.qq81234.cn +www.qq8583.cn +www.qq8586.cn +www.qq8622.cn +www.qq86666.cn +www.qq8868.com +www.qq888.us +www.qq88k.cn +www.qq88vv.cn +www.qq8d8.cn +www.qq8you.cn.im +www.qq9y.cn +www.qqa51.com +www.qqa520.cn +www.qqab8.cn +www.qqad2009.cn +www.qqaese.cn +www.qqaoc.com +www.qqaon.com +www.qqaou.com +www.qqaov.com +www.qqasv.com +www.qqaup.com +www.qqazxc.cn +www.qqbbbb.cn +www.qqbnpd.cn +www.qqbov.cn +www.qqc51.cn +www.qqcc99.cn +www.qqccxc.cn +www.qqcej.cn +www.qqcfq.cn +www.qqchaj.cn +www.qqcjidc.cn +www.qqcmts.cn +www.qqcoa.com +www.qqcomk.cn +www.qqcs2009.cn +www.qqcv2009.cn +www.qqcvip.com.cn +www.qqcxz.com +www.qqdmku.cn +www.qqdnfqq.com +www.qqeetu.cn +www.qqekq.cn +www.qqen10000.in +www.qqenet.com +www.qqeype.cn +www.qqfarmw.cn +www.qqfc.cz.cc +www.qqfc8.cn +www.qqfmh.com +www.qqfrt.cn +www.qqfrw.cn +www.qqgamepet.com +www.qqh2009.com +www.qqhd69.cn +www.qqhqf.cn +www.qqhsv.cn +www.qqhuii.cn +www.qqhyt.cn +www.qqhz2009.cn +www.qqi199.cn +www.qqi97.cn +www.qqih8.com +www.qqihkn.cn +www.qqitf.cn +www.qqitq.cn +www.qqjhn.cn +www.qqjiang.com +www.qqk2009.com +www.qqkggf.cn +www.qqkhth.cn +www.qqkk009.cn +www.qqkkkq.cn +www.qqkongjiankelong.com.cn +www.qqkpz.com +www.qqkskr.cn +www.qqksy.com +www.qqlhc.com +www.qqlmr.cn +www.qqluck2009.cn +www.qqm.name +www.qqo68.cn +www.qqokgy.com +www.qqokq.com +www.qqoksu.com +www.qqomc.cn +www.qqootv.cn +www.qqoov.com +www.qqpcj.cn +www.qqpiy.com +www.qqq176.cn +www.qqqcf.com +www.qqqpp.com +www.qqqq.org.cn +www.qqqq2009.com +www.qqqqkkkss.cn +www.qqrgb.cn +www.qqs8.ws +www.qqsevice.com.cn +www.qqsg.ok.to +www.qqsiaz.com +www.qqsp09.cn +www.qqsvm.cn +www.qqszn10000.com +www.qqtegong.com +www.qqtp2009.cn +www.qqtrrt.com.cn +www.qqttt8.cn +www.qqttx.com +www.qqtwwt.cn +www.qqtx-10.com +www.qqtxk.com +www.qqtxvip9.com +www.qquak.com +www.qqupm.cn +www.qquude.cn +www.qquuu8.cn +www.qquxv2.cn +www.qqv0088.com.cn +www.qqv32.cn +www.qqv88.com +www.qqvdnf.cn +www.qqvip-09.com +www.qqvip.org +www.qqvip009.com +www.qqvip09.com +www.qqvip168.com +www.qqvip16888.com +www.qqvip2.cn +www.qqvip26.cn +www.qqvip315.com +www.qqvip510.com +www.qqvip520.com +www.qqvip668.com +www.qqvip678.cn +www.qqvip8.com +www.qqvip911.com +www.qqviphls.cn +www.qqvipqqcom.cn +www.qqvong.cn +www.qqvotel.cn +www.qqvqz.cn +www.qqwais.com +www.qqwbaokaw.com +www.qqwg.tk +www.qqwp2009.cn +www.qqwt2009.cn +www.qqwvy.cn +www.qqxdnf.cn +www.qqxnm.cn +www.qqxs6.cn +www.qqxtup.cn +www.qqxuy.cn +www.qqxuyy.cn +www.qqxxwaigua.cn +www.qqywf.com +www.qqz15.cn +www.qqzaj.com +www.qqzock.cn +www.qraashxi.com +www.qsqwyt.net +www.qt0955.cn +www.qt6878.cn +www.qtdyf.cn +www.qtq178.cn +www.qtq61.cn +www.qtxw48.cn +www.qu1q.cn +www.quchagg.cn +www.quimica.com.br +www.qv0d996.cn +www.qvod1.info +www.qvod22.cn +www.qvod26.cn +www.qvod69.cn +www.qvod83.cn +www.qvod998.cn +www.qvoddianying.com +www.qvodman.cn +www.qvodmuise.cn +www.qvodonline.cn +www.qvodpian.cn +www.qvodplus01.cn +www.qvodplus04.cn +www.qvodsetup.cn +www.qw2009k.cn +www.qx5k.cn +www.qxqy88.com +www.qxzpc.cn +www.qymmg.cn +www.qyyjly.com +www.qzdachang.cn +www.qznylsf.cn +www.qzone6.com +www.qzswt.cn +www.r00tx.org +www.r2-bug.cn +www.r220.cn +www.r5p9.cn +www.ra898.com +www.radio-80.com +www.raenm.nl +www.railshow.cn +www.rapidantivirus09.com +www.ray365.com +www.rbav.net +www.rbrtys.com +www.real5460666.com +www.redzaclechner.at +www.renbenfengliu.com +www.renbense.com +www.reportes201.com +www.retaobao.com +www.rfgrgd.cn +www.rhgfee.cn +www.rhinexpo.com +www.ribenchengren.com +www.richfs.com +www.richiekotzenbrasil.com +www.rising2009.org.cn +www.risinima.com +www.rl-sh.com.cn +www.rmb521.id666.com +www.rmk-lgs.com +www.rnalcase.com +www.ro7ay.org +www.roadandtrack.net.au +www.rootgou.cn +www.rootqq.cn +www.rqq1.cn +www.rqq888.cn +www.rqqke.com +www.rrgrthh.cn +www.rrrkkk.com +www.rt163.info +www.rthao123.com +www.rtmmd.cn +www.rtyscn.com +www.rtyshu.com +www.ruixing2008.cn +www.ruixingshadu.co.cc +www.runescapesr.com +www.rushometeems.com +www.rxgsslla.cn +www.rxgssllb.cn +www.rxgssllc.cn +www.rxgsslld.cn +www.rxgsslle.cn +www.rxgssllf.cn +www.rxgssllg.cn +www.rxgssllh.cn +www.rxgsslli.cn +www.rxgssllj.cn +www.rxgsslll.Cn +www.rxgssllm.cn +www.rxgsslln.cn +www.rxgssllo.cn +www.rxgssllp.cn +www.rxgssllq.cn +www.rxgssllr.cn +www.rxgsslls.cn +www.rxgssllt.cn +www.rxgssllu.cn +www.rxgssllv.cn +www.rxgssllw.cn +www.rxgssllx.cn +www.rxgsslly.cn +www.rxgssllz.cn +www.rxjh-bug.cn +www.rxsdrj.com +www.rxzhifu.cn +www.ry11108.cn +www.ry222.org +www.rz168.com +www.s058.com +www.s2kill.com +www.s4lllj.cn +www.s626s.net +www.saerbili.cn +www.salveme.net +www.sanmartinianovdr.org.ar +www.sans.cn +www.sanyamarry.com +www.sao69.com +www.sao86.com +www.sao96.com +www.sapag.com.cn +www.saryg.cn +www.sasezdfg.cn +www.sat-china.com +www.sb0028.cn +www.sb0213.cn +www.sb2190.cn +www.sb3452.cn +www.sb3589.cn +www.sb6234.cn +www.sb7896.cn +www.sb8456.cn +www.sb8632.cn +www.sb8778.cn +www.sb9835.cn +www.sc7w.cn +www.scaizq.cn +www.schoder.at +www.scldh.com +www.scope23.info +www.scoralicks.com.br +www.scql028.cn +www.scw666.com +www.scw678.cn +www.sd78.info +www.sdaohang.info +www.sddz78.cn +www.sdfdfsdfdfdf.cn +www.sdfsdfzxcvdfse.cn +www.sdhdfhtyf.cn +www.sdjnha.com +www.sdo.ms +www.sdo.tc +www.sdo17173.cn +www.sdobuy.com +www.sdomxd.cn +www.sdoovip.com +www.sdthdrhedrew.cn +www.sdyy.info +www.se-wang.cn +www.se.1ddkk.com +www.se.2ggss.com +www.se.7gghh.com +www.se11.info +www.se11se.net +www.se12se.com +www.se13se.com +www.se14se.net +www.se17mm.com +www.se18mm.com +www.se321.com +www.se54se.com +www.se77.info +www.seanmcdermotts.co.uk +www.sebaidu.com +www.sebmany.com +www.sebobo.info +www.securitydot.net +www.securitytestinternetguide.com +www.seemimi.net +www.seexgle.tv +www.seibb.com +www.sejia.info +www.sejie.com +www.seku8.com +www.selang05.cn +www.selang777.com +www.selang8.info +www.selang888.com +www.selaoda.cn +www.selaoda.us +www.semm66.cn +www.sentinelz.net +www.seoees.cn +www.seones.cn +www.seonos.cn +www.seoppp.com +www.seqingbobo.com +www.seqingwang.net +www.seqingwangzhan.org +www.sese100.com.cn +www.sese119.com.cn +www.sese33.info +www.sesebx.cn +www.sesej8.cn +www.sesejkw.cn +www.sesejqw.cn +www.sesemao.net +www.sesemi.cn +www.sesesemml.cn +www.seset.com +www.setao.info +www.setu119.cn +www.sex-123.cn +www.sex52sex.com +www.sexbo66.com +www.sexfortv.com +www.sexgamefun.com +www.sexho.com +www.sexkanagcom.cn +www.sexonlineaovivo.com.br +www.sexurl.biz +www.sexwolf.org +www.sexxse.com +www.seyou.co.cc +www.sezhongse8.net +www.sezse.info +www.sfc008.com +www.sfjianshe.cn +www.sfnnn.com +www.sfooooo.cn +www.sftcp.cn +www.sg2028.cn +www.sg2321.cn +www.sg2678.cn +www.sg4s.cn +www.sgcqwm.com +www.sgtjj.gov.cn +www.sh-jiexing.com +www.sh-tz.com +www.sh588.com +www.shagua.cn +www.shaimokale.com +www.shandaren.com +www.shangav.com +www.shangcheng.com +www.shanhuopu.com +www.shanpao.com +www.she48.com +www.she58.com +www.shenguichuanqi-waigua.cn +www.shhdyb.cn +www.shipin39.cn +www.shiping8.info +www.shjj88.com.cn +www.shmhxy.cn +www.shopccc.net +www.shoptvandmore.com +www.shoujiqianming.com +www.shqianwang.cn +www.shsh3.cn +www.shsmg.com.cn +www.shu1.com +www.shuazuanji.com +www.shufa.net.cn +www.shuma1997.com +www.shuwo.info +www.shwggs.cn +www.sibrtyue.cn +www.siiml.cn +www.siisc.cn +www.siiso.cn +www.siisw.cn +www.sikis19.net +www.sina-utg.cn +www.sina.com.cn-v-dianying-mianfeijiqing.sina-cn.com.cn +www.sina5io.com +www.sinaj29.com +www.sinap4k.com +www.sinasj9.com +www.sinaxnq.com +www.sinditec.com.br +www.sinocare.com.cn +www.sinoware.com.cn +www.siwamm.net.cn +www.six49.com +www.six555.com +www.sj899.cn +www.sjjt777.cn +www.sk50.net +www.sksk.us +www.skyc3.cn +www.skydh.com.cn +www.skywebsv.com +www.skyxo.cn +www.sl4llj.cn +www.sll1209.cn +www.sll2468.cn +www.sll4362.cn +www.sll4lj.cn +www.sll6890.cn +www.sll7822.cn +www.sll8625.cn +www.sll9012.cn +www.sll9026.cn +www.sll9621.cn +www.sll9860.cn +www.slll4j.cn +www.slllj4.cn +www.slwyt.com +www.slyvideos.com +www.smadav.net +www.smashingapps.com +www.smdian.cn +www.smmmo.cn +www.smsyzx.org +www.smtsd.com +www.smx.nu +www.sndacn.cn +www.so11.cn +www.soasnovas-radioplay.com +www.soasnovas.com +www.soccer9you.com +www.socks5service.cn +www.softgx.com +www.sogouliulanqi.com +www.sohbetsensin.com +www.sohu.com.blog.seqing.mobile-bpm.cn +www.sohu.com.blog.seqing.sdjzw.cn +www.sohu12333333.com +www.sohucrt.com +www.sohukio.com +www.sohusw4.com +www.sonyu9u8.cn +www.soongin.org +www.sosonv.com +www.sounet-vip.com +www.sourmath.on.nimp.org +www.sp666666.com +www.sp99123.cn +www.spaecsina.com.cn +www.spafeixin.cn +www.spearfishrealty.com +www.spjiaoyou.com +www.splendid-ol.cn +www.spliaotian.com +www.splts.com +www.sportsbay.cn +www.sporttoday.cn +www.spsonica.com +www.spydajaba.com +www.spyware-fighter.com +www.sq5yt.info +www.sqq1.cn +www.sqwuyt.com +www.sqwyl.com +www.sres-whu-edu.cn +www.srs.com.cn +www.ss209.com +www.ss52ss.com +www.ss52ss.net +www.ss53ss.com +www.ssdyw.com +www.sseae.com +www.ssee88.com +www.ssh1688.com +www.sshsex.info +www.sslepay.com +www.ssq001.com +www.ssq007.com +www.ssq010.cn +www.ssq585.com +www.ssq868.cn +www.ssq886.com +www.ssq999.cn +www.sssseeee.com +www.starfutures.com.cn +www.starmobel.ro +www.startor.cn +www.statelinefastpitch.com +www.stbyzq.com +www.stbzq.com +www.stourismbangladesh.com +www.superdns.in +www.superobamaonline.com +www.suppadw.com +www.sxac.com +www.sxgxjy.com +www.sxky.com +www.sxtz.com +www.sy1816.com +www.sy3333333.com +www.syk6.com +www.sysetv.com +www.system-files.cn +www.systemalkh.com.br +www.sz-keli.cn +www.sz968.com +www.szbzkzgs.com +www.szhc555.com +www.szhi0121.com +www.szhwlgz110.cn +www.szjyjg.com.cn +www.szlay.com +www.sznylsf.cn +www.szsjhb.com +www.szyjzj.cn +www.t-softtemplates.com +www.t00ls.org +www.t1195.cn +www.t7hhhh.cn +www.t7t7.net +www.t888666.com +www.taabao.in +www.tab3w.cn +www.talkio.com +www.tangshan.gov.cn +www.tans6.cn +www.tanwinjiwr.cn +www.tao368.com +www.taobao359009580.com +www.taobaoa.us +www.taobaobed.cn +www.taobaodanbao.cn +www.taobaodvk.cn +www.taobaoonet.cn +www.taobaoos.com +www.taobaoot.com +www.taobaozy.com +www.taocao.com +www.taosebb.com +www.taotaob.com +www.taozhi.cc +www.taozuoxuan.com +www.tatarstan.ws +www.tax-qq.com +www.tb-vip.net.cn +www.tb0102-vip.cn +www.tbaae.cn +www.tbksw.com +www.tc2000.com.ar +www.tc669.com +www.techlistings.net +www.teendre.com +www.teipay.cn +www.tencenl.in +www.tencentc.tk +www.tengxun-2009qq.cn +www.tengxun4g2010.com +www.tepgrp.com +www.terea.net +www.tevnet.org +www.tex188.cn +www.th16388.com +www.thedefend.com +www.thestop.com.cn +www.tiancheng365.cn +www.tiandigp.com +www.tianfuhuoguo.com +www.tianheby.com +www.tiankongse.tk +www.tianqiyubao.net +www.tianyangdq.cn +www.tiavastube.com +www.ticai678.com +www.ticket365.co.kr +www.timeforfuck.com +www.ting163.com +www.tingting2.com +www.tingtingjidi.com +www.tiomrcash.net +www.tipoint.co.kr +www.tiu3.com +www.tivalley.cn +www.tiysoft.com +www.tk003.com +www.tk49.com +www.tk88888888.cn +www.tlshs.com +www.tlwg.cn +www.tlwg5.cn +www.tm05.com +www.tm3721.net +www.tm7749.com +www.tmaoint.com +www.tmlm.net +www.tomaer.com +www.tongrentanghk.com +www.tongruicn.com +www.tongxue.com +www.tonhaobilolao.com +www.toomore.cn +www.topadult10.com +www.totalaccessporn.com +www.toushi360.com +www.towwg.com +www.tq-88.cn +www.trdftygo.com +www.trendmicor.com.cn +www.trenublo.com +www.tribunarecife.com.br +www.trizz.cn +www.troi.gen.in +www.ts787.com +www.tse99.info +www.tsinghua-lx.org +www.tskscn.com +www.tsts168.com +www.tt-shenqi.com +www.tt9898.com +www.ttt258.com +www.ttxhh.net +www.ttzhibo.net +www.tu10000.net +www.tu456.com +www.tu5077.com +www.tu58123.com +www.tube1820.com +www.tubeblasterpro.com +www.tubnaqid.cn +www.tudoesportes.com.br +www.tudou868.cn +www.tujttt.cn +www.tuku99.cn/gov +www.tukuba.cn +www.tul.com.cn +www.turbochargedsoul.com +www.turkeyinworld.ru +www.turkiyegb.com +www.turksex.co +www.turthf.cn +www.tv-qq.com +www.tv190.com +www.tv5168.com +www.tvbys.com +www.tw066.com +www.tw789.com +www.tw7890.com +www.twin-2009.com +www.twqvod.com +www.tx-qq.com +www.tx138.com +www.txfdqq.cn +www.txhtjy.com +www.txqq-009.cn +www.txqq100000-vip.cn +www.txqq2009vipx.cn +www.txqq7.com +www.txqqyw.cn +www.txsm888.com +www.txviq.com +www.ty.zstu.edu.cn +www.tyjtyh.cn +www.tytzz.com +www.tywjj.com +www.u87.cn +www.uabbs.net +www.ucsanya.com +www.ucuc.cc +www.uebcixbagd.cn +www.uhnjid.co.cc +www.ui-wow.cn +www.uiouyu.cn +www.uk554.com.cn +www.unzjs.com +www.uoxz.info +www.upcomd.com +www.ursagates.co.uk +www.us100tv.com +www.us366.com +www.usa-yabao.com +www.usagene.com +www.usahao.com +www.usenet4all.ch +www.usmpvirtual.edu.pe +www.ut-sina.com +www.utg-sina.com +www.utsino.com +www.utt-sina.com.cn +www.uu77.info +www.uugoal.com +www.uvviewsoft.com +www.uxsavofjux.cn +www.uyghurpc.com +www.uznylsf.cn +www.v2ke.cn +www.v3338.com +www.v8ke.cn +www.v989.com +www.vagaa22.cn +www.vagosangshop.com +www.vanpeople.com +www.vastsea.com +www.vbcbncbncbn.cn +www.vemdelicia.com +www.veproxy.com +www.veropoema.net +www.videobox.com +www.vielkind.at +www.vip-cc1.cn +www.vip-cctv2.com +www.vip-qq2011.com +www.vip.qq.wz12.com +www.vip09x1.cn +www.vip2009-qq.com +www.vipcctv-2.cn +www.vipchat8.com +www.vipfq.com +www.viping.com.br +www.vipliao8.com +www.vippq.cn +www.vipq.us +www.vipyx.com +www.vipzuoai.cn +www.vipzuoai.com +www.visualbounds.com +www.vkers.cn +www.vn52.com +www.vnet6.com +www.vodaoao.com +www.vodwyt.com +www.vol777.com +www.vph.qfqf.co.cc +www.vpi1b.com +www.vpn318.cn +www.vs88.com.cn +www.vsdnf.com +www.vsvsssdw.com +www.vv088.com +www.vv8888.com +www.vv98mm.cn +www.vv9999.cn +www.vv9999.com +www.vymar.cz +www.vytf.com.cn +www.vznylsf.cn +www.w-x-y.cn +www.w22rt.com +www.w23q.cn +www.w2682.cn +www.w2if.cn +www.w2photo.cn +www.w6rt67ew7d.cn +www.w928.cn +www.wa-vip.com +www.wa128.cn +www.wa200.com +www.wal33d.info +www.wan886.com +www.wang321.cn +www.wangchao.net.cn +www.wangxinyue512.cn +www.wanku.com +www.wanmei-gua.com.cn +www.wansf.net +www.warcraftehina.com +www.warcrnftchina.com +www.wardrake.net +www.wasec.cn +www.waseecard.cn +www.waueeqianming.cn +www.wawa12345.com +www.wawasp.cn +www.waypoint-center.org +www.wbg544.us +www.wc86.com +www.wdswe.com +www.web233.cn +www.web898.net +www.wed.com.tw +www.weiboo.com +www.weifanghongli.com +www.weige19.com +www.weimagp.cn +www.weiquan365.com +www.weiss-cannon.de +www.weloveqianming.cn +www.westhertscardiology.com +www.wetpussygames.com +www.wfjinshun.com +www.wg.gd +www.whboy.net +www.whfgaiqqq.cn +www.whhhxy.com +www.whink.com +www.whsmg.cn +www.win388.com +www.windowsvistasp1.com.cn +www.winmend.com +www.winsdo-sim.cn +www.wixks.com +www.wk988.com +www.wkleaks.com +www.wl22.com +www.wlqxz3.cn +www.wmsjsf.com +www.wnyvfa.org +www.wo-yao-xing-jiao.info +www.wofkinsoyd.cn +www.wohenleile.cn +www.womenzz.com +www.woool.sc.cn +www.woools.sd.cn +www.wooolwaigua.com.cn +www.word888.com +www.wow-duowan.com +www.wow258.cn +www.wowand.com +www.wower.org +www.wowoke.us +www.wowshe1l.com +www.wowyesgo.info +www.wowyx.com +www.woxhyuj.cn +www.woxiaohei.cn +www.woyaocaonima.info +www.wqq1.cn +www.wrmetal.com +www.wrmfwa.cn +www.wrmfwb.cn +www.wrmfwc.cn +www.wrmfwd.cn +www.wrmfwe.cn +www.wrmfwf.cn +www.wrmfwg.cn +www.wrmfwh.cn +www.wrmfwm.cn +www.wrmfwn.cn +www.wrmfwo.cn +www.wrmfwq.cn +www.wrmfwr.cn +www.wrmfws.cn +www.wrmfwt.cn +www.wrmfwu.cn +www.wrmfwv.cn +www.wrmfwx.cn +www.ws789.com +www.ws91.cn +www.wscz.gov.cn +www.wst360.cn +www.wuhan3506.com.cn +www.wuhemd.cn +www.wujimov.cn +www.wundermanbudapest.hu +www.wusheng.org +www.wuxod.com +www.wuya1001.com +www.wuyedy.com +www.ww.th16388.com +www.ww2qq.com +www.wwcctv3.com +www.wwwwpppaa.cn +www.wx888.cc +www.wxafu.com +www.wxdz7788.cn +www.wye88.cn +www.wylt.net +www.wymfw.cn +www.wyt3.info +www.wyt95.com +www.wytmimi.com +www.wytvod.com +www.wz4321.com +www.wzszhi.com +www.x-ba.com.cn +www.x.mymirx.cn +www.x0gko.cn +www.x365x.com +www.x365x.net +www.x5-qq.com +www.xamweb.com +www.xatae.cn +www.xbsh.cn +www.xcrc114.com +www.xd558.com +www.xdfzq.com +www.xdxny.com +www.xenhijij.cn +www.xfbsw.com +www.xfjy.info +www.xfrgj.com +www.xg008.com +www.xg189.net +www.xg2618.cn +www.xg389.net +www.xg569.cn +www.xg5699.com +www.xg968.com +www.xg998.com +www.xg9988.com +www.xgmntp.com +www.xgztwt.cn +www.xh0088.cn +www.xh2009.com +www.xhdzsc888.com +www.xhostcoderx.hpg.com.br +www.xhsky.net +www.xhwjt.cn +www.xhyjl.cn +www.xiankenet.com +www.xiantugames.com +www.xiao776.com +www.xiao776.net +www.xiaolala.com +www.xiaoneirt.com +www.xiaoshuo8.cc +www.xiaoyx8.cn +www.xiazai0067.com +www.xiazai189.com +www.xidianjunpin.com +www.xindan.net.cn +www.xinfeibbs.cn +www.xingfu5yt.info +www.xingjiaow.com +www.xinglanhai.cn +www.xingpingchem.com +www.xingquwei.com +www.xinhua678.com +www.xinkeor.cn +www.xinlongcc.com +www.xinxinbaidu.com.cn +www.xiubo.net +www.xiyiyi.com.cn +www.xizlang.cn +www.xjcjwy.com +www.xjh3.cn +www.xkcode.com +www.xldzq.net +www.xm6216.cn +www.xmcs.info +www.xmmluoliao.cn +www.xmovie.com +www.xn--xkrp7r.com +www.xpstzx.cn +www.xsedu.zJ.cn +www.xsm3.com +www.xtdmm.com.cn +www.xtrades.com.cn +www.xuan666.com +www.xunlei.com.bwjjr.com +www.xunlei100.com +www.xunqu.com +www.xunwoai.com +www.xunxian55.com +www.xunxian78.com +www.xuqc907.com +www.xvghb.info +www.xx171.cn +www.xx175.cn +www.xxaixx.com +www.xxlavaix01xx.net +www.xxoowz.com +www.xxp2p.com +www.xxx130.com +www.xxxkkkkkkk.cn +www.xxxodnokursniki.com +www.xxxsrg.cn +www.xxxymovies.com +www.xxzfch.tk +www.xy2cjz.com +www.xy2gm.com +www.xyhai.com +www.xyqwaigua.cn +www.xyqwaigua.com.cn +www.xzilang.com +www.xznylsf.cn +www.xzwrn.cn +www.y0888.com +www.y131.com +www.y4ml.cn +www.y66y666.cn +www.y6888.com +www.y78y.com +www.y8898.com +www.yahocof.com +www.yahome.com.cn +www.yahoo-09yh.cn +www.yahoo.com.cn.22885.info +www.yahoo.com.mierr.cn +www.yahoo12d.com +www.yahooa.t3.to +www.yahoocde.com +www.yahookk.t3.to +www.yahooppd.com +www.yahooui0.com +www.yahoowoi.com +www.yahoozsw.com +www.yahu328.com +www.yahu365.com +www.yahuo.info +www.yaobobo.net.cn +www.yaokan8.cn +www.yaolihui.cn +www.yaorb.com +www.yazhoubt.net +www.yazhousetu.org +www.ycsp2009.cn +www.yd2265.cn +www.yd78.com +www.yd8628.cn +www.yekwc4.com +www.yeonj.info +www.yesdh.com +www.yese55.com +www.yesmybi.cn +www.yetaobao.com +www.yeye7.cn +www.yeyejiqing.com +www.yeziio.cn +www.yffs369.com +www.yh898.com +www.yi996.cn +www.yidianse.com +www.yigeav.com +www.yingzixitong.cn +www.yinhu.info +www.yinshui.info +www.yiqicall.com +www.yiqikanba.com +www.yiqilai.com +www.yiqisi.com +www.yiugtgfvs.cn +www.yiyejq.com +www.yiyese.com +www.yjsjl.cn +www.ykekj.com +www.ylly.info +www.ylzf001.cn +www.ylzf002.cn +www.ylzf003.cn +www.ylzf004.cn +www.ylzf005.cn +www.ymo5.cn +www.yo19.cn +www.yochat.cn +www.yoka100.cn +www.yollomeo.com +www.yometop.cn +www.yorkstrike.on.nimp.org +www.you8x.com +www.youareanidiot.org +www.youasoft.com +www.youku.com-09.info +www.youku.com.cn-vipsexdvd-play.texunsp.com +www.youku.com.huangsedianying.avl.ah.cn +www.youku.com.huangsedianying.xixidns.com +www.youkurt.com +www.youlku.com.baidu.com.fgjgjjggjdgjggdrd.crdy.info +www.yousex.in +www.youxi19.com +www.youxi213.cn +www.youxixinfeng.com +www.yp178.com +www.yqwt5efe56w56e.cn +www.ys315.net +www.ys8.com +www.ysa888.com +www.yshi.cn +www.yshqianming.com.cn +www.yskj.org +www.yssyy.com +www.ystv2010.com +www.ysxgyy.com +www.yt39.com +www.yt9a.cn +www.ytuku.com +www.yu171.cn +www.yuanweiming.com +www.yug28.com +www.yuhaiwei.cn +www.yule918.cn +www.yulewyt.cn +www.yunsheng.com +www.yuqiu8.cn +www.yuse.info +www.yutergfrg.cn +www.yuyangua.cn +www.yuyu611.info +www.yx-163.com +www.yy-douwan.com +www.yy-duowan.com +www.yy-xy.com +www.yy66666.cn +www.yybobo.com +www.yybobo.net +www.yydoudou.com +www.yymfdy.cn +www.yyq111.com +www.yyq58.com +www.yyuse.cn +www.yyxiazai.com +www.yyywang.com +www.yznylsf.cn +www.yztzxd888.com +www.yzzfs.cn +www.z130827.infobox.ru +www.z360.net +www.z900.info +www.zanxixi.cn +www.zb777.com +www.zblianyi.com +www.zcaiw.bj.cn +www.zcdnf.com +www.zddx.net +www.zdq004.cn +www.zeetone.com +www.zeusfiles.com +www.zexernet.com +www.zg89.com +www.zgcgsslle.cn +www.zgcp598.cn +www.zgflcp01.cn +www.zgftc.cn +www.zghncsa.cn +www.zghncsc.cn +www.zghncsd.cn +www.zghncse.cn +www.zghncsf.cn +www.zghncsg.cn +www.zghncsh.cn +www.zghncsi.cn +www.zghncsj.cn +www.zghncsl.cn +www.zghncsm.cn +www.zghncsn.cn +www.zghncso.cn +www.zghncsp.cn +www.zghncsq.cn +www.zghncsr.cn +www.zghncss.cn +www.zghncst.cn +www.zghncsu.cn +www.zghncsv.cn +www.zghncsw.cn +www.zghncsy.cn +www.zgynkma.cn +www.zgynkmb.cn +www.zgynkmc.cn +www.zgynkmd.cn +www.zgynkme.cn +www.zgynkmf.cn +www.zgynkmi.cn +www.zgynkmj.cn +www.zgynkmk.cn +www.zgynkml.cn +www.zgynkmo.cn +www.zgynkmp.cn +www.zgynkmq.cn +www.zgynkmr.cn +www.zgynkmt.cn +www.zgynkmu.cn +www.zgynkmv.cn +www.zgynkmx.cn +www.zgynkmy.cn +www.zgynkmz.cn +www.zh-cw.com +www.zh033.com +www.zhajinhua.cc +www.zhangyk.org +www.zhanzhangle.com +www.zhao09922.com +www.zhaobf.com +www.zhaodao123.com +www.zhaohao5.com +www.zhaokey.com.cn +www.zhaoqinggolf.com +www.zhaoxf.com +www.zhaoyanyu8.com +www.zhcvv.com +www.zhcw.org +www.zhcw178.cn +www.zhcw889.com +www.zhcwyc.25u.com +www.zhenglianzq.com +www.zhengtu-waigua.com +www.zhijinren.com +www.zhongguofulicaipiao.com +www.zhongguofulicaipiaowang.com +www.zhongjz.com +www.zhouli520.cn +www.zhuahei.cn +www.zhuangzi.gov.cn +www.zhujun0126.com +www.zhuti138.cn +www.zhuxian-bug.cn +www.zhuxian.he.cn +www.zhuxian2vip.com.cn +www.zigma.hk +www.zjbo.com +www.zjhanda.net +www.zjld.info +www.zjldw.com.cn +www.zjtv8.com +www.zlflawyer.com +www.zlzqw.cn +www.znwork.com +www.zogas.gr +www.zolcorp.com +www.zoooo.net +www.zop3.com +www.zq3366.com +www.zq346.com +www.zq4922.com +www.zq5599.com +www.zq69.com +www.zq966.com +www.zq98.com +www.zq9a.cn +www.zqingren.com +www.zquu.com +www.zqwww.com +www.zrngs.info +www.zsdnf.cn +www.zssb518.com +www.zt-tyre.com +www.zt1133.com +www.zugentong120.com +www.zuihouyi.com +www.zuimeng.net +www.zun168.com +www.zuoaibot.com +www.zxcai.cn +www.zxcai.com +www.zxekm.info +www.zxuu.com +www.zxzqcj.com +www.zygjzq.net +www.zyxyfy.com +www.zz10000.com +www.zz63.com +www.zz8888.net +www.zzbyfz.com +www.zzcore.com +www.zzdiy.net.cn +www.zzgame.co.kr +www.zzgy.net +www.zzhtnc.com +www.zznylsf.cn +www.zzt1.com +www.zzwwong.cn +www.zzyaya.com +www.zzyfsl.cn +www0.baidus-yahoo-sohu-163-sina-google.net.cn +www0.fds3.cn +www0.ibds3.cn +www1-qq.cn +www1.9wee.com +www1.bo3366.com +www1.deep-scansoft13.in +www1.deep-scansoft14.in +www1.deep-scansoft15.in +www1.deep-scansoft16.in +www1.deep-scansoft17.in +www1.deep-scansoft18.in +www1.deep-scansoft19.in +www1.dwjxn.com +www1.e-soso.com +www1.edude.net +www1.fdc8888.cn +www1.fine-guard-serv.in +www1.img-o.com +www1.kakawg.com +www1.rs3s2.com +www1.saveisarmy.co.cc +www1.self-checker11.in +www1.tywjj.com +www1.wdswe.com +www1.wopxs.com +www10.4252.net +www1108.cn +www12.tucows.com +www18.lianmeng.ws +www2.92ri.com +www2.asiappc.com +www2.bo3366.com +www2.chuantu.info +www2.s800qn.cn +www2.zjbdt.com +www2009tq.cn +www26jqcn.y712.cn +www3.soft-base22.net +www3.soft-base23.net +www330.megaupload.com +www5.8r3sw.cn +www6.hejians.cn +www88www.3322.org +www9.zhaoyou8.com +www_sina.ec.tc +wwwdegrees.info +wwweee.xxnimeixx.info +wwweee22.3322.org +wwwitems.cn +wwwjkad.3322.org +wwwkkuu.cn +wwww.2217.com +wwww.5555se.com +wwww.555ri.com +wwww.6mxx.com +wwww.92xxoo.com +wwww.962110.com +wwww.freevnbc.info +wwww.lifashi.com +wwww.pzzz.org +wwww.ttfabb.com +wwww.ttfafb.com +wwww.zaoxing.org +wwww.zhao-cha.com.cn +wwwworldweb.com +wwwwpppaa.cn +wwwwww.51smsad.com +wwwy7.cn +wxni.3322.org +wy163.doo.to +wy221.91mt.com +wye88.cn +wylf5168.web013.boothost.com +wyt.bo3366.com +wyt.paowyt.com +wyt.shanghaimeimei.cn +wyt09.com +wyt92.com +wyt94.com +wywfs.wywfs.com.cn +x-daily.com +x-e5tbao.cn +x-road.co.kr +x.17iw.com +x.40sese.com +x.52av.biz +x.6l.cn +x.6xx8.com +x.886.cn +x.97bose.com +x.97eee.org +x.b76.net +x.beijingxx6.com +x.erewx.info +x.kaspersky-com.info +x.ko115.com +x.moneyinfom.com +x.mymirx.cn +x.riniririni.info +x.w1s2d3.com +x.x5k.info +x.yidianse.com +x.yoyoface.com +x1.cssss.cn +x1.wcomn.cn +x166.2266s.com +x1ou.3322.org +x2.518mk.cn +x22qq.cn +x25mm.3322.org +x3r6.com +x5-qq.com +x5.hai265.com +x5978.3322.org +x846.e21r.com +x9host.cn +x9s7b.cn +xaalm.9966.org +xaj.ss.la +xakepbox.narod.ru +xalentarna.net +xao.ss.la +xaq.ss.la +xatae.cn +xb.zzuli.edu.cn +xbe.ss.la +xbx.tw +xc.97qingse.com +xc.beijingxx7.com +xc.haodifang7.com +xca.ss.la +xcbnr.cn +xcms.3322.org +xcnme.cn +xcvnr.cn +xd-23-59-a8.bta.net.cn +xd558.com +xdRexaS.q2bz.cn +xdjzdy.r.arpg2.com +xdl.uhfes.com +xdl.ur36d.com +xdnsrv.com +xdwlnbqsdsph5pc8rz81.cn +xdxd918.3322.org +xdyt.9966.org +xea.3322.org +xf.163wyt.com +xf.988wyt.com +xfj.huangshan.cn +xfzx.dtjy.org +xg008.com +xg569.cn +xg968.com +xg998.com +xgirl.3322.org +xgoogle88.9966.org +xgqsmz.ttqipai.com +xgztwt.cn +xhbngmhj.9966.org +xhhh005.cn +xia.2288.org +xia.23u.info +xia.jime3.info +xia.qunyou.info +xia0.ui18.xicp.cn +xia8866.com +xianfeng135.3322.org +xiang8981.com +xiao0.ui18.xicp.cn +xiaoneirt.com +xiaosu123.cn +xiaotao2.cn +xiaoxiaojd.3322.org +xiazai.bestxiyoudown.info +xiazai.chickenkiller.com +xiazai.dowmseslgrammar.info +xiazai.newxiyoudown.info +xiazai.qq12300.com +xiazai.qqceo.net +xiazai807.3322.org +xiazai828.3322.org +xiiyy.7766.org +xila.a32.53dns.com +xin110.kmip.net +xin254536.3322.org +xin33.3322.org +xin765.com +xin788954.3322.org +xin89221.com +xin8y879.3322.org +xin9527.com +xinfa8.com +xingchang.idc939.com +xingjiaow.com +xinhei333.3322.org +xinkangjie.com.cn +xinx02.cn +xiny69.cn +xinzhifu.maya777.com +xiqiji.cn +xiqiji2.cn +xiqiji28.cn +xiqiji36.cn +xis.dyndns-mail.com +xitong.animosite.info +xizlang.cn +xj.40sese.com +xj.46se.com +xj.816xx.com +xj.97qingse.com +xj.count.xj.cn +xjl1.3322.org +xl.97-97gan.com +xl.974671.com +xl.lunlidh.com +xl.swytw.com +xlxn.eu.kz +xm.wg-258.com +xm002.3322.org +xm1.bnz8.cn +xm17173.9966.org +xmas-party-pics.com +xmgogogo.8866.org +xml.btplay.net +xmm.cc +xmninbya.9966.org +xn--xkRp7r.com +xn.bisque110.com +xncvm.cn +xngh2.htmi2.com +xo.000cc.com +xo1u.3322.org +xoomer.virgilio.it +xoqei.cherishpoems.com +xp-download-center.com +xp.27gan.com +xp.ggg11.com +xp.wyt09.com +xp.yaorb.com +xp32.3322.org +xpehbam.net +xq80.njxzc.edu.cn +xqasvx.ttqipai.com +xqezwi.ttqipai.com +xrysanthema.gr +xs8g.com +xsddss.net +xsddz.com.cn +xsderfgbn.com +xsert5.com +xsw.2014wyt.net +xtjdm1.kmip.net +xtv.tv190.com +xudee.sv2.sgedns.cn +xuer888.cn +xunleikk.3322.org +xuxiao1234.3322.org +xvc.2018wyt.net +xvgh.isgre.at +xviewworldmy2.com +xw12.3322.org +xwb.cztv.tv +xwhoisdns.com +xwuor.cn +xx.67sao.com +xx.baidu369.cn +xx.ctivnn.cn +xx.deepty.com +xx.u097.cn +xx.use110.mobi +xx2.mao9988.cn +xxaixx.com +xxase.info +xxb0txx.xx.funpic.de +xxccv.mysxc.info +xxi.ss.la +xxll222.3322.org +xxlll.notlong.com +xxm.ss.la +xxo2.3322.org +xxpil.5617.com +xxqb.6600.org +xxswkj-xj.com +xxx-video-tube.org +xxx-youtube-porno.com +xxx.07ss.com +xxx.132xxoo.com +xxx.133xxoo.com +xxx.134xxoo.com +xxx.17qingse.com +xxx.222mi.net +xxx.345xxoo.com +xxx.365xxoo.com +xxx.456xxoo.com +xxx.46se.com +xxx.567xxoo.com +xxx.66qsw.com +xxx.678xxoo.com +xxx.720xxoo.com +xxx.745970.com +xxx.749571.com +xxx.789xxoo.com +xxx.920xxoo.com +xxx.970xxoo.com +xxx.971sese.com +xxx.bo33bo.net +xxx.elcakorea.co.kr +xxx.play-pornomovies.info +xxx.seqingbobo.com +xxx.shougongdailian.com +xxx.ss.la +xxx.sweetporn-movie.info +xxx.sysetv.com +xxx.tiantianse.com +xxx.waboa.tk +xxxo1.cn +xxxsrg.cn +xxxtube.freewebhostx.com +xxxvvvv.cn +xxxxi.271cn.net +xxxyyyzzzhhhjjj.caonimade360.com +xy.wowziti.com +xy1.gac4a.com +xy2.163chou.com +xy2.163choujiang.com +xy2.163jiang.com +xy2.163wyb.com +xy2.cbg.163.com-j.info +xy2.cbg.163.com.5217c.cn +xy2.cbg.com.kmwyl.com +xy2.cbg.yanzheng163.com +xy2.cbg163gm.cn +xy2.cbg163gs.cn +xy2.cbg163wy.com +xy2.cbg163wz.cn +xy2.cbg163wz.com +xy2.cbg163yh.cn +xy2.cbg163yhk.com +xy2.cbgwy163.com +xy2.diankachou.com +xy2.gmcbg.com +xy2.mbao163.org +xy2.mibaogm.com +xy2163cbg.com +xy2cbg.163.com-y.info +xy2cbg.com +xy2cjz.com +xy2mibao.com +xy2mibao163.com.cn +xy2mj-163.com +xy5.gac4a.com +xyq.163shenhe.com +xyq.dhj45.cn +xyq.djl87.cn +xyq.etu87.cn +xyq.fdg43.cn +xyq.gds43.cn +xyq.gjk67.cn +xyq.hfd46.cn +xyq.hjf54.cn +xyq.jhgf65.cn +xyq.kfd68.cn +xyq.khb86.cn +xyq.lgv97.cn +xyq.nge68.cn +xyunmd.a130.58ym.com +xz.50555dhrace.info +xz.8345netmarketing.info +xz.99dodos.info +xz.cocodowns.info +xz.dk127.cn +xz.flashubuntuu.info +xz.freedownxia.info +xz.fzibm.com +xz.gangubuntuu.info +xz.haojinyu.com +xz.newxiazaibacn.info +xz.palydownsyndrome.info +xz.proposition66coco.info +xz.qqdownsoft.info +xz.save-17173.info +xz.sina1663s.info +xz.soso1234site.info +xz.stressfreedownes.info +xz.thecocodowns.info +xz.thedowntgbus.info +xz.thenewfosoft.info +xz.wanggui.com +xz.wdjpq.net +xz.xiaxiasofys.info +xz1.177bt.com +xz2.177bt.com +xza.xx7.in +xzcbgfhngj11.3322.org +xzd11.ouyaoxiazai.com +xzz.dnf3600.cn +xzzde.com +xzznimaya.xicp.cn +y.8j5f.cn +y.8x2x.com +y.99xx99.cn +y.bobo111.cn +y.d5hk.cn +y.dsw0.cn +y.dsw4.cn +y.ge8r.cn +y.hd3s.cn +y.jd3m.cn +y.kh34.cn +y.moneyinfom.com +y.oy5e.cn +y.vfw3.cn +y5fgb.cn +y6dq.cn +ya-tracker.com +ya.com.9d1u.cn +yahcoo.top.to +yaho0.8800.org +yahoo-09yh.cn +yahoo-10.com +yahoo-comi.tk +yahoo-gg.com +yahoo-ll.com +yahoo-lo.in +yahoo-maill.asia +yahoo-maill.com +yahoo.com.cn.t3.to +yahoo.hd-2009.com.cn +yahoo.mzccf.cn +yahoonacy.info +yahootv.cn.to +yahoovip-yahoo.co.cc +yanlan88.cn +yanzhaomen.tv +yaoLihui-cn +yaolihui.cn +yaoyao52Ogg.com +yaoyaofree.com +yasws-05.cn +yawxowaj.cn +yaya.5dfgy.cn +yazhoubt.net +yazhousetu.org +yb-sport-555.cn +yb.xijing.edu.cn +yc.jsnetcom.com +yeerey.googlecode.com +yehua.2009.tk +yepeishan.cn +yes1088.3322.org +yes169.3322.org +yes9821.3322.org +yescss.3322.org +yesoff.com +yetaobao.com +yeye7.cn +yeyeyye.yo2.cn +yfh9bs.cx.cc +yg.donglink.cn +ygfc1.cn +yh898.com +yhhsx6anj.com +yhn6nhh.cn +yhoo-city.in +yhoo.serqc.cn +yia.dns0755.net +yidianse.com +yifaddz.com +yigeav.com +yigeshabi.8800.org +yij.dns0755.net +yin666.8udns2.cn +ying154.hjgvkk67.cn +ying154.jhbvjh676.cn +ying154.justcctv4.cn +ying154.justcctv5.cn +ying154.justhello.hi.cn +ying154.sport.mo.cn +yinhu.info +yisheng222.3322.org +yisheng321.3322.org +yishneg258.3322.org +yiyejq.com +yiyeqing.2288.org +yken.3322.org +ylaoda.3322.org +ylguanli.9966.org +ylkt.3322.org +ylzf002.cn +ylzf003.cn +ylzf004.cn +ylzf005.cn +ym6999.91mt.com +ynasd.cn +yo19.cn +yochat.cn +yof6.cn +yohooie.com +yomwarayom2001.ru +yongyou100.com +yoopwm.3322.org +you8x.com +youbet.cc88cc.com +youfu110.cn +youhai2.3322.org +youku.com-09.info +youku.com.huangsedianying.xixidns.com +youku321.com +youkurt.com +youkuv.tudoudou.5ku.com.6rooms.com.2geren.com +youngmetal.ru +your24domain.com +youradore.com +yourbestworld.cn +yourcountycoupon.com +youregypt.com +yourexportal.org +yourfilmfest.in +yourgreatlove.com +yourlocatorusa.com +yourmusic.count.xj.cn +yournameshop.cn +yourownplanet.cn +yourplusantivirus.com +yourweb.count.xj.cn +youryear.count.xj.cn +youtube-top-video.com +youxiang.host48.gomeidc.net +youxiarobolet.com +yovel.net +yoy.yoy.cn +yp2121.91mt.com +ypdede.chickenkiller.com +yqvip.com +yrdsaaw.3322.org +ys988.cn +ysdf1.cn +ysizy.ferxiziw.cn +yssyy.com +ystv2010.com +yt.jzjz.net +yt39.com +yt9a.cn +yu.2009pjfdnc.cn +yu.2009vdfgd.cn +yu.fgerth.cn +yu.sirutn.cn +yu171.cn +yuandan007.3322.org +yubv5569.xw2.cdn9.info +yudgoalq.co.cc +yuhaiwei.cn +yuioyui.fr6.hai51.com +yulekongjian.tk +yulewyt.cn +yumen1.36tt.3322.org +yuna133.3322.org +yushimuye.com +yuyu98.com +yvetteshipley.com +yx-163.com +yx.gannetea.net +yx123.zu58.com +yx3721.com +yxj26.9966.org +yxj77.9966.org +yxjbaby.9966.org +yxwm.3322.org +yy-douwan.cn +yy-duowan.com +yy.dkjf45.com.cn +yy.douawan.com +yy.duowanz.com +yy.dwowan.com +yy.fmzx.com +yy12s.com +yy8008.cn +yybbbb.com +yybobo.com +yybobo.net +yygeiwofc.cn +yykkss.36tt.3322.org +yyreg4.2288.org +yyy.2012wyt.net +yyywang.com +yzfkj.com +yzhuaxiang.cn +yzzfs.cn +z-bizsoftportal.com +z.214d.com +z.ds974.cn +z.fghf8.cn +z.fghf9.cn +z.gd863.cn +z.gh674.cn +z.hg973.cn +z.ie854.cn +z.iy467.cn +z.jd963.cn +z.kghh1.cn +z.kghh3.cn +z.kghh4.cn +z.kghh5.cn +z.km940.cn +z.te963.cn +z.ur346.cn +z.us963.cn +z.y098.cn +z1.16wuu.com +z360.net +z5auz.spaces.live.com +z6ailnvi94jgg.cn +z900.info +z999hu.cn +za.automtv.com +za178.cn +zaebalisuki.com +zaixian-kandianying.46132.cn +zalupkin.ru +zaofu66.cn +zaoxiezhiliao.com +zaq.2014wyt.com +zarenaga.com +zatura.cn +zazhi.maya777.com +zbhykj.com +zbwtuis.cn +zc.mzdbt.com +zcac123.3322.org +zdan84115.xx108.zgsj.net +zdqwe3q2.cn +zeldaxtreme.net +zemondocooler.com +zenitchampion.cn +zenka.fileave.com +zero2000.com +zetaw.com +zetross.com +zeus.xpsweb.com +zf8.id666.com +zfgrewrw.cn +zg89.com +zgcp598.cn +zgflcp01.cn +zgunion.cn +zgysyy.com +zhang.nu +zhanggzy.web.beian6.com +zhcw.org +zhcw178.cn +zhcw889.com +zhenjia123.3322.org +zhong288.com +zhongboph.com +zhongguofulicaipiao.com +zhongguoren.qianjiejie.com +zhongtianheng.3322.org +zhongyou.131181.com +zhouli520.cn +zhouyuhuzhouyuhu.com.cn +zhuxian.he.cn +zhuxian2vip.com.cn +zhuzhuzhux1.3322.org +zi7726.91mt.com +zief.pl +zilchtin.ru +zio77777.interfree.it +ziofile.com +zitagallerani.com +zitm.info +ziyueshi.com +zjcx.gov.cn +zjjf531ne4kaa.3322.org +zjy188.d68.zgsj.net +zka88.3322.org +zkeiuq3.3322.org +zl.bugxue.com +zloeradio.org.ua +zlwrnm11.cn +zmkm888.cn +zmx5.cn +zndxyey.8866.org +zo921.91mt.com +zomen.net +zone-exe-files.com +zonetech.info +zongshangwang.wxrex.com +zougua.wxrex.com +zouxi.wxrex.com +zozis.net +zp.1791xx.com +zpress.100free.com +zqt.antiterroris.com +zros.info +zs.gcp.edu.cn +zs.orzsystem.me +zs.qq2009d.cn +zsb.lyge.cn +zsoforoms.cn +zsrdgrki32qw.com +zsw3.cn +zsw5.cn +zt.jw961.cn +ztxp.net +zuanding.wxrex.com +zuclowix.cn +zunnonggang.wxrex.com +zurl.ws +zus.seobash.org +zusojbktvo.cn +zuxmash.info +zwwderff.cn +zx-yahoo.in +zx.bo3366.com +zxasdc.3322.org +zxcai.cn +zxcai.com +zxian.vz.to +zxva.info +zxxt58y.com +zxxz.8800.org +zy.gzidc.cn +zy123267084.3322.org +zyejanag.cn +zyfx110.cn +zyfx987.cn +zz10000.com +zz222.8866.org +zz555.8866.org +zzb.nenu.edu.cn +zzzz.hostindianet.com +zzzz6655.cn \ No newline at end of file diff --git a/src/test/java/com/greate/community/ElasticsearchTest.java b/src/test/java/com/greate/community/ElasticsearchTest.java index df7444e..5df0e6c 100644 --- a/src/test/java/com/greate/community/ElasticsearchTest.java +++ b/src/test/java/com/greate/community/ElasticsearchTest.java @@ -30,6 +30,11 @@ public class ElasticsearchTest { @Test public void testGet() { - log.info(elasticsearchService.getDiscussPostById(33).toString()); + log.info(elasticsearchService.getDiscussPostById(62).toString()); + } + + @Test + public void testSearch() { + log.info(elasticsearchService.searchDiscussPost("测试", 1, 10).toString()); } } -- Gitee From a9c6829f4d8c8f44738b87c46ceaf6e39af2e71c Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Sat, 5 Mar 2022 15:04:20 +0800 Subject: [PATCH 072/125] =?UTF-8?q?es=E6=90=9C=E7=B4=A2=E5=85=B3=E9=94=AE?= =?UTF-8?q?=E8=AF=8D=E9=AB=98=E4=BA=AE=E6=A0=87=E7=AD=BE=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SearchController.java | 5 +--- .../service/ElasticsearchService.java | 23 ++++++++++++++++--- src/main/resources/application.properties | 4 ++-- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/greate/community/controller/SearchController.java b/src/main/java/com/greate/community/controller/SearchController.java index 1c846a7..2e0a8e7 100644 --- a/src/main/java/com/greate/community/controller/SearchController.java +++ b/src/main/java/com/greate/community/controller/SearchController.java @@ -11,8 +11,8 @@ import com.greate.community.service.LikeService; import com.greate.community.service.UserService; import com.greate.community.util.CommunityConstant; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import java.util.*; @@ -53,7 +53,6 @@ public class SearchController extends BaseController implements CommunityConstan for (DiscussPost post : searchResult) { Map map = new HashMap<>(); // 帖子 -// map.put("post", post); //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 map.put("post", discussPostService.toDiscussPostJsonObject(post)); @@ -77,6 +76,4 @@ public class SearchController extends BaseController implements CommunityConstan return new Result("success", Result.SUCCESS, jsonObject); } - - } diff --git a/src/main/java/com/greate/community/service/ElasticsearchService.java b/src/main/java/com/greate/community/service/ElasticsearchService.java index 6f754bb..e8694da 100644 --- a/src/main/java/com/greate/community/service/ElasticsearchService.java +++ b/src/main/java/com/greate/community/service/ElasticsearchService.java @@ -1,6 +1,7 @@ package com.greate.community.service; import com.greate.community.entity.DiscussPost; +import lombok.extern.slf4j.Slf4j; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; import org.elasticsearch.search.sort.SortBuilders; @@ -20,11 +21,13 @@ import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.List; +import java.util.Map; /** * 搜索相关 */ @Service +@Slf4j public class ElasticsearchService { @Autowired @@ -36,6 +39,9 @@ public class ElasticsearchService { if (!elasticsearchRestTemplate.indexOps(DiscussPost.class).exists()) { elasticsearchRestTemplate.indexOps(DiscussPost.class).create(); elasticsearchRestTemplate.indexOps(DiscussPost.class).putMapping(); + log.info("es服务器无 discusspost 索引,创建该索引"); + }else { + log.info("es服务器存在 discusspost 索引,无需创建该索引"); } } @@ -82,16 +88,27 @@ public class ElasticsearchService { .withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC)) .withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC)) .withPageable(PageRequest.of(current, limit)) +// .withHighlightFields( +// new HighlightBuilder.Field("title").preTags("").postTags(""), +// new HighlightBuilder.Field("content").preTags("").postTags("")) .withHighlightFields( - new HighlightBuilder.Field("title").preTags("").postTags(""), - new HighlightBuilder.Field("content").preTags("").postTags("") - ).build(); + new HighlightBuilder.Field("title"), + new HighlightBuilder.Field("content")) + .withHighlightBuilder( + new HighlightBuilder().preTags("").postTags("")) + .build(); SearchHits searchHits = elasticsearchRestTemplate.search(searchQuery, DiscussPost.class); //封装page对象 List content = new ArrayList<>(); for (SearchHit productSearchHit : searchHits) { + //高亮的内容 + Map> highlightFields = productSearchHit.getHighlightFields(); + //将高亮的内容填充到content中 + productSearchHit.getContent().setTitle(highlightFields.get("title")==null ? productSearchHit.getContent().getTitle():highlightFields.get("title").get(0)); + productSearchHit.getContent().setContent(highlightFields.get("content")==null ? productSearchHit.getContent().getContent():highlightFields.get("content").get(0)); + //放到实体类中 content.add(productSearchHit.getContent()); } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f11f2d7..0056a96 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,5 @@ -#spring.profiles.active = develop -spring.profiles.active = test +spring.profiles.active = develop +#spring.profiles.active = test #spring.profiles.active = produce # logback -- Gitee From 475e0a07508dfb70f12e9cb042f5b631924ffb18 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Sat, 5 Mar 2022 15:25:45 +0800 Subject: [PATCH 073/125] update set username length --- .../greate/community/config/AppConfig.java | 17 +----- .../community/controller/LoginController.java | 18 +++---- .../community/controller/UserController.java | 2 + .../greate/community/entity/LoginTicket.java | 54 ++----------------- 4 files changed, 14 insertions(+), 77 deletions(-) diff --git a/src/main/java/com/greate/community/config/AppConfig.java b/src/main/java/com/greate/community/config/AppConfig.java index 55f783e..3327509 100644 --- a/src/main/java/com/greate/community/config/AppConfig.java +++ b/src/main/java/com/greate/community/config/AppConfig.java @@ -2,27 +2,14 @@ package com.greate.community.config; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.Environment; - -import javax.annotation.PostConstruct; @Data @Slf4j @Configuration public class AppConfig { + @Value("${spring.profiles.active}") public static String env; - - private final Environment environment; - - public AppConfig(Environment environment) { - this.environment = environment; - } - - @PostConstruct - public void init() { - env=environment.getProperty("spring.profiles.active"); - log.info("spring.profiles.active: {}", env); - } } diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index 754c493..002fe09 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -195,22 +195,21 @@ public class LoginController extends BaseController implements CommunityConstant @GetMapping("/wechat/login") public void wechatLogin(@AuthenticationPrincipal UserWeChat userWeChat, HttpServletResponse response) throws IOException { String openid = userWeChat.getOpenId(); - String username = userWeChat.getNickName(); //微信昵称 - String password = CommunityUtil.generateUUID(); //随机密码,不能随便让人破解 +// String username = userWeChat.getNickName(); //微信昵称 +// String password = CommunityUtil.generateUUID(); //随机密码,不能随便让人破解 String headerUrl = userWeChat.getHeadimgurl(); //微信头像地址 - String email = "wechat@none.com"; //微信登录的用户,邮箱是一个特殊标识字符串 +// String email = "wechat@none.com"; //微信登录的用户,邮箱是一个特殊标识字符串 // 若微信用户对应的账号已存在,跳过模拟注册操作,直接进入登录过程 -// User u = userMapper.selectByName(username); User u = userMapper.selectByOpenid(openid); User user = new User(); if (u == null) { // 模拟注册操作 // user.setUsername(username); - user.setPassword(password); - user.setEmail(email); +// user.setPassword(password); +// user.setEmail(email); user.setType(0); // 默认普通用户 - user.setStatus(1); // 微信登录用户默认激活,无需邮箱验证 + user.setStatus(1); // 微信登录用户默认激活 user.setLevel(0); // 等级默认0级 user.setExp(0); // 经验0 user.setLikeCount(0); // 点赞数量0 @@ -218,11 +217,9 @@ public class LoginController extends BaseController implements CommunityConstant // 用户头像 user.setHeaderUrl(headerUrl); // 微信头像地址 user.setCreateTime(new Date()); // 注册时间 - user.setOpenid(openid); //微信用户openid + user.setOpenid(openid); // 微信用户openid userMapper.insertUser(user); - // 这一步主要是为了获取userId -// user = userMapper.selectByName(username); user = userMapper.selectByOpenid(openid); } else { user = u; @@ -245,7 +242,6 @@ public class LoginController extends BaseController implements CommunityConstant String ticket = loginTicket.getTicket(); - //todo 带上ticket重定向到前端 response.sendRedirect("http://119.91.149.96:8080/?ticket=" + ticket); } diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 8f2e980..384ef03 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -83,6 +83,8 @@ public class UserController extends BaseController implements CommunityConstant public Result updateUsername(@RequestBody String username) { if (StringUtils.isBlank(username)) { return new Result("fail", "1", "用户名不能为空"); + } else if (username.length() <= 2 || username.length() > 10) { + return new Result("fail", "4", "用户名长度不能超过2-10个字符"); } int result = userService.updateUsername(getUser().getId(), username); if (result == 2) { diff --git a/src/main/java/com/greate/community/entity/LoginTicket.java b/src/main/java/com/greate/community/entity/LoginTicket.java index f13c271..36caafa 100644 --- a/src/main/java/com/greate/community/entity/LoginTicket.java +++ b/src/main/java/com/greate/community/entity/LoginTicket.java @@ -1,7 +1,10 @@ package com.greate.community.entity; +import lombok.Data; + import java.util.Date; +@Data public class LoginTicket { private int id; @@ -9,55 +12,4 @@ public class LoginTicket { private String ticket; // 凭证 private int status; // 状态(是否有效) private Date expired; // 过期时间 - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public int getUserId() { - return userId; - } - - public void setUserId(int userId) { - this.userId = userId; - } - - public String getTicket() { - return ticket; - } - - public void setTicket(String ticket) { - this.ticket = ticket; - } - - public int getStatus() { - return status; - } - - public void setStatus(int status) { - this.status = status; - } - - public Date getExpired() { - return expired; - } - - public void setExpired(Date expired) { - this.expired = expired; - } - - @Override - public String toString() { - return "LoginTicket{" + - "id=" + id + - ", userId=" + userId + - ", ticket='" + ticket + '\'' + - ", status=" + status + - ", expired=" + expired + - '}'; - } } -- Gitee From c245b51b85a5bd8369778f208f815479740cc458 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Sun, 6 Mar 2022 13:44:27 +0800 Subject: [PATCH 074/125] add login by email, delet login by username --- .../community/controller/LoginController.java | 53 +++++++------------ .../greate/community/entity/LoginTicket.java | 3 ++ .../community/service/TicketService.java | 33 ++++++++++++ .../greate/community/service/UserService.java | 43 +++++++-------- .../community/util/CommunityConstant.java | 1 + .../greate/community/util/RedisKeyUtil.java | 6 +-- src/main/resources/application.properties | 4 +- 7 files changed, 81 insertions(+), 62 deletions(-) create mode 100644 src/main/java/com/greate/community/service/TicketService.java diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index 002fe09..64572c7 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -7,21 +7,16 @@ import com.alibaba.fastjson.JSONObject; import com.greate.community.auth.wechatauth.domain.UserWeChat; import com.greate.community.dao.UserMapper; import com.greate.community.entity.Event; -import com.greate.community.entity.LoginTicket; import com.greate.community.entity.Result; import com.greate.community.entity.User; import com.greate.community.event.EventProducer; -import com.greate.community.service.ExpService; +import com.greate.community.service.TicketService; import com.greate.community.service.UserService; import com.greate.community.util.CommunityConstant; -import com.greate.community.util.CommunityUtil; import com.greate.community.util.ExpType; import com.greate.community.util.RedisKeyUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.core.annotation.AuthenticationPrincipal; @@ -43,21 +38,27 @@ import java.util.concurrent.TimeUnit; @RestController public class LoginController extends BaseController implements CommunityConstant { - @Autowired - private UserService userService; + private final UserService userService; - @Autowired - private UserMapper userMapper; + private final TicketService ticketService; - @Autowired - private RedisTemplate redisTemplate; + private final UserMapper userMapper; - @Autowired - private EventProducer eventProducer; + private final RedisTemplate redisTemplate; + + private final EventProducer eventProducer; @Value("${bbs.captcha-enable}") private boolean captchaEnable; + public LoginController(UserService userService, TicketService ticketService, UserMapper userMapper, RedisTemplate redisTemplate, EventProducer eventProducer) { + this.userService = userService; + this.ticketService = ticketService; + this.userMapper = userMapper; + this.redisTemplate = redisTemplate; + this.eventProducer = eventProducer; + } + /** * 注册用户 * @@ -138,9 +139,9 @@ public class LoginController extends BaseController implements CommunityConstant } /** - * 用户登录 + * 邮箱登录 * - * @param username 用户名 + * @param email 邮箱 * @param password 密码 * @param code 验证码 * @param rememberMe 是否记住我(点击记住我后,凭证的有效期延长) @@ -148,7 +149,7 @@ public class LoginController extends BaseController implements CommunityConstant * @return */ @PostMapping("/login") - public Result login(@RequestParam("username") String username, + public Result login(@RequestParam("email") String email, @RequestParam("password") String password, @RequestParam("code") String code, @RequestParam("rememberMe") boolean rememberMe, @@ -170,7 +171,7 @@ public class LoginController extends BaseController implements CommunityConstant // 凭证过期时间(是否记住我) int expiredSeconds = rememberMe ? REMEMBER_EXPIRED_SECONDS : DEFAULT_EXPIRED_SECONDS; // 验证用户名和密码 - Map map = userService.login(username, password, expiredSeconds); + Map map = userService.loginByEmail(email, password, expiredSeconds); if (map.containsKey("ticket")) { String ticket = map.get("ticket").toString(); @@ -225,22 +226,8 @@ public class LoginController extends BaseController implements CommunityConstant user = u; } - // 模拟普通登录过程 - // 凭证过期时间 - int expiredSeconds = DEFAULT_EXPIRED_SECONDS; - // 用户名和密码均正确,为该用户生成登录凭证 - LoginTicket loginTicket = new LoginTicket(); - loginTicket.setUserId(user.getId()); - loginTicket.setTicket(CommunityUtil.generateUUID()); // 随机凭证 - loginTicket.setStatus(0); // 设置凭证状态为有效(当用户登出的时候,设置凭证状态为无效) - loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000)); // 设置凭证到期时间 - - // 将登录凭证存入 redis - String redisKey = RedisKeyUtil.getTicketKey(loginTicket.getTicket()); - redisTemplate.opsForValue().set(redisKey, loginTicket); - - String ticket = loginTicket.getTicket(); + String ticket = ticketService.saveTicket(user.getId(), DEFAULT_EXPIRED_SECONDS); response.sendRedirect("http://119.91.149.96:8080/?ticket=" + ticket); } diff --git a/src/main/java/com/greate/community/entity/LoginTicket.java b/src/main/java/com/greate/community/entity/LoginTicket.java index 36caafa..e2116c7 100644 --- a/src/main/java/com/greate/community/entity/LoginTicket.java +++ b/src/main/java/com/greate/community/entity/LoginTicket.java @@ -1,5 +1,7 @@ package com.greate.community.entity; +import com.greate.community.util.CommunityUtil; +import com.greate.community.util.RedisKeyUtil; import lombok.Data; import java.util.Date; @@ -12,4 +14,5 @@ public class LoginTicket { private String ticket; // 凭证 private int status; // 状态(是否有效) private Date expired; // 过期时间 + } diff --git a/src/main/java/com/greate/community/service/TicketService.java b/src/main/java/com/greate/community/service/TicketService.java new file mode 100644 index 0000000..f2cbd54 --- /dev/null +++ b/src/main/java/com/greate/community/service/TicketService.java @@ -0,0 +1,33 @@ +package com.greate.community.service; + +import com.greate.community.entity.LoginTicket; +import com.greate.community.util.CommunityUtil; +import com.greate.community.util.RedisKeyUtil; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.Date; + +@Service +public class TicketService { + + private final RedisTemplate redisTemplate; + + public TicketService(RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + + public String saveTicket(int userId, int expiredSeconds) { + LoginTicket loginTicket = new LoginTicket(); + loginTicket.setUserId(userId); + loginTicket.setTicket(CommunityUtil.generateUUID()); // 随机凭证 + loginTicket.setStatus(0); // 设置凭证状态为有效(当用户登出的时候,设置凭证状态为无效) + loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000)); // 设置凭证到期时间 + + // 将登录凭证存入 redis + String redisKey = RedisKeyUtil.getTicketKey(loginTicket.getTicket()); + redisTemplate.opsForValue().set(redisKey, loginTicket); + + return loginTicket.getTicket(); + } +} diff --git a/src/main/java/com/greate/community/service/UserService.java b/src/main/java/com/greate/community/service/UserService.java index 9ae102b..fa3bd28 100644 --- a/src/main/java/com/greate/community/service/UserService.java +++ b/src/main/java/com/greate/community/service/UserService.java @@ -22,14 +22,20 @@ import java.util.concurrent.TimeUnit; @Service public class UserService implements CommunityConstant { - @Autowired - EmailUtil emailUtil; + final EmailUtil emailUtil; - @Autowired - private UserMapper userMapper; + private final UserMapper userMapper; - @Autowired - private RedisTemplate redisTemplate; + private final RedisTemplate redisTemplate; + + private final TicketService ticketService; + + public UserService(RedisTemplate redisTemplate, TicketService ticketService, EmailUtil emailUtil, UserMapper userMapper) { + this.redisTemplate = redisTemplate; + this.ticketService = ticketService; + this.emailUtil = emailUtil; + this.userMapper = userMapper; + } /** * 根据 Id 查询用户 @@ -148,19 +154,19 @@ public class UserService implements CommunityConstant { } /** - * 用户登录(为用户创建凭证) + * 用户邮箱登录(为用户创建凭证) * - * @param username + * @param email * @param password * @param expiredSeconds 多少秒后凭证过期 * @return Map 返回错误提示消息以及 ticket(凭证) */ - public Map login(String username, String password, int expiredSeconds) { + public Map loginByEmail(String email, String password, int expiredSeconds) { Map map = new HashMap<>(); // 空值处理 - if (StringUtils.isBlank(username)) { - map.put("usernameMsg", "账号不能为空"); + if (StringUtils.isBlank(email)) { + map.put("usernameMsg", "邮箱不能为空"); return map; } if (StringUtils.isBlank(password)) { @@ -169,7 +175,7 @@ public class UserService implements CommunityConstant { } // 验证账号 - User user = userMapper.selectByName(username); + User user = userMapper.selectByEmail(email); if (user == null) { map.put("passwordMsg", "密码错误"); return map; @@ -190,18 +196,8 @@ public class UserService implements CommunityConstant { } // 用户名和密码均正确,为该用户生成登录凭证 - LoginTicket loginTicket = new LoginTicket(); - loginTicket.setUserId(user.getId()); - loginTicket.setTicket(CommunityUtil.generateUUID()); // 随机凭证 - loginTicket.setStatus(0); // 设置凭证状态为有效(当用户登出的时候,设置凭证状态为无效) - loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000)); // 设置凭证到期时间 - - // 将登录凭证存入 redis - String redisKey = RedisKeyUtil.getTicketKey(loginTicket.getTicket()); - redisTemplate.opsForValue().set(redisKey, loginTicket); - map.put("userId", user.getId()); - map.put("ticket", loginTicket.getTicket()); + map.put("ticket", ticketService.saveTicket(user.getId(), expiredSeconds)); return map; } @@ -212,7 +208,6 @@ public class UserService implements CommunityConstant { * @param ticket */ public void logout(String ticket) { - // 修改(先删除再插入)对应用户在 redis 中的凭证状态 String redisKey = RedisKeyUtil.getTicketKey(ticket); // LoginTicket loginTicket = (LoginTicket) redisTemplate.opsForValue().get(redisKey); // loginTicket.setStatus(1); diff --git a/src/main/java/com/greate/community/util/CommunityConstant.java b/src/main/java/com/greate/community/util/CommunityConstant.java index 6215864..c2dd7b7 100644 --- a/src/main/java/com/greate/community/util/CommunityConstant.java +++ b/src/main/java/com/greate/community/util/CommunityConstant.java @@ -18,6 +18,7 @@ public interface CommunityConstant { // 默认的登录凭证超时时间 (12小时) int DEFAULT_EXPIRED_SECONDS = 3600 * 12; +// int DEFAULT_EXPIRED_SECONDS = 30; // 记住我状态下的凭证超时时间 (100天) int REMEMBER_EXPIRED_SECONDS = 3600 * 24 * 100; diff --git a/src/main/java/com/greate/community/util/RedisKeyUtil.java b/src/main/java/com/greate/community/util/RedisKeyUtil.java index 734254b..bad0a4f 100644 --- a/src/main/java/com/greate/community/util/RedisKeyUtil.java +++ b/src/main/java/com/greate/community/util/RedisKeyUtil.java @@ -68,11 +68,11 @@ public class RedisKeyUtil { /** * 登陆凭证 * - * @param ticket + * @param userId * @return */ - public static String getTicketKey(String ticket) { - return PREFIX_TICKET + SPLIT + ticket; + public static String getTicketKey(String userId) { + return PREFIX_TICKET + SPLIT + userId; } /** diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 0056a96..f11f2d7 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,5 @@ -spring.profiles.active = develop -#spring.profiles.active = test +#spring.profiles.active = develop +spring.profiles.active = test #spring.profiles.active = produce # logback -- Gitee From fe7823cd81f2f3d34bbc9fb44cfc6e59ed08c0f7 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Sun, 6 Mar 2022 16:02:00 +0800 Subject: [PATCH 075/125] update login api --- .../community/controller/LoginController.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index 64572c7..b10b455 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -141,19 +141,17 @@ public class LoginController extends BaseController implements CommunityConstant /** * 邮箱登录 * - * @param email 邮箱 - * @param password 密码 - * @param code 验证码 - * @param rememberMe 是否记住我(点击记住我后,凭证的有效期延长) - * @param captchaToken 验证码标识 + * @return */ @PostMapping("/login") - public Result login(@RequestParam("email") String email, - @RequestParam("password") String password, - @RequestParam("code") String code, - @RequestParam("rememberMe") boolean rememberMe, - @RequestParam("captchaToken") String captchaToken) { + public Result login(@RequestBody HashMap request) { + String email = (String) request.get("email"); + String password = (String) request.get("password"); + String code = (String) request.get("code"); + Boolean rememberMe = (Boolean) request.get("rememberMe"); + String captchaToken = (String) request.get("captchaToken"); + // 检查验证码 if (captchaEnable) { String captcha = null; -- Gitee From c0ccfd573f5329da6bf38336c8546b9216767e11 Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Sun, 6 Mar 2022 17:10:34 +0800 Subject: [PATCH 076/125] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=85=B3=E6=B3=A8?= =?UTF-8?q?=E9=87=8D=E5=A4=8D=E9=80=9A=E7=9F=A5=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/FollowController.java | 25 +++++++++++++------ .../greate/community/dao/MessageMapper.java | 7 ++++++ .../community/service/MessageService.java | 24 ++++++++++++++++++ src/main/resources/application.properties | 4 +-- src/main/resources/mapper/message-mapper.xml | 11 ++++++++ 5 files changed, 61 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/greate/community/controller/FollowController.java b/src/main/java/com/greate/community/controller/FollowController.java index 8f1fe27..8f7a0ba 100644 --- a/src/main/java/com/greate/community/controller/FollowController.java +++ b/src/main/java/com/greate/community/controller/FollowController.java @@ -7,6 +7,7 @@ import com.greate.community.entity.Result; import com.greate.community.entity.User; import com.greate.community.event.EventProducer; import com.greate.community.service.FollowService; +import com.greate.community.service.MessageService; import com.greate.community.service.UserService; import com.greate.community.util.CommunityConstant; import com.greate.community.util.CommunityUtil; @@ -33,6 +34,9 @@ public class FollowController extends BaseController implements CommunityConstan @Autowired private UserService userService; + @Autowired + private MessageService messageService; + @Autowired private EventProducer eventProducer; @@ -57,15 +61,20 @@ public class FollowController extends BaseController implements CommunityConstan }else{ //未关注该用户,执行关注操作 followService.followOrUnfollow(user.getId(), entityType, entityId); - // 触发关注事件(系统通知) - Event event = new Event() - .setTopic(TOPIC_FOLLOW) - .setUserId(getUser().getId()) - .setEntityType(entityType) - .setEntityId(entityId) - .setEntityUserId(entityId); - eventProducer.fireEvent(event); + //判断是否已经存在由 getUser().getId() 用户关注 entityId 用户生成的 follow 类型系统通知 + boolean hasFollowMessage = messageService.hasFollowMessage(entityId, getUser().getId()); + if(!hasFollowMessage){ + //尚无该关注通知,则 + // 触发关注事件(系统通知) + Event event = new Event() + .setTopic(TOPIC_FOLLOW) + .setUserId(getUser().getId()) + .setEntityType(entityType) + .setEntityId(entityId) + .setEntityUserId(entityId); + eventProducer.fireEvent(event); + } return new Result("success", Result.SUCCESS, "关注用户成功"); } } diff --git a/src/main/java/com/greate/community/dao/MessageMapper.java b/src/main/java/com/greate/community/dao/MessageMapper.java index b52fd72..c5f8959 100644 --- a/src/main/java/com/greate/community/dao/MessageMapper.java +++ b/src/main/java/com/greate/community/dao/MessageMapper.java @@ -107,6 +107,13 @@ public interface MessageMapper { */ int updateStatusAll(int userId, String conversationId); + /** + * 查询具有给定 toId 和 content 的 follow 类型的系统通知记录条数 + * @param toId + * @param content + * @return + */ + int selectFollowMessageByToidAndContent(int toId, String content); } diff --git a/src/main/java/com/greate/community/service/MessageService.java b/src/main/java/com/greate/community/service/MessageService.java index 6acf7fa..4e9da97 100644 --- a/src/main/java/com/greate/community/service/MessageService.java +++ b/src/main/java/com/greate/community/service/MessageService.java @@ -1,5 +1,6 @@ package com.greate.community.service; +import com.alibaba.fastjson.JSONObject; import com.greate.community.dao.MessageMapper; import com.greate.community.entity.Message; import com.greate.community.util.SensitiveFilter; @@ -7,7 +8,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.util.HtmlUtils; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * 私信/系统通知相关 @@ -150,4 +153,25 @@ public class MessageService { return messageMapper.updateStatusAll(userId, conversationId); } + + + /** + * 判断是否已经存在由 userId 用户关注 toId 用户生成的 follow 类型系统通知 + * @param toId + * @param userId + * @return + */ + public boolean hasFollowMessage(int toId, int userId){ + Map contentMap = new HashMap<>(); + contentMap.put("userId", userId); + contentMap.put("entityType", 3); + contentMap.put("entityId", toId); + String content = JSONObject.toJSONString(contentMap); + content = HtmlUtils.htmlEscape(content); + + int messageNum = messageMapper.selectFollowMessageByToidAndContent(toId, content); + + return messageNum > 0; + } + } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f11f2d7..0056a96 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,5 @@ -#spring.profiles.active = develop -spring.profiles.active = test +spring.profiles.active = develop +#spring.profiles.active = test #spring.profiles.active = produce # logback diff --git a/src/main/resources/mapper/message-mapper.xml b/src/main/resources/mapper/message-mapper.xml index 345d2b2..8ded1d1 100644 --- a/src/main/resources/mapper/message-mapper.xml +++ b/src/main/resources/mapper/message-mapper.xml @@ -146,4 +146,15 @@ + + + + + \ No newline at end of file -- Gitee From 6d36dce2964039c27ebe54621430d3fa3d455ef3 Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Sun, 6 Mar 2022 17:33:44 +0800 Subject: [PATCH 077/125] =?UTF-8?q?=E4=BF=AE=E6=94=B9AppConfig.java?= =?UTF-8?q?=E4=B8=ADenv=E5=8F=98=E9=87=8F=E8=AE=BE=E5=80=BC=E6=96=B9?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/greate/community/config/AppConfig.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/greate/community/config/AppConfig.java b/src/main/java/com/greate/community/config/AppConfig.java index 3327509..55f783e 100644 --- a/src/main/java/com/greate/community/config/AppConfig.java +++ b/src/main/java/com/greate/community/config/AppConfig.java @@ -2,14 +2,27 @@ package com.greate.community.config; import lombok.Data; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +import javax.annotation.PostConstruct; @Data @Slf4j @Configuration public class AppConfig { - @Value("${spring.profiles.active}") public static String env; + + private final Environment environment; + + public AppConfig(Environment environment) { + this.environment = environment; + } + + @PostConstruct + public void init() { + env=environment.getProperty("spring.profiles.active"); + log.info("spring.profiles.active: {}", env); + } } -- Gitee From 073fe5c4535efe3f0c2e221c6ded2961ebf0f479 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Sun, 6 Mar 2022 19:40:00 +0800 Subject: [PATCH 078/125] update save ticket --- src/main/java/com/greate/community/service/TicketService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/greate/community/service/TicketService.java b/src/main/java/com/greate/community/service/TicketService.java index f2cbd54..ed00c89 100644 --- a/src/main/java/com/greate/community/service/TicketService.java +++ b/src/main/java/com/greate/community/service/TicketService.java @@ -25,7 +25,7 @@ public class TicketService { loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000)); // 设置凭证到期时间 // 将登录凭证存入 redis - String redisKey = RedisKeyUtil.getTicketKey(loginTicket.getTicket()); + String redisKey = RedisKeyUtil.getTicketKey(String.valueOf(userId)); redisTemplate.opsForValue().set(redisKey, loginTicket); return loginTicket.getTicket(); -- Gitee From e152d7a2317996ac66faffe1a45b888a0041ac48 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Mon, 7 Mar 2022 15:55:10 +0800 Subject: [PATCH 079/125] update jwt --- pom.xml | 14 ++ .../community/controller/LoginController.java | 85 +++++----- .../community/controller/UserController.java | 15 +- .../greate/community/entity/LoginTicket.java | 18 --- .../community/entity/dto/EmailLoginDTO.java | 21 +++ .../filter/AuthenticationTokenFilter.java | 71 +++++---- .../greate/community/jwt/JwtTokenUtil.java | 145 ++++++++++++++++++ .../community/service/TicketService.java | 33 ---- .../greate/community/service/UserService.java | 71 ++++----- .../greate/community/util/RedisKeyUtil.java | 4 +- .../resources/application-develop.properties | 6 +- 11 files changed, 304 insertions(+), 179 deletions(-) delete mode 100644 src/main/java/com/greate/community/entity/LoginTicket.java create mode 100644 src/main/java/com/greate/community/entity/dto/EmailLoginDTO.java create mode 100644 src/main/java/com/greate/community/jwt/JwtTokenUtil.java delete mode 100644 src/main/java/com/greate/community/service/TicketService.java diff --git a/pom.xml b/pom.xml index fce4d14..40b02b3 100644 --- a/pom.xml +++ b/pom.xml @@ -119,6 +119,13 @@ 2.1.4.RELEASE + + + io.jsonwebtoken + jjwt + 0.9.1 + + com.alibaba @@ -187,6 +194,13 @@ test + + + javax.validation + validation-api + 2.0.1.Final + + diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index b10b455..d6d3719 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -9,8 +9,9 @@ import com.greate.community.dao.UserMapper; import com.greate.community.entity.Event; import com.greate.community.entity.Result; import com.greate.community.entity.User; +import com.greate.community.entity.dto.EmailLoginDTO; import com.greate.community.event.EventProducer; -import com.greate.community.service.TicketService; +import com.greate.community.jwt.JwtTokenUtil; import com.greate.community.service.UserService; import com.greate.community.util.CommunityConstant; import com.greate.community.util.ExpType; @@ -21,6 +22,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; @@ -38,9 +40,9 @@ import java.util.concurrent.TimeUnit; @RestController public class LoginController extends BaseController implements CommunityConstant { - private final UserService userService; + private final JwtTokenUtil jwtTokenUtil; - private final TicketService ticketService; + private final UserService userService; private final UserMapper userMapper; @@ -51,12 +53,16 @@ public class LoginController extends BaseController implements CommunityConstant @Value("${bbs.captcha-enable}") private boolean captchaEnable; - public LoginController(UserService userService, TicketService ticketService, UserMapper userMapper, RedisTemplate redisTemplate, EventProducer eventProducer) { + public LoginController(UserService userService, + UserMapper userMapper, + RedisTemplate redisTemplate, + EventProducer eventProducer, + JwtTokenUtil jwtTokenUtil) { this.userService = userService; - this.ticketService = ticketService; this.userMapper = userMapper; this.redisTemplate = redisTemplate; this.eventProducer = eventProducer; + this.jwtTokenUtil = jwtTokenUtil; } /** @@ -145,33 +151,27 @@ public class LoginController extends BaseController implements CommunityConstant * @return */ @PostMapping("/login") - public Result login(@RequestBody HashMap request) { - String email = (String) request.get("email"); - String password = (String) request.get("password"); - String code = (String) request.get("code"); - Boolean rememberMe = (Boolean) request.get("rememberMe"); - String captchaToken = (String) request.get("captchaToken"); - + public Result login(@RequestBody @Validated EmailLoginDTO emailLoginDTO) { // 检查验证码 if (captchaEnable) { String captcha = null; - if (StringUtils.isNotBlank(captchaToken)) { - String redisKey = RedisKeyUtil.getKaptchaKey(captchaToken); + if (StringUtils.isNotBlank(emailLoginDTO.getCaptchaToken())) { + String redisKey = RedisKeyUtil.getKaptchaKey(emailLoginDTO.getCaptchaToken()); captcha = (String) redisTemplate.opsForValue().get(redisKey); } - if (StringUtils.isBlank(captcha) || StringUtils.isBlank(code) || !captcha.equalsIgnoreCase(code)) { - + if (StringUtils.isBlank(captcha) || StringUtils.isBlank(emailLoginDTO.getCode()) || !captcha.equalsIgnoreCase(emailLoginDTO.getCode())) { return new Result("fail", "1", "验证码错误"); } } // 凭证过期时间(是否记住我) - int expiredSeconds = rememberMe ? REMEMBER_EXPIRED_SECONDS : DEFAULT_EXPIRED_SECONDS; +// int expiredSeconds = rememberMe ? REMEMBER_EXPIRED_SECONDS : DEFAULT_EXPIRED_SECONDS; + // 验证用户名和密码 - Map map = userService.loginByEmail(email, password, expiredSeconds); - if (map.containsKey("ticket")) { - String ticket = map.get("ticket").toString(); + Map map = userService.loginByEmail(emailLoginDTO); + if (map.containsKey("token")) { + String token = map.get("token").toString(); // 触发增加经验事件 Event event = new Event() @@ -180,7 +180,7 @@ public class LoginController extends BaseController implements CommunityConstant .setData("type", ExpType.EXP_LOGIN.getName()); eventProducer.fireEvent(event); - return new Result("success", Result.SUCCESS, ticket); + return new Result("success", Result.SUCCESS, token); } else { return new Result("fail", "2", map); } @@ -200,34 +200,37 @@ public class LoginController extends BaseController implements CommunityConstant // String email = "wechat@none.com"; //微信登录的用户,邮箱是一个特殊标识字符串 // 若微信用户对应的账号已存在,跳过模拟注册操作,直接进入登录过程 - User u = userMapper.selectByOpenid(openid); - User user = new User(); - if (u == null) { + User user = userMapper.selectByOpenid(openid); + User newUser = new User(); + if (user == null) { // 模拟注册操作 -// user.setUsername(username); -// user.setPassword(password); -// user.setEmail(email); - user.setType(0); // 默认普通用户 - user.setStatus(1); // 微信登录用户默认激活 - user.setLevel(0); // 等级默认0级 - user.setExp(0); // 经验0 - user.setLikeCount(0); // 点赞数量0 +// newUser.setUsername(username); +// newUser.setPassword(password); +// newUser.setEmail(email); + newUser.setType(0); // 默认普通用户 + newUser.setStatus(1); // 微信登录用户默认激活 + newUser.setLevel(0); // 等级默认0级 + newUser.setExp(0); // 经验0 + newUser.setLikeCount(0); // 点赞数量0 // 用户头像 - user.setHeaderUrl(headerUrl); // 微信头像地址 - user.setCreateTime(new Date()); // 注册时间 - user.setOpenid(openid); // 微信用户openid + newUser.setHeaderUrl(headerUrl); // 微信头像地址 + newUser.setCreateTime(new Date()); // 注册时间 + newUser.setOpenid(openid); // 微信用户openid - userMapper.insertUser(user); - user = userMapper.selectByOpenid(openid); + userMapper.insertUser(newUser); + newUser = userMapper.selectByOpenid(openid); } else { - user = u; + newUser = user; } - // 用户名和密码均正确,为该用户生成登录凭证 - String ticket = ticketService.saveTicket(user.getId(), DEFAULT_EXPIRED_SECONDS); + // 生成token并返回, 此时的username用邮箱代替 + String token = jwtTokenUtil.generateToken(String.valueOf(newUser.getId())); + + // 缓存token + redisTemplate.opsForValue().set(RedisKeyUtil.getTokenKey(String.valueOf(user.getId())), user, DEFAULT_EXPIRED_SECONDS); - response.sendRedirect("http://119.91.149.96:8080/?ticket=" + ticket); + response.sendRedirect("http://119.91.149.96:8080/?ticket=" + token); } /** diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 384ef03..00b815e 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -6,6 +6,7 @@ import com.greate.community.entity.*; import com.greate.community.service.*; import com.greate.community.util.CommunityConstant; import com.greate.community.util.CommunityUtil; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,18 +20,14 @@ import java.util.*; /** * 用户 */ +@Slf4j @RestController @RequestMapping("/user") public class UserController extends BaseController implements CommunityConstant { - private static final Logger logger = LoggerFactory.getLogger(UserController.class); - @Autowired private UserService userService; - @Autowired - private LikeService likeService; - @Autowired private FollowService followService; @@ -40,17 +37,13 @@ public class UserController extends BaseController implements CommunityConstant @Autowired private CommentService commentService; - // 项目名(访问路径) - @Value("${server.servlet.context-path}") - private String contextPath; - /** * 通过ticket获取user * * @return */ @GetMapping("/get") - public Result getUserByTicket() { + public Result getUserByToken() { JSONObject jsonObject = new JSONObject(); User user = getUser(); if (user == null) { @@ -125,7 +118,7 @@ public class UserController extends BaseController implements CommunityConstant } /** - * 获取用户信息 + * 获取其它用户信息 * * @param userId 可以进入任意用户的个人主页 * @return diff --git a/src/main/java/com/greate/community/entity/LoginTicket.java b/src/main/java/com/greate/community/entity/LoginTicket.java deleted file mode 100644 index e2116c7..0000000 --- a/src/main/java/com/greate/community/entity/LoginTicket.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.greate.community.entity; - -import com.greate.community.util.CommunityUtil; -import com.greate.community.util.RedisKeyUtil; -import lombok.Data; - -import java.util.Date; - -@Data -public class LoginTicket { - - private int id; - private int userId; - private String ticket; // 凭证 - private int status; // 状态(是否有效) - private Date expired; // 过期时间 - -} diff --git a/src/main/java/com/greate/community/entity/dto/EmailLoginDTO.java b/src/main/java/com/greate/community/entity/dto/EmailLoginDTO.java new file mode 100644 index 0000000..fd17486 --- /dev/null +++ b/src/main/java/com/greate/community/entity/dto/EmailLoginDTO.java @@ -0,0 +1,21 @@ +package com.greate.community.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +@Data +public class EmailLoginDTO { + + @NotBlank + private String email; + + @NotBlank + private String password; + + private String code; + + private Boolean rememberMe; + + private String captchaToken; +} diff --git a/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java b/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java index 7b6e8a2..c0eda3f 100644 --- a/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java +++ b/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java @@ -1,18 +1,17 @@ package com.greate.community.filter; import cn.hutool.extra.servlet.ServletUtil; -import com.greate.community.entity.LoginTicket; import com.greate.community.entity.User; import com.greate.community.entity.VisitData; -import com.greate.community.service.UserService; +import com.greate.community.jwt.JwtTokenUtil; import com.greate.community.service.VisitDataService; -import com.greate.community.util.HostHolder; +import com.greate.community.util.RedisKeyUtil; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.context.SecurityContextImpl; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; @@ -35,44 +34,52 @@ import java.util.Date; @Component public class AuthenticationTokenFilter extends OncePerRequestFilter { - private final UserService userService; + private final JwtTokenUtil jwtTokenUtil; private final VisitDataService visitDataService; + @Lazy + private final RedisTemplate redisTemplate; - public AuthenticationTokenFilter(UserService userService, VisitDataService visitDataService) { - this.userService = userService; + public AuthenticationTokenFilter(VisitDataService visitDataService, JwtTokenUtil jwtTokenUtil, RedisTemplate redisTemplate) { this.visitDataService = visitDataService; + this.jwtTokenUtil = jwtTokenUtil; + this.redisTemplate = redisTemplate; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - String ticket = request.getHeader("ticket"); log.info("request请求地址: path[{}] uri[{}] ip[{}]", request.getServletPath(), request.getRequestURI(), ServletUtil.getClientIP(request)); - log.info("获取ticket: " + ticket); + // 获取httpServletRequest中的请求头为“Authorization”的 token 值 + String httpHeader = request.getHeader(this.jwtTokenUtil.getTokenHeader()); + // 验证值是否为空且以tokenHead开头 + if (httpHeader != null && httpHeader.startsWith(this.jwtTokenUtil.getTokenHead())) { + // 截取tokenHead后面的值 + final String authToken = httpHeader.substring(this.jwtTokenUtil.getTokenHead().length()); + log.info("token:{}", authToken); + // 获取用户账号 + String userId = jwtTokenUtil.getUsernameFromToken(authToken); + log.info("JwtAuthenticationTokenFilter[doFilterInternal] checking authentication {} ", userId); + // 验证用户账号是否合法 + if (userId != null && SecurityContextHolder.getContext().getAuthentication() == null) { + // 根据account去缓存中查询user数据,足够信任token的情况下,可以省略这一步 + User user = (User) redisTemplate.opsForValue().get(RedisKeyUtil.getTokenKey(userId)); + if (user != null && jwtTokenUtil.validateToken(authToken, String.valueOf(user.getId()))) { +// UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( +// userDetails, null, userDetails.getAuthorities()); +// authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); +// log.info("authenticated user {} setting security context", account); +// SecurityContextHolder.getContext().setAuthentication(authentication); +// log.info("authenticated user {} setting security context finished", account); - VisitData visitData = new VisitData(); - visitData.setPath(request.getServletPath()); - visitData.setIp(ServletUtil.getClientIP(request)); - visitData.setCreateTime(new Date()); - - if (ticket != null) { - // 查询凭证 - LoginTicket loginTicket = userService.findLoginTicket(ticket); - // 检查凭证状态(是否有效)以及是否过期 - if (loginTicket != null && loginTicket.getStatus() == 0 && loginTicket.getExpired().after(new Date())) { - // 根据凭证查询用户 - User user = userService.findUserById(loginTicket.getUserId()); - log.info("用户会话信息: " + user.toString()); - visitData.setUserId(user.getId()); - // 构建用户认证的结果,并存入 SecurityContext, 以便于 Spring Security 进行授权 - Authentication authentication = new UsernamePasswordAuthenticationToken( - user, user.getPassword(), userService.getAuthorities(user.getId()) - ); - SecurityContextHolder.setContext(new SecurityContextImpl(authentication)); + VisitData visitData = new VisitData(); + visitData.setPath(request.getServletPath()); + visitData.setIp(ServletUtil.getClientIP(request)); + visitData.setCreateTime(new Date()); + visitData.setUserId(user.getId()); + visitDataService.addVisitData(visitData); + } } } - visitDataService.addVisitData(visitData); - filterChain.doFilter(request, response); } } diff --git a/src/main/java/com/greate/community/jwt/JwtTokenUtil.java b/src/main/java/com/greate/community/jwt/JwtTokenUtil.java new file mode 100644 index 0000000..10d8391 --- /dev/null +++ b/src/main/java/com/greate/community/jwt/JwtTokenUtil.java @@ -0,0 +1,145 @@ +package com.greate.community.jwt; + +import com.greate.community.util.RedisKeyUtil; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import lombok.Data; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +@Data +@ConfigurationProperties(prefix = "jwt") +@Component +public class JwtTokenUtil { + + private static final String CLAIM_KEY_USER_ACCOUNT = "sub"; + + private static final String CLAIM_KEY_CREATED = "created"; + + private String secret; // 秘钥 + + private Long expiration; // 过期时间 + + private String tokenHeader; + + private String tokenHead; + +// /** +// * 生成RedisKey +// * @param userId +// * @return +// */ +// public String generateRedisKey(String userId) { +// return RedisKeyUtil.getTicketKey(userId); +// } + + /** + * 从数据声明生成令牌 + * + * @param claims 数据声明 + * @return 令牌 + */ + private String generateToken(Map claims) { + Date expirationDate = new Date(System.currentTimeMillis() + expiration); + return Jwts.builder().setClaims(claims).setExpiration(expirationDate).signWith(SignatureAlgorithm.HS512, secret).compact(); + } + + /** + * 从令牌中获取数据声明 + * + * @param token 令牌 + * @return 数据声明 + */ + private Claims getClaimsFromToken(String token) { + Claims claims; + try { + claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody(); + } catch (Exception e) { + claims = null; + } + return claims; + } + + /** + * 生成令牌 + * + * @param userId 用户id + * @return 令牌 + */ + public String generateToken(String userId) { + Map claims = new HashMap<>(2); + claims.put(CLAIM_KEY_USER_ACCOUNT, userId); + claims.put(CLAIM_KEY_CREATED, new Date()); + return generateToken(claims); + } + + /** + * 从令牌中获取用户名 + * + * @param token 令牌 + * @return 用户名 + */ + public String getUsernameFromToken(String token) { + String username; + try { + Claims claims = getClaimsFromToken(token); + username = claims.getSubject(); + } catch (Exception e) { + username = null; + } + return username; + } + + /** + * 判断令牌是否过期 + * + * @param token 令牌 + * @return 是否过期 + */ + public Boolean isTokenExpired(String token) { + try { + Claims claims = getClaimsFromToken(token); + Date expiration = claims.getExpiration(); + return expiration.before(new Date()); + } catch (Exception e) { + return false; + } + } + + /** + * 刷新令牌 + * + * @param token 原令牌 + * @return 新令牌 + */ + public String refreshToken(String token) { + String refreshedToken; + try { + Claims claims = getClaimsFromToken(token); + claims.put(CLAIM_KEY_CREATED, new Date()); + refreshedToken = generateToken(claims); + } catch (Exception e) { + refreshedToken = null; + } + return refreshedToken; + } + + /** + * 验证令牌 + * + * @param token 令牌 + * @param testUsername 待验证的用户名 + * @return 是否有效 + */ + public Boolean validateToken(String token, String testUsername) { + String username = getUsernameFromToken(token); + return (username.equals(testUsername) && !isTokenExpired(token)); + } +} diff --git a/src/main/java/com/greate/community/service/TicketService.java b/src/main/java/com/greate/community/service/TicketService.java deleted file mode 100644 index ed00c89..0000000 --- a/src/main/java/com/greate/community/service/TicketService.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.greate.community.service; - -import com.greate.community.entity.LoginTicket; -import com.greate.community.util.CommunityUtil; -import com.greate.community.util.RedisKeyUtil; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Service; - -import java.util.Date; - -@Service -public class TicketService { - - private final RedisTemplate redisTemplate; - - public TicketService(RedisTemplate redisTemplate) { - this.redisTemplate = redisTemplate; - } - - public String saveTicket(int userId, int expiredSeconds) { - LoginTicket loginTicket = new LoginTicket(); - loginTicket.setUserId(userId); - loginTicket.setTicket(CommunityUtil.generateUUID()); // 随机凭证 - loginTicket.setStatus(0); // 设置凭证状态为有效(当用户登出的时候,设置凭证状态为无效) - loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000)); // 设置凭证到期时间 - - // 将登录凭证存入 redis - String redisKey = RedisKeyUtil.getTicketKey(String.valueOf(userId)); - redisTemplate.opsForValue().set(redisKey, loginTicket); - - return loginTicket.getTicket(); - } -} diff --git a/src/main/java/com/greate/community/service/UserService.java b/src/main/java/com/greate/community/service/UserService.java index fa3bd28..0f8470e 100644 --- a/src/main/java/com/greate/community/service/UserService.java +++ b/src/main/java/com/greate/community/service/UserService.java @@ -1,12 +1,12 @@ package com.greate.community.service; import com.greate.community.dao.UserMapper; -import com.greate.community.entity.LoginTicket; import com.greate.community.entity.User; +import com.greate.community.entity.dto.EmailLoginDTO; +import com.greate.community.jwt.JwtTokenUtil; import com.greate.community.util.*; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.core.GrantedAuthority; import org.springframework.stereotype.Service; @@ -22,19 +22,23 @@ import java.util.concurrent.TimeUnit; @Service public class UserService implements CommunityConstant { - final EmailUtil emailUtil; + private final EmailUtil emailUtil; + + private final JwtTokenUtil jwtTokenUtil; private final UserMapper userMapper; private final RedisTemplate redisTemplate; - private final TicketService ticketService; - public UserService(RedisTemplate redisTemplate, TicketService ticketService, EmailUtil emailUtil, UserMapper userMapper) { + public UserService(RedisTemplate redisTemplate, + EmailUtil emailUtil, + UserMapper userMapper, + JwtTokenUtil jwtTokenUtil) { this.redisTemplate = redisTemplate; - this.ticketService = ticketService; this.emailUtil = emailUtil; this.userMapper = userMapper; + this.jwtTokenUtil = jwtTokenUtil; } /** @@ -44,7 +48,6 @@ public class UserService implements CommunityConstant { * @return */ public User findUserById(int id) { - // return userMapper.selectById(id); User user = getCache(id); // 优先从缓存中查询数据 if (user == null) { user = initCache(id); @@ -72,6 +75,16 @@ public class UserService implements CommunityConstant { return userMapper.selectByName(username); } + /** + * 根据 email 查询用户 + * + * @param email + * @return + */ + public User findUserByEmail(String email) { + return userMapper.selectByEmail(email); + } + /** * 用户注册 * @@ -155,27 +168,12 @@ public class UserService implements CommunityConstant { /** * 用户邮箱登录(为用户创建凭证) - * - * @param email - * @param password - * @param expiredSeconds 多少秒后凭证过期 - * @return Map 返回错误提示消息以及 ticket(凭证) */ - public Map loginByEmail(String email, String password, int expiredSeconds) { + public Map loginByEmail(EmailLoginDTO emailLoginDTO) { Map map = new HashMap<>(); - // 空值处理 - if (StringUtils.isBlank(email)) { - map.put("usernameMsg", "邮箱不能为空"); - return map; - } - if (StringUtils.isBlank(password)) { - map.put("passwordMsg", "密码不能为空"); - return map; - } - // 验证账号 - User user = userMapper.selectByEmail(email); + User user = userMapper.selectByEmail(emailLoginDTO.getEmail()); if (user == null) { map.put("passwordMsg", "密码错误"); return map; @@ -189,15 +187,20 @@ public class UserService implements CommunityConstant { } // 验证密码 - password = CommunityUtil.md5(password + user.getSalt()); + String password = CommunityUtil.md5(emailLoginDTO.getPassword() + user.getSalt()); if (!user.getPassword().equals(password)) { map.put("passwordMsg", "密码错误"); return map; } - // 用户名和密码均正确,为该用户生成登录凭证 + // 生成token并返回, 此时的username用邮箱代替 + String token = jwtTokenUtil.generateToken(String.valueOf(user.getId())); + + // 缓存token + redisTemplate.opsForValue().set(RedisKeyUtil.getTokenKey(String.valueOf(user.getId())), user, DEFAULT_EXPIRED_SECONDS); + map.put("userId", user.getId()); - map.put("ticket", ticketService.saveTicket(user.getId(), expiredSeconds)); + map.put("token", token); return map; } @@ -208,25 +211,13 @@ public class UserService implements CommunityConstant { * @param ticket */ public void logout(String ticket) { - String redisKey = RedisKeyUtil.getTicketKey(ticket); + String redisKey = RedisKeyUtil.getTokenKey(ticket); // LoginTicket loginTicket = (LoginTicket) redisTemplate.opsForValue().get(redisKey); // loginTicket.setStatus(1); // redisTemplate.opsForValue().set(redisKey, loginTicket); redisTemplate.delete(redisKey); } - /** - * 根据 ticket 查询 LoginTicket 信息 - * - * @param ticket - * @return - */ - public LoginTicket findLoginTicket(String ticket) { - // return loginTicketMapper.selectByTicket(ticket); - String redisKey = RedisKeyUtil.getTicketKey(ticket); - return (LoginTicket) redisTemplate.opsForValue().get(redisKey); - } - /** * 修改用户头像 * diff --git a/src/main/java/com/greate/community/util/RedisKeyUtil.java b/src/main/java/com/greate/community/util/RedisKeyUtil.java index bad0a4f..73aea0f 100644 --- a/src/main/java/com/greate/community/util/RedisKeyUtil.java +++ b/src/main/java/com/greate/community/util/RedisKeyUtil.java @@ -11,7 +11,7 @@ public class RedisKeyUtil { private static final String PREFIX_FOLLOWER = "follower"; // 被关注(粉丝) private static final String PREFIX_FOLLOWEE = "followee"; // 关注的目标 private static final String PREFIX_KAPTCHA = "kaptcha"; // 验证码 - private static final String PREFIX_TICKET = "ticket"; // 登录凭证 + private static final String PREFIX_TICKET = "token"; // 登录凭证 private static final String PREFIX_USER = "user"; // 登录凭证 private static final String PREFIX_UV = "uv"; // 独立访客 private static final String PREFIX_DAU = "dau"; // 日活跃用户 @@ -71,7 +71,7 @@ public class RedisKeyUtil { * @param userId * @return */ - public static String getTicketKey(String userId) { + public static String getTokenKey(String userId) { return PREFIX_TICKET + SPLIT + userId; } diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index a665e92..c7f0cfa 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -13,8 +13,10 @@ community.path.domain = http://localhost:8080 # Editor.Md ͼƬϴ· community.path.editormdUploadPath = E:/GreateCommunity/src/main/resources/static/editor-md-upload -# Thymeleaf -spring.thymeleaf.cache=false +# JWT +jwt.token-header=Authorization +jwt.secret=yJleHAiOjE1NDMyMDUyODUsInN1YiI6ImFkbWluIiwiY3JlYXRlZCI6MTU0MDYxMzI4N +jwt.token-head=HUSTer_ # MySQL spring.datasource.url = jdbc:mysql://gz-cdb-ejk0kptx.sql.tencentcdb.com:57734/bbs-dev?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong -- Gitee From ab65484aec7de26cf49f7031010315a67a17e67a Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Mon, 7 Mar 2022 16:13:29 +0800 Subject: [PATCH 080/125] update jwt --- .../com/greate/community/controller/LoginController.java | 2 +- src/main/java/com/greate/community/jwt/JwtTokenUtil.java | 9 +++------ .../java/com/greate/community/service/UserService.java | 2 +- src/main/resources/application-develop.properties | 9 +++++++-- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index d6d3719..366c152 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -228,7 +228,7 @@ public class LoginController extends BaseController implements CommunityConstant String token = jwtTokenUtil.generateToken(String.valueOf(newUser.getId())); // 缓存token - redisTemplate.opsForValue().set(RedisKeyUtil.getTokenKey(String.valueOf(user.getId())), user, DEFAULT_EXPIRED_SECONDS); + redisTemplate.opsForValue().set(RedisKeyUtil.getTokenKey(String.valueOf(user.getId())), user, jwtTokenUtil.getExpiration()); response.sendRedirect("http://119.91.149.96:8080/?ticket=" + token); } diff --git a/src/main/java/com/greate/community/jwt/JwtTokenUtil.java b/src/main/java/com/greate/community/jwt/JwtTokenUtil.java index 10d8391..fdfc07b 100644 --- a/src/main/java/com/greate/community/jwt/JwtTokenUtil.java +++ b/src/main/java/com/greate/community/jwt/JwtTokenUtil.java @@ -1,13 +1,10 @@ package com.greate.community.jwt; -import com.greate.community.util.RedisKeyUtil; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import lombok.Data; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; import java.util.Date; @@ -23,9 +20,9 @@ public class JwtTokenUtil { private static final String CLAIM_KEY_CREATED = "created"; - private String secret; // 秘钥 + private int expiration = 3600 * 12; // 过期时间, 单位: 秒 - private Long expiration; // 过期时间 + private String secret; // 秘钥 private String tokenHeader; @@ -47,7 +44,7 @@ public class JwtTokenUtil { * @return 令牌 */ private String generateToken(Map claims) { - Date expirationDate = new Date(System.currentTimeMillis() + expiration); + Date expirationDate = new Date(System.currentTimeMillis() + expiration * 1000L); return Jwts.builder().setClaims(claims).setExpiration(expirationDate).signWith(SignatureAlgorithm.HS512, secret).compact(); } diff --git a/src/main/java/com/greate/community/service/UserService.java b/src/main/java/com/greate/community/service/UserService.java index 0f8470e..49686ac 100644 --- a/src/main/java/com/greate/community/service/UserService.java +++ b/src/main/java/com/greate/community/service/UserService.java @@ -197,7 +197,7 @@ public class UserService implements CommunityConstant { String token = jwtTokenUtil.generateToken(String.valueOf(user.getId())); // 缓存token - redisTemplate.opsForValue().set(RedisKeyUtil.getTokenKey(String.valueOf(user.getId())), user, DEFAULT_EXPIRED_SECONDS); + redisTemplate.opsForValue().set(RedisKeyUtil.getTokenKey(String.valueOf(user.getId())), user, jwtTokenUtil.getExpiration(), TimeUnit.SECONDS); map.put("userId", user.getId()); map.put("token", token); diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index c7f0cfa..b27992f 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -13,9 +13,15 @@ community.path.domain = http://localhost:8080 # Editor.Md ͼƬϴ· community.path.editormdUploadPath = E:/GreateCommunity/src/main/resources/static/editor-md-upload -# JWT +# Thymeleaf +spring.thymeleaf.cache=false + +### JWT?? jwt.token-header=Authorization +# ??????? jwt.secret=yJleHAiOjE1NDMyMDUyODUsInN1YiI6ImFkbWluIiwiY3JlYXRlZCI6MTU0MDYxMzI4N +# token expiration, 12hours +jwt.expiration=43200 jwt.token-head=HUSTer_ # MySQL @@ -62,7 +68,6 @@ elasticsearch.password = elastic2021. elasticsearch.hostname = es-50b9cgrk.public.tencentelasticsearch.com elasticsearch.port = 9200 elasticsearch.scheme = https -es.index-name.discuss-post = discuss-post-dev # Quartz spring.quartz.job-store-type = jdbc -- Gitee From 6da51b8b8872e81bb1e94cdfe3cdd326d80cac4a Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Mon, 7 Mar 2022 16:22:24 +0800 Subject: [PATCH 081/125] update jwt --- .../filter/AuthenticationTokenFilter.java | 25 +-- .../resources/application-develop.properties | 143 ++++++++---------- .../resources/application-test.properties | 143 ++++++++---------- src/main/resources/application.properties | 4 +- 4 files changed, 146 insertions(+), 169 deletions(-) diff --git a/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java b/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java index c0eda3f..4376b67 100644 --- a/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java +++ b/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java @@ -4,13 +4,17 @@ import cn.hutool.extra.servlet.ServletUtil; import com.greate.community.entity.User; import com.greate.community.entity.VisitData; import com.greate.community.jwt.JwtTokenUtil; +import com.greate.community.service.UserService; import com.greate.community.service.VisitDataService; import com.greate.community.util.RedisKeyUtil; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.context.SecurityContextImpl; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; @@ -34,15 +38,19 @@ import java.util.Date; @Component public class AuthenticationTokenFilter extends OncePerRequestFilter { + private final UserService userService; private final JwtTokenUtil jwtTokenUtil; private final VisitDataService visitDataService; - @Lazy private final RedisTemplate redisTemplate; - public AuthenticationTokenFilter(VisitDataService visitDataService, JwtTokenUtil jwtTokenUtil, RedisTemplate redisTemplate) { + public AuthenticationTokenFilter(VisitDataService visitDataService, + JwtTokenUtil jwtTokenUtil, + RedisTemplate redisTemplate, + UserService userService) { this.visitDataService = visitDataService; this.jwtTokenUtil = jwtTokenUtil; this.redisTemplate = redisTemplate; + this.userService = userService; } @Override @@ -60,15 +68,14 @@ public class AuthenticationTokenFilter extends OncePerRequestFilter { log.info("JwtAuthenticationTokenFilter[doFilterInternal] checking authentication {} ", userId); // 验证用户账号是否合法 if (userId != null && SecurityContextHolder.getContext().getAuthentication() == null) { - // 根据account去缓存中查询user数据,足够信任token的情况下,可以省略这一步 + // 根据userId去缓存中查询user数据 User user = (User) redisTemplate.opsForValue().get(RedisKeyUtil.getTokenKey(userId)); if (user != null && jwtTokenUtil.validateToken(authToken, String.valueOf(user.getId()))) { -// UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( -// userDetails, null, userDetails.getAuthorities()); -// authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); -// log.info("authenticated user {} setting security context", account); -// SecurityContextHolder.getContext().setAuthentication(authentication); -// log.info("authenticated user {} setting security context finished", account); + // 构建用户认证的结果,并存入 SecurityContext, 以便于 Spring Security 进行授权 + Authentication authentication = new UsernamePasswordAuthenticationToken( + user, user.getPassword(), userService.getAuthorities(user.getId()) + ); + SecurityContextHolder.setContext(new SecurityContextImpl(authentication)); VisitData visitData = new VisitData(); visitData.setPath(request.getServletPath()); diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index b27992f..7d5ee0c 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -1,108 +1,89 @@ # ???? -bbs.captcha-enable = false - +bbs.captcha-enable=false # ˿ -server.port = 8080 +server.port=8080 #server.port = 80 # Ŀ(Ŀ·) http://localhost:8080/...... -server.servlet.context-path = - +server.servlet.context-path= # վ -community.path.domain = http://localhost:8080 - +community.path.domain=http://localhost:8080 # Editor.Md ͼƬϴ· -community.path.editormdUploadPath = E:/GreateCommunity/src/main/resources/static/editor-md-upload - +community.path.editormdUploadPath=E:/GreateCommunity/src/main/resources/static/editor-md-upload # Thymeleaf spring.thymeleaf.cache=false - -### JWT?? +# JWT jwt.token-header=Authorization -# ??????? jwt.secret=yJleHAiOjE1NDMyMDUyODUsInN1YiI6ImFkbWluIiwiY3JlYXRlZCI6MTU0MDYxMzI4N -# token expiration, 12hours -jwt.expiration=43200 jwt.token-head=HUSTer_ - # MySQL -spring.datasource.url = jdbc:mysql://gz-cdb-ejk0kptx.sql.tencentcdb.com:57734/bbs-dev?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong -spring.datasource.username = root -spring.datasource.password = Root@2021 +spring.datasource.url=jdbc:mysql://gz-cdb-ejk0kptx.sql.tencentcdb.com:57734/bbs-dev?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong +spring.datasource.username=root +spring.datasource.password=Root@2021 # Mysql 5.0+ 汾ʹ com.mysql.jdbc.Driver # 8.0+ İ汾ij com.mysql.cj.jdbc.Driver -spring.datasource.driver-class-name = com.mysql.jdbc.Driver - +spring.datasource.driver-class-name=com.mysql.jdbc.Driver # Mybatis -mybatis.mapper-locations = classpath:mapper/*.xml -mybatis.type-aliases-package = com.greate.community.entity -mybatis.configuration.useGeneratedKeys = true -mybatis.configuration.mapUnderscoreToCamelCase = true - +mybatis.mapper-locations=classpath:mapper/*.xml +mybatis.type-aliases-package=com.greate.community.entity +mybatis.configuration.useGeneratedKeys=true +mybatis.configuration.mapUnderscoreToCamelCase=true # Spring Mail -spring.mail.host = smtp.qq.com -spring.mail.username = xuetao1999@vip.qq.com -spring.mail.personal = HUSTer -spring.mail.password = ttgqzosyzyjmdhja -spring.mail.protocol = smtps -spring.mail.properties.mail.smtp.ssl.enable = true +spring.mail.host=smtp.qq.com +spring.mail.username=xuetao1999@vip.qq.com +spring.mail.personal=HUSTer +spring.mail.password=ttgqzosyzyjmdhja +spring.mail.protocol=smtps +spring.mail.properties.mail.smtp.ssl.enable=true # ??????????????????? spring.mail.code-expiration=3600000 spring.mail.reg-header=Register spring.mail.forget-password-header=Register - # Redis -spring.redis.database = 3 -spring.redis.host = gz-crs-limbivl1.sql.tencentcdb.com -spring.redis.port = 21993 -spring.redis.password = root2021 - +spring.redis.database=3 +spring.redis.host=gz-crs-limbivl1.sql.tencentcdb.com +spring.redis.port=21993 +spring.redis.password=root2021 # Kafka -spring.kafka.bootstrap-servers = 159.75.254.198:9092 -spring.kafka.consumer.group-id = develop-consumer-group -spring.kafka.consumer.enable-auto-commit = true -spring.kafka.consumer.auto-commit-interval = 3000 - +spring.kafka.bootstrap-servers=159.75.254.198:9092 +spring.kafka.consumer.group-id=develop-consumer-group +spring.kafka.consumer.enable-auto-commit=true +spring.kafka.consumer.auto-commit-interval=3000 # Elasticsearch -elasticsearch.username = elastic -elasticsearch.password = elastic2021. -elasticsearch.hostname = es-50b9cgrk.public.tencentelasticsearch.com -elasticsearch.port = 9200 -elasticsearch.scheme = https - +elasticsearch.username=elastic +elasticsearch.password=elastic2021. +elasticsearch.hostname=es-50b9cgrk.public.tencentelasticsearch.com +elasticsearch.port=9200 +elasticsearch.scheme=https # Quartz -spring.quartz.job-store-type = jdbc -spring.quartz.scheduler-name = communityScheduler -spring.quartz.properties.org.quartz.scheduler.instanceId = AUTO -spring.quartz.properties.org.quartz.jobStore.class = org.springframework.scheduling.quartz.LocalDataSourceJobStore -spring.quartz.properties.org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate -spring.quartz.properties.org.quartz.jobStore.isClustered = true -spring.quartz.properties.org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool -spring.quartz.properties.org.quartz.threadPool.threadCount = 5 - +spring.quartz.job-store-type=jdbc +spring.quartz.scheduler-name=communityScheduler +spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO +spring.quartz.properties.org.quartz.jobStore.class=org.springframework.scheduling.quartz.LocalDataSourceJobStore +spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate +spring.quartz.properties.org.quartz.jobStore.isClustered=true +spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool +spring.quartz.properties.org.quartz.threadPool.threadCount=5 # tencent cos -tencent.secretId = AKID1rR2RcXCcmgMo1yf7LK34uUosgEXaPyI -tencent.secretKey = 5uUnpb8OO9gxyjEVVFjywd3EApDLCm6B - +tencent.secretId=AKID1rR2RcXCcmgMo1yf7LK34uUosgEXaPyI +tencent.secretKey=5uUnpb8OO9gxyjEVVFjywd3EApDLCm6B # Caffeine -caffeine.posts.max-size = 15 -caffeine.posts.expire-seconds = 180 - +caffeine.posts.max-size=15 +caffeine.posts.expire-seconds=180 # OAuth2 -wechat.client.clientId = wxa75d140e71f8903e -wechat.client.clientSecret = 2e6dbcad650a9fa495a762c0eb28906a -wechat.client.accessTokenUri = https://api.weixin.qq.com/sns/oauth2/access_token -wechat.client.userAuthorizationUri = https://open.weixin.qq.com/connect/oauth2/authorize -wechat.client.tokenName = access_token -wechat.client.authenticationScheme = query -wechat.client.clientAuthenticationScheme = form -wechat.client.scope = snsapi_userinfo -wechat.resource.userInfoUri = https://api.weixin.qq.com/sns/userinfo -wechat.config.app-id = appid -wechat.config.client-id = client_id -wechat.config.secret = secret -wechat.config.client-secret = client_secret -wechat.config.state = state -wechat.config.wechat-redirect = wechat_redirect - -logging.level.com.greate = debug -logging.level.org.springframework.security = DEBUG \ No newline at end of file +wechat.client.clientId=wxa75d140e71f8903e +wechat.client.clientSecret=2e6dbcad650a9fa495a762c0eb28906a +wechat.client.accessTokenUri=https://api.weixin.qq.com/sns/oauth2/access_token +wechat.client.userAuthorizationUri=https://open.weixin.qq.com/connect/oauth2/authorize +wechat.client.tokenName=access_token +wechat.client.authenticationScheme=query +wechat.client.clientAuthenticationScheme=form +wechat.client.scope=snsapi_userinfo +wechat.resource.userInfoUri=https://api.weixin.qq.com/sns/userinfo +wechat.config.app-id=appid +wechat.config.client-id=client_id +wechat.config.secret=secret +wechat.config.client-secret=client_secret +wechat.config.state=state +wechat.config.wechat-redirect=wechat_redirect +logging.level.com.greate=debug +logging.level.org.springframework.security=DEBUG \ No newline at end of file diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties index c9d1cf4..205272a 100644 --- a/src/main/resources/application-test.properties +++ b/src/main/resources/application-test.properties @@ -1,92 +1,81 @@ -bbs.captcha-enable = false - -server.port = 8080 -server.servlet.context-path = - -community.path.domain = http://localhost:8080 - -community.path.editormdUploadPath = E:/GreateCommunity/src/main/resources/static/editor-md-upload - +bbs.captcha-enable=false +server.port=8080 +server.servlet.context-path= +community.path.domain=http://localhost:8080 +community.path.editormdUploadPath=E:/GreateCommunity/src/main/resources/static/editor-md-upload # Thymeleaf spring.thymeleaf.cache=false - +# JWT +jwt.token-header=Authorization +jwt.secret=yJleHAiOjE1NDMyMDUyODUsInN1YiI6ImFkbWluIiwiY3JlYXRlZCI6MTU0MDYxMzI4N +jwt.token-head=HUSTer_ # MySQL -spring.datasource.url = jdbc:mysql://172.16.0.4:3306/bbs-test?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong -spring.datasource.username = root -spring.datasource.password = Root@2021 -spring.datasource.driver-class-name = com.mysql.jdbc.Driver - +spring.datasource.url=jdbc:mysql://172.16.0.4:3306/bbs-test?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong +spring.datasource.username=root +spring.datasource.password=Root@2021 +spring.datasource.driver-class-name=com.mysql.jdbc.Driver # Mybatis -mybatis.mapper-locations = classpath:mapper/*.xml -mybatis.type-aliases-package = com.greate.community.entity -mybatis.configuration.useGeneratedKeys = true -mybatis.configuration.mapUnderscoreToCamelCase = true - +mybatis.mapper-locations=classpath:mapper/*.xml +mybatis.type-aliases-package=com.greate.community.entity +mybatis.configuration.useGeneratedKeys=true +mybatis.configuration.mapUnderscoreToCamelCase=true # Spring Mail -spring.mail.host = smtp.qq.com -spring.mail.username = xuetao1999@vip.qq.com -spring.mail.personal = HUSTer -spring.mail.password = ttgqzosyzyjmdhja -spring.mail.protocol = smtps -spring.mail.properties.mail.smtp.ssl.enable = true +spring.mail.host=smtp.qq.com +spring.mail.username=xuetao1999@vip.qq.com +spring.mail.personal=HUSTer +spring.mail.password=ttgqzosyzyjmdhja +spring.mail.protocol=smtps +spring.mail.properties.mail.smtp.ssl.enable=true spring.mail.code-expiration=3600000 spring.mail.reg-header=Register spring.mail.forget-password-header=Register - # Redis -spring.redis.database = 2 -spring.redis.host = 172.16.0.10 -spring.redis.port = 6379 -spring.redis.password = root2021 - +spring.redis.database=2 +spring.redis.host=172.16.0.10 +spring.redis.port=6379 +spring.redis.password=root2021 # Kafka -spring.kafka.bootstrap-servers = localhost:9092 -spring.kafka.consumer.group-id = test-consumer-group -spring.kafka.consumer.enable-auto-commit = true -spring.kafka.consumer.auto-commit-interval = 3000 - +spring.kafka.bootstrap-servers=localhost:9092 +spring.kafka.consumer.group-id=test-consumer-group +spring.kafka.consumer.enable-auto-commit=true +spring.kafka.consumer.auto-commit-interval=3000 # Elasticsearch -elasticsearch.username = elastic -elasticsearch.password = elastic2021. -elasticsearch.hostname = 172.16.0.8 -elasticsearch.port = 9200 -elasticsearch.scheme = http -es.index-name.discuss-post = discuss-post-test - +elasticsearch.username=elastic +elasticsearch.password=elastic2021. +elasticsearch.hostname=172.16.0.8 +elasticsearch.port=9200 +elasticsearch.scheme=http +es.index-name.discuss-post=discuss-post-test # Quartz -spring.quartz.job-store-type = jdbc -spring.quartz.scheduler-name = communityScheduler -spring.quartz.properties.org.quartz.scheduler.instanceId = AUTO -spring.quartz.properties.org.quartz.jobStore.class = org.springframework.scheduling.quartz.LocalDataSourceJobStore -spring.quartz.properties.org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate -spring.quartz.properties.org.quartz.jobStore.isClustered = true -spring.quartz.properties.org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool -spring.quartz.properties.org.quartz.threadPool.threadCount = 5 - +spring.quartz.job-store-type=jdbc +spring.quartz.scheduler-name=communityScheduler +spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO +spring.quartz.properties.org.quartz.jobStore.class=org.springframework.scheduling.quartz.LocalDataSourceJobStore +spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate +spring.quartz.properties.org.quartz.jobStore.isClustered=true +spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool +spring.quartz.properties.org.quartz.threadPool.threadCount=5 # tencent cos -tencent.secretId = AKID1rR2RcXCcmgMo1yf7LK34uUosgEXaPyI -tencent.secretKey = 5uUnpb8OO9gxyjEVVFjywd3EApDLCm6B - +tencent.secretId=AKID1rR2RcXCcmgMo1yf7LK34uUosgEXaPyI +tencent.secretKey=5uUnpb8OO9gxyjEVVFjywd3EApDLCm6B # Caffeine -caffeine.posts.max-size = 15 -caffeine.posts.expire-seconds = 180 - +caffeine.posts.max-size=15 +caffeine.posts.expire-seconds=180 # OAuth2 ΢ŵ¼ -wechat.client.clientId = wxa75d140e71f8903e -wechat.client.clientSecret = 2e6dbcad650a9fa495a762c0eb28906a -wechat.client.accessTokenUri = https://api.weixin.qq.com/sns/oauth2/access_token -wechat.client.userAuthorizationUri = https://open.weixin.qq.com/connect/oauth2/authorize -wechat.client.tokenName = access_token -wechat.client.authenticationScheme = query -wechat.client.clientAuthenticationScheme = form -wechat.client.scope = snsapi_userinfo -wechat.resource.userInfoUri = https://api.weixin.qq.com/sns/userinfo -wechat.config.app-id = appid -wechat.config.client-id = client_id -wechat.config.secret = secret -wechat.config.client-secret = client_secret -wechat.config.state = state -wechat.config.wechat-redirect = wechat_redirect - -logging.level.com.greate = debug -logging.level.org.springframework.security = DEBUG \ No newline at end of file +wechat.client.clientId=wxa75d140e71f8903e +wechat.client.clientSecret=2e6dbcad650a9fa495a762c0eb28906a +wechat.client.accessTokenUri=https://api.weixin.qq.com/sns/oauth2/access_token +wechat.client.userAuthorizationUri=https://open.weixin.qq.com/connect/oauth2/authorize +wechat.client.tokenName=access_token +wechat.client.authenticationScheme=query +wechat.client.clientAuthenticationScheme=form +wechat.client.scope=snsapi_userinfo +wechat.resource.userInfoUri=https://api.weixin.qq.com/sns/userinfo +wechat.config.app-id=appid +wechat.config.client-id=client_id +wechat.config.secret=secret +wechat.config.client-secret=client_secret +wechat.config.state=state +wechat.config.wechat-redirect=wechat_redirect +logging.level.com.greate=debug +logging.level.org.springframework.security=DEBUG \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 0056a96..f11f2d7 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,5 @@ -spring.profiles.active = develop -#spring.profiles.active = test +#spring.profiles.active = develop +spring.profiles.active = test #spring.profiles.active = produce # logback -- Gitee From 4cb91a7a3685c487748cad60fcd75bad8506e431 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Mon, 7 Mar 2022 20:09:14 +0800 Subject: [PATCH 082/125] fix: user in redis problem --- .../community/controller/BaseController.java | 2 - .../controller/DiscussPostController.java | 6 --- .../community/controller/LoginController.java | 50 +++---------------- .../greate/community/service/UserService.java | 42 +++++++++++++--- .../greate/community/util/RedisKeyUtil.java | 2 +- .../resources/application-develop.properties | 1 - 6 files changed, 44 insertions(+), 59 deletions(-) diff --git a/src/main/java/com/greate/community/controller/BaseController.java b/src/main/java/com/greate/community/controller/BaseController.java index 0e6474c..a0a6b26 100644 --- a/src/main/java/com/greate/community/controller/BaseController.java +++ b/src/main/java/com/greate/community/controller/BaseController.java @@ -14,8 +14,6 @@ import org.springframework.security.core.context.SecurityContextHolder; public class BaseController { protected User getUser() { -// return (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); /** * 当未登录时,SecurityContextHolder.getContext().getAuthentication().getPrincipal()返回值 diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index 150d471..ed40ed3 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -29,9 +29,6 @@ public class DiscussPostController extends BaseController implements CommunityCo @Autowired private UserService userService; - @Autowired - private ExpService expService; - @Autowired private LikeService likeService; @@ -41,9 +38,6 @@ public class DiscussPostController extends BaseController implements CommunityCo @Autowired private RedisTemplate redisTemplate; - @Autowired - private ElasticsearchRestTemplate elasticsearchRestTemplate; - /** * 添加帖子(发帖) * diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index 366c152..17fe411 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -28,7 +28,6 @@ import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -114,7 +113,7 @@ public class LoginController extends BaseController implements CommunityConstant // 将验证码存入 redis String captchaToken = UUID.fastUUID().toString(); - String redisKey = RedisKeyUtil.getKaptchaKey(captchaToken); + String redisKey = RedisKeyUtil.getCaptchaKey(captchaToken); redisTemplate.opsForValue().set(redisKey, lineCaptcha.getCode(), 60, TimeUnit.SECONDS); JSONObject result = new JSONObject(); @@ -134,7 +133,7 @@ public class LoginController extends BaseController implements CommunityConstant if (StringUtils.isBlank(checkCode)) { return "未发现输入的图片验证码"; } - String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner); + String redisKey = RedisKeyUtil.getCaptchaKey(kaptchaOwner); String kaptchaValue = (String) redisTemplate.opsForValue().get(redisKey); if (StringUtils.isBlank(kaptchaValue)) { return "图片验证码过期"; @@ -156,7 +155,7 @@ public class LoginController extends BaseController implements CommunityConstant if (captchaEnable) { String captcha = null; if (StringUtils.isNotBlank(emailLoginDTO.getCaptchaToken())) { - String redisKey = RedisKeyUtil.getKaptchaKey(emailLoginDTO.getCaptchaToken()); + String redisKey = RedisKeyUtil.getCaptchaKey(emailLoginDTO.getCaptchaToken()); captcha = (String) redisTemplate.opsForValue().get(redisKey); } @@ -193,43 +192,7 @@ public class LoginController extends BaseController implements CommunityConstant */ @GetMapping("/wechat/login") public void wechatLogin(@AuthenticationPrincipal UserWeChat userWeChat, HttpServletResponse response) throws IOException { - String openid = userWeChat.getOpenId(); -// String username = userWeChat.getNickName(); //微信昵称 -// String password = CommunityUtil.generateUUID(); //随机密码,不能随便让人破解 - String headerUrl = userWeChat.getHeadimgurl(); //微信头像地址 -// String email = "wechat@none.com"; //微信登录的用户,邮箱是一个特殊标识字符串 - - // 若微信用户对应的账号已存在,跳过模拟注册操作,直接进入登录过程 - User user = userMapper.selectByOpenid(openid); - User newUser = new User(); - if (user == null) { - // 模拟注册操作 -// newUser.setUsername(username); -// newUser.setPassword(password); -// newUser.setEmail(email); - newUser.setType(0); // 默认普通用户 - newUser.setStatus(1); // 微信登录用户默认激活 - newUser.setLevel(0); // 等级默认0级 - newUser.setExp(0); // 经验0 - newUser.setLikeCount(0); // 点赞数量0 - - // 用户头像 - newUser.setHeaderUrl(headerUrl); // 微信头像地址 - newUser.setCreateTime(new Date()); // 注册时间 - newUser.setOpenid(openid); // 微信用户openid - - userMapper.insertUser(newUser); - newUser = userMapper.selectByOpenid(openid); - } else { - newUser = user; - } - - // 生成token并返回, 此时的username用邮箱代替 - String token = jwtTokenUtil.generateToken(String.valueOf(newUser.getId())); - - // 缓存token - redisTemplate.opsForValue().set(RedisKeyUtil.getTokenKey(String.valueOf(user.getId())), user, jwtTokenUtil.getExpiration()); - + String token = userService.loginByWechat(userWeChat); response.sendRedirect("http://119.91.149.96:8080/?ticket=" + token); } @@ -240,8 +203,9 @@ public class LoginController extends BaseController implements CommunityConstant */ @GetMapping("/logout") public Result logout(HttpServletRequest request) { - String ticket = request.getHeader("ticket"); - userService.logout(ticket); + if (getUser() != null) { + userService.logout(String.valueOf(getUser().getId())); + } SecurityContextHolder.clearContext(); return new Result("success", Result.SUCCESS, "退出成功"); } diff --git a/src/main/java/com/greate/community/service/UserService.java b/src/main/java/com/greate/community/service/UserService.java index 49686ac..6726ce8 100644 --- a/src/main/java/com/greate/community/service/UserService.java +++ b/src/main/java/com/greate/community/service/UserService.java @@ -1,5 +1,6 @@ package com.greate.community.service; +import com.greate.community.auth.wechatauth.domain.UserWeChat; import com.greate.community.dao.UserMapper; import com.greate.community.entity.User; import com.greate.community.entity.dto.EmailLoginDTO; @@ -205,16 +206,45 @@ public class UserService implements CommunityConstant { return map; } + public String loginByWechat(UserWeChat userWeChat) { + String openid = userWeChat.getOpenId(); + String headerUrl = userWeChat.getHeadimgurl(); //微信头像地址 + + // 若微信用户对应的账号已存在,跳过模拟注册操作,直接进入登录过程 + User user = userMapper.selectByOpenid(openid); + if (user == null) { + // 若不存在该微信用户,注册一个账号 + User newUser = new User(); + newUser.setType(0); // 默认普通用户 + newUser.setStatus(1); // 微信登录用户默认激活 + newUser.setLevel(0); // 等级默认0级 + newUser.setExp(0); // 经验0 + newUser.setLikeCount(0); // 点赞数量0 + + // 用户头像 + newUser.setHeaderUrl(headerUrl); // 微信头像地址 + newUser.setCreateTime(new Date()); // 注册时间 + newUser.setOpenid(openid); // 微信用户openid + + userMapper.insertUser(newUser); + user = userMapper.selectByOpenid(openid); + } + // 生成token并返回, 此时的username用邮箱代替 + String token = jwtTokenUtil.generateToken(String.valueOf(user.getId())); + + // 缓存token + redisTemplate.opsForValue().set(RedisKeyUtil.getTokenKey(String.valueOf(user.getId())), user, jwtTokenUtil.getExpiration(), TimeUnit.SECONDS); + + return token; + } + /** * 用户退出(删除缓存) * - * @param ticket + * @param userId */ - public void logout(String ticket) { - String redisKey = RedisKeyUtil.getTokenKey(ticket); -// LoginTicket loginTicket = (LoginTicket) redisTemplate.opsForValue().get(redisKey); -// loginTicket.setStatus(1); -// redisTemplate.opsForValue().set(redisKey, loginTicket); + public void logout(String userId) { + String redisKey = RedisKeyUtil.getTokenKey(userId); redisTemplate.delete(redisKey); } diff --git a/src/main/java/com/greate/community/util/RedisKeyUtil.java b/src/main/java/com/greate/community/util/RedisKeyUtil.java index 73aea0f..47d3b91 100644 --- a/src/main/java/com/greate/community/util/RedisKeyUtil.java +++ b/src/main/java/com/greate/community/util/RedisKeyUtil.java @@ -61,7 +61,7 @@ public class RedisKeyUtil { * 随机生成一个字符串,短暂的存入 cookie,使用这个字符串来标识这个用户 * @return */ - public static String getKaptchaKey(String owner) { + public static String getCaptchaKey(String owner) { return PREFIX_KAPTCHA + SPLIT + owner; } diff --git a/src/main/resources/application-develop.properties b/src/main/resources/application-develop.properties index 7d5ee0c..93234f7 100644 --- a/src/main/resources/application-develop.properties +++ b/src/main/resources/application-develop.properties @@ -34,7 +34,6 @@ spring.mail.personal=HUSTer spring.mail.password=ttgqzosyzyjmdhja spring.mail.protocol=smtps spring.mail.properties.mail.smtp.ssl.enable=true -# ??????????????????? spring.mail.code-expiration=3600000 spring.mail.reg-header=Register spring.mail.forget-password-header=Register -- Gitee From e919d46e52218ae5e8a375dcdfa9c0175a74cfb6 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Mon, 7 Mar 2022 23:05:08 +0800 Subject: [PATCH 083/125] fix: parse redis json --- .../community/CommunityApplication.java | 2 +- .../community/controller/BaseController.java | 6 +- .../controller/DiscussPostController.java | 7 +- .../controller/FollowController.java | 10 +- .../community/controller/LikeController.java | 4 +- .../controller/MessageController.java | 7 +- .../community/controller/UserController.java | 12 +-- .../filter/AuthenticationTokenFilter.java | 6 +- .../greate/community/jwt/JwtTokenUtil.java | 9 -- .../com/greate/community/jwt/JwtUser.java | 92 +++++++++++++++++++ .../greate/community/service/UserService.java | 9 +- src/main/resources/application.properties | 4 +- 12 files changed, 128 insertions(+), 40 deletions(-) create mode 100644 src/main/java/com/greate/community/jwt/JwtUser.java diff --git a/src/main/java/com/greate/community/CommunityApplication.java b/src/main/java/com/greate/community/CommunityApplication.java index 361e0ae..17532c6 100644 --- a/src/main/java/com/greate/community/CommunityApplication.java +++ b/src/main/java/com/greate/community/CommunityApplication.java @@ -23,7 +23,7 @@ public class CommunityApplication { } /** - * Sprintboot默认通过jackson来转换JSON,配置成以fastjson来转换JSON,以扫描@JSONField(serialize = false)注解, + * SpringBoot默认通过jackson来转换JSON,配置成以fastjson来转换JSON,以扫描@JSONField(serialize = false)注解, */ @Bean public HttpMessageConverters fastJsonHttpMessageConverters() { diff --git a/src/main/java/com/greate/community/controller/BaseController.java b/src/main/java/com/greate/community/controller/BaseController.java index a0a6b26..6886755 100644 --- a/src/main/java/com/greate/community/controller/BaseController.java +++ b/src/main/java/com/greate/community/controller/BaseController.java @@ -1,6 +1,6 @@ package com.greate.community.controller; -import com.greate.community.entity.User; +import com.greate.community.jwt.JwtUser; import org.springframework.security.core.context.SecurityContextHolder; /** @@ -13,7 +13,7 @@ import org.springframework.security.core.context.SecurityContextHolder; */ public class BaseController { - protected User getUser() { + protected JwtUser getUser() { Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); /** * 当未登录时,SecurityContextHolder.getContext().getAuthentication().getPrincipal()返回值 @@ -23,7 +23,7 @@ public class BaseController { return null; } else { - return (User) principal; + return (JwtUser) principal; } } } diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index ed40ed3..965c2b5 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -61,13 +61,12 @@ public class DiscussPostController extends BaseController implements CommunityCo picUrls = picUrls.substring(0, picUrls.length() - 1); } - User user = getUser(); - if (user == null) { + if (getUser() == null) { return new Result("forbidden", "403", "您还未登录"); } DiscussPost discussPost = new DiscussPost(); - discussPost.setUserId(user.getId()); + discussPost.setUserId(getUser().getId()); discussPost.setTitle(title); discussPost.setContent(content); discussPost.setPicUrls(picUrls); @@ -81,7 +80,7 @@ public class DiscussPostController extends BaseController implements CommunityCo // 触发发帖事件,通过消息队列将其存入 Elasticsearch 服务器 Event publishEvent = new Event() .setTopic(TOPIC_PUBLISH) - .setUserId(user.getId()) + .setUserId(getUser().getId()) .setEntityType(ENTITY_TYPE_POST) .setEntityId(discussPost.getId()); eventProducer.fireEvent(publishEvent); diff --git a/src/main/java/com/greate/community/controller/FollowController.java b/src/main/java/com/greate/community/controller/FollowController.java index 8f7a0ba..332dcad 100644 --- a/src/main/java/com/greate/community/controller/FollowController.java +++ b/src/main/java/com/greate/community/controller/FollowController.java @@ -6,6 +6,7 @@ import com.greate.community.entity.Page; import com.greate.community.entity.Result; import com.greate.community.entity.User; import com.greate.community.event.EventProducer; +import com.greate.community.jwt.JwtUser; import com.greate.community.service.FollowService; import com.greate.community.service.MessageService; import com.greate.community.service.UserService; @@ -51,7 +52,7 @@ public class FollowController extends BaseController implements CommunityConstan int entityType = map.get("entityType"); int entityId = map.get("entityId"); - User user = getUser(); + JwtUser user = getUser(); // followService.follow(user.getId(), entityType, entityId); @@ -89,15 +90,10 @@ public class FollowController extends BaseController implements CommunityConstan public Result unfollow(@RequestBody HashMap map) { int entityType = map.get("entityType"); int entityId = map.get("entityId"); - - User user = getUser(); - -// followService.unfollow(user.getId(), entityType, entityId); - boolean hasFollowed = hasFollowed(entityType, entityId);//判断当前登录用户是否关注该实体类型的实体id if(hasFollowed){ //已经关注该用户,执行取关操作 - followService.followOrUnfollow(user.getId(), entityType, entityId); + followService.followOrUnfollow(getUser().getId(), entityType, entityId); return new Result("success", Result.SUCCESS, "已取消关注"); }else{ diff --git a/src/main/java/com/greate/community/controller/LikeController.java b/src/main/java/com/greate/community/controller/LikeController.java index 4fc8746..39b3769 100644 --- a/src/main/java/com/greate/community/controller/LikeController.java +++ b/src/main/java/com/greate/community/controller/LikeController.java @@ -4,8 +4,10 @@ import com.greate.community.entity.Event; import com.greate.community.entity.Result; import com.greate.community.entity.User; import com.greate.community.event.EventProducer; +import com.greate.community.jwt.JwtUser; import com.greate.community.service.LikeService; import com.greate.community.util.*; +import io.jsonwebtoken.Jwt; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; @@ -47,7 +49,7 @@ public class LikeController extends BaseController implements CommunityConstant @PostMapping("/like") @ResponseBody public Result like(int entityType, int entityId, int entityUserId, int postId) { - User user = getUser(); + JwtUser user = getUser(); log.info("点赞用户: " + user.toString()); // 点赞 diff --git a/src/main/java/com/greate/community/controller/MessageController.java b/src/main/java/com/greate/community/controller/MessageController.java index 0889c48..031e2fe 100644 --- a/src/main/java/com/greate/community/controller/MessageController.java +++ b/src/main/java/com/greate/community/controller/MessageController.java @@ -3,6 +3,7 @@ package com.greate.community.controller; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.greate.community.entity.*; +import com.greate.community.jwt.JwtUser; import com.greate.community.service.CommentService; import com.greate.community.service.DiscussPostService; import com.greate.community.service.MessageService; @@ -69,7 +70,7 @@ public class MessageController extends BaseController implements CommunityConsta JSONObject jsonObject = new JSONObject(); // 获取当前登录用户信息 - User user = getUser(); + JwtUser user = getUser(); // 分页信息 page.setPath("/letter/list"); // 查询会话总数 @@ -228,7 +229,7 @@ public class MessageController extends BaseController implements CommunityConsta @GetMapping("/notice/list") public Result getNoticeList() { JSONObject jsonObject = new JSONObject(); - User user = getUser(); + JwtUser user = getUser(); // 查询评论类通知 Message message = messageService.findLatestNotice(user.getId(), TOPIC_COMMNET); @@ -320,7 +321,7 @@ public class MessageController extends BaseController implements CommunityConsta */ @GetMapping("/notice/detail/{topic}") public Result getNoticeDetail(@PathVariable("topic") String topic, Page page) { - User user = getUser(); + JwtUser user = getUser(); page.setPath("/notice/detail/" + topic); page.setRows(messageService.findNoticeCount(user.getId(), topic)); diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 00b815e..42c4d16 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -3,6 +3,7 @@ package com.greate.community.controller; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.greate.community.entity.*; +import com.greate.community.jwt.JwtUser; import com.greate.community.service.*; import com.greate.community.util.CommunityConstant; import com.greate.community.util.CommunityUtil; @@ -45,18 +46,17 @@ public class UserController extends BaseController implements CommunityConstant @GetMapping("/get") public Result getUserByToken() { JSONObject jsonObject = new JSONObject(); - User user = getUser(); - if (user == null) { + if (getUser() == null) { return new Result("fail", "1", "该用户不存在"); } // 用户 - jsonObject.put("user", user); + jsonObject.put("user", userService.findUserById(getUser().getId())); // 关注数量 - long followeeCount = followService.findFolloweeCount(user.getId(), ENTITY_TYPE_USER); + long followeeCount = followService.findFolloweeCount(getUser().getId(), ENTITY_TYPE_USER); jsonObject.put("followeeCount", followeeCount); // 粉丝数量 - long followerCount = followService.findFollowerCount(ENTITY_TYPE_USER, user.getId()); + long followerCount = followService.findFollowerCount(ENTITY_TYPE_USER, getUser().getId()); jsonObject.put("followerCount", followerCount); return new Result("success", Result.SUCCESS, jsonObject); @@ -99,7 +99,7 @@ public class UserController extends BaseController implements CommunityConstant @PostMapping("/password") public Result updatePassword(@RequestBody String oldPassword, @RequestBody String newPassword) { // 验证原密码是否正确 - User user = getUser(); + User user = userService.findUserById(getUser().getId()); String md5OldPassword = CommunityUtil.md5(oldPassword + user.getSalt()); if (!user.getPassword().equals(md5OldPassword)) { return new Result("fail", "1", "原密码错误"); diff --git a/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java b/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java index 4376b67..eb1239c 100644 --- a/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java +++ b/src/main/java/com/greate/community/filter/AuthenticationTokenFilter.java @@ -4,6 +4,7 @@ import cn.hutool.extra.servlet.ServletUtil; import com.greate.community.entity.User; import com.greate.community.entity.VisitData; import com.greate.community.jwt.JwtTokenUtil; +import com.greate.community.jwt.JwtUser; import com.greate.community.service.UserService; import com.greate.community.service.VisitDataService; import com.greate.community.util.RedisKeyUtil; @@ -69,12 +70,13 @@ public class AuthenticationTokenFilter extends OncePerRequestFilter { // 验证用户账号是否合法 if (userId != null && SecurityContextHolder.getContext().getAuthentication() == null) { // 根据userId去缓存中查询user数据 - User user = (User) redisTemplate.opsForValue().get(RedisKeyUtil.getTokenKey(userId)); + JwtUser user = (JwtUser) redisTemplate.opsForValue().get(RedisKeyUtil.getTokenKey(userId)); if (user != null && jwtTokenUtil.validateToken(authToken, String.valueOf(user.getId()))) { // 构建用户认证的结果,并存入 SecurityContext, 以便于 Spring Security 进行授权 - Authentication authentication = new UsernamePasswordAuthenticationToken( + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( user, user.getPassword(), userService.getAuthorities(user.getId()) ); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.setContext(new SecurityContextImpl(authentication)); VisitData visitData = new VisitData(); diff --git a/src/main/java/com/greate/community/jwt/JwtTokenUtil.java b/src/main/java/com/greate/community/jwt/JwtTokenUtil.java index fdfc07b..7e35d88 100644 --- a/src/main/java/com/greate/community/jwt/JwtTokenUtil.java +++ b/src/main/java/com/greate/community/jwt/JwtTokenUtil.java @@ -28,15 +28,6 @@ public class JwtTokenUtil { private String tokenHead; -// /** -// * 生成RedisKey -// * @param userId -// * @return -// */ -// public String generateRedisKey(String userId) { -// return RedisKeyUtil.getTicketKey(userId); -// } - /** * 从数据声明生成令牌 * diff --git a/src/main/java/com/greate/community/jwt/JwtUser.java b/src/main/java/com/greate/community/jwt/JwtUser.java new file mode 100644 index 0000000..86e60fe --- /dev/null +++ b/src/main/java/com/greate/community/jwt/JwtUser.java @@ -0,0 +1,92 @@ +package com.greate.community.jwt; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.greate.community.entity.User; +import lombok.Data; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; +import java.util.List; + +@Data +public class JwtUser implements UserDetails { + + private Integer id; + + private String username; + + @JsonIgnore + private String password; + + private Integer status; + + private Collection authorities; + + public JwtUser() { + } + + public JwtUser(Integer id, String username, String password, Integer status, Collection authorities) { + this.id = id; + this.username = username; + this.password = password; + this.status = status; + this.authorities = authorities; + } + + public static JwtUser build(User user) { + List authorities = null; + return new JwtUser(user.getId(), user.getUsername(), user.getPassword(), user.getStatus(), authorities); + } + + public void setAuthorities(Collection authorities) { + this.authorities = authorities; + } + + @Override + public Collection getAuthorities() { + return authorities; + } + + @JsonIgnore + @Override + public String getPassword() { + return this.password; + } + + @Override + public String getUsername() { + return this.username; + } + + //账户是否过期,过期无法验证 + @JsonIgnore + @Override + public boolean isAccountNonExpired() { + return true; + } + + //指定用户是否被锁定或者解锁,锁定的用户无法进行身份验证, 0.禁用 1.正常 2.被删除 + @JsonIgnore + @Override + public boolean isAccountNonLocked() { + if (status == null) { + return false; + } + return status==1; + } + + //指示是否已过期的用户的凭据(密码),过期的凭据防止认证 + @JsonIgnore + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + //是否被禁用,禁用的用户不能身份验证 + @JsonIgnore + @Override + public boolean isEnabled() { + return true; + } +} diff --git a/src/main/java/com/greate/community/service/UserService.java b/src/main/java/com/greate/community/service/UserService.java index 6726ce8..8226f30 100644 --- a/src/main/java/com/greate/community/service/UserService.java +++ b/src/main/java/com/greate/community/service/UserService.java @@ -5,6 +5,7 @@ import com.greate.community.dao.UserMapper; import com.greate.community.entity.User; import com.greate.community.entity.dto.EmailLoginDTO; import com.greate.community.jwt.JwtTokenUtil; +import com.greate.community.jwt.JwtUser; import com.greate.community.util.*; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -197,8 +198,10 @@ public class UserService implements CommunityConstant { // 生成token并返回, 此时的username用邮箱代替 String token = jwtTokenUtil.generateToken(String.valueOf(user.getId())); + JwtUser jwtUser = JwtUser.build(user); + // 缓存token - redisTemplate.opsForValue().set(RedisKeyUtil.getTokenKey(String.valueOf(user.getId())), user, jwtTokenUtil.getExpiration(), TimeUnit.SECONDS); + redisTemplate.opsForValue().set(RedisKeyUtil.getTokenKey(String.valueOf(user.getId())), jwtUser, jwtTokenUtil.getExpiration(), TimeUnit.SECONDS); map.put("userId", user.getId()); map.put("token", token); @@ -232,8 +235,10 @@ public class UserService implements CommunityConstant { // 生成token并返回, 此时的username用邮箱代替 String token = jwtTokenUtil.generateToken(String.valueOf(user.getId())); + JwtUser jwtUser = JwtUser.build(user); + // 缓存token - redisTemplate.opsForValue().set(RedisKeyUtil.getTokenKey(String.valueOf(user.getId())), user, jwtTokenUtil.getExpiration(), TimeUnit.SECONDS); + redisTemplate.opsForValue().set(RedisKeyUtil.getTokenKey(String.valueOf(user.getId())), jwtUser, jwtTokenUtil.getExpiration(), TimeUnit.SECONDS); return token; } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f11f2d7..0056a96 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,5 @@ -#spring.profiles.active = develop -spring.profiles.active = test +spring.profiles.active = develop +#spring.profiles.active = test #spring.profiles.active = produce # logback -- Gitee From a17e6f3e606380378941b16d61f39de524c608c7 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Tue, 8 Mar 2022 14:14:29 +0800 Subject: [PATCH 084/125] add verify user realname --- .../greate/community/config/QuartzConfig.java | 37 +++++++- .../greate/community/config/WebMvcConfig.java | 34 ------- .../community/controller/AuditController.java | 1 + .../controller/DiscussPostController.java | 94 +++++++++++++++++++ .../community/controller/IndexController.java | 84 ----------------- .../controller/SearchController.java | 79 ---------------- .../community/controller/UserController.java | 23 ++--- .../controller/advice/ExceptionAdvice.java | 36 ------- .../interceptor/DataInterceptor.java | 31 ------ .../com/greate/community/entity/User.java | 2 + .../community/quartz/PostScoreRefreshJob.java | 6 +- .../community/quartz/RealNameVerifyJob.java | 69 ++++++++++++++ .../service/ElasticsearchService.java | 15 +-- .../greate/community/service/UserService.java | 2 + .../greate/community/util/CommunityUtil.java | 63 ++++++++++--- .../greate/community/util/RedisKeyUtil.java | 12 ++- 16 files changed, 290 insertions(+), 298 deletions(-) delete mode 100644 src/main/java/com/greate/community/config/WebMvcConfig.java delete mode 100644 src/main/java/com/greate/community/controller/IndexController.java delete mode 100644 src/main/java/com/greate/community/controller/SearchController.java delete mode 100644 src/main/java/com/greate/community/controller/advice/ExceptionAdvice.java delete mode 100644 src/main/java/com/greate/community/controller/interceptor/DataInterceptor.java create mode 100644 src/main/java/com/greate/community/quartz/RealNameVerifyJob.java diff --git a/src/main/java/com/greate/community/config/QuartzConfig.java b/src/main/java/com/greate/community/config/QuartzConfig.java index f641dde..b9ea1e7 100644 --- a/src/main/java/com/greate/community/config/QuartzConfig.java +++ b/src/main/java/com/greate/community/config/QuartzConfig.java @@ -1,6 +1,7 @@ package com.greate.community.config; import com.greate.community.quartz.PostScoreRefreshJob; +import com.greate.community.quartz.RealNameVerifyJob; import org.quartz.JobDataMap; import org.quartz.JobDetail; import org.springframework.context.annotation.Bean; @@ -12,10 +13,11 @@ import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean; * Spring Quartz 配置类,用于将数据存入数据库,以后直接从数据库中调用数据 */ @Configuration -public class QuartzConfig { +public class QuartzConfig { /** * 刷新帖子分数任务 + * * @return */ @Bean @@ -31,6 +33,7 @@ public class QuartzConfig { /** * 刷新帖子分数触发器 + * * @return */ @Bean @@ -43,4 +46,36 @@ public class QuartzConfig { factoryBean.setJobDataMap(new JobDataMap()); return factoryBean; } + + /** + * 自动实名审核 + * + * @return + */ + @Bean + public JobDetailFactoryBean realNameVerifyJobDetail() { + JobDetailFactoryBean factoryBean = new JobDetailFactoryBean(); + factoryBean.setJobClass(RealNameVerifyJob.class); + factoryBean.setName("realNameVerifyJob"); + factoryBean.setGroup("communityJobGroup"); + factoryBean.setDurability(true); + factoryBean.setRequestsRecovery(true); + return factoryBean; + } + + /** + * 自动实名审核触发器 + * + * @return + */ + @Bean + public SimpleTriggerFactoryBean realNameVerifyTrigger(JobDetail realNameVerifyJobDetail) { + SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean(); + factoryBean.setJobDetail(realNameVerifyJobDetail); + factoryBean.setName("realNameVerifyTrigger"); + factoryBean.setGroup("communityTriggerGroup"); + factoryBean.setRepeatInterval(1000 * 60 * 60); // 每小时刷新一次 + factoryBean.setJobDataMap(new JobDataMap()); + return factoryBean; + } } diff --git a/src/main/java/com/greate/community/config/WebMvcConfig.java b/src/main/java/com/greate/community/config/WebMvcConfig.java deleted file mode 100644 index 19fc9f7..0000000 --- a/src/main/java/com/greate/community/config/WebMvcConfig.java +++ /dev/null @@ -1,34 +0,0 @@ -//package com.greate.community.config; -// -//import com.greate.community.controller.interceptor.DataInterceptor; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.context.annotation.Configuration; -//import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -//import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -// -///** -// * 拦截器配置类 -// */ -//@Configuration -//public class WebMvcConfig implements WebMvcConfigurer { -// -// @Autowired -// private DataInterceptor dataInterceptor; -// -// // 对除静态资源外所有路径进行拦截 -// @Override -// public void addInterceptors(InterceptorRegistry registry) { -// registry.addInterceptor(dataInterceptor) -// .excludePathPatterns("/css/**", "/js/**", "/img/**", "/editor-md/**", "/editor-md-upload/**"); -// } -// -// // 配置虚拟路径映射访问 -// @Override -// public void addResourceHandlers(ResourceHandlerRegistry registry){ -// // System.getProperty("user.dir") 获取程序的当前路径 -// String path = System.getProperty("user.dir")+"\\src\\main\\resources\\static\\editor-md-upload\\"; -// registry.addResourceHandler("/editor-md-upload/**").addResourceLocations("file:" + path); -// } -// -//} diff --git a/src/main/java/com/greate/community/controller/AuditController.java b/src/main/java/com/greate/community/controller/AuditController.java index 38865ca..795733a 100644 --- a/src/main/java/com/greate/community/controller/AuditController.java +++ b/src/main/java/com/greate/community/controller/AuditController.java @@ -24,6 +24,7 @@ import java.util.Map; */ @RestController public class AuditController { + @Autowired private UserService userService; diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index 965c2b5..2a8c356 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -23,6 +23,9 @@ import java.util.*; @RequestMapping("/discuss") public class DiscussPostController extends BaseController implements CommunityConstant { + @Autowired + private ElasticsearchService elasticsearchService; + @Autowired private DiscussPostService discussPostService; @@ -99,6 +102,54 @@ public class DiscussPostController extends BaseController implements CommunityCo return new Result("success", "200", "帖子发布成功," + "配图 " + picNum + " 张"); } + /** + * 查找首页帖子列表 + * @param model + * @param page + * @param orderMode 默认是 0(最新) + * @return + */ + @GetMapping("/index") + @ResponseBody + public Result getIndexPage(Model model, Page page, @RequestParam(name = "orderMode", defaultValue = "0") int orderMode) { + HashMap hashMap = new HashMap<>(); + + // 获取总页数 + page.setRows(discussPostService.findDiscussPostRows(0)); + page.setPath("/index?orderMode=" + orderMode); + + // 分页查询 + List list = discussPostService.findDiscussPosts(0, page.getOffset(), page.getLimit(), orderMode); + // 封装帖子和该帖子对应的用户信息 + List> discussPosts = new ArrayList<>(); + if (list != null) { + for (DiscussPost post : list) { + Map map = new HashMap<>(); + + //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 + map.put("post", discussPostService.toDiscussPostJsonObject(post)); + + User user = userService.findUserById(post.getUserId()); + map.put("user", user); + + // 当前登录用户对帖子的点赞状态 + int likeStatus = getUser() == null ? 0 : + likeService.findEntityLikeStatus(getUser().getId(), ENTITY_TYPE_POST, post.getId()); + map.put("likeStatus",likeStatus); + + discussPosts.add(map); + } + } +// hashMap.put("discussPosts", discussPosts); + JSONArray result = (JSONArray) JSONArray.toJSON(discussPosts); + page.setResult(result); + hashMap.put("discussPosts", page); + + hashMap.put("orderMode", orderMode); + + return new Result("success",Result.SUCCESS,hashMap); + } + /** * 进入帖子详情页 * @@ -145,6 +196,49 @@ public class DiscussPostController extends BaseController implements CommunityCo return new Result("success", Result.SUCCESS, resultMap); } + + /** + * 搜索 + * search?keword=xxx¤t=2&limit=2 + * @param keyword 关键词 + * @param page + * @return + */ + @PostMapping("/search") + public Result search(String keyword, Page page) { + JSONObject jsonObject = new JSONObject(); + // 搜索帖子 (Spring 提供的 Page 当前页码从 0 开始计数) + org.springframework.data.domain.Page searchResult = elasticsearchService.searchDiscussPost(keyword, page.getCurrent()-1, page.getLimit()); + // 聚合数据 + List> discussPosts = new ArrayList<>(); + if (searchResult != null) { + for (DiscussPost post : searchResult) { + Map map = new HashMap<>(); + // 帖子 + //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 + map.put("post", discussPostService.toDiscussPostJsonObject(post)); + + // 作者 + map.put("user", userService.findUserById(post.getUserId())); + // 点赞数量 + map.put("likeCount", likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId())); + + discussPosts.add(map); + } + } + + // 设置分页 + page.setPath("/search?keyword="+ keyword); + page.setRows(searchResult == null ? 0 : (int) searchResult.getTotalElements()); + + jsonObject.put("keyword", keyword); + JSONArray result = (JSONArray) JSONArray.toJSON(discussPosts); + page.setResult(result); + jsonObject.put("discussPosts", discussPosts); + + return new Result("success", Result.SUCCESS, jsonObject); + } + /** * 置顶帖子 * diff --git a/src/main/java/com/greate/community/controller/IndexController.java b/src/main/java/com/greate/community/controller/IndexController.java deleted file mode 100644 index 43a1921..0000000 --- a/src/main/java/com/greate/community/controller/IndexController.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.greate.community.controller; - -import com.alibaba.fastjson.JSONArray; -import com.greate.community.entity.DiscussPost; -import com.greate.community.entity.Page; -import com.greate.community.entity.Result; -import com.greate.community.entity.User; -import com.greate.community.service.DiscussPostService; -import com.greate.community.service.LikeService; -import com.greate.community.service.UserService; -import com.greate.community.util.CommunityConstant; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.*; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * 首页 - */ -@RestController -public class IndexController extends BaseController implements CommunityConstant { - - @Autowired - private DiscussPostService discussPostService; - - @Autowired - private UserService userService; - - @Autowired - private LikeService likeService; - - /** - * 进入首页 - * @param model - * @param page - * @param orderMode 默认是 0(最新) - * @return - */ - @GetMapping("/index") - @ResponseBody - public Result getIndexPage(Model model, Page page, @RequestParam(name = "orderMode", defaultValue = "0") int orderMode) { - HashMap hashMap = new HashMap<>(); - - // 获取总页数 - page.setRows(discussPostService.findDiscussPostRows(0)); - page.setPath("/index?orderMode=" + orderMode); - - // 分页查询 - List list = discussPostService.findDiscussPosts(0, page.getOffset(), page.getLimit(), orderMode); - // 封装帖子和该帖子对应的用户信息 - List> discussPosts = new ArrayList<>(); - if (list != null) { - for (DiscussPost post : list) { - Map map = new HashMap<>(); - - //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 - map.put("post", discussPostService.toDiscussPostJsonObject(post)); - - User user = userService.findUserById(post.getUserId()); - map.put("user", user); - - // 当前登录用户对帖子的点赞状态 - int likeStatus = getUser() == null ? 0 : - likeService.findEntityLikeStatus(getUser().getId(), ENTITY_TYPE_POST, post.getId()); - map.put("likeStatus",likeStatus); - - discussPosts.add(map); - } - } -// hashMap.put("discussPosts", discussPosts); - JSONArray result = (JSONArray) JSONArray.toJSON(discussPosts); - page.setResult(result); - hashMap.put("discussPosts", page); - - hashMap.put("orderMode", orderMode); - - return new Result("success",Result.SUCCESS,hashMap); - } - -} diff --git a/src/main/java/com/greate/community/controller/SearchController.java b/src/main/java/com/greate/community/controller/SearchController.java deleted file mode 100644 index 2e0a8e7..0000000 --- a/src/main/java/com/greate/community/controller/SearchController.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.greate.community.controller; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.greate.community.entity.DiscussPost; -import com.greate.community.entity.Page; -import com.greate.community.entity.Result; -import com.greate.community.service.DiscussPostService; -import com.greate.community.service.ElasticsearchService; -import com.greate.community.service.LikeService; -import com.greate.community.service.UserService; -import com.greate.community.util.CommunityConstant; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.*; - -/** - * 搜索 - */ -@RestController -public class SearchController extends BaseController implements CommunityConstant { - - @Autowired - private ElasticsearchService elasticsearchService; - - @Autowired - private UserService userService; - - @Autowired - private LikeService likeService; - - @Autowired - private DiscussPostService discussPostService; - - /** - * 搜索 - * search?keword=xxx¤t=2&limit=2 - * @param keyword 关键词 - * @param page - * @return - */ - @PostMapping("/search") - public Result search(String keyword, Page page) { - JSONObject jsonObject = new JSONObject(); - // 搜索帖子 (Spring 提供的 Page 当前页码从 0 开始计数) - org.springframework.data.domain.Page searchResult = elasticsearchService.searchDiscussPost(keyword, page.getCurrent()-1, page.getLimit()); - // 聚合数据 - List> discussPosts = new ArrayList<>(); - if (searchResult != null) { - for (DiscussPost post : searchResult) { - Map map = new HashMap<>(); - // 帖子 - //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 - map.put("post", discussPostService.toDiscussPostJsonObject(post)); - - // 作者 - map.put("user", userService.findUserById(post.getUserId())); - // 点赞数量 - map.put("likeCount", likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId())); - - discussPosts.add(map); - } - } - - // 设置分页 - page.setPath("/search?keyword="+ keyword); - page.setRows(searchResult == null ? 0 : (int) searchResult.getTotalElements()); - - jsonObject.put("keyword", keyword); - JSONArray result = (JSONArray) JSONArray.toJSON(discussPosts); - page.setResult(result); - jsonObject.put("discussPosts", discussPosts); - - return new Result("success", Result.SUCCESS, jsonObject); - } -} diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 42c4d16..7403ecb 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -178,17 +178,16 @@ public class UserController extends BaseController implements CommunityConstant // 封装帖子和该帖子对应的用户信息 List> discussPosts = new ArrayList<>(); if (list != null) { - for (DiscussPost post : list) { + list.forEach(discussPost -> { Map map = new HashMap<>(); // map.put("post", post); //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 - map.put("post", discussPostService.toDiscussPostJsonObject(post)); + map.put("post", discussPostService.toDiscussPostJsonObject(discussPost)); discussPosts.add(map); - } + }); } -// jsonObject.put("discussPosts", discussPosts); JSONArray result = (JSONArray) JSONArray.toJSON(discussPosts); page.setResult(result); jsonObject.put("discussPosts", page); @@ -224,14 +223,14 @@ public class UserController extends BaseController implements CommunityConstant // 封装评论和该评论对应的帖子信息 List> comments = new ArrayList<>(); if (list != null) { - for (Comment comment : list) { + list.forEach(comment -> { Map map = new HashMap<>(); // 显示评论/回复对应的文章信息 map.put("comment", comment); if (comment.getRootId() == 0) { // 如果是对帖子的评论 DiscussPost post = discussPostService.findDiscussPostById(comment.getPostId()); - //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 + // 将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 map.put("post", discussPostService.toDiscussPostJsonObject(post)); } else { JSONObject parent = new JSONObject(); @@ -243,12 +242,12 @@ public class UserController extends BaseController implements CommunityConstant map.put("parent", parent); DiscussPost post = discussPostService.findDiscussPostById(comment.getPostId()); - //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 + // 将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 map.put("post", discussPostService.toDiscussPostJsonObject(post)); } comments.add(map); - } + }); } JSONArray result = (JSONArray) JSONArray.toJSON(comments); @@ -269,10 +268,12 @@ public class UserController extends BaseController implements CommunityConstant if (user == null) { return new Result("fail", "1", "the request parameters are invalid"); } + // 已实名 + if (userService.findUserById(getUser().getId()).getAuditStatus() == 2) { + return new Result("success", Result.SUCCESS, "用户已实名"); + } - int userId = getUser().getId(); - user.setId(userId); - + user.setId(getUser().getId()); userService.updateRealNameInfo(user); return new Result("success", Result.SUCCESS, "用户实名信息更新成功"); } diff --git a/src/main/java/com/greate/community/controller/advice/ExceptionAdvice.java b/src/main/java/com/greate/community/controller/advice/ExceptionAdvice.java deleted file mode 100644 index e063c30..0000000 --- a/src/main/java/com/greate/community/controller/advice/ExceptionAdvice.java +++ /dev/null @@ -1,36 +0,0 @@ -//package com.greate.community.controller.advice; -// -//import com.greate.community.util.CommunityUtil; -//import org.slf4j.Logger; -//import org.slf4j.LoggerFactory; -//import org.springframework.stereotype.Controller; -//import org.springframework.web.bind.annotation.ControllerAdvice; -//import org.springframework.web.bind.annotation.ExceptionHandler; -//import org.springframework.web.bind.annotation.RestController; -// -//import javax.servlet.http.HttpServletRequest; -//import javax.servlet.http.HttpServletResponse; -//import java.io.IOException; -//import java.io.PrintWriter; -// -///** -// * 处理服务端异常(500) -// */ -//@ControllerAdvice(annotations = RestController.class) // 扫描带有 @RestController 的组件 -//public class ExceptionAdvice { -// -// private static final Logger logger = LoggerFactory.getLogger(ExceptionAdvice.class); -// -// @ExceptionHandler({Exception.class}) -// public void handleException(Exception e, HttpServletRequest request, HttpServletResponse response) throws IOException { -// logger.error("服务器发生异常:" + e.getMessage()); -// for (StackTraceElement element : e.getStackTrace()) { -// logger.error(element.toString()); -// } -// -// response.setContentType("application/plain;charset=utf-8"); -// PrintWriter writer = response.getWriter(); -// writer.write(CommunityUtil.getJSONString(500, "服务器异常: " + e.getMessage())); -// } -// -//} diff --git a/src/main/java/com/greate/community/controller/interceptor/DataInterceptor.java b/src/main/java/com/greate/community/controller/interceptor/DataInterceptor.java deleted file mode 100644 index 1075775..0000000 --- a/src/main/java/com/greate/community/controller/interceptor/DataInterceptor.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.greate.community.controller.interceptor; - -import com.greate.community.service.VisitDataService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.springframework.web.servlet.HandlerInterceptor; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -@Component -public class DataInterceptor implements HandlerInterceptor { - - @Autowired - private VisitDataService dataService; - - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - // 统计 UV -// String ip = request.getRemoteHost(); -// dataService.recordUV(ip); - - // 统计 DAU -// User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); -// if (user != null) { -// dataService.recordDAU(user.getId()); -// } - - return true; - } -} diff --git a/src/main/java/com/greate/community/entity/User.java b/src/main/java/com/greate/community/entity/User.java index 45fa369..788d426 100644 --- a/src/main/java/com/greate/community/entity/User.java +++ b/src/main/java/com/greate/community/entity/User.java @@ -20,6 +20,7 @@ public class User { private String email; private int exp; private int level; + // 0-用户; 1-超级管理员; 2-管理员; 3-huster private int type; private int status; private String activationCode; @@ -29,6 +30,7 @@ public class User { private String realName; private String institute; private String professionalClass; + // 审核状态,0-未实名,1-未审核,2-审核通过,3-审核驳回 private int auditStatus; private int likeCount; private Date createTime; diff --git a/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java b/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java index a2c88f9..38ee082 100644 --- a/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java +++ b/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java @@ -52,15 +52,15 @@ public class PostScoreRefreshJob implements Job, CommunityConstant { BoundSetOperations operations = redisTemplate.boundSetOps(redisKey); if (operations.size() == 0) { - logger.info("[任务取消] 没有需要刷新的帖子"); + logger.info("[Post Score Job Execution] no post need refresh"); return ; } - logger.info("[任务开始] 正在刷新帖子分数: " + operations.size()); + logger.info("[Post Score Job Execution] refresh post score start: " + operations.size()); while (operations.size() > 0) { this.refresh((Integer) operations.pop()); } - logger.info("[任务结束] 帖子分数刷新完毕"); + logger.info("[Post Score Job Execution] refresh post score over"); } /** diff --git a/src/main/java/com/greate/community/quartz/RealNameVerifyJob.java b/src/main/java/com/greate/community/quartz/RealNameVerifyJob.java new file mode 100644 index 0000000..2e8dec2 --- /dev/null +++ b/src/main/java/com/greate/community/quartz/RealNameVerifyJob.java @@ -0,0 +1,69 @@ +package com.greate.community.quartz; + +import com.greate.community.entity.User; +import com.greate.community.service.UserService; +import com.greate.community.util.CommunityUtil; +import com.greate.community.util.RedisKeyUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.BoundSetOperations; +import org.springframework.data.redis.core.RedisTemplate; + +@Slf4j +public class RealNameVerifyJob implements Job { + + @Autowired + private RedisTemplate redisTemplate; + + @Autowired + private UserService userService; + + @Override + public void execute(JobExecutionContext context) throws JobExecutionException { + log.info("执行实名审核任务"); + // 检查实名 + String redisKey = RedisKeyUtil.getRealNameKey(); + BoundSetOperations operations = redisTemplate.boundSetOps(redisKey); + if (operations == null || operations.size() == 0) { + log.info("[RealName Verify Job Execution] no user need verify"); + return ; + } + + log.info("[RealName Verify Job Execution] verify user start"); + while (operations.size() > 0) { + this.checkRealName((Integer) operations.pop()); + } + log.info("[RealName Verify Job Execution] verify user over"); + } + + public void checkRealName(int userId) { + User user = userService.findUserById(userId); + if (user == null || user.getAuditStatus() == 2) { + return; + } + + // 字段为空不通过 + if (StringUtils.isBlank(user.getStudentCardUrl()) || + StringUtils.isBlank(user.getStudentCode()) || + StringUtils.isBlank(user.getRealName()) || + StringUtils.isBlank(user.getInstitute()) || + StringUtils.isBlank(user.getProfessionalClass())) { + log.info("[RealName Verify Job Execution] reject user: {}", userId); + userService.updateAuditStatus(userId, 3); + return; + } + + // 检查学号 + if (CommunityUtil.checkStudentId(user.getStudentCode())) { + log.info("[RealName Verify Job Execution] accept user: {}", userId); + userService.updateAuditStatus(userId, 2); + } else { + log.info("[RealName Verify Job Execution] reject user: {}", userId); + userService.updateAuditStatus(userId, 3); + } + } +} diff --git a/src/main/java/com/greate/community/service/ElasticsearchService.java b/src/main/java/com/greate/community/service/ElasticsearchService.java index e8694da..a183572 100644 --- a/src/main/java/com/greate/community/service/ElasticsearchService.java +++ b/src/main/java/com/greate/community/service/ElasticsearchService.java @@ -34,14 +34,14 @@ public class ElasticsearchService { private ElasticsearchRestTemplate elasticsearchRestTemplate; @PostConstruct - public void initEs(){ - //初始化es服务器,如果无 discusspost 索引,则创建索引 + public void initEs() { + // 初始化es服务器,如果无 discuss-post 索引,则创建索引 if (!elasticsearchRestTemplate.indexOps(DiscussPost.class).exists()) { + log.info("es have no discuss-post index, create it"); elasticsearchRestTemplate.indexOps(DiscussPost.class).create(); elasticsearchRestTemplate.indexOps(DiscussPost.class).putMapping(); - log.info("es服务器无 discusspost 索引,创建该索引"); - }else { - log.info("es服务器存在 discusspost 索引,无需创建该索引"); + } else { + log.info("es have discuss-post index, do nothing"); } } @@ -56,6 +56,7 @@ public class ElasticsearchService { /** * 从 Elasticsearch 服务器上查找数据 + * * @param id * @return */ @@ -106,8 +107,8 @@ public class ElasticsearchService { //高亮的内容 Map> highlightFields = productSearchHit.getHighlightFields(); //将高亮的内容填充到content中 - productSearchHit.getContent().setTitle(highlightFields.get("title")==null ? productSearchHit.getContent().getTitle():highlightFields.get("title").get(0)); - productSearchHit.getContent().setContent(highlightFields.get("content")==null ? productSearchHit.getContent().getContent():highlightFields.get("content").get(0)); + productSearchHit.getContent().setTitle(highlightFields.get("title") == null ? productSearchHit.getContent().getTitle() : highlightFields.get("title").get(0)); + productSearchHit.getContent().setContent(highlightFields.get("content") == null ? productSearchHit.getContent().getContent() : highlightFields.get("content").get(0)); //放到实体类中 content.add(productSearchHit.getContent()); } diff --git a/src/main/java/com/greate/community/service/UserService.java b/src/main/java/com/greate/community/service/UserService.java index 8226f30..11f0928 100644 --- a/src/main/java/com/greate/community/service/UserService.java +++ b/src/main/java/com/greate/community/service/UserService.java @@ -479,6 +479,8 @@ public class UserService implements CommunityConstant { * @return */ public int updateRealNameInfo(User user) { + String redisKey = RedisKeyUtil.getRealNameKey(); + redisTemplate.opsForSet().add(redisKey, user.getId()); return userMapper.updateRealNameInfo(user); } diff --git a/src/main/java/com/greate/community/util/CommunityUtil.java b/src/main/java/com/greate/community/util/CommunityUtil.java index 2785023..4b19754 100644 --- a/src/main/java/com/greate/community/util/CommunityUtil.java +++ b/src/main/java/com/greate/community/util/CommunityUtil.java @@ -6,14 +6,14 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import org.springframework.util.DigestUtils; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; +import java.util.*; +import java.util.regex.Pattern; public class CommunityUtil { /** * 生成随机字符串 + * * @return */ public static String generateUUID() { @@ -23,21 +23,23 @@ public class CommunityUtil { /** * md5 加密 + * * @param key 要加密的字符串 * @return */ public static String md5(String key) { if (StringUtils.isBlank(key)) { - return null; + return null; } return DigestUtils.md5DigestAsHex(key.getBytes()); } /** * 将服务端返回的消息封装成 JSON 格式的字符串 + * * @param code 状态码 - * @param msg 提示消息 - * @param map 业务数据 + * @param msg 提示消息 + * @param map 业务数据 * @return 返回 JSON 格式字符串 */ public static String getJSONString(int code, String msg, Map map) { @@ -84,17 +86,56 @@ public class CommunityUtil { return Integer.toString(codeNum); } + /** + * 检查学生id + * + * @param studentId 学生id + */ + public static boolean checkStudentId(String studentId) { + // 长度为10 + if (studentId.length() != 10) { + return false; + } + char firstChar = studentId.charAt(1); + if (firstChar == 'u' || firstChar == 'U' || + firstChar == 'm' || firstChar == 'M' || + firstChar == 'x' || firstChar == 'X' || + firstChar == 'd' || firstChar == 'D') { + return false; + } + + // 最后 9 位是数字 + String digitStr = studentId.substring(1); + if (!Pattern.compile("^[-\\+]?[\\d]*$").matcher(digitStr).matches()) { + return false; + } + + // 学号年份大于今年 + int year = Integer.parseInt(digitStr.substring(0, 4)); + if (year > Calendar.getInstance().get(Calendar.YEAR)) { + return false; + } + + return true; + } + /** * 测试 + * * @param args */ public static void main(String[] args) { - Map map = new HashMap<>(); - map.put("name", "Jack"); - map.put("age", 18); +// Map map = new HashMap<>(); +// map.put("name", "Jack"); +// map.put("age", 18); // {"msg":"ok","code":0,"name":"Jack","age":18} - System.out.println(getJSONString(0, "ok", map)); + System.out.println(Calendar.getInstance().get(Calendar.YEAR)); + System.out.println(checkStudentId("M202173802")); + System.out.println(checkStudentId("m202173802")); + System.out.println(checkStudentId("U20217382")); + System.out.println(checkStudentId("U202273802")); + System.out.println(checkStudentId("U205573802")); + System.out.println(checkStudentId("x202173802")); } - } diff --git a/src/main/java/com/greate/community/util/RedisKeyUtil.java b/src/main/java/com/greate/community/util/RedisKeyUtil.java index 47d3b91..0155177 100644 --- a/src/main/java/com/greate/community/util/RedisKeyUtil.java +++ b/src/main/java/com/greate/community/util/RedisKeyUtil.java @@ -10,12 +10,13 @@ public class RedisKeyUtil { private static final String PREFIX_USER_LIKE = "like:user"; // 用户的获赞 private static final String PREFIX_FOLLOWER = "follower"; // 被关注(粉丝) private static final String PREFIX_FOLLOWEE = "followee"; // 关注的目标 - private static final String PREFIX_KAPTCHA = "kaptcha"; // 验证码 + private static final String PREFIX_KAPTCHA = "captcha"; // 验证码 private static final String PREFIX_TICKET = "token"; // 登录凭证 private static final String PREFIX_USER = "user"; // 登录凭证 private static final String PREFIX_UV = "uv"; // 独立访客 private static final String PREFIX_DAU = "dau"; // 日活跃用户 private static final String PREFIX_POST = "post"; // 用于统计帖子分数 + private static final String PREFIX_REAL_NAME = "realName"; // 用于实名审核 /** * 某个实体点过赞的 userId @@ -135,4 +136,13 @@ public class RedisKeyUtil { public static String getPostScoreKey() { return PREFIX_POST + SPLIT + "score"; } + + /** + * 实名审核 + * + * @return + */ + public static String getRealNameKey() { + return PREFIX_REAL_NAME; + } } -- Gitee From 8cca333e93a0f9c92da4cb09521bb17a7bc125d0 Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Tue, 8 Mar 2022 18:12:30 +0800 Subject: [PATCH 085/125] =?UTF-8?q?=E5=B8=96=E5=AD=90=E7=83=AD=E5=BA=A6?= =?UTF-8?q?=E7=AE=97=E6=B3=95=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/quartz/PostScoreRefreshJob.java | 98 ++++++++++++++++--- src/main/resources/application.properties | 4 +- 2 files changed, 89 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java b/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java index a2c88f9..f650376 100644 --- a/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java +++ b/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java @@ -3,9 +3,11 @@ package com.greate.community.quartz; import com.greate.community.entity.DiscussPost; import com.greate.community.service.DiscussPostService; import com.greate.community.service.ElasticsearchService; +import com.greate.community.service.FollowService; import com.greate.community.service.LikeService; import com.greate.community.util.CommunityConstant; import com.greate.community.util.RedisKeyUtil; +import org.apache.commons.lang3.StringUtils; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; @@ -14,6 +16,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.BoundSetOperations; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.web.util.HtmlUtils; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -35,6 +38,9 @@ public class PostScoreRefreshJob implements Job, CommunityConstant { @Autowired private ElasticsearchService elasticsearchService; + @Autowired + private FollowService followService; + // Epoch 纪元 private static final Date epoch; @@ -75,23 +81,93 @@ public class PostScoreRefreshJob implements Job, CommunityConstant { return ; } - // 是否加精 +// // 是否加精 +// boolean wonderful = post.getStatus() == 1; +// // 评论数量 +// int commentCount = post.getCommentCount(); +// // 点赞数量 +// long likeCount = post.getLikeCount(); +// +// // 计算权重 +// double w = (wonderful ? 75 : 0) + commentCount * 10 + likeCount * 2; +// // 分数 = 权重 + 发帖距离天数 +// double score = Math.log10(Math.max(w, 1)) +// + (post.getCreateTime().getTime() - epoch.getTime()) / (1000 * 3600 * 24); +// // 更新帖子分数 +// discussPostService.updateScore(postId, score); +// // 同步搜索数据 +// post.setScore(score); +// elasticsearchService.saveDiscussPost(post); + + + //还要考虑内容长度质量因素、配图数量等 + //发帖作者 + int userId = post.getUserId(); + //关注该发帖作者的粉丝数量 + long followerCount = followService.findFollowerCount(3, userId); + //帖子是否加精 boolean wonderful = post.getStatus() == 1; - // 评论数量 + //帖子评论数量 int commentCount = post.getCommentCount(); - // 点赞数量 + //帖子点赞数量 long likeCount = post.getLikeCount(); + //帖子浏览量 + int viewCount = post.getViewCount(); + //帖子创建时间 + long createTime = post.getCreateTime().getTime(); + //当前时间 + long now = System.currentTimeMillis(); + + String content = HtmlUtils.htmlUnescape(post.getContent()); + //帖子内容长度,最好还是要统计热门词汇数量 + int wordNums = content.length(); + String pic_urls = post.getPicUrls(); + //帖子配图数量 + int picNums = StringUtils.countMatches(pic_urls,"https://"); + + /** + * 初始热度值,与最后的热度值H呈 正相关 (不是正比), + * 根据发帖作者的 粉丝数量、帖子内容、帖子配图 来计算 + */ + double H_init = followerCount*4 + picNums*8 + (wordNums/50)*5; + /** + * 互动热度值,与最后的热度值H呈 负相关 (不是反比), + * 根据该帖子 是否加精、浏览量、点赞数、评论数 来计算 + */ + double H_interact = (wonderful ? 100 : 0) + viewCount*2 + likeCount*3 + commentCount*5; + /** + * 时间衰减因子,即 现在距帖子发布时间的时间距离,以小时计,在计算热度值H时加1是为了 + * 防止最新发表的会导致分母过小 ,这个值可调,在前期平台人数较少时调整大 + * 一些,在后期人数增长起来后,可以调整的小一些,比如,因为用户对平 + * 台资源有一个消化时间。并不是一发出来就有数据的 + */ + double H_time = (now - createTime) / (1000 * 3600); + /** + * 重力因子,它决定了热度随时间下降的速度,前期平台人员较少时,相对应得 + * 发的资源也会比较少,这时可以把G调小一点,减缓时间推移对热度下降的影响, + * 后期平台人员增多时,相对应的资源也会增加,这时可以把G调大一点,加速时间 + * 推移对热度下降的影响。比如:1.2-1.8 + */ + double G = 0.8; + if(H_init >= 200) + G = 0.9; + if(G == 0.9 && H_interact >= 200) + G = 0.95; + /** + * 加减权重,初始值可以为0,在某些偶然或者极端情况下需要人为 + * 干预的时候,可以动态调整其值,使其能够及时的控制其热度 + */ + double Hweight = 0; + + /** + * 热度值计算 + */ + double H_score = ((H_init + H_interact)/Math.pow(H_time + 1, G)) + Hweight; - // 计算权重 - double w = (wonderful ? 75 : 0) + commentCount * 10 + likeCount * 2; - // 分数 = 权重 + 发帖距离天数 - double score = Math.log10(Math.max(w, 1)) - + (post.getCreateTime().getTime() - epoch.getTime()) / (1000 * 3600 * 24); // 更新帖子分数 - discussPostService.updateScore(postId, score); + discussPostService.updateScore(postId, H_score); // 同步搜索数据 - post.setScore(score); + post.setScore(H_score); elasticsearchService.saveDiscussPost(post); - } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f11f2d7..0056a96 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,5 @@ -#spring.profiles.active = develop -spring.profiles.active = test +spring.profiles.active = develop +#spring.profiles.active = test #spring.profiles.active = produce # logback -- Gitee From 4eb04cf0a36828bdfdd6cfb2a47f7cee0fc64a57 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Wed, 9 Mar 2022 17:32:04 +0800 Subject: [PATCH 086/125] add dockerfile --- Dockerfile | 16 ++++++++++ pom.xml | 29 +++++++++++++------ .../controller/DiscussPostController.java | 3 +- .../community/quartz/RealNameVerifyJob.java | 1 - .../resources/application-test.properties | 2 +- 5 files changed, 38 insertions(+), 13 deletions(-) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..30da6d1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM java:8 +#作者 +MAINTAINER mono +#声明一个挂载点,容器内此路径会对应宿主机的某个文件夹 +VOLUME /tmp +#复制上下文目录下的target/demo-1.0.0.jar 到容器里 +COPY target/hust-bbs-0.0.1-SNAPSHOT.jar hust-bbs.jar + +#bash方式执行,使hust-bbs.jar可访问 +#RUN新建立一层,在其上执行这些命令,执行结束后, commit 这一层的修改,构成新的镜像。 +RUN bash -c "touch /hust-bbs.jar" + +#指定容器启动程序及参数 "" +ENTRYPOINT ["java","-jar","hust-bbs.jar"] + +EXPOSE 8080 \ No newline at end of file diff --git a/pom.xml b/pom.xml index 40b02b3..14324e2 100644 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,7 @@ 1.8 + mono @@ -71,13 +72,6 @@ spring-boot-starter-mail - - - com.github.penggle - kaptcha - 2.3.2 - - @@ -204,7 +198,7 @@ - hust-bbs + hust-bbs-${project.version} org.springframework.boot @@ -227,7 +221,24 @@ true + + + com.spotify + docker-maven-plugin + 1.0.0 + + ${docker.image.prefix}/${project.artifactId} + src/main/docker + + + / + ${project.build.directory} + ${project.build.finalName}.jar + + + + + - diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index 2a8c356..18138ed 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -104,14 +104,13 @@ public class DiscussPostController extends BaseController implements CommunityCo /** * 查找首页帖子列表 - * @param model * @param page * @param orderMode 默认是 0(最新) * @return */ @GetMapping("/index") @ResponseBody - public Result getIndexPage(Model model, Page page, @RequestParam(name = "orderMode", defaultValue = "0") int orderMode) { + public Result getIndexPage(Page page, @RequestParam(name = "orderMode", defaultValue = "0") int orderMode) { HashMap hashMap = new HashMap<>(); // 获取总页数 diff --git a/src/main/java/com/greate/community/quartz/RealNameVerifyJob.java b/src/main/java/com/greate/community/quartz/RealNameVerifyJob.java index 2e8dec2..4364445 100644 --- a/src/main/java/com/greate/community/quartz/RealNameVerifyJob.java +++ b/src/main/java/com/greate/community/quartz/RealNameVerifyJob.java @@ -24,7 +24,6 @@ public class RealNameVerifyJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { - log.info("执行实名审核任务"); // 检查实名 String redisKey = RedisKeyUtil.getRealNameKey(); BoundSetOperations operations = redisTemplate.boundSetOps(redisKey); diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties index 205272a..120d2aa 100644 --- a/src/main/resources/application-test.properties +++ b/src/main/resources/application-test.properties @@ -35,7 +35,7 @@ spring.redis.host=172.16.0.10 spring.redis.port=6379 spring.redis.password=root2021 # Kafka -spring.kafka.bootstrap-servers=localhost:9092 +spring.kafka.bootstrap-servers=localhost:9093 spring.kafka.consumer.group-id=test-consumer-group spring.kafka.consumer.enable-auto-commit=true spring.kafka.consumer.auto-commit-interval=3000 -- Gitee From fd89b16e5a37b362756cf6a46748db792dcfdf2c Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Thu, 10 Mar 2022 13:35:02 +0800 Subject: [PATCH 087/125] fix some bugs --- .../java/com/greate/community/quartz/PostScoreRefreshJob.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java b/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java index b59b1d3..738d2c6 100644 --- a/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java +++ b/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java @@ -100,7 +100,6 @@ public class PostScoreRefreshJob implements Job, CommunityConstant { // elasticsearchService.saveDiscussPost(post); - //还要考虑内容长度质量因素、配图数量等 //发帖作者 int userId = post.getUserId(); //关注该发帖作者的粉丝数量 @@ -149,6 +148,7 @@ public class PostScoreRefreshJob implements Job, CommunityConstant { * 推移对热度下降的影响。比如:1.2-1.8 */ double G = 0.8; + //视不同情况,增大重力因子G,加速帖子热度下降 if(H_init >= 200) G = 0.9; if(G == 0.9 && H_interact >= 200) -- Gitee From 1a538a854852bb4e3a38b454aba4c45b1d85ce83 Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Thu, 10 Mar 2022 17:15:37 +0800 Subject: [PATCH 088/125] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=B8=96=E5=AD=90?= =?UTF-8?q?=E5=88=86=E6=95=B0=E5=88=B7=E6=96=B0=E8=A7=A6=E5=8F=91=E6=9D=A1?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/DiscussPostController.java | 12 +++++++---- .../community/controller/LikeController.java | 9 +++++++-- .../community/quartz/PostScoreRefreshJob.java | 20 +++++++++---------- .../community/service/DiscussPostService.java | 20 +++++++++++++++++++ 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index 18138ed..de75f0a 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -96,8 +96,9 @@ public class DiscussPostController extends BaseController implements CommunityCo eventProducer.fireEvent(expEvent); // 计算帖子分数 - String redisKey = RedisKeyUtil.getPostScoreKey(); - redisTemplate.opsForSet().add(redisKey, discussPost.getId()); +// String redisKey = RedisKeyUtil.getPostScoreKey(); +// redisTemplate.opsForSet().add(redisKey, discussPost.getId()); + return new Result("success", "200", "帖子发布成功," + "配图 " + picNum + " 张"); } @@ -192,6 +193,8 @@ public class DiscussPostController extends BaseController implements CommunityCo // 增加帖子浏览量 discussPostService.viewPost(discussPost.getId()); + discussPostService.addDisscussPostToRefreshScore(discussPost.getId()); + return new Result("success", Result.SUCCESS, resultMap); } @@ -283,8 +286,9 @@ public class DiscussPostController extends BaseController implements CommunityCo eventProducer.fireEvent(event); // 计算帖子分数 - String redisKey = RedisKeyUtil.getPostScoreKey(); - redisTemplate.opsForSet().add(redisKey, id); +// String redisKey = RedisKeyUtil.getPostScoreKey(); +// redisTemplate.opsForSet().add(redisKey, id); + discussPostService.addDisscussPostToRefreshScore(id); return new Result("success", Result.SUCCESS, ""); } diff --git a/src/main/java/com/greate/community/controller/LikeController.java b/src/main/java/com/greate/community/controller/LikeController.java index 39b3769..262c403 100644 --- a/src/main/java/com/greate/community/controller/LikeController.java +++ b/src/main/java/com/greate/community/controller/LikeController.java @@ -5,6 +5,7 @@ import com.greate.community.entity.Result; import com.greate.community.entity.User; import com.greate.community.event.EventProducer; import com.greate.community.jwt.JwtUser; +import com.greate.community.service.DiscussPostService; import com.greate.community.service.LikeService; import com.greate.community.util.*; import io.jsonwebtoken.Jwt; @@ -37,6 +38,9 @@ public class LikeController extends BaseController implements CommunityConstant @Autowired private RedisTemplate redisTemplate; + @Autowired + private DiscussPostService discussPostService; + /** * 点赞 * @@ -88,8 +92,9 @@ public class LikeController extends BaseController implements CommunityConstant if (entityType == ENTITY_TYPE_POST) { // 计算帖子分数 - String redisKey = RedisKeyUtil.getPostScoreKey(); - redisTemplate.opsForSet().add(redisKey, postId); +// String redisKey = RedisKeyUtil.getPostScoreKey(); +// redisTemplate.opsForSet().add(redisKey, postId); + discussPostService.addDisscussPostToRefreshScore(postId); } return new Result("success", Result.SUCCESS, map); diff --git a/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java b/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java index 738d2c6..a73eb6c 100644 --- a/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java +++ b/src/main/java/com/greate/community/quartz/PostScoreRefreshJob.java @@ -41,16 +41,16 @@ public class PostScoreRefreshJob implements Job, CommunityConstant { @Autowired private FollowService followService; - // Epoch 纪元 - private static final Date epoch; - - static { - try { - epoch = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2014-01-01 00:00:00"); - } catch (ParseException e) { - throw new RuntimeException("初始化 Epoch 纪元失败", e); - } - } +// // Epoch 纪元 +// private static final Date epoch; +// +// static { +// try { +// epoch = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2014-01-01 00:00:00"); +// } catch (ParseException e) { +// throw new RuntimeException("初始化 Epoch 纪元失败", e); +// } +// } @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { diff --git a/src/main/java/com/greate/community/service/DiscussPostService.java b/src/main/java/com/greate/community/service/DiscussPostService.java index 3e787d1..222dcfa 100644 --- a/src/main/java/com/greate/community/service/DiscussPostService.java +++ b/src/main/java/com/greate/community/service/DiscussPostService.java @@ -7,6 +7,7 @@ import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; import com.greate.community.dao.DiscussPostMapper; import com.greate.community.entity.DiscussPost; +import com.greate.community.util.RedisKeyUtil; import com.greate.community.util.SensitiveFilter; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -14,6 +15,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.web.util.HtmlUtils; @@ -35,6 +37,9 @@ public class DiscussPostService { @Autowired private SensitiveFilter sensitiveFilter; + @Autowired + private RedisTemplate redisTemplate; + @Value("${caffeine.posts.max-size}") private int maxSize; @@ -246,4 +251,19 @@ public class DiscussPostService { public int viewPost(int id) { return discussPostMapper.addViewCount(id,1); } + + /** + * 将 postId 添加到 Redis 集合中,以便定时任务刷新帖子分数 + * + * @param postId + * @return + */ + public void addDisscussPostToRefreshScore(int postId){ + String redisKey = RedisKeyUtil.getPostScoreKey(); + + boolean postInSet = redisTemplate.opsForSet().isMember(redisKey, postId); + if( ! postInSet ){ + redisTemplate.opsForSet().add(redisKey, postId); + } + } } -- Gitee From b885024d93610cec41b20ec16a42aecf3e923012 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Fri, 11 Mar 2022 15:21:10 +0800 Subject: [PATCH 089/125] fix: discuss post controller --- Dockerfile | 16 +-- pom.xml | 13 ++- .../community/config/SecurityConfig.java | 19 ++-- .../controller/DiscussPostController.java | 98 +++++++++---------- .../greate/community/entity/DiscussPost.java | 2 +- .../community/entity/dto/AddPostDTO.java | 20 ++++ .../greate/community/event/EventConsumer.java | 3 - .../exception/GlobalExceptionHandler.java | 29 ++++++ .../community/service/DiscussPostService.java | 2 +- .../service/ElasticsearchService.java | 9 +- .../resources/mapper/discusspost-mapper.xml | 6 +- 11 files changed, 130 insertions(+), 87 deletions(-) create mode 100644 src/main/java/com/greate/community/entity/dto/AddPostDTO.java create mode 100644 src/main/java/com/greate/community/exception/GlobalExceptionHandler.java diff --git a/Dockerfile b/Dockerfile index 30da6d1..334dfea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,16 +1,16 @@ FROM java:8 -#作者 +# 作者 MAINTAINER mono -#声明一个挂载点,容器内此路径会对应宿主机的某个文件夹 +# 声明一个挂载点,容器内此路径会对应宿主机的某个文件夹 VOLUME /tmp -#复制上下文目录下的target/demo-1.0.0.jar 到容器里 -COPY target/hust-bbs-0.0.1-SNAPSHOT.jar hust-bbs.jar +#复 制target/demo-1.0.0.jar 到容器里 +COPY target/hust-bbs.jar hust-bbs.jar -#bash方式执行,使hust-bbs.jar可访问 -#RUN新建立一层,在其上执行这些命令,执行结束后, commit 这一层的修改,构成新的镜像。 +# bash方式执行,使hust-bbs.jar可访问 +# RUN新建立一层,在其上执行这些命令,执行结束后, commit 这一层的修改,构成新的镜像。 RUN bash -c "touch /hust-bbs.jar" -#指定容器启动程序及参数 "" +# 指定容器启动程序及参数 "" ENTRYPOINT ["java","-jar","hust-bbs.jar"] -EXPOSE 8080 \ No newline at end of file +EXPOSE 8081 8080 diff --git a/pom.xml b/pom.xml index 14324e2..8d7de09 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.greate community - 0.0.1-SNAPSHOT + 0.0.1 community hust bbs jar @@ -189,6 +189,10 @@ + + org.springframework.boot + spring-boot-starter-validation + javax.validation validation-api @@ -198,7 +202,7 @@ - hust-bbs-${project.version} + hust-bbs org.springframework.boot @@ -227,8 +231,11 @@ docker-maven-plugin 1.0.0 + + ${project.version} + + ${docker.image.prefix}/${project.artifactId} - src/main/docker / diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index a983b66..ac34700 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -74,9 +74,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm "/user/updateHeader", "/letter/**", "/notice/**", - "/like", - "/follow", - "/unfollow", "/exp/**", "/cos/credential", "/message/unread" @@ -88,8 +85,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm AUTHORITY_HUSTER ) .antMatchers( + "/like", + "/follow", + "/unfollow", "/discuss/add", - "/comment/add" + "/comment/add", + "/discuss/delete/**" ) .hasAnyAuthority( AUTHORITY_ADMIN, @@ -98,18 +99,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm ) .antMatchers( "/discuss/top", - "/discuss/wonderful" - ) - .hasAnyAuthority( - AUTHORITY_MODERATOR - ) - .antMatchers( - "/discuss/delete", - "/discuss/delete/", + "/discuss/disable/**", "/data/**", "/admin/**" ) .hasAnyAuthority( + AUTHORITY_MODERATOR, AUTHORITY_ADMIN ) .anyRequest().permitAll(); diff --git a/src/main/java/com/greate/community/controller/DiscussPostController.java b/src/main/java/com/greate/community/controller/DiscussPostController.java index de75f0a..8b395ec 100644 --- a/src/main/java/com/greate/community/controller/DiscussPostController.java +++ b/src/main/java/com/greate/community/controller/DiscussPostController.java @@ -4,21 +4,30 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.greate.community.entity.*; +import com.greate.community.entity.dto.AddPostDTO; import com.greate.community.event.EventProducer; import com.greate.community.service.*; import com.greate.community.util.*; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.ui.Model; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.util.HtmlUtils; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; import java.util.*; +import java.util.stream.Collectors; /** * 帖子 */ +@Validated @RestController @RequestMapping("/discuss") public class DiscussPostController extends BaseController implements CommunityConstant { @@ -38,31 +47,20 @@ public class DiscussPostController extends BaseController implements CommunityCo @Autowired private EventProducer eventProducer; - @Autowired - private RedisTemplate redisTemplate; - /** * 添加帖子(发帖) * * @return */ @PostMapping("/add") - public Result addDiscussPost(@RequestBody HashMap map) { - String title = (String) map.get("title"); - String content = (String) map.get("content"); - List picUrlList = (List) map.get("picUrls"); - - String picUrls = ""; - int picNum = 0; - - if (picUrlList != null && picUrlList.size() != 0) { - for (String picUrl : picUrlList) { - picUrls = picUrls + picUrl + ","; - picNum++; - } - //删除最后一个 , - picUrls = picUrls.substring(0, picUrls.length() - 1); - } + public Result addDiscussPost(@RequestBody @Validated AddPostDTO addPostDTO) { + String title = addPostDTO.getTitle(); + String content = addPostDTO.getContent(); + List picUrlList = addPostDTO.getPicUrls(); + + List filter = picUrlList.stream().filter(url -> !StringUtils.isBlank(url)).collect(Collectors.toList()); + + String picUrls = StringListConvertor.join(filter); if (getUser() == null) { return new Result("forbidden", "403", "您还未登录"); @@ -99,12 +97,12 @@ public class DiscussPostController extends BaseController implements CommunityCo // String redisKey = RedisKeyUtil.getPostScoreKey(); // redisTemplate.opsForSet().add(redisKey, discussPost.getId()); - - return new Result("success", "200", "帖子发布成功," + "配图 " + picNum + " 张"); + return new Result("success", "200", "帖子发布成功," + "配图 " + filter.size() + " 张"); } /** * 查找首页帖子列表 + * * @param page * @param orderMode 默认是 0(最新) * @return @@ -112,7 +110,7 @@ public class DiscussPostController extends BaseController implements CommunityCo @GetMapping("/index") @ResponseBody public Result getIndexPage(Page page, @RequestParam(name = "orderMode", defaultValue = "0") int orderMode) { - HashMap hashMap = new HashMap<>(); + HashMap hashMap = new HashMap<>(); // 获取总页数 page.setRows(discussPostService.findDiscussPostRows(0)); @@ -135,7 +133,7 @@ public class DiscussPostController extends BaseController implements CommunityCo // 当前登录用户对帖子的点赞状态 int likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus(getUser().getId(), ENTITY_TYPE_POST, post.getId()); - map.put("likeStatus",likeStatus); + map.put("likeStatus", likeStatus); discussPosts.add(map); } @@ -147,7 +145,7 @@ public class DiscussPostController extends BaseController implements CommunityCo hashMap.put("orderMode", orderMode); - return new Result("success",Result.SUCCESS,hashMap); + return new Result("success", Result.SUCCESS, hashMap); } /** @@ -166,8 +164,13 @@ public class DiscussPostController extends BaseController implements CommunityCo if (discussPost == null) { return new Result("fail", "1", "没有找到帖子"); } - String content = HtmlUtils.htmlUnescape(discussPost.getContent()); // 内容反转义,不然 markDown 格式无法显示 - discussPost.setContent(content); + if (discussPost.getStatus() == 1) { + discussPost.setContent("该帖子因违反社区规范,已无法查看"); + discussPost.setPicUrls(null); + } else { + String content = HtmlUtils.htmlUnescape(discussPost.getContent()); // 内容反转义,不然 markDown 格式无法显示 + discussPost.setContent(content); + } //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 resultMap.put("post", discussPostService.toDiscussPostJsonObject(discussPost)); @@ -202,6 +205,7 @@ public class DiscussPostController extends BaseController implements CommunityCo /** * 搜索 * search?keword=xxx¤t=2&limit=2 + * * @param keyword 关键词 * @param page * @return @@ -210,14 +214,14 @@ public class DiscussPostController extends BaseController implements CommunityCo public Result search(String keyword, Page page) { JSONObject jsonObject = new JSONObject(); // 搜索帖子 (Spring 提供的 Page 当前页码从 0 开始计数) - org.springframework.data.domain.Page searchResult = elasticsearchService.searchDiscussPost(keyword, page.getCurrent()-1, page.getLimit()); + org.springframework.data.domain.Page searchResult = elasticsearchService.searchDiscussPost(keyword, page.getCurrent() - 1, page.getLimit()); // 聚合数据 List> discussPosts = new ArrayList<>(); if (searchResult != null) { for (DiscussPost post : searchResult) { Map map = new HashMap<>(); // 帖子 - //将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 + // 将discuss_post表中以 , 分隔的pic_url转为json数组返回到前端 map.put("post", discussPostService.toDiscussPostJsonObject(post)); // 作者 @@ -230,7 +234,7 @@ public class DiscussPostController extends BaseController implements CommunityCo } // 设置分页 - page.setPath("/search?keyword="+ keyword); + page.setPath("/search?keyword=" + keyword); page.setRows(searchResult == null ? 0 : (int) searchResult.getTotalElements()); jsonObject.put("keyword", keyword); @@ -262,47 +266,42 @@ public class DiscussPostController extends BaseController implements CommunityCo .setEntityId(id); eventProducer.fireEvent(event); - return new Result("success", Result.SUCCESS, ""); + return new Result("success", Result.SUCCESS, "置顶成功"); } - /** - * 加精帖子 + * 禁用帖子(管理员操作) * * @return */ - @PostMapping("/wonderful") - public Result setWonderful(@RequestBody HashMap map) { - int id = map.get("id"); - + @PostMapping("/disable/{id}") + public Result setDisable(@PathVariable int id) { discussPostService.updateStatus(id, 1); - // 触发发帖事件,通过消息队列将其存入 Elasticsearch 服务器 + // 触发删帖事件,通过消息队列更新 Elasticsearch 服务器 Event event = new Event() - .setTopic(TOPIC_PUBLISH) + .setTopic(TOPIC_DELETE) .setUserId(getUser().getId()) .setEntityType(ENTITY_TYPE_POST) .setEntityId(id); eventProducer.fireEvent(event); - // 计算帖子分数 -// String redisKey = RedisKeyUtil.getPostScoreKey(); -// redisTemplate.opsForSet().add(redisKey, id); - discussPostService.addDisscussPostToRefreshScore(id); - - return new Result("success", Result.SUCCESS, ""); + return new Result("success", Result.SUCCESS, "禁用成功"); } - /** - * 删除帖子 + * 删除帖子(只能自己删除自己的) * * @return */ - @PostMapping("/delete") + @PostMapping("/delete/{id}") @ResponseBody - public Result setDelete(@RequestBody HashMap map) { - int id = map.get("id"); + public Result setDelete(@PathVariable int id) { + DiscussPost discussPost = discussPostService.findDiscussPostById(id); + if (discussPost == null || discussPost.getUserId() != getUser().getId()) { + return new Result("fail", "1", "只能删除自己的帖子"); + } + discussPostService.updateStatus(id, 2); // 触发删帖事件,通过消息队列更新 Elasticsearch 服务器 @@ -315,5 +314,4 @@ public class DiscussPostController extends BaseController implements CommunityCo return new Result("success", Result.SUCCESS, "删除成功"); } - } diff --git a/src/main/java/com/greate/community/entity/DiscussPost.java b/src/main/java/com/greate/community/entity/DiscussPost.java index 8a4bce9..df57fe8 100644 --- a/src/main/java/com/greate/community/entity/DiscussPost.java +++ b/src/main/java/com/greate/community/entity/DiscussPost.java @@ -24,7 +24,7 @@ public class DiscussPost { private int id; // @Field(type = FieldType.Integer) - private int userId; + private int userId; // 发表用户 // @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart") private String title; diff --git a/src/main/java/com/greate/community/entity/dto/AddPostDTO.java b/src/main/java/com/greate/community/entity/dto/AddPostDTO.java new file mode 100644 index 0000000..5dfa679 --- /dev/null +++ b/src/main/java/com/greate/community/entity/dto/AddPostDTO.java @@ -0,0 +1,20 @@ +package com.greate.community.entity.dto; + +import lombok.Data; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import java.util.List; + +@Data +public class AddPostDTO { + + @NotBlank(message = "标题不能为空") + @Size(max = 20, message = "标题不能超过20字") + private String title; + + @NotBlank(message = "内容不能为空") + @Size(max = 1000, message = "内容过长") + private String content; + + private List picUrls; +} diff --git a/src/main/java/com/greate/community/event/EventConsumer.java b/src/main/java/com/greate/community/event/EventConsumer.java index b2c1c96..84f1f02 100644 --- a/src/main/java/com/greate/community/event/EventConsumer.java +++ b/src/main/java/com/greate/community/event/EventConsumer.java @@ -106,9 +106,6 @@ public class EventConsumer implements CommunityConstant { return; } - // 增加经验 - expService.handleGetExp(event.getUserId(), ExpType.EXP_PUBLISH.getName()); - // 将帖子转存到elasticsearch DiscussPost post = discussPostService.findDiscussPostById(event.getEntityId()); if (post == null) { diff --git a/src/main/java/com/greate/community/exception/GlobalExceptionHandler.java b/src/main/java/com/greate/community/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..3192a27 --- /dev/null +++ b/src/main/java/com/greate/community/exception/GlobalExceptionHandler.java @@ -0,0 +1,29 @@ +package com.greate.community.exception; + +import com.greate.community.entity.Result; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.validation.BindException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Slf4j +@RestControllerAdvice +public class GlobalExceptionHandler { + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(BindException.class) + public Result handleValidatedBindException(BindException e) { + log.error(e.getMessage(), e); + String message = e.getAllErrors().get(0).getDefaultMessage(); + return new Result("error", "400", message); + } + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(Exception.class) + public Result handleException(Exception e) { + log.error(e.getMessage(), e); + return new Result("error", "500", e.getMessage()); + } +} diff --git a/src/main/java/com/greate/community/service/DiscussPostService.java b/src/main/java/com/greate/community/service/DiscussPostService.java index 222dcfa..96cb400 100644 --- a/src/main/java/com/greate/community/service/DiscussPostService.java +++ b/src/main/java/com/greate/community/service/DiscussPostService.java @@ -194,7 +194,7 @@ public class DiscussPostService { } /** - * 修改帖子状态:0-正常; 1-精华; 2-拉黑; + * 修改帖子状态:0-正常; 1-违规; 2-删除; * * @param id * @param status diff --git a/src/main/java/com/greate/community/service/ElasticsearchService.java b/src/main/java/com/greate/community/service/ElasticsearchService.java index a183572..36e2e13 100644 --- a/src/main/java/com/greate/community/service/ElasticsearchService.java +++ b/src/main/java/com/greate/community/service/ElasticsearchService.java @@ -85,13 +85,10 @@ public class ElasticsearchService { Pageable pageable = PageRequest.of(current, limit); NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.multiMatchQuery(keyword, "title", "content")) - .withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC)) - .withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC)) - .withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC)) + .withSorts(SortBuilders.fieldSort("type").order(SortOrder.DESC), + SortBuilders.fieldSort("score").order(SortOrder.DESC), + SortBuilders.fieldSort("createTime").order(SortOrder.DESC)) .withPageable(PageRequest.of(current, limit)) -// .withHighlightFields( -// new HighlightBuilder.Field("title").preTags("").postTags(""), -// new HighlightBuilder.Field("content").preTags("").postTags("")) .withHighlightFields( new HighlightBuilder.Field("title"), new HighlightBuilder.Field("content")) diff --git a/src/main/resources/mapper/discusspost-mapper.xml b/src/main/resources/mapper/discusspost-mapper.xml index 863e4f3..39c059f 100644 --- a/src/main/resources/mapper/discusspost-mapper.xml +++ b/src/main/resources/mapper/discusspost-mapper.xml @@ -13,11 +13,11 @@ - + - - + select * + from follow + where user_id = #{userId} + and entity_type = 3 + order by create_time desc + limit #{offset} + , #{limit} - + select * + from follow + where entity_id = #{entityId} + and entity_type = 3 + order by create_time desc + limit #{offset} + , #{limit} \ No newline at end of file -- Gitee From cd67e5aeea54a816f2f9ca5ec83cf2d7be88cb86 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Sat, 12 Mar 2022 14:48:07 +0800 Subject: [PATCH 092/125] fix: comment controller --- .../community/config/SecurityConfig.java | 7 +- .../controller/CommentController.java | 118 +++++++++++++----- .../community/entity/dto/AddCommentDTO.java | 30 +++++ .../community/service/CommentService.java | 18 +++ .../community/util/StringListConvertor.java | 2 +- src/main/resources/mapper/comment-mapper.xml | 77 ++++++------ 6 files changed, 180 insertions(+), 72 deletions(-) create mode 100644 src/main/java/com/greate/community/entity/dto/AddCommentDTO.java diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index ac34700..3627d30 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -54,6 +54,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm } // 认证环节我们使用自己的代码 LoginController,绕过 Spring Security 的 + /** * 授权 * @@ -88,10 +89,11 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm "/like", "/follow", "/unfollow", + "/discuss/delete/**", "/discuss/add", "/comment/add", - "/discuss/delete/**" - ) + "/comment/delete/**" + ) .hasAnyAuthority( AUTHORITY_ADMIN, AUTHORITY_MODERATOR, @@ -100,6 +102,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm .antMatchers( "/discuss/top", "/discuss/disable/**", + "/comment/disable/**", "/data/**", "/admin/**" ) diff --git a/src/main/java/com/greate/community/controller/CommentController.java b/src/main/java/com/greate/community/controller/CommentController.java index 0871b85..3d14af5 100644 --- a/src/main/java/com/greate/community/controller/CommentController.java +++ b/src/main/java/com/greate/community/controller/CommentController.java @@ -2,18 +2,22 @@ package com.greate.community.controller; import com.alibaba.fastjson.JSONArray; import com.greate.community.entity.*; +import com.greate.community.entity.dto.AddCommentDTO; import com.greate.community.event.EventProducer; import com.greate.community.service.CommentService; import com.greate.community.service.DiscussPostService; import com.greate.community.service.LikeService; import com.greate.community.service.UserService; import com.greate.community.util.*; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Controller; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.*; +import java.util.stream.Collectors; /** * 评论/回复 @@ -31,6 +35,9 @@ public class CommentController extends BaseController implements CommunityConsta @Autowired private CommentService commentService; + @Autowired + private RedisTemplate redisTemplate; + @Autowired private EventProducer eventProducer; @@ -38,15 +45,16 @@ public class CommentController extends BaseController implements CommunityConsta * 添加评论 */ @PostMapping("/add") - public Result addComment(@RequestBody HashMap map) { + public Result addComment(@RequestBody @Validated AddCommentDTO addCommentDTO) { Comment comment = new Comment(); - comment.setContent((String) map.get("content")); - comment.setPicUrls(StringListConvertor.join((List) map.get("picUrls"))); - comment.setParentId((Integer) map.get("parentId")); - comment.setRootId((Integer) map.get("rootId")); - comment.setPostId((Integer) map.get("postId")); - comment.setParentUserId((Integer) map.get("parentUserId")); + comment.setContent(addCommentDTO.getContent()); + List filter = addCommentDTO.getPicUrls().stream().filter(url -> !StringUtils.isBlank(url)).collect(Collectors.toList()); + comment.setPicUrls(StringListConvertor.join(filter)); + comment.setParentId(addCommentDTO.getParentId()); + comment.setRootId(addCommentDTO.getRootId()); + comment.setPostId(addCommentDTO.getPostId()); + comment.setParentUserId(addCommentDTO.getParentUserId()); comment.setUserId(getUser().getId()); comment.setLikeCount(0); @@ -78,19 +86,17 @@ public class CommentController extends BaseController implements CommunityConsta .setData("type", ExpType.EXP_COMMENT.getName()); eventProducer.fireEvent(expEvent); -// if (comment.getRootId() == 0) { -// // 触发发帖事件,通过消息队列将其存入 Elasticsearch 服务器 -// Event event = new Event() -// .setTopic(TOPIC_PUBLISH) -// .setUserId(comment.getUserId()) -// .setEntityType(ENTITY_TYPE_POST) -// .setEntityId(comment.getPostId()); -// eventProducer.fireEvent(event); -// -// // 计算帖子分数 -// String redisKey = RedisKeyUtil.getPostScoreKey(); -// redisTemplate.opsForSet().add(redisKey, comment.getPostId()); -// } + // 触发发帖事件,通过消息队列将其存入 Elasticsearch 服务器 + Event event = new Event() + .setTopic(TOPIC_PUBLISH) + .setUserId(comment.getUserId()) + .setEntityType(ENTITY_TYPE_POST) + .setEntityId(comment.getPostId()); + eventProducer.fireEvent(event); + + // 计算帖子分数 + String redisKey = RedisKeyUtil.getPostScoreKey(); + redisTemplate.opsForSet().add(redisKey, comment.getPostId()); return new Result("success", Result.SUCCESS, "评论成功"); } @@ -99,7 +105,9 @@ public class CommentController extends BaseController implements CommunityConsta * 获取帖子的评论列表 */ @GetMapping("/list/{discussPostId}") - public Result getCommentsByPostId(@PathVariable("discussPostId") int discussPostId, Page page) { + public Result getCommentsByPostId(@PathVariable("discussPostId") int discussPostId, + @RequestParam(value = "replyLimit", defaultValue = "3") int replyLimit, + Page page) { page.setPath("/comment/get/" + discussPostId); // 帖子下评论总数 @@ -112,8 +120,9 @@ public class CommentController extends BaseController implements CommunityConsta // 封装评论及其相关信息 List> commentVoList = new ArrayList<>(); if (commentList != null && !commentList.isEmpty()) { - for (Comment comment : commentList) { + commentList.forEach(comment -> { Map commentVo = new HashMap<>(); + shieldContent(comment); commentVo.put("comment", StringListConvertor.toJsonObject(comment, "picUrls")); // 评论 commentVo.put("user", userService.findUserById(comment.getUserId())); // 发布评论的作者 // 当前登录用户对该评论的点赞状态 @@ -121,19 +130,21 @@ public class CommentController extends BaseController implements CommunityConsta getUser().getId(), ENTITY_TYPE_COMMENT, comment.getId()); commentVo.put("likeStatus", likeStatus); // 存储每个评论对应的回复, 查询点赞量最高的前3条回复 - List replyList = commentService.findReplyByComment(comment.getId(), 0, 3); + List replyList = commentService.findReplyByComment(comment.getId(), 0, replyLimit); List> replyVoList = new ArrayList<>(); // 封装对评论的评论和评论的作者信息 if (replyList != null) { - for (Comment reply : replyList) { + replyList.forEach(reply -> { Map replyVo = new HashMap<>(); + shieldContent(reply); replyVo.put("reply", StringListConvertor.toJsonObject(reply, "picUrls")); // 回复 replyVo.put("user", userService.findUserById(reply.getUserId())); // 发布该回复的作者 - likeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( + // 当前登录用户对该回复的点赞状态 + int replyLikeStatus = getUser() == null ? 0 : likeService.findEntityLikeStatus( getUser().getId(), ENTITY_TYPE_COMMENT, reply.getId()); - replyVo.put("likeStatus", likeStatus); // 当前登录用户的点赞状态 + replyVo.put("likeStatus", replyLikeStatus); // 当前登录用户的点赞状态 replyVoList.add(replyVo); - } + }); } commentVo.put("replys", replyVoList); @@ -142,7 +153,7 @@ public class CommentController extends BaseController implements CommunityConsta commentVo.put("replyCount", replyCount); commentVoList.add(commentVo); - } + }); } JSONArray result = (JSONArray) JSONArray.toJSON(commentVoList); @@ -165,8 +176,9 @@ public class CommentController extends BaseController implements CommunityConsta // 封装评论及其相关信息 List> replyVoList = new ArrayList<>(); if (replyList != null && !replyList.isEmpty()) { - for (Comment reply : replyList) { + replyList.forEach(reply -> { Map commentVo = new HashMap<>(); + shieldContent(reply); commentVo.put("comment", StringListConvertor.toJsonObject(reply, "picUrls")); commentVo.put("user", userService.findUserById(reply.getUserId())); // 发布评论的作者 // 当前登录用户对该评论的点赞状态 @@ -175,7 +187,7 @@ public class CommentController extends BaseController implements CommunityConsta commentVo.put("likeStatus", likeStatus); replyVoList.add(commentVo); - } + }); } JSONArray result = (JSONArray) JSONArray.toJSON(replyVoList); @@ -184,15 +196,53 @@ public class CommentController extends BaseController implements CommunityConsta return new Result("success", Result.SUCCESS, page); } + /** + * 禁用评论(禁用仍然可以查询出来,不修改帖子分数) + * + * @return + */ + @PostMapping("/disable/{id}") + public Result setDisable(@PathVariable int id) { + commentService.updateStatus(id, 1); + return new Result("success", Result.SUCCESS, "禁用成功"); + } + /** * 删除评论 * * @return */ - @PostMapping("/delete") - public Result setDelete(@RequestBody HashMap map) { - int id = map.get("id"); - commentService.updateStatus(id, 2); + @PostMapping("/delete/{id}") + public Result setDelete(@PathVariable int id) { + Comment comment = commentService.findCommentById(id); + if (comment == null) { + return new Result("fail", "1", "评论不存在"); + } + if (getUser().getId() != comment.getUserId()) { + return new Result("fail", "2", "只能删除自己的评论"); + } + + commentService.deleteComment(comment); + + // 触发发帖事件,通过消息队列将其存入 Elasticsearch 服务器 + Event event = new Event() + .setTopic(TOPIC_PUBLISH) + .setUserId(comment.getUserId()) + .setEntityType(ENTITY_TYPE_POST) + .setEntityId(comment.getPostId()); + eventProducer.fireEvent(event); + + // 计算帖子分数 + String redisKey = RedisKeyUtil.getPostScoreKey(); + redisTemplate.opsForSet().add(redisKey, comment.getPostId()); + return new Result("success", Result.SUCCESS, "删除成功"); } + + private void shieldContent(Comment comment) { + if (comment.getStatus() == 1) { + comment.setContent("该评论因违反社区规定,已无法查看"); + comment.setPicUrls(null); + } + } } diff --git a/src/main/java/com/greate/community/entity/dto/AddCommentDTO.java b/src/main/java/com/greate/community/entity/dto/AddCommentDTO.java new file mode 100644 index 0000000..c936b57 --- /dev/null +++ b/src/main/java/com/greate/community/entity/dto/AddCommentDTO.java @@ -0,0 +1,30 @@ +package com.greate.community.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.util.List; + +@Data +public class AddCommentDTO { + + @NotBlank(message = "评论不能为空") + @Size(max = 1000, message = "内容太长") + private String content; + + private List picUrls; + + @NotNull + private Integer parentId; + + @NotNull + private Integer rootId; + + @NotNull + private Integer postId; + + @NotNull + private Integer parentUserId; +} diff --git a/src/main/java/com/greate/community/service/CommentService.java b/src/main/java/com/greate/community/service/CommentService.java index 818c13d..b06280f 100644 --- a/src/main/java/com/greate/community/service/CommentService.java +++ b/src/main/java/com/greate/community/service/CommentService.java @@ -135,6 +135,24 @@ public class CommentService implements CommunityConstant { return rows; } + /** + * 删除评论 + * + * @param comment + * @return + */ + @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED) + public int deleteComment(Comment comment) { + if (comment == null) { + throw new IllegalArgumentException("参数不能为空"); + } + int rows = commentMapper.updateStatus(comment.getId(), 2); + if (rows == 1) { + discussPostService.addCommentCount(comment.getPostId(), -1); + } + return rows; + } + public int like(int id) { return commentMapper.addLikeCount(id, 1); } diff --git a/src/main/java/com/greate/community/util/StringListConvertor.java b/src/main/java/com/greate/community/util/StringListConvertor.java index 651e351..34c25f0 100644 --- a/src/main/java/com/greate/community/util/StringListConvertor.java +++ b/src/main/java/com/greate/community/util/StringListConvertor.java @@ -40,7 +40,7 @@ public class StringListConvertor { } else { JSONObject discussPostJsonObject = (JSONObject) JSONObject.toJSON(object); String value = discussPostJsonObject.getString(key); - if (StringUtils.isNotEmpty(value.trim())) { + if (value != null && StringUtils.isNotEmpty(value.trim())) { String[] picUrlArray = value.split(separator); JSONArray picUrlJSONArray = (JSONArray) JSONArray.toJSON(picUrlArray); discussPostJsonObject.remove(key); diff --git a/src/main/resources/mapper/comment-mapper.xml b/src/main/resources/mapper/comment-mapper.xml index 6b0d004..cdece2b 100644 --- a/src/main/resources/mapper/comment-mapper.xml +++ b/src/main/resources/mapper/comment-mapper.xml @@ -4,62 +4,68 @@ "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - - id, content, pic_urls, user_id, parent_id, root_id, parent_user_id, post_id, like_count, status, create_time + + id + , content, pic_urls, user_id, parent_id, root_id, parent_user_id, post_id, like_count, status, create_time - - content, pic_urls, user_id, parent_id, root_id, parent_user_id, post_id, like_count, status, create_time + + content + , pic_urls, user_id, parent_id, root_id, parent_user_id, post_id, like_count, status, create_time - + SELECT LAST_INSERT_ID() insert into comment() - values(#{content}, #{picUrls}, #{userId}, #{parentId}, #{rootId}, #{parentUserId}, #{postId}, #{likeCount}, #{status}, #{createTime}) + values(#{content}, #{picUrls}, #{userId}, #{parentId}, #{rootId}, #{parentUserId}, #{postId}, #{likeCount}, + #{status}, #{createTime}) - + select + from comment where id = #{id} - - - + select + from comment - where status = 0 + where status != 2 and root_id = 0 and post_id = #{postId} - order by like_count desc + order by like_count desc, create_time desc limit #{offset}, #{limit} - - - + select + from comment - where status = 0 + where status != 2 and root_id = #{rootId} - order by like_count desc + order by like_count desc, create_time desc limit #{offset}, #{limit} - - select count(id) from comment where status = 0 - and post_id = #{postId} + and post_id = #{postId} - - select count(id) from comment where status = 0 @@ -67,17 +73,18 @@ and post_id = #{postId} - - select count(id) from comment where status = 0 and root_id = #{rootId} - - + select + from comment where status = 0 and user_id = #{userId} @@ -85,22 +92,22 @@ limit #{offset}, #{limit} - - select count(id) from comment where status = 0 - and user_id = #{userId} + and user_id = #{userId} - + update comment set like_count = like_count + #{likeCount} where id = #{id} - + update comment set status = #{status} -- Gitee From 1c9dd6adceaefa92ea2aa662d840d0bd4d89bd38 Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Sat, 12 Mar 2022 14:50:51 +0800 Subject: [PATCH 093/125] =?UTF-8?q?=E6=97=A0=E7=8A=B6=E6=80=81session-?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95=E8=BF=87=E7=A8=8B=E4=B8=AD?= =?UTF-8?q?=E9=83=A8=E5=88=86=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/config/SecurityConfig.java | 16 +++--- .../community/controller/LoginController.java | 1 - .../controller/MessageController.java | 11 +++- .../community/controller/UserController.java | 55 ++++++++++++------- .../community/entity/dto/EmailLoginDTO.java | 2 +- .../community/entity/dto/LetterDTO.java | 21 +++++++ .../community/entity/dto/PasswordDTO.java | 20 +++++++ .../community/entity/dto/RealNameDTO.java | 32 +++++++++++ 8 files changed, 125 insertions(+), 33 deletions(-) create mode 100644 src/main/java/com/greate/community/entity/dto/LetterDTO.java create mode 100644 src/main/java/com/greate/community/entity/dto/PasswordDTO.java create mode 100644 src/main/java/com/greate/community/entity/dto/RealNameDTO.java diff --git a/src/main/java/com/greate/community/config/SecurityConfig.java b/src/main/java/com/greate/community/config/SecurityConfig.java index a983b66..ad4adc7 100644 --- a/src/main/java/com/greate/community/config/SecurityConfig.java +++ b/src/main/java/com/greate/community/config/SecurityConfig.java @@ -12,6 +12,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.AuthenticationException; import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter; import org.springframework.security.web.AuthenticationEntryPoint; @@ -62,16 +63,14 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm */ @Override protected void configure(HttpSecurity http) throws Exception { + //启用无状态session + http.sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS); + http.cors().and().csrf().disable() .authorizeRequests() .antMatchers( - "/user/get", - "/user/setting", - "/user/upload", - "/user/studentCard/url", - "/user/header/url", - "/user/username", - "/user/updateHeader", + "/user/**", "/letter/**", "/notice/**", "/like", @@ -79,7 +78,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter implements Comm "/unfollow", "/exp/**", "/cos/credential", - "/message/unread" + "/message/unread", + "/message/allread" ) .hasAnyAuthority( AUTHORITY_USER, diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index 666d88d..f594698 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -151,7 +151,6 @@ public class LoginController extends BaseController implements CommunityConstant */ @PostMapping("/login") public Result login(@RequestBody @Validated EmailLoginDTO emailLoginDTO) { - System.out.println("------------------------"+emailLoginDTO.getEmail()); // 检查验证码 if (captchaEnable) { diff --git a/src/main/java/com/greate/community/controller/MessageController.java b/src/main/java/com/greate/community/controller/MessageController.java index b077de5..829897d 100644 --- a/src/main/java/com/greate/community/controller/MessageController.java +++ b/src/main/java/com/greate/community/controller/MessageController.java @@ -3,6 +3,7 @@ package com.greate.community.controller; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.greate.community.entity.*; +import com.greate.community.entity.dto.LetterDTO; import com.greate.community.jwt.JwtUser; import com.greate.community.service.CommentService; import com.greate.community.service.DiscussPostService; @@ -10,6 +11,7 @@ import com.greate.community.service.MessageService; import com.greate.community.service.UserService; import com.greate.community.util.CommunityConstant; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.util.HtmlUtils; @@ -191,12 +193,15 @@ public class MessageController extends BaseController implements CommunityConsta /** * 发送私信 * - * @param userId 收信人 userId - * @param content 内容 + * @param letterDTO * @return */ @PostMapping("/letter/send") - public Result sendLetter(int userId, String content) { +// public Result sendLetter(int userId, String content) { + public Result sendLetter(@RequestBody @Validated LetterDTO letterDTO) { + int userId = letterDTO.getUserId(); + String content = letterDTO.getContent(); + User target = userService.findUserById(userId); if (target == null) { return new Result("fail", "1", "目标用户不存在!"); diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 5b47d5b..843eb35 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -3,6 +3,8 @@ package com.greate.community.controller; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.greate.community.entity.*; +import com.greate.community.entity.dto.PasswordDTO; +import com.greate.community.entity.dto.RealNameDTO; import com.greate.community.service.*; import com.greate.community.util.CommunityConstant; import com.greate.community.util.CommunityUtil; @@ -10,6 +12,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.*; @@ -42,6 +45,7 @@ public class UserController extends BaseController implements CommunityConstant */ @GetMapping("/get") public Result getUserByToken() { + JSONObject jsonObject = new JSONObject(); if (getUser() == null) { return new Result("fail", "1", "该用户不存在"); @@ -55,6 +59,7 @@ public class UserController extends BaseController implements CommunityConstant // 粉丝数量 long followerCount = followService.findFollowerCount(ENTITY_TYPE_USER, getUser().getId()); jsonObject.put("followerCount", followerCount); + return new Result("success", Result.SUCCESS, jsonObject); } @@ -64,19 +69,23 @@ public class UserController extends BaseController implements CommunityConstant * @return */ @GetMapping("/realname/get") - public Result getRealNameUserByTicket() { - User user = userService.findAllUserById(getUser().getId()); - return new Result("success", Result.SUCCESS, user); + public Result getRealNameUserByToken() { + if(getUser() == null){ + return new Result("fail", "1", "实名信息获取失败"); + }else { + User user = userService.findAllUserById(getUser().getId()); + return new Result("success", Result.SUCCESS, user); + } } - @PostMapping("/username") - public Result updateUsername(@RequestBody String username) { - if (StringUtils.isBlank(username)) { + @GetMapping("/username") + public Result updateUsername(@RequestParam String newname) { + if (StringUtils.isBlank(newname)) { return new Result("fail", "1", "用户名不能为空"); - } else if (username.length() <= 2 || username.length() > 10) { + } else if (newname.length() <= 2 || newname.length() > 10) { return new Result("fail", "4", "用户名长度不能超过2-10个字符"); } - int result = userService.updateUsername(getUser().getId(), username); + int result = userService.updateUsername(getUser().getId(), newname); if (result == 2) { return new Result("fail", "2", "用户名不能重复"); } else if (result == 0) { @@ -89,12 +98,14 @@ public class UserController extends BaseController implements CommunityConstant /** * 修改用户密码 * - * @param oldPassword 原密码 - * @param newPassword 新密码 + * @param passwordDTO * @return */ @PostMapping("/password") - public Result updatePassword(@RequestBody String oldPassword, @RequestBody String newPassword) { + public Result updatePassword(@RequestBody @Validated PasswordDTO passwordDTO) { + String oldPassword = passwordDTO.getOldPassword(); + String newPassword = passwordDTO.getNewPassword(); + // 验证原密码是否正确 User user = userService.findUserById(getUser().getId()); String md5OldPassword = CommunityUtil.md5(oldPassword + user.getSalt()); @@ -257,20 +268,24 @@ public class UserController extends BaseController implements CommunityConstant /** * 更新用户实名信息 * - * @param user + * @param realNameDTO * @return */ - @PostMapping("/realname") - public Result updateRealNameInfo(@RequestBody User user) { - if (user == null) { - return new Result("fail", "1", "the request parameters are invalid"); - } - // 已实名 + @PostMapping("/realname/update") + public Result updateRealNameInfo(@RequestBody @Validated RealNameDTO realNameDTO) { + // 已实名认证通过,则无法更新实名信息 if (userService.findUserById(getUser().getId()).getAuditStatus() == 2) { - return new Result("success", Result.SUCCESS, "用户已实名"); + return new Result("success", Result.SUCCESS, "用户已实名认证通过,无法更新实名信息"); } + + User user = new User(); user.setId(getUser().getId()); + user.setStudentCardUrl(realNameDTO.getStudentCardUrl()); + user.setStudentCode(realNameDTO.getStudentCode()); + user.setRealName(realNameDTO.getRealName()); + user.setInstitute(realNameDTO.getInstitute()); + user.setProfessionalClass(realNameDTO.getProfessionalClass()); userService.updateRealNameInfo(user); return new Result("success", Result.SUCCESS, "用户实名信息更新成功"); } @@ -285,7 +300,7 @@ public class UserController extends BaseController implements CommunityConstant public Result updateHeader(@RequestBody JSONObject jsonObject) { String headerUrl = jsonObject.getString("headerUrl"); - if (headerUrl == null) { + if (StringUtils.isEmpty(headerUrl)) { return new Result("fail", "1", "the request parameters are invalid"); } diff --git a/src/main/java/com/greate/community/entity/dto/EmailLoginDTO.java b/src/main/java/com/greate/community/entity/dto/EmailLoginDTO.java index 1474a6c..af7d2d9 100644 --- a/src/main/java/com/greate/community/entity/dto/EmailLoginDTO.java +++ b/src/main/java/com/greate/community/entity/dto/EmailLoginDTO.java @@ -11,7 +11,7 @@ import javax.validation.constraints.Size; public class EmailLoginDTO { @NotBlank - @Size(max = 20) + @Size(max = 30) private String email; @NotBlank diff --git a/src/main/java/com/greate/community/entity/dto/LetterDTO.java b/src/main/java/com/greate/community/entity/dto/LetterDTO.java new file mode 100644 index 0000000..5273bce --- /dev/null +++ b/src/main/java/com/greate/community/entity/dto/LetterDTO.java @@ -0,0 +1,21 @@ +package com.greate.community.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +/** + * @author xzx + * @date 2022/3/12 0:39 + */ +@Data +public class LetterDTO { + @NotNull + private Integer userId; + + @NotBlank + @Size(max = 200) + private String content; +} diff --git a/src/main/java/com/greate/community/entity/dto/PasswordDTO.java b/src/main/java/com/greate/community/entity/dto/PasswordDTO.java new file mode 100644 index 0000000..d651c44 --- /dev/null +++ b/src/main/java/com/greate/community/entity/dto/PasswordDTO.java @@ -0,0 +1,20 @@ +package com.greate.community.entity.dto; + +import lombok.Data; +import org.springframework.web.bind.annotation.RequestBody; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +/** + * @author xzx + * @date 2022/3/11 18:10 + */ +@Data +public class PasswordDTO { + @NotBlank + private String oldPassword; + + @NotBlank + private String newPassword; +} diff --git a/src/main/java/com/greate/community/entity/dto/RealNameDTO.java b/src/main/java/com/greate/community/entity/dto/RealNameDTO.java new file mode 100644 index 0000000..7844388 --- /dev/null +++ b/src/main/java/com/greate/community/entity/dto/RealNameDTO.java @@ -0,0 +1,32 @@ +package com.greate.community.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +/** + * @author xzx + * @date 2022/3/11 23:38 + */ +@Data +public class RealNameDTO { + @NotBlank + private String studentCardUrl; + + @NotBlank + @Size(max = 30) + private String studentCode; + + @NotBlank + @Size(max = 20) + private String realName; + + @NotBlank + @Size(max = 20) + private String institute; + + @NotBlank + @Size(max = 20) + private String professionalClass; +} -- Gitee From 29204b51b862ddcdf500d96faf656b690d769983 Mon Sep 17 00:00:00 2001 From: cunyi <2224236998@qq.com> Date: Sat, 12 Mar 2022 16:23:43 +0800 Subject: [PATCH 094/125] fix: audit controller --- .../community/controller/AuditController.java | 23 +++++++++++-------- .../community/controller/UserController.java | 5 ++-- .../greate/community/service/UserService.java | 4 +++- src/main/resources/mapper/user-mapper.xml | 7 ++++-- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/greate/community/controller/AuditController.java b/src/main/java/com/greate/community/controller/AuditController.java index 795733a..043b66c 100644 --- a/src/main/java/com/greate/community/controller/AuditController.java +++ b/src/main/java/com/greate/community/controller/AuditController.java @@ -23,7 +23,7 @@ import java.util.Map; * @date 2022/2/9 21:41 */ @RestController -public class AuditController { +public class AuditController extends BaseController { @Autowired private UserService userService; @@ -93,11 +93,12 @@ public class AuditController { resultDetailedUser.put("id", user.getId()); resultDetailedUser.put("username", user.getUsername()); resultDetailedUser.put("email", user.getEmail()); - resultDetailedUser.put("student_card_url", user.getStudentCardUrl()); - resultDetailedUser.put("student_code", user.getStudentCode()); - resultDetailedUser.put("real_name", user.getRealName()); + resultDetailedUser.put("studentCardUrl", user.getStudentCardUrl()); + resultDetailedUser.put("studentCode", user.getStudentCode()); + resultDetailedUser.put("realName", user.getRealName()); resultDetailedUser.put("institute", user.getInstitute()); - resultDetailedUser.put("professional_class", user.getProfessionalClass()); + resultDetailedUser.put("professionalClass", user.getProfessionalClass()); + resultDetailedUser.put("auditStatus", user.getAuditStatus()); resultDetailedUserList.add(resultDetailedUser); } @@ -116,15 +117,19 @@ public class AuditController { @GetMapping("/admin/user/detailedById") public Result getDetailedUserById(int userId) { User user = userService.findRealNameUserById(userId); + if (user == null) { + return new Result("fail", "1", "用户不存在"); + } HashMap resultDetailedUser = new HashMap<>(); resultDetailedUser.put("id", user.getId()); resultDetailedUser.put("username", user.getUsername()); resultDetailedUser.put("email", user.getEmail()); - resultDetailedUser.put("student_card_url", user.getStudentCardUrl()); - resultDetailedUser.put("student_code", user.getStudentCode()); - resultDetailedUser.put("real_name", user.getRealName()); + resultDetailedUser.put("studentCardUrl", user.getStudentCardUrl()); + resultDetailedUser.put("studentCode", user.getStudentCode()); + resultDetailedUser.put("realName", user.getRealName()); resultDetailedUser.put("institute", user.getInstitute()); - resultDetailedUser.put("professional_class", user.getProfessionalClass()); + resultDetailedUser.put("professionalClass", user.getProfessionalClass()); + resultDetailedUser.put("auditStatus", user.getAuditStatus()); return new Result("success", Result.SUCCESS, resultDetailedUser); } diff --git a/src/main/java/com/greate/community/controller/UserController.java b/src/main/java/com/greate/community/controller/UserController.java index 843eb35..6f71265 100644 --- a/src/main/java/com/greate/community/controller/UserController.java +++ b/src/main/java/com/greate/community/controller/UserController.java @@ -45,7 +45,6 @@ public class UserController extends BaseController implements CommunityConstant */ @GetMapping("/get") public Result getUserByToken() { - JSONObject jsonObject = new JSONObject(); if (getUser() == null) { return new Result("fail", "1", "该用户不存在"); @@ -70,9 +69,9 @@ public class UserController extends BaseController implements CommunityConstant */ @GetMapping("/realname/get") public Result getRealNameUserByToken() { - if(getUser() == null){ + if (getUser() == null) { return new Result("fail", "1", "实名信息获取失败"); - }else { + } else { User user = userService.findAllUserById(getUser().getId()); return new Result("success", Result.SUCCESS, user); } diff --git a/src/main/java/com/greate/community/service/UserService.java b/src/main/java/com/greate/community/service/UserService.java index 0c42b6e..d104ed8 100644 --- a/src/main/java/com/greate/community/service/UserService.java +++ b/src/main/java/com/greate/community/service/UserService.java @@ -430,7 +430,9 @@ public class UserService implements CommunityConstant { * @return */ public int updateAuditStatus(int userId, int auditStatus) { - return userMapper.updateAuditStatus(userId, auditStatus); + int rows = userMapper.updateAuditStatus(userId, auditStatus); + clearCache(userId); + return rows; } /** diff --git a/src/main/resources/mapper/user-mapper.xml b/src/main/resources/mapper/user-mapper.xml index fc9e3cf..cc5c69f 100644 --- a/src/main/resources/mapper/user-mapper.xml +++ b/src/main/resources/mapper/user-mapper.xml @@ -77,6 +77,9 @@ , type = 3 + + , type = 0 + where id = #{id} @@ -84,7 +87,7 @@ - select id, username, email, student_card_url, student_code, real_name, institute, professional_class + select id, username, email, student_card_url, student_code, real_name, institute, professional_class, audit_status from user where id = #{id} -- Gitee From adf5e3025cd1cca1819b5445290d9421a031b2b2 Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Sat, 12 Mar 2022 17:26:40 +0800 Subject: [PATCH 095/125] =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E8=BF=87=E7=A8=8B=E4=B8=AD=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/controller/LikeController.java | 5 ++++ .../community/controller/LoginController.java | 29 ++++++++++++++----- .../community/entity/dto/LetterDTO.java | 4 +-- .../community/entity/dto/PasswordDTO.java | 4 +-- .../community/entity/dto/RealNameDTO.java | 10 +++---- .../community/entity/dto/RegisterDTO.java | 25 ++++++++++++++++ .../greate/community/service/LikeService.java | 19 ++++++++++++ .../greate/community/service/UserService.java | 18 ------------ 8 files changed, 79 insertions(+), 35 deletions(-) create mode 100644 src/main/java/com/greate/community/entity/dto/RegisterDTO.java diff --git a/src/main/java/com/greate/community/controller/LikeController.java b/src/main/java/com/greate/community/controller/LikeController.java index e31ba87..1fef093 100644 --- a/src/main/java/com/greate/community/controller/LikeController.java +++ b/src/main/java/com/greate/community/controller/LikeController.java @@ -47,6 +47,11 @@ public class LikeController extends BaseController implements CommunityConstant */ @PostMapping("/like") public Result like(int entityType, int entityId, int entityUserId, int postId) { + Object likeTargetEntity = likeService.getLikeTargetEntity(entityType, entityId); + if(likeTargetEntity == null){ + return new Result("fail", "1", "点赞目标不存在"); + } + JwtUser user = getUser(); log.info("点赞用户: " + user.toString()); diff --git a/src/main/java/com/greate/community/controller/LoginController.java b/src/main/java/com/greate/community/controller/LoginController.java index f594698..a09d127 100644 --- a/src/main/java/com/greate/community/controller/LoginController.java +++ b/src/main/java/com/greate/community/controller/LoginController.java @@ -3,6 +3,7 @@ package com.greate.community.controller; import cn.hutool.captcha.CaptchaUtil; import cn.hutool.captcha.LineCaptcha; import cn.hutool.core.lang.UUID; +import cn.hutool.core.lang.Validator; import com.alibaba.fastjson.JSONObject; import com.greate.community.auth.wechatauth.domain.UserWeChat; import com.greate.community.dao.UserMapper; @@ -10,6 +11,7 @@ import com.greate.community.entity.Event; import com.greate.community.entity.Result; import com.greate.community.entity.User; import com.greate.community.entity.dto.EmailLoginDTO; +import com.greate.community.entity.dto.RegisterDTO; import com.greate.community.event.EventProducer; import com.greate.community.jwt.JwtTokenUtil; import com.greate.community.service.UserService; @@ -67,16 +69,27 @@ public class LoginController extends BaseController implements CommunityConstant /** * 注册用户 * - * @param user + * @param registerDTO * @return */ @PostMapping("/register") - public Result register(@RequestBody User user) { - Map map = userService.register(user); - if (map == null || map.isEmpty()) { - return new Result("success", Result.SUCCESS, "注册成功, 我们已经向您的邮箱发送了一封激活邮件,请尽快激活!"); - } else { - return new Result("fail", Result.FAIL, map); + public Result register(@RequestBody @Validated RegisterDTO registerDTO) { + boolean isEmail = Validator.isEmail(registerDTO.getEmail()); + + if(isEmail){ + User user = new User(); + user.setUsername(registerDTO.getUsername()); + user.setPassword(registerDTO.getPassword()); + user.setEmail(registerDTO.getEmail()); + + Map map = userService.register(user); + if (map == null || map.isEmpty()) { + return new Result("success", Result.SUCCESS, "注册成功, 我们已经向您的邮箱发送了一封激活邮件,请尽快激活!"); + } else { + return new Result("fail", Result.FAIL, map); + } + }else { + return new Result("fail", "1", "请输入合法的邮箱地址"); } } @@ -88,7 +101,7 @@ public class LoginController extends BaseController implements CommunityConstant * @param code 激活码 * @return http://localhost:8080/echo/activation/用户id/激活码 */ - @GetMapping("/activation/{userId}/{code}") +// @GetMapping("/activation/{userId}/{code}") public Result activation(@PathVariable("userId") int userId, @PathVariable("code") String code) { int result = userService.activation(userId, code); diff --git a/src/main/java/com/greate/community/entity/dto/LetterDTO.java b/src/main/java/com/greate/community/entity/dto/LetterDTO.java index 5273bce..2be32ab 100644 --- a/src/main/java/com/greate/community/entity/dto/LetterDTO.java +++ b/src/main/java/com/greate/community/entity/dto/LetterDTO.java @@ -12,10 +12,10 @@ import javax.validation.constraints.Size; */ @Data public class LetterDTO { - @NotNull + @NotNull(message = "私信目标不能为空") private Integer userId; @NotBlank - @Size(max = 200) + @Size(max = 200, message = "私信内容过长,不能超过200字") private String content; } diff --git a/src/main/java/com/greate/community/entity/dto/PasswordDTO.java b/src/main/java/com/greate/community/entity/dto/PasswordDTO.java index d651c44..232c102 100644 --- a/src/main/java/com/greate/community/entity/dto/PasswordDTO.java +++ b/src/main/java/com/greate/community/entity/dto/PasswordDTO.java @@ -12,9 +12,9 @@ import javax.validation.constraints.Size; */ @Data public class PasswordDTO { - @NotBlank + @NotBlank(message = "请输入原密码") private String oldPassword; - @NotBlank + @NotBlank(message = "新密码不能为空") private String newPassword; } diff --git a/src/main/java/com/greate/community/entity/dto/RealNameDTO.java b/src/main/java/com/greate/community/entity/dto/RealNameDTO.java index 7844388..e5a3e7e 100644 --- a/src/main/java/com/greate/community/entity/dto/RealNameDTO.java +++ b/src/main/java/com/greate/community/entity/dto/RealNameDTO.java @@ -11,22 +11,22 @@ import javax.validation.constraints.Size; */ @Data public class RealNameDTO { - @NotBlank + @NotBlank(message = "请上传学生证照片") private String studentCardUrl; - @NotBlank + @NotBlank(message = "请输入学号") @Size(max = 30) private String studentCode; - @NotBlank + @NotBlank(message = "请输入姓名") @Size(max = 20) private String realName; - @NotBlank + @NotBlank(message = "请输入学院") @Size(max = 20) private String institute; - @NotBlank + @NotBlank(message = "请输入班级") @Size(max = 20) private String professionalClass; } diff --git a/src/main/java/com/greate/community/entity/dto/RegisterDTO.java b/src/main/java/com/greate/community/entity/dto/RegisterDTO.java new file mode 100644 index 0000000..bb8c1df --- /dev/null +++ b/src/main/java/com/greate/community/entity/dto/RegisterDTO.java @@ -0,0 +1,25 @@ +package com.greate.community.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +/** + * @author xzx + * @date 2022/3/12 15:17 + */ +@Data +public class RegisterDTO { + @NotBlank(message = "用户名不能为空") + @Size(max = 20, message = "内容过长,用户名20字以内") + private String username; + + @NotBlank(message = "密码不能为空") + @Size(max = 30, message = "内容过长,密码30字以内") + private String password; + + @NotBlank(message = "邮箱不能为空") + @Size(max = 30, message = "内容过长,邮箱30字以内") + private String email; +} diff --git a/src/main/java/com/greate/community/service/LikeService.java b/src/main/java/com/greate/community/service/LikeService.java index f07d556..bc7c745 100644 --- a/src/main/java/com/greate/community/service/LikeService.java +++ b/src/main/java/com/greate/community/service/LikeService.java @@ -85,6 +85,25 @@ public class LikeService implements CommunityConstant { return count; } + /** + * 获取被点赞的目标实体 + * + * @param entityType + * @param entityId + * @return + */ + public Object getLikeTargetEntity(int entityType, int entityId) { + Object object = null; + if (entityType == ENTITY_TYPE_POST) { + object = discussPostService.findDiscussPostById(entityId); + } else if (entityType == ENTITY_TYPE_COMMENT) { + object = commentService.findCommentById(entityId); + } else if (entityType == ENTITY_TYPE_USER) { + object = userService.findUserById(entityId); + } + return object; + } + /** * 查询某个用户对某个实体的点赞状态(是否已赞) * diff --git a/src/main/java/com/greate/community/service/UserService.java b/src/main/java/com/greate/community/service/UserService.java index 0c42b6e..6f2429e 100644 --- a/src/main/java/com/greate/community/service/UserService.java +++ b/src/main/java/com/greate/community/service/UserService.java @@ -96,24 +96,6 @@ public class UserService implements CommunityConstant { public Map register(User user) { Map map = new HashMap<>(); - if (user == null) { - throw new IllegalArgumentException("参数不能为空"); - } - if (StringUtils.isBlank(user.getUsername())) { - map.put("usernameMsg", "账号不能为空"); - return map; - } - - if (StringUtils.isBlank(user.getPassword())) { - map.put("passwordMsg", "密码不能为空"); - return map; - } - - if (StringUtils.isBlank(user.getEmail())) { - map.put("emailMsg", "邮箱不能为空"); - return map; - } - // 验证账号是否已存在 User u = userMapper.selectByName(user.getUsername()); if (u != null) { -- Gitee From c1cea8ba01c63d516ce0e5d12a0694f4fd7840cc Mon Sep 17 00:00:00 2001 From: xzx <3144790170@qq.com> Date: Sun, 13 Mar 2022 14:36:47 +0800 Subject: [PATCH 096/125] =?UTF-8?q?discuss-mapper.xml=E8=AF=AD=E6=B3=95?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/mapper/discusspost-mapper.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/mapper/discusspost-mapper.xml b/src/main/resources/mapper/discusspost-mapper.xml index 39c059f..17eafff 100644 --- a/src/main/resources/mapper/discusspost-mapper.xml +++ b/src/main/resources/mapper/discusspost-mapper.xml @@ -17,7 +17,7 @@