/*
GNU GENERAL LICENSE
Copyright (C) 2006 The Lobo Project. Copyright (C) 2014 - 2017 Lobo Evolution
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
verion 3 of the License, or (at your option) any later version.
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
General License for more details.
You should have received a copy of the GNU General Public
along with this program. If not, see <http://www.gnu.org/licenses/>.
Contact info: lobochief@users.sourceforge.net; ivan.difrancesco@yahoo.it
*/
package org.lobobrowser.html.style;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.StringTokenizer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.lobobrowser.html.domimpl.HTMLDocumentImpl;
import org.lobobrowser.http.UserAgentContext;
import org.lobobrowser.util.SSLCertificate;
import org.lobobrowser.util.Strings;
import org.lobobrowser.util.Urls;
import org.lobobrowser.util.io.IORoutines;
import org.w3c.css.sac.InputSource;
import org.w3c.dom.css.CSSStyleSheet;
import org.w3c.dom.stylesheets.MediaList;
import com.steadystate.css.parser.CSSOMParser;
import com.steadystate.css.parser.SACParserCSS3;
/**
* The Class CSSUtilities.
*/
public class CSSUtilities {
/** The Constant logger. */
private static final Logger logger = LogManager.getLogger(CSSUtilities.class.getName());
/**
* Instantiates a new CSS utilities.
*/
private CSSUtilities() {
}
/**
* Pre process css.
*
* @param text
* the text
* @return the string
*/
public static String preProcessCss(String text) {
try {
BufferedReader reader = new BufferedReader(new StringReader(text));
String line;
StringBuffer sb = new StringBuffer();
String pendingLine = null;
// Only last line should be trimmed.
while ((line = reader.readLine()) != null) {
String tline = line.trim();
if (tline.length() != 0) {
if (pendingLine != null) {
sb.append(pendingLine);
sb.append("\r\n");
pendingLine = null;
}
if (tline.startsWith("//")) {
pendingLine = line;
continue;
}
sb.append(line);
sb.append("\r\n");
}
}
return sb.toString();
} catch (IOException ioe) {
// not possible
throw new IllegalStateException(ioe.getMessage());
}
}
/**
* Gets the css input source for style sheet.
*
* @param text
* the text
* @param scriptURI
* the script uri
* @return the css input source for style sheet
*/
public static InputSource getCssInputSourceForStyleSheet(String text, String scriptURI) {
java.io.Reader reader = new StringReader(text);
InputSource is = new InputSource(reader);
is.setURI(scriptURI);
return is;
}
/**
* @param href
* @param href
* @param doc
* @return
* @throws Exception
*/
public static CSSStyleSheet parse(String href, HTMLDocumentImpl doc) throws Exception {
URL url = null;
CSSOMParser parser = new CSSOMParser(new SACParserCSS3());
URL baseURL = new URL(doc.getBaseURI());
URL scriptURL = Urls.createURL(baseURL, href);
String scriptURI = scriptURL == null ? href : scriptURL.toExternalForm();
try {
if (scriptURI.startsWith("//")) {
scriptURI = "http:" + scriptURI;
}
url = new URL(scriptURI);
} catch (MalformedURLException mfu) {
int idx = scriptURI.indexOf(':');
if ((idx == -1) || (idx == 1)) {
// try file
url = new URL("file:" + scriptURI);
} else {
throw mfu;
}
}
logger.info("process(): Loading URI=[" + scriptURI + "].");
SSLCertificate.setCertificate();
URLConnection connection = url.openConnection();
connection.setRequestProperty("User-Agent", UserAgentContext.DEFAULT_USER_AGENT);
connection.setRequestProperty("Cookie", "");
if (connection instanceof HttpURLConnection) {
HttpURLConnection hc = (HttpURLConnection) connection;
hc.setInstanceFollowRedirects(true);
int responseCode = hc.getResponseCode();
logger.info("process(): HTTP response code: " + responseCode);
}
InputStream in = connection.getInputStream();
byte[] content;
try {
content = IORoutines.load(in, 8192);
} finally {
in.close();
}
String source = new String(content, "UTF-8");
InputSource is = getCssInputSourceForStyleSheet(source, doc.getBaseURI());
return parser.parseStyleSheet(is, null, null);
}
/**
* Matches media.
*
* @param mediaValues
* the media values
* @param rcontext
* the rcontext
* @return true, if successful
*/
public static boolean matchesMedia(String mediaValues, UserAgentContext rcontext) {
if ((mediaValues == null) || (mediaValues.length() == 0)) {
return true;
}
if (rcontext == null) {
return false;
}
StringTokenizer tok = new StringTokenizer(mediaValues, ",");
while (tok.hasMoreTokens()) {
String token = tok.nextToken().trim();
String mediaName = Strings.trimForAlphaNumDash(token);
if (rcontext.isMedia(mediaName)) {
return true;
}
}
return false;
}
/**
* Matches media.
*
* @param mediaList
* the media list
* @param rcontext
* the rcontext
* @return true, if successful
*/
public static boolean matchesMedia(MediaList mediaList, UserAgentContext rcontext) {
if (mediaList == null) {
return true;
}
int length = mediaList.getLength();
if (length == 0) {
return true;
}
if (rcontext == null) {
return false;
}
for (int i = 0; i < length; i++) {
String mediaName = mediaList.item(i);
if (rcontext.isMedia(mediaName)) {
return true;
}
}
return false;
}
}