· 8 years ago · Jan 05, 2018, 01:30 AM
1<?php
2
3/*
4 * Podcast URL Extractor
5 * implemented at http://itunes.so-nik.com
6 *
7 * All code has been re-written by lasavior.
8 * Original code & inspiration from Michael Sitarzewski, zerologic.com
9 *
10 * Ex: http://ax.phobos.apple.com.edgesuite.net/WebObjects/MZStore.woa/wa/viewPodcast?id=269238657
11 * Ex: http://itunes.apple.com/us/podcast/hombre-potato/id319810190?uo=4
12 *
13 * Usage: itunes.php?http://itunes.apple.com/us/podcast/the-morning-stream/id414564832?uo=4
14 * Returns: http://myextralife.com/ftp/radio/morningstream.xml
15
16CHANGE LOG:::
17EDIT 5/10/11: Removed flat-file database storing. Reformatted for SQLite (requires PHP 5 and above). Script will create database & table if they dont exist.
18
19EDIT 6/2/11: Added safety catch for iTunes-U URL's. (Currently Apple does not offer a way to subscribe to these outside of iTunes [as far as i've seen]). Also touched up a little bit of code here & there.
20
21EDIT 6/21/11: Added another safety catch for iTunes-U pages. Now instead of just checking the URL, it will also check the page content (as there are links that do not include the tag 'itunes-u' that was previously checked for).
22
23EDIT 6/28/11: Previous iTunes-U update was flawed and resulted in a lot of false-positives. Fixed in new update.
24
25EDIT 8/29/11: Added catch for material not available in the US store.
26
27EDIT 9/3/11: Removed POST option, changed to GET only. (if you wish to re-enable it, set $url = $_REQUEST['terms'];)
28
29EDIT 10/16/12: Changed the checkFEED function to look only for "http" instead of "http://" as it would fail on https:// links.
30EDIT 10/16/12: Script now checks a URL twice before determining that it doesn't work. Sometimes iTunes just doesn't want to cooperate the first time around.
31
32EDIT 10/23/12: Lots of little changes. Control structure changes (i used alt syntax improperly), plus adding in new error finding.
33
34EIDT 10/25/12: Minor fixes and restructuring to make the code flow better. Also fixed cache displaying error.
35 */
36
37
38//-----------------------------------------
39// a couple of settings
40$_SETT = array(
41 'hashalgo' => 'md5',
42 'contactemail' => 'admin@example.com',
43 'dbtable' => 'feedurls',
44 'dbfilename' => 'itnfedb.sqdb'
45 );
46
47//-----------------------------------------
48// the base URL
49$url = ($_GET['terms'] != null) ? urldecode(urldecode($_GET['terms'])) : urldecode(urldecode($_SERVER['QUERY_STRING']));
50$urlhash = hash($_SETT['hashalgo'], $url);
51
52//-----------------------------------------
53//Functions
54function curlfeed($churl) {
55
56 $ch = curl_init();
57 curl_setopt_array ($ch, array(
58 CURLOPT_RETURNTRANSFER => TRUE,
59 CURLOPT_FOLLOWLOCATION => TRUE,
60 CURLOPT_MAXREDIRS => 10,
61 CURLOPT_CONNECTTIMEOUT => 5,
62 CURLOPT_URL => $churl,
63 CURLOPT_USERAGENT => 'iTunes/9.1.1'
64 ));
65 $chresult = curl_exec($ch);
66 curl_close($ch);
67
68 return $chresult;
69 } //END function: curlfeed
70
71function subURL($urltosub, $string1 = 'feed-url="', $string2 ='"') {
72
73 $str1 = strpos($urltosub, $string1) + strlen($string1);
74 $str2 = strpos($urltosub, $string2, $str1);
75 $subbedstring = substr($urltosub, $str1, ($str2 - $str1));
76
77 return $subbedstring;
78 } //END function: subURL
79
80function checkFEED($thefeed, $mainURL, $isCached = NULL) {
81
82 global $feedURL, $invalidURL, $_SETT;
83
84 //For your reference, the following is called a HEREDOC
85 $badURL = <<<BADURL
86 <div style="font-size:15px;white-space:normal;max-width:400px">iTunes failed to return the feed-url.
87 <br>
88 <br>This may be due to different reasons:
89 <br> 1) the podcast has been deleted,
90 <br> 2) the podcast has no items,
91 <br> 3) the podcast may be outside the USA,
92 <br>and many other reasons im not aware of. Unfortunately iTunes isnt perfect (hence why your here).
93 <br>
94 <br>Im sorry my script was of no help to you. If you feel this was in error, you can <a href="outfeed.php?$mainURL" style="text-decoration:underline" target="_blank">view the source,</a><br> or you can always <a href="mailto:{$_SETT['contactemail']}?subject=IFE Error&body=URL i tried: $mainURL" style="display:inline;text-decoration:underline">email me</a> the URL and i will see if its fixable.</div>
95BADURL;
96
97 if (substr($thefeed, 0, 4) != "http") {
98
99 if (is_null($isCached)) {
100
101 $feedURL = $badURL;
102 } //END if: isCached
103 $invalidURL = "The cake is a lie.";
104 } //END if: http
105
106 } //END function: checkFEED
107
108//-----------------------------------------
109//Here we initiate the sqlite database and setup the cached variables
110if ($database = sqlite_open($_SETT['dbfilename'], 0666, $sqlerror)) {
111
112 $check_cache_query = "SELECT url FROM {$_SETT['dbtable']} WHERE uniqueid='$urlhash'";
113 $cache_file = @sqlite_single_query($database, $check_cache_query, true);
114 if(sqlite_last_error($database)) {
115
116 $create_table_query = "CREATE TABLE {$_SETT['dbtable']}(uniqueid TEXT, url TEXT, date TEXT)";
117 @sqlite_exec($database, $create_table_query);
118 $cache_file = NULL;
119 } //END if: sqlite last error
120 } //END if: sqlite open
121else {
122
123 $failed_to_initialize_sqlite = $sqlerror;
124 } //END if: sqlite open
125
126//-----------------------------------------
127//For caching files, this determines if the cached file already exists
128if ($cache_file == NULL || isset($failed_to_initialize_sqlite)) {
129
130 //-----------------------------------------
131 //Here we identify the podcast url scheme
132 $idstyles = array(
133 '?id=',
134 '&id=',
135 '/id'
136 );
137
138 for ($counter = 0; $counter < count($idstyles); $counter++) {
139
140 if (strpos($url, $idstyles[$counter])) {
141
142 $idstyle = $idstyles[$counter];
143 $validID = "So, how are you holding up? Because I'm a potato!";
144 break;
145 } //END if: idstyles
146 } //END for: counter
147
148 //-----------------------------------------
149 //Since iTunes-U uses the same identifier symbols,
150 //this is where we rule them out until it is supported
151 //Note: more checking for itunes-u content is done farther below
152 if (strpos($url, '/itunes-u/')) {
153
154 unset($validID);
155 $invalidID = "itunes-u";
156 } //END if: itunes-u
157
158 //-----------------------------------------
159 // extract feed-id, get page from itunes & find feed-url
160 if (isset($validID)) {
161
162 for ($loopcount = 1; $loopcount < 3; $loopcount++) {
163
164 preg_match("/[0-9]+/", $url, $podid, 0, strpos($url, $idstyle)); // here we extract the feed ID
165 $curled1 = curlfeed("http://itunes.apple.com/podcast/id".$podid[0]);
166 if (strpos($curled1, "<key>kind</key><string>Goto</string>") > 1) {
167
168 $newURL = subURL($curled1, "<key>url</key><string>", "</string>");
169 $curled1 = curlfeed($newURL);
170 } //END if:goto
171
172 if (strpos($curled1, 'not currently available in the U.S. store')) {
173
174 $feedURL = <<<ITUNESFOREIGNSTORE
175 <div style="font-size:15px;white-space:normal;max-width:400px">This item is not available in the US store.
176 <br>
177 <br>(This may also be a problem with the podcast not existing in the iTunes store at all. Unfortunately iTunes returns the same error for both so they are indistinguishable from each other.) Apple currently restricts access to some content based on geographic locations. As I reside in the United States, I cannot retrieve your podcast link.
178 <br>
179 <br>If you have any PHP knowledge you can try translating the public source code to retrieve the URL on your own:
180 <br>http://snipplr.com/view/52465</div>
181ITUNESFOREIGNSTORE;
182 $invalidID = 'itunes_foreign';
183 } //END if: us store
184 elseif (strpos($curled1, '<span class="track-count">0 Items</span>')) {
185
186 $emptyPodcastText = <<<EMPTYPODCAST
187 <div style="font-size:15px;white-space:normal;max-width:400px"><b>Empty podcast.</b>
188 <br>
189 <br>Your podcast contains no episodes at the time this script last checked. Unfortunately Apple does not provide the feed URL for empty podcasts. Please check back in as little as 12 hours or once the podcast has active items.</div>
190EMPTYPODCAST;
191 $feedURL = $emptyPodcastText . "\n" . (time() + 60 * 60 * 12);
192 $invalidID = 'empty_podcast';
193 } //END if: 0 items
194 elseif (strpos($curled1, ' <key>message</key><string>Your request is temporarily unable to be processed.</string>') || strlen($curled1) < 20) {
195
196 if ($loopcount == 2) {
197
198 $feedURL = <<<CANTPROCESS
199 <div style="font-size:15px;white-space:normal;max-width:400px">Temporarily unable to process.
200 <br>
201 <br>iTunes returned the following error: "Your request is temporarily unable to be processed." Please try again later.</div>
202CANTPROCESS;
203 $invalidID = $doNotCacheResults = TRUE;
204 } //END if: loopcount
205 } //END if: unable to process
206 elseif (strpos($curled1, 'iTunes U')) { //Leave this as the last elseif as it may catch non-iTunesU material
207
208 $itunesU_title = subURL($curled1, '<title>', '</title>');
209 $itunesU_title_char = urlencode($itunesU_title);
210 $itunesU_crumbs = subURL($curled1, 'start breadcrumbs', 'end breadcrumbs');
211 $itunesU_li = subURL($itunesU_crumbs, '<li>', '</li>');
212 if (strpos($itunesU_li, 'iTunes U')) {
213
214 $feedURL = <<<ITUNESU
215 <div style="font-size:15px;white-space:normal;max-width:400px">iTunes-U links not supported.
216 <br>
217 <br>Currently Apple does not offer a way to subscribe to iTunes-U material outside of iTunes (that i can find). A temporary solution is to search for a similar title as a podcast in hopes that the content providers also posted it to the iTunes Podcast Directory (do no expect this for password protected content). Try searching for:
218 <br>"$itunesU_title"
219 <br>
220 <br>You can <a href='http://itunes.so-nik.com/index.php?terms=$itunesU_title_char' style="display:inline;text-decoration:underline;color:blue">click here</a> to try that now.</div>
221ITUNESU;
222 $invalidID = 'itunes-u';
223 } //END if: itunesu_li
224 } //END if: iTunes U
225 if (!isset($invalidID)) {
226
227 $feedURL = subURL($curled1);
228 checkFEED($feedURL, $url);
229 if (isset($invalidURL) && $loopcount == 1) {
230
231 unset($invalidURL, $podid);
232 sleep(2);
233 } // END if: loopcount
234 else {
235
236 break;
237 } //END if: loopcount
238 } //END if: invalidID
239 else {
240
241 break;
242 } //END if: invalidID
243 } //END for: loopcount
244
245 if (!isset($failed_to_initialize_sqlite) && !isset($doNotCacheResults)) {
246
247 $newfeedURL = sqlite_escape_string($feedURL);
248 $cache_query_put_content = "INSERT INTO {$_SETT['dbtable']} (uniqueid,url,date) VALUES ('$urlhash', '$newfeedURL', '".date("r")."'";
249 @sqlite_exec($database, $cache_query_put_content);
250 } //END if: failed sqlite
251 } //END if: validID
252 else {
253
254 if ($invalidID == "itunes-u") {
255
256 //Example URL: http://itunes.apple.com/itunes-u/the-civil-war-reconstruction/id341650730
257 $itu_label = subURL($url, '/itunes-u/', '/');
258 $itu_label_white = trim(ucwords(str_replace('-', ' ', $itu_label)));
259 $itu_label_char = str_replace('-', '%20', $itu_label);
260 $feedURL = <<<FEEDURL
261 <div style="font-size:15px;white-space:normal;max-width:400px">iTunes-U links not supported.
262 <br>
263 <br>Currently Apple does not offer a way to subscribe to iTunes-U material outside of iTunes (that i can find). A temporary solution is to search for a similar title as a podcast in hopes that the content providers also posted it to the iTunes Podcast Directory (do no expect this for password protected content). Try searching for:
264 <br>"$itu_label_white"
265 <br>
266 <br>You can <a href='http://itunes.so-nik.com/index.php?terms=$itu_label_char' style="display:inline;text-decoration:underline;color:blue">click here</a> to try that now.</div>
267FEEDURL;
268 } //END if: itunes-u
269 else {
270
271 $feedURL = "URL not supported. <br><br>Please contact <a href='mailto:{$_SETT['contactemail']}?subject=Feed-Error&body=Error on URL:$url' style=\"display:inline;text-decoration:underline\">{$_SETT['contactemail']}</a> <br>and notify me of the URL you are trying.";
272 $invalidID = "I was doing fine. Noone was trying to murder me, or put me in a potato, or feed me to birds.";
273 } //END if: itunes-u
274 } //END if: validID
275 } //END if: cache_file
276else {
277
278 $feedURL = $cache_file;
279 if (strpos($feedURL, '<b>Empty podcast.</b>')) {
280
281 $invalidID = TRUE;
282 $feedURL_explode = explode("\n", $feedURL);
283 if (time() > (int)trim(end($feedURL_explode))) {
284
285 $delete_table_query = "DELETE FROM {$_SETT['dbtable']} WHERE uniqueid='$urlhash'";
286 @sqlite_exec($database, $delete_table_query);
287 header("Location: " . $_SERVER["SCRIPT_URI"] . "?" . $_SERVER["QUERY_STRING"]);
288 exit;
289 } //END if: time
290 else {
291
292 $feedURL = implode("\n", explode("\n", $feedURL, -1));
293 } //END if: time
294 } //END if: empty podcast
295 elseif (stripos($feedURL, 'itunes-u')) {
296
297 $invalidID = 'itunes-u';
298 } //END elseif: itunes-u
299 else {
300
301 checkFEED($feedURL, $url, TRUE);
302 } //END if: empty podcast
303 } //END if: cache_file
304
305//-----------------------------------------
306// html output to browser
307$podcastURL = (isset($invalidURL) || isset($invalidID)) ? ($invalidID == 'empty_podcast' ? $emptyPodcastText : $feedURL) : "<a href=\"$feedURL\">$feedURL</a>";
308
309echo <<<OUTTEXT
310<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
311 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
312
313<html xmlns="http://www.w3.org/1999/xhtml" style="height: 100%;">
314 <head>
315 <title>Podcast URL</title>
316 <meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
317 <meta name="robots" content="NOINDEX, NOFOLLOW, NOARCHIVE, NOSNIPPET">
318 <style type="text/css" media="screen">@import "iphonenav.css";</style>
319 <link rel="apple-touch-icon" href="./icon.png" />
320 <link rel="shortcut icon" href="./favicon.ico">
321 </head>
322
323 <!-- GUI, iTunes Store searching & feed extraction credited to lasavior, so-nik.com -->
324 <!-- Original idea & inspiration credited to Michael Sitarzewski, zerologic.com -->
325 <!-- For the PHP code to extract the podcast feed yourself, visit http://snipplr.com/view/52465 -->
326
327 <body style="height: 100%;">
328
329 <h1>Podcast URL:</h1>
330 <ul>
331 <li style="height: 100%; padding:10px 10px 10px 10px; font-size:20px; word-wrap:break-word">$podcastURL</li>
332 <li style="height: 100%; padding:10px 10px 10px 10px; font-size:10px; border-bottom: 0px solid;"><div style="color:LightGray;font-size:12px;"><a href="mailto:ife@so-nik.com" style="color:LightGray; font-size:12px; text-decoration:none;">ife@so-nik.com</a> / <a href="http://podcasturlextractor.blogspot.com/" style="color:LightGray; font-size:12px; text-decoration:none;" target="_blank">News</a> / <a href="http://podcasturlextractor.blogspot.com/p/what-it-is-and-why-its-here.html" style="color:LightGray; font-size:12px; text-decoration:none;" target="_blank">About</a></div></li>
333 </ul>
334 </body>
335</html>
336OUTTEXT;
337
338?>