1268 lines
55 KiB
PHP
1268 lines
55 KiB
PHP
<?php # $Id$
|
|
|
|
if (IN_serendipity !== true) {
|
|
die ("Don't hack!");
|
|
}
|
|
|
|
|
|
// Probe for a language include with constants. Still include defines later on, if some constants were missing
|
|
$probelang = dirname(__FILE__) . '/' . $serendipity['charset'] . 'lang_' . $serendipity['lang'] . '.inc.php';
|
|
if (file_exists($probelang)) {
|
|
include $probelang;
|
|
}
|
|
|
|
include_once dirname(__FILE__) . '/lang_en.inc.php';
|
|
include_once dirname(__FILE__) . '/podcast_player.php';
|
|
|
|
@define("SERENDIPITY_EVENT_PODCAST_VERSION", "1.37");
|
|
|
|
class serendipity_event_podcast extends serendipity_event {
|
|
/**
|
|
The Serendipity Podcasting Plugin
|
|
|
|
@author Hannes Gassert <hannes@mediagonal.ch>
|
|
@package serendipity
|
|
@version $Id$
|
|
class serendipity_event_podcast extends serendipity_event{
|
|
**/
|
|
var $title = PLUGIN_PODCAST_NAME;
|
|
|
|
// Array of extensions => shorttype filled by configuration
|
|
var $supportedFiletypes = null;
|
|
// Array of shorttype => player filled by configuration
|
|
var $supportedPlayers = null;
|
|
|
|
// Array of fileurls replaced with player code
|
|
var $playerUrlsAdded = array();
|
|
|
|
// Enable debug messages?
|
|
var $debug = false;
|
|
|
|
/**
|
|
@access public
|
|
*/
|
|
function introspect(&$propbag)
|
|
{
|
|
|
|
$events = array(
|
|
'frontend_display:rss-1.0:per_entry' => true,
|
|
'frontend_display:rss-2.0:per_entry' => true,
|
|
'frontend_display:rss-1.0:namespace' => true,
|
|
'frontend_display:rss-2.0:namespace' => true,
|
|
'frontend_display' => true,
|
|
'frontend_header' => true,
|
|
'css' => true
|
|
);
|
|
|
|
$propbag->add('name', PLUGIN_PODCAST_NAME);
|
|
$propbag->add('description', PLUGIN_PODCAST_DESC);
|
|
$propbag->add('stackable', false);
|
|
$propbag->add('license', 'GPL');
|
|
|
|
$propbag->add('cachable_events', $events);
|
|
$propbag->add('event_hooks', $events);
|
|
$propbag->add('configuration', array(
|
|
'info',
|
|
|
|
'easy',
|
|
'use_player',
|
|
'automatic_size',
|
|
'width',
|
|
'height',
|
|
'align',
|
|
'firstmedia_only',
|
|
'nopodcasting_class',
|
|
'epheader',
|
|
'extendet_enclosure_attributes',
|
|
'extendet_enclosure_position',
|
|
'ep_automatic_size',
|
|
'ep_align',
|
|
'ep_asure_enc',
|
|
|
|
'mergemulti',
|
|
'downloadlink',
|
|
|
|
'expert',
|
|
|
|
'itunes_meta',
|
|
|
|
/* players */
|
|
'extflow',
|
|
'extflow_player',
|
|
|
|
'extquicktime',
|
|
'extquicktime_player',
|
|
|
|
'extwinmedia',
|
|
'extwinmedia_player',
|
|
|
|
'extflash',
|
|
'extflash_player',
|
|
|
|
'extxspf',
|
|
'extxspf_player',
|
|
|
|
'extaudio',
|
|
'extaudio_player',
|
|
|
|
'exthtml5_audio',
|
|
'exthtml5_audio_player',
|
|
|
|
'exthtml5_video',
|
|
'exthtml5_video_player',
|
|
|
|
/* exotic options */
|
|
'use_cache',
|
|
'plugin_http_path'
|
|
));
|
|
|
|
$propbag->add('author', 'Grischa Brockhaus, Hannes Gassert, Garvin Hicking');
|
|
$propbag->add('version', SERENDIPITY_EVENT_PODCAST_VERSION);
|
|
$propbag->add('requirements', array(
|
|
'serendipity' => '0.7',
|
|
'smarty' => '2.6.7',
|
|
'php' => '4.1.0'
|
|
));
|
|
$propbag->add('groups', array('BACKEND_EDITOR'));
|
|
}
|
|
|
|
/**
|
|
@access public
|
|
*/
|
|
function introspect_config_item($name, &$propbag) {
|
|
global $serendipity;
|
|
switch($name) {
|
|
case 'info':
|
|
$propbag->add('type', 'content');
|
|
$propbag->add('default', nl2br(htmlspecialchars(PLUGIN_PODCAST_USAGE) . "\n" . PLUGIN_PODCAST_USAGE_RSS));
|
|
break;
|
|
|
|
case 'easy':
|
|
$propbag->add('type', 'content');
|
|
$propbag->add('default', nl2br(PLUGIN_PODCAST_EASY));
|
|
break;
|
|
|
|
case 'expert':
|
|
$propbag->add('type', 'content');
|
|
$propbag->add('default', nl2br(PLUGIN_PODCAST_EXPERT . "\n" . PLUGIN_PODCAST_EXPERT_HINT));
|
|
break;
|
|
|
|
case 'epheader':
|
|
$propbag->add('type', 'content');
|
|
$propbag->add('default', nl2br(PLUGIN_PODCAST_EXTATTRSETTINGS));
|
|
break;
|
|
|
|
case 'seperator':
|
|
$propbag->add('type', 'seperator');
|
|
break;
|
|
|
|
case 'use_player':
|
|
$propbag->add('type', 'boolean');
|
|
$propbag->add('name', PLUGIN_PODCAST_USEPLAYER);
|
|
$propbag->add('description', '');
|
|
$propbag->add('default', 'true');
|
|
break;
|
|
|
|
case 'automatic_size':
|
|
$propbag->add('type', 'boolean');
|
|
$propbag->add('name', PLUGIN_PODCAST_AUTOSIZE);
|
|
$propbag->add('description', PLUGIN_PODCAST_AUTOSIZE_DESC);
|
|
$propbag->add('default', 'false');
|
|
break;
|
|
|
|
case 'mergemulti':
|
|
$propbag->add('type', 'boolean');
|
|
$propbag->add('name', PLUGIN_PODCAST_MERGEMULTI);
|
|
$propbag->add('description', '');
|
|
$propbag->add('default', 'true');
|
|
break;
|
|
|
|
case 'downloadlink':
|
|
$propbag->add('type', 'boolean');
|
|
$propbag->add('name', PLUGIN_PODCAST_DOWNLOADLINK);
|
|
$propbag->add('description', PLUGIN_PODCAST_DOWNLOADLINK_DESC);
|
|
$propbag->add('default', 'true');
|
|
break;
|
|
|
|
case 'ep_automatic_size':
|
|
$propbag->add('type', 'boolean');
|
|
$propbag->add('name', PLUGIN_PODCAST_AUTOSIZE);
|
|
$propbag->add('description', PLUGIN_PODCAST_AUTOSIZE_DESC);
|
|
$propbag->add('default', 'false');
|
|
break;
|
|
|
|
case 'width':
|
|
$propbag->add('type', 'string');
|
|
$propbag->add('name', PLUGIN_PODCAST_WIDTH);
|
|
$propbag->add('description', PLUGIN_PODCAST_WIDTH_DESC);
|
|
$propbag->add('default', '200');
|
|
break;
|
|
|
|
case 'height':
|
|
$propbag->add('type', 'string');
|
|
$propbag->add('name', PLUGIN_PODCAST_HEIGHT);
|
|
$propbag->add('description', PLUGIN_PODCAST_HEIGHT_DESC);
|
|
$propbag->add('default', '200');
|
|
break;
|
|
|
|
case 'align':
|
|
$propbag->add('type', 'select');
|
|
$propbag->add('name', PLUGIN_PODCAST_ALIGN);
|
|
$propbag->add('description', PLUGIN_PODCAST_ALIGN_DESC);
|
|
$propbag->add('select_values', $this->GetAlignOptionsArray());
|
|
$propbag->add('default', 'left');
|
|
break;
|
|
case 'nopodcasting_class':
|
|
$propbag->add('type', 'string');
|
|
$propbag->add('name', PLUGIN_PODCAST_NOPODCASTING_CLASS);
|
|
$propbag->add('description', PLUGIN_PODCAST_NOPODCASTING_CLASS_DESC);
|
|
$propbag->add('default', 'nopodcast');
|
|
break;
|
|
|
|
case 'firstmedia_only':
|
|
$propbag->add('type', 'boolean');
|
|
$propbag->add('name', PLUGIN_PODCAST_FIRSTMEDIAONLY);
|
|
$propbag->add('description', PLUGIN_PODCAST_FIRSTMEDIAONLY_DESC);
|
|
$propbag->add('default', 'false');
|
|
break;
|
|
|
|
case 'ep_align':
|
|
$propbag->add('type', 'select');
|
|
$propbag->add('name', PLUGIN_PODCAST_ALIGN);
|
|
$propbag->add('description', PLUGIN_PODCAST_ALIGN_DESC);
|
|
$propbag->add('select_values', $this->GetAlignOptionsArray());
|
|
$propbag->add('default', 'center');
|
|
break;
|
|
|
|
case 'extendet_enclosure_attributes':
|
|
$propbag->add('type', 'string');
|
|
$propbag->add('name', PLUGIN_PODCAST_EXTATTR);
|
|
$propbag->add('description', PLUGIN_PODCAST_EXTATTR_DESC);
|
|
$propbag->add('default', 'Podcast,Video');
|
|
break;
|
|
|
|
case 'extendet_enclosure_position':
|
|
$positions = array(
|
|
'none' => PLUGIN_PODCAST_EXTPOS_NONE,
|
|
'body_top' => PLUGIN_PODCAST_EXTPOS_BT,
|
|
'body_botton' => PLUGIN_PODCAST_EXTPOS_BB,
|
|
'ext_top' => PLUGIN_PODCAST_EXTPOS_ET,
|
|
'ext_botton' => PLUGIN_PODCAST_EXTPOS_EB,
|
|
);
|
|
$propbag->add('type', 'select');
|
|
$propbag->add('name', PLUGIN_PODCAST_EXTPOS);
|
|
$propbag->add('description', PLUGIN_PODCAST_EXTPOS_DESC);
|
|
$propbag->add('select_values', $positions);
|
|
$propbag->add('default', 'none');
|
|
break;
|
|
|
|
case 'ep_asure_enc':
|
|
$propbag->add('type', 'boolean');
|
|
$propbag->add('name', PLUGIN_PODCAST_ASURE_FEEDENC);
|
|
$propbag->add('description', PLUGIN_PODCAST_ASURE_FEEDEENC_DESC);
|
|
$propbag->add('default', 'true');
|
|
break;
|
|
|
|
/* PLAYERS */
|
|
case 'extflow':
|
|
$propbag->add('type', 'string');
|
|
$propbag->add('name', PLUGIN_PODCAST_FLOWEXT);
|
|
$propbag->add('description', PLUGIN_PODCAST_FLOWEXT_DESC);
|
|
$propbag->add('default', PLUGIN_PODCAST_FLOWEXT_DEFAULT);
|
|
break;
|
|
|
|
case 'exthtml5_audio':
|
|
$propbag->add('type', 'string');
|
|
$propbag->add('name', PLUGIN_PODCAST_HTML5_AUDIO);
|
|
$propbag->add('description', PLUGIN_PODCAST_HTML5_AUDIO_DESC);
|
|
$propbag->add('default', PLUGIN_PODCAST_HTML5_AUDIO_DEFAULT);
|
|
break;
|
|
|
|
case 'exthtml5_video':
|
|
$propbag->add('type', 'string');
|
|
$propbag->add('name', PLUGIN_PODCAST_HTML5_VIDEO);
|
|
$propbag->add('description', PLUGIN_PODCAST_HTML5_VIDEO_DESC);
|
|
$propbag->add('default', PLUGIN_PODCAST_HTML5_VIDEO_DEFAULT);
|
|
break;
|
|
|
|
case 'extquicktime':
|
|
$propbag->add('type', 'string');
|
|
$propbag->add('name', PLUGIN_PODCAST_QTEXT);
|
|
$propbag->add('description', PLUGIN_PODCAST_QTEXT_DESC);
|
|
$propbag->add('default', PLUGIN_PODCAST_QTEXT_DEFAULT);
|
|
break;
|
|
|
|
case 'extwinmedia':
|
|
$propbag->add('type', 'string');
|
|
$propbag->add('name', PLUGIN_PODCAST_WMEXT);
|
|
$propbag->add('description', PLUGIN_PODCAST_WMEXT_DESC);
|
|
$propbag->add('default', PLUGIN_PODCAST_WMEXT_DEFAULT);
|
|
break;
|
|
|
|
case 'extflash':
|
|
$propbag->add('type', 'string');
|
|
$propbag->add('name', PLUGIN_PODCAST_MFEXT);
|
|
$propbag->add('description', PLUGIN_PODCAST_MFEXT_DESC);
|
|
$propbag->add('default', PLUGIN_PODCAST_MFEXT_DEFAULT);
|
|
break;
|
|
|
|
case 'extxspf':
|
|
$propbag->add('type', 'string');
|
|
$propbag->add('name', PLUGIN_PODCAST_XSPFEXT);
|
|
$propbag->add('description', PLUGIN_PODCAST_XSPFEXT_DESC);
|
|
$propbag->add('default', PLUGIN_PODCAST_XSPFEXT_DEFAULT);
|
|
break;
|
|
|
|
case 'extaudio':
|
|
$propbag->add('type', 'string');
|
|
$propbag->add('name', PLUGIN_PODCAST_AUEXT);
|
|
$propbag->add('description', PLUGIN_PODCAST_AUEXT_DESC);
|
|
$propbag->add('default', PLUGIN_PODCAST_AUEXT_DEFAULT);
|
|
break;
|
|
|
|
|
|
|
|
case 'extflow_player':
|
|
$propbag->add('type', 'text');
|
|
$propbag->add('name', PLUGIN_PODCAST_FLOWEXT_HTML);
|
|
$propbag->add('description', '');
|
|
$propbag->add('default', PLUGIN_PODCAST_FLOWPLAYER);
|
|
break;
|
|
|
|
case 'exthtml5_audio_player':
|
|
$propbag->add('type', 'text');
|
|
$propbag->add('name', PLUGIN_PODCAST_HTML5_AUDIO_HTML);
|
|
$propbag->add('description', '');
|
|
$propbag->add('default', PLUGIN_PODCAST_HTML5_AUDIOPLAYER);
|
|
break;
|
|
|
|
case 'exthtml5_video_player':
|
|
$propbag->add('type', 'text');
|
|
$propbag->add('name', PLUGIN_PODCAST_HTML5_VIDEO_HTML);
|
|
$propbag->add('description', '');
|
|
$propbag->add('default', PLUGIN_PODCAST_HTML5_VIDEOPLAYER);
|
|
break;
|
|
|
|
case 'extquicktime_player':
|
|
$propbag->add('type', 'text');
|
|
$propbag->add('name', PLUGIN_PODCAST_QTEXT_HTML);
|
|
$propbag->add('description', '');
|
|
$propbag->add('default', PLUGIN_PODCAST_QUICKTIMEPLAYER);
|
|
break;
|
|
|
|
case 'extwinmedia_player':
|
|
$propbag->add('type', 'text');
|
|
$propbag->add('name', PLUGIN_PODCAST_WMEXT_HTML);
|
|
$propbag->add('description', '');
|
|
$propbag->add('default', PLUGIN_PODCAST_WMPLAYER);
|
|
break;
|
|
|
|
case 'extflash_player':
|
|
$propbag->add('type', 'text');
|
|
$propbag->add('name', PLUGIN_PODCAST_MFEXT_HTML);
|
|
$propbag->add('description', '');
|
|
$propbag->add('default', PLUGIN_PODCAST_FLASHPLAYER);
|
|
break;
|
|
|
|
case 'extxspf_player':
|
|
$propbag->add('type', 'text');
|
|
$propbag->add('name', PLUGIN_PODCAST_XSPFEXT_HTML);
|
|
$propbag->add('description', '');
|
|
$propbag->add('default', PLUGIN_PODCAST_XSPFPLAYER);
|
|
break;
|
|
|
|
case 'extaudio_player':
|
|
$propbag->add('type', 'text');
|
|
$propbag->add('name', PLUGIN_PODCAST_AUEXT_HTML);
|
|
$propbag->add('description', '');
|
|
$propbag->add('default', PLUGIN_PODCAST_MP3PLAYER);
|
|
break;
|
|
|
|
|
|
/* exotic */
|
|
case 'use_cache':
|
|
$propbag->add('type', 'boolean');
|
|
$propbag->add('name', PLUGIN_PODCAST_USECACHE);
|
|
$propbag->add('description', PLUGIN_PODCAST_USECACHE_DESC);
|
|
$propbag->add('default', 'true');
|
|
break;
|
|
|
|
case 'itunes_meta':
|
|
$propbag->add('type', 'text');
|
|
$propbag->add('name', PLUGIN_PODCAST_ITUNES);
|
|
$propbag->add('description', PLUGIN_PODCAST_ITUNES_DESC);
|
|
$propbag->add('default', "
|
|
|
|
<itunes:subtitle>" . htmlspecialchars($serendipity['blogTitle']) . "</itunes:subtitle>
|
|
<itunes:author>" . htmlspecialchars($serendipity['blogTitle']) . "</itunes:author>
|
|
<itunes:summary>" . htmlspecialchars($serendipity['blogDescription']) . "</itunes:summary>
|
|
<itunes:image href=\"" . $serendipity['baseURL'] . "itunes.jpg\" />
|
|
<itunes:category text=\"Technology\" />
|
|
");
|
|
break;
|
|
|
|
case 'plugin_http_path':
|
|
$propbag->add('type', 'string');
|
|
$propbag->add('name', PLUGIN_PODCAST_HTTPREL);
|
|
$propbag->add('description', PLUGIN_PODCAST_HTTPREL_DESC);
|
|
$propbag->add('default', $serendipity['serendipityHTTPPath'] . 'plugins/serendipity_event_podcast');
|
|
break;
|
|
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function iTunify(&$eventData) {
|
|
$eventData['per_entry_display_dat'] .= '<itunes:author>' . htmlspecialchars($eventData['author']) . '</itunes:author>' . "\n";
|
|
$eventData['per_entry_display_dat'] .= '<itunes:subtitle>' . htmlspecialchars($eventData['title']) . '</itunes:subtitle>' . "\n";
|
|
$eventData['per_entry_display_dat'] .= '<itunes:summary>' . htmlspecialchars(strip_tags($eventData['feed_body'])) . '</itunes:summary>' . "\n";
|
|
}
|
|
|
|
/**
|
|
@access public
|
|
*/
|
|
function event_hook($event, &$bag, &$eventData, $addData = null){
|
|
global $serendipity;
|
|
static $use_player = null;
|
|
static $firstmedia_only = null;
|
|
static $patterns = null;
|
|
|
|
$this->log("EventHook: " . $event);
|
|
|
|
$this->InitializeSupportedFiletypes();
|
|
|
|
if ($patterns == null) {
|
|
//yes indeed, we wont find links like "download.php?file=rock.mp3&foo=bar"
|
|
$patterns = array(
|
|
//'mediaLinkPattern' => '@href\s*=\s*(\'|")([^>]+\.(' . implode('|', array_keys($this->supportedFiletypes)) . '))\1@Usie',
|
|
|
|
'playerRewritePattern' => '@<a\s+[^>]*?href\s*=\s*(\'|")([^\'"]+\.('
|
|
. implode('|', array_keys($this->supportedFiletypes))
|
|
. '))\1[^>]*?>.*?</a>@si', //won't match nested tags, like <a .. <b>.. </b></a>. but that's ugly anyway.
|
|
|
|
'embeddedObjectPattern' => '@<embed[^>]*?src="([^"]*?)"[^>]*?>@Usi',
|
|
'podcastLinkPattern' => '@\[podcast:\s*(href\s*=\s*)?(("|\'|")(.+)("|\'|"))(\s+mediaType\s*=\s*(.+))?\]@Usi'
|
|
);
|
|
}
|
|
|
|
if ($use_player === null) {
|
|
$use_player = serendipity_db_bool($this->get_config('use_player', 'true'));
|
|
}
|
|
if ($firstmedia_only === null) {
|
|
$firstmedia_only = serendipity_db_bool($this->get_config('firstmedia_only', 'false'));
|
|
}
|
|
|
|
switch ($event) {
|
|
//////////////////////// Add Javascript for JW FLV Player ////////////////////////
|
|
case 'frontend_header':
|
|
case 'backend_header':
|
|
echo '<script type="text/javascript" src="' . $this->GetPluginHttpPath() . '/player/flowplayer/example/flowplayer-3.2.6.min.js"></script>' . "\n";
|
|
$this->log("Init\n--------------------------------------------------------------------------------------\n");
|
|
break;
|
|
|
|
//////////////////////// RSS Entries ////////////////////////
|
|
case 'frontend_display:rss-2.0:per_entry':
|
|
case 'frontend_display:rss-1.0:per_entry':
|
|
case 'frontend_display:atom-1.0:per_entry':
|
|
|
|
$this->log("Feed creation");
|
|
$addedEnclosures[] = "enclosures";
|
|
|
|
// Search for all embedded objects and make the RSS enclosured.
|
|
// RSS only displays body always. In fullview, body contains body + extended here.
|
|
// In "small" view only embed the media beeing part of the small view.
|
|
// In short: body only always!
|
|
$matchSource = $eventData['body'];
|
|
|
|
// Remove our own players first, they are matched using $eventData['podcastUrlsRewrittenByPlayerCode']
|
|
$this->log("Removing podcast players");
|
|
$eventData['feed_body'] = preg_replace(
|
|
'@<!-- podcastplayerstart -->.*?<!-- podcastplayerend -->@si',
|
|
'',
|
|
$eventData['feed_body']);
|
|
|
|
// urls rewritten by player code
|
|
$this->log("Matching URLs set by extended attributes. Isset=" . isset($eventData['podcastUrlsRewrittenByPlayerCode']));
|
|
if (isset($eventData['podcastUrlsRewrittenByPlayerCode']) && is_array($eventData['podcastUrlsRewrittenByPlayerCode'])) {
|
|
$this->log("Matching URLs set by extended attributes: FOUND");
|
|
$urlsRewwrittenByPlayerCode = $eventData['podcastUrlsRewrittenByPlayerCode'];
|
|
foreach ($urlsRewwrittenByPlayerCode as $url) {
|
|
$fileInfo = $this->GetFileInfo($url);
|
|
$type = $fileInfo['mime'];
|
|
$enclosure = $this->GetEnclosure($event, $url, $type, $fileInfo['length'], $fileInfo['md5']);
|
|
|
|
if (!empty($enclosure)) {
|
|
$this->iTunify($eventData, $enclosure);
|
|
if (empty($addedEnclosures[$enclosure])) {
|
|
$eventData['display_dat'] .= $enclosure;
|
|
if ($firstmedia_only) return true;
|
|
}
|
|
$addedEnclosures[$enclosure] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// match the Embed-Syntax added manualy by user
|
|
$this->log("Matching embeddedObjectPattern");
|
|
if (preg_match_all($patterns['embeddedObjectPattern'], $matchSource, $matches)) {
|
|
for ($i = 0, $maxi = count($matches[1]); $i < $maxi; $i++){
|
|
$url = $matches[1][$i];
|
|
$fileInfo = $this->GetFileInfo($url);
|
|
$type = $fileInfo['mime'];
|
|
$enclosure = $this->GetEnclosure($event, $url, $type, $fileInfo['length'], $fileInfo['md5']);
|
|
|
|
if (!empty($enclosure)) {
|
|
$this->iTunify($eventData, $enclosure);
|
|
if (empty($addedEnclosures[$enclosure])) {
|
|
$eventData['display_dat'] .= $enclosure;
|
|
if ($firstmedia_only) return true;
|
|
}
|
|
$addedEnclosures[$enclosure] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Match the old style [podcast] syntax as well
|
|
$this->log("Matching podcastLinkPattern");
|
|
if (preg_match_all($patterns['podcastLinkPattern'], $matchSource, $matches)) {
|
|
for ($i = 0, $maxi = count($matches[1]); $i < $maxi; $i++){
|
|
$url = $matches[4][$i];
|
|
$fileInfo = $this->GetFileInfo($url);
|
|
if (!empty($matches[7][$i])) {
|
|
$type = $matches[7][$i];
|
|
} else {
|
|
$type = $fileInfo['mime'];
|
|
}
|
|
$enclosure = $this->GetEnclosure($event, $url, $type, $fileInfo['length'], $fileInfo['md5']);
|
|
|
|
if (!empty($enclosure)) {
|
|
$this->iTunify($eventData, $enclosure);
|
|
if (empty($addedEnclosures[$enclosure])) {
|
|
$eventData['display_dat'] .= $enclosure;
|
|
if ($firstmedia_only) return true;
|
|
}
|
|
$addedEnclosures[$enclosure] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Last, also match the '<a href>' style, if "use_player" is disabled and thus no <embed> might exist.
|
|
$this->log("Matching playerRewritePattern");
|
|
$nopodcasting_class = $this->get_config('nopodcasting_class','nopodcast');
|
|
if (!empty($nopodcasting_class)) {
|
|
$classPattern = '@class\s*=\s*(\'|")\s*' . $nopodcasting_class . '\s*(\'|")+@si';
|
|
}
|
|
|
|
if (!$use_player && preg_match_all($patterns['playerRewritePattern'], $matchSource, $matches)) {
|
|
for ($i = 0, $maxi = count($matches[1]); $i < $maxi; $i++){
|
|
$complete = $matches[0];
|
|
if (!empty($nopodcasting_class) && preg_match($classPattern, $complete)) {
|
|
$this->log("NoPodcasting class found!");
|
|
continue;
|
|
}
|
|
else {
|
|
$this->log("NoPodcasting class not found! [" . $classPattern . "]");
|
|
}
|
|
$url = $matches[2][$i];
|
|
$fileInfo = $this->GetFileInfo($url);
|
|
$type = $fileInfo['mime'];
|
|
$enclosure = $this->GetEnclosure($event, $url, $type, $fileInfo['length'], $fileInfo['md5']);
|
|
|
|
if (!empty($enclosure)) {
|
|
$this->iTunify($eventData, $enclosure);
|
|
if (empty($addedEnclosures[$enclosure])) {
|
|
$eventData['display_dat'] .= $enclosure;
|
|
if ($firstmedia_only) return true;
|
|
}
|
|
$addedEnclosures[$enclosure] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Check, if podcasts are added via the extended article attribute and make it enclosured if not already embedded, too:
|
|
if (serendipity_db_bool($this->get_config('ep_asure_enc', 'true'))) {
|
|
$extended_attributes = explode(',',$this->get_config('extendet_enclosure_attributes','Podcast,Video'));
|
|
|
|
foreach ($extended_attributes as $eattr) {
|
|
$this->log("EP: " . trim($eattr));
|
|
$eattr = "ep_" . trim($eattr);
|
|
if (!empty($eattr) && !empty($eventData['properties'][$eattr])) {
|
|
$fileInfo = $this->GetFileInfo($eventData['properties'][$eattr]);
|
|
$type = $fileInfo['mime'];
|
|
$fileUrl = str_replace(' ','%20',$eventData['properties'][$eattr]);
|
|
$enclosure = $this->GetEnclosure($event, $this->GetHostUrl() . htmlspecialchars($fileUrl), $type, $fileInfo['length'], $fileInfo['md5']);
|
|
|
|
if (!empty($enclosure)) {
|
|
$this->iTunify($eventData, $enclosure);
|
|
if (empty($addedEnclosures[$enclosure])) {
|
|
$eventData['display_dat'] .= $enclosure;
|
|
if ($firstmedia_only) return true;
|
|
}
|
|
$addedEnclosures[$enclosure] = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// A RSS feet doesn't need the object tags (they are embedded now). So remove them:
|
|
$eventData['feed_body'] = preg_replace(
|
|
'@<object .*?</object>@si',
|
|
'',
|
|
$eventData['feed_body']);
|
|
|
|
// Purely embedded objects are RSS enclosured now too, so we can remove them if still there:
|
|
$eventData['feed_body'] = preg_replace(
|
|
'@<embed .*?</embed>@si',
|
|
'',
|
|
$eventData['feed_body']);
|
|
|
|
return true;
|
|
|
|
case 'css':
|
|
if (!strpos($eventData, '.podcastplayer')) {
|
|
echo '.podcastplayer { display: block; }' . "\n";
|
|
echo '.podcastdownload { display: block; }' . "\n";
|
|
}
|
|
return true;
|
|
|
|
|
|
|
|
//////////////////////// RSS 1 NS /////////////////////////////
|
|
case 'frontend_display:rss-1.0:namespace':
|
|
|
|
$eventData['display_dat'] .= " xmlns:enc='http://purl.oclc.org/net/rss_2.0/enc#'\n";
|
|
$eventData['display_dat'] .= " xmlns:podcast='http://ipodder.sourceforge.net/docs/podcast.html'\n";
|
|
$eventData['display_dat'] .= " xmlns:atom=\"http://www.w3.org/2005/Atom\"\n";
|
|
$eventData['display_dat'] .= " xmlns:sc=\"http://podlove.org/simple-chapters\"\n";
|
|
|
|
return true;
|
|
|
|
//////////////////////// RSS 2 NS///// ////////////////////////
|
|
case 'frontend_display:rss-2.0:namespace':
|
|
|
|
$eventData['display_dat'] .= " xmlns:itunes=\"http://www.itunes.com/dtds/podcast-1.0.dtd\"\n";
|
|
$eventData['display_dat'] .= " xmlns:atom=\"http://www.w3.org/2005/Atom\"\n";
|
|
$eventData['display_dat'] .= " xmlns:sc=\"http://podlove.org/simple-chapters\"\n";
|
|
|
|
|
|
if (version_compare(preg_replace('@[^0-9\.]@', '', $serendipity['version']), '1.6', '<')) {
|
|
} else {
|
|
$eventData['channel_dat'] .= $this->get_config('itunes_meta');
|
|
}
|
|
//$eventData['display_dat'] .= " xmlns:podcast='http://ipodder.sourceforge.net/docs/podcast.html'\n";
|
|
return true;
|
|
|
|
//////////////////////// HTML Entry /////////////////////////
|
|
case 'frontend_display':
|
|
|
|
if (!isset($eventData['body']) && !isset($eventData['extended'])) {
|
|
// Do not use player HTML for user comments, html nuggets, static pages etc.
|
|
return false;
|
|
break;
|
|
}
|
|
|
|
if (isset($eventData['properties']['ep_disable_markup'. $this->instance]) || isset($serendipity['POST']['properties']['disable_markup_' . $this->instance])) {
|
|
// Do not use player HTML, when the extended properties plugin disables this markup plugin.
|
|
return false;
|
|
break;
|
|
}
|
|
|
|
// Reset URL list replaced by players
|
|
$this->playerUrlsAdded = array();
|
|
|
|
// First replace old style [podcast] syntax always, even without player replacement
|
|
if (is_array($eventData)) {
|
|
if (preg_match($patterns['podcastLinkPattern'],$eventData['body'])) {
|
|
$eventData['body'] .= '<!-- old podcast style found -->';
|
|
}
|
|
$eventData['body'] = preg_replace(
|
|
$patterns['podcastLinkPattern'],
|
|
'<a href="\4">\4</a>',
|
|
$eventData['body']);
|
|
|
|
$eventData['extended'] = preg_replace(
|
|
$patterns['podcastLinkPattern'],
|
|
'<a href="\4">\4</a>',
|
|
$eventData['extended']);
|
|
}
|
|
|
|
// Now replace all links to mediafiles with the configured players:
|
|
if ($use_player && is_array($eventData)) {
|
|
$eventData['body'] = preg_replace_callback(
|
|
$patterns['playerRewritePattern'],
|
|
array( $this, "playerRewriteCallBack"),
|
|
$eventData['body']);
|
|
|
|
$eventData['extended'] = preg_replace_callback(
|
|
$patterns['playerRewritePattern'],
|
|
array( $this, "playerRewriteCallBack"),
|
|
$eventData['extended']);
|
|
}
|
|
|
|
|
|
// Check, if podcasts are added via the extended article attribute and add them to the article, if configured:
|
|
if ($this->get_config('extendet_enclosure_position','never')!='never') {
|
|
$extended_attributes = explode(',',$this->get_config('extendet_enclosure_attributes','Podcast,Video'));
|
|
$extra_links = '';
|
|
foreach ($extended_attributes as $eattr) {
|
|
$eattr = "ep_" . trim($eattr);
|
|
$ep_align= $this->get_config('ep_align','center');
|
|
if (!empty($eattr) && !empty($eventData['properties'][$eattr])) {
|
|
$fileUrl = $this->GetHostUrl() . $eventData['properties'][$eattr];
|
|
|
|
$this->log("found input in $eattr: {$eventData['properties'][$eattr]}");
|
|
$this->log("fileurl in $eattr: $fileUrl");
|
|
|
|
$fileInfo = $this->GetFileInfo($eventData['properties'][$eattr]);
|
|
|
|
$this->log("filinfo: " . print_r($fileInfo, true));
|
|
|
|
// Produce player code
|
|
if ($use_player) {
|
|
if (serendipity_db_bool($this->get_config('ep_automatic_size', 'false'))) {
|
|
$player = $this->GetPlayerByExt($fileInfo['extension'], $fileUrl, $fileInfo['width'],$fileInfo['height'], $ep_align, $fileInfo['mime']);
|
|
} else {
|
|
$player = $this->GetPlayerByExt($fileInfo['extension'], $fileUrl, null, null, $ep_align, $fileInfo['mime']);
|
|
}
|
|
} else {
|
|
$player = '<a href="' . $fileUrl . '">' . basename($eventData['properties'][$eattr]) . '</a>';
|
|
}
|
|
|
|
$extra_links .= $player;
|
|
}
|
|
}
|
|
if (!empty($extra_links)) {
|
|
switch ($this->get_config('extendet_enclosure_position','never')) {
|
|
case 'body_top':
|
|
$eventData['body'] = $extra_links . $eventData['body'];
|
|
break;
|
|
case 'body_botton':
|
|
$eventData['body'] = $eventData['body'] . $extra_links;
|
|
break;
|
|
case 'ext_top':
|
|
$eventData['extended'] = $extra_links . $eventData['extended'];
|
|
break;
|
|
case 'ext_botton':
|
|
$eventData['extended'] = $eventData['extended'] . $extra_links;
|
|
break;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remember media urls rewritten by player code for RSS feed.
|
|
if (count($this->playerUrlsAdded)>0) {
|
|
$eventData['podcastUrlsRewrittenByPlayerCode'] = $this->playerUrlsAdded;
|
|
}
|
|
|
|
$this->cleanup_html5($eventData['body']);
|
|
$this->cleanup_html5($eventData['extended']);
|
|
|
|
break;
|
|
|
|
default:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
function cleanup_html5(&$input) {
|
|
global $serendipity;
|
|
static $mergemulti = null;
|
|
|
|
if ($mergemulti === null) {
|
|
$mergemulti = serendipity_db_bool($this->get_config('mergemulti'));
|
|
}
|
|
|
|
if ($mergemulti) {
|
|
$pat = '@(<audio[^>]*>)(.+)(</audio>)@imsU';
|
|
$aparts = array();
|
|
if (preg_match_all($pat, $input, $m)) {
|
|
$is_first = true;
|
|
foreach($m[2] AS $idx => $part) {
|
|
$aparts[] = $part;
|
|
if (!$is_first) {
|
|
$input = str_replace($m[0][$idx], '', $input);
|
|
}
|
|
$is_first = false;
|
|
}
|
|
$input = preg_replace($pat, '\1 ' . implode("\n", $aparts) . ' \3', $input);
|
|
}
|
|
|
|
$pat = '@(<video[^>]*>)(.+)(</video>)@imsU';
|
|
$aparts = array();
|
|
if (preg_match_all($pat, $input, $m)) {
|
|
$is_first = true;
|
|
foreach($m[2] AS $idx => $part) {
|
|
$aparts[] = $part;
|
|
if (!$is_first) {
|
|
$input = str_replace($m[0][$idx], '', $input);
|
|
}
|
|
$is_first = false;
|
|
}
|
|
$input = preg_replace($pat, '\1 ' . implode("\n", $aparts) . ' \3', $input);
|
|
}
|
|
}
|
|
}
|
|
|
|
function playerRewriteCallBack($treffer) {
|
|
global $serendipity;
|
|
$this->log('playerRewriteCallBack: treffer=' . print_r($treffer,true));
|
|
|
|
// Check for nopodcasting class
|
|
$nopodcasting_class = $this->get_config('nopodcasting_class','nopodcast');
|
|
if (!empty($nopodcasting_class)) {
|
|
$classPattern = '@class\s*=\s*(\'|")\s*' . $nopodcasting_class . '\s*(\'|")+@si';
|
|
if (preg_match($classPattern , $treffer[0])) return $treffer[0];
|
|
}
|
|
|
|
$fileUrl = $serendipity['baseURL'] . $treffer[2];
|
|
if (serendipity_db_bool($this->get_config('automatic_size', 'false'))) {
|
|
$fileInfo = $this->GetFileInfo($treffer[2]);
|
|
return $this->GetPlayerByExt(strtolower($treffer[3]),$treffer[2], $fileInfo['width'], $fileInfo['height'], null, $fileInfo['mime']);
|
|
} else {
|
|
$fileInfo = $this->GetFileInfo($treffer[2]);
|
|
return $this->GetPlayerByExt(strtolower($treffer[3]),$treffer[2], null, null, null, $fileInfo['mime']);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Produces an array for the podcast aligning configuration
|
|
*/
|
|
function GetAlignOptionsArray() {
|
|
return array(
|
|
'left' => PLUGIN_PODCAST_ALIGN_LEFT,
|
|
'right' => PLUGIN_PODCAST_ALIGN_RIGHT,
|
|
'center' => PLUGIN_PODCAST_ALIGN_CENTER,
|
|
'noalign' => PLUGIN_PODCAST_ALIGN_NONE,
|
|
);
|
|
|
|
}
|
|
|
|
/**
|
|
* Returns the Host including http(s)://
|
|
*/
|
|
function GetHostUrl() {
|
|
return (strtolower($_SERVER['HTTPS']) == 'on' ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'];
|
|
}
|
|
|
|
/**
|
|
* Returns HTTP path of the podcast plugin
|
|
*/
|
|
function GetPluginHttpPath() {
|
|
return $this->get_config('plugin_http_path');
|
|
}
|
|
|
|
function getFileMime($ext, $fallback = '') {
|
|
$this->log("getFileMime: $ext, $fallback");
|
|
|
|
switch(strtolower($ext)) {
|
|
case 'm4a':
|
|
return 'audio/mp4';
|
|
case 'm4v':
|
|
return 'video/mp4';
|
|
case 'ogg':
|
|
return 'audio/ogg';
|
|
case 'ogv':
|
|
return 'video/ogg';
|
|
}
|
|
|
|
// fallback
|
|
if (!empty($fallback)) return $fallback;
|
|
|
|
return 'audio/' . $ext;
|
|
}
|
|
|
|
/**
|
|
* Calculates infos on the given file and returns an array containing these infos
|
|
*/
|
|
function GetFileInfo($url) {
|
|
global $serendipity;
|
|
|
|
$this->log("GetFileInfo for $url");
|
|
|
|
$fileInfo = array();
|
|
|
|
//caching metadata
|
|
$cacheOptions = array(
|
|
'lifeTime' => '2592000',
|
|
'automaticSerialization' => true,
|
|
'cacheDir' => $serendipity['serendipityPath'] . 'templates_c/'
|
|
);
|
|
|
|
if (serendipity_db_bool($this->get_config('use_cache', 'true'))) {
|
|
$this->log("GetFileInfo: Trying cached infos");
|
|
|
|
//md5 for not having strange characters in that id..
|
|
$cacheId = md5($url) . '.2';
|
|
|
|
include_once(S9Y_PEAR_PATH . "Cache/Lite.php");
|
|
|
|
$cache = new Cache_Lite($cacheOptions);
|
|
if ($fileInfo = $cache->get($cacheId)){
|
|
$this->log("GetFileInfo: Cached infos found in file $cacheId");
|
|
//return directly on cache hit
|
|
return $fileInfo;
|
|
}
|
|
}
|
|
|
|
//cache miss! -> get data, store it in cache and return.
|
|
|
|
// translate pontential relative url to absolute url
|
|
if (preg_match('@https?://@', $url)) $absolute_url = $url;
|
|
else $absolute_url = $this->GetHostUrl() . $url;
|
|
|
|
if ($this->debug) $fileInfo['absolute_url'] = $absolute_url;
|
|
|
|
// Now remove configured base URL
|
|
$rel_path = str_replace($serendipity['baseURL'], "", $absolute_url);
|
|
|
|
if ($this->debug) $fileInfo['rel_path'] = $rel_path;
|
|
|
|
// do we have a local file here?
|
|
//$localMediaFile = $serendipity['serendipityPath'] . $urlParts['path'];
|
|
$localMediaFile = $serendipity['serendipityPath'] . $rel_path;
|
|
|
|
$fileInfo['localMediaFile'] = $localMediaFile;
|
|
|
|
$this->log("Absolute_url: $absolute_url - Relative: $localMediaFile");
|
|
|
|
// Remember extension of file
|
|
list($sName, $fileInfo['extension']) = serendipity_parseFileName($localMediaFile);
|
|
|
|
if (file_exists($localMediaFile)) {
|
|
$this->log("GetFileInfo: Local file exists");
|
|
$fileInfo['length'] = filesize($localMediaFile);
|
|
$fileInfo['md5'] = md5_file($localMediaFile);
|
|
$this->GetID3Infos($localMediaFile, $fileInfo);
|
|
$this->log(print_r($fileInfo,true));
|
|
// Set default
|
|
$fileInfo['mime'] = $this->getFileMime($fileInfo['extension'], $fileInfo['mime']);
|
|
}
|
|
|
|
/*
|
|
If not local: we have a problem :)
|
|
We don't want to download an external file.
|
|
First we have the problem of allow_url_fopen probably
|
|
being disabled and then we can't load the entire file
|
|
into memory, it would be too big anyway in most cases.
|
|
So best we can do is trying to see if we can send a HTTP HEAD
|
|
request and get the size that way (and MD5, if possible). Let's see if this works:
|
|
*/
|
|
elseif (preg_match('@https?://@', $url)){
|
|
include_once(S9Y_PEAR_PATH . 'HTTP/Request.php');
|
|
if (function_exists('serendipity_request_start')) {
|
|
serendipity_request_start();
|
|
}
|
|
|
|
$this->Log("Execute HTTP_Request for $url");
|
|
$http = new HTTP_Request($url);
|
|
$http->setMethod(HTTP_REQUEST_METHOD_HEAD);
|
|
|
|
if (!PEAR::isError($http->sendRequest(false))){
|
|
$fileInfo['length'] = intval($http->getResponseHeader('content-length'));
|
|
$fileInfo['md5'] = $http->getResponseHeader('content-md5'); //will return false if not present
|
|
$fileInfo['mime'] =$http->getResponseHeader('content-type');
|
|
$this->Log("Filling MIME with HTTP Header: " . print_r($fileInfo, true));
|
|
}
|
|
|
|
if (function_exists('serendipity_request_end')) {
|
|
serendipity_request_end();
|
|
}
|
|
} else { // Not found locally and no URL
|
|
$fileInfo['notfound'] = true;
|
|
}
|
|
|
|
if (serendipity_db_bool($this->get_config('use_cache', 'true'))) {
|
|
$cache->save($fileInfo , $cacheId);
|
|
}
|
|
|
|
return $fileInfo;
|
|
}
|
|
|
|
function absolve($url) {
|
|
global $serendipity;
|
|
|
|
if (!preg_match('@^https*://@', $url)) {
|
|
if ($url{0} == '/') {
|
|
$url = $this->GetHostUrl() . $url;
|
|
} else {
|
|
$url = $this->getHostUrl() . $serendipity['serendipityHTTPPath'] . $url;
|
|
}
|
|
}
|
|
|
|
return $url;
|
|
}
|
|
|
|
/**
|
|
* Creates an enclosure tag for different feed types
|
|
*/
|
|
function GetEnclosure($event, $url, $type, $length = null, $md5 = null) {
|
|
$url = str_replace(array('&',' '),array('&','%20'),$url);
|
|
$url = $this->absolve($url);
|
|
|
|
preg_match('@^.*\.([^\.]+)$@imsU', $url, $ext);
|
|
|
|
if (isset($_REQUEST['podcast_format'])) {
|
|
$allowed = explode(',', $_REQUEST['podcast_format']);
|
|
$is_allowed = false;
|
|
foreach($allowed AS $allowed_ext) {
|
|
if ($allowed_ext == $ext[1]) {
|
|
$is_allowed = true;
|
|
}
|
|
}
|
|
|
|
if (!$is_allowed) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
switch($event) {
|
|
case 'frontend_display:rss-2.0:per_entry':
|
|
$enclosureAttrs = 'url="' . $url . '" type="' . $type . '" ';
|
|
|
|
if (isset($length) && $length !== false && $length !== 0){
|
|
$enclosureAttrs .= "length='{$length}' ";
|
|
}
|
|
|
|
return "\n\t<enclosure $enclosureAttrs/>";
|
|
|
|
case 'frontend_display:rss-1.0:per_entry':
|
|
$enclosureElts = "<enc:url>$url</enc:url><enc:type>$type</enc:type>";
|
|
|
|
// check due to HTTP_Request possibly returning false
|
|
if (isset($length) && ($length !== false) && ($length !== 0)){
|
|
$enclosureElts .= "<enc:length>$length</enc:length>";
|
|
}
|
|
|
|
if (isset($md5) && ($md5 !== false)){
|
|
$enclosureElts .= "<podcast:enclosure_protection md5='{$md5}' />\n";
|
|
}
|
|
|
|
return "\n\t<enc:enclosure><enc:Enclosure>$enclosureElts</enc:Enclosure></enc:enclosure>";
|
|
|
|
case 'frontend_display:atom-1.0:per_entry':
|
|
return '<link rel="enclosure">'.$url.'</link>';
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Determines the Mimetype using the getid3 functionality
|
|
*/
|
|
function GetID3Infos($filename, &$fileInfoArray) {
|
|
// Set default fileinformation:
|
|
$fileInfoArray['mime'] = serendipity_guessMime($fileInfoArray['extension']);
|
|
|
|
$this->log("GetID3Infos, Guessed mime: " . $fileInfoArray['mime']);
|
|
$fileInfoArray['width'] = 0;
|
|
$fileInfoArray['height'] = 0;
|
|
|
|
// Try to find the getid3 library in the bundled-libs first:
|
|
if (file_exists(dirname(__FILE__) . '/player/getid3/getid3.lib.php')) {
|
|
@define('GETID3_INCLUDEPATH', dirname(__FILE__) . '/player/getid3/');
|
|
} elseif (file_exists(S9Y_INCLUDE_PATH . '/bundled-libs/getid3/getid3.lib.php')) {
|
|
$this->log("GetID3Infos: include path " . S9Y_INCLUDE_PATH . '/bundled-libs/getid3/');
|
|
@define('GETID3_INCLUDEPATH', S9Y_INCLUDE_PATH . '/bundled-libs/getid3/');
|
|
} else if (file_exists(dirname(__FILE__) . '/getid3/getid3.lib.php')) {
|
|
$this->log("GetID3Infos: include path " . dirname(__FILE__) . '/getid3/');
|
|
@define('GETID3_INCLUDEPATH', dirname(__FILE__) . '/getid3/');
|
|
} else {
|
|
$this->log("GetID3Infos: GetID3 not found!");
|
|
return false;
|
|
}
|
|
|
|
// include getID3() library (can be in a different directory if full path is specified)
|
|
$this->log("GetID3Infos: including " . GETID3_INCLUDEPATH . 'getid3.php');
|
|
require_once(GETID3_INCLUDEPATH . 'getid3.php');
|
|
// Initialize getID3 engine
|
|
$getID3 = new getID3;
|
|
if (file_exists($filename)) {
|
|
$id3 =& $getID3->analyze($filename);
|
|
getid3_lib::CopyTagsToComments($id3);
|
|
if (isset($id3['error'])) {
|
|
$fileInfoArray['id3error'] = $id3['error'];
|
|
} else {
|
|
$this->log("ID3: " . print_r($id3,true));
|
|
$mimeType = $id3['mime_type'];
|
|
$fileInfoArray['mime'] = $mimeType;
|
|
$fileInfoArray['width'] = $id3['video']['resolution_x'];
|
|
$fileInfoArray['height'] = $id3['video']['resolution_y'];
|
|
|
|
// Hack: ID3 gets wrong dimension on FLV files. Try to get another entry
|
|
if ((int)$fileInfoArray['width']<1 && (int)$fileInfoArray['height']<1 && isset($id3['meta']['onMetaData']['height']) && isset($id3['meta']['onMetaData']['width'])) {
|
|
$fileInfoArray['width'] = $id3['meta']['onMetaData']['width'];
|
|
$fileInfoArray['height'] = $id3['meta']['onMetaData']['height'];
|
|
}
|
|
}
|
|
|
|
} else {
|
|
$fileInfoArray['mime'] = 'error/filenotfound';
|
|
$this->log("File $filename not found");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Evaluates a player by an extension. Returns the complete HTML code
|
|
*
|
|
*/
|
|
function GetPlayerByExt($ext, $filename, $valwidth = null, $valheight = null, $valalign = null, $mime = null){
|
|
static $downloadlink = null;
|
|
|
|
if ($downloadlink === null) {
|
|
$downloadlink = serendipity_db_bool($this->get_config('downloadlink'));
|
|
}
|
|
|
|
$this->playerUrlsAdded[] = $filename;
|
|
|
|
$this->InitializeSupportedPlayers();
|
|
if(!isset($this->supportedFiletypes[$ext])){
|
|
return "\n<!-- unknown fileext: $ext ". count($this->supportedFiletypes) ." -->";
|
|
}
|
|
$short = $this->supportedFiletypes[$ext];
|
|
|
|
if (!isset($this->supportedPlayers[$short])){
|
|
return "<!-- no player for: " . $short. " -->";
|
|
}
|
|
$player = $this->supportedPlayers[$short];
|
|
|
|
// Configure Player:
|
|
// Add Height for controls
|
|
if (isset($valheight) && $valheight >0) {
|
|
if ($short == 'w') $valheight = $valheight + 43;
|
|
else if ($short == 'q') $valheight = $valheight + 16;
|
|
else if ($short == 'v') $valheight = $valheight + 20;
|
|
}
|
|
|
|
// Replace align, width and height attributes in players
|
|
$width = 'width="' . ( isset($valwidth) && $valwidth > 0 ? $valwidth : $this->get_config('width', '200') ) . '"';
|
|
$height = 'height="' . ( isset($valheight) && $valheight > 0 ? $valheight : $this->get_config('height', '200') ) . '"';
|
|
$intwidth = ( isset($valwidth) && $valwidth > 0 ? $valwidth : $this->get_config('width', '200') ) ;
|
|
$intheight = ( isset($valheight) && $valheight > 0 ? $valheight : $this->get_config('height', '200') ) ;
|
|
if ((isset($valalign))) {
|
|
$align = ($valalign!='noalign'?'align="' . $valalign . '"':'');
|
|
} else if ($this->get_config('align','left') != 'noalign') {
|
|
$align = 'align="' . $this->get_config('align', 'left') . '"';
|
|
} else {
|
|
$align = '';
|
|
}
|
|
|
|
$filename = str_replace(array(' '),array('%20'),$filename);
|
|
$filename = $this->absolve($filename);
|
|
$filename_noext = preg_replace('@\.'. $ext .'$@is','',$filename);
|
|
|
|
if ($mime == null) {
|
|
$mime = $this->getFileMime($ext);
|
|
}
|
|
|
|
$result = str_replace(
|
|
array(
|
|
'#url#',
|
|
'#url_noext#',
|
|
'#filename#',
|
|
'#htmlid#',
|
|
'#width#',
|
|
'#height#',
|
|
'#intwidth#',
|
|
'#intheight#',
|
|
'#align#',
|
|
'#plugin#',
|
|
'#mime#'
|
|
),
|
|
|
|
array(
|
|
$filename,
|
|
$filename_noext,
|
|
basename($filename),
|
|
md5($filename),
|
|
$width,
|
|
$height,
|
|
$intwidth,
|
|
$intheight,
|
|
$align,
|
|
$this->GetPluginHttpPath(),
|
|
$mime
|
|
),
|
|
$player
|
|
);
|
|
|
|
if ($downloadlink) {
|
|
$result .= "\n<a href=\"" . $filename . "\" class=\"podcastdownload\">" . basename($filename) . "</a>\n";
|
|
}
|
|
|
|
return '<!-- podcastplayerstart -->' . $result . '<!-- podcastplayerend -->';
|
|
}
|
|
|
|
/**
|
|
* Initializes the array holding extension -> playertype
|
|
*/
|
|
function InitializeSupportedFiletypes() {
|
|
|
|
if (!isset($this->supportedFiletypes)) {
|
|
$this->supportedFiletypes = array();
|
|
$qtexts = explode(',', $this->get_config('extquicktime' ,PLUGIN_PODCAST_QTEXT_DDEFAULT));
|
|
$wmexts = explode(',', $this->get_config('extwinmedia' ,PLUGIN_PODCAST_WMEXT_DDEFAULT));
|
|
$flexts = explode(',', $this->get_config('extflash' ,PLUGIN_PODCAST_MFEXT_DDEFAULT));
|
|
$mp3exts = explode(',', $this->get_config('extaudio' ,PLUGIN_PODCAST_AUEXT_DDEFAULT));
|
|
$xspfexts = explode(',', $this->get_config('extxspf' ,PLUGIN_PODCAST_XSPFEXT_DDEFAULT));
|
|
$flvexts = explode(',', $this->get_config('extflow' ,PLUGIN_PODCAST_FLOWEXT_DEFAULT));
|
|
$a5exts = explode(',', $this->get_config('exthtml5_audio',PLUGIN_PODCAST_HTML5_AUDIO_DEFAULT));
|
|
$v5exts = explode(',', $this->get_config('exthtml5_video',PLUGIN_PODCAST_HTML5_VIDEO_DEFAULT));
|
|
|
|
foreach($qtexts as $ext){
|
|
$this->supportedFiletypes[trim($ext)] = 'q';
|
|
}
|
|
foreach($wmexts as $ext){
|
|
$this->supportedFiletypes[trim($ext)] = 'w';
|
|
}
|
|
foreach($flexts as $ext){
|
|
$this->supportedFiletypes[trim($ext)] = 'f';
|
|
}
|
|
foreach($mp3exts as $ext){
|
|
$this->supportedFiletypes[trim($ext)] = 'm';
|
|
}
|
|
foreach($xspfexts as $ext){
|
|
$this->supportedFiletypes[trim($ext)] = 'x';
|
|
}
|
|
foreach($flvexts as $ext){
|
|
$this->supportedFiletypes[trim($ext)] = 'v';
|
|
}
|
|
foreach($a5exts as $ext){
|
|
$this->supportedFiletypes[trim($ext)] = 'a5';
|
|
}
|
|
foreach($v5exts as $ext){
|
|
$this->supportedFiletypes[trim($ext)] = 'v5';
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initializes the array holding playertype -> player HTML code
|
|
*/
|
|
function InitializeSupportedPlayers(){
|
|
|
|
if (!isset($this->supportedPlayers)){
|
|
$this->supportedPlayers = array(
|
|
'q' => $this->get_config('extquicktime_player', PLUGIN_PODCAST_QUICKTIMEPLAYER),
|
|
'w' => $this->get_config('extwinmedia_player', PLUGIN_PODCAST_WMPLAYER),
|
|
'f' => $this->get_config('extflash_player', PLUGIN_PODCAST_FLASHPLAYER),
|
|
'x' => $this->get_config('extxspf_player', PLUGIN_PODCAST_XSPFPLAYER),
|
|
'm' => $this->get_config('extaudio_player', PLUGIN_PODCAST_MP3PLAYER),
|
|
'v' => $this->get_config('extflow_player', PLUGIN_PODCAST_FLOWPLAYER),
|
|
'a5' => $this->get_config('exthtml5_audio_player', PLUGIN_PODCAST_HTML5_AUDIOPLAYER),
|
|
'v5' => $this->get_config('exthtml5_video_player', PLUGIN_PODCAST_HTML5_VIDEOPLAYER),
|
|
);
|
|
}
|
|
}
|
|
function log($message){
|
|
global $serendipity;
|
|
|
|
if (!$this->debug) return;
|
|
$fp = fopen($serendipity['serendipityPath'] . PATH_SMARTY_COMPILE . '/serendipity_event_podcast' . '.log','a');
|
|
fwrite($fp, date("d.m.Y H:i") . " - " . $_SERVER['REQUEST_URI'] . " - " . $_SERVER['REMOTE_ADDR'] . " - " . $message . "\n");
|
|
fclose($fp);
|
|
}
|
|
|
|
}
|