1 22 23 package org.meshcms.core; 24 25 import java.io.*; 26 import java.net.*; 27 import java.util.*; 28 import java.util.zip.*; 29 import javax.servlet.*; 30 import javax.servlet.http.*; 31 import org.meshcms.util.*; 32 33 36 public final class HitFilter implements Filter { 37 40 public static final String CACHE_FILE_NAME = "_cache.gz"; 41 42 48 public static final String THEME_FILE_ATTRIBUTE = "meshcmstheme"; 49 50 54 public static final String THEME_PATH_ATTRIBUTE = "meshcmsthemepath"; 55 56 public static final String LOCALE_ATTRIBUTE = "meshcmslocale"; 57 58 public static final String LAST_MODIFIED_ATTRIBUTE = "meshcmslastmodified"; 59 60 public static final String BLOCK_CACHE_ATTRIBUTE = "meshcmsnocache"; 61 62 public static final String WEBSITE_ATTRIBUTE = "webSite"; 63 64 68 public static final String HOTLINKING_ALLOWED = "meshcmshotlinkingallowed"; 69 70 75 public static final String ACTION_NAME = "meshcmsaction"; 76 77 81 public static final String ACTION_EDIT = "edit"; 82 83 public static final String ROOT_WEBSITE = "meshcmsrootsite"; 84 85 private FilterConfig filterConfig = null; 86 87 public void init(FilterConfig filterConfig) throws ServletException { 88 this.filterConfig = filterConfig; 89 } 90 91 public void destroy() { 92 this.filterConfig = null; 93 } 94 95 98 public void doFilter(ServletRequest request, ServletResponse response, 99 FilterChain chain) throws IOException, ServletException { 100 if (filterConfig != null && (request instanceof HttpServletRequest)) { 101 ServletContext sc = filterConfig.getServletContext(); 102 HttpServletResponse httpRes = (HttpServletResponse) response; 103 WebSite rootSite = getRootSite(sc, false); 104 WebSite webSite = rootSite.getWebSite(request); 105 106 if (webSite == null) { 107 httpRes.sendError(HttpServletResponse.SC_FORBIDDEN, "Site not found"); 108 return; 109 } 110 111 request.setAttribute(WEBSITE_ATTRIBUTE, webSite); 112 request.setCharacterEncoding(WebSite.SYSTEM_CHARSET); 113 HttpServletRequest httpReq = webSite.wrapRequest(request); 114 Path pagePath = webSite.getRequestedPath(httpReq); 115 116 117 if (webSite instanceof VirtualWebSite && 118 httpReq.getRequestURI().toLowerCase().endsWith(".jsp/")) { 119 httpRes.sendError(HttpServletResponse.SC_NOT_FOUND); 120 return; 121 } 122 123 if (webSite.isDirectory(pagePath)) { 124 Path wPath = webSite.findCurrentWelcome(pagePath); 125 Configuration conf = webSite.getConfiguration(); 126 127 if (conf == null || conf.isAlwaysDenyDirectoryListings()) { 128 if (wPath != null) { 129 redirect(httpReq, httpRes, wPath); 130 } else { 131 httpRes.sendError(HttpServletResponse.SC_FORBIDDEN, 132 "Directory listing denied"); 133 } 134 135 return; 136 } 137 } 138 139 SiteMap siteMap = null; 140 PageInfo pageInfo = null; 141 boolean isAdminPage = false; 142 boolean isGuest = true; 143 String pageCharset = null; 144 145 if (webSite.getCMSPath() != null) { 146 if (pagePath.isContainedIn(webSite.getVirtualSitesPath()) || 147 pagePath.isContainedIn(webSite.getPrivatePath())) { 148 httpRes.sendError(HttpServletResponse.SC_NOT_FOUND); 149 return; 150 } 151 152 siteMap = webSite.getSiteMap(); 153 isAdminPage = pagePath.isContainedIn(webSite.getAdminPath()); 154 HttpSession session = httpReq.getSession(); 155 156 if (webSite.getConfiguration().isSearchMovedPages() && 157 !(isAdminPage || webSite.getFile(pagePath).exists())) { 158 Path redirPath = siteMap.getRedirMatch(pagePath); 159 160 if (redirPath != null) { 161 redirect(httpReq, httpRes, redirPath); 162 return; 163 } 164 } 165 166 UserInfo userInfo = (session == null) ? null : 167 (UserInfo) session.getAttribute("userInfo"); 168 isGuest = userInfo == null || userInfo.isGuest(); 169 170 if (FileTypes.isPage(pagePath.getLastElement())) { 172 178 179 WebUtils.updateLastModifiedTime(httpReq, webSite.getFile(pagePath)); 180 blockRemoteCaching(httpRes); 181 182 Path themePath = null; 184 String themeParameter = request.getParameter(THEME_FILE_ATTRIBUTE); 185 186 if (themeParameter != null) { 187 themePath = (Path) siteMap.getThemesMap().get(themeParameter); 188 } 189 190 if (themePath == null || !webSite.getFile(themePath).exists()) { 191 themePath = webSite.getThemePath(pagePath); 192 } 193 194 if (themePath != null) { request.setAttribute(THEME_PATH_ATTRIBUTE, themePath); 196 197 if (!isAdminPage || themeParameter != null) { 199 request.setAttribute(THEME_FILE_ATTRIBUTE, "/" + 200 webSite.getServedPath(themePath) + "/" + 201 SiteMap.THEME_DECORATOR); 202 } 203 } 204 205 207 if (session != null && webSite.getConfiguration().isPreventHotlinking() && 208 session.getAttribute(HOTLINKING_ALLOWED) == null && !isAdminPage) { 209 session.setAttribute(HOTLINKING_ALLOWED, HOTLINKING_ALLOWED); 210 } 211 } 212 213 if (webSite.getConfiguration().isPreventHotlinking() && 214 FileTypes.isPreventHotlinking(pagePath.getLastElement()) && 215 (session == null || session.getAttribute(HOTLINKING_ALLOWED) == null)) { 216 String agent = httpReq.getHeader("user-agent"); 217 218 if (agent == null || agent.toLowerCase().indexOf("java") < 0) { 219 try { 220 String domain = WebUtils.get2ndLevelDomain(httpReq); 221 222 if (domain != null) { 223 String referrer = httpReq.getHeader("referer"); 224 225 try { 226 referrer = new URL(referrer).getHost(); 227 } catch (Exception ex) { 228 referrer = null; 229 } 230 231 if (referrer == null || referrer.indexOf(domain) < 0) { 232 httpRes.sendRedirect(httpReq.getContextPath() + "/" + 233 webSite.getAdminPath() + "/hotlinking.jsp?path=" + pagePath); 234 return; 235 } 236 } 237 } catch (MalformedURLException ex) {} 238 } 239 } 240 241 pageInfo = siteMap.getPageInfo(pagePath); 242 243 if (pageInfo != null) { if (isGuest) { 245 pageInfo.addHit(); 246 } 247 248 if (pageInfo.getCharset() != null) { 249 pageCharset = pageInfo.getCharset(); 250 } 251 } else { if (isAdminPage && pagePath.getLastElement().endsWith(".js") && 254 userInfo != null && userInfo.canDo(UserInfo.CAN_BROWSE_FILES)) { 255 String script = null; 256 257 if (pagePath.isContainedIn(webSite.getAdminScriptsPath().add("tiny_mce"))) { 258 script = "TinyMCE"; 259 } else if (pagePath.isContainedIn(webSite.getAdminScriptsPath().add("jscalendar"))) { 260 script = "DHTMLCalendar"; 261 } 262 263 if (script != null) { 264 Locale locale = Utils.getLocale(userInfo.getPreferredLocaleCode()); 265 ResourceBundle bundle = 266 ResourceBundle.getBundle("org/meshcms/webui/Locales", locale); 267 String s = bundle.getString(script + "LangCode"); 268 269 if (!Utils.isNullOrEmpty(s) && pagePath.getLastElement().equals(s + ".js")) { 270 s = bundle.getString(script + "LangCharset"); 271 272 if (!Utils.isNullOrEmpty(s)) { 273 pageCharset = s; 274 } 275 } 276 } 277 } } 279 } 281 String mimeType = sc.getMimeType(pagePath.getLastElement()); 282 283 if (mimeType == null) { 284 mimeType = "text/html"; 285 } 286 287 httpRes.setContentType(mimeType + "; charset=" + 288 Utils.noNull(pageCharset, WebSite.SYSTEM_CHARSET)); 289 290 try { 291 if (isGuest && pageInfo != null && 293 httpReq.getMethod().equalsIgnoreCase("get") && 294 Utils.isNullOrEmpty(httpReq.getQueryString()) && 295 webSite.isVisuallyEditable(pagePath)) { 296 int cacheType = webSite.getConfiguration().getCacheType(); 297 298 String ae = httpReq.getHeader("Accept-Encoding"); 300 boolean gzip = ae != null && ae.toLowerCase().indexOf("gzip") > -1; 301 InputStream in = null; 302 303 if (cacheType == Configuration.IN_MEMORY_CACHE) { 304 byte[] pageBytes = siteMap.getCached(pageInfo.getPath()); 305 306 if (pageBytes != null && pageBytes.length > 256) { 308 in = new ByteArrayInputStream(pageBytes); 309 } 310 } else if (cacheType == Configuration.ON_DISK_CACHE) { 311 File cacheFile = WebUtils.getCacheFile(webSite, siteMap, pagePath); 312 313 if (cacheFile != null) { 314 in = new FileInputStream(cacheFile); 315 } 316 } 317 318 if (in != null) { 320 ServletOutputStream sos = response.getOutputStream(); 321 322 if (gzip) { 323 httpRes.setHeader("Content-Encoding", "gzip"); 324 } else { 325 in = new GZIPInputStream(in); 327 } 328 329 Utils.copyStream(in, sos, false); 330 sos.flush(); 331 return; 332 } 333 334 if (cacheType != Configuration.NO_CACHE) { 336 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 337 OutputStream os = new GZIPOutputStream(baos); 338 CacheResponseWrapper wrapper = new CacheResponseWrapper(httpRes, os); 339 chain.doFilter(httpReq, wrapper); 340 wrapper.finishResponse(); 341 343 345 if (!WebUtils.isCacheBlocked(httpReq)) { 346 if (cacheType == Configuration.IN_MEMORY_CACHE) { 347 siteMap.cache(pageInfo.getPath(), baos.toByteArray()); 348 } else if (cacheType == Configuration.ON_DISK_CACHE) { 349 File cacheFile = webSite.getRepositoryFile 350 (siteMap.getServedPath(pagePath), CACHE_FILE_NAME); 351 cacheFile.getParentFile().mkdirs(); 352 Utils.writeFully(cacheFile, baos.toByteArray()); 353 } 354 } 355 356 return; 357 } 358 } 360 chain.doFilter(httpReq, httpRes); 361 webSite.updateSiteMap(false); } catch (Exception ex) { 363 if (isAdminPage) { 364 webSite.setLastAdminThemeBlock(System.currentTimeMillis()); 365 } 366 367 Path wPath = webSite.findCurrentWelcome(pagePath); 368 369 if (wPath != null) { 370 redirect(httpReq, httpRes, wPath); 371 return; 372 } 373 374 sc.log("--------\n\nIMPORTANT: an exception has been caught while serving " + 375 httpReq.getRequestURI(), ex); 376 377 Configuration c = webSite.getConfiguration(); 378 379 if (c == null || c.isHideExceptions()) { 380 httpRes.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 381 } else { 382 throw new ServletException(ex); 383 } 384 } 385 386 return; 387 } 388 389 chain.doFilter(request, response); 391 } 392 393 private static void redirect(HttpServletRequest httpReq, 394 HttpServletResponse httpRes, Path redirPath) throws IOException { 395 blockRemoteCaching(httpRes); 396 String q = httpReq.getQueryString(); 397 398 if (Utils.isNullOrEmpty(q)) { 399 httpRes.sendRedirect(httpReq.getContextPath() + "/" + redirPath); 400 } else { 401 httpRes.sendRedirect(httpReq.getContextPath() + "/" + redirPath + '?' + q); 402 } 403 } 404 405 408 public static WebSite getRootSite(ServletContext sc, boolean alwaysCreate) { 409 WebSite rootSite = (WebSite) sc.getAttribute(ROOT_WEBSITE); 410 411 if (rootSite == null || alwaysCreate) { 412 File rootFile = new File(sc.getRealPath("/")); 413 Path cmsPath = new CMSDirectoryFinder(rootFile, false).getCMSPath(); 414 boolean multisite = false; 415 File sitesDir = new File(rootFile, cmsPath + "/sites"); 416 417 if (sitesDir.isDirectory()) { 418 File[] dirs = sitesDir.listFiles(); 419 420 for (int i = 0; i < dirs.length; i++) { 421 if (dirs[i].isDirectory()) { 422 multisite = true; 423 } 424 } 425 } 426 427 rootSite = multisite ? 428 MainWebSite.create(sc, WebUtils.getWelcomeFiles(sc), rootFile, 429 Path.ROOT, cmsPath) : 430 WebSite.create(sc, WebUtils.getWelcomeFiles(sc), rootFile, 431 Path.ROOT, cmsPath); 432 sc.setAttribute(ROOT_WEBSITE, rootSite); 433 } 434 435 return rootSite; 436 } 437 438 441 public static void blockRemoteCaching(HttpServletResponse httpRes) { 442 httpRes.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); 444 httpRes.setHeader("Pragma", "no-cache"); 446 httpRes.setDateHeader("Expires", -1); 448 } 449 } 450 | Popular Tags |