diff pydershell/pydershell.py @ 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 b7037cd0f375
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)