Mercurial > scratch
changeset 24:dace90a7f5e3
Added a 'jsexposed' decorator and, for security purposes, required that __jsexposed__ be True on all callables passed into JS-land as well.
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Mon, 07 Sep 2009 16:53:41 -0700 |
parents | 35ab0ad3c294 |
children | 64fb84017d87 |
files | pydershell/pydershell.py pydershell/test.py |
diffstat | 2 files changed, 36 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/pydershell/pydershell.py Mon Sep 07 16:25:58 2009 -0700 +++ b/pydershell/pydershell.py Mon Sep 07 16:53:41 2009 -0700 @@ -194,6 +194,31 @@ lines.insert(0, "Traceback (most recent call last):") return '\n'.join(lines) +def jsexposed(name=None, on=None): + """ + Decorator used to expose the decorated function or method to + untrusted JS. + + 'name' is an optional alternative name for the function. + + 'on' is an optional SafeJsObjectWrapper that the function can be + automatically attached as a property to. + """ + + if callable(name): + func = name + func.__jsexposed__ = True + return func + + def make_exposed(func): + if name: + func.__name__ = name + func.__jsexposed__ = True + if on: + on[func.__name__] = func + return func + return make_exposed + class JsExposedObject(object): """ Trivial base/mixin class for any Python classes that choose to @@ -337,6 +362,10 @@ # It's already wrapped, just unwrap it. return value.wrapped_jsobject elif callable(value): + if not (hasattr(value, '__jsexposed__') and + value.__jsexposed__): + raise ValueError("Callable isn't configured for exposure " + "to untrusted JS code") return self.__wrap_pycallable(value) elif isinstance(value, JsExposedObject): return self.__wrap_pyinstance(value)
--- a/pydershell/test.py Mon Sep 07 16:25:58 2009 -0700 +++ b/pydershell/test.py Mon Sep 07 16:53:41 2009 -0700 @@ -5,38 +5,38 @@ import sys import pydermonkey -from pydershell import JsSandbox, JsExposedObject +from pydershell import JsSandbox, JsExposedObject, jsexposed if __name__ == '__main__': sandbox = JsSandbox() class Baz(JsExposedObject): + @jsexposed def woozle(self, blap): return blap + 5 - woozle.__jsexposed__ = True + @jsexposed(on=sandbox.root) def baz(): return Baz() - sandbox.root.baz = baz + @jsexposed(on=sandbox.root) def bar(obj): print obj.bar() - sandbox.root.bar = bar + @jsexposed(on=sandbox.root) def foo(callback): return callback() - sandbox.root.foo = foo + @jsexposed(on=sandbox.root) def ensureBaz(baz): if not isinstance(baz, Baz): print "Uhoh" else: print "ok" - sandbox.root.ensureBaz = ensureBaz + @jsexposed(name="print", on=sandbox.root) def jsprint(string): print string - sandbox.root['print'] = jsprint retval = sandbox.run_script('test.js')