From 450707fec626e4e2b2eed4e46591fcf06368d0a1 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 16 Nov 2010 12:41:35 -0800 Subject: Stub LinkPreview plugin --- plugins/LinkPreview/LinkPreviewPlugin.php | 94 +++++++++++++++++++++++++++++++ plugins/LinkPreview/linkpreview.js | 10 ++++ 2 files changed, 104 insertions(+) create mode 100644 plugins/LinkPreview/LinkPreviewPlugin.php create mode 100644 plugins/LinkPreview/linkpreview.js (limited to 'plugins') diff --git a/plugins/LinkPreview/LinkPreviewPlugin.php b/plugins/LinkPreview/LinkPreviewPlugin.php new file mode 100644 index 000000000..d887ca040 --- /dev/null +++ b/plugins/LinkPreview/LinkPreviewPlugin.php @@ -0,0 +1,94 @@ +. + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +/** + * Some UI extras for now... + * + * @package LinkPreviewPlugin + * @maintainer Brion Vibber + */ +class LinkPreviewPlugin extends Plugin +{ + function onPluginVersion(&$versions) + { + $versions[] = array('name' => 'LinkPreview', + 'version' => STATUSNET_VERSION, + 'author' => 'Brion Vibber', + 'homepage' => 'http://status.net/wiki/Plugin:LinkPreview', + 'rawdescription' => + _m('UI extensions previewing thumbnails from links.')); + + return true; + } + + /** + * Load JS at runtime if we're logged in. + * + * @param Action $action + * @return boolean hook result + */ + function onEndShowScripts($action) + { + $user = common_current_user(); + if ($user) { + $action->script('plugins/LinkPreview/linkpreview.js'); + } + return true; + } + + /** + * Autoloader + * + * Loads our classes if they're requested. + * + * @param string $cls Class requested + * + * @return boolean hook return + */ + function onAutoload($cls) + { + switch ($cls) + { + case 'LinkpreviewAction': + require_once dirname(__FILE__) . '/linkpreviewaction.php'; + return false; + default: + return true; + } + } + + /** + * Hook for RouterInitialized event. + * + * @param Net_URL_Mapper $m URL mapper + * + * @return boolean hook return + */ + function onStartInitializeRouter($m) + { + $m->connect('main/preview/link', + array('action' => 'linkpreview')); + + return true; + } +} diff --git a/plugins/LinkPreview/linkpreview.js b/plugins/LinkPreview/linkpreview.js new file mode 100644 index 000000000..37710e7d5 --- /dev/null +++ b/plugins/LinkPreview/linkpreview.js @@ -0,0 +1,10 @@ +/** + * (c) 2010 StatusNet, Inc. + */ + +$(function() { + $('#notice_data-text').change(function() { + var text = $(this).val(); + alert(text); + }); +}); -- cgit v1.2.3-54-g00ecf From e851882f964c9eaa1cdd73f028fd09dd9acba734 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 16 Nov 2010 13:16:25 -0800 Subject: LinkPreview: flesh out stub JS code a bit. URL splitting doesn't quite match core, note. --- plugins/LinkPreview/linkpreview.js | 47 +++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/LinkPreview/linkpreview.js b/plugins/LinkPreview/linkpreview.js index 37710e7d5..f6a4dc34f 100644 --- a/plugins/LinkPreview/linkpreview.js +++ b/plugins/LinkPreview/linkpreview.js @@ -3,8 +3,53 @@ */ $(function() { + /** + * Find URL links from the source text that may be interesting. + * + * @param {String} text + * @return {Array} list of URLs + */ + function findLinks(text) + { + // @fixme match this to core code + var re = /(?:^| )(https?:\/\/.+?\/.+?)(?= |$)/g; + var links = []; + var matches; + while ((matches = re.exec(text)) !== null) { + links.push(matches[1]); + } + return links; + } + + /** + * Start looking up info for a link preview... + * May start async data loads. + * + * @param {String} id + * @param {String} url + */ + function prepLinkPreview(id, url) + { + console.log(id, url); + } + + /** + * Update the live preview section with links found in the given text. + * May start async data loads. + * + * @param {String} text: free-form input text + */ + function previewLinks(text) + { + var links = findLinks(text); + for (var i = 0; i < links.length; i++) { + var id = 'link-preview-' + i; + prepLinkPreview(id, links[i]); + } + } + $('#notice_data-text').change(function() { var text = $(this).val(); - alert(text); + previewLinks(text); }); }); -- cgit v1.2.3-54-g00ecf From 5166e71d24d1121f7d99bc788fe734d5c6e86e79 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 16 Nov 2010 13:49:23 -0800 Subject: LinkPreview plugin more or less functioning (though not pretty), using oohembed remote lookup and fixed sizes. --- plugins/LinkPreview/linkpreview.js | 57 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/LinkPreview/linkpreview.js b/plugins/LinkPreview/linkpreview.js index f6a4dc34f..eae6dfd43 100644 --- a/plugins/LinkPreview/linkpreview.js +++ b/plugins/LinkPreview/linkpreview.js @@ -12,7 +12,7 @@ $(function() { function findLinks(text) { // @fixme match this to core code - var re = /(?:^| )(https?:\/\/.+?\/.+?)(?= |$)/g; + var re = /(?:^| )(https?:\/\/.+?\/.+?)(?= |$)/mg; var links = []; var matches; while ((matches = re.exec(text)) !== null) { @@ -21,6 +21,30 @@ $(function() { return links; } + /** + * Do an oEmbed lookup for the given URL. + * + * @fixme proxy through ourselves if possible? + * @fixme use the global thumbnail size settings + * + * @param {String} url + * @param {function} callback + */ + function oEmbedLookup(url, callback) + { + var api = 'http://oohembed.com/oohembed'; + var params = { + url: url, + format: 'json', + maxwidth: 100, + maxheight: 75, + callback: '?' + }; + $.get(api, params, function(data, xhr) { + callback(data); + }, 'jsonp'); + } + /** * Start looking up info for a link preview... * May start async data loads. @@ -30,7 +54,32 @@ $(function() { */ function prepLinkPreview(id, url) { - console.log(id, url); + oEmbedLookup(url, function(data) { + var thumb = null; + var width = 100; + if (typeof data.thumbnail_url == "string") { + thumb = data.thumbnail_url; + if (typeof data.thumbnail_width !== "undefined") { + if (data.thumbnail_width < width) { + width = data.thumbnail_width; + } + } + } else if (data.type == 'photo' && typeof data.url == "string") { + thumb = data.url; + if (typeof data.width !== "undefined") { + if (data.width < width) { + width = data.width; + } + } + } + if (thumb) { + var img = $('') + .attr('src', thumb) + .attr('width', width) + .attr('title', data.title || data.url || url); + $('#' + id).append(img); + } + }); } /** @@ -42,12 +91,14 @@ $(function() { function previewLinks(text) { var links = findLinks(text); + $('#link-preview').html(''); for (var i = 0; i < links.length; i++) { var id = 'link-preview-' + i; + $('#link-preview').append(''); prepLinkPreview(id, links[i]); } } - + $('#form_notice').append(''); $('#notice_data-text').change(function() { var text = $(this).val(); previewLinks(text); -- cgit v1.2.3-54-g00ecf From f103a550521bffd9662dff473119389b10696582 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 16 Nov 2010 13:58:22 -0800 Subject: LinkPreview: link the thumbnails --- plugins/LinkPreview/linkpreview.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'plugins') diff --git a/plugins/LinkPreview/linkpreview.js b/plugins/LinkPreview/linkpreview.js index eae6dfd43..9f0ed6562 100644 --- a/plugins/LinkPreview/linkpreview.js +++ b/plugins/LinkPreview/linkpreview.js @@ -73,11 +73,14 @@ $(function() { } } if (thumb) { - var img = $('') - .attr('src', thumb) - .attr('width', width) - .attr('title', data.title || data.url || url); - $('#' + id).append(img); + var link = $(''); + link.attr('href', url) + .attr('target', '_blank') + .find('img') + .attr('src', thumb) + .attr('width', width) + .attr('title', data.title || data.url || url); + $('#' + id).append(link); } }); } -- cgit v1.2.3-54-g00ecf From eeb7f02b98f104e1536cc116f4a8607dfde0d00b Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 16 Nov 2010 14:16:23 -0800 Subject: LinkPreview: piggyback on the counter update logic, cache lookups. --- plugins/LinkPreview/linkpreview.js | 103 +++++++++++++++++++++++++------------ 1 file changed, 71 insertions(+), 32 deletions(-) (limited to 'plugins') diff --git a/plugins/LinkPreview/linkpreview.js b/plugins/LinkPreview/linkpreview.js index 9f0ed6562..6af3e920d 100644 --- a/plugins/LinkPreview/linkpreview.js +++ b/plugins/LinkPreview/linkpreview.js @@ -21,29 +21,63 @@ $(function() { return links; } - /** - * Do an oEmbed lookup for the given URL. - * - * @fixme proxy through ourselves if possible? - * @fixme use the global thumbnail size settings - * - * @param {String} url - * @param {function} callback - */ - function oEmbedLookup(url, callback) - { - var api = 'http://oohembed.com/oohembed'; - var params = { - url: url, - format: 'json', - maxwidth: 100, - maxheight: 75, - callback: '?' - }; - $.get(api, params, function(data, xhr) { - callback(data); - }, 'jsonp'); - } + var oEmbed = { + api: 'http://oohembed.com/oohembed', + cache: {}, + callbacks: {}, + + /** + * Do a cached oEmbed lookup for the given URL. + * + * @param {String} url + * @param {function} callback + */ + lookup: function(url, callback) + { + if (typeof oEmbed.cache[url] == "object") { + // We already have a successful lookup. + callback(oEmbed.cache[url]); + } else if (typeof oEmbed.callbacks[url] == "undefined") { + // No lookup yet... Start it! + oEmbed.callbacks[url] = [callback]; + + oEmbed.rawLookup(url, function(data) { + oEmbed.cache[url] = data; + var callbacks = oEmbed.callbacks[url]; + oEmbed.callbacks[url] = undefined; + for (var i = 0; i < callbacks.length; i++) { + callbacks[i](data); + } + }); + } else { + // A lookup is in progress. + oEmbed.callbacks[url].push(callback); + } + }, + + /** + * Do an oEmbed lookup for the given URL. + * + * @fixme proxy through ourselves if possible? + * @fixme use the global thumbnail size settings + * + * @param {String} url + * @param {function} callback + */ + rawLookup: function(url, callback) + { + var params = { + url: url, + format: 'json', + maxwidth: 100, + maxheight: 75, + callback: '?' + }; + $.get(oEmbed.api, params, function(data, xhr) { + callback(data); + }, 'jsonp'); + } + }; /** * Start looking up info for a link preview... @@ -54,7 +88,7 @@ $(function() { */ function prepLinkPreview(id, url) { - oEmbedLookup(url, function(data) { + oEmbed.lookup(url, function(data) { var thumb = null; var width = 100; if (typeof data.thumbnail_url == "string") { @@ -73,9 +107,11 @@ $(function() { } } if (thumb) { - var link = $(''); - link.attr('href', url) - .attr('target', '_blank') + var link = $(''); + link.find('a') + .attr('href', url) + .attr('target', '_blank') + .last() .find('img') .attr('src', thumb) .attr('width', width) @@ -101,9 +137,12 @@ $(function() { prepLinkPreview(id, links[i]); } } - $('#form_notice').append(''); - $('#notice_data-text').change(function() { - var text = $(this).val(); - previewLinks(text); - }); + $('#form_notice').append(''); + + // Piggyback on the counter update... + var origCounter = SN.U.Counter; + SN.U.Counter = function(form) { + previewLinks($('#notice_data-text').val()); + return origCounter(form); + } }); -- cgit v1.2.3-54-g00ecf From b5fc71253c5ad1d28bcff37733d11467eb15ca91 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 16 Nov 2010 14:27:01 -0800 Subject: LinkPreview: restructure a bit so we can pass config over --- plugins/LinkPreview/LinkPreviewPlugin.php | 6 +++ plugins/LinkPreview/linkpreview.js | 65 ++++++++++++++++++------------- 2 files changed, 43 insertions(+), 28 deletions(-) (limited to 'plugins') diff --git a/plugins/LinkPreview/LinkPreviewPlugin.php b/plugins/LinkPreview/LinkPreviewPlugin.php index d887ca040..6f7c99a38 100644 --- a/plugins/LinkPreview/LinkPreviewPlugin.php +++ b/plugins/LinkPreview/LinkPreviewPlugin.php @@ -52,6 +52,12 @@ class LinkPreviewPlugin extends Plugin $user = common_current_user(); if ($user) { $action->script('plugins/LinkPreview/linkpreview.js'); + $data = json_encode(array( + 'api' => common_config('oohembed', 'endpoint'), + 'width' => common_config('attachments', 'thumbwidth'), + 'height' => common_config('attachments', 'thumbheight'), + )); + $action->inlineScript('$(function() {SN.Init.LinkPreview && SN.Init.LinkPreview('.$data.');})'); } return true; } diff --git a/plugins/LinkPreview/linkpreview.js b/plugins/LinkPreview/linkpreview.js index 6af3e920d..db9921229 100644 --- a/plugins/LinkPreview/linkpreview.js +++ b/plugins/LinkPreview/linkpreview.js @@ -2,27 +2,11 @@ * (c) 2010 StatusNet, Inc. */ -$(function() { - /** - * Find URL links from the source text that may be interesting. - * - * @param {String} text - * @return {Array} list of URLs - */ - function findLinks(text) - { - // @fixme match this to core code - var re = /(?:^| )(https?:\/\/.+?\/.+?)(?= |$)/mg; - var links = []; - var matches; - while ((matches = re.exec(text)) !== null) { - links.push(matches[1]); - } - return links; - } - +(function() { var oEmbed = { api: 'http://oohembed.com/oohembed', + width: 100, + height: 75, cache: {}, callbacks: {}, @@ -69,8 +53,8 @@ $(function() { var params = { url: url, format: 'json', - maxwidth: 100, - maxheight: 75, + maxwidth: oEmbed.width, + maxheight: oEmbed.height, callback: '?' }; $.get(oEmbed.api, params, function(data, xhr) { @@ -79,6 +63,24 @@ $(function() { } }; + /** + * Find URL links from the source text that may be interesting. + * + * @param {String} text + * @return {Array} list of URLs + */ + function findLinks(text) + { + // @fixme match this to core code + var re = /(?:^| )(https?:\/\/.+?\/.+?)(?= |$)/mg; + var links = []; + var matches; + while ((matches = re.exec(text)) !== null) { + links.push(matches[1]); + } + return links; + } + /** * Start looking up info for a link preview... * May start async data loads. @@ -137,12 +139,19 @@ $(function() { prepLinkPreview(id, links[i]); } } - $('#form_notice').append(''); - // Piggyback on the counter update... - var origCounter = SN.U.Counter; - SN.U.Counter = function(form) { - previewLinks($('#notice_data-text').val()); - return origCounter(form); + SN.Init.LinkPreview = function(params) { + if (params.api) oEmbed.api = params.api; + if (params.width) oEmbed.width = params.width; + if (params.height) oEmbed.height = params.height; + + $('#form_notice').append(''); + + // Piggyback on the counter update... + var origCounter = SN.U.Counter; + SN.U.Counter = function(form) { + previewLinks($('#notice_data-text').val()); + return origCounter(form); + } } -}); +})(); -- cgit v1.2.3-54-g00ecf From 73f28ffabe3f023f4a8c6f4242c2929c907b6c71 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 16 Nov 2010 14:41:30 -0800 Subject: LinkPreview: use a local proxy for oEmbed lookups so we use a consistent common code path, and don't open up to oohembed.com being evil --- plugins/LinkPreview/LinkPreviewPlugin.php | 13 +++++++------ plugins/LinkPreview/linkpreview.js | 5 ++--- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'plugins') diff --git a/plugins/LinkPreview/LinkPreviewPlugin.php b/plugins/LinkPreview/LinkPreviewPlugin.php index 6f7c99a38..da7981148 100644 --- a/plugins/LinkPreview/LinkPreviewPlugin.php +++ b/plugins/LinkPreview/LinkPreviewPlugin.php @@ -53,7 +53,7 @@ class LinkPreviewPlugin extends Plugin if ($user) { $action->script('plugins/LinkPreview/linkpreview.js'); $data = json_encode(array( - 'api' => common_config('oohembed', 'endpoint'), + 'api' => common_local_url('oembedproxy'), 'width' => common_config('attachments', 'thumbwidth'), 'height' => common_config('attachments', 'thumbheight'), )); @@ -73,10 +73,11 @@ class LinkPreviewPlugin extends Plugin */ function onAutoload($cls) { - switch ($cls) + $lower = strtolower($cls); + switch ($lower) { - case 'LinkpreviewAction': - require_once dirname(__FILE__) . '/linkpreviewaction.php'; + case 'oembedproxyaction': + require_once dirname(__FILE__) . '/' . $lower . '.php'; return false; default: return true; @@ -92,8 +93,8 @@ class LinkPreviewPlugin extends Plugin */ function onStartInitializeRouter($m) { - $m->connect('main/preview/link', - array('action' => 'linkpreview')); + $m->connect('main/oembed/proxy', + array('action' => 'oembedproxy')); return true; } diff --git a/plugins/LinkPreview/linkpreview.js b/plugins/LinkPreview/linkpreview.js index db9921229..8e411f908 100644 --- a/plugins/LinkPreview/linkpreview.js +++ b/plugins/LinkPreview/linkpreview.js @@ -54,12 +54,11 @@ url: url, format: 'json', maxwidth: oEmbed.width, - maxheight: oEmbed.height, - callback: '?' + maxheight: oEmbed.height }; $.get(oEmbed.api, params, function(data, xhr) { callback(data); - }, 'jsonp'); + }, 'json'); } }; -- cgit v1.2.3-54-g00ecf From acdb9ac1e5b63f24262449356f526ff8168db8d3 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 16 Nov 2010 14:57:35 -0800 Subject: LinkPreview: restructure to make it easier to keep old link data --- plugins/LinkPreview/linkpreview.js | 146 +++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 71 deletions(-) (limited to 'plugins') diff --git a/plugins/LinkPreview/linkpreview.js b/plugins/LinkPreview/linkpreview.js index 8e411f908..37b0241a5 100644 --- a/plugins/LinkPreview/linkpreview.js +++ b/plugins/LinkPreview/linkpreview.js @@ -62,82 +62,86 @@ } }; - /** - * Find URL links from the source text that may be interesting. - * - * @param {String} text - * @return {Array} list of URLs - */ - function findLinks(text) - { - // @fixme match this to core code - var re = /(?:^| )(https?:\/\/.+?\/.+?)(?= |$)/mg; - var links = []; - var matches; - while ((matches = re.exec(text)) !== null) { - links.push(matches[1]); - } - return links; - } + var LinkPreview = { + links: [], + + /** + * Find URL links from the source text that may be interesting. + * + * @param {String} text + * @return {Array} list of URLs + */ + findLinks: function (text) + { + // @fixme match this to core code + var re = /(?:^| )(https?:\/\/.+?\/.+?)(?= |$)/mg; + var links = []; + var matches; + while ((matches = re.exec(text)) !== null) { + links.push(matches[1]); + } + return links; + }, - /** - * Start looking up info for a link preview... - * May start async data loads. - * - * @param {String} id - * @param {String} url - */ - function prepLinkPreview(id, url) - { - oEmbed.lookup(url, function(data) { - var thumb = null; - var width = 100; - if (typeof data.thumbnail_url == "string") { - thumb = data.thumbnail_url; - if (typeof data.thumbnail_width !== "undefined") { - if (data.thumbnail_width < width) { - width = data.thumbnail_width; + /** + * Start looking up info for a link preview... + * May start async data loads. + * + * @param {String} id + * @param {String} url + */ + prepLinkPreview: function(id, url) + { + oEmbed.lookup(url, function(data) { + var thumb = null; + var width = 100; + if (typeof data.thumbnail_url == "string") { + thumb = data.thumbnail_url; + if (typeof data.thumbnail_width !== "undefined") { + if (data.thumbnail_width < width) { + width = data.thumbnail_width; + } } - } - } else if (data.type == 'photo' && typeof data.url == "string") { - thumb = data.url; - if (typeof data.width !== "undefined") { - if (data.width < width) { - width = data.width; + } else if (data.type == 'photo' && typeof data.url == "string") { + thumb = data.url; + if (typeof data.width !== "undefined") { + if (data.width < width) { + width = data.width; + } } } - } - if (thumb) { - var link = $(''); - link.find('a') - .attr('href', url) - .attr('target', '_blank') - .last() - .find('img') - .attr('src', thumb) - .attr('width', width) - .attr('title', data.title || data.url || url); - $('#' + id).append(link); - } - }); - } + if (thumb) { + var link = $(''); + link.find('a') + .attr('href', url) + .attr('target', '_blank') + .last() + .find('img') + .attr('src', thumb) + .attr('width', width) + .attr('title', data.title || data.url || url); + $('#' + id).append(link); + } + }); + }, - /** - * Update the live preview section with links found in the given text. - * May start async data loads. - * - * @param {String} text: free-form input text - */ - function previewLinks(text) - { - var links = findLinks(text); - $('#link-preview').html(''); - for (var i = 0; i < links.length; i++) { - var id = 'link-preview-' + i; - $('#link-preview').append(''); - prepLinkPreview(id, links[i]); + /** + * Update the live preview section with links found in the given text. + * May start async data loads. + * + * @param {String} text: free-form input text + */ + previewLinks: function(text) + { + var links = LinkPreview.findLinks(text); + $('#link-preview').html(''); + for (var i = 0; i < links.length; i++) { + var id = 'link-preview-' + i; + $('#link-preview').append(''); + LinkPreview.prepLinkPreview(id, links[i]); + } } - } + }; SN.Init.LinkPreview = function(params) { if (params.api) oEmbed.api = params.api; @@ -149,7 +153,7 @@ // Piggyback on the counter update... var origCounter = SN.U.Counter; SN.U.Counter = function(form) { - previewLinks($('#notice_data-text').val()); + LinkPreview.previewLinks($('#notice_data-text').val()); return origCounter(form); } } -- cgit v1.2.3-54-g00ecf From f7fe3fa3868f4e7d84c7d0c8b04ccf6f0727f6bb Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 16 Nov 2010 15:20:37 -0800 Subject: Less redrawing of bits in the link thumbnail preview --- plugins/LinkPreview/linkpreview.js | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) (limited to 'plugins') diff --git a/plugins/LinkPreview/linkpreview.js b/plugins/LinkPreview/linkpreview.js index 37b0241a5..5dca3a807 100644 --- a/plugins/LinkPreview/linkpreview.js +++ b/plugins/LinkPreview/linkpreview.js @@ -133,13 +133,34 @@ */ previewLinks: function(text) { + var old = LinkPreview.links; var links = LinkPreview.findLinks(text); - $('#link-preview').html(''); - for (var i = 0; i < links.length; i++) { - var id = 'link-preview-' + i; - $('#link-preview').append(''); - LinkPreview.prepLinkPreview(id, links[i]); + + // Check for existing common elements... + for (var i = 0; i < old.length && i < links.length; i++) { + if (links[i] != old[i]) { + // Change an existing entry! + var id = 'link-preview-' + i; + $('#' + id).html(''); + LinkPreview.prepLinkPreview(id, links[i]); + } + } + if (links.length > old.length) { + // Adding new entries, whee! + for (var i = old.length; i < links.length; i++) { + var id = 'link-preview-' + i; + $('#link-preview').append(''); + LinkPreview.prepLinkPreview(id, links[i]); + } + } else if (old.length > links.length) { + // Remove preview entries for links that have been removed. + for (var i = links.length; i < old.length; i++) { + var id = 'link-preview-' + i; + $('#' + id).remove(); + } } + + LinkPreview.links = links; } }; -- cgit v1.2.3-54-g00ecf From 9cdb9cc18d7aea9eaf13443413ba051e78e1f89e Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 16 Nov 2010 15:31:03 -0800 Subject: LinkPreview: clear preview thumbnails & data on form submission/reset --- plugins/LinkPreview/linkpreview.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/LinkPreview/linkpreview.js b/plugins/LinkPreview/linkpreview.js index 5dca3a807..641adb729 100644 --- a/plugins/LinkPreview/linkpreview.js +++ b/plugins/LinkPreview/linkpreview.js @@ -161,6 +161,14 @@ } LinkPreview.links = links; + }, + + /** + * Clear out any link preview data. + */ + clear: function() { + LinkPreview.links = []; + $('#link-preview').empty(); } }; @@ -169,7 +177,11 @@ if (params.width) oEmbed.width = params.width; if (params.height) oEmbed.height = params.height; - $('#form_notice').append(''); + $('#form_notice') + .append('') + .bind('reset', function() { + LinkPreview.clear(); + }); // Piggyback on the counter update... var origCounter = SN.U.Counter; -- cgit v1.2.3-54-g00ecf From d1fb52264bc41a54061614772580377f200e90ee Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 16 Nov 2010 15:36:53 -0800 Subject: Use session token protection on oEmbed proxy action for LinkPreview... and commit the file *sigh* --- plugins/LinkPreview/linkpreview.js | 3 +- plugins/LinkPreview/oembedproxyaction.php | 84 +++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 plugins/LinkPreview/oembedproxyaction.php (limited to 'plugins') diff --git a/plugins/LinkPreview/linkpreview.js b/plugins/LinkPreview/linkpreview.js index 641adb729..0c0eb734e 100644 --- a/plugins/LinkPreview/linkpreview.js +++ b/plugins/LinkPreview/linkpreview.js @@ -54,7 +54,8 @@ url: url, format: 'json', maxwidth: oEmbed.width, - maxheight: oEmbed.height + maxheight: oEmbed.height, + token: $('#token').val() }; $.get(oEmbed.api, params, function(data, xhr) { callback(data); diff --git a/plugins/LinkPreview/oembedproxyaction.php b/plugins/LinkPreview/oembedproxyaction.php new file mode 100644 index 000000000..470f78073 --- /dev/null +++ b/plugins/LinkPreview/oembedproxyaction.php @@ -0,0 +1,84 @@ +. + * + * @package StatusNet + * @author Brion Vibber + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { + exit(1); +} + +/** + * Oembed proxy implementation + * + * This class provides an interface for our JS-side code to pull info on + * links from other sites, using either native oEmbed, our own custom + * handlers, or the oohEmbed.com offsite proxy service as configured. + * + * @category oEmbed + * @package StatusNet + * @author Brion Vibber + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class OembedproxyAction extends OembedAction +{ + + function handle($args) + { + // We're not a general oEmbed proxy service; limit to valid sessions. + $token = $this->trimmed('token'); + if (!$token || $token != common_session_token()) { + $this->clientError(_('There was a problem with your session token. '. + 'Try again, please.')); + } + + $format = $this->arg('format'); + if ($format && $format != 'json') { + throw new ClientException('Invalid format; only JSON supported.'); + } + + $url = $this->arg('url'); + if (!common_valid_http_url($url)) { + throw new ClientException('Invalid URL.'); + } + + $params = array(); + if ($this->arg('maxwidth')) { + $params['maxwidth'] = $this->arg('maxwidth'); + } + if ($this->arg('maxheight')) { + $params['maxheight'] = $this->arg('maxheight'); + } + + $data = oEmbedHelper::getObject($url, $params); + + $this->init_document('json'); + print json_encode($data); + } + +} -- cgit v1.2.3-54-g00ecf From 83f6bb9da1c91e0f464c1a665d01c4d5d1bfed09 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 17 Nov 2010 12:21:01 -0500 Subject: use minified version of realtime.js --- plugins/Realtime/RealtimePlugin.php | 2 +- plugins/Realtime/realtimeupdate.min.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 plugins/Realtime/realtimeupdate.min.js (limited to 'plugins') diff --git a/plugins/Realtime/RealtimePlugin.php b/plugins/Realtime/RealtimePlugin.php index 99d1ff9c1..113187e1e 100644 --- a/plugins/Realtime/RealtimePlugin.php +++ b/plugins/Realtime/RealtimePlugin.php @@ -322,7 +322,7 @@ class RealtimePlugin extends Plugin function _getScripts() { - return array('plugins/Realtime/realtimeupdate.js'); + return array('plugins/Realtime/realtimeupdate.min.js'); } /** diff --git a/plugins/Realtime/realtimeupdate.min.js b/plugins/Realtime/realtimeupdate.min.js new file mode 100644 index 000000000..a06c03c4e --- /dev/null +++ b/plugins/Realtime/realtimeupdate.min.js @@ -0,0 +1 @@ +RealtimeUpdate={_userid:0,_replyurl:"",_favorurl:"",_repeaturl:"",_deleteurl:"",_updatecounter:0,_maxnotices:50,_windowhasfocus:true,_documenttitle:"",_paused:false,_queuedNotices:[],init:function(c,b,d,e,a){RealtimeUpdate._userid=c;RealtimeUpdate._replyurl=b;RealtimeUpdate._favorurl=d;RealtimeUpdate._repeaturl=e;RealtimeUpdate._deleteurl=a;RealtimeUpdate._documenttitle=document.title;$(window).bind("focus",function(){RealtimeUpdate._windowhasfocus=true});$(window).bind("blur",function(){$("#notices_primary .notice").removeClass("mark-top");$("#notices_primary .notice:first").addClass("mark-top");RealtimeUpdate._updatecounter=0;document.title=RealtimeUpdate._documenttitle;RealtimeUpdate._windowhasfocus=false;return false})},receive:function(a){if(RealtimeUpdate._paused===false){RealtimeUpdate.purgeLastNoticeItem();RealtimeUpdate.insertNoticeItem(a)}else{RealtimeUpdate._queuedNotices.push(a);RealtimeUpdate.updateQueuedCounter()}RealtimeUpdate.updateWindowCounter()},insertNoticeItem:function(a){if($("#notice-"+a.id).length>0){return}var b=RealtimeUpdate.makeNoticeItem(a);var c=$(b).attr("id");$("#notices_primary .notices").prepend(b);$("#notices_primary .notice:first").css({display:"none"});$("#notices_primary .notice:first").fadeIn(1000);SN.U.NoticeReplyTo($("#"+c));SN.U.NoticeWithAttachment($("#"+c))},purgeLastNoticeItem:function(){if($("#notices_primary .notice").length>RealtimeUpdate._maxnotices){$("#notices_primary .notice:last").remove()}},updateWindowCounter:function(){if(RealtimeUpdate._windowhasfocus===false){RealtimeUpdate._updatecounter+=1;document.title="("+RealtimeUpdate._updatecounter+") "+RealtimeUpdate._documenttitle}},makeNoticeItem:function(c){if(c.hasOwnProperty("retweeted_status")){original=c.retweeted_status;repeat=c;c=original;unique=repeat.id;responsible=repeat.user}else{original=null;repeat=null;unique=c.id;responsible=c.user}user=c.user;html=c.html.replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/&/g,"&");source=c.source.replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/&/g,"&");ni='
  • '+user.screen_name+''+user.screen_name+'

    '+html+'

    a few seconds ago from '+source+"";if(c.conversation_url){ni=ni+' in context'}if(repeat){ru=repeat.user;ni=ni+'Repeated by '+ru.screen_name+""}ni=ni+"
    ";ni=ni+'
    ';if(RealtimeUpdate._userid!=0){var a=$("form#form_notice fieldset input#token");var b=a.val();ni=ni+RealtimeUpdate.makeFavoriteForm(c.id,b);ni=ni+RealtimeUpdate.makeReplyLink(c.id,c.user["screen_name"]);if(RealtimeUpdate._userid==responsible.id){ni=ni+RealtimeUpdate.makeDeleteLink(c.id)}else{if(RealtimeUpdate._userid!=user.id){ni=ni+RealtimeUpdate.makeRepeatForm(c.id,b)}}}ni=ni+"
    ";ni=ni+"
  • ";return ni},makeFavoriteForm:function(c,b){var a;a='
    Favor this notice
    ';return a},makeReplyLink:function(c,a){var b;b='Reply '+c+"";return b},makeRepeatForm:function(c,b){var a;a='
    Repeat this notice?
    ';return a},makeDeleteLink:function(c){var b,a;a=RealtimeUpdate._deleteurl.replace("0000000000",c);b='Delete';return b},initActions:function(a,b,c){$("#notices_primary").prepend('
    ');RealtimeUpdate._pluginPath=c;RealtimeUpdate.initPlayPause();RealtimeUpdate.initAddPopup(a,b,RealtimeUpdate._pluginPath)},initPlayPause:function(){if(typeof(localStorage)=="undefined"){RealtimeUpdate.showPause()}else{if(localStorage.getItem("RealtimeUpdate_paused")==="true"){RealtimeUpdate.showPlay()}else{RealtimeUpdate.showPause()}}},showPause:function(){RealtimeUpdate.setPause(false);RealtimeUpdate.showQueuedNotices();RealtimeUpdate.addNoticesHover();$("#realtime_playpause").remove();$("#realtime_actions").prepend('
  • ');$("#realtime_pause").text(SN.msg("realtime_pause")).attr("title",SN.msg("realtime_pause_tooltip")).bind("click",function(){RealtimeUpdate.removeNoticesHover();RealtimeUpdate.showPlay();return false})},showPlay:function(){RealtimeUpdate.setPause(true);$("#realtime_playpause").remove();$("#realtime_actions").prepend('
  • ');$("#realtime_play").text(SN.msg("realtime_play")).attr("title",SN.msg("realtime_play_tooltip")).bind("click",function(){RealtimeUpdate.showPause();return false})},setPause:function(a){RealtimeUpdate._paused=a;if(typeof(localStorage)!="undefined"){localStorage.setItem("RealtimeUpdate_paused",RealtimeUpdate._paused)}},showQueuedNotices:function(){$.each(RealtimeUpdate._queuedNotices,function(a,b){RealtimeUpdate.insertNoticeItem(b)});RealtimeUpdate._queuedNotices=[];RealtimeUpdate.removeQueuedCounter()},updateQueuedCounter:function(){$("#realtime_playpause #queued_counter").html("("+RealtimeUpdate._queuedNotices.length+")")},removeQueuedCounter:function(){$("#realtime_playpause #queued_counter").empty()},addNoticesHover:function(){$("#notices_primary .notices").hover(function(){if(RealtimeUpdate._paused===false){RealtimeUpdate.showPlay()}},function(){if(RealtimeUpdate._paused===true){RealtimeUpdate.showPause()}})},removeNoticesHover:function(){$("#notices_primary .notices").unbind()},initAddPopup:function(a,b,c){$("#realtime_timeline").append('');$("#realtime_popup").text(SN.msg("realtime_popup")).attr("title",SN.msg("realtime_popup_tooltip")).bind("click",function(){window.open(a,"","toolbar=no,resizable=yes,scrollbars=yes,status=no,menubar=no,personalbar=no,location=no,width=500,height=550");return false})},initPopupWindow:function(){$(".notices .entry-title a, .notices .entry-content a").bind("click",function(){window.open(this.href,"");return false});$("#showstream .entity_profile").css({width:"69%"})}}; \ No newline at end of file -- cgit v1.2.3-54-g00ecf From fae63a5161ab1ad9d2988c396d0fda00f608505d Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 17 Nov 2010 12:22:02 -0500 Subject: use minified version of meteorupdater.js --- plugins/Meteor/MeteorPlugin.php | 2 +- plugins/Meteor/meteorupdater.min.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 plugins/Meteor/meteorupdater.min.js (limited to 'plugins') diff --git a/plugins/Meteor/MeteorPlugin.php b/plugins/Meteor/MeteorPlugin.php index a48c52b56..1bdccae7a 100644 --- a/plugins/Meteor/MeteorPlugin.php +++ b/plugins/Meteor/MeteorPlugin.php @@ -89,7 +89,7 @@ class MeteorPlugin extends RealtimePlugin { $scripts = parent::_getScripts(); $scripts[] = 'http://'.$this->webserver.(($this->webport == 80) ? '':':'.$this->webport).'/meteor.js'; - $scripts[] = common_path('plugins/Meteor/meteorupdater.js'); + $scripts[] = common_path('plugins/Meteor/meteorupdater.min.js'); return $scripts; } diff --git a/plugins/Meteor/meteorupdater.min.js b/plugins/Meteor/meteorupdater.min.js new file mode 100644 index 000000000..61928ab4f --- /dev/null +++ b/plugins/Meteor/meteorupdater.min.js @@ -0,0 +1 @@ +var MeteorUpdater=function(){return{init:function(c,a,b){Meteor.callbacks.process=function(d){RealtimeUpdate.receive(JSON.parse(d))};Meteor.host=c;Meteor.port=a;Meteor.joinChannel(b,0);Meteor.connect()}}}(); \ No newline at end of file -- cgit v1.2.3-54-g00ecf From 197b56778a04a1d0f12dabb84e95dc9b80902aeb Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 17 Nov 2010 13:03:59 -0800 Subject: Add $config['attachments']['process_links'] to allow disabling processing of mentioned URL links for attachment info (oEmbed lookups) and dereferencing of redirects that we didn't have shortened ourselves. This option may be useful for intranet sites that don't have direct access to the internet, as they may be unable to successfully fetch those resources. --- classes/File_redirection.php | 12 +++++++++--- classes/Notice.php | 12 ++++++++---- lib/default.php | 1 + lib/util.php | 8 +++++--- plugins/LinkPreview/LinkPreviewPlugin.php | 2 +- plugins/TwitterBridge/twitterimport.php | 8 +++++--- 6 files changed, 29 insertions(+), 14 deletions(-) (limited to 'plugins') diff --git a/classes/File_redirection.php b/classes/File_redirection.php index 1976e3439..4ee43026b 100644 --- a/classes/File_redirection.php +++ b/classes/File_redirection.php @@ -139,6 +139,7 @@ class File_redirection extends Memcached_DataObject * reached. * * @param string $in_url + * @param boolean $discover true to attempt dereferencing the redirect if we don't know it already * @return mixed one of: * string - target URL, if this is a direct link or a known redirect * array - redirect info if this is an *unknown* redirect: @@ -150,7 +151,7 @@ class File_redirection extends Memcached_DataObject * size (optional): byte size from Content-Length header * time (optional): timestamp from Last-Modified header */ - public function where($in_url) { + public function where($in_url, $discover=true) { // let's see if we know this... $a = File::staticGet('url', $in_url); @@ -166,8 +167,13 @@ class File_redirection extends Memcached_DataObject } } - $ret = File_redirection::lookupWhere($in_url); - return $ret; + if ($discover) { + $ret = File_redirection::lookupWhere($in_url); + return $ret; + } else { + // No manual dereferencing; leave the unknown URL as is. + return $in_url; + } } /** diff --git a/classes/Notice.php b/classes/Notice.php index 85c7dabea..dd9438f16 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -476,7 +476,9 @@ class Notice extends Memcached_DataObject * @return void */ function saveUrls() { - common_replace_urls_callback($this->content, array($this, 'saveUrl'), $this->id); + if (common_config('attachments', 'process_links')) { + common_replace_urls_callback($this->content, array($this, 'saveUrl'), $this->id); + } } /** @@ -489,9 +491,11 @@ class Notice extends Memcached_DataObject */ function saveKnownUrls($urls) { - // @fixme validation? - foreach (array_unique($urls) as $url) { - File::processNew($url, $this->id); + if (common_config('attachments', 'process_links')) { + // @fixme validation? + foreach (array_unique($urls) as $url) { + File::processNew($url, $this->id); + } } } diff --git a/lib/default.php b/lib/default.php index ece01f2a8..a91fa338f 100644 --- a/lib/default.php +++ b/lib/default.php @@ -253,6 +253,7 @@ $default = 'show_thumbs' => true, // show thumbnails in notice lists for uploaded images, and photos and videos linked remotely that provide oEmbed info 'thumb_width' => 100, 'thumb_height' => 75, + 'process_links' => true, // check linked resources for embeddable photos and videos; this will hit referenced external web sites when processing new messages. ), 'application' => array('desclimit' => null), diff --git a/lib/util.php b/lib/util.php index e6b62f750..49566c4d4 100644 --- a/lib/util.php +++ b/lib/util.php @@ -848,7 +848,7 @@ function common_linkify($url) { $canon = File_redirection::_canonUrl($url); - $longurl_data = File_redirection::where($canon); + $longurl_data = File_redirection::where($canon, common_config('attachments', 'process_links')); if (is_array($longurl_data)) { $longurl = $longurl_data['url']; } elseif (is_string($longurl_data)) { @@ -872,8 +872,10 @@ function common_linkify($url) { $f = File::staticGet('url', $longurl); if (empty($f)) { - // XXX: this writes to the database. :< - $f = File::processNew($longurl); + if (common_config('attachments', 'process_links')) { + // XXX: this writes to the database. :< + $f = File::processNew($longurl); + } } if (!empty($f)) { diff --git a/plugins/LinkPreview/LinkPreviewPlugin.php b/plugins/LinkPreview/LinkPreviewPlugin.php index da7981148..39d2c9bf3 100644 --- a/plugins/LinkPreview/LinkPreviewPlugin.php +++ b/plugins/LinkPreview/LinkPreviewPlugin.php @@ -50,7 +50,7 @@ class LinkPreviewPlugin extends Plugin function onEndShowScripts($action) { $user = common_current_user(); - if ($user) { + if ($user && common_config('attachments', 'process_links')) { $action->script('plugins/LinkPreview/linkpreview.js'); $data = json_encode(array( 'api' => common_local_url('oembedproxy'), diff --git a/plugins/TwitterBridge/twitterimport.php b/plugins/TwitterBridge/twitterimport.php index 498e9b1fc..9e53849d8 100644 --- a/plugins/TwitterBridge/twitterimport.php +++ b/plugins/TwitterBridge/twitterimport.php @@ -659,9 +659,11 @@ class TwitterImport */ function saveStatusAttachments($notice, $status) { - if (!empty($status->entities) && !empty($status->entities->urls)) { - foreach ($status->entities->urls as $url) { - File::processNew($url->url, $notice->id); + if (common_config('attachments', 'process_links')) { + if (!empty($status->entities) && !empty($status->entities->urls)) { + foreach ($status->entities->urls as $url) { + File::processNew($url->url, $notice->id); + } } } } -- cgit v1.2.3-54-g00ecf