diff --git a/CONFIGURE b/CONFIGURE
index 141c475563..bec9e90a6f 100644
--- a/CONFIGURE
+++ b/CONFIGURE
@@ -592,23 +592,6 @@ desclimit: maximum number of characters to allow in group descriptions.
addtag: Whether to add a tag for the group nickname for every group post
(pre-1.0.x behaviour). Defaults to false.
-oembed
---------
-
-oEmbed endpoint for multimedia attachments (links in posts). Will also
-work as 'oohembed' for backwards compatibility.
-
-endpoint: oohembed endpoint using http://oohembed.com/ software. Defaults to
- 'http://oohembed.com/oohembed/'.
-order: Array of methods to check for OEmbed data. Methods include 'built-in'
- (use a built-in function to simulate oEmbed for some sites),
- 'well-known' (use well-known public oEmbed endpoints),
- 'discovery' (discover using headers in HTML), 'service' (use
- a third-party service, like oohembed or embed.ly. Default is
- array('built-in', 'well-known', 'service', 'discovery'). Note that very
- few sites implement oEmbed; 'discovery' is going to fail 99% of the
- time.
-
search
------
diff --git a/actions/attachment.php b/actions/attachment.php
index 30499c15f4..d9cacb1193 100644
--- a/actions/attachment.php
+++ b/actions/attachment.php
@@ -96,28 +96,6 @@ class AttachmentAction extends Action
return $a->title();
}
- function extraHead()
- {
- $this->element('link',array('rel'=>'alternate',
- 'type'=>'application/json+oembed',
- 'href'=>common_local_url(
- 'oembed',
- array(),
- array('format'=>'json', 'url'=>
- common_local_url('attachment',
- array('attachment' => $this->attachment->id)))),
- 'title'=>'oEmbed'),null);
- $this->element('link',array('rel'=>'alternate',
- 'type'=>'text/xml+oembed',
- 'href'=>common_local_url(
- 'oembed',
- array(),
- array('format'=>'xml','url'=>
- common_local_url('attachment',
- array('attachment' => $this->attachment->id)))),
- 'title'=>'oEmbed'),null);
- }
-
/**
* Handle input
*
diff --git a/actions/oembed.php b/actions/oembed.php
deleted file mode 100644
index da0352edf8..0000000000
--- a/actions/oembed.php
+++ /dev/null
@@ -1,244 +0,0 @@
-.
- *
- * @category Twitter
- * @package StatusNet
- * @author Evan Prodromou
- * @copyright 2008 StatusNet, Inc.
- * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
- * @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 provider implementation
- *
- * This class handles all /main/oembed(.xml|.json)/ requests.
- *
- * @category oEmbed
- * @package StatusNet
- * @author Craig Andrews
- * @copyright 2008 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 OembedAction extends Action
-{
-
- function handle($args)
- {
- common_debug("in oembed api action");
-
- $url = $args['url'];
- if( substr(strtolower($url),0,strlen(common_root_url())) == strtolower(common_root_url()) ){
- $path = substr($url,strlen(common_root_url()));
-
- $r = Router::get();
-
- $proxy_args = $r->map($path);
-
- if (!$proxy_args) {
- // TRANS: Server error displayed in oEmbed action when path not found.
- // TRANS: %s is a path.
- $this->serverError(sprintf(_('"%s" not found.'),$path), 404);
- }
- $oembed=array();
- $oembed['version']='1.0';
- $oembed['provider_name']=common_config('site', 'name');
- $oembed['provider_url']=common_root_url();
- switch($proxy_args['action']){
- case 'shownotice':
- $oembed['type']='link';
- $id = $proxy_args['notice'];
- $notice = Notice::getKV($id);
- if(empty($notice)){
- // TRANS: Server error displayed in oEmbed action when notice not found.
- // TRANS: %s is a notice.
- $this->serverError(sprintf(_("Notice %s not found."),$id), 404);
- }
- $profile = $notice->getProfile();
- if (empty($profile)) {
- // TRANS: Server error displayed in oEmbed action when notice has not profile.
- $this->serverError(_('Notice has no profile.'), 500);
- }
- $authorname = $profile->getFancyName();
- // TRANS: oEmbed title. %1$s is the author name, %2$s is the creation date.
- $oembed['title'] = sprintf(_('%1$s\'s status on %2$s'),
- $authorname,
- common_exact_date($notice->created));
- $oembed['author_name']=$authorname;
- $oembed['author_url']=$profile->profileurl;
- $oembed['url']=$notice->getUrl();
- $oembed['html']=$notice->rendered;
- break;
- case 'attachment':
- $id = $proxy_args['attachment'];
- $attachment = File::getKV($id);
- if(empty($attachment)){
- // TRANS: Server error displayed in oEmbed action when attachment not found.
- // TRANS: %d is an attachment ID.
- $this->serverError(sprintf(_('Attachment %s not found.'),$id), 404);
- }
- if(empty($attachment->filename) && $file_oembed = File_oembed::getKV('file_id', $attachment->id)){
- // Proxy the existing oembed information
- $oembed['type']=$file_oembed->type;
- $oembed['provider']=$file_oembed->provider;
- $oembed['provider_url']=$file_oembed->provider_url;
- $oembed['width']=$file_oembed->width;
- $oembed['height']=$file_oembed->height;
- $oembed['html']=$file_oembed->html;
- $oembed['title']=$file_oembed->title;
- $oembed['author_name']=$file_oembed->author_name;
- $oembed['author_url']=$file_oembed->author_url;
- $oembed['url']=$file_oembed->getUrl();
- }else if(substr($attachment->mimetype,0,strlen('image/'))=='image/'){
- $oembed['type']='photo';
- if ($attachment->filename) {
- $filepath = File::path($attachment->filename);
- $gis = @getimagesize($filepath);
- if ($gis) {
- $oembed['width'] = $gis[0];
- $oembed['height'] = $gis[1];
- } else {
- // TODO Either throw an error or find a fallback?
- }
- }
- $oembed['url']=$attachment->getUrl();
- try {
- $thumb = $attachment->getThumbnail();
- $oembed['thumbnail_url'] = $thumb->getUrl();
- $oembed['thumbnail_width'] = $thumb->width;
- $oembed['thumbnail_height'] = $thumb->height;
- unset($thumb);
- } catch (UnsupportedMediaException $e) {
- // No thumbnail data available
- }
- }else{
- $oembed['type']='link';
- $oembed['url']=common_local_url('attachment',
- array('attachment' => $attachment->id));
- }
- if($attachment->title) $oembed['title']=$attachment->title;
- break;
- default:
- // TRANS: Server error displayed in oEmbed request when a path is not supported.
- // TRANS: %s is a path.
- $this->serverError(sprintf(_('"%s" not supported for oembed requests.'),$path), 501);
- }
- switch($args['format']){
- case 'xml':
- $this->init_document('xml');
- $this->elementStart('oembed');
- $this->element('version',null,$oembed['version']);
- $this->element('type',null,$oembed['type']);
- if($oembed['provider_name']) $this->element('provider_name',null,$oembed['provider_name']);
- if($oembed['provider_url']) $this->element('provider_url',null,$oembed['provider_url']);
- if($oembed['title']) $this->element('title',null,$oembed['title']);
- if($oembed['author_name']) $this->element('author_name',null,$oembed['author_name']);
- if($oembed['author_url']) $this->element('author_url',null,$oembed['author_url']);
- if($oembed['url']) $this->element('url',null,$oembed['url']);
- if($oembed['html']) $this->element('html',null,$oembed['html']);
- if($oembed['width']) $this->element('width',null,$oembed['width']);
- if($oembed['height']) $this->element('height',null,$oembed['height']);
- if($oembed['cache_age']) $this->element('cache_age',null,$oembed['cache_age']);
- if($oembed['thumbnail_url']) $this->element('thumbnail_url',null,$oembed['thumbnail_url']);
- if($oembed['thumbnail_width']) $this->element('thumbnail_width',null,$oembed['thumbnail_width']);
- if($oembed['thumbnail_height']) $this->element('thumbnail_height',null,$oembed['thumbnail_height']);
-
- $this->elementEnd('oembed');
- $this->end_document('xml');
- break;
- case 'json': case '':
- $this->init_document('json');
- print(json_encode($oembed));
- $this->end_document('json');
- break;
- default:
- // TRANS: Error message displaying attachments. %s is a raw MIME type (eg 'image/png')
- $this->serverError(sprintf(_('Content type %s not supported.'), $apidata['content-type']), 501);
- }
- }else{
- // TRANS: Error message displaying attachments. %s is the site's base URL.
- $this->serverError(sprintf(_('Only %s URLs over plain HTTP please.'), common_root_url()), 404);
- }
- }
-
- function init_document($type)
- {
- switch ($type) {
- case 'xml':
- header('Content-Type: application/xml; charset=utf-8');
- $this->startXML();
- break;
- case 'json':
- header('Content-Type: application/json; charset=utf-8');
-
- // Check for JSONP callback
- $callback = $this->arg('callback');
- if ($callback) {
- print $callback . '(';
- }
- break;
- default:
- // TRANS: Server error displayed in oEmbed action when request specifies an unsupported data format.
- $this->serverError(_('Not a supported data format.'), 501);
- break;
- }
- }
-
- function end_document($type='xml')
- {
- switch ($type) {
- case 'xml':
- $this->endXML();
- break;
- case 'json':
- // Check for JSONP callback
- $callback = $this->arg('callback');
- if ($callback) {
- print ')';
- }
- break;
- default:
- // TRANS: Server error displayed in oEmbed action when request specifies an unsupported data format.
- $this->serverError(_('Not a supported data format.'), 501);
- break;
- }
- return;
- }
-
- /**
- * Is this action read-only?
- *
- * @param array $args other arguments
- *
- * @return boolean is read only action?
- */
- function isReadOnly($args)
- {
- return true;
- }
-}
diff --git a/actions/shownotice.php b/actions/shownotice.php
index ff39080eeb..28cb68c121 100644
--- a/actions/shownotice.php
+++ b/actions/shownotice.php
@@ -282,21 +282,6 @@ class ShownoticeAction extends Action
'content' => $id->toString()));
}
- $this->element('link',array('rel'=>'alternate',
- 'type'=>'application/json+oembed',
- 'href'=>common_local_url(
- 'oembed',
- array(),
- array('format'=>'json','url'=>$this->notice->getUrl())),
- 'title'=>'oEmbed'),null);
- $this->element('link',array('rel'=>'alternate',
- 'type'=>'text/xml+oembed',
- 'href'=>common_local_url(
- 'oembed',
- array(),
- array('format'=>'xml','url'=>$this->notice->getUrl())),
- 'title'=>'oEmbed'),null);
-
// Extras to aid in sharing notices to Facebook
$avatarUrl = $this->profile->avatarUrl(AVATAR_PROFILE_SIZE);
$this->element('meta', array('property' => 'og:image',
diff --git a/classes/File.php b/classes/File.php
index 29dc7b5492..69aee7fcee 100644
--- a/classes/File.php
+++ b/classes/File.php
@@ -75,62 +75,26 @@ class File extends Managed_DataObject
// I don't know why we have to keep doing this but I'm adding this last check to avoid
// uniqueness bugs.
- $x = File::getKV('url', $given_url);
+ $file = File::getKV('url', $given_url);
- if (!$x instanceof File) {
- $x = new File;
- $x->url = $given_url;
- if (!empty($redir_data['protected'])) $x->protected = $redir_data['protected'];
- if (!empty($redir_data['title'])) $x->title = $redir_data['title'];
- if (!empty($redir_data['type'])) $x->mimetype = $redir_data['type'];
- if (!empty($redir_data['size'])) $x->size = intval($redir_data['size']);
- if (isset($redir_data['time']) && $redir_data['time'] > 0) $x->date = intval($redir_data['time']);
- $file_id = $x->insert();
+ if (!$file instanceof File) {
+ $file = new File;
+ $file->url = $given_url;
+ if (!empty($redir_data['protected'])) $file->protected = $redir_data['protected'];
+ if (!empty($redir_data['title'])) $file->title = $redir_data['title'];
+ if (!empty($redir_data['type'])) $file->mimetype = $redir_data['type'];
+ if (!empty($redir_data['size'])) $file->size = intval($redir_data['size']);
+ if (isset($redir_data['time']) && $redir_data['time'] > 0) $file->date = intval($redir_data['time']);
+ $file_id = $file->insert();
}
- $x->saveOembed($redir_data, $given_url);
- return $x;
- }
-
- /**
- * Save embedding information for this file, if applicable.
- *
- * Normally this won't need to be called manually, as File::saveNew()
- * takes care of it.
- *
- * @param array $redir_data lookup data eg from File_redirection::where()
- * @param string $given_url
- * @return boolean success
- */
- public function saveOembed(array $redir_data, $given_url)
- {
- if (isset($redir_data['type'])
- && (('text/html' === substr($redir_data['type'], 0, 9)
- || 'application/xhtml+xml' === substr($redir_data['type'], 0, 21)))) {
- try {
- $oembed_data = File_oembed::_getOembed($given_url);
- } catch (Exception $e) {
- return false;
- }
- if ($oembed_data === false) {
- return false;
- }
- $fo = File_oembed::getKV('file_id', $this->id);
-
- if ($fo instanceof File_oembed) {
- common_log(LOG_WARNING, "Strangely, a File_oembed object exists for new file $file_id", __FILE__);
- } else {
- File_oembed::saveNew($oembed_data, $this->id);
- return true;
- }
- }
- return false;
+ Event::handle('EndFileSaveNew', array($file, $redir_data, $given_url));
+ return $file;
}
/**
* Go look at a URL and possibly save data about it if it's new:
* - follow redirect chains and store them in file_redirection
- * - look up oEmbed data and save it in file_oembed
* - if a thumbnail is available, save it in file_thumbnail
* - save file record with basic info
* - optionally save a file_to_post record
@@ -384,7 +348,7 @@ class File extends Managed_DataObject
$enclosure->size=$this->size;
$enclosure->mimetype=$this->mimetype;
- if(! isset($this->filename)){
+ if (!isset($this->filename)) {
$notEnclosureMimeTypes = array(null,'text/html','application/xhtml+xml');
$mimetype = $this->mimetype;
if($mimetype != null){
@@ -394,32 +358,8 @@ class File extends Managed_DataObject
if($semicolon){
$mimetype = substr($mimetype,0,$semicolon);
}
- if(in_array($mimetype,$notEnclosureMimeTypes)){
- // Never treat generic HTML links as an enclosure type!
- // But if we have oEmbed info, we'll consider it golden.
- $oembed = File_oembed::getKV('file_id',$this->id);
- if($oembed && in_array($oembed->type, array('photo', 'video'))){
- $mimetype = strtolower($oembed->mimetype);
- $semicolon = strpos($mimetype,';');
- if($semicolon){
- $mimetype = substr($mimetype,0,$semicolon);
- }
- // @fixme uncertain if this is right.
- // we want to expose things like YouTube videos as
- // viewable attachments, but don't expose them as
- // downloadable enclosures.....?
- //if (in_array($mimetype, $notEnclosureMimeTypes)) {
- // return false;
- //} else {
- if($oembed->mimetype) $enclosure->mimetype=$oembed->mimetype;
- if($oembed->url) $enclosure->url=$oembed->url;
- if($oembed->title) $enclosure->title=$oembed->title;
- if($oembed->modified) $enclosure->modified=$oembed->modified;
- unset($oembed->size);
- //}
- } else {
- return false;
- }
+ if (in_array($mimetype, $notEnclosureMimeTypes)) {
+ Event::handle('FileEnclosureMetadata', array($file, &$enclosure));
}
}
return $enclosure;
diff --git a/classes/File_redirection.php b/classes/File_redirection.php
index 42021668d9..0bcccc6cff 100644
--- a/classes/File_redirection.php
+++ b/classes/File_redirection.php
@@ -257,9 +257,6 @@ class File_redirection extends Managed_DataObject
// Save file and embedding data about it!
$file = File::saveNew($redir_data, $long_url);
$file_id = $file->id;
- if (!empty($redir_data['oembed']['json'])) {
- File_oembed::saveNew($redir_data['oembed']['json'], $file_id);
- }
} else if (is_string($redir_data)) {
// The file is a known redirect target.
$file = File::getKV('url', $redir_data);
diff --git a/db/core.php b/db/core.php
index d435c03cd6..61f8228cb5 100644
--- a/db/core.php
+++ b/db/core.php
@@ -67,7 +67,6 @@ $classes = array('Schema_version',
'Group_inbox',
'Group_member',
'File',
- 'File_oembed',
'File_redirection',
'File_thumbnail',
'File_to_post',
diff --git a/lib/action.php b/lib/action.php
index e219847c70..4d917dc69e 100644
--- a/lib/action.php
+++ b/lib/action.php
@@ -166,6 +166,11 @@ class Action extends HTMLOutputter // lawsuit
return $this->scoped;
}
+ public function getActionName()
+ {
+ return $this->action;
+ }
+
/**
* Show page, a template method.
*
diff --git a/lib/attachmentlist.php b/lib/attachmentlist.php
index 7f356f9527..66b03182b3 100644
--- a/lib/attachmentlist.php
+++ b/lib/attachmentlist.php
@@ -134,8 +134,6 @@ class AttachmentListItem extends Widget
var $attachment = null;
- var $oembed = null;
-
/**
* @param File $attachment the attachment we will display
*/
@@ -143,21 +141,10 @@ class AttachmentListItem extends Widget
{
parent::__construct($out);
$this->attachment = $attachment;
- $this->oembed = File_oembed::getKV('file_id', $this->attachment->id);
}
function title() {
- if (empty($this->attachment->title)) {
- if (empty($this->oembed->title)) {
- $title = $this->attachment->filename;
- } else {
- $title = $this->oembed->title;
- }
- } else {
- $title = $this->attachment->title;
- }
-
- return $title;
+ return $this->attachment->title ?: $this->attachment->filename;
}
function linkTitle() {
@@ -238,40 +225,19 @@ class AttachmentListItem extends Widget
class Attachment extends AttachmentListItem
{
function showLink() {
- $this->out->elementStart('div', array('id' => 'attachment_view',
- 'class' => 'hentry'));
- $this->out->elementStart('div', 'entry-title');
- $this->out->element('a', $this->linkAttr(), $this->linkTitle());
- $this->out->elementEnd('div');
+ if (Event::handle('StartShowAttachmentLink', array($this->out, $this->attachment))) {
+ $this->out->elementStart('div', array('id' => 'attachment_view',
+ 'class' => 'hentry'));
+ $this->out->elementStart('div', 'entry-title');
+ $this->out->element('a', $this->linkAttr(), $this->linkTitle());
+ $this->out->elementEnd('div');
- $this->out->elementStart('div', 'entry-content');
- $this->showRepresentation();
- $this->out->elementEnd('div');
-
- if (!empty($this->oembed->author_name) || !empty($this->oembed->provider)) {
- $this->out->elementStart('div', array('id' => 'oembed_info',
- 'class' => 'entry-content'));
- if (!empty($this->oembed->author_name)) {
- $this->out->elementStart('div', 'fn vcard author');
- if (empty($this->oembed->author_url)) {
- $this->out->text($this->oembed->author_name);
- } else {
- $this->out->element('a', array('href' => $this->oembed->author_url,
- 'class' => 'url'), $this->oembed->author_name);
- }
- }
- if (!empty($this->oembed->provider)) {
- $this->out->elementStart('div', 'fn vcard');
- if (empty($this->oembed->provider_url)) {
- $this->out->text($this->oembed->provider);
- } else {
- $this->out->element('a', array('href' => $this->oembed->provider_url,
- 'class' => 'url'), $this->oembed->provider);
- }
- }
+ $this->out->elementStart('div', 'entry-content');
+ $this->showRepresentation();
+ $this->out->elementEnd('div');
+ Event::handle('EndShowAttachmentLink', array($this->out, $this->attachment));
$this->out->elementEnd('div');
}
- $this->out->elementEnd('div');
}
function show() {
@@ -288,28 +254,7 @@ class Attachment extends AttachmentListItem
function showRepresentation() {
if (Event::handle('StartShowAttachmentRepresentation', array($this->out, $this->attachment))) {
- if (!empty($this->oembed->type)) {
- switch ($this->oembed->type) {
- case 'rich':
- case 'video':
- case 'link':
- if (!empty($this->oembed->html)) {
- require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
- $config = array(
- 'safe'=>1,
- 'elements'=>'*+object+embed');
- $this->out->raw(htmLawed($this->oembed->html,$config));
- }
- break;
-
- case 'photo':
- $this->out->element('img', array('src' => $this->oembed->url, 'width' => $this->oembed->width, 'height' => $this->oembed->height, 'alt' => 'alt'));
- break;
-
- default:
- Event::handle('ShowUnsupportedAttachmentRepresentation', array($this->out, $this->attachment));
- }
- } elseif (!empty($this->attachment->mimetype)) {
+ if (!empty($this->attachment->mimetype)) {
switch ($this->attachment->mimetype) {
case 'image/gif':
case 'image/png':
diff --git a/lib/default.php b/lib/default.php
index d2270fa6a5..65301bbb45 100644
--- a/lib/default.php
+++ b/lib/default.php
@@ -303,6 +303,7 @@ $default =
'ClientSideShorten' => array(),
'EmailAuthentication' => array(),
'Event' => array(),
+ 'Oembed' => array(),
'OpenID' => array(),
'Poll' => array(),
'QnA' => array(),
diff --git a/lib/router.php b/lib/router.php
index 71bf4e8e82..3febbbeff4 100644
--- a/lib/router.php
+++ b/lib/router.php
@@ -168,9 +168,6 @@ class Router
$m->connect('main/tagprofile', array('action' => 'tagprofile'));
- $m->connect('main/oembed',
- array('action' => 'oembed'));
-
$m->connect('main/xrds',
array('action' => 'publicxrds'));
diff --git a/plugins/Bookmark/README b/plugins/Bookmark/README
new file mode 100644
index 0000000000..e853760544
--- /dev/null
+++ b/plugins/Bookmark/README
@@ -0,0 +1 @@
+Depends on the oEmbed plugin (Oembed).
diff --git a/plugins/LinkPreview/README b/plugins/LinkPreview/README
new file mode 100644
index 0000000000..a1b1a87303
--- /dev/null
+++ b/plugins/LinkPreview/README
@@ -0,0 +1 @@
+Depends on the oEmbed plugin (Oembed)
diff --git a/plugins/Oembed/CONFIGURE b/plugins/Oembed/CONFIGURE
new file mode 100644
index 0000000000..b8d24f909f
--- /dev/null
+++ b/plugins/Oembed/CONFIGURE
@@ -0,0 +1,18 @@
+So far this is still in $config['site']['oembed'].
+
+oembed
+--------
+
+oEmbed endpoint for multimedia attachments (links in posts). Will also
+work as 'oohembed' for backwards compatibility.
+
+endpoint: oohembed endpoint using http://oohembed.com/ software. Defaults to
+ 'http://oohembed.com/oohembed/'.
+order: Array of methods to check for OEmbed data. Methods include 'built-in'
+ (use a built-in function to simulate oEmbed for some sites),
+ 'well-known' (use well-known public oEmbed endpoints),
+ 'discovery' (discover using headers in HTML), 'service' (use
+ a third-party service, like oohembed or embed.ly. Default is
+ array('built-in', 'well-known', 'service', 'discovery'). Note that very
+ few sites implement oEmbed; 'discovery' is going to fail 99% of the
+ time.
diff --git a/plugins/Oembed/OembedPlugin.php b/plugins/Oembed/OembedPlugin.php
new file mode 100644
index 0000000000..177fd6ed3e
--- /dev/null
+++ b/plugins/Oembed/OembedPlugin.php
@@ -0,0 +1,187 @@
+ensureTable('file_oembed', File_oembed::schemaDef());
+ return true;
+ }
+
+ public function onRouterInitialized(URLMapper $m)
+ {
+ $m->connect('main/oembed', array('action' => 'oembed'));
+ }
+
+ public function onEndShowHeadElements(Action $action)
+ {
+ switch ($action->getActionName()) {
+ case 'attachment':
+ $action->element('link',array('rel'=>'alternate',
+ 'type'=>'application/json+oembed',
+ 'href'=>common_local_url(
+ 'oembed',
+ array(),
+ array('format'=>'json', 'url'=>
+ common_local_url('attachment',
+ array('attachment' => $action->attachment->id)))),
+ 'title'=>'oEmbed'),null);
+ $action->element('link',array('rel'=>'alternate',
+ 'type'=>'text/xml+oembed',
+ 'href'=>common_local_url(
+ 'oembed',
+ array(),
+ array('format'=>'xml','url'=>
+ common_local_url('attachment',
+ array('attachment' => $action->attachment->id)))),
+ 'title'=>'oEmbed'),null);
+ break;
+ case 'shownotice':
+ $this->element('link',array('rel'=>'alternate',
+ 'type'=>'application/json+oembed',
+ 'href'=>common_local_url(
+ 'oembed',
+ array(),
+ array('format'=>'json','url'=>$this->notice->getUrl())),
+ 'title'=>'oEmbed'),null);
+ $this->element('link',array('rel'=>'alternate',
+ 'type'=>'text/xml+oembed',
+ 'href'=>common_local_url(
+ 'oembed',
+ array(),
+ array('format'=>'xml','url'=>$this->notice->getUrl())),
+ 'title'=>'oEmbed'),null);
+ break;
+ }
+
+ return true;
+ }
+
+ /**
+ * Save embedding information for a File, if applicable.
+ *
+ * Normally this event is called through File::saveNew()
+ *
+ * @param File $file The newly inserted File object.
+ * @param array $redir_data lookup data eg from File_redirection::where()
+ * @param string $given_url
+ *
+ * @return boolean success
+ */
+ public function onEndFileSaveNew(File $file, array $redir_data, $given_url)
+ {
+ $fo = File_oembed::getKV('file_id', $file->id);
+ if ($fo instanceof File_oembed) {
+ common_log(LOG_WARNING, "Strangely, a File_oembed object exists for new file $file_id", __FILE__);
+ return true;
+ }
+
+ if (isset($redir_data['oembed']['json'])
+ && !empty($redir_data['oembed']['json'])) {
+ File_oembed::saveNew($redir_data['oembed']['json'], $file->id);
+ } elseif (isset($redir_data['type'])
+ && (('text/html' === substr($redir_data['type'], 0, 9)
+ || 'application/xhtml+xml' === substr($redir_data['type'], 0, 21)))) {
+
+ try {
+ $oembed_data = File_oembed::_getOembed($given_url);
+ if ($oembed_data === false) {
+ throw new Exception('Did not get oEmbed data from URL');
+ }
+ } catch (Exception $e) {
+ return true;
+ }
+
+ File_oembed::saveNew($oembed_data, $file->id);
+ }
+ return true;
+ }
+
+ public function onEndShowAttachmentLink(HTMLOutputter $out, File $file)
+ {
+ $oembed = File_oembed::getKV('file_id', $file->id);
+ if (empty($oembed->author_name) && empty($oembed->provider)) {
+ return true;
+ }
+ $out->elementStart('div', array('id'=>'oembed_info', 'class'=>'entry-content'));
+ if (!empty($oembed->author_name)) {
+ $out->elementStart('div', 'fn vcard author');
+ if (empty($oembed->author_url)) {
+ $out->text($oembed->author_name);
+ } else {
+ $out->element('a', array('href' => $oembed->author_url,
+ 'class' => 'url'),
+ $oembed->author_name);
+ }
+ }
+ if (!empty($oembed->provider)) {
+ $out->elementStart('div', 'fn vcard');
+ if (empty($oembed->provider_url)) {
+ $out->text($oembed->provider);
+ } else {
+ $out->element('a', array('href' => $oembed->provider_url,
+ 'class' => 'url'),
+ $oembed->provider);
+ }
+ }
+ $out->elementEnd('div');
+ }
+
+ public function onFileEnclosureMetadata(File $file, &$enclosure)
+ {
+ // Never treat generic HTML links as an enclosure type!
+ // But if we have oEmbed info, we'll consider it golden.
+ $oembed = File_oembed::getKV('file_id', $file->id);
+ if (!$oembed instanceof File_oembed || !in_array($oembed->type, array('photo', 'video'))) {
+ return true;
+ }
+
+ foreach (array('mimetype', 'url', 'title', 'modified') as $key) {
+ if (!empty($oembed->{$key})) {
+ $enclosure->{$key} = $oembed->{$key};
+ }
+ }
+ return true;
+ }
+
+ public function onStartShowAttachmentRepresentation(HTMLOutputter $out, File $file)
+ {
+ $oembed = File_oembed::getKV('file_id', $file->id);
+ if (empty($oembed->type)) {
+ return true;
+ }
+ switch ($oembed->type) {
+ case 'rich':
+ case 'video':
+ case 'link':
+ if (!empty($oembed->html)) {
+ require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
+ $config = array(
+ 'safe'=>1,
+ 'elements'=>'*+object+embed');
+ $out->raw(htmLawed($oembed->html,$config));
+ }
+ break;
+
+ case 'photo':
+ $out->element('img', array('src' => $oembed->url, 'width' => $oembed->width, 'height' => $oembed->height, 'alt' => 'alt'));
+ break;
+
+ default:
+ Event::handle('ShowUnsupportedAttachmentRepresentation', array($out, $file));
+ }
+ }
+
+ public function onPluginVersion(array &$versions)
+ {
+ $versions[] = array('name' => 'Oembed',
+ 'version' => GNUSOCIAL_VERSION,
+ 'author' => 'Mikael Nordfeldth',
+ 'homepage' => 'http://gnu.io/',
+ 'description' =>
+ // TRANS: Plugin description.
+ _m('Plugin for using and representing Oembed data.'));
+ return true;
+ }
+}
diff --git a/plugins/Oembed/README b/plugins/Oembed/README
new file mode 100644
index 0000000000..be8c09f7a6
--- /dev/null
+++ b/plugins/Oembed/README
@@ -0,0 +1 @@
+It's really called oEmbed.
diff --git a/plugins/Oembed/actions/oembed.php b/plugins/Oembed/actions/oembed.php
new file mode 100644
index 0000000000..509c3a73ee
--- /dev/null
+++ b/plugins/Oembed/actions/oembed.php
@@ -0,0 +1,236 @@
+.
+ */
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+/**
+ * Oembed provider implementation
+ *
+ * This class handles all /main/oembed(.xml|.json)/ requests.
+ *
+ * @category oEmbed
+ * @package GNUsocial
+ * @author Craig Andrews
+ * @author Mikael Nordfeldth
+ * @copyright 2008 StatusNet, Inc.
+ * @copyright 2014 Free Software Foundation, 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 OembedAction extends Action
+{
+ protected function handle()
+ {
+ parent::handle();
+
+ $url = $this->trimmed('url');
+ if (substr(strtolower($url),0,strlen(common_root_url())) == strtolower(common_root_url())) {
+ $path = substr($url,strlen(common_root_url()));
+
+ $r = Router::get();
+
+ $proxy_args = $r->map($path);
+ if (!$proxy_args) {
+ // TRANS: Server error displayed in oEmbed action when path not found.
+ // TRANS: %s is a path.
+ $this->serverError(sprintf(_('"%s" not found.'),$path), 404);
+ }
+
+ $oembed=array();
+ $oembed['version']='1.0';
+ $oembed['provider_name']=common_config('site', 'name');
+ $oembed['provider_url']=common_root_url();
+
+ switch ($proxy_args['action']) {
+ case 'shownotice':
+ $oembed['type']='link';
+ $id = $proxy_args['notice'];
+ $notice = Notice::getKV($id);
+ if(empty($notice)){
+ // TRANS: Server error displayed in oEmbed action when notice not found.
+ // TRANS: %s is a notice.
+ $this->serverError(sprintf(_("Notice %s not found."),$id), 404);
+ }
+ $profile = $notice->getProfile();
+ if (empty($profile)) {
+ // TRANS: Server error displayed in oEmbed action when notice has not profile.
+ $this->serverError(_('Notice has no profile.'), 500);
+ }
+ $authorname = $profile->getFancyName();
+ // TRANS: oEmbed title. %1$s is the author name, %2$s is the creation date.
+ $oembed['title'] = sprintf(_('%1$s\'s status on %2$s'),
+ $authorname,
+ common_exact_date($notice->created));
+ $oembed['author_name']=$authorname;
+ $oembed['author_url']=$profile->profileurl;
+ $oembed['url']=$notice->getUrl();
+ $oembed['html']=$notice->rendered;
+ break;
+
+ case 'attachment':
+ $id = $proxy_args['attachment'];
+ $attachment = File::getKV($id);
+ if(empty($attachment)){
+ // TRANS: Server error displayed in oEmbed action when attachment not found.
+ // TRANS: %d is an attachment ID.
+ $this->serverError(sprintf(_('Attachment %s not found.'),$id), 404);
+ }
+ if (empty($attachment->filename) && $file_oembed = File_oembed::getKV('file_id', $attachment->id)) {
+ // Proxy the existing oembed information
+ $oembed['type']=$file_oembed->type;
+ $oembed['provider']=$file_oembed->provider;
+ $oembed['provider_url']=$file_oembed->provider_url;
+ $oembed['width']=$file_oembed->width;
+ $oembed['height']=$file_oembed->height;
+ $oembed['html']=$file_oembed->html;
+ $oembed['title']=$file_oembed->title;
+ $oembed['author_name']=$file_oembed->author_name;
+ $oembed['author_url']=$file_oembed->author_url;
+ $oembed['url']=$file_oembed->getUrl();
+ } elseif (substr($attachment->mimetype,0,strlen('image/'))==='image/') {
+ $oembed['type']='photo';
+ if ($attachment->filename) {
+ $filepath = File::path($attachment->filename);
+ $gis = @getimagesize($filepath);
+ if ($gis) {
+ $oembed['width'] = $gis[0];
+ $oembed['height'] = $gis[1];
+ } else {
+ // TODO Either throw an error or find a fallback?
+ }
+ }
+ $oembed['url']=$attachment->getUrl();
+ try {
+ $thumb = $attachment->getThumbnail();
+ $oembed['thumbnail_url'] = $thumb->getUrl();
+ $oembed['thumbnail_width'] = $thumb->width;
+ $oembed['thumbnail_height'] = $thumb->height;
+ unset($thumb);
+ } catch (UnsupportedMediaException $e) {
+ // No thumbnail data available
+ }
+ } else {
+ $oembed['type']='link';
+ $oembed['url']=common_local_url('attachment',
+ array('attachment' => $attachment->id));
+ }
+ if ($attachment->title) {
+ $oembed['title']=$attachment->title;
+ }
+ break;
+ default:
+ // TRANS: Server error displayed in oEmbed request when a path is not supported.
+ // TRANS: %s is a path.
+ $this->serverError(sprintf(_('"%s" not supported for oembed requests.'),$path), 501);
+ }
+ switch ($this->trimmed('format')) {
+ case 'xml':
+ $this->init_document('xml');
+ $this->elementStart('oembed');
+ foreach(array(
+ 'version', 'type', 'provider_name',
+ 'provider_url', 'title', 'author_name',
+ 'author_url', 'url', 'html', 'width',
+ 'height', 'cache_age', 'thumbnail_url',
+ 'thumbnail_width', 'thumbnail_height',
+ ) as $key) {
+ if (isset($oembed[$key]) && $oembed[$key]!='') {
+ $this->element($key, null, $oembed[$key]);
+ }
+ }
+ $this->elementEnd('oembed');
+ $this->end_document('xml');
+ break;
+
+ case 'json':
+ case null:
+ $this->init_document('json');
+ $this->raw(json_encode($oembed));
+ $this->end_document('json');
+ break;
+ default:
+ // TRANS: Error message displaying attachments. %s is a raw MIME type (eg 'image/png')
+ $this->serverError(sprintf(_('Content type %s not supported.'), $apidata['content-type']), 501);
+ }
+ } else {
+ // TRANS: Error message displaying attachments. %s is the site's base URL.
+ $this->serverError(sprintf(_('Only %s URLs over plain HTTP please.'), common_root_url()), 404);
+ }
+ }
+
+ public function init_document($type)
+ {
+ switch ($type) {
+ case 'xml':
+ header('Content-Type: application/xml; charset=utf-8');
+ $this->startXML();
+ break;
+ case 'json':
+ header('Content-Type: application/json; charset=utf-8');
+
+ // Check for JSONP callback
+ $callback = $this->arg('callback');
+ if ($callback) {
+ print $callback . '(';
+ }
+ break;
+ default:
+ // TRANS: Server error displayed in oEmbed action when request specifies an unsupported data format.
+ $this->serverError(_('Not a supported data format.'), 501);
+ break;
+ }
+ }
+
+ public function end_document($type)
+ {
+ switch ($type) {
+ case 'xml':
+ $this->endXML();
+ break;
+ case 'json':
+ // Check for JSONP callback
+ $callback = $this->arg('callback');
+ if ($callback) {
+ print ')';
+ }
+ break;
+ default:
+ // TRANS: Server error displayed in oEmbed action when request specifies an unsupported data format.
+ $this->serverError(_('Not a supported data format.'), 501);
+ break;
+ }
+ return;
+ }
+
+ /**
+ * Is this action read-only?
+ *
+ * @param array $args other arguments
+ *
+ * @return boolean is read only action?
+ */
+ function isReadOnly($args)
+ {
+ return true;
+ }
+}
diff --git a/classes/File_oembed.php b/plugins/Oembed/classes/File_oembed.php
similarity index 100%
rename from classes/File_oembed.php
rename to plugins/Oembed/classes/File_oembed.php
diff --git a/lib/oembedhelper.php b/plugins/Oembed/lib/oembedhelper.php
similarity index 100%
rename from lib/oembedhelper.php
rename to plugins/Oembed/lib/oembedhelper.php
diff --git a/scripts/fixup_files.php b/plugins/Oembed/scripts/fixup_files.php
similarity index 89%
rename from scripts/fixup_files.php
rename to plugins/Oembed/scripts/fixup_files.php
index 18feaf2218..50ddc8a994 100755
--- a/scripts/fixup_files.php
+++ b/plugins/Oembed/scripts/fixup_files.php
@@ -18,7 +18,7 @@
* along with this program. If not, see .
*/
-define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
+define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));
$longoptions = array('dry-run');
@@ -62,11 +62,8 @@ while ($f->fetch()) {
$f->decache();
if (is_array($data)) {
- if ($f->saveOembed($data, $f->url)) {
- echo " (ok)\n";
- } else {
- echo " (ok, no embedding data)\n";
- }
+ Event::handle('EndFileSaveNew', array($f, $data, $f->url));
+ echo " (ok)\n";
} else {
echo " (ok, but embedding lookup failed)\n";
}
diff --git a/tests/oEmbedTest.php b/plugins/Oembed/tests/oEmbedTest.php
similarity index 98%
rename from tests/oEmbedTest.php
rename to plugins/Oembed/tests/oEmbedTest.php
index 50f3fd2919..49e070cb6d 100644
--- a/tests/oEmbedTest.php
+++ b/plugins/Oembed/tests/oEmbedTest.php
@@ -5,7 +5,7 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
exit();
}
-define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
+define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));
define('GNUSOCIAL', true);
define('STATUSNET', true); // compatibility