1778 lines
72 KiB
PHP
Executable File
1778 lines
72 KiB
PHP
Executable File
<?php
|
||
############################################################
|
||
# PODCAST GENERATOR
|
||
#
|
||
# Created by Alberto Betella
|
||
# http://www.podcastgenerator.net
|
||
#
|
||
# This is Free Software released under the GNU/GPL License.
|
||
############################################################
|
||
|
||
##################################################################################
|
||
|
||
function checkFileType ($filetype,$absoluteurl) {
|
||
|
||
if (file_exists($absoluteurl."components/supported_media/supported_media.xml")) {
|
||
|
||
$parser = simplexml_load_file($absoluteurl.'components/supported_media/supported_media.xml','SimpleXMLElement',LIBXML_NOCDATA);
|
||
|
||
$podcast_filetypes = array();
|
||
$podcast_filemimetypes = array();
|
||
foreach($parser->mediaFile as $singleFileType) {
|
||
array_push ($podcast_filetypes,$singleFileType->extension[0]);
|
||
array_push ($podcast_filemimetypes,$singleFileType->mimetype[0]);
|
||
}
|
||
|
||
$i=0;
|
||
$isFileSupported=FALSE;
|
||
$fileData = array();
|
||
while (($i < sizeof($podcast_filetypes)) && $isFileSupported==false) {
|
||
if ($filetype==$podcast_filetypes[$i]) {
|
||
$fileData[0]=$podcast_filetypes[$i];
|
||
$fileData[1]=$podcast_filemimetypes[$i];
|
||
$isFileSupported=TRUE;
|
||
}
|
||
$i++;
|
||
}
|
||
|
||
|
||
//Always return something
|
||
if (!isset($fileData[0])) $fileData[0] = NULL;
|
||
if (!isset($fileData[1])) $fileData[1] = NULL;
|
||
|
||
//returns bool (true if file is present in supported_media.xml)
|
||
$fileData[2] = $isFileSupported;
|
||
|
||
//Array with 3 values: podcast_filetypes, podcast_filemimetypes, isFileSupported
|
||
return ($fileData);
|
||
}
|
||
}
|
||
## END - DETECT SUPPORTED MEDIA FILE FORMATS AND RETURN MIMETYPE
|
||
##################################################################################
|
||
|
||
|
||
|
||
|
||
|
||
########
|
||
|
||
## Rename uploaded file - STRICT
|
||
|
||
function renamefilestrict ($filetorename) { // strict rename policy (just characters from a to z and numbers... no accents and other characters). This kind of renaming can have problems with some languages (e.g. oriental)
|
||
|
||
$filetorename = remove_accents($filetorename);
|
||
$filetorename = strtolower($filetorename);
|
||
$filetorename = str_replace(array(' ', '.', ',', 'amp'), "_",$filetorename); //amp is the remaining string from &
|
||
// \w matches alphanumeric characters and underscores + dash added
|
||
$filetorename = preg_replace("/[^\w-]/", "", $filetorename);
|
||
|
||
return $filetorename;
|
||
|
||
}
|
||
|
||
########
|
||
|
||
|
||
########
|
||
#remove accents
|
||
function remove_accents($str)
|
||
{
|
||
$a = array('À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'ß', 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ', 'Ā', 'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ', 'ĉ', 'Ċ', 'ċ', 'Č', 'č', 'Ď', 'ď', 'Đ', 'đ', 'Ē', 'ē', 'Ĕ', 'ĕ', 'Ė', 'ė', 'Ę', 'ę', 'Ě', 'ě', 'Ĝ', 'ĝ', 'Ğ', 'ğ', 'Ġ', 'ġ', 'Ģ', 'ģ', 'Ĥ', 'ĥ', 'Ħ', 'ħ', 'Ĩ', 'ĩ', 'Ī', 'ī', 'Ĭ', 'ĭ', 'Į', 'į', 'İ', 'ı', 'IJ', 'ij', 'Ĵ', 'ĵ', 'Ķ', 'ķ', 'Ĺ', 'ĺ', 'Ļ', 'ļ', 'Ľ', 'ľ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'Ń', 'ń', 'Ņ', 'ņ', 'Ň', 'ň', 'ʼn', 'Ō', 'ō', 'Ŏ', 'ŏ', 'Ő', 'ő', 'Œ', 'œ', 'Ŕ', 'ŕ', 'Ŗ', 'ŗ', 'Ř', 'ř', 'Ś', 'ś', 'Ŝ', 'ŝ', 'Ş', 'ş', 'Š', 'š', 'Ţ', 'ţ', 'Ť', 'ť', 'Ŧ', 'ŧ', 'Ũ', 'ũ', 'Ū', 'ū', 'Ŭ', 'ŭ', 'Ů', 'ů', 'Ű', 'ű', 'Ų', 'ų', 'Ŵ', 'ŵ', 'Ŷ', 'ŷ', 'Ÿ', 'Ź', 'ź', 'Ż', 'ż', 'Ž', 'ž', 'ſ', 'ƒ', 'Ơ', 'ơ', 'Ư', 'ư', 'Ǎ', 'ǎ', 'Ǐ', 'ǐ', 'Ǒ', 'ǒ', 'Ǔ', 'ǔ', 'Ǖ', 'ǖ', 'Ǘ', 'ǘ', 'Ǚ', 'ǚ', 'Ǜ', 'ǜ', 'Ǻ', 'ǻ', 'Ǽ', 'ǽ', 'Ǿ', 'ǿ');
|
||
$b = array('A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 's', 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'y', 'A', 'a', 'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c', 'D', 'd', 'D', 'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'G', 'g', 'G', 'g', 'G', 'g', 'G', 'g', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'IJ', 'ij', 'J', 'j', 'K', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'l', 'l', 'N', 'n', 'N', 'n', 'N', 'n', 'n', 'O', 'o', 'O', 'o', 'O', 'o', 'OE', 'oe', 'R', 'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'T', 't', 'T', 't', 'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'W', 'w', 'Y', 'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 's', 'f', 'O', 'o', 'U', 'u', 'A', 'a', 'I', 'i', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'A', 'a', 'AE', 'ae', 'O', 'o');
|
||
return str_replace($a, $b, $str);
|
||
}
|
||
|
||
|
||
## Rename uploaded file - LESS STRICT
|
||
|
||
function renamefile ($filetorename) { // normal file rename policy
|
||
|
||
$filetorename = strtolower($filetorename); // lower-case.
|
||
$filetorename = strip_tags($filetorename); // remove HTML tags.
|
||
$filetorename = preg_replace('!\s+!','_',$filetorename); // change space chars to underscores.
|
||
$filetorename = stripslashes($filetorename); //remove slashes in the file name
|
||
$filetorename = str_replace("'", "", $filetorename);
|
||
$filetorename = str_replace("&", "_and_", $filetorename);
|
||
|
||
return $filetorename;
|
||
|
||
}
|
||
|
||
########
|
||
|
||
## Validate e-mail address
|
||
|
||
function validate_email ($address) { //validate email address
|
||
return (preg_match("/^[_\.0-9a-zA-Z-]+@([0-9a-zA-Z][0-9a-zA-Z-]+\.)+[a-zA-Z]{2,6}$/i", $address));
|
||
}
|
||
|
||
########
|
||
|
||
## Depurate feed Content from non accepted characters (according also to iTunes specifications)
|
||
|
||
function depurateContent($content) {
|
||
$content = stripslashes($content);
|
||
//$content = str_replace('<', '<', $content);
|
||
//$content = str_replace('>', '>', $content);
|
||
//$content = str_replace('&', '&', $content); //double subsitution to avoid &&&s;
|
||
//$content = str_replace('&', '&', $content);
|
||
//$content = str_replace('’', ''', $content);
|
||
/*
|
||
$content = str_replace('&', '&', $content); //double subsitution to avoid &&&s;
|
||
$content = str_replace('<', '<', $content);
|
||
$content = str_replace('>', '>', $content);
|
||
$content = str_replace('&', '&', $content);
|
||
$content = str_replace('\'', ''', $content);
|
||
$content = str_replace('’', ''', $content);
|
||
$content = str_replace('"', '"', $content);
|
||
$content = str_replace('©', '©', $content);
|
||
$content = str_replace('©', '©', $content);
|
||
$content = str_replace('℗', '℗', $content);
|
||
$content = str_replace('™', '™', $content);
|
||
*/
|
||
|
||
//NB. double_encode = FALSE Will not encode existing html entities
|
||
$content = htmlspecialchars($content,ENT_COMPAT,'UTF-8',FALSE);
|
||
|
||
|
||
|
||
return $content;
|
||
}
|
||
|
||
//this is just for CDATA fields such as <itunes:summary> (long description in PG)
|
||
function iTunesSummaryLinks($content) {
|
||
$content = htmlspecialchars_decode($content);
|
||
//tags that work in iTunes and iOS podcast app
|
||
$allowedTags = array("<a>","<p>","<ul>","<ol>","<li>");
|
||
$content = strip_tags($content,implode($allowedTags)); //implode = array to string
|
||
$tagExists = false;
|
||
foreach ($allowedTags as $singleTag)
|
||
{
|
||
//substr removes last character from tags, so attributes are accepted, e.g. <a> and <a href="">
|
||
if (strpos($content, substr($singleTag, 0, -1)) === true) $tagExists = true;
|
||
}
|
||
if ($tagExists = true) {
|
||
$content = trim(preg_replace('/\s+/', ' ', $content)); //trim new lines
|
||
$content = '<![CDATA['.$content.']]>'; //CDATA Field
|
||
}
|
||
|
||
$content = ampersandEntitiesConvert($content);
|
||
return $content;
|
||
}
|
||
|
||
// to ensure compatibility of iTunes:summary and long description (support <a> tags but ampersand should be entities)
|
||
function ampersandEntitiesConvert ($content) {
|
||
$content = str_replace('&', '&', $content); //double subsitution to avoid &&&s;
|
||
$content = str_replace('&', '&', $content);
|
||
return $content;
|
||
}
|
||
|
||
// used in the categores ID at the moment
|
||
function ampersandRemove ($content) {
|
||
$content = str_replace('&', 'and', $content);
|
||
$content = str_replace('&', 'and;', $content);
|
||
return $content;
|
||
}
|
||
|
||
########
|
||
|
||
## Sanitize URL Content to avoid cross-site scripting (XSS)
|
||
|
||
function avoidXSS($url) {
|
||
$url = filter_var($url,FILTER_SANITIZE_URL);
|
||
$url = str_replace('<', '<', $url);
|
||
$url = str_replace('>', '>', $url);
|
||
$url = str_replace('&', '&', $url); //double subsitution to avoid &&&s;
|
||
$url = str_replace('&', '&', $url);
|
||
$url = str_replace('’', ''', $url);
|
||
$url = str_replace('"', '"', $url);
|
||
$url = str_replace('iframe', '', $url);
|
||
$url = str_replace('width=', '', $url);
|
||
$url = str_replace('height=', '', $url);
|
||
$url = str_replace('src=', '', $url);
|
||
$url = str_replace('javascript=', '', $url);
|
||
return $url;
|
||
}
|
||
|
||
|
||
############ Determine whether to use the old or the new theme engine
|
||
//It depends on the presence or absence of the file theme.xml in the theme root folder
|
||
function useNewThemeEngine($theme_path) //$theme_path is defined in config.php
|
||
{
|
||
if (file_exists($theme_path.'theme.xml')) {
|
||
return TRUE;
|
||
}
|
||
else {
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
############ Create form date and time
|
||
function CreaFormData($inName, $useDate=0, $dateformat) //inName is the form name, it can be null
|
||
{
|
||
// array with months
|
||
$monthName = array(1=> _("Jan"), _("Feb"), _("Mar"),
|
||
_("Apr"), _("May"), _("Jun"), _("Jul"), _("Aug"),
|
||
_("Sep"), _("Oct"), _("Nov"), _("Dec"));
|
||
|
||
// se data non specificata, o invalida, usa timestamp corrente
|
||
if($useDate == NULL)
|
||
{
|
||
$useDate = Time();
|
||
}
|
||
|
||
$outputform = '<p>'._("Date:").'</p>'; //title
|
||
|
||
//day
|
||
$outputformDAY = "<select class=\"input-sm input-small\" name=\"" . $inName . "Day\">\n";
|
||
for($currentDay=1; $currentDay <= 31; $currentDay++)
|
||
{
|
||
$outputformDAY .= "<option value=\"$currentDay\"";
|
||
if(intval(date( "d", $useDate))==$currentDay)
|
||
{
|
||
$outputformDAY .= " selected";
|
||
}
|
||
$outputformDAY .= ">$currentDay\n";
|
||
}
|
||
$outputformDAY .= "</select>";
|
||
|
||
//mese
|
||
$outputformMONTH = "<select class=\"input-sm input-small\" name=\"" . $inName . "Month\">\n";
|
||
for($currentMonth = 1; $currentMonth <= 12; $currentMonth++)
|
||
{
|
||
$outputformMONTH .= "<option value=\"";
|
||
$outputformMONTH .= intval($currentMonth);
|
||
$outputformMONTH .= "\"";
|
||
if(intval(date( "m", $useDate))==$currentMonth)
|
||
{
|
||
$outputformMONTH .= " selected";
|
||
}
|
||
$outputformMONTH .= ">" . $monthName[$currentMonth] . "\n";
|
||
}
|
||
$outputformMONTH .= "</select>";
|
||
|
||
//anno
|
||
$outputformYEAR = "<select class=\"input-sm input-small\" name=\"" . $inName . "Year\">\n";
|
||
$startYear = date( "Y", $useDate);
|
||
for($currentYear = $startYear - 5; $currentYear <= $startYear+5;$currentYear++)
|
||
{
|
||
$outputformYEAR .= "<option value=\"$currentYear\"";
|
||
if(date( "Y", $useDate)==$currentYear)
|
||
{
|
||
$outputformYEAR .= " selected";
|
||
}
|
||
$outputformYEAR .= ">$currentYear\n";
|
||
}
|
||
$outputformYEAR .= "</select>";
|
||
|
||
|
||
if ($dateformat == "m-d-Y") {
|
||
$outputform.= $outputformMONTH.$outputformDAY.$outputformYEAR;}
|
||
elseif ($dateformat == "Y-m-d") {
|
||
$outputform.= $outputformYEAR.$outputformMONTH.$outputformDAY;}
|
||
else { $outputform.= $outputformDAY.$outputformMONTH.$outputformYEAR; }
|
||
|
||
|
||
$outputform .= " "; //two blank spaces
|
||
$outputform .= '<p>'._("Time:").'</p>'; //titoletto
|
||
|
||
|
||
//ore
|
||
$outputform .= "<select class=\"input-sm input-small\" name=\"" . $inName . "Hour\">\n";
|
||
for($currentHour = 0; $currentHour <= 23; $currentHour++)
|
||
{
|
||
$outputform .= "<option value=\"";
|
||
$outputform .= intval($currentHour);
|
||
$outputform .= "\"";
|
||
if(intval(date( "G", $useDate))==$currentHour)
|
||
{
|
||
$outputform .= " selected";
|
||
}
|
||
$outputform .= ">" . $currentHour. "\n";
|
||
}
|
||
$outputform .= "</select>";
|
||
|
||
//minuti
|
||
$outputform .= "<select class=\"input-sm input-small\" name=\"" . $inName . "Minute\">\n";
|
||
for($currentMinute = 0; $currentMinute <= 59; $currentMinute++)
|
||
{
|
||
$outputform .= "<option value=\"";
|
||
|
||
if ($currentMinute <= 9) {
|
||
$outputform .= "0".intval($currentMinute); } //add 0 to numbers from 1 to 9
|
||
else { $outputform .= intval($currentMinute); }
|
||
|
||
$outputform .= "\"";
|
||
if(intval(date( "i", $useDate))==$currentMinute)
|
||
{
|
||
$outputform .= " selected";
|
||
}
|
||
|
||
if ($currentMinute <= 9) {
|
||
$outputform .= ">0".intval($currentMinute). "\n"; } //add 0 to numbers from 1 to 9
|
||
else { $outputform .= ">".intval($currentMinute). "\n"; }
|
||
|
||
}
|
||
$outputform .= "</select>";
|
||
|
||
return $outputform;
|
||
|
||
} // End - form date and time
|
||
|
||
|
||
##################################################################################
|
||
##################################################################################
|
||
## SOCIAL NETWORK INTEGRATION
|
||
|
||
//$fullURL,$text_title are episode data. the rest: value 1 (TRUE) enable a certain social network, value 0 disables
|
||
function displaySocialNetworkButtons($fullURL,$text_title,$fb,$tw,$gp) {
|
||
|
||
$construct_output = '<br />'; //space above
|
||
|
||
//TWITTER Button
|
||
if ($tw == TRUE) {
|
||
$construct_output.= '
|
||
<a href="https://twitter.com/share" class="twitter-share-button" data-url="'.$fullURL.'" data-text="'.$text_title.'" data-hashtags="podcastgen">Tweet</a>
|
||
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
|
||
';
|
||
}
|
||
|
||
//G+ Button
|
||
if ($gp == TRUE) {
|
||
$construct_output .= '
|
||
<div class="g-plusone" data-size="medium" data-href="'.$fullURL.'"></div>
|
||
|
||
<script type="text/javascript">
|
||
(function() {
|
||
var po = document.createElement(\'script\'); po.type = \'text/javascript\'; po.async = true;
|
||
po.src = \'https://apis.google.com/js/plusone.js\';
|
||
var s = document.getElementsByTagName(\'script\')[0]; s.parentNode.insertBefore(po, s);
|
||
})();
|
||
</script>
|
||
';
|
||
}
|
||
|
||
|
||
//FB Like Button
|
||
if ($fb == TRUE) {
|
||
$construct_output .= '
|
||
<iframe src="https://www.facebook.com/plugins/like.php?href='.$fullURL.'&width=79&layout=button_count&action=like&size=small&show_faces=false&share=false&height=21&appId=379539238761383" width="100" height="21" style="border:none;overflow:hidden" scrolling="no" frameborder="0" allowTransparency="true"></iframe>
|
||
';
|
||
}
|
||
|
||
|
||
return $construct_output;
|
||
}
|
||
## END SOCIAL NETWORK INTEGRATION
|
||
##################################################################################
|
||
|
||
|
||
##################################################################################
|
||
##################################################################################
|
||
## SHOW PODCAST EPISODES
|
||
|
||
//NB $all is bool (FALSE = takes $max_recent from config.php) $category is the category name from GET (null = all categories)
|
||
function showPodcastEpisodes($all,$category) {
|
||
|
||
include("core/includes.php");
|
||
$finalOutputEpisodes = NULL; // declare final output to return
|
||
|
||
if ($all == TRUE) {
|
||
$max_recent = NULL; //reset limitation for recent episodes set in config.php
|
||
$categoryURLforPagination = "&cat=all"; //preserve category in links in number of pages at the button
|
||
|
||
//don't show social networks when noextras is appended to the URL
|
||
if (isset($_GET['noextras'])) {
|
||
$disableextras = TRUE;
|
||
$categoryURLforPagination .= "&noextras"; //preserve category in links in number of pages at the button
|
||
}
|
||
|
||
}
|
||
else { // in home page, do not paginate but use $max_recent
|
||
$episodeperpage = 999999; //do not use pagination (workaround - could be more elegant)
|
||
}
|
||
|
||
|
||
/// Header for Category (RSS and Title)
|
||
if (isset($category) AND $category != NULL) {
|
||
|
||
$CounterEpisodesInCategory = 0; // set counter to 0
|
||
$category = avoidXSS($category); //URL depuration
|
||
$categoryURLforPagination = "&cat=".$category;
|
||
|
||
//retrieve existing categories (description/long name)
|
||
//NB $existingCategories[$category] is category full name (not just ID)
|
||
$existingCategories = readPodcastCategories ($absoluteurl);
|
||
|
||
$category_header = '<div>';
|
||
if (isset($existingCategories[$category])) {
|
||
$category_header .= '<h3 class="sectionTitle"><a href="'.$url.'feed.php?cat='.$category.'"><i class="fa fa-rss "></i> '.$existingCategories[$category].'</a></h3>';
|
||
}
|
||
$category_header .= '</div>';
|
||
}
|
||
|
||
// Open podcast directory and read all the files contained
|
||
$fileNamesList = readMediaDir ($absoluteurl,$upload_dir);
|
||
|
||
|
||
if (empty($fileNamesList)) { // If media directory is empty
|
||
$finalOutputEpisodes .= '<div class="topseparator"><p>'._("No episodes here yet...").'</p></div>';
|
||
}
|
||
else { // If media directory contains files
|
||
|
||
$episodesCounter = 0; //set counter to zero
|
||
|
||
//if isset pagination variable in GET
|
||
if (isset($_GET["pgn"]) AND is_numeric($_GET["pgn"])) {
|
||
$maxC = $episodeperpage * $_GET["pgn"];
|
||
$minC = $episodeperpage* $_GET["pgn"] - $episodeperpage;
|
||
}
|
||
//if home page or no pages are set in GET
|
||
else {
|
||
$maxC = $episodeperpage;
|
||
$minC = 0;
|
||
}
|
||
|
||
// Loop through each file in the media directory
|
||
foreach ($fileNamesList as $singleFileName) {
|
||
|
||
$resulting_episodes = NULL; //declare the 1st time and then reset
|
||
|
||
//If current episode won't be displayed in this page, skip it and break the loop
|
||
if ($episodesCounter > $maxC) {
|
||
//NB. count($fileNamesList)/2 is the total number of episodes
|
||
$episodesCounter = count($fileNamesList)/2;
|
||
break;
|
||
}
|
||
//Else if this episode is shown in this page, or no limitation in $max_recent (i.e. home page)
|
||
else if ($episodesCounter < $max_recent OR $max_recent == NULL) {
|
||
|
||
////Validate the current episode
|
||
//NB. validateSingleEpisode returns [0] episode is supported (bool), [1] Episode Absolute path, [2] Episode XML DB absolute path,[3] File Extension (Type), [4] File MimeType, [5] File name without extension, [6] episode file supported but to XML present
|
||
$thisPodcastEpisode = validateSingleEpisode($singleFileName);
|
||
|
||
|
||
////If episode is supported and has a related xml db, and if it's not set to a future date OR if it's set for a future date but you are logged in as admin
|
||
if (($thisPodcastEpisode[0]==TRUE AND !publishInFuture($thisPodcastEpisode[1])) OR ($thisPodcastEpisode[0]==TRUE AND publishInFuture($thisPodcastEpisode[1]) AND isUserLogged())) {
|
||
|
||
////Parse XML data related to the episode
|
||
// NB. Function parseXMLepisodeData returns: [0] episode title, [1] short description, [2] long description, [3] image associated, [4] iTunes keywords, [5] Explicit language,[6] Author's name,[7] Author's email,[8] PG category 1, [9] PG category 2, [10] PG category 3, [11] file_info_size, [12] file_info_duration, [13] file_info_bitrate, [14] file_info_frequency, [15] embedded image in mp3
|
||
$thisPodcastEpisodeData = parseXMLepisodeData($thisPodcastEpisode[2]);
|
||
|
||
////if category is specified as a parameter of this function
|
||
if (isset($category) AND $category != NULL) {
|
||
//if category is not associated to the current episode
|
||
if ($category != $thisPodcastEpisodeData[8] AND $category != $thisPodcastEpisodeData[9] AND $category != $thisPodcastEpisodeData[10]) {
|
||
continue; //STOP this cycle and start a new one
|
||
} else {
|
||
$CounterEpisodesInCategory++; // Incremente episodes counter
|
||
}
|
||
}
|
||
|
||
//// Start constructing episode HTML output
|
||
|
||
//Theme engine PG version >= 2.0
|
||
if (useNewThemeEngine($theme_path)) {
|
||
//episodes per line in some themes (e.g. bootstrap)
|
||
$numberOfEpisodesPerLine = 2;
|
||
//If the current episode number is multiple of $numberOfEpisodesPerLine
|
||
if ($episodesCounter % $numberOfEpisodesPerLine != 0 OR $episodesCounter == count($fileNamesList)) {
|
||
//open div with class row-fluid (theme based on bootstrap)
|
||
//N.B. row-fluid is a CSS class for a div containing 1 or more episodes
|
||
//$resulting_episodes .= '<div class="row-fluid">';
|
||
$resulting_episodes .= '<div class="episode">';
|
||
}
|
||
$resulting_episodes .= '<div class="span6 col-md-6 6u episodebox">'; //open the single episode DIV
|
||
}
|
||
//If old Theme engine for <2.0 themes retro compatibility.
|
||
else {
|
||
$resulting_episodes .= '<div class="episode">'; //open the single episode DIV
|
||
}
|
||
|
||
////Title
|
||
$resulting_episodes .= '<h3 class="episode_title"><a href="?name='.$thisPodcastEpisode[5].'.'.$thisPodcastEpisode[3].'">'.$thisPodcastEpisodeData[0];
|
||
if (isItAvideo($thisPodcastEpisode[3])) $resulting_episodes .= ' <i class="fa fa-youtube-play"></i>'; //add video icon
|
||
$resulting_episodes .= '</a></h3>';
|
||
|
||
////Date
|
||
$resulting_episodes .= '<p class="episode_date">';
|
||
$thisEpisodeDate = filemtime($thisPodcastEpisode[1]);
|
||
if ($thisEpisodeDate > time()) { //if future date
|
||
$resulting_episodes .= '<i class="fa fa-clock-o fa-2x"></i> '; //show watch icon
|
||
}
|
||
$episodeDate = date ($dateformat, $thisEpisodeDate);
|
||
$resulting_episodes .= $episodeDate.'</p>';
|
||
|
||
|
||
//// Edit/Delete button for logged user (i.e. admin)
|
||
if (isUserLogged()) {
|
||
$resulting_episodes .= '<p><a class="btn btn-inverse btn-xs btn-mini" href="?p=admin&do=edit&=episode&name='.urlencode($thisPodcastEpisode[5]).'.'.$thisPodcastEpisode[3].'">'._("Edit / Delete").'</a></p>';
|
||
}
|
||
|
||
|
||
//Show Image embedded in the mp3 file or image associated in the images/ folder from previous versions of PG (i.e. 1.4-) - Just jpg and png extension supported
|
||
if (file_exists($absoluteurl.$img_dir.$thisPodcastEpisode[5].'.jpg')) {
|
||
$resulting_episodes .= '<img class="episode_image" src="'.$url.$img_dir.$thisPodcastEpisode[5].'.jpg" alt="'.$thisPodcastEpisodeData[0].'" />';
|
||
}
|
||
else if (file_exists($absoluteurl.$img_dir.$thisPodcastEpisode[5].'.png')) {
|
||
$resulting_episodes .= '<img class="episode_image" src="'.$url.$img_dir.$thisPodcastEpisode[5].'.png" alt="'.$thisPodcastEpisodeData[0].'" />';
|
||
}
|
||
|
||
|
||
//// Short Description
|
||
$resulting_episodes .= '<p>'.$thisPodcastEpisodeData[1].'</p>';
|
||
|
||
|
||
////Buttons (More, Download, Watch)
|
||
$resulting_episodes .= showButtons($thisPodcastEpisode[5],$thisPodcastEpisode[3],$url,$upload_dir,$episodesCounter,$thisPodcastEpisode[1],$enablestreaming);
|
||
|
||
|
||
////Other details (file type, duration, bitrate, frequency)
|
||
//NB. read from XML DB (except file extension = $thisPodcastEpisode[3]).
|
||
$episodeDetails = _('Filetype:')." ".strtoupper($thisPodcastEpisode[3]);
|
||
if ($thisPodcastEpisodeData[11] != NULL) $episodeDetails .= ' - '._('Size:')." ".$thisPodcastEpisodeData[11]._("MB");
|
||
|
||
if($thisPodcastEpisodeData[12]!=NULL) { // display file duration
|
||
$episodeDetails .= " - "._("Duration:")." ".$thisPodcastEpisodeData[12]." "._("m");
|
||
}
|
||
if($thisPodcastEpisode[3]=="mp3" AND $thisPodcastEpisodeData[13] != NULL AND $thisPodcastEpisodeData[14] != NULL) { //if mp3 show bitrate and frequency
|
||
$episodeDetails .= " (".$thisPodcastEpisodeData[13]." "._("kbps")." ".$thisPodcastEpisodeData[14]." "._("Hz").")";
|
||
}
|
||
$resulting_episodes .= '<p class="episode_info">'.$episodeDetails.'</p>';
|
||
|
||
|
||
////Playes: audio (flash/html5) and video (html5), for supported files and browsers
|
||
//if audio and video streaming is enabled in PG options
|
||
if ($enablestreaming=="yes" AND !detectMobileDevice()) {
|
||
$resulting_episodes .= showStreamingPlayers ($thisPodcastEpisode[5],$thisPodcastEpisode[3],$url,$upload_dir,$episodesCounter);
|
||
}
|
||
$isvideo = FALSE; //RESET isvideo for next episode
|
||
|
||
|
||
////Social networks and (eventual) embedded code
|
||
$resulting_episodes .= attachToEpisode($thisPodcastEpisode[5],$thisPodcastEpisode[3],$thisPodcastEpisodeData[0]);
|
||
|
||
|
||
//Blank space as bottom margin (to be replaced with CSS style!)
|
||
$resulting_episodes .= "<br />";
|
||
//Close the single episode DIV
|
||
$resulting_episodes .= "</div>";
|
||
//Close div with class row-fluid (theme based on bootstrap). Theme engine >= 2.0
|
||
if (useNewThemeEngine($theme_path) AND $episodesCounter % $numberOfEpisodesPerLine != 0 OR $episodesCounter == count($fileNamesList)) {
|
||
$resulting_episodes .= "</div>"; //close class row-fluid (bootstrap)
|
||
}
|
||
|
||
$episodesCounter++; //increment counter
|
||
} // END - If episode is supported and has a related xml db
|
||
|
||
|
||
if ($episodesCounter <= $maxC AND $episodesCounter > $minC) {
|
||
//Append this episode to the final output to return
|
||
$finalOutputEpisodes .= $resulting_episodes;
|
||
}
|
||
|
||
} //END - Else if this episode is shown in this page, or no limitation in $max_recent
|
||
|
||
} // END - Loop through each file in the media directory
|
||
|
||
} // END - If media directory contains files
|
||
|
||
//IF a category is requested add category header and message when empty
|
||
if (isset($category) AND $category != NULL) {
|
||
//If a category is requested and doesn't contain any episode
|
||
if ($CounterEpisodesInCategory < 1 AND !empty($fileNamesList)) {
|
||
$finalOutputEpisodes .= '<p>'.("No episodes here yet...").'</p>';
|
||
}
|
||
$finalOutputEpisodes = $category_header.$finalOutputEpisodes; //category header at the top
|
||
}
|
||
|
||
|
||
////Pagination (and links to pages)
|
||
|
||
//Calculate total number of pages
|
||
if (isset($episodesCounter)) $numberOfPages = ($episodesCounter / $episodeperpage);
|
||
if (isset($numberOfPages) AND $numberOfPages>1) $numberOfPages = ceil($numberOfPages); //round to the next integer
|
||
//echo $numberOfPages; // Debug
|
||
|
||
if (isset($_GET['p'])) $pageURLforPagination = avoidXSS(($_GET['p']));
|
||
else $pageURLforPagination = "home";
|
||
|
||
if (isset($_GET["pgn"])) $thisCurrentPage = $_GET["pgn"];
|
||
else $thisCurrentPage = 1;
|
||
|
||
if (isset($episodesCounter) AND $episodesCounter > $episodeperpage) {
|
||
$finalOutputEpisodes .= '<div style="clear:both;"><p>';
|
||
|
||
//Print page index and links
|
||
for ($onePage =1; $onePage <= $numberOfPages; $onePage++) {
|
||
if ($thisCurrentPage == $onePage) {
|
||
$finalOutputEpisodes .= $onePage.' | ';
|
||
} else
|
||
$finalOutputEpisodes .= '<a href="?p='.$pageURLforPagination.$categoryURLforPagination.'&pgn='.$onePage.'">'.$onePage.'</a> | ';
|
||
}
|
||
$finalOutputEpisodes .= '</p></div>';
|
||
}
|
||
|
||
//Finally, return all the episodes to output on the web page
|
||
return $finalOutputEpisodes;
|
||
|
||
}
|
||
## END - SHOW PODCAST EPISODES
|
||
##################################################################################
|
||
|
||
|
||
|
||
##################################################################################
|
||
##################################################################################
|
||
## SHOW SINGLE EPISODE
|
||
|
||
// $justTitle is bool and returns just the title of the episode
|
||
function showSingleEpisode($singleEpisode,$justTitle) {
|
||
|
||
include("core/includes.php");
|
||
$finalOutputEpisodes = NULL; // declare final output to return
|
||
|
||
$resulting_episodes = NULL; //declare the 1st time and then reset
|
||
|
||
////Validate the current episode
|
||
//NB. validateSingleEpisode returns [0] episode is supported (bool), [1] Episode Absolute path, [2] Episode XML DB absolute path,[3] File Extension (Type), [4] File MimeType, [5] File name without extension, [6] episode file supported but to XML present
|
||
|
||
$thisPodcastEpisode = validateSingleEpisode($singleEpisode);
|
||
|
||
////If episode is supported and has a related xml db, and if it's not set to a future date OR if it's set for a future date but you are logged in as admin
|
||
if (($thisPodcastEpisode[0]==TRUE AND !publishInFuture($thisPodcastEpisode[1])) OR ($thisPodcastEpisode[0]==TRUE AND publishInFuture($thisPodcastEpisode[1]) AND isUserLogged())) {
|
||
|
||
////Parse XML data related to the episode
|
||
// NB. Function parseXMLepisodeData returns: [0] episode title, [1] short description, [2] long description, [3] image associated, [4] iTunes keywords, [5] Explicit language,[6] Author's name,[7] Author's email,[8] PG category 1, [9] PG category 2, [10] PG category 3, [11] file_info_size, [12] file_info_duration, [13] file_info_bitrate, [14] file_info_frequency
|
||
$thisPodcastEpisodeData = parseXMLepisodeData($thisPodcastEpisode[2]);
|
||
|
||
//// Return just title and end function here, if just title is required
|
||
if (isset($justTitle) AND $justTitle == TRUE) return $thisPodcastEpisodeData[0]; //Function ends here
|
||
|
||
//// Start constructing episode HTML output
|
||
|
||
//Theme engine PG version >= 2.0 row-fluid
|
||
$resulting_episodes .= '<div class="episode">';
|
||
$resulting_episodes .= '<div class="span6 col-md-6 6u episodebox">'; //open the single episode DIV
|
||
|
||
|
||
////Title
|
||
$resulting_episodes .= '<h3 class="episode_title">'.$thisPodcastEpisodeData[0];
|
||
if (isItAvideo($thisPodcastEpisode[3])) $resulting_episodes .= ' <i class="fa fa-youtube-play"></i>'; //add video icon
|
||
$resulting_episodes .= '</h3>';
|
||
|
||
|
||
////Date
|
||
$resulting_episodes .= '<p class="episode_date">';
|
||
$thisEpisodeDate = filemtime($thisPodcastEpisode[1]);
|
||
if ($thisEpisodeDate > time()) { //if future date
|
||
$resulting_episodes .= '<i class="fa fa-clock-o fa-2x"></i> '; //show watch icon
|
||
}
|
||
$episodeDate = date ($dateformat, $thisEpisodeDate);
|
||
$resulting_episodes .= $episodeDate.'</p>';
|
||
|
||
|
||
//// Edit/Delete button for logged user (i.e. admin)
|
||
if (isUserLogged()) {
|
||
$resulting_episodes .= '<p><a class="btn btn-inverse btn-xs btn-mini" href="?p=admin&do=edit&=episode&name='.urlencode($thisPodcastEpisode[5]).'.'.$thisPodcastEpisode[3].'">'._("Edit / Delete").'</a></p>';
|
||
}
|
||
|
||
|
||
//Show Image embedded in the mp3 file or image associated in the images/ folder from previous versions of PG (i.e. 1.4-) - Just jpg and png extension supported
|
||
if (file_exists($absoluteurl.$img_dir.$thisPodcastEpisode[5].'.jpg')) {
|
||
$resulting_episodes .= '<img class="episode_image" src="'.$url.$img_dir.$thisPodcastEpisode[5].'.jpg" alt="'.$thisPodcastEpisodeData[0].'" />';
|
||
}
|
||
else if (file_exists($absoluteurl.$img_dir.$thisPodcastEpisode[5].'.png')) {
|
||
$resulting_episodes .= '<img class="episode_image" src="'.$url.$img_dir.$thisPodcastEpisode[5].'.png" alt="'.$thisPodcastEpisodeData[0].'" />';
|
||
}
|
||
|
||
//// Show Long description if available, otherwise, short Description
|
||
if ($thisPodcastEpisodeData[2] != NULL) $resulting_episodes .= '<div>'.ampersandEntitiesConvert(htmlspecialchars_decode($thisPodcastEpisodeData[2])).'</div>';
|
||
else $resulting_episodes .= '<p>'.$thisPodcastEpisodeData[1].'</p>';
|
||
|
||
/// Categories
|
||
$resulting_episodes .= '<p><em>'._("Categories").'</em> ';
|
||
if ($thisPodcastEpisodeData[8] != "") $resulting_episodes .= ' | <a href="?p=archive&cat='.$thisPodcastEpisodeData[8] .'">'.categoryNameFromID($absoluteurl,$thisPodcastEpisodeData[8]).'</a>';
|
||
if ($thisPodcastEpisodeData[9] != "") $resulting_episodes .= ' | <a href="?p=archive&cat='.$thisPodcastEpisodeData[9].'">'.categoryNameFromID($absoluteurl,$thisPodcastEpisodeData[9]).'</a>';
|
||
if ($thisPodcastEpisodeData[10] != "") $resulting_episodes .= ' | <a href="?p=archive&cat='.$thisPodcastEpisodeData[10].'">'.categoryNameFromID($absoluteurl,$thisPodcastEpisodeData[10]).'</a>';
|
||
$resulting_episodes .= '</p>';
|
||
|
||
|
||
////Buttons (More, Download, Watch).
|
||
$resulting_episodes .= showButtons($thisPodcastEpisode[5],$thisPodcastEpisode[3],$url,$upload_dir,"singleEpisode",$thisPodcastEpisode[1],$enablestreaming);
|
||
|
||
|
||
////Other details (file type, duration, bitrate, frequency)
|
||
//NB. read from XML DB (except file extension = $thisPodcastEpisode[3]).
|
||
$episodeDetails = _('Filetype:')." ".strtoupper($thisPodcastEpisode[3]);
|
||
if ($thisPodcastEpisodeData[11] != NULL) $episodeDetails .= ' - '._('Size:')." ".$thisPodcastEpisodeData[11]._("MB");
|
||
|
||
if($thisPodcastEpisodeData[12]!=NULL) { // display file duration
|
||
$episodeDetails .= " - "._("Duration:")." ".$thisPodcastEpisodeData[12]." "._("m");
|
||
}
|
||
if($thisPodcastEpisode[3]=="mp3" AND $thisPodcastEpisodeData[13] != NULL AND $thisPodcastEpisodeData[14] != NULL) { //if mp3 show bitrate and frequency
|
||
$episodeDetails .= " (".$thisPodcastEpisodeData[13]." "._("kbps")." ".$thisPodcastEpisodeData[14]." "._("Hz").")";
|
||
}
|
||
$resulting_episodes .= '<p class="episode_info">'.$episodeDetails.'</p>';
|
||
|
||
|
||
////Playes: audio (flash/html5) and video (html5), for supported files and browsers
|
||
//if audio and video streaming is enabled in PG options
|
||
if ($enablestreaming=="yes" AND !detectMobileDevice()) {
|
||
$resulting_episodes .= showStreamingPlayers ($thisPodcastEpisode[5],$thisPodcastEpisode[3],$url,$upload_dir,"singleEpisode");
|
||
}
|
||
$isvideo = FALSE; //RESET isvideo for next episode
|
||
|
||
|
||
////Social networks and (eventual) embedded code
|
||
$resulting_episodes .= attachToEpisode($thisPodcastEpisode[5],$thisPodcastEpisode[3],$thisPodcastEpisodeData[0]);
|
||
|
||
|
||
//Close the single episode DIV
|
||
$resulting_episodes .= "</div>";
|
||
//Close div with class row-fluid (theme based on bootstrap). Theme engine >= 2.0
|
||
$resulting_episodes .= "</div>"; //close class row-fluid (bootstrap)
|
||
|
||
//Append this episode to the final output to return
|
||
$finalOutputEpisodes .= $resulting_episodes;
|
||
}
|
||
|
||
|
||
//Finally, return all the episodes to output on the web page
|
||
return $finalOutputEpisodes;
|
||
|
||
}
|
||
## END - SHOW SIGLE EPISODE
|
||
##################################################################################
|
||
|
||
|
||
|
||
function divideFilenameFromExtension ($filetodivide) {
|
||
|
||
$file_parts = pathinfo($filetodivide); //divide filename from extension
|
||
|
||
$fileParts = array();
|
||
|
||
$fileParts[0] = $file_parts['filename'];
|
||
$fileParts[1] = $file_parts['extension'];
|
||
|
||
return $fileParts;
|
||
|
||
}
|
||
|
||
|
||
function readPodcastCategories ($absoluteurl) {
|
||
|
||
if (file_exists($absoluteurl."categories.xml")) { //if categories file exists
|
||
|
||
$parser = simplexml_load_file($absoluteurl."categories.xml",'SimpleXMLElement',LIBXML_NOCDATA);
|
||
|
||
//var_dump($parser); //Debug
|
||
|
||
$existingCategories = array();
|
||
|
||
$n = 0;
|
||
foreach($parser->category as $singlecategory) {
|
||
|
||
//create array containing category id as seed and description for each id
|
||
$catID = $singlecategory->id[0];
|
||
$catDescription = $singlecategory->description[0];
|
||
$existingCategories["$catID"] = depurateContent($catDescription);
|
||
|
||
$n++;
|
||
}
|
||
}
|
||
return $existingCategories;
|
||
}
|
||
|
||
|
||
//generate language ISO639 format (e.g. just "en" and not "en_EN") for RSS feed
|
||
function languageISO639 ($language) {
|
||
$parts = explode("_", $language);
|
||
return $parts[0];
|
||
}
|
||
|
||
function categoryNameFromID ($absoluteurl,$id) {
|
||
include ("$absoluteurl"."core/admin/readXMLcategories.php");
|
||
if (in_array($id, $arrid)) {
|
||
$positionInArray = array_search($id, $arrid);
|
||
$catName = ampersandEntitiesConvert($arr[$positionInArray]);
|
||
return $catName;
|
||
} else {
|
||
return;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
function languagesList ($absoluteurl,$isTranslation) { // $isTranslation TRUE when the list is used for localized files
|
||
|
||
if (file_exists($absoluteurl."components/locale/languages.xml")) {
|
||
|
||
$parser = simplexml_load_file($absoluteurl.'components/locale/languages.xml','SimpleXMLElement',LIBXML_NOCDATA);
|
||
|
||
}
|
||
|
||
$languageList = array (); //empty
|
||
|
||
$n = 0;
|
||
foreach($parser->language as $singlelanguage)
|
||
{
|
||
|
||
//echo $singlelanguage->id[0]."<br>";
|
||
//echo $singlelanguage->description[0];
|
||
|
||
$id = $singlelanguage->id[0];
|
||
$desc = $singlelanguage->description[0];
|
||
|
||
if ($isTranslation == TRUE) {
|
||
//if localization folder exists
|
||
|
||
$localizedFolder = $absoluteurl."components/locale/".$id."/LC_MESSAGES/";
|
||
|
||
if (file_exists($localizedFolder."messages.mo") AND file_exists($localizedFolder."messages.po")) {
|
||
$languageList["$id"] = "$desc"; //double quotes necessary
|
||
}
|
||
} else {
|
||
//add all to the list
|
||
$languageList["$id"] = "$desc"; //double quotes necessary
|
||
}
|
||
|
||
$n++;
|
||
}
|
||
|
||
return $languageList;
|
||
}
|
||
|
||
|
||
function random_str($size) {
|
||
$text = NULL;
|
||
$randoms = array(
|
||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b",
|
||
"c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
|
||
"o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
|
||
);
|
||
|
||
srand ((double) microtime() * 1000000);
|
||
|
||
for($i = 1; $i <= $size; $i++)
|
||
$text .= $randoms[(rand(0,35))];
|
||
|
||
return $text;
|
||
}
|
||
|
||
|
||
|
||
function detectMobileDevice() {
|
||
|
||
//Some of the main mobile devices
|
||
$iPod = stripos($_SERVER['HTTP_USER_AGENT'],"iPod");
|
||
$iPhone = stripos($_SERVER['HTTP_USER_AGENT'],"iPhone");
|
||
$iPad = stripos($_SERVER['HTTP_USER_AGENT'],"iPad");
|
||
$Android= stripos($_SERVER['HTTP_USER_AGENT'],"Android");
|
||
$webOS= stripos($_SERVER['HTTP_USER_AGENT'],"webOS");
|
||
$Blackberry= stripos($_SERVER['HTTP_USER_AGENT'],"BlackBerry");
|
||
$Kindle= stripos($_SERVER['HTTP_USER_AGENT'],"Kindle");
|
||
|
||
//here we can do something with the mobile devices or just a subset of them
|
||
if($iPod OR $iPhone OR $iPad OR $Android OR $webOS OR $Blackberry OR $Kindle){
|
||
return TRUE;
|
||
} else {
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
//detect browser name and version from user agent (until get_browser will come in bundle with PHP)
|
||
function browserAndVersion() {
|
||
$userAgent = strtolower($_SERVER['HTTP_USER_AGENT']);
|
||
|
||
|
||
//The following conditions are custom-tailored for specific user agents and may change in future
|
||
|
||
//Opera (NB. It goes before Chrome, cause the user agent contains chrome too
|
||
if(preg_match('/(opr)[ \/]([\w.]+)/', $userAgent)) {
|
||
$browser = 'opera';
|
||
preg_match('/(opr)[ \/]([\w]+)/', $userAgent, $versionExtracted); //used (opr) in regexp
|
||
}
|
||
//Chrome
|
||
else if(preg_match('/(chrome)[ \/]([\w.]+)/', $userAgent)) {
|
||
$browser = 'chrome';
|
||
preg_match('/('.$browser.')[ \/]([\w]+)/', $userAgent, $versionExtracted);
|
||
}
|
||
//Firefox
|
||
else if(preg_match('/(firefox)[ \/]([\w.]+)/', $userAgent)) {
|
||
$browser = 'firefox';
|
||
preg_match('/('.$browser.')[ \/]([\w]+)/', $userAgent, $versionExtracted);
|
||
}
|
||
//IE
|
||
else if(preg_match('/(msie)[ \/]([\w.]+)/', $userAgent)) {
|
||
$browser = 'msie';
|
||
preg_match('/('.$browser.')[ \/]([\w]+)/', $userAgent, $versionExtracted);
|
||
}
|
||
//IE 11
|
||
else if(preg_match('/(trident)[ \/]([\w.]+)/', $userAgent)) {
|
||
$browser = 'msie';
|
||
$version = "11"; //manually assigned to IE 11
|
||
}
|
||
//SAFARI
|
||
else if(preg_match('/(safari)[ \/]([\w.]+)/', $userAgent)) {
|
||
$browser = 'safari';
|
||
preg_match('/(version)[ \/]([\w]+)/', $userAgent, $versionExtracted); //version in the regexp
|
||
}
|
||
else {
|
||
$browser = "notDetected";
|
||
$version = "0";
|
||
}
|
||
|
||
if (!isset($version)) $version = $versionExtracted[2];
|
||
|
||
/*
|
||
if(preg_match('/(chromium)[ \/]([\w.]+)/', $userAgent))
|
||
$browser = 'chromium';
|
||
elseif(preg_match('/(chrome)[ \/]([\w.]+)/', $userAgent))
|
||
$browser = 'chrome';
|
||
elseif(preg_match('/(safari)[ \/]([\w.]+)/', $userAgent))
|
||
$browser = 'safari';
|
||
elseif(preg_match('/(opera)[ \/]([\w.]+)/', $userAgent))
|
||
$browser = 'opera';
|
||
elseif(preg_match('/(msie)[ \/]([\w.]+)/', $userAgent))
|
||
$browser = 'msie';
|
||
elseif(preg_match('/(mozilla)[ \/]([\w.]+)/', $userAgent))
|
||
$browser = 'mozilla';
|
||
elseif(preg_match('/(opr)[ \/]([\w.]+)/', $userAgent))
|
||
$browser = 'opera';
|
||
|
||
|
||
*/
|
||
|
||
// DEBUG!
|
||
//echo $userAgent."<br />";
|
||
//echo $browser." v.".$version."<br />";
|
||
|
||
return array($browser,$version, 'name'=>$browser,'version'=>$version);
|
||
}
|
||
|
||
|
||
//Function detectModernBrowser detects modern browsers to enable HTML5 audio/video players
|
||
//It compares user agent and versions agains a list of browsers known to support html5 audio/video tags
|
||
function detectModernBrowser()
|
||
{
|
||
|
||
$supportHTML5audioTag = array("msie","firefox","chrome","safari");
|
||
$supportHTML5videoTag = array("msie","chrome","safari"); //firefox does not fully support mp4 videos yet
|
||
|
||
//for each browser, which is the minimum required version that supports HTML5 audio and video tags
|
||
$minumumRequiredVersion = array(
|
||
"msie" => 9,
|
||
"firefox" => 29,
|
||
"safari" => 5,
|
||
"chrome" => 36,
|
||
);
|
||
|
||
$browser = browserAndVersion();
|
||
$browsername = $browser[0];
|
||
$browserMajorVersion = $browser[1];
|
||
|
||
|
||
$HTML5audiosupport = FALSE;
|
||
if (in_array($browser[0], $supportHTML5audioTag)) {
|
||
//echo "<br/>Browser: ".$browsername." - Version: ".$browserMajorVersion." supports HTML5 audio tag";
|
||
if ($browserMajorVersion >= $minumumRequiredVersion[$browsername]) $HTML5audiosupport = TRUE;
|
||
//echo $HTML5audiosupport;
|
||
|
||
}
|
||
|
||
$HTML5videosupport = FALSE;
|
||
if (in_array($browser[0], $supportHTML5videoTag)) {
|
||
//echo "<br/>Browser: ".$browsername." - Version: ".$browserMajorVersion." supports HTML5 video tag";
|
||
if ($browserMajorVersion >= $minumumRequiredVersion[$browsername]) $HTML5videosupport = TRUE;
|
||
//echo $HTML5audiosupport;
|
||
|
||
}
|
||
|
||
$browserCompatibility = array($HTML5audiosupport,$HTML5videosupport);
|
||
//print_r($browserCompatibility);
|
||
|
||
return $browserCompatibility;
|
||
}
|
||
|
||
|
||
function isItAvideo($podcast_filetype) {
|
||
$listOfVideoFormats = array("mpg","mpeg","mov","mp4","wmv","3gp","avi","flv","m4v");
|
||
if (in_array($podcast_filetype, $listOfVideoFormats)) { // if it is a video
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
|
||
function showButtons($filenameWithoutExtension,$podcast_filetype,$url,$upload_dir,$recent_count,$absolutePathEpisode,$enablestreaming) {
|
||
|
||
$buttonsOutput = '<p>';
|
||
|
||
//// Button "More" - in the permalink it is not show (no numeric var passed)
|
||
if (is_numeric($recent_count)) $buttonsOutput .= '<a class="btn btn-default" href="?name='.urlencode($filenameWithoutExtension).'.'.$podcast_filetype.'"><i class="fa fa-search"></i> '._("More").'</a> ';
|
||
|
||
//// Button Watch (takes into account $enablestreaming from config.php)
|
||
$browserAudioVideoSupport = detectModernBrowser();
|
||
if ($enablestreaming == "yes" AND isItAvideo($podcast_filetype) == TRUE AND $browserAudioVideoSupport[1] == TRUE AND !detectMobileDevice()) {
|
||
//javascript:; is added as an empty link for href
|
||
$buttonsOutput .= '<a href="javascript:;" class="btn btn-default" onclick="$(\'#videoPlayer'.$recent_count.'\').fadeToggle();$(this).css(\'font-weight\',\'bold\');"><i class="fa fa-youtube-play"></i> '._("Watch").'</a> ';
|
||
}
|
||
|
||
//// Button download
|
||
//Download button doesn't appear for episodes with future publication date (security reasons)
|
||
if (!publishInFuture($absolutePathEpisode)) {
|
||
//iOS device has been reported having some trouble downloading episode using the "download.php" forced download...
|
||
if (!detectMobileDevice()) {
|
||
//show button (FORCED) download using download.php
|
||
$buttonsOutput .= '<a class="btn btn-default" href="'.$url.'download.php?filename='.urlencode($filenameWithoutExtension).'.'.$podcast_filetype.'"><i class="fa fa-download"></i> '._("Download").'</a>';
|
||
}
|
||
else { // SHOW BUTTON DOWNLOAD THAT links directly to the file (so no problems with PHP forcing headers)
|
||
//Write "watch" or "listen" in mobile devices.
|
||
if (isItAvideo($podcast_filetype) == TRUE) {
|
||
$buttonsOutput .= '<a class="btn btn-default" href="'.$url.$upload_dir.urlencode($filenameWithoutExtension).'.'.$podcast_filetype.'"><i class="fa fa-youtube-play"></i> '._("Watch").'</a>';
|
||
}
|
||
//if it's audio
|
||
else if ($podcast_filetype=="mp3" OR $podcast_filetype=="m4a"){
|
||
$buttonsOutput .= '<a class="btn btn-default" href="'.$url.$upload_dir.urlencode($filenameWithoutExtension).'.'.$podcast_filetype.'"><i class="fa fa-play"></i> '._("Listen").'</a>';
|
||
} else {
|
||
$buttonsOutput .= '<a class="btn btn-default" href="'.$url.$upload_dir.urlencode($filenameWithoutExtension).'.'.$podcast_filetype.'"><i class="fa fa-download"></i> '._("Download").'</a>';
|
||
}
|
||
}
|
||
}
|
||
|
||
$buttonsOutput .= '</p>';
|
||
|
||
return $buttonsOutput;
|
||
}
|
||
|
||
|
||
function showStreamingPlayers($filenameWithoutExtension,$podcast_filetype,$url,$upload_dir,$recent_count) {
|
||
|
||
$playersOutput = "";
|
||
|
||
$browserAudioVideoSupport = detectModernBrowser();
|
||
|
||
//// AUDIO PLAYER (MP3)
|
||
if ($browserAudioVideoSupport[0] == TRUE AND $podcast_filetype=="mp3") { //if browser supports HTML5
|
||
$showplayercode = '<audio style="width:80%;" controls preload="none">
|
||
<source src="'.$url.$upload_dir.$filenameWithoutExtension.'.mp3" type="audio/mpeg">
|
||
'._("Your browser does not support the audio player").'
|
||
</audio>';
|
||
$playersOutput .= ''.$showplayercode.'<br />';
|
||
|
||
}
|
||
// Flash Player disabled from version 2.5
|
||
/*
|
||
else { //if no support for HTML5, then flash player just for mp3
|
||
if($podcast_filetype=="mp3") { //if not mobile
|
||
include ("components/player/player.php");
|
||
$playersOutput .= ''.$showplayercode.'<br />';
|
||
}
|
||
|
||
}
|
||
*/
|
||
//// END AUDIO PLAYER (MP3)
|
||
|
||
|
||
//// VIDEO PLAYER (MP4)
|
||
|
||
// If the file is a video and the browser supports HTML5 video tag
|
||
if (isItAvideo($podcast_filetype) == TRUE AND $browserAudioVideoSupport[1] == TRUE) {
|
||
|
||
$playersOutput .= '<video width="85%" id="videoPlayer'.$recent_count.'" style="display:none;" controls preload="none">
|
||
<source src="'.$url.$upload_dir.$filenameWithoutExtension.'.'.$podcast_filetype.'" type="video/mp4">
|
||
'._("Your browser does not support the video player").'
|
||
</video>';
|
||
|
||
$playersOutput .= '<br />';
|
||
}
|
||
|
||
return $playersOutput;
|
||
|
||
}
|
||
|
||
|
||
|
||
function retrieveMediaFileDetails ($MediaFile,$absoluteURL,$filenameWithoutExtension,$imgDir) {
|
||
|
||
if ($filenameWithoutExtension != NULL AND $imgDir != NULL) {
|
||
$extraDataSent = TRUE;
|
||
// echo 'File name no ext: '.$filenameWithoutExtension.'<br>image dir: '.$imgDir.'<br>';
|
||
} else {
|
||
$extraDataSent = FALSE;
|
||
}
|
||
|
||
|
||
|
||
require_once($absoluteURL."components/getid3/getid3.php"); //Lib to read ID3 tags in media files
|
||
$getID3 = new getID3; //initialize getID3 engine
|
||
|
||
$ThisFileSizeInMB = round(filesize($MediaFile)/1048576,2);
|
||
$ThisFileInfo = $getID3->analyze($MediaFile); //read file tags
|
||
$file_duration = @$ThisFileInfo['playtime_string'];
|
||
//$file_type = @$ThisFileInfo['fileformat'];
|
||
$file_bitrate = @$ThisFileInfo['bitrate']/1000;
|
||
$file_freq = @$ThisFileInfo['audio']['sample_rate'];
|
||
$file_embedded_image = NULL;
|
||
|
||
|
||
//// Title from ID3 tags
|
||
$thisFileTitleID3 = NULL;
|
||
if (isset($ThisFileInfo['tags']['id3v2']['title'][0]) AND $ThisFileInfo['tags']['id3v2']['title'][0] != NULL) { //ID3 v2
|
||
$thisFileTitleID3 = @$ThisFileInfo['tags']['id3v2']['title'][0];
|
||
} elseif (isset($ThisFileInfo['tags']['id3v1']['title'][0]) AND $ThisFileInfo['tags']['id3v1']['title'][0] != NULL) { //ID3 v1
|
||
$thisFileTitleID3 = @$ThisFileInfo['tags']['id3v1']['title'][0];
|
||
}
|
||
|
||
//// Artist from ID3 tags
|
||
$thisFileArtistID3 = NULL;
|
||
if (isset($ThisFileInfo['tags']['id3v2']['artist'][0]) AND $ThisFileInfo['tags']['id3v2']['artist'][0] != NULL) { //ID3 v2
|
||
$thisFileArtistID3 = @$ThisFileInfo['tags']['id3v2']['artist'][0];
|
||
} elseif (isset($ThisFileInfo['tags']['id3v1']['artist'][0]) AND $ThisFileInfo['tags']['id3v1']['artist'][0] != NULL) { //ID3 v1
|
||
$thisFileArtistID3 = @$ThisFileInfo['tags']['id3v1']['artist'][0];
|
||
}
|
||
|
||
|
||
//Image embedded in the MP3 - Extract and Save
|
||
if($extraDataSent AND isset($ThisFileInfo['id3v2']['APIC'][0]) AND !file_exists($absoluteURL.$imgDir.$filenameWithoutExtension.'.png') AND !file_exists($absoluteURL.$imgDir.$filenameWithoutExtension.'.jpg')) {
|
||
|
||
$imageMimeType = $ThisFileInfo['id3v2']['APIC'][0]['image_mime'];
|
||
$imageData = $ThisFileInfo['id3v2']['APIC'][0]['data'];
|
||
|
||
//$file_embedded_image = 'data:'.$ThisFileInfo['id3v2']['APIC'][0]['image_mime'].';charset=utf-8;base64,'.base64_encode( $ThisFileInfo['id3v2']['APIC'][0]['data']);
|
||
// echo 'Image Embedded:<br><img id="FileImage" width="150" src="'.$file_embedded_image.'" />';
|
||
|
||
//Save image file extracted from ID3 v2 APIC (attached picture) tag
|
||
$data = 'data:'.$imageMimeType.';base64,'.base64_encode($imageData);
|
||
list($type, $data) = explode(';', $data);
|
||
list(, $data) = explode(',', $data);
|
||
$data = base64_decode($data);
|
||
|
||
//choose extension between png and jpg (jpg by default)
|
||
if ($imageMimeType == "image/png") $thisImageExtension = "png";
|
||
else $thisImageExtension = "jpg";
|
||
|
||
//write file
|
||
file_put_contents($absoluteURL.$imgDir.$filenameWithoutExtension.'.'.$thisImageExtension.'', $data);
|
||
}
|
||
|
||
return array($ThisFileSizeInMB,$file_duration,$file_bitrate,$file_freq,$thisFileTitleID3,$thisFileArtistID3);
|
||
|
||
}
|
||
|
||
|
||
|
||
function readMediaDir ($absoluteurl,$upload_dir) {
|
||
|
||
//List of directories or files to exclude
|
||
$toExclude = array("..",".","index.htm","_vti_cnf",".DS_Store",".svn",".xml");
|
||
|
||
$handle = opendir ($absoluteurl.$upload_dir);
|
||
$files_array = array(); //null array
|
||
while (($filename = readdir ($handle)) !== false)
|
||
{
|
||
if (!in_array($filename, $toExclude)) $files_array[$filename] = filemtime ($absoluteurl.$upload_dir.$filename);
|
||
}
|
||
|
||
//$files_array has the file name as key and the file date as value - here we sort inversely by time
|
||
arsort ($files_array); //opposite of asort
|
||
|
||
//Now that the array as been ordered by date (most recent on top), we can keep just keys (file names)
|
||
$fileNamesList = array_keys($files_array);
|
||
|
||
//array containing all the accepted files names in media folder, with the exception of $toExclude
|
||
return $fileNamesList;
|
||
}
|
||
|
||
|
||
|
||
##################################################################################
|
||
##################################################################################
|
||
## GENERATE PODCAST RSS FEED
|
||
|
||
//GeneratePodcastFeed $outputInFile TRUE writes to a file (feed.xml), FALSE prints on screen, $manualRegeneration means that the function is called explicitly by the user (and writeEpisodeXMLDB is called)
|
||
function generatePodcastFeed ($outputInFile,$category,$manualRegeneration) {
|
||
|
||
//include functions and variables in config.php
|
||
include("core/includes.php");
|
||
|
||
|
||
//// Set custom web url (shown in iTunes Store), if specified in config.php
|
||
if (isset($feed_iTunes_LINKS_Website) AND $feed_iTunes_LINKS_Website != NULL) {
|
||
$podcastWebHomePage = $feed_iTunes_LINKS_Website; }
|
||
else { $podcastWebHomePage = $url; }
|
||
|
||
|
||
//// Define feed filename
|
||
$feedfilename = $absoluteurl.$feed_dir."feed.xml";
|
||
|
||
//// Rewrite the language var to adhere to ISO639
|
||
$feed_language = languageISO639($feed_language);
|
||
|
||
|
||
##### Clean categories strings
|
||
#Depurate feed content according to iTunes specifications
|
||
$itunes_category[0] = depurateContent($itunes_category[0]);
|
||
$itunes_category[1] = depurateContent($itunes_category[1]);
|
||
$itunes_category[2] = depurateContent($itunes_category[2]);
|
||
|
||
//If a different URL is specified in config.php
|
||
if (isset($feed_URL_replace) AND $feed_URL_replace != NULL)
|
||
{ $feed_url = $feed_URL_replace; }
|
||
else { $feed_url = $url.$feed_dir."feed.xml"; }
|
||
|
||
//iTunes Cover art (jpg or png)
|
||
if (file_exists($absoluteurl.$img_dir.'itunes_image.jpg')) {
|
||
$podcastCoverArt = $url.$img_dir.'itunes_image.jpg';
|
||
} else if (file_exists($absoluteurl.$img_dir.'itunes_image.png')) {
|
||
$podcastCoverArt = $url.$img_dir.'itunes_image.png';
|
||
} else { $podcastCoverArt = ""; }
|
||
|
||
|
||
//RSS FEED HEADER
|
||
$head_feed =
|
||
'<?xml version="1.0" encoding="'.$feed_encoding.'"?>
|
||
<!-- generator="Podcast Generator '.$podcastgen_version.'" -->
|
||
<rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xml:lang="'.$feed_language.'" version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||
<channel>
|
||
<title>'.$podcast_title.'</title>
|
||
<link>'.$podcastWebHomePage.'</link>
|
||
<atom:link href="'.$feed_url.'" rel="self" type="application/rss+xml" />
|
||
<description>'.$podcast_description.'</description>
|
||
<generator>Podcast Generator '.$podcastgen_version.' - http://www.podcastgenerator.net</generator>
|
||
<lastBuildDate>'.date("r").'</lastBuildDate>
|
||
<language>'.$feed_language.'</language>
|
||
<copyright>'.$copyright.'</copyright>
|
||
<itunes:image href="'.$podcastCoverArt.'" />
|
||
<image>
|
||
<url>'.$podcastCoverArt.'</url>
|
||
<title>'.$podcast_title.'</title>
|
||
<link>'.$podcastWebHomePage.'</link>
|
||
</image>
|
||
<itunes:summary>'.$podcast_description.'</itunes:summary>
|
||
<itunes:subtitle>'.$podcast_subtitle.'</itunes:subtitle>
|
||
<itunes:author>'.$author_name.'</itunes:author>
|
||
<itunes:owner>
|
||
<itunes:name>'.$author_name.'</itunes:name>
|
||
<itunes:email>'.$author_email.'</itunes:email>
|
||
</itunes:owner>
|
||
<itunes:explicit>'.$explicit_podcast.'</itunes:explicit>
|
||
';
|
||
|
||
|
||
//// iTunes categories (and subcategories, which are separated by :)
|
||
//category 1
|
||
if ($itunes_category[0]!=NULL) {
|
||
$tmpcat = explode(":",$itunes_category[0]);
|
||
$head_feed.= '
|
||
<itunes:category text="'.$tmpcat[0].'">';
|
||
//Sub Category
|
||
if (isset($tmpcat[1]) AND $tmpcat[1]!=NULL) $head_feed.= '<itunes:category text="'.$tmpcat[1].'" />';
|
||
$head_feed.= '</itunes:category>
|
||
';
|
||
} //end category 1
|
||
//category 2
|
||
if ($itunes_category[1]!=NULL) {
|
||
$tmpcat = explode(":",$itunes_category[1]);
|
||
$head_feed.= '<itunes:category text="'.$tmpcat[0].'">';
|
||
//Sub Category
|
||
if (isset($tmpcat[1]) AND $tmpcat[1]!=NULL) $head_feed.= '<itunes:category text="'.$tmpcat[1].'" />';
|
||
$head_feed.= '</itunes:category>
|
||
';
|
||
} //end category 2
|
||
//category 3
|
||
if ($itunes_category[2]!=NULL) {
|
||
$tmpcat =explode(":",$itunes_category[2]);
|
||
$head_feed.= '<itunes:category text="'.$tmpcat[0].'">';
|
||
//Sub Category
|
||
if (isset($tmpcat[1]) AND $tmpcat[1]!=NULL) $head_feed.= '<itunes:category text="'.$tmpcat[1].'" />';
|
||
$head_feed.= '</itunes:category>
|
||
';
|
||
} //end category 3
|
||
|
||
|
||
//// List all the items (i.e. podcast episodes)
|
||
// Open podcast directory
|
||
$fileNamesList = readMediaDir ($absoluteurl,$upload_dir);
|
||
|
||
$episodes_feed = NULL; //define variable
|
||
if (!empty($fileNamesList)) { // If media directory contains files
|
||
|
||
$episodesCounter = 0; //set counter to zero
|
||
|
||
// Loop through each file in the media directory
|
||
foreach ($fileNamesList as $singleFileName) {
|
||
|
||
//Limit episodes in the feed (from config.php)
|
||
if ($episodesCounter < $recent_episode_in_feed OR $recent_episode_in_feed == "All") {
|
||
|
||
////Validate the current episode
|
||
//NB. validateSingleEpisode returns [0] episode is supported (bool), [1] Episode Absolute path, [2] Episode XML DB absolute path,[3] File Extension (Type), [4] File MimeType, [5] File name without extension, [6] episode file supported but to XML present
|
||
$thisPodcastEpisode = validateSingleEpisode($singleFileName);
|
||
|
||
|
||
////If episode is supported and has a related xml db, and if it's not set to a future date OR if it's set for a future date but you are logged in as admin
|
||
if (($thisPodcastEpisode[0]==TRUE AND !publishInFuture($thisPodcastEpisode[1]))) {
|
||
|
||
|
||
////Parse XML data related to the episode
|
||
// NB. Function parseXMLepisodeData returns: [0] episode title, [1] short description, [2] long description, [3] image associated, [4] iTunes keywords, [5] Explicit language,[6] Author's name,[7] Author's email,[8] PG category 1, [9] PG category 2, [10] PG category 3, [11] file_info_size, [12] file_info_duration, [13] file_info_bitrate, [14] file_info_frequency
|
||
$thisPodcastEpisodeData = parseXMLepisodeData($thisPodcastEpisode[2]);
|
||
|
||
|
||
//// If feed manually regenerated, recreate XML DB for each file when XML does not contain file data such as size, duration etc... (i.e. <fileInfoPG> tag)
|
||
// NB. The following function is transitional, to enable new XML tags in the file XML data introduced with PG 2.3: it can be removed in future versions.
|
||
// We check for data about episode size ($thisPodcastEpisodeData[11]) cause all the episodes should have it, if not, the XML was generated with a version of PG < 2.3
|
||
// We also check whether $thisPodcastEpisodeData[3] (image) is null. From PG 2.4 the image field can be a) a file name (for retro compatibility with older versions), b) 1 (mp3 parsed for embedded image. If image exists the file is extracted automatically in the images/ folder by the function retrieveMediaFileDetails)
|
||
if ($manualRegeneration AND $thisPodcastEpisodeData[11] == NULL OR $manualRegeneration AND $thisPodcastEpisodeData[3] == "") { //NB $thisPodcastEpisodeData[3] = to "" empty and not NULL (it exists but does not contain any value).
|
||
//// Remapping data from parseXMLepisodeData to be sent as a parameter to writeEpisodeXMLDB
|
||
$thisEpisodeDataToWriteInXML[0] = $thisPodcastEpisodeData[0]; // Title
|
||
$thisEpisodeDataToWriteInXML[1] = $thisPodcastEpisodeData[1]; // Short Desc
|
||
$thisEpisodeDataToWriteInXML[2] = $thisPodcastEpisodeData[2]; // Long Desc
|
||
|
||
//Image embedded or specified in the XML file is empty (no values)
|
||
if ($thisPodcastEpisodeData[3] == "") $thisEpisodeDataToWriteInXML[3] = 1; // assign value of 1 (so in future it won't be processed)
|
||
else $thisEpisodeDataToWriteInXML[3] = $thisPodcastEpisodeData[3]; // Image
|
||
|
||
$thisEpisodeDataToWriteInXML[4] = array($thisPodcastEpisodeData[8],$thisPodcastEpisodeData[9],$thisPodcastEpisodeData[10]); // Categories
|
||
$thisEpisodeDataToWriteInXML[5] = $thisPodcastEpisodeData[4]; // Keywords
|
||
$thisEpisodeDataToWriteInXML[6] = $thisPodcastEpisodeData[5]; // Explicit
|
||
$thisEpisodeDataToWriteInXML[7] = $thisPodcastEpisodeData[6]; // Auth name
|
||
$thisEpisodeDataToWriteInXML[8] = $thisPodcastEpisodeData[7]; // Auth email
|
||
|
||
//Episode size and data from GETID3 from retrieveMediaFileDetails function
|
||
//NB retrieveMediaFileDetails returns: [0] $ThisFileSizeInMB, [1] $file_duration, [2] $file_bitrate, [3] $file_freq, [4] $thisFileTitleID3, [5] $thisFileArtistID3
|
||
$episodeID3 = retrieveMediaFileDetails ($thisPodcastEpisode[1],$absoluteurl,$thisPodcastEpisode[5],$img_dir);
|
||
|
||
//Rewrite the XML data file of this episode (including the fileInfoPG tag)
|
||
writeEpisodeXMLDB($thisEpisodeDataToWriteInXML,$absoluteurl,$thisPodcastEpisode[1],$thisPodcastEpisode[2],$thisPodcastEpisode[5],TRUE);
|
||
|
||
} //end if $manualRegeneration
|
||
|
||
|
||
//// If category is specified, show just episodes belonging to it (if the current is not, skip this loop)
|
||
if (isset($category) AND $category != NULL AND $category != $thisPodcastEpisodeData[8] AND $category != $thisPodcastEpisodeData[9] AND $category != $thisPodcastEpisodeData[10]) {
|
||
continue;
|
||
}
|
||
|
||
|
||
//// Content Depuration (to avoid validation errors in the RSS feed)
|
||
|
||
$text_title = depurateContent($thisPodcastEpisodeData[0]); //title
|
||
$text_shortdesc = depurateContent($thisPodcastEpisodeData[1]); //short desc
|
||
$text_longdesc = iTunesSummaryLinks(depurateContent($thisPodcastEpisodeData[2]));
|
||
$text_keywordspg = depurateContent($thisPodcastEpisodeData[4]); //Keywords
|
||
$text_authornamepg = depurateContent($thisPodcastEpisodeData[6]); //author's name
|
||
$text_authoremailpg = depurateContent($thisPodcastEpisodeData[7]);
|
||
|
||
// Other Data from the file
|
||
$text_explicit = $thisPodcastEpisodeData[5];
|
||
$file_size = filesize($thisPodcastEpisode[1]);
|
||
$filetime = filemtime($thisPodcastEpisode[1]);
|
||
$filepubdate = date ('r', $filetime);
|
||
$filemimetype = $thisPodcastEpisode[4];
|
||
$fileDuration = $thisPodcastEpisodeData[12];
|
||
|
||
$episodes_feed.= '
|
||
<item>
|
||
<title>'.$text_title.'</title>
|
||
<itunes:subtitle>'.$text_shortdesc.'</itunes:subtitle>
|
||
<itunes:summary>'.$text_longdesc.'</itunes:summary>
|
||
<description>'.$text_shortdesc.'</description>
|
||
<link>'.$link.$singleFileName.'</link>
|
||
<enclosure url="'.$url.$upload_dir.$singleFileName.'" length="'.$file_size.'" type="'.$filemimetype.'"/>
|
||
<guid>'.$link.$singleFileName.'</guid>
|
||
';
|
||
|
||
//// Duration
|
||
if($fileDuration != NULL) {
|
||
$episodes_feed.= '<itunes:duration>'.$fileDuration.'</itunes:duration>
|
||
';
|
||
}
|
||
|
||
|
||
|
||
//Image associated to single episode
|
||
if (file_exists($absoluteurl.$img_dir.$thisPodcastEpisode[5].'.jpg')) {
|
||
$episodes_feed.= '<itunes:image href="'.$url.$img_dir.$thisPodcastEpisode[5].'.jpg" />
|
||
';
|
||
}
|
||
else if (file_exists($absoluteurl.$img_dir.$thisPodcastEpisode[5].'.png')) {
|
||
$episodes_feed.= '<itunes:image href="'.$url.$img_dir.$thisPodcastEpisode[5].'.png" />
|
||
';
|
||
}
|
||
|
||
|
||
|
||
//// Author
|
||
// If no author specified, use default author from config.php
|
||
if ($text_authornamepg == NULL OR $text_authornamepg == ",") {
|
||
$episodes_feed.= '<author>'.$author_email.' ('.$author_name.')</author>
|
||
<itunes:author>'.$author_name.'</itunes:author>
|
||
';
|
||
} else {
|
||
$episodes_feed.= '<author>'.$text_authoremailpg.' ('.$text_authornamepg.')</author>
|
||
<itunes:author>'.$text_authornamepg.'</itunes:author>
|
||
';
|
||
}
|
||
|
||
|
||
//// Keywords
|
||
if ($text_keywordspg!=NULL) { //if keywords are present
|
||
$episodes_feed.= '<itunes:keywords>'.$text_keywordspg.'</itunes:keywords>
|
||
';
|
||
}
|
||
|
||
|
||
//// Explicit
|
||
if ($text_explicit!=NULL) {
|
||
$episodes_feed.= '<itunes:explicit>'.$text_explicit.'</itunes:explicit>
|
||
';
|
||
}
|
||
|
||
//// File Date
|
||
$episodes_feed.= '<pubDate>'.$filepubdate.'</pubDate>
|
||
</item>
|
||
';
|
||
|
||
$episodesCounter++; // increment recent counter
|
||
|
||
} // END - If episode is supported
|
||
} // END - Limit episodes in the feed
|
||
} // END - Loop through each file in the media directory
|
||
} // END - If media directory contains files
|
||
|
||
|
||
|
||
//// RSS Feed Tail
|
||
$tail_feed = '
|
||
</channel>
|
||
</rss>';
|
||
|
||
//// Construct Output
|
||
$finalRSSfeed = $head_feed.$episodes_feed.$tail_feed;
|
||
|
||
// Output in a file
|
||
if ($outputInFile == TRUE) {
|
||
$fp1 = fopen($feedfilename, "w+"); //Open for reading and empty
|
||
fclose($fp1);
|
||
|
||
$fp = fopen($feedfilename, "a+"); //testa xml
|
||
fwrite($fp, $finalRSSfeed);
|
||
fclose($fp);
|
||
}
|
||
// Output on screen
|
||
else {
|
||
echo $finalRSSfeed;
|
||
}
|
||
|
||
if (!isset($episodesCounter)) $episodesCounter = 0;
|
||
return $episodesCounter;
|
||
|
||
}
|
||
## END - GENERATE PODCAST RSS FEED
|
||
##################################################################################
|
||
|
||
|
||
|
||
function attachToEpisode ($episodeFileNameWithoutExtension,$episodeFileExtension,$episodeTitle) {
|
||
//include functions and variables in config.php
|
||
include("core/includes.php");
|
||
|
||
//NB $url comes from config.php
|
||
$fullURL = $url."?name=".$episodeFileNameWithoutExtension.'.'.$episodeFileExtension; //full URL of the episode
|
||
|
||
$outputToReturn = NULL;
|
||
|
||
// CUSTOMIZED CODE TO EMBED along with each episode
|
||
// IF a file called embed-code.txt is manually created in the root of Podcast Generator. The content of that file will be displayed along with each episode
|
||
if(file_exists($absoluteurl."embed-code.txt")){
|
||
$embeddedcodetoshow = file_get_contents($absoluteurl."embed-code.txt");
|
||
$outputToReturn .= $embeddedcodetoshow; }
|
||
|
||
//SOCIAL NETWORKS INTEGRATION
|
||
//if the parameter "noextras" (e.g. ?p=archive&cat=all&noextras) is passed in the GET, then no social network integration is displayed
|
||
if (!isset($_GET['noextras'])) {
|
||
if (in_array(TRUE,$enablesocialnetworks)) { //IF at least one value of config.php is true
|
||
$outputToReturn .= displaySocialNetworkButtons($fullURL,$episodeTitle,$enablesocialnetworks[0],$enablesocialnetworks[1],$enablesocialnetworks[2]); //0 is FB, 1 twitter, 2 G+
|
||
//Blank space
|
||
$outputToReturn .= '<br />';
|
||
}
|
||
}
|
||
|
||
return $outputToReturn;
|
||
}
|
||
|
||
|
||
function validateSingleEpisode ($episodeFile) {
|
||
//include functions and variables in config.php
|
||
|
||
include("core/includes.php");
|
||
|
||
$episodeFile_parts = divideFilenameFromExtension($episodeFile); // PHP >= 5.2.0 needed
|
||
$episodeFilenameWithoutExtension = $episodeFile_parts[0];
|
||
$EpisodeFileExtension = strtolower($episodeFile_parts[1]); //lowercase extension
|
||
$checkEpisodeFileFormat = checkFileType($EpisodeFileExtension,$absoluteurl);
|
||
$episodeFileType = $checkEpisodeFileFormat[0];
|
||
$episodeFileMimeType = $checkEpisodeFileFormat[1];
|
||
$episodeFileFullPath = $absoluteurl.$upload_dir.$episodeFile;
|
||
$episodeFileXMLDB = $absoluteurl.$upload_dir.$episodeFilenameWithoutExtension.'.xml'; //database file
|
||
|
||
//If media file is ok and XML file is associated to it
|
||
if (isset($episodeFileType) AND $EpisodeFileExtension==$episodeFileType AND file_exists($episodeFileXMLDB)) {
|
||
//NB. $GoForIt = TRUE means that the episode file format is supported, it has a corresponding XML data file
|
||
$GoForIt = TRUE;
|
||
$OkButNoXMLDBpresent = FALSE;
|
||
}
|
||
//If media file is ok but no XML file is associated (i.e. auto index / FTP feature)
|
||
else if (isset($episodeFileType) AND $EpisodeFileExtension==$episodeFileType AND !file_exists($episodeFileXMLDB)) {
|
||
$GoForIt = FALSE;
|
||
$OkButNoXMLDBpresent = TRUE;
|
||
}
|
||
else {
|
||
$GoForIt = FALSE;
|
||
$OkButNoXMLDBpresent = FALSE;
|
||
}
|
||
|
||
return array($GoForIt,$episodeFileFullPath,$episodeFileXMLDB,$episodeFileType,$episodeFileMimeType,$episodeFilenameWithoutExtension,$OkButNoXMLDBpresent);
|
||
|
||
}
|
||
|
||
|
||
|
||
//DETECT WHETHER USER IS LOGGED-IN OR NOT
|
||
function isUserLogged () {
|
||
//// Security code (Register Globals ON)
|
||
if (isset($_REQUEST['GLOBALS'])) { exit; }
|
||
|
||
//read user and md5 pwd from config.php
|
||
if (file_exists("config.php")) include("config.php");
|
||
//compare sessions to stored user and md5 pwd
|
||
if(isset($_SESSION["user_session"]) AND $_SESSION["user_session"]==$username AND md5($_SESSION["password_session"])==$userpassword) { return TRUE; }
|
||
else { return FALSE; }
|
||
}
|
||
|
||
|
||
// Is the episode set to a future date?
|
||
function publishInFuture($filefullpath) {
|
||
$fileTime = 0;
|
||
if (file_exists($filefullpath)) $fileTime = filemtime($filefullpath);
|
||
if ($fileTime > time()) return TRUE;
|
||
else return FALSE;
|
||
}
|
||
|
||
|
||
function parseXMLepisodeData ($episodeFileXMLDB) {
|
||
|
||
$parser = simplexml_load_file($episodeFileXMLDB,'SimpleXMLElement',LIBXML_NOCDATA);
|
||
//var_dump($parser); //Debug
|
||
|
||
//NB. to handle CDATA values see: http://blog.evandavey.com/2008/04/how-to-fix-simplexml-cdata-problem-in-php.html
|
||
|
||
//Parse the episode in the xml file - just one episode (array [0]) is stored in each XML file
|
||
$episode_title = $parser->episode[0]->titlePG[0]; //episode title
|
||
$episode_shortdesc = $parser->episode[0]->shortdescPG[0]; //short description
|
||
$episode_longdesc = $parser->episode[0]->longdescPG[0]; // long description
|
||
$episode_imgpg = $parser->episode[0]->imgPG[0]; // image (url) associated to episode
|
||
$episode_keywordspg = $parser->episode[0]->keywordsPG[0]; //iTunes keywords
|
||
$episode_explicitpg = $parser->episode[0]->explicitPG[0]; //explicit podcast (yes or no)
|
||
$episode_authornamepg = $parser->episode[0]->authorPG[0]->namePG[0]; //author's name
|
||
$episode_authoremailpg = $parser->episode[0]->authorPG[0]->emailPG[0]; //author's email
|
||
|
||
//categories
|
||
$episode_category1 = $parser->episode[0]->categoriesPG[0]->category1PG[0];
|
||
$episode_category2 = $parser->episode[0]->categoriesPG[0]->category2PG[0];
|
||
$episode_category3 = $parser->episode[0]->categoriesPG[0]->category3PG[0];
|
||
|
||
//Until PG 2.2 this data was read from the media file in real time, from 2.3+ it'll be stored in the XML
|
||
$file_info_size = NULL;
|
||
$file_info_duration = NULL;
|
||
$file_info_bitrate = NULL;
|
||
$file_info_frequency = NULL;
|
||
if (isset($parser->episode[0]->fileInfoPG[0]->size[0])) $file_info_size = $parser->episode[0]->fileInfoPG[0]->size[0];
|
||
if (isset($parser->episode[0]->fileInfoPG[0]->duration[0])) $file_info_duration = $parser->episode[0]->fileInfoPG[0]->duration[0];
|
||
if (isset($parser->episode[0]->fileInfoPG[0]->bitrate[0])) $file_info_bitrate = $parser->episode[0]->fileInfoPG[0]->bitrate[0];
|
||
if (isset($parser->episode[0]->fileInfoPG[0]->frequency[0])) $file_info_frequency = $parser->episode[0]->fileInfoPG[0]->frequency[0];
|
||
|
||
|
||
return array($episode_title,$episode_shortdesc,$episode_longdesc,$episode_imgpg,$episode_keywordspg,$episode_explicitpg,$episode_authornamepg,$episode_authoremailpg,$episode_category1,$episode_category2,$episode_category3,$file_info_size,$file_info_duration,$file_info_bitrate,$file_info_frequency);
|
||
|
||
}
|
||
|
||
|
||
// $readID3 is a bool (true on first upload and on manual RSS regeneration)
|
||
function writeEpisodeXMLDB ($thisEpisodeData,$absoluteurl,$episodeFileAbsPath,$episodeXMLDBAbsPath,$episodeFileNameWithoutExtension,$readID3) {
|
||
|
||
|
||
include($absoluteurl."core/includes.php");
|
||
|
||
|
||
|
||
//NB. $thisEpisodeData array contains [0] $title, [1] $description, [2] $long_description, [3] $image_new_name, [4] $category (array), [5] $keywords, [6] $explicit, [7] $auth_name, [8] $auth_email
|
||
|
||
|
||
$xmlfiletocreate = '<?xml version="1.0" encoding="'.$feed_encoding.'"?>
|
||
<PodcastGenerator>
|
||
<episode>
|
||
<titlePG><![CDATA['.$thisEpisodeData[0].']]></titlePG>
|
||
<shortdescPG><![CDATA['.$thisEpisodeData[1].']]></shortdescPG>
|
||
<longdescPG><![CDATA['.$thisEpisodeData[2].']]></longdescPG>
|
||
<imgPG>'.$thisEpisodeData[3].'</imgPG>
|
||
<categoriesPG>
|
||
<category1PG>';
|
||
if(isset($thisEpisodeData[4][0]) AND $thisEpisodeData[4][0]!= NULL){
|
||
$xmlfiletocreate .= depurateContent($thisEpisodeData[4][0]);
|
||
}
|
||
$xmlfiletocreate .='</category1PG>
|
||
<category2PG>';
|
||
if(isset($thisEpisodeData[4][1]) AND $thisEpisodeData[4][1]!= NULL){
|
||
$xmlfiletocreate .= depurateContent($thisEpisodeData[4][1]);
|
||
}
|
||
$xmlfiletocreate .='</category2PG>
|
||
<category3PG>';
|
||
if(isset($thisEpisodeData[4][2]) AND $thisEpisodeData[4][2]!= NULL){
|
||
$xmlfiletocreate .= depurateContent($thisEpisodeData[4][2]);
|
||
}
|
||
$xmlfiletocreate .='</category3PG>
|
||
</categoriesPG>
|
||
<keywordsPG><![CDATA['.$thisEpisodeData[5].']]></keywordsPG>
|
||
<explicitPG>'.$thisEpisodeData[6].'</explicitPG>
|
||
<authorPG>
|
||
<namePG>'.depurateContent($thisEpisodeData[7]).'</namePG>
|
||
<emailPG>'.$thisEpisodeData[8].'</emailPG>
|
||
</authorPG>';
|
||
|
||
|
||
$episodeID3 = array(); //Declaration
|
||
if ($readID3 == TRUE) {
|
||
|
||
//Episode size and data from GETID3 from retrieveMediaFileDetails function
|
||
//NB retrieveMediaFileDetails returns: [0] $ThisFileSizeInMB, [1] $file_duration, [2] $file_bitrate, [3] $file_freq, [4] $thisFileTitleID3, [5] $thisFileArtistID3
|
||
$episodeID3 = retrieveMediaFileDetails ($episodeFileAbsPath,$absoluteurl,$episodeFileNameWithoutExtension,$img_dir);
|
||
|
||
$xmlfiletocreate .='
|
||
<fileInfoPG>';
|
||
if(isset($episodeID3[0]) AND $episodeID3[0]!= NULL){
|
||
$xmlfiletocreate .= '
|
||
<size>'.$episodeID3[0].'</size>';
|
||
}
|
||
if(isset($episodeID3[1]) AND $episodeID3[1]!= NULL){
|
||
$xmlfiletocreate .= '
|
||
<duration>'.$episodeID3[1].'</duration>';
|
||
}
|
||
//NB variable bitrate is rounded to int
|
||
if(isset($episodeID3[2]) AND $episodeID3[2]!= NULL){
|
||
$xmlfiletocreate .= '
|
||
<bitrate>'.round($episodeID3[2]).'</bitrate>';
|
||
}
|
||
if(isset($episodeID3[3]) AND $episodeID3[3]!= NULL){
|
||
$xmlfiletocreate .= '
|
||
<frequency>'.$episodeID3[3].'</frequency>';
|
||
}
|
||
}
|
||
|
||
$xmlfiletocreate .='
|
||
</fileInfoPG>
|
||
</episode>
|
||
</PodcastGenerator>';
|
||
|
||
|
||
//// Write the XMK file
|
||
$fp = fopen($episodeXMLDBAbsPath,'w');
|
||
fwrite($fp,$xmlfiletocreate);
|
||
fclose($fp);
|
||
|
||
}
|
||
|
||
|
||
// NB. Former "FTP Feature"
|
||
function autoIndexingEpisodes () {
|
||
|
||
include("core/includes.php");
|
||
|
||
// Open podcast directory and read all the files contained
|
||
$fileNamesList = readMediaDir ($absoluteurl,$upload_dir);
|
||
|
||
|
||
if (!empty($fileNamesList)) { // If media directory contains files
|
||
|
||
$episodesCounter = 0; //set counter to zero
|
||
|
||
// Loop through each file in the media directory
|
||
foreach ($fileNamesList as $singleFileName) {
|
||
|
||
////Validate the current episode
|
||
//NB. validateSingleEpisode returns [0] episode is supported (bool), [1] Episode Absolute path, [2] Episode XML DB absolute path,[3] File Extension (Type), [4] File MimeType, [5] File name without extension, [6] episode file supported but to XML present
|
||
$thisPodcastEpisode = validateSingleEpisode($singleFileName);
|
||
|
||
////If episode is supported and does NOT have a related xml db
|
||
if ($thisPodcastEpisode[6]==TRUE) {
|
||
|
||
|
||
// From config.php
|
||
if ($strictfilenamepolicy == "yes") {
|
||
$episodeNewFileName = date('Y-m-d')."_".renamefilestrict($thisPodcastEpisode[5]);
|
||
}
|
||
else {
|
||
$episodeNewFileName = renamefile($thisPodcastEpisode[5]);
|
||
}
|
||
|
||
//lowercase extension
|
||
$episodeNewFileExtension = strtolower($thisPodcastEpisode[3]);
|
||
|
||
// New file full path
|
||
$episodeNewNameAbsPath = $absoluteurl.$upload_dir.$episodeNewFileName.'.'.$episodeNewFileExtension;
|
||
//if file already exists add an incremental suffix
|
||
|
||
|
||
$filesuffix = NULL;
|
||
while (file_exists($episodeNewNameAbsPath)) {
|
||
$filesuffix++;
|
||
$episodeNewNameAbsPath = $absoluteurl.$upload_dir.$episodeNewFileName.$filesuffix.'.'.$episodeNewFileExtension;
|
||
}
|
||
|
||
|
||
if (file_exists($thisPodcastEpisode[1])) {
|
||
//rename episode
|
||
rename ($thisPodcastEpisode[1],$episodeNewNameAbsPath);
|
||
// Change file date to now
|
||
touch($episodeNewNameAbsPath,time());
|
||
} else { exit; }
|
||
|
||
|
||
//Episode size and data from GETID3 from retrieveMediaFileDetails function
|
||
//NB retrieveMediaFileDetails returns: [0] $ThisFileSizeInMB, [1] $file_duration, [2] $file_bitrate, [3] $file_freq, [4] $thisFileTitleID3, [5] $thisFileArtistID3
|
||
$episodeID3 = retrieveMediaFileDetails ($episodeNewNameAbsPath,$absoluteurl,$thisPodcastEpisode[5],$img_dir);
|
||
|
||
//// Assign title and short description (from ID3 title and artist, respectively. Or default)
|
||
if ($episodeID3[4]!= "") $thisEpisodeTitle = $episodeID3[4];
|
||
else $thisEpisodeTitle = $thisPodcastEpisode[5];
|
||
if ($episodeID3[5]!= "") $thisEpisodeShortDesc = $episodeID3[5];
|
||
else $thisEpisodeShortDesc = _("Podcast Episode");
|
||
|
||
// Use GETID3 Title and Artist to fill title and description automatically
|
||
$thisEpisodeData = array($thisEpisodeTitle,$thisEpisodeShortDesc,NULL,NULL,NULL,NULL,$explicit_podcast,NULL,NULL);
|
||
|
||
$episodeXMLDBAbsPath = $absoluteurl.$upload_dir.$episodeNewFileName.$filesuffix.'.xml';
|
||
//// Creating xml file associated to episode
|
||
writeEpisodeXMLDB($thisEpisodeData,$absoluteurl,$episodeNewNameAbsPath,$episodeXMLDBAbsPath,$episodeNewFileName.$filesuffix,TRUE);
|
||
|
||
$episodesCounter++;
|
||
|
||
} // END - If episode is supported
|
||
|
||
} // END - Loop through each file
|
||
|
||
} // END - If media directory contains files
|
||
|
||
return $episodesCounter;
|
||
|
||
}
|
||
|
||
|
||
?>
|