All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sk.iway.iwcm.PathFilter Maven / Gradle / Ivy

package sk.iway.iwcm;

import org.apache.commons.codec.binary.Base64;
import org.apache.struts.util.TokenProcessor;
import org.springframework.web.util.NestedServletException;
import sk.iway.iwcm.analytics.AnalyticsHelper;
import sk.iway.iwcm.common.*;
import sk.iway.iwcm.components.abtesting.ABTesting;
import sk.iway.iwcm.components.domainRedirects.DomainRedirectDB;
import sk.iway.iwcm.components.response_header.rest.ResponseHeaderService;
import sk.iway.iwcm.dmail.Sender;
import sk.iway.iwcm.doc.DebugTimer;
import sk.iway.iwcm.doc.DocDB;
import sk.iway.iwcm.doc.DocDetails;
import sk.iway.iwcm.doc.GroupDetails;
import sk.iway.iwcm.doc.ninja.Ninja;
import sk.iway.iwcm.filebrowser.EditForm;
import sk.iway.iwcm.i18n.Prop;
import sk.iway.iwcm.io.*;
import sk.iway.iwcm.stat.BrowserDetector;
import sk.iway.iwcm.stat.SessionHolder;
import sk.iway.iwcm.stat.StatDB;
import sk.iway.iwcm.system.WJResponseWrapper;
import sk.iway.iwcm.system.context.ContextFilter;
import sk.iway.iwcm.system.ntlm.AuthenticationFilter;
import sk.iway.iwcm.system.stripes.CSRF;
import sk.iway.iwcm.users.UsersDB;

import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.PageContext;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.SocketException;
import java.net.URL;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.*;

/**
 * Filter premapovava volania na virtualne adresare a stranky do volani na
 * spravne docid
 *
 * @Title WebJET
 * @Company Interway s.r.o. (www.interway.sk)
 * @Copyright Interway s.r.o. (c) 2001-2002
 * @author Craig McClanahan
 * @version $Revision: 1.4 $ $Date: 2004/03/01 17:03:45 $
 * @created Nede?e, 2002, okt?ber 27
 * @modified $Date: 2004/03/01 17:03:45 $
 */
@SuppressWarnings("java:S1075")
public class PathFilter implements Filter
{
	private static final String CHECK_ADMIN_SESSION_KEY = "pathFilter.checkAdmin";
	private static final String CHECK_WEB_ACCESS_SESSION_KEY = "pathFilter.checkWebAccess";
	private static final String CHECK_DOMAIN_SESSION_KEY = "pathFilter.checkDomain";
	private static String customPath = null;
	private static Map passwordProtected;
	public static final String REQUEST_START_TIME = "pathFilet.requestStartTime";

	private static String[] bypassPath = null;
	//pocet sekund cache pre staticky obsah
	private static int cacheStaticContentSeconds = -1;
	private static String[] cacheStaticContentSuffixes = null;

	private static List responseHeaders;

	private static Map dynamicForwards;

	/**
	 * Inicializacia servletu
	 */
	@Override
	public void init(FilterConfig filterConfig) throws ServletException
	{
		//tu nemozeme pouzivat logger pretoze toto sa vola skor ako zbehne InitServlet
		Logger.info(PathFilter.class, "PathFilter init");
		try
		{
			//inicializuj password protected
			//robime az v doFilter reloadProtectedDirs();

			PathFilter.setCustomPath(filterConfig.getInitParameter("customPath"));
			//aby bolo mozne nastavit aj cez -Dwebjet.customPath=...
			String systemParam = System.getProperty("webjet.customPath");
			if (Tools.isNotEmpty(systemParam)) PathFilter.setCustomPath(systemParam);
			prepareTemplates();
		}
		catch (Exception e)
		{
			sk.iway.iwcm.Logger.error(e);
		}
	}

	public static void registerDynamicForward(String name, DynamicForward dynamicForward)
	{
		if (dynamicForwards==null) dynamicForwards = Collections.synchronizedMap(new HashMap());
		dynamicForwards.put(name, dynamicForward);
	}

	public static void unregisterDynamicForward(String name)
	{
		if (dynamicForwards==null) return;
		if (dynamicForwards.containsKey(name)) dynamicForwards.remove(name);
	}

	public static void prepareTemplates()
	{
		if (Tools.isNotEmpty(customPath))
		{
			//tu nemozeme pouzivat logger pretoze toto sa vola skor ako zbehne InitServlet
			Logger.info(PathFilter.class, "PathFilterInit - customPath: " + customPath + File.separatorChar + Constants.getInstallName());
			//skopiruj templates do custom adresara
			File templatesDir = new File(customPath + File.separatorChar + Constants.getInstallName() + File.separatorChar
					+ "/templates/");
			if (templatesDir.exists())
			{
				File f;
				f = new File(Tools.getRealPath("/templates/" + Constants.getInstallName() + "/"));
				if (f.exists() == false)
				{
					//vytvor adresar
					if(f.mkdirs() == false) return;
				}
				File[] listFiles = templatesDir.listFiles();
				int size = listFiles.length;
				int i;
				File outFile;
				for (i = 0; i < size; i++)
				{
					f = listFiles[i];
					//Logger.println(this,"copy: " + f.getName());
					outFile = new File(Tools.getRealPath(
							"/templates/" + Constants.getInstallName() + "/" + f.getName()));
					if (outFile.exists() == false || outFile.lastModified() < f.lastModified())
					{
						//skopiruj subory
						FileTools.copyFile(f, outFile);
					}
				}
			}
		}
	}

	public static String getCustomPath()
	{
		return(customPath);
	}

	/**
	 * Vrati REAL PATH pre zadane URL aj s detekciou Custom Path (pouzitelne len pre staticke subory)
	 * @param url
	 * @return
	 */
	public static String getCustomPathRealPath(String url)
	{
		String realPath = PathFilter.getRealPath(url);
		if (PathFilter.getCustomPath() != null)
		{
			//skontroluj, ci pozadovany subor nie je custom
			IwcmFile fCusom = new IwcmFile(PathFilter.getCustomPath() + File.separatorChar + Constants.getInstallName() + url.replace('/', File.separatorChar));
			if (fCusom.exists() && fCusom.canRead()) realPath = fCusom.getAbsolutePath();
		}
		return realPath;
	}

	/**
	 * Take this filter out of service.
	 */
	@Override
	public void destroy()
	{
		//
	}

	/**
	 * Select and set (if specified) the character encoding to be used to
	 * interpret request parameters for this request.
	 *
	 * @param chain
	 *           The filter chain we are processing
	 * @exception IOException
	 *               if an input/output error occurs
	 * @exception ServletException
	 *               if a servlet error occurs
	 */
	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException
	{
		String path = null;
		DebugTimer timer = null;

		HttpServletRequest req = (HttpServletRequest) servletRequest;
		HttpServletResponse res = (HttpServletResponse) servletResponse;

		try
		{
			if (passwordProtected==null) reloadProtectedDirs();

			//System.out.println("PathFilter.doFilter: "+servletRequest.getClass());
			//System.out.println("PathFilter.doFilter: "+(servletRequest instanceof HttpServletRequest));

			//req.setCharacterEncoding("windows-1250");
			//req.setAttribute("SetCharacterEncodingFilter.encoding", "windows-1250");

			path = req.getRequestURI();
			if (Tools.isNotEmpty(req.getContextPath()))
			{
				path = path.substring(req.getContextPath().length());
			}
			if (path.contains("//"))
			{
				path = Tools.replace(path, "/////", "/");
				path = Tools.replace(path, "////", "/");
				path = Tools.replace(path, "///", "/");
				path = Tools.replace(path, "//", "/");
				res.setStatus(302);

				StringBuilder redir = new StringBuilder();
				redir.append(Tools.sanitizeHttpHeaderParam(path));
				String qs = req.getQueryString();
				if (Tools.isNotEmpty(qs)) redir.append('?').append(qs);

				res.setHeader("Location", redir.toString());
				//res.sendRedirect(path);
				return;
			}

			//Logger.println(this,"query string PATH FILTER=" + req.getQueryString());
			String qs = req.getQueryString();
			boolean isFirstPathFilterCall = (req.getAttribute("path_filter_orig_path")==null);
			req.setAttribute("path_filter_query_string", qs);
			req.setAttribute("path_filter_orig_path", path);

			setNginxProxyMode(req, res);
			setXFrameOptions(res);
			setAccessControlAllowOrigin(path, res);
			setXXssProtection(res);
			setFeaturePolicy(res);
			setXRobotsTagValue(path, res);
			setResponseHeaders(path, req, res);

			//blokovanie akcie /showdoc.do
			if(path.startsWith("/showdoc.do") && !"*".equals(Constants.getString("showDocActionAllowedDocids")))
			{
				int docId = Tools.getIntValue(req.getParameter("docid"), -1);
				Identity user = (Identity)req.getSession().getAttribute(Constants.USER_KEY);

				if (Tools.isEmpty(Constants.getString("showDocActionAllowedDocids"))
						|| ((user == null || !user.isAdmin()) && path.startsWith("/showdoc.do") && !isShowDocAllowDocId(docId, "showDocActionAllowedDocids")))
				{
					Adminlog.add(Adminlog.TYPE_CLIENT_SPECIFIC, "Nepovolene pouzitie /showdoc.do docId:"+docId+" showDocActionAllowedDocids : "+ Constants.getString("showDocActionAllowedDocids"), -1, -1);
					res.setStatus(HttpServletResponse.SC_NOT_FOUND);
					forwardSafely("/404.jsp", req, res);
					return;
				}
			}

			if (Constants.getInt("linkType") == Constants.LINK_TYPE_HTML && path.startsWith("/showdoc.do") && isFirstPathFilterCall &&
					req.getParameterMap().size()==1 && req.getParameter("docid")!=null		)
			{
				//presmeruj sa na stranku v HTML formate
				int docId = Tools.getIntValue(req.getParameter("docid"), -1);
				if (docId > 0)
				{
					DocDB docDB = DocDB.getInstance();
					if (InitServlet.isTypeCloud() || (Constants.getBoolean("enableStaticFilesExternalDir") && Constants.getBoolean("multiDomainEnabled")))
					{
						DocDetails doc = DocDB.getInstance().getBasicDocDetails(docId, true);
						if (doc!=null)
						{
							GroupDetails group = GroupDetails.getById(doc.getGroupId());
							//MBO: Ak je zapnuty Cloud, otestuje, ci je dany DOC dostupny pre tuto domenu, ak nie, nevykona redirect ale hodi 404
							if (group==null || !group.getDomainName().equals(CloudToolsForCore.getDomainName()))
							{
								Logger.debug(PathFilter.class, "DOC ID="+docId+" is not allowed for domain "+ CloudToolsForCore.getDomainName());
								res.setStatus(HttpServletResponse.SC_NOT_FOUND);
								forwardSafely("/404.jsp", req, res);
								return;
							}
						}
					}
					String redirPath = docDB.getDocLink(docId, req);

					if (redirPath.startsWith("/showdoc.do")==false && Tools.isNotEmpty(redirPath))
					{
						res.setStatus(301);
						//zrusene, pridanie domeny je zbytocne a potom to zle presmerovava ak sme na inom ako 80 porte if (redirPath.toLowerCase().startsWith("http")==false) redirPath = Tools.getBaseHref(req)+redirPath;
						res.setHeader("Location", redirPath);
						//res.sendRedirect(redirPath);
								/*if (timer != null)		//dead code
								{
									timer.diff("   Path filter - chain, path: " + path);
									DBPool.getInstance().logConnections();
								}*/
						return;
					}
				}
			}

			if (path.indexOf('\'')!=-1 || path.indexOf('"')!=-1 || path.indexOf('\r')!=-1 || path.indexOf('\n')!=-1 ||
				path.contains("%0D") || path.contains("%0A") || path.contains("%0d") || path.contains("%0a") || //crlf utok
				req.getRequestURI().indexOf("//")!=-1 || path.indexOf('\\')!=-1 || path.indexOf("/../")!=-1)
			{
				if (DocTools.isXssStrictUrlException(path, "xssProtectionStrictGetUrlException")==false)
				{
					//je to pokus o XSS: /404.html/'onmouseover=prompt(915761)
					Adminlog.add(Adminlog.TYPE_XSS, "XSS path="+path, -1, -1);
					res.setStatus(HttpServletResponse.SC_FORBIDDEN);
					forwardSafely("/403.jsp", req, res);
					return;
				}
			}

			if (Tools.replace(path.toLowerCase(), ";jsessionid", "jsessionid").contains(";"))
			{
				//utok typu /;/admin/help/search.jsp, povolene je len ;jsessionid
				res.setStatus(HttpServletResponse.SC_NOT_FOUND);
				forwardSafely("/404.jsp", req, res);
				return;
			}

			//povolenie swagger-ui / defaultnej stranky Apache CXF (/ws)
         if (path.contains("/swagger") || path.contains("/v2/api-docs") || path.equals("/ws") || path.equals("/ws/"))
         {
            boolean swaggerEnabled = Constants.getBoolean("swaggerEnabled");
            if (swaggerEnabled)
            {
               //testni, ci je povoleny aj pre neadmina
               if (Constants.getBoolean("swaggerRequireAdmin"))
               {
                  Identity user = UsersDB.getCurrentUser(req);
                  if (user==null || user.isAdmin()==false) swaggerEnabled = false;
               }
            }

            if (swaggerEnabled==false)
            {
               Adminlog.add(Adminlog.TYPE_XSS, "Swagger path is not enabled (conf. swaggerEnabled=false), path="+path, -1, -1);
               res.setStatus(HttpServletResponse.SC_NOT_FOUND);
               forwardSafely("/404.jsp", req, res);
					return;
            }
         }

			if (path.contains(".DS_Store") || path.contains("debug.") || path.contains("config.properties"))
			{
				res.setStatus(HttpServletResponse.SC_NOT_FOUND);
				forwardSafely("/404.jsp", req, res);
				return;
			}

			//pred bypass NESMIE byt citany ziaden parameter!!!
			if ("true".equals(servletRequest.getAttribute("PathFilter.bypass")))
			{
				//request ziadno nemodifikujeme
				try
				{
					chain.doFilter(servletRequest, servletResponse);
				}
				catch (SocketException se)
				{
					//toto neriesime
				}
				return;
			}

			//STRICT XSS FILTER (aplikuje sa na vsetky HTTP poziadavky)
			String strictXssRedirect = DocTools.getXssStrictUrlRedirect(req, path, qs);
			if (strictXssRedirect != null)
			{
				res.sendRedirect(strictXssRedirect);
				return;
			}

			req.setAttribute("path_filter_orig_docid", req.getParameter("docid"));

			if ("true".equals(req.getHeader("userInServletContext")))
			{
				Identity user2 = (Identity)Constants.getServletContext().getAttribute(Constants.USER_KEY);
				if (user2 != null)
				{
					LogonTools.setUserToSession(req.getSession(), user2);
					req.setAttribute("NO WJTOOLBAR", "true");
				}
			}

			//kontrola IP adries pre web sidlo, ci sa moze zobrazit
			if (!checkWebAccess(req, path))
			{
				Logger.debug(PathFilter.class, "checkWebAccess=false, forbidden access, path="+path+" ip="+Tools.getRemoteIP(req));
				res.setStatus(HttpServletResponse.SC_FORBIDDEN);
				forwardSafely("/403.jsp", req, res);
				return;
			}

			//kontrola na domenove presmerovania
			String serverName = Tools.getServerName(req, false);
			String redir = DomainRedirectDB.translate(serverName, path, req.getQueryString(), Tools.isSecure(req));
			if (redir != null)
			{
				res.setStatus(301);
				res.setHeader("Location", redir);
				return;
			}

			//System.out.println("PathFilter.doFilter path="+path);

			req.setAttribute(REQUEST_START_TIME, System.currentTimeMillis());

			Identity user = (Identity)req.getSession().getAttribute(Constants.USER_KEY);

			if (path.startsWith("/private/rest/") || path.startsWith("/rest/private/") || path.startsWith("/rest/admin/") || path.startsWith("/websocket/private/") || path.startsWith("/websocket/admin/"))
			{
				if (user == null || ( user.isAdmin()==false && path.contains("/admin/") ))
				{
					Logger.debug(PathFilter.class, "Nepovoleny pristup k REST/WS");
					res.setStatus(HttpServletResponse.SC_FORBIDDEN);
               return;
				}
			}

            ///// SPRING INTEGRACIA
            // ak sa nezacina na /spring (aby sa to necyklilo) a ak je to url ktoru pozna spring, forwardne to na spring servlet
            if (dynamicForwards!=null && !dynamicForwards.isEmpty())
            {
                boolean adminAccessAllowed = checkAccessToAdmin(path, req, res);
                boolean privateAccessAllowed = true;
                if (path.startsWith("/private") && UsersDB.getCurrentUser(req.getSession())==null) privateAccessAllowed = false;

                for (DynamicForward df : dynamicForwards.values())
                {
                    if (df.isValid(path))
                    {
                        if (adminAccessAllowed && privateAccessAllowed)
                        {
									boolean returnAfterForward = df.forward(path, req, res);
									if (returnAfterForward) return;
                        }
                        else
                        {
                        	//ak nie je user prihlaseny a zacina to na /components a neobsahuje rest, tak posli na 403.jsp kde ho moze redirectnut do admin casti (na logon)
									if (path.startsWith("/components") && path.contains("rest")==false)
									{
										res.setStatus(HttpServletResponse.SC_FORBIDDEN);
										forwardSafely("/403.jsp", req, res);
										return;
									}
                           res.setStatus(HttpServletResponse.SC_FORBIDDEN);
                           return;
                        }
                    }
                }
            }

            //toto musi byt az za Springom, aby pre Spring isli aj ostatne HTTP metody
            if (Constants.getBoolean("enableUnsafeHttpMethods") == false && path.contains("/rest")==false)
            {
                String method = req.getMethod().toUpperCase();
                //IE zial robi dotaz na SVG aj ako HEAD, takze to musime mat ako vynimku
                if (path.endsWith(".svg") && "HEAD".equals(method)) method = "allowedSVG";

                //vynimka pre uptimerobot.com, pouzivaju to v statnej sprave
                if ("HEAD".equals(method) || "TRACE".equals(method) || "OPTIONS".equals(method))
                {
                    String userAgent = req.getHeader("User-Agent");
                    if (Tools.isNotEmpty(userAgent) && userAgent.contains("uptimerobot.com"))
                    {
                        method = "allowedUptimerobot";
                    }
                }

                if ("HEAD".equals(method) || "TRACE".equals(method) || "OPTIONS".equals(method))
                {
                    //je to pokus o XSS: /404.html/'onmouseover=prompt(915761)
                    Adminlog.add(Adminlog.TYPE_XSS, "HTTP method not allowed: "+method, -1, -1);
                    res.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
                    forwardSafely("/403.jsp", req, res);
                    return;
                }
            }

			String logLevel = req.getParameter("_logLevel");
			if (logLevel != null) {
				Logger.setWJLogLevel(logLevel);
			}

			if (Logger.isLevel(Logger.DEBUG) && path.indexOf("refresher")==-1 && (path.endsWith(".do") || path.endsWith(".jsp") || path.endsWith(".html") || path.endsWith(".js") || path.endsWith(".htc")))
			{
				if (req.getParameter("showPathFilterTime")!=null || req.getSession().getAttribute("pathFilter.showPathFilterTime")!=null)
				{
					req.getSession().setAttribute("pathFilter.showPathFilterTime", "true");
					timer = new DebugTimer("PathFilter");
				}
				Logger.debug(PathFilter.class, path);
			}

			//trackovanie videni emailu
			String trackGif = Constants.getString("dmailTrackopenGif");
			if(Tools.isNotEmpty(trackGif))
			{
				if(path.contains(trackGif))
				{
					int emailId = Tools.getIntValue(req.getParameter("emailId"), -1);
					if (emailId > 0)
					{
						EmailToolsForCore.addStatOpen(emailId);
					}
				}
			}

			// url tracking with GA or something else
			AnalyticsHelper.track(path, req);

			//trackovanie kliknuti na linku v emaile
			String dmailStatParamValue = req.getParameter(Constants.getString("dmailStatParam"));
			if (Tools.isNotEmpty(dmailStatParamValue))
			{
				int emailId = Sender.getEmailIdFromClickHash(dmailStatParamValue);
				if (emailId > 0)
				{
					String extURL = req.getParameter("extURL");
					if (Tools.isNotEmpty(extURL))
					{
						if (extURL.toLowerCase().trim().startsWith("http")==false)
						{
							try
							{
								String extURL2 = Tools.replace(extURL, "|", "=");
								Base64 b64 = new Base64();
								extURL = new String(b64.decode(extURL2.getBytes()));
							}
							catch (Exception e)
							{
								sk.iway.iwcm.Logger.error(e);
							}
						}
						EmailToolsForCore.addStatClick(emailId, extURL, req.getQueryString(), req, res);
						res.sendRedirect(extURL.replaceAll("[\r\n]", ""));
						return;
					}
					else
					{
						EmailToolsForCore.addStatClick(emailId, path, req.getQueryString(), req, res);
					}
				}
			}

			//kontrola jsessionid v URL, vynimka pre .jsessionid. je pre grpd cookie modul kde sa edituje takyto kluc
			if (path.toLowerCase().contains("jsessionid") || (req.getQueryString()!=null && req.getQueryString().toLowerCase().contains("jsessionid") && req.getQueryString().toLowerCase().contains(".jsessionid.")==false) || req.isRequestedSessionIdFromURL())
			{
				String description = "SESSION using jsessionid INVALIDATING, sessionId="+req.getSession().getId()+" req IP="+Tools.getRemoteIP(req);
				Logger.error(PathFilter.class, description);

				//toto stale hlasi acunetix ovs ako neriesene, toto je pokus o riesenie
				req.getSession().invalidate();
				req.getSession(true);

				String pathFixed = path;
				int i = pathFixed.toLowerCase().indexOf(";jsessionid");
				if (i > 0) pathFixed = pathFixed.substring(0, i);

				i = pathFixed.toLowerCase().indexOf("jsessionid");
				if (i > 0) pathFixed = pathFixed.substring(0, i);

				res.sendRedirect(pathFixed);
				return;
			}

			SessionHolder holder = SessionHolder.getInstance();
			if (
					"get".equalsIgnoreCase(req.getMethod())==false ||
				 	((path.endsWith(".do") || path.endsWith(".jsp") || path.endsWith(".html") || path.endsWith("/") || path.endsWith(".action")) && path.contains("/admin/") && !path.contains("/scripts/"))
				)
			{
				//	setni data pre SessionListener - admin cast (ostatne stranky su az dole)
				if (holder.set(req.getSession().getId(), path, req)==false)
				{
					//nastalo session stealing, spravime redirect aby nenastavali exception v JSP

					StringBuilder redirPath = new StringBuilder(path);
					if (Tools.isNotEmpty(req.getQueryString())) redirPath.append('?').append(req.getQueryString());

					res.sendRedirect(Tools.sanitizeHttpHeaderParam(redirPath.toString()));
					return;
				}
			}

			if (path.startsWith("/admin"))
			{
				boolean ret = checkAdmin(req);
				if (!ret)
				{
					Logger.debug(PathFilter.class, "checkAdmin="+ret+" forwarding to 404.jsp");
					//not found posielame aby sa admin cast tvarila akoze vobec neexistuje
					res.setStatus(HttpServletResponse.SC_NOT_FOUND);
					forwardSafely("/404.jsp", req, res);
					return;
				}
				else
				{
					// cesta /admin/statchart je tam kvoli generovaniu PDF aby ho bolo mozne unsecure embednut
					if (Constants.getBoolean("adminRequireSSL") && Tools.isSecure(req) == false && path.indexOf("/admin/statchart")==-1)
					{
						String httpsRedirectUrl = PathFilter.getHttpsRedirectUrl(req);
						Logger.debug(PathFilter.class, "Redirect (adminRequireSSL): " + httpsRedirectUrl);
						res.sendRedirect(httpsRedirectUrl);
						return;
					}
				}

				//#37426 CSRF ochrana Struts formularov
				if (req.getSession().getAttribute("org.apache.struts.action.TOKEN")==null)
				{
					//vygeneruj token, kedze struts u nas konci vygenerujem len jeden token do session
					TokenProcessor.getInstance().saveToken(req);
				}
				else if (path.endsWith(".do") && "post".equalsIgnoreCase(req.getMethod()) && (req.getContentType()==null || req.getContentType().contains("multipart")==false))
				{
				   if (DocTools.isXssStrictUrlException(path, "xssProtectionStrictPostUrlException")==false)
					{
						//validuj token
						boolean isTokenValid = TokenProcessor.getInstance().isTokenValid(req, false);
						if (isTokenValid == false)
						{
						   Logger.info(PathFilter.class, "Struts token not valid, path="+path);
							req.setAttribute("errorText", Prop.getInstance(req).getText("components.csrfError"));
							forwardSafely("/components/maybeError.jsp", req, res);
							return;
						}
					}
				}
			}

			if (!checkCSRFTokenAjax(path, req)) {
				Logger.debug(PathFilter.class, "CSRF token missing - header param X-CSRF-Token");
				res.setStatus(HttpServletResponse.SC_FORBIDDEN);
				forwardSafely("/403.jsp", req, res);
				return;
			}

			//skus prihlasit usera (ak treba)
			if ("true".equals(req.getParameter("doFilterLogon")) || "redir".equals(req.getParameter("doFilterLogon")) || Tools.isNotEmpty(req.getHeader("wjlogontoken")))
			{
				if (user == null)
				{
					String username = req.getParameter("username");
					String password = req.getParameter("password");

					String token = req.getParameter("token");
					if (token == null) token = req.getHeader("wjlogontoken");
					if (Tools.isEmpty(username) && Tools.isEmpty(password) && Tools.isNotEmpty(token))
					{
						try
						{
							//toto je len finta, token zacina na NAHODNY ZNAK aby to nebolo na prvy pohlad base64 automaticky dekodovatelne
							token = Tools.replace(token, "|", "=").substring(1);
							Base64 b64 = new Base64();
							token = new String(b64.decode(token.getBytes()));
							int i = token.indexOf(":");
							if (i>0)
							{
								username = token.substring(0, i);
								password = token.substring(i+1);
							}
						}
						catch (Exception ex) {}
					}

					if (Tools.isNotEmpty(username) && Tools.isNotEmpty(password))
					{
						user = new Identity();
						Map errors = new Hashtable<>();
						sk.iway.iwcm.i18n.Prop prop = sk.iway.iwcm.i18n.Prop.getInstance(Constants.getServletContext(), req);
						String forward = LogonTools.logon(username, password, user, errors, req, prop);

						if (req.getAttribute("logon.err.noadmin")!=null)
						{
								//nie je to admin, prihlasme ho ako normalneho usera, ak to zbehne, bude user v session
								LogonTools.logonUser(req, username, password);
						}
						else if (forward.compareTo("logon_ok_admin") != 0 || user == null || user.isAdmin() == false)
						{
							user = null;
						}
						else
						{
							user.setLoginName(username);
							user.setPasswordPlain(password);
							user.setValid(true);
							//je korektne prihlaseny
							LogonTools.setUserToSession(req.getSession(), user);
							req.setAttribute("NO WJTOOLBAR", "true");
						}

						if ("redir".equals(req.getParameter("doFilterLogon")))
						{
							res.sendRedirect(path);
							return;
						}
					}
				}
			}

			/*
			  Kontrola pristupu do admin casti (#10398)
			 */
			if (!checkAccessToAdmin(path, req, res))
			{
				if (path.equals("/admin/refresher.jsp") == false && path.equals("/admin/rest/refresher") == false && path.equals("/admin/rest/monitoring/actual") == false)
				{
					Adminlog.add(Adminlog.TYPE_XSS, "Pouzivatel nema pristup do admin casti, presmerovavam na prihlasenie", -1, -1);
				}

				//ak je to nieco ako /admin.zip /admin~ /admin_backup tak nepresmeruj ale daj chybu
				if (path.startsWith("/admin") && path.indexOf("/", 4)==-1 && path.length()>6) {
					Logger.debug(PathFilter.class, "Is file like, forwarding to 404.jsp");
					//not found posielame aby sa admin cast tvarila akoze vobec neexistuje
					res.setStatus(HttpServletResponse.SC_NOT_FOUND);
					forwardSafely("/404.jsp", req, res);
					return;
				}

				//na public node rovno vyhlasme 404, tiez pre nepovolene IP adresy
				if ("public".equals(Constants.getString("clusterMyNodeType")) || checkAdmin(req)==false)
				{
					Logger.debug(PathFilter.class, "Public node, forwarding to 404.jsp");
					//not found posielame aby sa admin cast tvarila akoze vobec neexistuje
					res.setStatus(HttpServletResponse.SC_NOT_FOUND);
					forwardSafely("/404.jsp", req, res);
					return;
				}

				Logger.println(PathFilter.class, "Pouzivatel nema pristup do admin casti, presmerovavam na prihlasenie, path="+path + " allowedUrls="+ Constants.getString("allowAdminUrls"));

            	LogonTools.saveAfterLogonRedirect(req);

				String domainController = AuthenticationFilter.getDomainController();
				if (Tools.isNotEmpty(domainController))
				{
					res.sendRedirect("/ntlm/logon.do?admin=true");
				}
				else if (path.startsWith("/admin/m/"))
				{
					res.sendRedirect("/admin/m/logon.jsp");
				}
				else
				{
					res.sendRedirect(ContextFilter.addContextPath(req.getContextPath(), "/admin/logon/"));
				}
				return;
			}

			if (path.toLowerCase().endsWith(".jsp") || path.endsWith("/"))
			{
				if (path.startsWith("/images") || path.startsWith("/files") || path.startsWith("/shared"))
				{
					Logger.debug(PathFilter.class, "Volane JSP z nepovoleneho adresara, path="+path);
					//not found posielame aby sa admin cast tvarila akoze vobec neexistuje
					res.setStatus(HttpServletResponse.SC_NOT_FOUND);
					forwardSafely("/404.jsp", req, res);
					return;
				}
			}

			if (path.endsWith(".appcache"))
			{
				//handlovanie zapnutia online modu pre appcache
				String appcacheMode = Tools.getCookieValue(req.getCookies(), "appcacheMode", null);
				if ("online".equals(appcacheMode))
				{
					Cookie c = new Cookie("appcacheMode", "");
					c.setPath("/");
					c.setMaxAge(-1);
					c.setHttpOnly(false);
					Tools.addCookie(c, res, req);

					res.setStatus(HttpServletResponse.SC_NOT_FOUND);
					return;
				}
				else if (req.getSession().getAttribute(Constants.USER_KEY)==null)
				{
					//toto nastane, ked user nie je prihlaseny, nemozeme vtedy poslat obsah suboru, lebo sa nacachuje zoznam ako neprihlaseny user
					Logger.debug(PathFilter.class, "User not logged " + path);
					res.setStatus(HttpServletResponse.SC_FORBIDDEN);
					return;
				}
			}

			//skontroluj password protected
			EditForm ef = isPasswordProtected(path, req);
			if (ef != null && ef.isAccessibleFor(user)==false)
			{
				if (doFileForbiddenRedirect(ef, user, path, req, res)) return;
			}

			if (path.contains("admin/") && (path.endsWith(".js") || path.endsWith(".html")))
			{
				//otestuj, ci existuje JSP nahrada
				File f = new File(Tools.getRealPath(path+".jsp"));
				if (f.exists() && f.canRead())
				{
					f = null;

					res.setHeader("Pragma","No-Cache");
					res.setDateHeader("Expires",0);
					res.setHeader("Cache-Control","no-Cache");

					Logger.debug(PathFilter.class, "Forwarding: "+path+".jsp");

					forwardSafely(path+".jsp", req, res);
					return;
				}
			}
			if (path.endsWith(".jsp"))
			{
				res.setHeader("Pragma","No-Cache");
				res.setDateHeader("Expires",0);
				res.setHeader("Cache-Control","no-Cache");
			}

			//nastav kodovanie JS suborom
			if (path.indexOf("admin/")==-1 && path.endsWith(".js"))
			{
				IwcmFile f = new IwcmFile(Tools.getRealPath(path));

				//otestuj, ci existuje nahrada
				File fNahrada = new File(Tools.getRealPath(path+".jsp"));
				if (fNahrada.exists() && fNahrada.canRead())
				{
					//jsp subor by mal nastavit kodovanie spravne
					//f = fNahrada;
					//tu nespravime nic, musi sa to sprocesovat ako JSP
				}
				else
				{
					IwcmFile fCusom = null;
					if (customPath != null)
					{
						//skontroluj, ci pozadovany subor nie je custom
						fCusom = new IwcmFile(customPath + File.separatorChar + Constants.getInstallName() + path.replace('/', File.separatorChar));
						if (fCusom.exists() && fCusom.canRead()) f = fCusom;
					}
					String customUrl = WriteTagToolsForCore.getCustomPageNull(path, req);
					if (customUrl != null)
					{
						fCusom = new IwcmFile(Tools.getRealPath(customUrl));
						if (fCusom.exists() && fCusom.canRead()) f = fCusom;
					}

					if (f.exists() && f.canRead())
					{
						sk.iway.iwcm.Encoding.setResponseEnc(req, res, "text/javascript");
						boolean staticHeadersSet = setStaticContentHeaders(path, user, req, res);
						setXRobotsTagValue(path, res);

						if (staticHeadersSet && IwcmFsDB.useDBStorage()==false && FileCache.useFileCache())
						{
							if (writeAndCacheFile(path, res)) return;
						}
						FilePathTools.writeFileOut(f, req, res);
						if (timer != null)
						{
							timer.diff("   Path filter - chain, path: " + path);
							DBPool.getInstance().logConnections();
						}

						return;
					}
				}
			}

			//posielaj admin/v9/dist/ adresar ako utf-8
			if (path.startsWith("/admin/v9/dist") && (path.endsWith(".js") || path.endsWith(".css")))
			{
				IwcmFile f = new IwcmFile(Tools.getRealPath(path));
				if (f.exists() && f.canRead())
				{
					String encoding = "text/javascript";
					if (path.endsWith(".css")) encoding = "text/css";
					sk.iway.iwcm.Encoding.setResponseEnc(req, res, encoding);
					setStaticContentHeaders(path, user, req, res);
					setXRobotsTagValue(path, res);

					Logger.debug(PathFilter.class, "Sending DIST file: " + f.getAbsolutePath());
					FilePathTools.writeFileOut(f, req, res);

					return;
				}
			}

         	setDownloadHeaders(path, req, res);
			boolean staticHeadersSet = setStaticContentHeaders(path, user, req, res);
			if (staticHeadersSet && IwcmFsDB.useDBStorage()==false && FileCache.useFileCache())
			{
				if (writeAndCacheFile(path, res)) return;
			}

			//toto standardne Tomcat nepozna, pridame hlavicky podla specky
			if (path.endsWith(".woff2") || path.endsWith(".woff"))
			{
				if (path.endsWith(".woff2")) res.setHeader("Content-Type", "font/woff2");
				else res.setHeader("Content-Type", "font/woff");
			}

			//accessDocId je docId web stranky, ktoru sa zobrazuje, ku ktorej sa pristupuje z verejnej casti sidla, nie admin cast
			DocDB docDB = DocDB.getInstance();
			String domain = DocDB.getDomain(req);
			int accessDocId = -1;
			//files adresar musime nechat povoleny kvoli linkam z fulltext indexu (/files/subor.xls.html) a presmerovaniu na subor.xls
			if (path.startsWith("/images")==false && path.startsWith("/css")==false && path.startsWith("/jscripts")==false)
			{
				if (Constants.getBoolean("ABTesting")==true)
				{
					accessDocId = ABTesting.getVirtualPathDocId(path, domain, req, res);
				}
				else
				{
					//upravene takto ak nie je vobec abtesting trieda dostupna (napr. v cloude)
					accessDocId = docDB.getVirtualPathDocId(path, domain);
				}
			}

			//TatraBanka - ich proxy dava na koniec za .do kontext /, cize zo /showdoc.do?docid=4 vznikne /showdoc.do/
				/*
				if (accessDocId < 1 && "/showdoc.do/".equals(path))
				{
					req.getRequestDispatcher("/showdoc.do").forward(req, res);
				}
				*/

			if (accessDocId > 0)
			{
				//kontrola spravnosti domeny
				if (!checkDomain(req))
				{
					Logger.debug(PathFilter.class, "checkDomain=false, forwarding to 404.jsp");
					res.setStatus(HttpServletResponse.SC_NOT_FOUND);
					forwardSafely("/404.jsp", req, res);
					return;
				}

				//porovnaj URL a pripadne sprav redirect
				String realUrl = docDB.getDocLink(accessDocId, req);
				if (realUrl!=null && realUrl.equals(path)==false && !realUrl.contains(Constants.getString("ABTestingName")))
				{
					//URL so znakom * sa odstranuju, musime specialne skontrolovat
					String virtualPath = docDB.getBasicDocDetails(accessDocId, true).getVirtualPath();
					if (virtualPath == null || virtualPath.indexOf("*")==-1)
					{
						Logger.debug(PathFilter.class, "nesedi real URL, redirecting to: "+realUrl);
						res.setStatus(301);
						if (Tools.isNotEmpty(req.getQueryString())) realUrl += '?'+req.getQueryString();
						if (realUrl.toLowerCase().startsWith("http")==false) realUrl = Tools.getBaseHref(req)+realUrl;
						res.setHeader("Location", Tools.sanitizeHttpHeaderParam(realUrl));
						return;
					}
				}

				//	setni data pre SessionListener - customer cast
				String lastURL = path;
				if (req.getQueryString()!=null)
				{
					path = path + "?" + req.getQueryString();
				}

				if (holder.set(req.getSession().getId(), lastURL, req)==false)
				{
					//nastalo session stealing, spravime redirect aby nenastavali exception v JSP

					StringBuilder redirPath = new StringBuilder(path);
					if (Tools.isNotEmpty(req.getQueryString())) redirPath.append('?').append(req.getQueryString());

					res.sendRedirect(Tools.sanitizeHttpHeaderParam(redirPath.toString()));
					return;
				}

				//akoze skuska ochrany pred chybou Cannot create a session after the response has been committed
				if (req.getSession().getAttribute("preventCannotCreateSession")==null)
				{
					req.getSession().setAttribute("preventCannotCreateSession", "1");
				}

				//Logger.println(this,"forwarding to docId: " + docId);
				StringBuilder url = new StringBuilder("/showdoc.do?docid=").append(accessDocId);

				if ("get".equalsIgnoreCase(req.getMethod()))
				{
					String name;
					String[] values;
					Enumeration params = req.getParameterNames();
					while (params.hasMoreElements())
					{
						name = params.nextElement();
						if (name.equals("docid") || name.equals("password")) continue;
						values = req.getParameterValues(name);
						for (int i = 0; i < values.length; i++)
						{
							url.append("&").append(Tools.sanitizeHttpHeaderParam(name)).append('=').append(Tools.sanitizeHttpHeaderParam(values[i]));
						}
					}
				}

				Logger.debug(PathFilter.class, "PathFilter, url: " + url + " domain="+domain+" origUrl="+path+" qs="+req.getQueryString());
				if (Constants.getInt("linkType") == Constants.LINK_TYPE_HTML || path.endsWith(".php") || path.endsWith(".asp") || path.endsWith(".aspx") || Constants.getBoolean("forwardVirtualPath"))
				{
					req.setAttribute("docid", Integer.toString(accessDocId));
					Logger.debug(PathFilter.class, "forwarding1: req=" + req + " resp="+res);

					String packagerMode = Constants.getString("packagerMode");
					String packagerModeParam = req.getParameter("_packagerMode");
					if (Tools.isNotEmpty(packagerModeParam)) packagerMode = packagerModeParam;

					if (Tools.isEmpty(packagerMode) || "none".endsWith(packagerMode))
					{
						req.getRequestDispatcher("/showdoc.do?docid=" + accessDocId).forward(req, res);
					}
					else
					{
						long start = Tools.getNow();

						WJResponseWrapper respWrapper = new WJResponseWrapper(res, req);
						req.getRequestDispatcher("/showdoc.do?docid=" + accessDocId).forward(req, respWrapper);
						StringBuilder htmlCode = new StringBuilder(respWrapper.strWriter.getBuffer().toString());

						String fixedHtml = htmlCode.toString();

						//moznost prepnutia packagera (pre kazdy pripad)
						String packagerModeAttr = (String)req.getAttribute("packagerMode");
						if (packagerModeAttr!=null) packagerMode = packagerModeAttr;

						//ak je treba posli redirect
						if (Tools.isNotEmpty(respWrapper.getRedirectURL())) res.sendRedirect(respWrapper.getRedirectURL());

						long end = Tools.getNow();
						Logger.debug(PathFilter.class, "Packager: HTML packaging tooks: " + (end-start) + "ms");

						//zapis vystup
						respWrapper.writeResponseToOriginalOutput(req, fixedHtml);
					}
				}
				else
				{
					Logger.debug(PathFilter.class, "redirecting: req="+req+" resp="+res);
					res.sendRedirect(req.getContextPath() + url.toString());
				}
				if (timer != null)
				{
					timer.diff("   Path filter - chain, path: " + path);
					DBPool.getInstance().logConnections();
				}
				return;
			}
			else
			{
				if ("/sitemap.xml".equals(path))
				{
					//nie je definovana stranka s URL /sitemap.xml, priamo forwardnem
					//je to tu kvoli cloudu, pretoze do 404.jsp uz dorazi request a nema RequestBean (zjavne sa to vola az po skonceni filtrov)
					res.setContentType("text/xml; charset=utf-8");
					res.setStatus(HttpServletResponse.SC_OK);
					String customPage = WriteTagToolsForCore.getCustomPage("/components/sitemap/google-sitemap.jsp", req);
					forwardSafely(customPage, req, res);
					return;
				}
			}

			if ((path.startsWith("/components/") || path.startsWith("/templates/")) && path.lastIndexOf('.') > path.lastIndexOf('/') && path.equals("/components/editoricon.gif")==false)
			{
				try
				{
					//skus najst nahradu za pozadovanu stranku
					String customPage = WriteTagToolsForCore.getCustomPage(path, req);
					if (customPage.equals(path)==false)
					{
						forwardSafely(customPage, req, res);
						return;
					}

					if (path.endsWith("editor_component.jsp"))
					{
						//over ci existuje, ak nie, pouzi defaultnu
						if (WriteTagToolsForCore.isFileExists(path)==false)
						{
							try
							{
								//tu mame plne meno povodneho suboru v include
								String jspFileName = req.getParameter("jspFileName");
								if (jspFileName != null)
								{
									if (jspFileName.startsWith("!INCLUDE(")) jspFileName = jspFileName.substring(9).trim();

									//skus verziu s odstranenou druhou castou, /components/iway/news/editor_component.jsp -> /components/news/editor_component.jsp
									String pathBezDruhejCasti = "/components"+path.substring(path.indexOf("/", 13));
									if (WriteTagToolsForCore.isFileExists(pathBezDruhejCasti))
									{
										//mame custom subor, ak ale existuje nastaveny CONF kluc k danemu suboru nepouzijeme
										String CONF_KEY = jspFileName.substring(0, jspFileName.lastIndexOf('.')).replace('/', '.').substring(1);
										Prop prop = Prop.getInstance(req);
										//ak kluc neexistuje pouzijeme
										if (prop.getText(CONF_KEY+".conf.propSearchKey").equals(CONF_KEY+".conf.propSearchKey") && prop.getText(CONF_KEY+".conf").equals(CONF_KEY+".conf"))
										{
											Logger.debug(PathFilter.class, "forwarding to:"+pathBezDruhejCasti);
											req.getRequestDispatcher(WriteTagToolsForCore.getCustomPage(pathBezDruhejCasti, req)).forward(req, res);
										}
									}
								}
							}
							catch (Exception ex)
							{
								sk.iway.iwcm.Logger.error(ex);
							}

							req.getRequestDispatcher(WriteTagToolsForCore.getCustomPage("/components/editor_component_universal.jsp", req)).forward(req, res);
							return;
						}

					}
				}
				catch (RuntimeException e)
				{
					sk.iway.iwcm.Logger.error(e);
				}

			}
			//podpora custom pluginov v editore - NETREBA uz bereme z dist priecinka
			/*if (path.startsWith("/admin/skins/webjet8/ckeditor/dist/plugins/") || path.startsWith("/admin/skins/webjet8/ckeditor/plugins/"))
			{
				path = Tools.replace(path, "/admin/skins/webjet8/ckeditor/dist/plugins/", "/admin/ckeditor/plugins/");
				path = Tools.replace(path, "/admin/skins/webjet8/ckeditor/plugins/", "/admin/ckeditor/plugins/");
				String customPage = WriteTagToolsForCore.getCustomPageAdmin(path, req);
				if (customPage != null)
				{
					req.getRequestDispatcher(customPage).forward(req, res);
					return;
				}
			}*/
			if (path.endsWith(".php") || path.endsWith(".asp"))
			{
				//skus najst JSP verziu stranky
				String jspPath = path.substring(0, path.length() - 4) + ".jsp";
				File jspFile = new File(Tools.getRealPath(jspPath));
				if (jspFile.exists())
				{
					forwardSafely(jspPath, req, res);
					if (timer != null)
					{
						timer.diff("   Path filter - chain, path: " + path);
						DBPool.getInstance().logConnections();
					}
					return;
				}
			}
			if (customPath != null)
			{
				//skontroluj, ci pozadovany subor nie je custom
				IwcmFile f = new IwcmFile(customPath + File.separatorChar + Constants.getInstallName() + path.replace('/', File.separatorChar));

				if (f.exists()==false)
				{
					f = new IwcmFile(Tools.getRealPath("/templates/" + Constants.getInstallName() + "/assets" + path));
				}

				if (f.exists()==false && path.contains("/admin/docsify/") && "iwcm.interway.sk".equals(req.getServerName()) && user != null && user.isAdmin() && path.contains("..")==false)
                {
                    //je to docsify subor, ten mame inde, musime upravit
                    f = new IwcmFile(Tools.getRealPath("/"));
                    f = new IwcmFile(f.getParentFile(), path.substring(6).replace('/', File.separatorChar));
                }

				//Logger.println(this,"Checking CUSTOM: "+f.getAbsolutePath());
				if (f.exists() && f.isFile())
				{
					//existuje custom subor, posli ho na vystup
					if (path.toLowerCase().endsWith(".jsp") || path.toLowerCase().endsWith(".class"))
					{
						//toto este nevieme, nerob nic
						Logger.error(this,"TOTO AKO CUSTOM NEVIEM: " + path);
					}
					else
					{
						//Logger.println(this,"sending custom page:
						// "+f.getAbsolutePath());
						//je to nejaky obrazok, alebo subor, posli na vystup
						FilePathTools.writeFileOut(f, req, res);
						//Logger.println(this,"Zapisany subor: " + path);
						if (timer != null)
						{
							timer.diff("   Path filter - chain, path: " + path);
							DBPool.getInstance().logConnections();
						}
						return;
					}
				}
			}

			if (FilePathTools.isExternalDir(path))
			{
				//externy adresar pre cloudStaticFilesDir folder
				boolean fileWritten = FilePathTools.writeFileOut(path, req, res);
				if (fileWritten)
				{
					if (timer != null)
					{
						timer.diff("   Path filter - chain, path: " + path);
						DBPool.getInstance().logConnections();
					}
					return;
				}
			}

			//zaslanie fresh suboru pre elfinder (volane len s parametrom v=xxx) po zmene velkosti
			//tomcat 8 totiz nejako divne cachuje obrazky a aj ked ho zmenime tak to nepomoze a vrati povodny
			if (user != null && user.isAdmin() && req.getParameter("v")!=null)
			{
				String mimeType = Constants.getServletContext().getMimeType(path.toLowerCase());
				if (Tools.isEmpty(mimeType)) mimeType = "application/octet-stream";
				if (mimeType.startsWith("image/") && path.startsWith("/images"))
				{
					IwcmFile f = new IwcmFile(Tools.getRealPath(path));
					if (f.exists() && f.canRead()) {
						FilePathTools.writeFileOut(f, req, res);
						//Logger.println(this,"Zapisany subor: " + path);
						if (timer != null)
						{
							timer.diff("   Path filter - chain, path: " + path);
							DBPool.getInstance().logConnections();
						}
						return;
					}
				}
			}


			//preposlanie suboru z historie, tiket 13373, parameter pochadza z file_history.jsp
			if (req.getParameter("fHistoryId")!=null && user != null && user.isAdmin())
			{
				int fHistoryId = Tools.getIntValue(req.getParameter("fHistoryId"), -1);
				if (fHistoryId > 0)
				{
					boolean sendOK = FileHistoryDB.sendFileFromHistory(path, fHistoryId, res);
					if (sendOK == false)
					{
						res.setStatus(404);
					}
					return;
				}
			}



			if (path.startsWith("/templates/")) {
				Ninja.includeNinja(req);
			}

			//forward(request, response);
			//return;
		}
		catch (RuntimeException rex)
		{
			sk.iway.iwcm.Logger.error(rex);
		}
		catch (Exception ex)
		{
			if (ex.getClass().getCanonicalName().startsWith("org.spring")) throw ex;
			else
			{
				sk.iway.iwcm.Logger.error(ex);
			}
		}

		if (timer != null)
		{
			timer.diff("   Path filter - chain, path: " + path);
			DBPool.getInstance().logConnections();
		}

		try
		{
			// Pass control on to the next filter
			chain.doFilter(servletRequest, servletResponse);
		}
		catch (NestedServletException|org.springframework.security.access.AccessDeniedException e)
		{
			//nastane napr. pri volani /admin/adminlog/logging ak user nema pravo na cmp_adminlog
			//rest sluzby si to handluju same, toto sa tyka webview
			//neda sa zachytit priamo AccessDeniedException preto chytame NestedServletException
			if (e.getCause().toString().contains("AccessDeniedException"))
			{
				res.setStatus(HttpServletResponse.SC_FORBIDDEN);
				//ak to nie je rest posli ho aj na defaultnu 403 stranku
				if (path==null || path.contains("/rest")==false) forwardSafely("/403.jsp", req, res);
			}
			else
			{
				throw e;
			}
		}
	}




	/**
	 * Skontroluje, ci je mozne pristupit k verejnej casti webu, nie admin casti
	 * @author kmarton
	 *
	 * @param request
	 * @return
	 */
	public static boolean checkWebAccess(HttpServletRequest request, String path)
	{
        Identity user = UsersDB.getCurrentUser(request);

        //kontrola referer hlavicky (CSRF), je povinna pre POST alebo ked je prihlaseny user
        String pathLC = path.toLowerCase();
        if (user != null || "POST".equalsIgnoreCase(request.getMethod()) || pathLC.endsWith(".do") || pathLC.endsWith(".action"))
        {
            boolean isUrlAccessible = true;
            boolean xsrfUrlException = DocTools.isXssStrictUrlException(path, "xsrfUrlException");
            if (xsrfUrlException==false && isXsrfCheckRequired(request))
            {
                isUrlAccessible = checkXsrf(request);
            }

            //nastal CSRF utok, referer nesedi
            if (isUrlAccessible==false) return false;
        }

		//kontrola pristupu do /components/ adresara
		if ((path.startsWith("/components/") || path.startsWith("/apps/"))
			 && (path.endsWith(".jsp") || path.endsWith(".ftl") || path.endsWith(".html")))
		{
			if (user == null || user.isAdmin()==false)
			{
				boolean canAccess = DocTools.isXssStrictUrlException(path, "componentsDirectCallExceptions");
				if (canAccess==false)
				{
					//ak to zacina na /apps/ over este, ci to nie je platna URL adresa stranky
					int docId = -1;
					if (path.startsWith("/apps/")) docId = DocDB.getInstance().getDocIdFromURLImpl(path, DocDB.getDomain(request));
					if (docId < 1)
					{
						Adminlog.add(Adminlog.TYPE_XSS, "Direct component call, path="+path, -1, -1);
						return false;
					}
				}
				//duplicitna kontrola, v ziadnom pripade nema zmysel pristupovat na komponenty s URL obsahujucim admin a tiez do statistiky
				if (canAccess && path.contains("admin_answer.jsp")) return canAccess;
				if (path.contains("admin"))
				{
					if (user != null && (path.contains("FCKeditor") || path.contains("/components/gallery/admin_gallery_popup.jsp") ||
							path.contains("/components/helpdesk/fotogaleria/admin_upload.jsp")))
					{
						//specialna vynimka pre CK editor pre rozne projekty kde je user prihlaseny ale nie je admin
						//+ #17331 - pridana vynimka pre upload suboru vo fotogalerii v intre
					}
					else
					{
						return false;
					}
				}
				if (path.contains("/components/stat/") && path.contains("stat_async_ajax.jsp") == false) return false;
			}
		}

		//kontrola pristupu podla povolenych IP adries
		HttpSession session = request.getSession();
		Boolean val = (Boolean) session.getAttribute(CHECK_WEB_ACCESS_SESSION_KEY);
		if (val != null)
		{
			//Logger.println(this,"Checking to access web from session: " + val.booleanValue());
			return (val.booleanValue());
		}

		boolean ret = Tools.checkIpAccess(request, "webEnableIPs");
		session.setAttribute(CHECK_WEB_ACCESS_SESSION_KEY, Boolean.valueOf(ret));
		return (ret);
	}

	/**
	 * Skontroluje, ci je mozne pristupit k verejnej casti webu na zaklade domeny
* * Castokrat web najskor bezi na domene nieco.t8.iway.sk a nasledne sa spusti na * domenie nieco.sk, filter umoznuje zadat domeny, pre ktore bude stranka * vracat obsah a pre ktore bude robit 404 / redirect na inu domenu. * @author kmarton * * @param request * @return */ private boolean checkDomain(HttpServletRequest request) { HttpSession session = request.getSession(); Boolean val = (Boolean) session.getAttribute(CHECK_DOMAIN_SESSION_KEY); if (val != null) { //Logger.println(this,"Checking DOMAIN to access web from session: " + val.booleanValue()); return (val.booleanValue()); } String webAllowedDomains = Constants.getString("webAllowedDomains"); boolean ret = true; if (webAllowedDomains != null && webAllowedDomains.length() > 1) { ret = false; StringTokenizer st = new StringTokenizer(webAllowedDomains, ","); String domain; String myDomain = Tools.getServerName(request); Logger.println(this,"Checking: " + myDomain + " vs " + webAllowedDomains); while (st.hasMoreTokens()) { domain = st.nextToken(); if (myDomain.endsWith(domain)) { ret = true; break; } } } session.setAttribute(CHECK_DOMAIN_SESSION_KEY, Boolean.valueOf(ret)); return (ret); } private boolean checkAccessToAdmin(String path, HttpServletRequest request, HttpServletResponse response) { boolean isAdminUrlAccessible = true; Identity user = UsersDB.getCurrentUser(request.getSession()); boolean xsrfUrlException = DocTools.isXssStrictUrlException(path, "xsrfUrlException"); if(path.startsWith("/admin") || (path.startsWith("/components/") && path.contains("/admin")) || (path.startsWith("/apps/") && path.contains("/admin"))) //pristupuje do admin casti a admin komponent/app { if(user == null || UsersDB.checkUserPerms(user, "admin|editableGroupsNotEmpty")==false) //A nie je prihlaseny, alebo nie je prihlaseny ako admin { isAdminUrlAccessible = false; String allowAdminUrls = Constants.getString("allowAdminUrls"); //ak v starom WJ mali customizovanu premennu a nemaju tam springove prihlasenie, pridajme if (allowAdminUrls.contains("/admin/logon.do") && allowAdminUrls.contains("/admin/logon/")==false) allowAdminUrls += ",^/admin/logon$,^/admin/logon/$,^/admin/logon/changePassword$"; String[] adminUrls = Tools.getTokens(allowAdminUrls, ",", true); for(String url: adminUrls) { if(path.startsWith(url) || ("^"+path+"$").equals(url) || (path+"$").endsWith(url)) { isAdminUrlAccessible = true; break; } } } if(isAdminUrlAccessible && xsrfUrlException==false) { isAdminUrlAccessible = checkXsrf(request); } if (path.endsWith(".html") || path.endsWith(".jsp") || path.endsWith(".action") || path.endsWith(".do") || path.endsWith(".js") || path.endsWith("/") || path.indexOf("ajax")!=-1) { setUaCompatibleAdmin(path, response); } } if (user != null && user.isAdmin()) { if (xsrfUrlException==false) { if (isXsrfCheckRequired(request)) { isAdminUrlAccessible = checkXsrf(request); } } } return isAdminUrlAccessible; } /** * Overi, ci je potrebna XSRF kontrola (kontrola referera) * ta sa robi pri POST alebo ked v URL su nejake parametre (okrem vynimiek definovanych v xsrfParamNameException ako docid, _logLevel, combineEnabled atd) * @param request * @return */ private static boolean isXsrfCheckRequired(HttpServletRequest request) { //ak uz je user prihlaseny ako admin, kontrolujme CSRF vzdy (aby sa nedal spravit utok z inej stranky mazuci napr. data) //niektore URL musime whitelistovat, kedze mozu viest z mailu boolean isXsrfCheckRequired = false; if ("GET".equalsIgnoreCase(request.getMethod())) { Enumeration paramNames = request.getParameterNames(); int failsafe = 0; int maxFailsafe = 10; String xsrfParamNames = Constants.getString("xsrfParamNameExceptionSystem"); if (Tools.isNotEmpty(Constants.getString("xsrfParamNameException"))) xsrfParamNames += "," + Constants.getString("xsrfParamNameException"); String[] xsrfParamNameException = Tools.getTokens(xsrfParamNames.toLowerCase(), ",", true); while (paramNames.hasMoreElements() && failsafe++ <= maxFailsafe) { String name = paramNames.nextElement().toLowerCase(); //natvrdo kvoli performance if ("docid".equals(name)) continue; //displaytag povolime if (name.startsWith("d-")) continue; //over voci zoznamu povolenych parametrov if (Tools.containsOneItem(xsrfParamNameException, name)) continue; isXsrfCheckRequired = true; } //ak to ma vela parametrov tak to je rovno podozrive if (failsafe>=maxFailsafe) isXsrfCheckRequired = true; } else { //pre POST je check required isXsrfCheckRequired = true; } return isXsrfCheckRequired; } /** * Method checks for XSRF attack, if referrer from request header is not current server * or from list of trusted referrers (constant xsrfReferers, see {@link Constants} ) method denies * access to url and logs attack. for more information see Ticket 11207 * @param request request * @return true if xsrf is not detected, else false */ private static boolean checkXsrf(HttpServletRequest request) { String trustedXsrfReferers = Constants.getString("xsrfReferers"); //ten length je tam aby v Oracle DB bolo mozne v konfiguracii nastavit znak - if(Tools.isEmpty(trustedXsrfReferers) || trustedXsrfReferers.length()<2) return true; String remoteReferrer = request.getHeader("referer"); if(Tools.isEmpty(remoteReferrer)) { //vynimka pre elfinder download - /admin/elfinder-connector/?cmd=file&target=iwcm_2_L2ZpbGVzL3pfb19wcmlzcF9uYV9wb2hyZWJfcGRmLnBkZg_E_E&download=1&volumes=files //nechcel som dat vynimku pre cely elfinder-connector, preto sa testuje parameter download String path = PathFilter.getOrigPath(request); if ("/admin/elfinder-connector/".equals(path) && "1".equals(request.getParameter("download"))) { return true; } //do slaka, MSIE posiela empty referer ked otvara popup okno, takze zial MSIE nebude pre GET poziadavky chranene String userAgent = request.getHeader("User-Agent"); boolean isMsie = false; if (userAgent!=null && "GET".equalsIgnoreCase(request.getMethod())) { //vynimka len pre Trident/7.0 co je MSIE 11, starsi MSIE nebude podporovany (jedine ochranu uplne vypnut) if (userAgent.contains("Trident/7.0")) isMsie = true; } if (isMsie==false && isXsrfCheckRequired(request)) { Adminlog.add(Adminlog.TYPE_XSRF, "Possible XSRF attack, referer is empty", -1, -1); return false; } return true; } String remoteReferrerServer = ""; try { URL remoteReferrerUrl = new URL(remoteReferrer); remoteReferrerServer = remoteReferrerUrl.getHost(); } catch (Exception e) { Logger.debug(PathFilter.class,"Failed to create URL from referrer: " + remoteReferrer); } for(String trustedReferrer : trustedXsrfReferers.split(",")) { trustedReferrer = trustedReferrer.trim(); if(trustedReferrer.equalsIgnoreCase(Constants.SERVER_NAME_MACRO)) { trustedReferrer = Tools.getServerName(request, false); } if (trustedReferrer.startsWith("%") && trustedReferrer.endsWith("%") && trustedReferrer.length()>4 && remoteReferrerServer.contains(trustedReferrer.substring(1, trustedReferrer.length()-1))) { return true; } if (trustedReferrer.startsWith("%") && trustedReferrer.length()>2 && remoteReferrerServer.endsWith(trustedReferrer.substring(1))) { return true; } if(remoteReferrerServer.equalsIgnoreCase(trustedReferrer)) { return true; } } Adminlog.add(Adminlog.TYPE_XSRF, "Possible XSRF attack from: " + remoteReferrer, -1, -1); return false; } /** * Skontroluje, ci je mozne pristupit k admin casti * * @param request * @return */ public static boolean checkAdmin(HttpServletRequest request) { HttpSession session = request.getSession(); Boolean val = (Boolean) session.getAttribute(CHECK_ADMIN_SESSION_KEY); if (val != null) { return (val.booleanValue()); } if ("public".equals(Constants.getString("clusterMyNodeType"))) return false; String adminEnableIPs = Constants.getString("adminEnableIPs"); boolean ret = true; if (adminEnableIPs != null && adminEnableIPs.length() > 1) { ret = false; StringTokenizer st = new StringTokenizer(adminEnableIPs, ","); String ip; String myIP = Tools.getRemoteIP(request); Logger.println(PathFilter.class,"Checking: " + myIP + " vs " + adminEnableIPs); while (st.hasMoreTokens()) { ip = st.nextToken().trim(); if (myIP.startsWith(ip)) { ret = true; break; } } } session.setAttribute(CHECK_ADMIN_SESSION_KEY, Boolean.valueOf(ret)); return (ret); } /** * Nacita z databazy zoznam adresarov, v ktorych su chranene subory * */ public static synchronized void reloadProtectedDirs() { Map protectedDirs = new HashMap<>(); Connection db_conn = null; PreparedStatement ps = null; ResultSet rs = null; try { db_conn = DBPool.getConnection(); ps = db_conn.prepareStatement("SELECT * FROM dirprop"); rs = ps.executeQuery(); EditForm ef; String passProtected; while (rs.next()) { passProtected = DB.getDbString(rs, "password_protected"); if (Tools.isEmpty(passProtected)) { continue; } ef = new EditForm(); ef.setPasswordProtectedString(passProtected); ef.setOrigDir(DB.getDbString(rs, "dir_url")); ef.setIndexFulltext(rs.getBoolean("index_fulltext")); ef.setLogonDocId(rs.getInt("logon_doc_id")); protectedDirs.put(ef.getOrigDir(), ef); } rs.close(); ps.close(); rs = null; ps = null; } catch (Exception sqlEx) { //ak este nie je spraveny update toto hadze exception if (sqlEx.getMessage().indexOf("doesn't exist")!=-1) { sk.iway.iwcm.Logger.error(sqlEx); } } finally { try { if (db_conn != null) db_conn.close(); if (rs != null) rs.close(); if (ps != null) ps.close(); } catch (Exception ex2) { } } passwordProtected = protectedDirs; } /** * Skontroluje, ci zadane URL je v protected zone * @param url * @return EditForm ak je chranene, alebo null */ public static EditForm isPasswordProtected(String url, HttpServletRequest request) { if (request == null) return isPasswordProtected(url, null, null); return isPasswordProtected(url, request, request.getSession()); } /** * Skontroluje prava k danemu URL (suboru) * @param url - url adresa suboru z adresara /files * @param request - ak nie je null prida sa aj statistika videni (ak statistiku nechceme zaratat nastavime len session) * @param session - session z ktorej sa ziska identita pouzivatela * @return */ public static EditForm isPasswordProtected(String url, HttpServletRequest request, HttpSession session) { boolean galleryCheckUserPerms = Constants.getBoolean("galleryCheckUserPerms"); if (url.startsWith("/files")==false && (url.startsWith("/images/gallery/")==false || galleryCheckUserPerms == false)) { return(null); } if (session == null && request != null) session = request.getSession(); EditForm efBestMatch = null; if(passwordProtected != null && passwordProtected.size() > 0) { String testPath = url; int start = 1; //nastavit musim na 1, aby v pripade prvej podmienky islo do while cyklu if (testPath.endsWith("/")) testPath = testPath.substring(0, testPath.length()-1); else if(testPath.contains(".")) //ak sa jedna o subor - vytiahnem adresar { start = testPath.lastIndexOf("/"); if(start != -1) testPath = testPath.substring(0, testPath.lastIndexOf("/")); } EditForm ef = null; int failsafe = 0; String firstTestPath = ""; //hladam najblizsi nadradeny adresar kotry je password protected while (start > 0 && failsafe++ < 30) { if(failsafe == 1) firstTestPath = testPath; ef = passwordProtected.get(testPath); if(ef != null) { efBestMatch = ef; //pokial som nenasiel v prvom pokuse, pridam do zoznamu, nech pri dalsom volani neiterujem zbytocne + ochrana proti DOC utokom if(failsafe > 1 && passwordProtected.size() < 2000) passwordProtected.put(firstTestPath, ef); break; } start = testPath.lastIndexOf("/"); if (start > 0) testPath = testPath.substring(0, start); //substring len v pripade ak lomitko nieje na zaciatku } } if (url.startsWith("/files")) { //pre files skus skontrolovat ci nie je zaheslovany v sekcii /files/ DocDB docDB = DocDB.getInstance(); int docId = docDB.getDocIdFromURLImpl(url+".html", null); if (docId < 1) docId = docDB.getDocIdFromURLImpl(url+".html", DocDB.getDomain(request)); if (docId < 1) docId = docDB.getDocIdFromURLImpl(Tools.replace(url, ".", "-")+".html", null); if (docId < 1) docId = docDB.getDocIdFromURLImpl(Tools.replace(url, ".", "-")+".html", DocDB.getDomain(request)); if (docId > 0) { DocDetails fileDoc = docDB.getBasicDocDetails(docId, false); if (fileDoc != null) { Identity user = null; if (session != null) user = UsersDB.getCurrentUser(session); else { RequestBean rb = SetCharacterEncodingFilter.getCurrentRequestBean(); if (rb!=null && rb.getUserId()>0) user = new Identity(UsersDB.getUser(rb.getUserId())); } boolean canAccess = DocDB.canAccess(fileDoc, user, true); boolean isAvailable = fileDoc.isAvailable(); if (isAvailable == false && user != null && user.isAdmin() && Constants.getBoolean("adminCheckUserGroups")==false) { //ak je admin ignorujeme nastavenie available atributu stranky isAvailable = true; } if (!canAccess || !isAvailable) { efBestMatch = new EditForm(); //to cislo je bulharska konstanta len aby nam potom nezbehlo ef.isAccessibleFor, pretoze to neriesi podadresare dokumentu efBestMatch.setPasswordProtectedString("999888777"); } else { try { if (request != null) { StatDB.add(request.getSession(), request, null, docId); } } catch (Exception e) { sk.iway.iwcm.Logger.error(e); } } } } } return(efBestMatch); } /** * Vykona redirect (ak treba) na zobrazenie logon stranky / zamietnutia pristupu k suboru (/files/*), vrati true, ak bol redirect vykonany * @param ef * @param user * @param originalPath * @param req * @param res * @return true ak je redirect vykonany, inak false * @throws IOException * @throws ServletException */ public static boolean doFileForbiddenRedirect(EditForm ef, Identity user, String originalPath, HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException { boolean isAccesible = false; if (user != null && ef!=null) { //otestuj, ci je user v skupine pre tento adresar int i; int size = ef.getPasswordProtected().length; for (i=0; i0) { //res.sendRedirect("/showdoc.do?docid="+ef.getLogonDocId()); //request.setAttribute("docDetailsOriginal", doc); //pre subor sa musime submitnut priamo na usrlogon.do aby sa najskor spravilo prihlasenie az potom kontrola prav na subor req.setAttribute("logonFormSubmitURL", "/usrlogon.do"); req.getRequestDispatcher("/showdoc.do?docid="+ef.getLogonDocId()+"&dontUpdateLastDocId=true").forward(req, res); } else { req.getRequestDispatcher("/components/user/logon.jsp?permsDenied=true").forward(req, res); } } return true; } /** * Vrati cestu k suboru na disku z daneho URL, berie do uvahy aj custom path * @param url - url adresa suboru, napr. /css/page.css * @return - vrati cestu na disku, napr. /var/webapps/webjet/css/page.css */ public static String getRealPath(String url) { if (customPath != null) { //skontroluj, ci pozadovany subor nie je custom File f = new File(customPath + File.separatorChar + Constants.getInstallName() + (url.startsWith("/")?"":File.separatorChar) + url.replace('/', File.separatorChar)); //Logger.println(this,"Checking CUSTOM: "+f.getAbsolutePath()); if (f.exists()) { return(f.getAbsolutePath()); } } return(Tools.getRealPath(url)); } public static String getOrigPath(HttpServletRequest request) { return((String)request.getAttribute("path_filter_orig_path")); } /** * Vrati adresu povodnej stranky, v pripade DOCID liniek vratane parametra docid * @param request * @return */ public static String getOrigPathDocId(HttpServletRequest request) { if (Constants.getInt("linkType")==Constants.LINK_TYPE_DOCID && request.getParameter("docid")!=null) { return "/showdoc.do?docid="+Tools.getDocId(request); } String origPath = getOrigPath(request); if ("/showdoc.do".equals(origPath)) origPath = origPath + "?docid=" + Tools.getDocId(request); return origPath; } /** * Vrati adresu povodnej stranky, v pripade DOCID liniek vratane docid s pridanym * parametrom pre uload suboru pre stripes (aby to Stripes spracoval) * @param request * @return */ public static String getOrigPathUpload(HttpServletRequest request) { if (Constants.getInt("linkType")==Constants.LINK_TYPE_DOCID && request.getParameter("docid")!=null) { return "/showdoc.do?docid="+Tools.getDocId(request) +"&__sfu=1"; } return getOrigPath(request)+"?__sfu=1"; } public static boolean bypassPath(String path, ServletRequest servletRequest) { //aby nam lokalne fungoval customPath if (Tools.isNotEmpty(PathFilter.getCustomPath()) && "iwcm.interway.sk".equals(servletRequest.getServerName())) return false; if (bypassPath == null) { synchronized(PathFilter.class) //NOSONAR { if (bypassPath == null) { String[] tokens = Tools.getTokens(Constants.getString("pathFilterBypassPath"), ",", true); bypassPath = tokens == null ? new String[0] : tokens; } } } if (bypassPath.length > 0) { for (int i=0; i; rel=\"canonical\""); } //vypnutie cachovania pre obrazky z imageeditora if (path.contains("/_tmp_")) { response.setDateHeader("Expires",0); response.setDateHeader("Last-Modified", Tools.getNow()); response.setHeader("Cache-Control","no-store, no-cache, must-revalidate, max-age=0"); //response.setHeader("Cache-Control","post-check=0, pre-check=0"); response.setHeader("Pragma","No-Cache"); response.setHeader("Etag", ""); return false; } if (cacheStaticContentSeconds < 0) { cacheStaticContentSeconds = Constants.getInt("cacheStaticContentSeconds"); } if (cacheStaticContentSuffixes == null) { synchronized(PathFilter.class) //NOSONAR { if (cacheStaticContentSuffixes == null) { String[] tokens = Tools.getTokens(Constants.getString("cacheStaticContentSuffixes"), ",", true); cacheStaticContentSuffixes = tokens == null ? new String[0] : tokens; } } } //prefixom /cache mame oznacene veci, co sa musia cachovat kvoli rychlosti admin casti (/admin/scripts/common.jsp) if (path.startsWith("/cache/")==false) { if (cacheStaticContentSeconds<1 || cacheStaticContentSuffixes==null || cacheStaticContentSuffixes.length<1) return false; //administratorom cache nenastavujem (okrem admin casti, tam sa to casto nemeni) if (user!=null && user.isAdmin() && path.startsWith("/admin")==false && path.startsWith("/components")==false && Constants.getBoolean("cacheStaticContentForAdmin")==false) return false; //pre IP pre ktore neevidujeme statistiku nenastavujem (pravdepodobne IWAY + admini) if (Constants.getBoolean("cacheStaticContentForAdmin")==false && BrowserDetector.isStatIpAllowedFast(request)==false) return false; } //String pathLC = path.toLowerCase(); //v parametri v sa prenasa verzia suboru, v tom pripade cachujeme //uz cachujem aj admin cast if (pathLC.startsWith("/admin/") && (request.getParameter("v")==null && request.getParameter("t")==null)) return false; int myCacheStaticContentSeconds = cacheStaticContentSeconds; if (myCacheStaticContentSeconds < 1 && path.startsWith("/cache/")) myCacheStaticContentSeconds = 300; //ak mame parameter v tak natvrdo nastavime cas na 7 dni if (request.getParameter("v")!=null) myCacheStaticContentSeconds = 60 * 60 * 24 * 7; if (path.contains("ckeditor")) myCacheStaticContentSeconds = 60 * 60 * 24 * 7; if (path.contains("assets")) myCacheStaticContentSeconds = 60 * 60 * 24 * 7; if (path.contains("_common")) myCacheStaticContentSeconds = 60 * 60 * 24 * 7; if (path.contains("/admin/images/")) myCacheStaticContentSeconds = 60 * 60 * 24 * 7; if (myCacheStaticContentSeconds < cacheStaticContentSeconds) myCacheStaticContentSeconds = cacheStaticContentSeconds; for (int i=0; i 0 && bodka > lomka) { String fileName = path.substring(lomka + 1); if (isForceDownload(fileName)) { response.setHeader("Content-Disposition", "attachment;filename="+fileName); } } } catch (Exception ex) { sk.iway.iwcm.Logger.error(ex); } } } public static boolean isForceDownload(String fileName) { String forceDownloadSuffixes = Constants.getString("forceDownloadSuffixes"); String ext = FileTools.getFileExtension(fileName); return (Tools.isNotEmpty(forceDownloadSuffixes) && forceDownloadSuffixes.contains(ext)); } /** * Nastavi cache hlavicky na pozadovanu hodnotu v sekundach * @param myCacheStaticContentSeconds * @param response */ public static void setCacheHeaders(int myCacheStaticContentSeconds, HttpServletResponse response) { response.setHeader("Cache-Control", "max-age="+myCacheStaticContentSeconds); if (response.containsHeader("Pragma")) response.setHeader("Pragma",""); if (response.containsHeader("Expires")) response.setDateHeader("Expires", Tools.getNow()+myCacheStaticContentSeconds*1000); } /** * Cache pre staticke subory, cachuju sa len subory pre ktore sa nastavuje setStaticContentHeaders * @param url * @return */ public static boolean writeAndCacheFile(String url, HttpServletResponse response) { //ak je cache vypnuta, neriesime if (FileCache.useFileCache() == false) return false; //pre DB storage tu cache neriesime, to sa riesi priamo v IwcmFsFilter if (IwcmFsDB.useDBStorage()) return false; String mimeType = Constants.getServletContext().getMimeType(url.toLowerCase()); if (Tools.isEmpty(mimeType)) mimeType = "application/octet-stream"; response.setContentType(mimeType); byte[] data = FileCache.getObject(url); if (data != null) { response.setContentLength(data.length); try { OutputStream out=response.getOutputStream(); out.write(data); out.close(); return true; } catch (Exception ex) { sk.iway.iwcm.Logger.error(ex); } } else { IwcmFile f = new IwcmFile(Tools.getRealPath(url)); if (f.length() > FileCache.getMaxFileSize()) return false; response.setContentLength((int)f.length()); //nacitaj data do pola data = new byte[(int)f.length()]; boolean dataCopied = false; IwcmInputStream in = null; try { OutputStream out=response.getOutputStream(); in = new IwcmInputStream(f); byte[] buffer = new byte[64000]; int bytesRead = 0; int bytesCopied = 0; while ((bytesRead = in.read(buffer, 0, 64000)) != -1) { //Logger.debug(IwcmFsDB.class, "writing "+bytesRead); out.write(buffer, 0, bytesRead); System.arraycopy(buffer, 0, data, bytesCopied, bytesRead); bytesCopied+=bytesRead; } out.flush(); out.close(); in.close(); dataCopied = true; } catch (Exception e) { sk.iway.iwcm.Logger.error(e); } finally { if (in != null) try { in.close(); } catch (Exception e) {} } if (dataCopied) { FileCache.setObject(url, data); return true; } } return false; } /** * Nastavenie hlavicky X-Robots-Tag, viz https://developers.google.com/webmasters/control-crawl-index/docs/robots_meta_tag * @param url * @param response */ public static void setXRobotsTagValue(String url, HttpServletResponse response) { String xRobotsTagUrls = Constants.getString("xRobotsTagUrls"); if (Tools.isEmpty(xRobotsTagUrls)) return; if (url.charAt(0)=='/') url = url.toLowerCase(); //aby sa nam NOT_SEARCHABLE_PAGE nezmenilo na male pismena String[] paths = Tools.getTokens(xRobotsTagUrls, ",", true); for (String path : paths) { if (ResponseHeaderService.isPathCorrect(path, url)) { String xRobotsTagValue = Constants.getStringExecuteMacro("xRobotsTagValue"); if (Tools.isNotEmpty(xRobotsTagValue)) { response.setHeader("X-Robots-Tag", xRobotsTagValue); return; } } } } public static void setUaCompatibleAdmin(String path, HttpServletResponse response) { String xUaCompatibleAdminValue = Constants.getString("xUaCompatibleAdminValue"); if (Tools.isEmpty(xUaCompatibleAdminValue)) return; response.setHeader("X-UA-Compatible", xUaCompatibleAdminValue); } /** * Nastavi hlavicku X-Frame-Options podla konfiguracnej premennej xFrameOptions * @param response */ private static void setXFrameOptions(HttpServletResponse response) { String xFrameOptions = Constants.getString("xFrameOptions"); if (Tools.isEmpty(xFrameOptions)) return; response.setHeader("X-Frame-Options", xFrameOptions); } private static void setXXssProtection(HttpServletResponse response) { String xXssProtection = Constants.getString("xXssProtection"); if (Tools.isEmpty(xXssProtection)) return; response.setHeader("X-XSS-Protection", xXssProtection); } /** * Nastavi hlavicku Feature-Policy podla konfiguracnej premennej featurePolicyHeader * @param response */ public static void setFeaturePolicy(HttpServletResponse response) { String featurePolicy = Constants.getString("featurePolicyHeader"); if (Tools.isEmpty(featurePolicy)) return; response.setHeader("Feature-Policy", featurePolicy); response.setHeader("Permissions-Policy", featurePolicy); } /** * Nastavenie hlavicky Access-Control-Allow-Origin * @param url * @param response */ public static void setAccessControlAllowOrigin(String url, HttpServletResponse response) { String accessControlAllowOriginUrls = Constants.getString("accessControlAllowOriginUrls"); if (Tools.isEmpty(accessControlAllowOriginUrls)) return; String[] paths = Tools.getTokens(accessControlAllowOriginUrls, ",", true); String accessControlAllowOriginValue = Constants.getStringExecuteMacro("accessControlAllowOriginValue"); for (String path : paths) { if (ResponseHeaderService.isPathCorrect(path, url)) { if (Tools.isNotEmpty(accessControlAllowOriginValue)) { String accessControlAllowedOrigins = Constants.getString("accessControlAllowedOrigins"); boolean canAccess = false; if (Tools.isEmpty(accessControlAllowedOrigins)) { canAccess = true; } else { accessControlAllowedOrigins = Tools.replace(accessControlAllowedOrigins, "\n", ","); accessControlAllowedOrigins = Tools.replace(accessControlAllowedOrigins, "\r", ","); RequestBean rb = SetCharacterEncodingFilter.getCurrentRequestBean(); if (rb != null) { String origin = rb.getHeaderOrigin(); if (Tools.isNotEmpty(origin)) { if ((","+accessControlAllowedOrigins+",").contains(","+origin+",")) canAccess = true; } } } if (canAccess) { response.setHeader("Access-Control-Allow-Origin", accessControlAllowOriginValue); setHeader(response, "Access-Control-Allow-Headers", "accessControlAllowHeaders"); setHeader(response, "Access-Control-Allow-Methods", "accessControlAllowMethods"); setHeader(response, "Access-Control-Max-Age", "accessControlMaxAge"); return; } } } } } /** * Nastavi HTTP hlavicku podla nazvu konfiguracnej premennej * @param response * @param headerName - meno HTTP hlavicky * @param constantName - meno konfiguracnej premennej */ public static void setHeader(HttpServletResponse response, String headerName, String constantName) { String value = Constants.getStringExecuteMacro(constantName); if (Tools.isEmpty(value)) return; if (" ".equals(value)) value = " "; //Logger.debug(SetCharacterEncodingFilter.class, "Setting header "+headerName+":"+value); response.setHeader(headerName, value); } /** * Nastavi hlavicky pre konkretne volania podla konfiguracnej premennej responseHeaders * @param response */ private static void setResponseHeaders(String path, HttpServletRequest request, HttpServletResponse response) { if (path.startsWith("/files") || path.startsWith("/images") || path.startsWith("/shared")) { String lngCode = Constants.getString("defaultLanguage"); //set last known language for files and images folder if (path.contains("/en/")) lngCode = "en"; else if (path.contains("/de/")) lngCode = "de"; else if (path.contains("/cz/")) lngCode = "cz"; else if (path.contains("/sk/")) lngCode = "sk"; else lngCode = PageLng.getUserLng(request); String isoCode = PageLng.getUserLngIso(lngCode); ResponseHeaderService.setContentLanguageHeader(isoCode, true, request, response); } // parse and cache if(responseHeaders == null) { synchronized (PathFilter.class) { String[] headers = Tools.getTokens(Constants.getString("responseHeaders"), "\n"); if(headers.length > 0) { responseHeaders = new ArrayList<>(); for(int i = 0; i < headers.length; i++) { responseHeaders.add(new ResponseHeaderBean(headers[i])); } } } } // set headers if(responseHeaders != null) { for(ResponseHeaderBean header : responseHeaders) { if(path.startsWith(header.getUrl())) { response.setHeader(header.getName(), Constants.executeMacro(header.getValue())); } } } ResponseHeaderService.setResponseHeaders(path, request, response); } /** * Ak existuje _mobile.jsp verzia zadaneho JSP vykona nan interny forward a vrati true pre ukoncenie povodneho JSP, nieco ako: * if (PathFilter.forwardToMobileOrTablet("/components/magzilla/new_bug_popup.jsp", pageContext)) return; * @param jspFileName * @param context * @return */ public static boolean forwardToMobileOrTablet(String jspFileName, PageContext context) { if (BrowserDetector.isSmartphoneOrTablet((HttpServletRequest)context.getRequest())==false) return false; String mobileJsp = Tools.replace(jspFileName, ".jsp", "_mobile.jsp"); if (FileTools.isFile(mobileJsp)==false) return false; try { context.forward(mobileJsp); return true; } catch (Exception e) { sk.iway.iwcm.Logger.error(e); } return false; } /** * Pouziva sa v spojeni s nginx cache proxy serverom, nastavuje cookie s nazvom nc ktora nasledne v * dalsich http requestoch od klienta zamedzi posielaniu cache vysledkov (ak je nastavena na hodnotu 1) * @param request * @param response */ public static void setNginxProxyMode(HttpServletRequest request, HttpServletResponse response) { try { if (Constants.getBoolean("nginxProxyMode")==false) return; String actualCookieValue = Tools.getCookieValue(request.getCookies(), "nc", null); Cookie c = new Cookie("nc", "1"); c.setPath("/"); //ak potrebujeme nastavit nocache cookie if (isNoCacheCookieRequired(request)) { //ak uz je nastavena na 1 tak ju nemusime nastavovat if ("1".equals(actualCookieValue)==false) { //session cookie c.setMaxAge(-1); //toto nesmie ist cez Tools.addCookie pretoze sa ani v pripade EU smernice nemoze vypnut response.addCookie(c); } } else { if ("1".equals(actualCookieValue)) { //cookie nam prisla v http requeste ale uz ju nemam setovat, takze ju dam zmazat c.setMaxAge(0); //toto nesmie ist cez Tools.addCookie pretoze sa ani v pripade EU smernice nemoze vypnut response.addCookie(c); } } } catch (Exception e) { sk.iway.iwcm.Logger.error(e); } } /** * Overi, ci je mozne pouzit nginx proxy rezim (konstanta nginxProxyMode), ak je povoleny, overuje este: * prihlaseneho pouzivatela (rezim nedostupny) * prepnutie verzie cez forceBrowserDetector (ak je ina verzia ako pc nedostupne) * @param request * @return */ public static boolean isNoCacheCookieRequired(HttpServletRequest request) { if (request.getSession()!=null) { if (request.getSession().getAttribute(Constants.USER_KEY)!=null) return true; else if (request.getParameter("forceBrowserDetector")!=null && "pc".equals(request.getParameter("forceBrowserDetector"))==false) return true; //NOSONAR else if (request.getSession().getAttribute("BrowserDetector.forceBrowserDetector")!=null) return true; //NOSONAR } return false; } /** * Vrati URL adresu pre httpS presmerovanie * @param request * @return */ public static String getHttpsRedirectUrl(HttpServletRequest request) { String path = PathFilter.getOrigPath(request); String qs = request.getQueryString(); StringBuilder url = new StringBuilder("https://").append(Tools.getServerName(request)).append(path); if (Tools.isNotEmpty(qs)) url.append('?').append(qs); return Tools.sanitizeHttpHeaderParam(url.toString()); } /** * Otestuje, ci je povolene showdoc volanie pre dane docId * @param docId - id dokumentu * @param constantName - meno konstanty * @return */ private static boolean isShowDocAllowDocId(int docId, String constantName) { String showDocAllowDocIds = Constants.getString(constantName); if (Tools.isNotEmpty(showDocAllowDocIds)) { StringTokenizer st = new StringTokenizer(showDocAllowDocIds, ",+;"); while (st.hasMoreTokens()) { int token = Tools.getIntValue(st.nextToken().trim(), -1); if(token == -1) continue; //preskocim if(docId == token) { return true; } } } return false; } public static void resetResponseHeaders() { responseHeaders = null; } public static void resetCacheStaticContentSeconds() { cacheStaticContentSeconds = -1; cacheStaticContentSuffixes = null; } //pre WebJET 9 kontrolujeme pri REST volaniach CSRF token private boolean checkCSRFTokenAjax(String path, HttpServletRequest request) { if (path.startsWith("/admin/rest/")==false || path.startsWith("/admin/rest/document/") || path.startsWith("/admin/rest/datatables/") ) { //taketo URL nekontrolujeme return true; } //ak path obsahuje vyraz html tak token nie je potrebny if (path.contains("/html") || path.contains("html/")) return true; if ("webjet9".equals(Constants.getString("defaultSkin"))==false) return true; //pouziva sa pri prihlaseni tokenom, vtedy CSRF nie je posielane if (request.getAttribute("csrfDisabled")!=null) return true; String header = request.getHeader("X-CSRF-Token"); if (Tools.isEmpty(header)) { return false; } return CSRF.verifyTokenAjax(request.getSession(), header); } private static void setCustomPath(String path) { PathFilter.customPath = path; } /** * Safely forward request dispatcher, need to use this if next statement is return * eg. after checkAdmin you must return from PathFilter even when /404.jsp has compilation errors * @param request * @param response * @param path */ private static void forwardSafely(String path, HttpServletRequest request, HttpServletResponse response){ try { request.getRequestDispatcher(path).forward(request, response); } catch (Exception ex) { Logger.error(PathFilter.class, ex); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy