mirror of https://github.com/calzoneman/sync.git
Work on custom embeds
This commit is contained in:
parent
60743bd2ea
commit
01fbd3c54e
|
@ -1,22 +1,96 @@
|
||||||
const allowed = ["iframe", "object", "param", "embed"];
|
var cheerio = require("cheerio");
|
||||||
const tag_re = /<\s*\/?\s*([a-z]+)(\s*([a-z]+)\s*=\s*('[^']*'|"[^"]*"|[^"'>]*))*\s*>/ig;
|
var crypto = require("crypto");
|
||||||
|
var Media = require("./media");
|
||||||
|
|
||||||
function filter(str) {
|
function sha256(input) {
|
||||||
if (typeof str !== "string") {
|
var hash = crypto.createHash("sha256");
|
||||||
return "";
|
hash.update(input);
|
||||||
|
return hash.digest("base64");
|
||||||
|
}
|
||||||
|
|
||||||
|
function filter(input) {
|
||||||
|
var $ = cheerio.load(input, { xmlMode: true });
|
||||||
|
var meta = getMeta($);
|
||||||
|
var id = "cu:" + sha256(input);
|
||||||
|
|
||||||
|
return new Media(id, "Custom Media", "--:--", "cu", meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMeta($) {
|
||||||
|
var tag = $("embed");
|
||||||
|
if (tag.length !== 0) {
|
||||||
|
return filterEmbed(tag[0]);
|
||||||
|
}
|
||||||
|
tag = $("object");
|
||||||
|
if (tag.length !== 0) {
|
||||||
|
return filterObject(tag[0]);
|
||||||
|
}
|
||||||
|
tag = $("iframe");
|
||||||
|
if (tag.length !== 0) {
|
||||||
|
return filterIframe(tag[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
str = str.replace(tag_re, function (match, tag) {
|
throw new Error("Invalid embed. Input must be an <iframe>, <object>, or " +
|
||||||
if(!~allowed.indexOf(tag.toLowerCase())) {
|
"<embed> tag.");
|
||||||
return match.replace("<", "<").replace(">", ">");
|
}
|
||||||
|
|
||||||
|
const ALLOWED_PARAMS = /^(flashvars|bgcolor|movie)$/i;
|
||||||
|
function filterEmbed(tag) {
|
||||||
|
if (tag.attribs.type !== "application/x-shockwave-flash") {
|
||||||
|
throw new Error("Invalid embed. Only type 'application/x-shockwave-flash' " +
|
||||||
|
"is allowed for <embed> tags.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var meta = {
|
||||||
|
embed: {
|
||||||
|
tag: "object",
|
||||||
|
src: tag.attribs.src,
|
||||||
|
params: {}
|
||||||
}
|
}
|
||||||
return match;
|
}
|
||||||
});
|
|
||||||
str = str.replace(/(\bon\w*\s*=\s*('[^']*'|"[^"]"|[^\s><]*))/ig, function () {
|
for (var key in tag.attribs) {
|
||||||
return "";
|
if (ALLOWED_PARAMS.test(key)) {
|
||||||
|
meta.embed.params[key] = tag.attribs[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterObject(tag) {
|
||||||
|
if (tag.attribs.type !== "application/x-shockwave-flash") {
|
||||||
|
throw new Error("Invalid embed. Only type 'application/x-shockwave-flash' " +
|
||||||
|
"is allowed for <embed> tags.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var meta = {
|
||||||
|
embed: {
|
||||||
|
tag: "object",
|
||||||
|
src: tag.attribs.data,
|
||||||
|
params: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
tag.children.forEach(function (child) {
|
||||||
|
if (child.name !== "param") return;
|
||||||
|
if (!ALLOWED_PARAMS.test(child.attribs.name)) return;
|
||||||
|
|
||||||
|
meta.embed.params[child.attribs.name] = child.attribs.value;
|
||||||
});
|
});
|
||||||
|
|
||||||
return str.substring(0, 20000);
|
return meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterIframe(tag) {
|
||||||
|
var meta = {
|
||||||
|
embed: {
|
||||||
|
tag: "iframe",
|
||||||
|
src: tag.attribs.src
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.filter = filter;
|
exports.filter = filter;
|
||||||
|
|
|
@ -510,8 +510,17 @@ var Getters = {
|
||||||
|
|
||||||
/* custom embed */
|
/* custom embed */
|
||||||
cu: function (id, callback) {
|
cu: function (id, callback) {
|
||||||
id = CustomEmbedFilter(id);
|
var media;
|
||||||
var media = new Media(id, "Custom Media", "--:--", "cu");
|
try {
|
||||||
|
media = CustomEmbedFilter(id);
|
||||||
|
} catch (e) {
|
||||||
|
if (/invalid embed/i.test(e.message)) {
|
||||||
|
return callback(e.message);
|
||||||
|
} else {
|
||||||
|
Logger.errlog.log(e.stack);
|
||||||
|
return callback("Unknown error processing embed");
|
||||||
|
}
|
||||||
|
}
|
||||||
callback(false, media);
|
callback(false, media);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,8 @@ Media.prototype = {
|
||||||
restricted: this.meta.restricted,
|
restricted: this.meta.restricted,
|
||||||
codec: this.meta.codec,
|
codec: this.meta.codec,
|
||||||
bitrate: this.meta.bitrate,
|
bitrate: this.meta.bitrate,
|
||||||
scuri: this.meta.scuri
|
scuri: this.meta.scuri,
|
||||||
|
embed: this.meta.embed
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
genParam = (name, value) ->
|
||||||
|
$('<param/>').attr(
|
||||||
|
name: name
|
||||||
|
value: value
|
||||||
|
)
|
||||||
|
|
||||||
|
window.CustomEmbedPlayer = class CustomEmbedPlayer extends Player
|
||||||
|
constructor: (data) ->
|
||||||
|
if not (this instanceof CustomEmbedPlayer)
|
||||||
|
return new CustomEmbedPlayer(data)
|
||||||
|
|
||||||
|
@load(data)
|
||||||
|
|
||||||
|
load: (data) ->
|
||||||
|
embed = data.meta.embed
|
||||||
|
if not embed?
|
||||||
|
console.error('CustomEmbedPlayer::load(): missing meta.embed')
|
||||||
|
return
|
||||||
|
|
||||||
|
if embed.tag == 'object'
|
||||||
|
@player = @loadObject(embed)
|
||||||
|
else
|
||||||
|
@player = @loadIframe(embed)
|
||||||
|
|
||||||
|
removeOld(@player)
|
||||||
|
|
||||||
|
loadObject: (embed) ->
|
||||||
|
object = $('<object/>').attr(
|
||||||
|
type: 'application/x-shockwave-flash'
|
||||||
|
data: embed.src
|
||||||
|
)
|
||||||
|
genParam('allowfullscreen', 'true').appendTo(object)
|
||||||
|
genParam('allowscriptaccess', 'always').appendTo(object)
|
||||||
|
|
||||||
|
for key, value of embed.params
|
||||||
|
genParam(key, value).appendTo(object)
|
||||||
|
|
||||||
|
return object
|
||||||
|
|
||||||
|
loadIframe: (embed) ->
|
||||||
|
iframe = $('<iframe/>').attr(
|
||||||
|
src: embed.src
|
||||||
|
frameborder: '0'
|
||||||
|
)
|
||||||
|
|
||||||
|
return iframe
|
|
@ -0,0 +1,28 @@
|
||||||
|
DEFAULT_WARNING = 'You are currently connected via HTTPS but the embedded video
|
||||||
|
link uses non-secure plain HTTP. Your browser may therefore block it from
|
||||||
|
loading due to mixed content policy. To fix this, embed the video using a
|
||||||
|
secure link if available (https://...), or load this page over plain HTTP by
|
||||||
|
replacing "https://" with "http://" in the address bar (your websocket will
|
||||||
|
still be secured using HTTPS, but this will permit non-secure content to load).'
|
||||||
|
|
||||||
|
window.GenericIframePlayer = class GenericIframePlayer extends Player
|
||||||
|
constructor: (data, iframeSrc, customMixedContentWarning) ->
|
||||||
|
if not (this instanceof GenericIframePlayer)
|
||||||
|
return new GenericIframePlayer(data, iframeSrc, customMixedContentWarning)
|
||||||
|
|
||||||
|
load: (data, iframeSrc, customMixedContentWarning) ->
|
||||||
|
@setMediaProperties(data)
|
||||||
|
|
||||||
|
@player = $('<iframe/>').attr(
|
||||||
|
src: iframeSrc
|
||||||
|
frameborder: '0'
|
||||||
|
)
|
||||||
|
removeOld(@player)
|
||||||
|
|
||||||
|
if iframeSrc.indexOf('http:') == 0
|
||||||
|
if customMixedContentWarning
|
||||||
|
warning = customMixedContentWarning
|
||||||
|
else
|
||||||
|
warning = DEFAULT_WARNING
|
||||||
|
|
||||||
|
makeAlert('Mixed Content Warning', warning).appendTo($('#videowrap'))
|
|
@ -7,6 +7,7 @@ TYPE_MAP =
|
||||||
sc: SoundCloudPlayer
|
sc: SoundCloudPlayer
|
||||||
li: LivestreamPlayer
|
li: LivestreamPlayer
|
||||||
tw: TwitchPlayer
|
tw: TwitchPlayer
|
||||||
|
cu: CustomEmbedPlayer
|
||||||
|
|
||||||
window.loadMediaPlayer = (data) ->
|
window.loadMediaPlayer = (data) ->
|
||||||
if data.type of TYPE_MAP
|
if data.type of TYPE_MAP
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
(function() {
|
(function() {
|
||||||
var DailymotionPlayer, LivestreamPlayer, Player, SoundCloudPlayer, TYPE_MAP, TwitchPlayer, VideoJSPlayer, VimeoPlayer, YouTubePlayer, sortSources,
|
var CustomEmbedPlayer, DailymotionPlayer, LivestreamPlayer, Player, SoundCloudPlayer, TYPE_MAP, TwitchPlayer, VideoJSPlayer, VimeoPlayer, YouTubePlayer, genParam, sortSources,
|
||||||
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||||
hasProp = {}.hasOwnProperty;
|
hasProp = {}.hasOwnProperty;
|
||||||
|
|
||||||
|
@ -786,6 +786,67 @@
|
||||||
|
|
||||||
})(Player);
|
})(Player);
|
||||||
|
|
||||||
|
genParam = function(name, value) {
|
||||||
|
return $('<param/>').attr({
|
||||||
|
name: name,
|
||||||
|
value: value
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
window.CustomEmbedPlayer = CustomEmbedPlayer = (function(superClass) {
|
||||||
|
extend(CustomEmbedPlayer, superClass);
|
||||||
|
|
||||||
|
function CustomEmbedPlayer(data) {
|
||||||
|
if (!(this instanceof CustomEmbedPlayer)) {
|
||||||
|
return new CustomEmbedPlayer(data);
|
||||||
|
}
|
||||||
|
this.load(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomEmbedPlayer.prototype.load = function(data) {
|
||||||
|
var embed;
|
||||||
|
embed = data.meta.embed;
|
||||||
|
if (embed == null) {
|
||||||
|
console.error('CustomEmbedPlayer::load(): missing meta.embed');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (embed.tag === 'object') {
|
||||||
|
this.player = this.loadObject(embed);
|
||||||
|
} else {
|
||||||
|
this.player = this.loadIframe(embed);
|
||||||
|
}
|
||||||
|
return removeOld(this.player);
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomEmbedPlayer.prototype.loadObject = function(embed) {
|
||||||
|
var key, object, ref, value;
|
||||||
|
object = $('<object/>').attr({
|
||||||
|
type: 'application/x-shockwave-flash',
|
||||||
|
data: embed.src
|
||||||
|
});
|
||||||
|
genParam('allowfullscreen', 'true').appendTo(object);
|
||||||
|
genParam('allowscriptaccess', 'always').appendTo(object);
|
||||||
|
ref = embed.params;
|
||||||
|
for (key in ref) {
|
||||||
|
value = ref[key];
|
||||||
|
genParam(key, value).appendTo(object);
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomEmbedPlayer.prototype.loadIframe = function(embed) {
|
||||||
|
var iframe;
|
||||||
|
iframe = $('<iframe/>').attr({
|
||||||
|
src: embed.src,
|
||||||
|
frameborder: '0'
|
||||||
|
});
|
||||||
|
return iframe;
|
||||||
|
};
|
||||||
|
|
||||||
|
return CustomEmbedPlayer;
|
||||||
|
|
||||||
|
})(Player);
|
||||||
|
|
||||||
TYPE_MAP = {
|
TYPE_MAP = {
|
||||||
yt: YouTubePlayer,
|
yt: YouTubePlayer,
|
||||||
vi: VimeoPlayer,
|
vi: VimeoPlayer,
|
||||||
|
@ -794,7 +855,8 @@
|
||||||
gp: VideoJSPlayer,
|
gp: VideoJSPlayer,
|
||||||
sc: SoundCloudPlayer,
|
sc: SoundCloudPlayer,
|
||||||
li: LivestreamPlayer,
|
li: LivestreamPlayer,
|
||||||
tw: TwitchPlayer
|
tw: TwitchPlayer,
|
||||||
|
cu: CustomEmbedPlayer
|
||||||
};
|
};
|
||||||
|
|
||||||
window.loadMediaPlayer = function(data) {
|
window.loadMediaPlayer = function(data) {
|
||||||
|
|
Loading…
Reference in New Issue