use nodejs sandboxing
authorJames Bunton <jamesbunton@delx.net.au>
Thu, 17 Jul 2014 11:26:58 +0000 (21:26 +1000)
committerJames Bunton <jamesbunton@delx.net.au>
Thu, 17 Jul 2014 11:26:58 +0000 (21:26 +1000)
youtube.cgi

index d6273ba..6495c8d 100755 (executable)
@@ -35,14 +35,6 @@ QUALITIES = {
     "small": 1,
 }
 
-JS_BROWSER_STUB = """
-var window={};
-var document={};
-window.location={};
-var navigator={};
-"""
-
-
 
 class VideoUnavailable(Exception):
     pass
@@ -156,10 +148,15 @@ def find_func_name(script):
     func_name = match.groups()[0]
     return func_name
 
-def decode_signature(js_url, s):
+def decode_signature(js_url, signature):
     script = urlopen(js_url).read()
     func_name = find_func_name(script)
 
+    params = {
+        "func_name": func_name,
+        "signature": json.dumps(signature),
+        "code": json.dumps(extract_js(script)),
+    }
     p = subprocess.Popen(
         "js",
         shell=True,
@@ -167,17 +164,33 @@ def decode_signature(js_url, s):
         stdin=subprocess.PIPE,
         stdout=subprocess.PIPE
     )
-    w = p.stdin.write
-    w(JS_BROWSER_STUB)
-    w(extract_js(script))
-    w("console.log(%s('%s'));\n" % (func_name, s))
+    js_decode_script = ("""
+        var vm = require("vm");
+
+        var sandbox = {
+            window: {
+                location: {}
+            },
+            document: {},
+            navigator: {},
+            signature: %(signature)s,
+            transformed_signature: null
+        };
+
+        var execstring = ";transformed_signature = %(func_name)s(signature);";
+        vm.runInNewContext(%(code)s + execstring, sandbox);
+
+        console.log(sandbox.transformed_signature);
+    """ % params)
+
+    p.stdin.write(js_decode_script)
     p.stdin.close()
 
-    signature = p.stdout.read().strip()
+    transformed_signature = p.stdout.read().strip()
     if p.wait() != 0:
         raise Exception("js failed to execute: %d" % p.returncode)
 
-    return signature
+    return transformed_signature
 
 def get_best_video(player_config):
     url_data_list = player_config["args"]["url_encoded_fmt_stream_map"].split(",")