BrightSide Workbench Full Report + Source Code
ElephantFilter.java
Go to the documentation of this file.
1 /*
2  * TurrĂ³ i Cutiller Foundation. License notice.
3  * Copyright (C) 2011 Lluis TurrĂ³ Cutiller <http://www.turro.org/>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Affero General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Affero General Public License for more details.
14  *
15  * You should have received a copy of the GNU Affero General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 package org.turro.elephant.servlet.context;
19 
20 import java.io.IOException;
21 import java.util.Set;
22 import javax.servlet.Filter;
23 import javax.servlet.FilterChain;
24 import javax.servlet.FilterConfig;
25 import javax.servlet.RequestDispatcher;
26 import javax.servlet.ServletContext;
27 import javax.servlet.ServletException;
28 import javax.servlet.ServletRequest;
29 import javax.servlet.ServletResponse;
30 import javax.servlet.annotation.WebFilter;
31 import javax.servlet.http.HttpServletRequest;
32 import javax.servlet.http.HttpServletResponse;
33 import org.turro.config.Configurator;
34 import org.turro.string.Strings;
35 import org.turro.elephant.context.ElephantContext;
36 import org.turro.elephant.direct.DirectContents;
37 import org.turro.elephant.servlet.crawler.CrawlerOptions;
38 import org.turro.file.Document;
39 import org.turro.http.HttpUtil;
40 import org.turro.http.activity.IActivityOptions;
41 import org.turro.http.activity.IPActivity;
42 import org.turro.util.Cached;
43 
48 @WebFilter(filterName = "ContextFilter", urlPatterns = {"/*"})
49 public class ElephantFilter implements Filter {
50 
51  private FilterConfig filterConfig;
52  private IPActivity ipActivity;
53 
54  @Override
55  public void doFilter(ServletRequest request, ServletResponse response,
56  FilterChain chain)
57  throws IOException, ServletException {
58  if(request instanceof HttpServletRequest httpRequest) {
59  // Performance blocks
60  if(ipActivity.isBlocked(request.getRemoteAddr(), httpRequest.getServletPath(), httpRequest.getHeader("User-Agent"))) {
61  if(response instanceof HttpServletResponse httpResponse) {
62  Document crawlers = Document.from(ElephantContext.getRealPath(CrawlerOptions.CRAWLERS_RESPONSE));
63  httpResponse.setContentType("text/html");
64  httpResponse.setCharacterEncoding(ElephantContext.getEncoding());
65  httpResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
66  httpResponse.getWriter().write(crawlers.content());
67  }
68  return; // blocked
69  // Performance internal calls
70  } else if(!pass(httpRequest.getServletPath())) {
71  if(resource(httpRequest.getServletPath())) {
72  RequestDispatcher rd = getServletContext().getNamedDispatcher("default");
73  if(rd!= null) rd.forward(request, response);
74  return; // resource
75  }
76  if(!checkSchemas(httpRequest, (HttpServletResponse) response)) {
77  return; // redirected
78  }
80  if(!DirectContents.isDirectContent(httpRequest) && checkMobile(httpRequest)) {
81  forwardMobile(httpRequest, response);
82  return; // mobile context
83  }
84  ipActivity.check(request.getRemoteAddr(), httpRequest.getServletPath(), httpRequest.getHeader("User-Agent"));
85  }
86  }
87 
88  chain.doFilter(request, response);
89  }
90 
91  @Override
92  public void init(FilterConfig filterConfig) throws ServletException {
93  this.filterConfig = filterConfig;
94  this.ipActivity = IPActivity.instance(Cached.<IActivityOptions>instance(() -> CrawlerOptions.instance()));
95  }
96 
97  @Override
98  public void destroy() {
99  }
100 
101  private ServletContext getServletContext() {
102  return filterConfig.getServletContext();
103  }
104 
105  private static final Set<String> PASS = Set.of("/zkau", "/tag_", "/ws_", "/up_");
106 
107  private boolean pass(String reqUri) {
108  return PASS.stream().anyMatch(pass -> reqUri.equals(pass) || reqUri.startsWith(pass + "/"));
109  }
110 
111  private boolean resource(String reqUri) {
112  String req = HttpUtil.removeSession(reqUri);
113  return !req.endsWith(".jsp") && req.matches(".*\\.[a-zA-Z0-9]{2,5}");
114  /* && Document.from(getServletContext().getRealPath(reqUri)).exists()*/
115  }
116 
117  private boolean checkSchemas(HttpServletRequest request, HttpServletResponse response) {
118  String forcedDomain = ElephantContext.getSiteForcedDomain(),
119  serverName = request.getServerName(),
120  scheme = request.getScheme();
121  boolean changesDone = false;
122  String url = request.getRequestURL().toString();
123  if(forcedDomain != null && !forcedDomain.equals(serverName)) {
124  url = url.replaceFirst(serverName, forcedDomain);
125  changesDone = true;
126  }
127  if(ElephantContext.getUseSSL() && !"https".equals(scheme)) {
128  url = url.replaceFirst("http\\:", "https:");
129  changesDone = true;
130  }
131  if(changesDone) {
132  String query = request.getQueryString();
133  response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
134  response.setHeader("Location", url + (Strings.isBlank(query) ? "" : "?" + query));
135  response.setHeader( "Connection", "close" );
136  }
137  return !changesDone;
138  }
139 
140  private boolean checkMobile(HttpServletRequest request) {
141  String mobilePath = Configurator.instance().asString("Context.Mobile.Path");
142  return !Strings.isBlank(mobilePath) &&
143  request.getHeader("User-Agent").contains("Mobi") && // Set to ! to test
144  !request.getServletPath().startsWith(mobilePath);
145  }
146 
147  private void forwardMobile(HttpServletRequest request, ServletResponse response) throws ServletException, IOException {
148  String mobilePath = Configurator.instance().asString("Context.Mobile.Path");
149  ((HttpServletResponse) response).sendRedirect(request.getContextPath() +
150  mobilePath + HttpUtil.getServletQuery(request));
151  }
152 
153 }
static void initServerSchemas(HttpServletRequest request)
static boolean isDirectContent(HttpServletRequest request)
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)