/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library 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 Lesser General Public License for more * details. */ package com.liferay.portal.servlet.filters.dynamiccss; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.model.PortletConstants; import com.liferay.portal.kernel.model.Theme; import com.liferay.portal.kernel.service.ThemeLocalServiceUtil; import com.liferay.portal.kernel.theme.ThemeDisplay; import com.liferay.portal.kernel.util.CharPool; import com.liferay.portal.kernel.util.ParamUtil; import com.liferay.portal.kernel.util.PortalUtil; import com.liferay.portal.kernel.util.StringBundler; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.kernel.util.WebKeys; import java.net.URLDecoder; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; /** * @author Raymond Augé * @author Sergio Sánchez * @author David Truong */ public class DynamicCSSUtil { public static String replaceToken( ServletContext servletContext, HttpServletRequest request, String content) throws Exception { ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute( WebKeys.THEME_DISPLAY); Theme theme = _getTheme(request); if (theme == null) { return content; } return replaceToken( servletContext, request, themeDisplay, theme, content); } public static String replaceToken( ServletContext servletContext, HttpServletRequest request, ThemeDisplay themeDisplay, Theme theme, String parsedContent) throws Exception { String portalContextPath = PortalUtil.getPathContext(); String baseURL = servletContext.getContextPath(); if (baseURL.endsWith(StringPool.SLASH)) { baseURL = baseURL.substring(0, baseURL.length() - 1); } parsedContent = StringUtil.replace( parsedContent, new String[] {"@base_url@", "@portal_ctx@", "@theme_image_path@"}, new String[] { baseURL, portalContextPath, _getThemeImagesPath(request, themeDisplay, theme) }); return parsedContent; } /** * @see com.liferay.portal.servlet.filters.aggregate.AggregateFilter#aggregateCss( * com.liferay.portal.servlet.filters.aggregate.ServletPaths, String) */ protected static String propagateQueryString( String content, String queryString) { StringBuilder sb = new StringBuilder(content.length()); int pos = 0; while (true) { int importX = content.indexOf(_CSS_IMPORT_BEGIN, pos); int importY = content.indexOf( _CSS_IMPORT_END, importX + _CSS_IMPORT_BEGIN.length()); if ((importX == -1) || (importY == -1)) { sb.append(content.substring(pos)); break; } sb.append(content.substring(pos, importX)); sb.append(_CSS_IMPORT_BEGIN); String url = content.substring( importX + _CSS_IMPORT_BEGIN.length(), importY); char firstChar = url.charAt(0); if (firstChar == CharPool.APOSTROPHE) { sb.append(CharPool.APOSTROPHE); } else if (firstChar == CharPool.QUOTE) { sb.append(CharPool.QUOTE); } url = StringUtil.unquote(url); sb.append(url); if (url.indexOf(CharPool.QUESTION) != -1) { sb.append(CharPool.AMPERSAND); } else { sb.append(CharPool.QUESTION); } sb.append(queryString); if (firstChar == CharPool.APOSTROPHE) { sb.append(CharPool.APOSTROPHE); } else if (firstChar == CharPool.QUOTE) { sb.append(CharPool.QUOTE); } sb.append(_CSS_IMPORT_END); pos = importY + _CSS_IMPORT_END.length(); } return sb.toString(); } private static Theme _getTheme(HttpServletRequest request) throws Exception { long companyId = PortalUtil.getCompanyId(request); String themeId = ParamUtil.getString(request, "themeId"); if (Validator.isNotNull(themeId)) { try { Theme theme = ThemeLocalServiceUtil.getTheme( companyId, themeId); return theme; } catch (Exception e) { _log.error(e, e); } } String requestURI = URLDecoder.decode( request.getRequestURI(), StringPool.UTF8); Matcher portalThemeMatcher = _portalThemePattern.matcher(requestURI); if (portalThemeMatcher.find()) { String themePathId = portalThemeMatcher.group(1); themePathId = StringUtil.replace( themePathId, CharPool.UNDERLINE, StringPool.BLANK); themeId = PortalUtil.getJsSafePortletId(themePathId); } else { Matcher pluginThemeMatcher = _pluginThemePattern.matcher( requestURI); if (pluginThemeMatcher.find()) { String themePathId = pluginThemeMatcher.group(1); themePathId = StringUtil.replace( themePathId, CharPool.UNDERLINE, StringPool.BLANK); StringBundler sb = new StringBundler(4); sb.append(themePathId); sb.append(PortletConstants.WAR_SEPARATOR); sb.append(themePathId); sb.append("theme"); themePathId = sb.toString(); themeId = PortalUtil.getJsSafePortletId(themePathId); } } if (Validator.isNull(themeId)) { return null; } try { Theme theme = ThemeLocalServiceUtil.getTheme(companyId, themeId); return theme; } catch (Exception e) { _log.error(e, e); } return null; } private static String _getThemeImagesPath( HttpServletRequest request, ThemeDisplay themeDisplay, Theme theme) throws Exception { String themeImagesPath = null; if (themeDisplay != null) { themeImagesPath = themeDisplay.getPathThemeImages(); } else { String cdnHost = PortalUtil.getCDNHost(request); String themeStaticResourcePath = theme.getStaticResourcePath(); themeImagesPath = cdnHost + themeStaticResourcePath + theme.getImagesPath(); } return themeImagesPath; } private static final String _CSS_IMPORT_BEGIN = "@import url("; private static final String _CSS_IMPORT_END = ");"; private static final Log _log = LogFactoryUtil.getLog(DynamicCSSUtil.class); private static final Pattern _pluginThemePattern = Pattern.compile( "\\/([^\\/]+)-theme\\/", Pattern.CASE_INSENSITIVE); private static final Pattern _portalThemePattern = Pattern.compile( "themes\\/([^\\/]+)\\/css", Pattern.CASE_INSENSITIVE); }