/**
 * Axelor Business Solutions
 *
 * Copyright (C) 2005-2015 Axelor (<http://axelor.com>).
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.axelor.web;

import static com.axelor.common.StringUtils.isBlank;

import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.inject.Singleton;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.axelor.app.AppSettings;

/**
 * Simple CORS filter that checks <code>Origin</code> header of the requests
 * with the allowed origin pattern.
 * 
 * <p>
 * If the <code>Origin</code> header matches the configured allowed pattern, it
 * will set other configured CORS headers.
 * </p>
 * 
 */
@Singleton
public class CorsFilter implements Filter {

	private static final String DEFAULT_CORS_ALLOW_ORIGIN = "*";
	private static final String DEFAULT_CORS_ALLOW_CREDENTIALS = "true";
	private static final String DEFAULT_CORS_ALLOW_METHODS = "GET,PUT,POST,DELETE,HEAD,OPTIONS";
	private static final String DEFAULT_CORS_ALLOW_HEADERS = "Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers";

	private static Pattern corsOriginPattern;

	private static String corsAllowOrigin;
	private static String corsAllowCredentials;
	private static String corsAllowMethods;
	private static String corsAllowHeaders;

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {

		final AppSettings settings = AppSettings.get();

		corsAllowOrigin = settings.get("cors.allow.origin");
		corsAllowCredentials = settings.get("cors.allow.credentials", DEFAULT_CORS_ALLOW_CREDENTIALS);
		corsAllowMethods = settings.get("cors.allow.methods", DEFAULT_CORS_ALLOW_METHODS);
		corsAllowHeaders = settings.get("cors.allow.headers", DEFAULT_CORS_ALLOW_HEADERS);

		if (!isBlank(corsAllowOrigin)) {
			corsOriginPattern = Pattern.compile(corsAllowOrigin);
		}
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {

		final HttpServletRequest req = (HttpServletRequest) request;
		final HttpServletResponse res = (HttpServletResponse) response;
		final String origin = req.getHeader("Origin");

		if (corsOriginPattern == null || isBlank(origin)) {
			chain.doFilter(request, response);
			return;
		}

		final Matcher matcher = corsOriginPattern.matcher(origin);

		if (matcher.matches() || DEFAULT_CORS_ALLOW_ORIGIN.equals(corsAllowOrigin)) {
			res.addHeader("Access-Control-Allow-Origin", origin);
			res.addHeader("Access-Control-Allow-Credentials", corsAllowCredentials);
			res.addHeader("Access-Control-Allow-Methods", corsAllowMethods);
			res.addHeader("Access-Control-Allow-Headers", corsAllowHeaders);
		}

		chain.doFilter(request, response);
	}

	@Override
	public void destroy() {
	}
}

@@ -828,23 +828,23 @@
 l.regex.
-Match
+Patt
 er
+n
 ;%0Aimport
@@ -867,16 +867,31 @@
 .Pattern
+SyntaxException
 ;%0A%0Aimpor
@@ -1222,16 +1222,74 @@
 ponse;%0A%0A
+import org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0A%0A
 import c
@@ -2244,16 +2244,82 @@
 aders;%0A%0A
+%09private Logger log = LoggerFactory.getLogger(CorsFilter.class);%0A%0A
 %09@Overri
@@ -2777,9 +2777,8 @@
 if (
-!
 isBl
@@ -2808,60 +2808,371 @@
 %0A%09%09%09
-corsOriginPattern = Pattern.compile(corsAllowOrigin)
+return;%0A%09%09%7D%0A%0A%09%09log.debug(%22CORS origin: %7B%7D%22, corsAllowOrigin);%0A%0A%09%09if (DEFAULT_CORS_ALLOW_ORIGIN.equals(corsAllowOrigin)) %7B%0A%09%09%09corsOriginPattern = Pattern.compile(%22.*%22);%0A%09%09%09return;%0A%09%09%7D%0A%09%09try %7B%0A%09%09%09corsOriginPattern = Pattern.compile(corsAllowOrigin);%0A%09%09%7D catch (PatternSyntaxException e) %7B%0A%09%09%09log.error(%22CORS origin pattern is invalid%22, e);%0A%09%09%09corsAllowOrigin = null
 ;%0A%09%09
@@ -3615,95 +3615,12 @@
 %0A%0A%09%09
-final Matcher matcher = corsOriginPattern.matcher(origin);%0A%0A%09%09if (matcher.matches() %7C%7C 
+if (
 DEFA
@@ -3656,32 +3656,79 @@
 corsAllowOrigin)
+ %7C%7C corsOriginPattern.matcher(origin).matches()
 ) %7B%0A%09%09%09res.addHe

Fix CORS filter