Create javascript sandbox with jsoup support
Create javascript sandbox with jsoup support
- Create com.paesia.schema.script.Machine class as following
- Create com.paesia.schema.script.safe.jsoup.SJsoup class as following
- Create com.paesia.schema.script.safe.jsoup.SConnection class as following
- Create DataHandler class as following
- Create javascript as following
- Call Machine.run() method as following
Call Machine.run() method
String js = loadJS();
Map args = new HashMap();
List links = new ArrayList();
args.put("links", links);
Machine env = new Machine(new DataHandler());
Machine.run(env, js, args);
for (int i = 0; i < links.size(); i++) {
Map item = (Map)links.get(i);
String line = "";
for (Object key : item.keySet()) {
line += "\r\n" + key + " : " + item.get(key);
}
logger.info("\r\n--------------------------------\r\n" + line + "\r\n");
}
com.paesia.schema.script.Machine class
package com.paesia.schema.script;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.mozilla.javascript.ClassShutter;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
import com.paesia.schema.script.safe.jsoup.SJsoup;
import java.util.UUID;
import java.util.Random;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import javax.mail.internet.MimeUtility;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.Locale;
import java.util.TimeZone;
import java.util.SimpleTimeZone;
import java.util.Calendar;
public class Machine {
private Handler handler;
public static void run(Machine env, String js, Map args) throws Exception {
try {
Context cx = Context.enter();
cx.setClassShutter(new ClassShutter() {
public boolean visibleToScripts(String className) {
if ("com.paesia.schema.script.Machine".equals(className)) return true;
if ("java.lang.String".equals(className)) return true;
if ("java.lang.Object".equals(className)) return true;
if ("java.util.HashMap".equals(className)) return true;
if ("java.util.ArrayList".equals(className)) return true;
if ("java.lang.Byte".equals(className)) return true;
if ("java.lang.Short".equals(className)) return true;
if ("java.lang.Integer".equals(className)) return true;
if ("java.lang.Long".equals(className)) return true;
if ("java.lang.Float".equals(className)) return true;
if ("java.lang.Double".equals(className)) return true;
if ("java.lang.Boolean".equals(className)) return true;
if ("java.lang.Character".equals(className)) return true;
if ("java.util.Collection".equals(className)) return true;
if ("java.util.List".equals(className)) return true;
if ("java.util.Map".equals(className)) return true;
if ("java.util.LinkedHashMap".equals(className)) return true;
if ("java.util.Iterator".equals(className)) return true;
if ("java.util.ListIterator".equals(className)) return true;
if ("java.lang.Iterable".equals(className)) return true;
if ("java.net.URL".equals(className)) return true;
if (className.startsWith("org.jsoup.nodes.")) return true;
if (className.startsWith("org.jsoup.select.")) return true;
if (className.startsWith("org.jsoup.safety.")) return true;
if (className.startsWith("org.jsoup.parser.")) return true;
if (className.startsWith("com.paesia.schema.script.safe.")) return true;
if ("org.jsoup.helper.HttpConnection$Response".equals(className)) return true;
if ("java.util.Date".equals(className)) return true;
if ("java.text.SimpleDateFormat".equals(className)) return true;
if (className.startsWith("java.util.Collections")) return true;
if ("java.util.LinkedHashSet".equals(className)) return true;
if ("java.util.Locale".equals(className)) return true;
if ("java.util.TimeZone".equals(className)) return true;
if ("java.util.SimpleTimeZone".equals(className)) return true;
if ("java.util.Calendar".equals(className)) return true;
if ("java.util.GregorianCalendar".equals(className)) return true;
return false;
}
});
Scriptable scope = cx.initStandardObjects();
Object result = cx.evaluateString(scope, js, "<js>", 1, null);
Object fObj = scope.get("main", scope);
if (!(fObj instanceof Function)) {
throw new Exception("main() is undefined or not a function.");
} else {
Object functionArgs[] = { env, args };
Function f = (Function)fObj;
result = f.call(cx, scope, scope, functionArgs);
}
} catch (Exception e) {
throw e;
} finally {
Context.exit();
}
}
public String newString(String src) {
return src;
}
public String newString(byte[] src, String charset) throws Exception {
return new String(src, charset);
}
public HashMap newHashMap() {
return new HashMap();
}
public ArrayList newArrayList() {
return new ArrayList();
}
public Byte newByte(byte src) {
return (Byte)src;
}
public Short newShort(short src) {
return (Short)src;
}
public Integer newInteger(int src) {
return (Integer)src;
}
public Long newLong(long src) {
return (Long)src;
}
public Float newFloat(float src) {
return (Float)src;
}
public Double newDouble(double src) {
return (Double)src;
}
public Boolean newBoolean(boolean src) {
return (Boolean)src;
}
public Character newCharacter(char src) {
return (Character)src;
}
public List getKeys(Map src) {
List tag = new ArrayList();
for (Object key : src.keySet()) {
tag.add(key);
}
return tag;
}
public URL newURL(String protocol, String host, int port, String file) throws Exception {
return new URL(protocol, host, port, file);
}
public URL newURL(String protocol, String host, String file) throws Exception {
return new URL(protocol, host, file);
}
public URL newURL(String spec) throws Exception {
return new URL(spec);
}
public URL newURL(URL context, String spec) throws Exception {
return new URL(context, spec);
}
public SJsoup newJsoup() {
return new SJsoup();
}
public String encodeURL(String src, String charset) {
try {
return URLEncoder.encode(src, charset);
} catch (Exception e) {
return "";
}
}
public String decodeURL(String src, String charset) {
try {
return URLDecoder.decode(src, charset);
} catch (Exception e) {
return "";
}
}
public String uniqid() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
public String suniqid() {
Random random = new Random();
return Long.toString(Math.abs(random.nextLong()), 36);
}
public Date newDate() {
return new Date();
}
public Date newDate(long time) {
return new Date(time);
}
public SimpleDateFormat newDateFormat(String format) {
return new SimpleDateFormat(format);
}
public byte[] decodeBase64(byte[] b) throws Exception {
ByteArrayInputStream bais = new ByteArrayInputStream(b);
InputStream b64is = MimeUtility.decode(bais, "base64");
byte[] tmp = new byte[b.length];
int n = b64is.read(tmp);
byte[] res = new byte[n];
System.arraycopy(tmp, 0, res, 0, n);
return res;
}
public byte[] encodeBase64(byte[] b) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream b64os = MimeUtility.encode(baos, "base64");
b64os.write(b);
b64os.close();
return baos.toByteArray();
}
public List<Object> setToList(Set src) {
List<Object> tag = new ArrayList<Object>();
for (Object item : src) {
tag.add(item);
}
return tag;
}
public Locale newLocale(String language) {
return new Locale(language);
}
public Locale newLocale(String language, String country) {
return new Locale(language, country);
}
public Locale newLocale(String language, String country, String variant) {
return new Locale(language, country, variant);
}
public TimeZone newTimeZone(int rawOffset, String ID) {
return new SimpleTimeZone(rawOffset, ID);
}
public TimeZone newTimeZone(int rawOffset, String ID, int startMonth, int startDay, int startDayOfWeek, int startTime, int endMonth, int endDay, int endDayOfWeek, int endTime) {
return new SimpleTimeZone(rawOffset, ID, startMonth, startDay, startDayOfWeek, startTime, endMonth, endDay, endDayOfWeek, endTime);
}
public TimeZone newTimeZone(int rawOffset, String ID, int startMonth, int startDay, int startDayOfWeek, int startTime, int endMonth, int endDay, int endDayOfWeek, int endTime, int dstSavings) {
return new SimpleTimeZone(rawOffset, ID, startMonth, startDay, startDayOfWeek, startTime, endMonth, endDay, endDayOfWeek, endTime, dstSavings);
}
public TimeZone newTimeZone(int rawOffset, String ID, int startMonth, int startDay, int startDayOfWeek, int startTime, int startTimeMode, int endMonth, int endDay, int endDayOfWeek, int endTime, int endTimeMode, int dstSavings) {
return new SimpleTimeZone(rawOffset, ID, startMonth, startDay, startDayOfWeek, startTime, startTimeMode, endMonth, endDay, endDayOfWeek, endTime, endTimeMode, dstSavings);
}
public Calendar newCalendar() {
return Calendar.getInstance();
}
public Calendar newCalendar(Locale aLocale) {
return Calendar.getInstance(aLocale);
}
public Calendar newCalendar(TimeZone zone) {
return Calendar.getInstance(zone);
}
public Calendar newCalendar(TimeZone zone, Locale aLocale) {
return Calendar.getInstance(zone, aLocale);
}
public Machine(Handler handler) {
this.handler = handler;
}
public void debug(String message) {
if (handler != null) {
handler.debug(message);
}
}
public void error(String message) {
if (handler != null) {
handler.error(message);
}
}
public void fatal(String message) {
if (handler != null) {
handler.fatal(message);
}
}
public void info(String message) {
if (handler != null) {
handler.info(message);
}
}
public static class Handler {
public void debug(String message) { }
public void error(String message) { }
public void fatal(String message) { }
public void info(String message) { }
}
}
com.paesia.schema.script.safe.jsoup.SJsoup class
package com.paesia.schema.script.safe.jsoup;
import java.net.URL;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.safety.Whitelist;
public class SJsoup {
public static Document parse(String html, String baseUri) {
return Jsoup.parse(html, baseUri);
}
public static Document parse(String html) {
return Jsoup.parse(html);
}
public static Document parse(URL url, int timeoutMillis) throws Exception {
if (!"http".equals(url.getProtocol()) && !"https".equals(url.getProtocol())) throw new Exception("Protocol is not supported!");
return Jsoup.parse(url, timeoutMillis);
}
public static Document parseBodyFragment(String bodyHtml) {
return Jsoup.parseBodyFragment(bodyHtml);
}
public static Document parseBodyFragment(String bodyHtml, String baseUri) {
return Jsoup.parseBodyFragment(bodyHtml, baseUri);
}
public static String clean(String bodyHtml, String baseUri, Whitelist whitelist) {
return Jsoup.clean(bodyHtml, baseUri, whitelist);
}
public static String clean(String bodyHtml, Whitelist whitelist) {
return Jsoup.clean(bodyHtml, whitelist);
}
public static boolean isValid(String bodyHtml, Whitelist whitelist) {
return Jsoup.isValid(bodyHtml, whitelist);
}
public static SConnection connect(String url) throws Exception {
return connect(new URL(url));
}
public static SConnection connect(URL url) throws Exception {
if (!"http".equals(url.getProtocol()) && !"https".equals(url.getProtocol())) throw new Exception("Protocol is not supported!");
return new SConnection(Jsoup.connect(url.toString()));
}
}
com.paesia.schema.script.safe.jsoup.SConnection class
package com.paesia.schema.script.safe.jsoup;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import org.jsoup.Connection;
import org.jsoup.Connection.Method;
import org.jsoup.Connection.Response;
import org.jsoup.nodes.Document;
public class SConnection {
private Connection data;
public SConnection(Connection data) {
this.data = data;
}
public SConnection method(String src) {
if ("get".equalsIgnoreCase(src)) {
this.data.method(Method.GET);
}
if ("post".equalsIgnoreCase(src)) {
this.data.method(Method.POST);
}
return this;
}
public Response execute() throws Exception {
return this.data.execute();
}
public SConnection cookie(String name, String value) {
this.data.cookie(name, value);
return this;
}
public SConnection cookies(Map cookies) {
for (Object key : cookies.keySet()) {
cookie(key + "", cookies.get(key) + "");
}
return this;
}
public SConnection data(Map src) {
Map<String, String> tag = new HashMap<String, String>();
for (Object key : src.keySet()) {
tag.put(key + "", src.get(key) + "");
}
this.data.data(tag);
return this;
}
public SConnection data(String... keyvals) {
this.data.data(keyvals);
return this;
}
public Document get() throws Exception {
return this.data.get();
}
public SConnection header(String name, String value) {
this.data.header(name, value);
return this;
}
public Document post() throws Exception {
return this.data.post();
}
public Map getCookies() {
return this.data.response().cookies();
}
public SConnection referrer(String referrer) {
this.data.referrer(referrer);
return this;
}
public SConnection timeout(int millis) {
this.data.timeout(millis);
return this;
}
public SConnection url(URL url) throws Exception {
if (!"http".equals(url.getProtocol()) && !"https".equals(url.getProtocol())) throw new Exception("Protocol is not supported!");
this.data.url(url);
return this;
}
public SConnection url(String url) throws Exception {
return url(new URL(url));
}
public SConnection userAgent(String userAgent) {
this.data.userAgent(userAgent);
return this;
}
}
DataHandler class
public static class DataHandler extends Machine.Handler {
public void debug(String message) {
logger.debug(message);
}
public void error(String message) {
logger.error(message);
}
public void fatal(String message) {
logger.fatal(message);
}
public void info(String message) {
logger.info(message);
}
}
javascript
function main(env, args) {
var links = args.get('links');
try {
var url = env.newURL('http://yahoo.com');
var doc = env.newJsoup().parse(url, 60000);
var elements = doc.select('a');
for (var i = 0; i < elements.size(); i++) {
var element = elements.get(i);
var item = env.newHashMap();
item.put('title', element.text());
var href = env.newURL(url, element.attr('href'));
item.put('link', href + '');
links.add(item);
}
} catch (e) {
env.error(e);
}
}
No comments:
Post a Comment