package com.idega.content.themes.helpers.business; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import com.idega.content.business.ContentConstants; import com.idega.servlet.filter.IWBundleResourceFilter; import com.idega.util.ArrayUtil; import com.idega.util.CoreConstants; import com.idega.util.ListUtil; import com.idega.util.StringHandler; import com.idega.util.StringUtil; import com.idega.util.resources.ResourceScanner; @Scope(BeanDefinition.SCOPE_PROTOTYPE) @Service(CssScanner.SPRING_BEAN_IDENTIFIER) public class CssScanner implements ResourceScanner { private static final long serialVersionUID = -694282023660051365L; private static Logger LOGGER = Logger.getLogger(CssScanner.class.getName()); public static final String SPRING_BEAN_IDENTIFIER = "cssScanner"; private StringBuffer resultBuffer = null; private String linkToTheme = null; private boolean needToReplace = false; private int openers = 0; private int closers = 0; private static final String COLOR_STRING = "color"; private static final String COMMENT_BEGIN = "/*"; private static final String COMMENT_END = "*/"; private static final String DIRECTORY_LEVEL_UP = "../"; private static final String OPENER = "{"; private static final String CLOSER = "}"; private static final String UTF_8_DECLARATION = "@charset \"UTF-8\";"; @Autowired private ThemesHelper themesHelper; public void scanFile(List<String> fileLines) { openers = 0; closers = 0; needToReplace = false; resultBuffer = new StringBuffer(); String changedLine = null; for (String line: fileLines) { changedLine = line; changedLine = scanLine(line); resultBuffer.append(changedLine).append(ThemesConstants.NEW_LINE); if (!line.equals(changedLine)) { // If line was modified needToReplace = true; } } } public void setLinkToTheme(String linkToTheme) { this.linkToTheme = linkToTheme; } private boolean canUseURL(String line) { String urlExpressionStart = "url("; int start = line.indexOf(urlExpressionStart); int end = line.lastIndexOf(ContentConstants.BRACKET_CLOSING); if (start < 0 || end < 0) { return false; } String file = line.substring(line.lastIndexOf(CoreConstants.SLASH)); if (StringUtil.isEmpty(file) || file.indexOf(CoreConstants.DOT) == -1) return false; String urlExpression = line.substring(start + urlExpressionStart.length(), end); urlExpression = StringHandler.replace(urlExpression, DIRECTORY_LEVEL_UP, ThemesConstants.EMPTY); urlExpression = StringHandler.replace(urlExpression, "'", CoreConstants.EMPTY); urlExpression = StringHandler.replace(urlExpression, "\"", CoreConstants.EMPTY); String path = new StringBuffer(linkToTheme).append(urlExpression).toString(); try { return getThemesHelper().getSlideService().getExistence(path); } catch (Exception e) { LOGGER.log(Level.WARNING, "Error checking if file '" + path + "' exists", e); } return false; } private String scanLine(String line) { if (line == null) { return ThemesConstants.EMPTY; } if (line.indexOf(UTF_8_DECLARATION) != -1) { line = StringHandler.replace(line, UTF_8_DECLARATION, CoreConstants.EMPTY); return line; } // Checking for incorrect hexidecimal values if (line.indexOf(CoreConstants.HASH) != -1 && line.indexOf(COLOR_STRING) != -1) { String[] colorValue = line.split(CoreConstants.HASH); if (colorValue == null) { return line; } if (colorValue.length != 2) { return line; } String color = colorValue[1]; int index = StringHandler.getNotHexValueIndexInHexValue(color); String letterToReplace = null; while (index >= 0) { letterToReplace = CoreConstants.HEXIDECIMAL_LETTERS.get(getThemesHelper().getRandomNumber(CoreConstants.HEXIDECIMAL_LETTERS.size())); if (index == color.length() - 1) { color = color.replace(color.substring(index), letterToReplace); } else { color = color.replace(color.substring(index, index + 1), letterToReplace); } index = StringHandler.getNotHexValueIndexInHexValue(color); } line = new StringBuffer(colorValue[0]).append(CoreConstants.HASH).append(color).toString(); } // Checking URL stuff if (line.indexOf("url(") != -1) { if (canUseURL(line)) { return line; } else { LOGGER.log(Level.WARNING, "Removing CSS expression: '" + line + "' because this object was not found in theme's pack or it is invalid!"); return ThemesConstants.EMPTY; } } // Checking comments if (line.indexOf(OPENER) == -1 && line.indexOf(CLOSER) == -1) { return line; } int commentBeginIndex = line.indexOf(COMMENT_BEGIN); int commentEndIndex = line.indexOf(COMMENT_END); int styleDefinitionBeginIndex = line.indexOf(OPENER); int styleDefinitionEndIndex = line.indexOf(CLOSER); if (commentBeginIndex != -1 && commentEndIndex != -1) { // CSS: /* www.multithemes.com */ if (styleDefinitionBeginIndex == -1 && styleDefinitionEndIndex == -1) { return line; } // CSS: /*comment*/body { or: body {/*comment*/ if ((styleDefinitionBeginIndex > commentBeginIndex && styleDefinitionBeginIndex > commentEndIndex) || (styleDefinitionBeginIndex < commentBeginIndex && styleDefinitionBeginIndex < commentEndIndex)) { openers++; return line; } // CSS: /*comment*/} or }/*comment*/ if ((styleDefinitionEndIndex > commentBeginIndex && styleDefinitionEndIndex > commentEndIndex) || (styleDefinitionEndIndex < commentBeginIndex && styleDefinitionEndIndex < commentEndIndex)) { return finishCssLine(line); } } else { // Lines of comment if (commentBeginIndex != -1 && commentEndIndex == -1) { if (styleDefinitionBeginIndex != -1 && styleDefinitionBeginIndex < commentBeginIndex) { openers++; } if (styleDefinitionEndIndex != -1 && styleDefinitionEndIndex < commentBeginIndex) { return finishCssLine(line); } return line; } if (commentBeginIndex == -1 && commentEndIndex != -1) { if (styleDefinitionBeginIndex != -1 && styleDefinitionBeginIndex > commentEndIndex) { openers++; } if (styleDefinitionEndIndex != -1 && styleDefinitionEndIndex > commentEndIndex) { return finishCssLine(line); } return line; } } if (line.indexOf(OPENER) != -1 && line.indexOf(CLOSER) != -1 && openers == closers) { return line; } if (line.indexOf(OPENER) != -1 && line.indexOf(CLOSER) == -1) { openers++; return line; } if (line.indexOf(OPENER) == -1 && line.indexOf(CLOSER) != -1) { return finishCssLine(line); } return line; } private String finishCssLine(String line) { closers++; if (closers != openers) { line = line.replace(CLOSER, ThemesConstants.EMPTY); } openers = 0; closers = 0; return line; } public StringBuffer getResultBuffer() { return resultBuffer; } public boolean isNeedToReplace() { return needToReplace; } public String getParsedContent(List<String> contentLines, String fileUri) { if (ListUtil.isEmpty(contentLines) || fileUri == null) { return null; } String parsedLine = null; StringBuilder parsedContent = new StringBuilder(); for (String line: contentLines) { parsedLine = getParsedLine(line, fileUri); parsedContent.append("\n").append(parsedLine); } return parsedContent.toString(); } private String getParsedLine(String line, String fileUri) { String urlExpressionStart = "url("; if (line.indexOf(urlExpressionStart) == -1) { return line; } if (line.indexOf(IWBundleResourceFilter.BUNDLES_STANDARD_DIR) != -1) { return line; } line = line.replaceAll(CoreConstants.QOUTE_SINGLE_MARK, CoreConstants.EMPTY); line = line.replaceAll(CoreConstants.QOUTE_MARK, CoreConstants.EMPTY); int startIndex = line.indexOf(urlExpressionStart) + urlExpressionStart.length(); int endIndex = line.indexOf(")"); String urlExpression = null; if (startIndex != -1 && endIndex != -1 && startIndex <= endIndex) { urlExpression = line.substring(startIndex, endIndex); } if (urlExpression == null) { return line; } String originalExpression = urlExpression; String urlReplacement = null; int levelsUp = 0; if (urlExpression.startsWith(DIRECTORY_LEVEL_UP)) { while (urlExpression.indexOf(DIRECTORY_LEVEL_UP) != -1) { urlExpression = urlExpression.replaceFirst(DIRECTORY_LEVEL_UP, CoreConstants.EMPTY); levelsUp++; } } if (levelsUp == 0) { if (!urlExpression.startsWith(fileUri)) { urlReplacement = new StringBuilder(fileUri).append(urlExpression).toString(); } } else { String[] resourceParts = fileUri.split(CoreConstants.SLASH); if (ArrayUtil.isEmpty(resourceParts)) { return line; } StringBuilder newUrlExpression = new StringBuilder(); for (int i = 0; i < (resourceParts.length - levelsUp); i++) { if (!StringUtil.isEmpty(resourceParts[i])) { newUrlExpression.append(CoreConstants.SLASH).append(resourceParts[i]); } } urlReplacement = newUrlExpression.append(CoreConstants.SLASH).append(urlExpression).toString(); } if (StringUtil.isEmpty(urlReplacement)) { return line; } line = line.replace(originalExpression, urlReplacement); return line; } public ThemesHelper getThemesHelper() { return themesHelper; } public void setThemesHelper(ThemesHelper themesHelper) { this.themesHelper = themesHelper; } }