From c53db50bd628ec799b7a6a64addb9f18a2d42b73 Mon Sep 17 00:00:00 2001 From: Ruben Rodriguez Date: Thu, 4 Feb 2016 17:38:53 -0600 Subject: HTML5 Video Everywhere updated to 0.3.4 --- .../lib/break.js | 9 - .../lib/common.js | 2 + .../lib/dailymotion.js | 9 - .../lib/facebook.js | 7 - .../lib/flashgot-YouTube.js | 535 --------------------- .../lib/metacafe.js | 11 - .../lib/vimeo.js | 11 - .../lib/youtube.js | 30 -- 8 files changed, 2 insertions(+), 612 deletions(-) delete mode 100644 data/extensions/html5-video-everywhere@lejenome.me/lib/break.js delete mode 100644 data/extensions/html5-video-everywhere@lejenome.me/lib/dailymotion.js delete mode 100644 data/extensions/html5-video-everywhere@lejenome.me/lib/facebook.js delete mode 100644 data/extensions/html5-video-everywhere@lejenome.me/lib/flashgot-YouTube.js delete mode 100644 data/extensions/html5-video-everywhere@lejenome.me/lib/metacafe.js delete mode 100644 data/extensions/html5-video-everywhere@lejenome.me/lib/vimeo.js delete mode 100644 data/extensions/html5-video-everywhere@lejenome.me/lib/youtube.js (limited to 'data/extensions/html5-video-everywhere@lejenome.me/lib') diff --git a/data/extensions/html5-video-everywhere@lejenome.me/lib/break.js b/data/extensions/html5-video-everywhere@lejenome.me/lib/break.js deleted file mode 100644 index 0bad411..0000000 --- a/data/extensions/html5-video-everywhere@lejenome.me/lib/break.js +++ /dev/null @@ -1,9 +0,0 @@ -"use strict"; -var match = [/https?:\/\/www.break.com\/embed\/.*/]; -var inject = [ - "break.js" -]; -var when = "start"; -exports.when = when; -exports.match = match; -exports.inject = inject; \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/lib/common.js b/data/extensions/html5-video-everywhere@lejenome.me/lib/common.js index 354f4e9..3097942 100644 --- a/data/extensions/html5-video-everywhere@lejenome.me/lib/common.js +++ b/data/extensions/html5-video-everywhere@lejenome.me/lib/common.js @@ -16,5 +16,7 @@ if (prefs.player === 1) { style.push("LeanBackPlayer/css.player/leanbackPlayer.default.css"); } */ +exports.type = "site"; +exports.name = "common"; exports.inject = inject; exports.style = style; \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/lib/dailymotion.js b/data/extensions/html5-video-everywhere@lejenome.me/lib/dailymotion.js deleted file mode 100644 index 4872758..0000000 --- a/data/extensions/html5-video-everywhere@lejenome.me/lib/dailymotion.js +++ /dev/null @@ -1,9 +0,0 @@ -"use strict"; -var match = [/https?:\/\/(www.)dailymotion.com\/embed\/video\/.*/]; -var inject = [ - "dailymotion.js" -]; -var when = "start"; -exports.when = when; -exports.match = match; -exports.inject = inject; \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/lib/facebook.js b/data/extensions/html5-video-everywhere@lejenome.me/lib/facebook.js deleted file mode 100644 index 1198b28..0000000 --- a/data/extensions/html5-video-everywhere@lejenome.me/lib/facebook.js +++ /dev/null @@ -1,7 +0,0 @@ -"use strict"; -var match = [/https?:\/\/(www\.|beta\.)?facebook.com\/(.*\/videos\/.*|video.php\?.*)/]; -var inject = [ - "facebook.js" -]; -exports.match = match; -exports.inject = inject; \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/lib/flashgot-YouTube.js b/data/extensions/html5-video-everywhere@lejenome.me/lib/flashgot-YouTube.js deleted file mode 100644 index e8ca2d7..0000000 --- a/data/extensions/html5-video-everywhere@lejenome.me/lib/flashgot-YouTube.js +++ /dev/null @@ -1,535 +0,0 @@ -/***** BEGIN LICENSE BLOCK ***** - - FlashGot - a Firefox extension for external download managers integration - Copyright (C) 2004-2013 Giorgio Maone - g.maone@informaction.com - - 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 version 2 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 Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -***** END LICENSE BLOCK *****/ -/* Modified By Moez Bouhlel to be used on HTML5-Video-EveryWhere */ -/* jshint laxbreak:true, maxstatements:false, evil:true, latedef:false */ -/* jshint maxdepth:4 */ -/* jshint maxcomplexity:false, -W116 */ -/* global args:false */ -"use strict"; -const { - Cc, Ci, Cu, components, ChromeWorker -} = require("chrome"); -const service = require("sdk/preferences/service"); -var fg = { - log: (...args) => { - args.unshift("[FLASHGOT]"); - dump(args.join(" ") + "\n"); - }, - getPref: (title, def) => service.get("flashgot." + title, def), - setPref: (title, val) => service.set("flashgot." + title, val) -}; - -/////////////////////////////////////////////////////////////////////////////// -// Public part. -var Youtube = { - - decode_signature: function (params) { - /* Not encoded. */ - return params.stream.sig || ""; - }, - decode_signature_swap: function (a, idx) { - var tmp = a[0]; - a[0] = a[idx % a.length]; - a[idx] = tmp; - return a; - }, - - create_signature_decoder: function () { - var s = fg.getPref("media.YouTube.decode_signature_func", ""); - if (!s) { - return new SignatureDecoder(Youtube.decode_signature); - } - // Fail fast: try to compile right now to check the code for - // syntax errors, so that we don't do all that heavy stuff for - // sandbox initialization only to fail later in evalInSandbox() - // and have an incorrect error message saying "error _calling_ - // the function" while actually we failed to compile it. - var func = null; - try { - func = new Function("params", s); - } catch (x) { - throw new Error("Error compiling YouTube.decode_signature_func: " + (x.message || x)); - } - if ( ! fg.getPref("media.YouTube.decode_signature_func.sandbox", true)) { - return new SignatureDecoder(func); - } - // Wrap the code into a function invocation because we promised - // to call it as a function with one parameter. - s = "(function(params){\n" + s + "\n})(params);"; - return new SandboxedSignatureDecoder(s) - // Sandboxing stuff is not supported - fall back to non-sandboxed. - || new SignatureDecoder(func); - }, - - - refresh_signature_func: function (w, callback /*= null*/, force /*= false*/) { - return SDASniffer.sniff(w, callback, force); - } - -}; // Youtube - - -/////////////////////////////////////////////////////////////////////////////// -// Private part. - -// interface ISignatureDecoder { -// string decode(Params params); -// void dispose(); -// } -// class Params { -// Map stream; -// Map video_info; -// Function swap; //Array swap(Array, int); -// } -// -// class SignatureDecoder implements ISignatureDecoder { -// SignatureDecoder(Function func); -// } -function SignatureDecoder(func) { - this.func = func; -} - -SignatureDecoder.prototype = { - decode: function(params) { return this.func(params); }, - dispose: function() { this.func = null; } -}; - - -// class SandboxedSignatureDecoder implements ISignatureDecoder { -// SandboxedSignatureDecoder(String code_str); -// } -function SandboxedSignatureDecoder(code_str) { - this.code_str = code_str; - - this.sandbox = this.create_sandbox(); - if ( ! this.sandbox) { return null; } - -} // SandboxedSignatureDecoder() - - -SandboxedSignatureDecoder.prototype = { - // https://developer.mozilla.org/en-US/docs/Security_check_basics: - // The null principal (whose contract ID is @mozilla.org/nullprincipal;1) - // fails almost all security checks. It has no privileges and can't be - // accessed by anything but itself and chrome. They aren't same-origin - // with anything but themselves. - SANDBOX_PRINCIPAL: Cc["@mozilla.org/nullprincipal;1"] - .createInstance(Ci.nsIPrincipal), - - SANDBOX_OPTIONS: {wantComponents: false, wantXHRConstructor: false}, - - create_sandbox: function() { - if (typeof Cu.Sandbox !== "function") { - return null; - } - var s_gecko_ver = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULAppInfo) - .platformVersion; - var gecko_ver = parseInt(s_gecko_ver); - // NaN, Infinity. - if ( ! isFinite(gecko_ver)) { - throw new Error("Failed to parse Gecko version: '" + s_gecko_ver + "'."); - } - if (gecko_ver >= 2) { - return new Cu.Sandbox(this.SANDBOX_PRINCIPAL, this.SANDBOX_OPTIONS); - } - var opts = this.SANDBOX_OPTIONS; - var proto = opts.hasOwnProperty("sandboxPrototype") ? opts.sandboxPrototype : {} /*FIXME: null?*/; - var wantXrays = opts.hasOwnProperty("wantXrays") ? opts.wantXrays : true; - return new Cu.Sandbox(this.SANDBOX_PRINCIPAL, proto, wantXrays); - }, - - decode: function (params) { - var rc = Cu.evalInSandbox( - "var params = " + params.toSource() + ";\n" + - this.code_str, - this.sandbox); - - // No fancy return values - we expect a primitive string value. - // We don't silently return something that could pass for a signature. - // Instead, we throw - to inform the user that their decode_signature_func - // function is broken (anyone can make a typo) or malicious. - // - // It's OK to pass uncaught exceptions as-is because even if they have - // getters for properties like "message", those will be executed in the - // context of the sandbox (i.e. the global |this| will point to the sandbox), - // which is useless for malicious code anyway. - // Here's what am I talking about - somewhere in the sandboxed code: - // var x = new Error(); - // x.__defineGetter__("message", function(){alert("pwned");}); - // throw x; - // or: - // var x = { message: { valueOf: function(){alert("pwned");}, toString: function(){alert("pwned");} } }; - // throw x; - // We could catch the exceptions here, manually sanitize them and rethrow - // if they're safe to use in our chrome code, but I just don't see the point - // in doing so because if there's a bug in the security manager, then our - // manual sanitization will just conceal it. - if (typeof (rc) === "string") { return rc; } - // Nulls are kinda OK. - if (rc === null) { return ""; } - // A forgotten return or outdated code that returns nonexistent stream - // properties? Worth a warning in either case. - if (rc === undefined) { - fg.log("WARNING: YouTube.decode_signature_func returned undefined."); - return ""; - } - throw new Error("Invalid return value type: expected string, got " + typeof (rc)); - }, // decode() - - dispose: function () { - if (!this.sandbox) { return; } - for (var p in this.sandbox) { - if (this.sandbox.hasOwnProperty(p)) { - delete this.sandbox[p]; - } - } - if (typeof Cu.nukeSandbox === "function") { - Cu.nukeSandbox(this.sandbox); - } - this.sandbox = null; - } -}; // SandboxedSignatureDecoder.prototype - - - -// Signature decoding algorithm (SDA) sniffer. -var SDASniffer = { - // We don't want "over 9000" workers doing the same thing when one - // is enough (can happen if we're restoring a session with several - // YouTube tabs/windows). - // static boolean working = false; - // static Array callbacks = []; - working: false, - callbacks: [], - - sniff: function (w, callback /*= null*/, force /*= false*/) { - if (typeof(callback) !== "function") { callback = null; } - - if (this.working) { - if (callback) { this.callbacks.push(callback); } - return true; - } - - // Get the SWF player URL. - w = w.wrappedJSObject; - var swf_url; - var o; - // ytplayer.config.url - if (w && (o = w.ytplayer) && (o = o.config)) { - swf_url = o.url; - } - // yt.config_["PLAYER_CONFIG"].url - else if (w && (o = w.yt) && (o = o.config_) && (o = o.PLAYER_CONFIG)) { - swf_url = o.url; - } - if (!swf_url) { return false; } - fg.log("SWF URL: " + swf_url); - - // Automatic update frequency is limited so that we waste less traffic - // and CPU cycles in case YoutubeSwf code is outdated. - if ( ! force) { - var now = Math.floor(Date.now() / 1000); - var min_int = fg.getPref("media.YouTube.decode_signature_func.auto.min_interval", 60); - var last_update = fg.getPref("media.YouTube.decode_signature_func.auto.last_update_time", 0); - if (min_int !== 0 && now - last_update < min_int) { - if ( ! fg.getPref("media.YouTube.decode_signature_func.auto.last_update_ok")) { - return false; - } - // We promised to be async, so we can't call back _before_ we return, - // hence setTimeout. - w.setTimeout(function(){ - try { - callback(); - } catch (x) { - fg.log("Callback error: " + (x.message || x) + "\n" + x.stack); - } - }, 1); - return true; - } - fg.setPref("media.YouTube.decode_signature_func.auto.last_update_time", now); - } - - var st, ft; - var stream_ctx = { - file: swf_url, //.split("/").pop().replace(/\?.*$/, "").replace(/#.*$/, ""), - bytes: "", - contentLength: -1, - bstream: null - }; - var stream_listener = { - onDataAvailable: function (req, ctx, stream, offset, count) { - stream_ctx.bstream.setInputStream(stream); - stream_ctx.bytes += stream_ctx.bstream.readBytes(count); - }, - onStartRequest: function (req /*, ctx*/) { - var channel = req.QueryInterface(Ci.nsIChannel); - if (!((channel instanceof Ci.nsIHttpChannel) - && components.isSuccessCode(channel.status) - && channel.responseStatus === 200)) - { - throw new Error("cancel"); //req.cancel(NS_BINDING_ABORTED); - } - stream_ctx.contentLength = channel.contentLength || -1; - fg.log("SWF content length: " + stream_ctx.contentLength); - stream_ctx.bstream = Cc["@mozilla.org/binaryinputstream;1"] - .createInstance(Ci.nsIBinaryInputStream); - st = Date.now(); - }, - onStopRequest: function (req, ctx, status) { - ft = Date.now(); - stream_ctx.bstream = null; - // SDASniffer::sniff0 is async, so we can't simply do if (SDASniffer.working) {clean up}. - var cleanup = true; - if (components.isSuccessCode(status)) { - fg.log("SWF downloaded in " + (ft - st) + " ms, size: " + stream_ctx.bytes.length); - if (stream_ctx.contentLength === -1 || stream_ctx.bytes.length === stream_ctx.contentLength) { - SDASniffer.sniff0(stream_ctx, callback); - cleanup = false; - } - else { - fg.log("SWF content length mismatch: expected " + stream_ctx.contentLength + ", got " + stream_ctx.bytes.length); - } - } - else { - fg.log("Failed to download the SWF: status=" + status); - } - stream_ctx = null; - if (cleanup) { - SDASniffer.working = false; - SDASniffer.callbacks = []; - } - } - }; // stream_listener - Cc["@mozilla.org/network/io-service;1"] - .getService(Ci.nsIIOService) - .newChannel(swf_url, null, null) - .asyncOpen(stream_listener, null); - - this.working = true; - if (callback) { this.callbacks.push(callback); } - fg.setPref("media.YouTube.decode_signature_func.auto.last_update_ok", false); - return true; - }, - - - sniff0: function (ctx, callback) { - // Using a worker instead of a direct call resolves the problem - // with GUI freezing due to severe performance degradation: 100 ms - // vs 2400 ms for zip_inflate(), 100 ms vs 800 ms for swf_parse(). - // See bug 911570 (https://bugzilla.mozilla.org/show_bug.cgi?id=911570), - // or 776798, or 907201, or whatever is causing it. - var worker = new SDAWorker( {bytes: ctx.bytes, file: ctx.file} ); - ctx.bytes = null; - - worker.onfinish = function(rc) { - SDASniffer.working = false; - var callbacks = SDASniffer.callbacks; - SDASniffer.callbacks = []; - - if (typeof(rc) === "string") { - fg.log("Error refreshing signature function: " + rc); - return; - } - - if ( ! rc) { return; } - fg.setPref("media.YouTube.decode_signature_func.auto.last_update_ok", true); - - if (rc.timestamp !== fg.getPref("media.YouTube.decode_signature_func.timestamp")) { - fg.log("New timestamp: " + rc.timestamp); - fg.setPref("media.YouTube.decode_signature_func.timestamp", rc.timestamp); - } - - if (rc.func_text !== fg.getPref("media.YouTube.decode_signature_func")) { - fg.log("New signature function:\n" + rc.func_text); - fg.setPref("media.YouTube.decode_signature_func", rc.func_text); - callbacks.forEach(function(f){ - try { - f(); - } catch (x) { - fg.log("Callback error: " + (x.message || x) + "\n" + x.stack); - } - }); - } - }; - - try { - worker.start(); - } catch (x) { - worker.onfinish("Error starting the worker: " + (x.message || x) + "\n" + x.stack); - } - } -}; // SDASniffer - - - -// class SDAWorker; -function SDAWorker(ctx) { - this.ctx = ctx; - this.worker = null; - this.fired_onfinish = false; -} - -SDAWorker.prototype = { - // public - start: function() { - var worker = this.worker = new Worker("YoutubeSwf.js"); - worker["SDAWorker::this"] = this; - worker.onmessage = this.worker_onmessage; - worker.onerror = this.worker_onerror; - worker.postMessage(this.ctx); - this.ctx = null; - }, - - // Completion event handler, implemented by the caller. - // void onfinish(Object data); - // @param data - the result of the decoding, one of: - // 1) a primitive string value (typeof data === "string") - there was - // an uncaught exception in the worker, and |data| is the error message. - // 2) Object - struct { string func_text; int timestamp; } - the result - // of the decoding. Can be null/undefined (data == null covers both) - // if the signature function could not be decoded. - onfinish: function(){}, - - - // private - fire_onfinish: function(data) { - this.fired_onfinish = true; - try { - this.onfinish(data); - } catch (x) { - fg.log("Error in onfinish: " + (x.message || x) + "\n" + x.stack); - } - }, - - worker_onmessage: function(evt) { - var This = this["SDAWorker::this"]; - // struct msg { string type; Object data; }; - var msg = evt.data; - if (msg == null) { - fg.log("SDAWorker: Invalid message: null or undefined: " + msg); - This.finish(); - return; - } - if (typeof(msg) !== "object") { - fg.log("SDAWorker: Invalid message: expected [object], got [" + typeof(msg) + "]: " + msg); - This.finish(); - return; - } - switch (msg.type) { - case "done": - This.finish(); - return; - case "log": - fg.log(msg.data); - return; - case "result": - This.fire_onfinish(msg.data); - return; - } - fg.log("SDAWorker: Invalid message type: '" + msg.type + "'"); - This.finish(); - }, - - worker_onerror: function(evt) { - var This = this["SDAWorker::this"]; - This.fire_onfinish("Uncaught exception in worker: " + evt.message); - This.finish(); - }, - - finish: function() { - if ( ! this.fired_onfinish) { - this.fire_onfinish(null); - } - try { - this.worker.terminate(); - this.worker["SDAWorker::this"] - = this.worker.onmessage - = this.worker.onerror - = null; - this.worker = null; - } catch (x) { - fg.log("Error terminating the worker: " + (x.message || x) + "\n" + x.stack); - } - } -}; // SDAWorker.prototype - - -Youtube.fix_signature = function(data, fmts, swf_url, cb) { - try { - this.create_sig_decoder(swf_url, (signature_decoder) => { - for (let itag in fmts) { - if (fmts[itag].url.search("signature=") > 0) - continue; - fg.log("fixing stream", itag); - try { - var sig = signature_decoder.decode({ - stream: fmts[itag], - video_info: data, - swap: this.decode_signature_swap - }); - if (sig) { - fg.log("Fmt", itag, "url fixed:", sig); - fmts[itag].url += "&signature=" + encodeURIComponent(sig); - if(!sig.match(/^[0-9A-Z]{40}\.[0-9A-Z]{40}$/)) - fg.setPref("media.YouTube.decode_signature_func", ""); - } else { - fg.log("Failed to fix fmt", itag, "signature"); - delete fmts[itag]; - } - } catch (x) { - fg.log("Error calling YouTube.decode_signature_func: " + (x.message || x) + "\n" + x.stack); - } - } - try { - signature_decoder.dispose(); - } catch (e) { /* TODO: fix it */ } - cb(fmts); - }); - } catch (x) { - fg.log("Error creating signature decoder: " + (x.message || x) + "\n" + x.stack); - cb({}); - } -}; -Youtube.create_sig_decoder = function (swf_url, cb) { - // Wrapper around create_sig_decoder with callback and - // refresh_signature_decoder and emulate w object - if (fg.getPref("media.YouTube.decode_signature_func", "")) { - cb(this.create_signature_decoder()); - } else { - var w = {wrappedJSObject: {ytplayer: {config: {url: swf_url}}}}; - var success = this.refresh_signature_func(w, () => { - cb(this.create_signature_decoder()); - }, true); - if (!success) - cb(this.create_signature_decoder()); - } -}; -SDAWorker.prototype.start = function() { - var worker = this.worker = new ChromeWorker(require("sdk/self").data.url("flashgot-YouTubeSwf.js")); - worker["SDAWorker::this"] = this; - worker.onmessage = this.worker_onmessage; - worker.onerror = this.worker_onerror; - worker.postMessage(this.ctx); - this.ctx = null; -}; - -exports.flashgot = Youtube; diff --git a/data/extensions/html5-video-everywhere@lejenome.me/lib/metacafe.js b/data/extensions/html5-video-everywhere@lejenome.me/lib/metacafe.js deleted file mode 100644 index 4529ab7..0000000 --- a/data/extensions/html5-video-everywhere@lejenome.me/lib/metacafe.js +++ /dev/null @@ -1,11 +0,0 @@ -"use strict"; -var match = [/https?:\/\/www.metacafe.com\/watch\/.*/, - /https?:\/\/www.metacafe.com\/[^\/]+\/?/ -]; -var inject = [ - "metacafe.js" -]; -var when = "start"; -exports.when = when; -exports.match = match; -exports.inject = inject; \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/lib/vimeo.js b/data/extensions/html5-video-everywhere@lejenome.me/lib/vimeo.js deleted file mode 100644 index 59acc9e..0000000 --- a/data/extensions/html5-video-everywhere@lejenome.me/lib/vimeo.js +++ /dev/null @@ -1,11 +0,0 @@ -"use strict"; -var when = "start"; -var match = [/https?:\/\/vimeo.com\/.+/, - /https?:\/\/player.vimeo.com\/video.*/ -]; -var inject = [ - "vimeo.js" -]; -exports.when = when; -exports.match = match; -exports.inject = inject; \ No newline at end of file diff --git a/data/extensions/html5-video-everywhere@lejenome.me/lib/youtube.js b/data/extensions/html5-video-everywhere@lejenome.me/lib/youtube.js deleted file mode 100644 index e655ab2..0000000 --- a/data/extensions/html5-video-everywhere@lejenome.me/lib/youtube.js +++ /dev/null @@ -1,30 +0,0 @@ -"use strict"; -const flashgot = require("./flashgot-YouTube").flashgot; -var YOUTUBE_FLASH_REGEX = /https?:\/\/(www.)?youtube.com\/v\/([^#?\/]*)/; -var YT_BIN_REGEX = /https:\/\/s.ytimg.com\/yts\/jsbin\/[^\/]*\/base.js/; -var YT_PLAYER_REGEX = /https?:\/\/s.ytimg.com\/yts\/jsbin\/[^\/]*\/html5player.js/; -var when = "start"; -var match = ["*.www.youtube.com", "*.www.youtube-nocookie.com"]; -var inject = [ - "youtube-formats.js", - "youtube.js" -]; -var redirect = [{ - src: /https?:\/\/(www.)?youtube.com\/v\/([^#?\/]*)/, - funct: (_1, _2, v) => "https://www.youtube.com/embed/" + v -}]; -var block = [/https?:\/\/s.ytimg.com\/yts\/jsbin\/[^\/]*\/html5player.js/]; -var listen = { - "fix_signature": function(obj, worker) { - flashgot.fix_signature(obj.data, obj.fmts, obj.swf_url, (fmts) => - worker.port.emit("fixed_signature", fmts) - ); - } -}; -exports.when = when; -exports.match = match; -exports.inject = inject; -exports.redirect = redirect; -exports.block = block; -exports.listen = listen; -//exports.style = []; \ No newline at end of file -- cgit v1.2.3