Mercurial Hosting > nabble
comparison src/nabble/view/web/tools/SpamSearch.java @ 0:7ecd1a4ef557
add content
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 21 Mar 2019 19:15:52 -0600 |
parents | |
children | 72765b66e2c3 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:7ecd1a4ef557 |
---|---|
1 | |
2 package nabble.view.web.tools; | |
3 | |
4 import com.google.gson.Gson; | |
5 import nabble.model.ModelHome; | |
6 import nabble.model.Node; | |
7 import nabble.model.Site; | |
8 import nabble.view.lib.Jtp; | |
9 import nabble.view.lib.Shared; | |
10 | |
11 import javax.servlet.http.HttpServlet; | |
12 import javax.servlet.http.HttpServletRequest; | |
13 import javax.servlet.http.HttpServletResponse; | |
14 import java.io.IOException; | |
15 import java.io.InputStreamReader; | |
16 import java.io.PrintWriter; | |
17 import java.io.Reader; | |
18 import java.net.URL; | |
19 import java.net.URLEncoder; | |
20 import java.util.List; | |
21 import java.util.regex.Matcher; | |
22 import java.util.regex.Pattern; | |
23 | |
24 | |
25 public final class SpamSearch extends HttpServlet { | |
26 | |
27 private static final String GOOGLE_URL = "http://ajax.googleapis.com/ajax/services/search/web?v=1.0&key=AIzaSyCjUKhbJVpU83CiRPJ1WV1x7WyszYSntC0&q="; | |
28 private static final String CHARSET = "UTF-8"; | |
29 | |
30 private static final Pattern POST_PTN = Pattern.compile("/.*-t(d\\d+)|((p\\d+)(p\\d+)?)\\.html$"); | |
31 | |
32 /** | |
33 * Defines five blocks per page because google usually returns a block with four results. | |
34 * So it shows 20 results per page. | |
35 */ | |
36 private static final int BLOCKS_PER_PAGE = 6; | |
37 | |
38 static String extractDomain(String url) { | |
39 int posDoubleSlash = url.indexOf("://"); | |
40 if (posDoubleSlash == -1) | |
41 return null; | |
42 int posNextSlash = url.indexOf('/', posDoubleSlash+3); | |
43 return url.substring(posDoubleSlash+3, posNextSlash); | |
44 } | |
45 | |
46 private static Long getPostId(String url) { | |
47 Matcher m = POST_PTN.matcher(url); | |
48 if (m.find()) { | |
49 if (m.group(4) != null) | |
50 return Long.valueOf(m.group(4).substring(1)); | |
51 else if (m.group(3) != null) | |
52 return Long.valueOf(m.group(3).substring(1)); | |
53 else if (m.group(1) != null) | |
54 return Long.valueOf(m.group(1).substring(1)); | |
55 } | |
56 return null; | |
57 } | |
58 | |
59 private static Long getSiteId(String domain) { | |
60 if (domain.endsWith(Jtp.getDefaultHost())) { | |
61 domain = domain.replace('.'+Jtp.getDefaultHost(), ""); | |
62 int dot = domain.lastIndexOf('.'); | |
63 return Long.valueOf(domain.substring(dot+1)); | |
64 } | |
65 return null; | |
66 } | |
67 | |
68 public void printResult(GoogleResults results, int j, PrintWriter out) { | |
69 if (results.getResponseData() != null) { | |
70 GoogleResults.Result result = results.getResponseData().getResults().get(j); | |
71 String url = result.getUrl(); | |
72 String title = result.getTitle(); | |
73 String content = result.getContent(); | |
74 | |
75 Long siteId = null; | |
76 Long postId = getPostId(url); | |
77 if (postId != null) { | |
78 String domain = extractDomain(url); | |
79 if (domain != null) { | |
80 siteId = getSiteId(domain); | |
81 siteId = siteId == null? ModelHome.getSiteIdFromDomain(domain) : siteId; | |
82 } | |
83 } | |
84 Site site = siteId == null? null : ModelHome.getSite(siteId); | |
85 Node node = site == null? null : site.getNode(postId); | |
86 | |
87 out.print( "\r\n" ); | |
88 if (node != null && !node.getMessage().isDeleted()) { | |
89 out.print( "\r\n <tr>\r\n <td><input type=\"checkbox\" class=\"checkBox\" value=\"" ); | |
90 out.print( (siteId) ); | |
91 out.print( "|" ); | |
92 out.print( (postId) ); | |
93 out.print( "\" name=\"results\"/></td>\r\n <td>\r\n <a href=\"" ); | |
94 out.print( (url) ); | |
95 out.print( "\">" ); | |
96 out.print( (title) ); | |
97 out.print( "</a><br/>\r\n <div class=\"clickable\">\r\n <span class='url'>" ); | |
98 out.print( (url) ); | |
99 out.print( "</span><br/>\r\n " ); | |
100 out.print( (content) ); | |
101 out.print( "<br/>\r\n " ); | |
102 if (node.getDescendantCount() > 1) { | |
103 out.print( "\r\n <span class=\"badge\" style=\"font-weight:bold;background:red;color:white\">Has Replies</span>\r\n " ); | |
104 } | |
105 out.print( "\r\n " ); | |
106 Node.MailToList mail = node.getMailToList(); | |
107 out.print( "\r\n " ); | |
108 if (mail != null && mail.isPending()) { | |
109 out.print( "\r\n <span class=\"badge\" style=\"font-weight:bold;background:green;color:white\">Pending</span>\r\n " ); | |
110 } | |
111 out.print( "\r\n </div>\r\n </td>\r\n </tr>\r\n" ); | |
112 } else { | |
113 out.print( "\r\n <tr>\r\n <td></td>\r\n <td class=\"grayP\">\r\n <a href='" ); | |
114 out.print( (url) ); | |
115 out.print( "'>" ); | |
116 out.print( (title) ); | |
117 out.print( "</a><br/>\r\n <span class='url'>" ); | |
118 out.print( (url) ); | |
119 out.print( "</span><br/>\r\n " ); | |
120 out.print( (content) ); | |
121 out.print( "\r\n </td>\r\n </tr>\r\n" ); | |
122 } | |
123 out.print( "\r\n" ); | |
124 | |
125 } | |
126 } | |
127 | |
128 public void getResults(String query, String site,HttpServletRequest request,PrintWriter out) | |
129 throws IOException | |
130 { | |
131 int start = 0; | |
132 int page = 0; | |
133 | |
134 if(request.getParameter("start") != null) | |
135 start = Integer.parseInt(request.getParameter("start")); | |
136 | |
137 if(request.getParameter("page") != null) | |
138 page = Integer.parseInt(request.getParameter("page")); | |
139 | |
140 if(!"".equals(query)) { | |
141 | |
142 out.print( "\r\n<div>Page " ); | |
143 out.print( (page) ); | |
144 out.print( "</div>\r\n<table>\r\n" ); | |
145 | |
146 for (int k = 0; k < BLOCKS_PER_PAGE; k++) { | |
147 URL url = new URL(GOOGLE_URL+ URLEncoder.encode("site:"+site+" "+query, CHARSET)+"&start="+start ); | |
148 Reader reader = new InputStreamReader(url.openStream(), CHARSET); | |
149 GoogleResults results = new Gson().fromJson(reader, GoogleResults.class); | |
150 if (results.getResponseData() != null) { | |
151 int block_size = results.getResponseData().getResults().size(); | |
152 start += block_size; | |
153 for (int j = 0; j < block_size; j++) { | |
154 printResult(results,j,out); | |
155 } | |
156 } | |
157 } | |
158 | |
159 out.print( "\r\n</table>\r\n<br />\r\nPage " ); | |
160 out.print( (page) ); | |
161 out.print( " –\r\n<a href='?start=" ); | |
162 out.print( (start) ); | |
163 out.print( "&site=" ); | |
164 out.print( (site) ); | |
165 out.print( "&query=" ); | |
166 out.print( (query) ); | |
167 out.print( "&page=" ); | |
168 out.print( ((page+1)) ); | |
169 out.print( "'>Next</a>\r\n<br />\r\n<br />\r\n<input type=\"submit\" value=\"Delete Selected Posts\" />\r\n" ); | |
170 | |
171 } | |
172 } | |
173 | |
174 | |
175 protected void service(HttpServletRequest request,HttpServletResponse response) | |
176 throws IOException | |
177 { | |
178 String query = request.getParameter("query"); | |
179 query = query == null? "" : query; | |
180 | |
181 String site = request.getParameter("site"); | |
182 site = site == null? Jtp.getDefaultHost() : site; | |
183 | |
184 boolean isDelete = "POST".equals(request.getMethod()) && "delete".equals(request.getParameter("action")); | |
185 int deleteCounter = 0; | |
186 if (isDelete) { | |
187 String[] results = request.getParameterValues("results"); | |
188 for (String r : results) { | |
189 String[] parts = r.split("\\|"); | |
190 long siteId = Long.valueOf(parts[0]); | |
191 long nodeId = Long.valueOf(parts[1]); | |
192 Node n = ModelHome.getSite(siteId).getNode(nodeId); | |
193 if (n != null) { | |
194 n.deleteMessageOrNode(); | |
195 deleteCounter++; | |
196 } | |
197 } | |
198 } | |
199 | |
200 PrintWriter out = response.getWriter(); | |
201 | |
202 out.print( "\r\n<html>\r\n <head>\r\n <title>Nabble Search</title>\r\n " ); | |
203 Shared.loadJavascript(request, out); | |
204 out.print( "\r\n " ); | |
205 javascript(out); | |
206 out.print( "\r\n " ); | |
207 css(out); | |
208 out.print( "\r\n </head>\r\n <body>\r\n <h1>Nabble Search</h1>\r\n <form action=\"SpamSearch.jtp\" method=\"get\">\r\n Search for <input type=\"text\" name=\"query\" value=\"" ); | |
209 out.print( (query) ); | |
210 out.print( "\" /> in <input type=\"text\" name=\"site\" value=\"" ); | |
211 out.print( (site) ); | |
212 out.print( "\" />\r\n <input type=\"submit\" value=\"Search\" />\r\n <input type=\"hidden\" value=\"0\" name=\"start\" />\r\n <input type=\"hidden\" value=\"1\" name=\"page\" />\r\n </form>\r\n " ); | |
213 if (isDelete) { | |
214 out.print( "\r\n <div style=\"color:red;padding:.5em 0\">Deleted " ); | |
215 out.print( (deleteCounter) ); | |
216 out.print( " nodes.</div>\r\n " ); | |
217 } | |
218 out.print( "\r\n <div id='results'>\r\n <form action=\"SpamSearch.jtp\" method=\"post\">\r\n <input type=\"hidden\" value=\"delete\" name=\"action\" />\r\n <input type=\"hidden\" name=\"query\" value=\"" ); | |
219 out.print( (query) ); | |
220 out.print( "\"/>\r\n <input type=\"hidden\" name=\"site\" value=\"" ); | |
221 out.print( (site) ); | |
222 out.print( "\" />\r\n " ); | |
223 getResults(query,site,request,out); | |
224 out.print( "\r\n </form>\r\n </div>\r\n </body>\r\n</html>\r\n" ); | |
225 | |
226 } | |
227 | |
228 private void javascript(PrintWriter out) { | |
229 | |
230 out.print( "\r\n <script type=\"text/javascript\">\r\n $(document).ready(function() {\r\n $('div.clickable').each(function() {\r\n var $this = $(this);\r\n var $checkbox = $this.parent().prev().children().eq(0);\r\n $this.click(function() {\r\n var checked = $checkbox.attr('checked');\r\n if (checked) {\r\n $this.removeClass('selected-row');\r\n $checkbox.removeAttr('checked');\r\n } else {\r\n $this.addClass('selected-row');\r\n $checkbox.attr('checked', true);\r\n }\r\n });\r\n });\r\n });\r\n </script>\r\n" ); | |
231 | |
232 } | |
233 private void css(PrintWriter out) { | |
234 | |
235 out.print( "\r\n<style type=\"text/css\">\r\n body {\r\n padding: 1em;\r\n font-family: Verdana, Sans-serif;\r\n font-size:.84em;\r\n }\r\n span.url{\r\n color: green;\r\n }\r\n #results table {\r\n width: 100%;\r\n }\r\n #results table td {\r\n vertical-align:top;\r\n padding-bottom: 1em;\r\n }\r\n #results td.grayP , td.grayP a , td.grayP span {\r\n color: #C8C8C8 !important;\r\n }\r\n form input {\r\n margin-bottom: 15px;\r\n }\r\n span.badge {\r\n font-size:90%;\r\n -moz-border-radius: 5px;\r\n -webkit-border-radius: 5px;\r\n border-radius: 5px;\r\n padding: .2em .4em;\r\n }\r\n div.clickable { cursor:pointer; }\r\n .selected-row { background:#ffffcc; }\r\n</style>\r\n" ); | |
236 | |
237 } | |
238 } | |
239 | |
240 | |
241 class GoogleResults { | |
242 | |
243 private ResponseData responseData; | |
244 public ResponseData getResponseData() { return responseData; } | |
245 public void setResponseData(ResponseData responseData) { this.responseData = responseData; } | |
246 public String toString() { return "ResponseData[" + responseData + "]"; } | |
247 | |
248 static class ResponseData { | |
249 private List<Result> results; | |
250 public List<Result> getResults() { return results; } | |
251 public void setResults(List<Result> results) { this.results = results; } | |
252 public String toString() { return "Results[" + results + "]"; } | |
253 } | |
254 | |
255 static class Result { | |
256 private String url; | |
257 private String title; | |
258 private String content; | |
259 public String getUrl() { return url; } | |
260 public String getTitle() { return title; } | |
261 public String getContent() { return content; } | |
262 public void setUrl(String url) { this.url = url; } | |
263 public void setTitle(String title) { this.title = title; } | |
264 public String toString() { return "Result[url:" + url +",title:" + title + "]"; } | |
265 } | |
266 } | |
267 | |
268 | |
269 |