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://podcastgen.sourceforge.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; } 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); } else { echo $finalRSSfeed; } if (!isset($episodesCounter)) { $episodesCounter = 0; } return $episodesCounter; }
$filename = $_GET['filename']; //Clean variable, avoid downloading of file outside podcast generator root directory. $filename = str_replace("/", "", $filename); // Replace / in the filename $filename = str_replace("\\", "", $filename); // Replace \ in the filename $filename_path = $absoluteurl . $upload_dir . $filename; // absolute path of the filename to download if (file_exists($filename_path)) { $file_media = divideFilenameFromExtension($filename); $fileData = checkFileType($file_media[1], $absoluteurl); $podcast_filetype = $fileData[0]; $filemimetype = $fileData[1]; $isFileSupported = $fileData[2]; // SECURITY OPTION: if extension is supported (file to download must have a known episode extension) if ($isFileSupported == TRUE and $file_media[1] == $podcast_filetype and !publishInFuture($filename_path)) { //// Headers ### required by internet explorer if (ini_get('zlib.output_compression')) { ini_set('zlib.output_compression', 'Off'); } ### header("Pragma: public"); // required header("Expires: 0"); header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header("Cache-Control: private", false); // required for certain browsers header("Content-Type: {$filemimetype}"); header("Content-Disposition: attachment; filename=" . basename($filename_path) . ";"); header("Content-Transfer-Encoding: binary");