Moved oEmbed stuff out to a plugin (Oembed).
This commit is contained in:
parent
b0c4e8fc3d
commit
1776c90cb9
17
CONFIGURE
17
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 <link> 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
|
||||
------
|
||||
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -1,244 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* StatusNet-only extensions to the Twitter-like API
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @category Twitter
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @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 <candrews@integralblue.com>
|
||||
* @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;
|
||||
}
|
||||
}
|
@ -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',
|
||||
|
@ -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
|
||||
@ -395,31 +359,7 @@ class File extends Managed_DataObject
|
||||
$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;
|
||||
}
|
||||
Event::handle('FileEnclosureMetadata', array($file, &$enclosure));
|
||||
}
|
||||
}
|
||||
return $enclosure;
|
||||
|
@ -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);
|
||||
|
@ -67,7 +67,6 @@ $classes = array('Schema_version',
|
||||
'Group_inbox',
|
||||
'Group_member',
|
||||
'File',
|
||||
'File_oembed',
|
||||
'File_redirection',
|
||||
'File_thumbnail',
|
||||
'File_to_post',
|
||||
|
@ -166,6 +166,11 @@ class Action extends HTMLOutputter // lawsuit
|
||||
return $this->scoped;
|
||||
}
|
||||
|
||||
public function getActionName()
|
||||
{
|
||||
return $this->action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show page, a template method.
|
||||
*
|
||||
|
@ -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,6 +225,7 @@ class AttachmentListItem extends Widget
|
||||
class Attachment extends AttachmentListItem
|
||||
{
|
||||
function showLink() {
|
||||
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');
|
||||
@ -247,31 +235,9 @@ class Attachment extends AttachmentListItem
|
||||
$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);
|
||||
}
|
||||
}
|
||||
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':
|
||||
|
@ -303,6 +303,7 @@ $default =
|
||||
'ClientSideShorten' => array(),
|
||||
'EmailAuthentication' => array(),
|
||||
'Event' => array(),
|
||||
'Oembed' => array(),
|
||||
'OpenID' => array(),
|
||||
'Poll' => array(),
|
||||
'QnA' => array(),
|
||||
|
@ -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'));
|
||||
|
||||
|
1
plugins/Bookmark/README
Normal file
1
plugins/Bookmark/README
Normal file
@ -0,0 +1 @@
|
||||
Depends on the oEmbed plugin (Oembed).
|
1
plugins/LinkPreview/README
Normal file
1
plugins/LinkPreview/README
Normal file
@ -0,0 +1 @@
|
||||
Depends on the oEmbed plugin (Oembed)
|
18
plugins/Oembed/CONFIGURE
Normal file
18
plugins/Oembed/CONFIGURE
Normal file
@ -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 <link> 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.
|
187
plugins/Oembed/OembedPlugin.php
Normal file
187
plugins/Oembed/OembedPlugin.php
Normal file
@ -0,0 +1,187 @@
|
||||
<?php
|
||||
|
||||
class OembedPlugin extends Plugin
|
||||
{
|
||||
public function onCheckSchema()
|
||||
{
|
||||
$schema = Schema::get();
|
||||
$schema->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;
|
||||
}
|
||||
}
|
1
plugins/Oembed/README
Normal file
1
plugins/Oembed/README
Normal file
@ -0,0 +1 @@
|
||||
It's really called oEmbed.
|
236
plugins/Oembed/actions/oembed.php
Normal file
236
plugins/Oembed/actions/oembed.php
Normal file
@ -0,0 +1,236 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* oEmbed data action for /main/oembed(.xml|.json) requests
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
||||
|
||||
/**
|
||||
* Oembed provider implementation
|
||||
*
|
||||
* This class handles all /main/oembed(.xml|.json)/ requests.
|
||||
*
|
||||
* @category oEmbed
|
||||
* @package GNUsocial
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @author Mikael Nordfeldth <mmn@hethane.se>
|
||||
* @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;
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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)) {
|
||||
Event::handle('EndFileSaveNew', array($f, $data, $f->url));
|
||||
echo " (ok)\n";
|
||||
} else {
|
||||
echo " (ok, no embedding data)\n";
|
||||
}
|
||||
} else {
|
||||
echo " (ok, but embedding lookup failed)\n";
|
||||
}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user