2 /****************************************************
4 A PHP-Based RSS and Atom Feed Framework
5 Takes the hard work out of managing a complete RSS/Atom solution.
7 Version: "Lemon Meringue"
8 Updated: 24 November 2006
9 Copyright: 2004-2006 Ryan Parman, Geoffrey Sneddon
12 *****************************************************
15 GNU Lesser General Public License 2.1 (LGPL)
16 http://creativecommons.org/licenses/LGPL/2.1/
18 *****************************************************
19 Please submit all bug reports and feature requests to the SimplePie forums.
20 http://simplepie.org/support/
22 ****************************************************/
27 var $name = 'SimplePie';
28 var $version = '1.0 b3.2';
29 var $build = '20061124';
30 var $url = 'http://simplepie.org/';
34 // Other objects, instances created here so we can set options on them
41 var $xml_dump = false;
42 var $enable_cache = true;
43 var $max_minutes = 60;
44 var $cache_location = './cache';
45 var $order_by_date = true;
46 var $input_encoding = false;
47 var $cache_class = 'SimplePie_Cache';
48 var $locator_class = 'SimplePie_Locator';
49 var $parser_class = 'SimplePie_Parser';
50 var $file_class = 'SimplePie_File';
51 var $force_fsockopen = false;
52 var $cache_name_type = 'sha1';
58 function SimplePie($feed_url = null, $cache_location = null, $cache_max_minutes = null)
60 // Couple of variables built up from other variables
61 $this->useragent = $this->name . '/' . $this->version . ' (Feed Parser; ' . $this->url . '; Allow like Gecko) Build/' . $this->build;
62 $this->linkback = '<a href="' . $this->url . '" title="' . $this->name . ' ' . $this->version . '">' . $this->name . '</a>';
64 // Other objects, instances created here so we can set options on them
65 $this->sanitize = new SimplePie_Sanitize;
67 // Set options if they're passed to the constructor
68 if (!is_null($feed_url))
70 $this->feed_url($feed_url);
73 if (!is_null($cache_location))
75 $this->cache_location($cache_location);
78 if (!is_null($cache_max_minutes))
80 $this->cache_max_minutes($cache_max_minutes);
83 // If we've passed an xmldump variable in the URL, snap into XMLdump mode
84 if (isset($_GET['xmldump']))
86 $this->enable_xmldump(true);
89 // Only init the script if we're passed a feed URL
90 if (!is_null($feed_url))
96 function feed_url($url)
98 $this->rss_url = SimplePie_Misc::fix_protocol($url, 1);
101 function set_file(&$file)
103 if (is_a($file, 'SimplePie_File'))
105 $this->rss_url = $file->url;
106 $this->file =& $file;
110 function set_timeout($timeout = 10)
112 $this->timeout = (int) $timeout;
115 function set_raw_data($data)
117 $this->raw_data = trim((string) $data);
120 function enable_xmldump($enable = false)
122 $this->xml_dump = (bool) $enable;
125 function enable_caching($enable = true)
127 $this->enable_cache = (bool) $enable;
130 function cache_max_minutes($minutes = 60)
132 $this->max_minutes = (float) $minutes;
135 function cache_location($location = './cache')
137 $this->cache_location = (string) $location;
140 function order_by_date($enable = true)
142 $this->order_by_date = (bool) $enable;
145 function input_encoding($encoding = false)
149 $this->input_encoding = (string) $encoding;
153 $this->input_encoding = false;
157 function set_cache_class($class = 'SimplePie_Cache')
159 if (SimplePie_Misc::is_a_class($class, 'SimplePie_Cache'))
161 $this->cache_class = $class;
167 function set_locator_class($class = 'SimplePie_Locator')
169 if (SimplePie_Misc::is_a_class($class, 'SimplePie_Locator'))
171 $this->locator_class = $class;
177 function set_parser_class($class = 'SimplePie_Parser')
179 if (SimplePie_Misc::is_a_class($class, 'SimplePie_Parser'))
181 $this->parser_class = $class;
187 function set_file_class($class = 'SimplePie_File')
189 if (SimplePie_Misc::is_a_class($class, 'SimplePie_File'))
191 $this->file_class = $class;
197 function set_sanitize_class($object = 'SimplePie_Sanitize')
199 if (class_exists($object))
201 $this->sanitize = new $object;
207 function set_useragent($ua)
209 $this->useragent = (string) $ua;
212 function force_fsockopen($enable = false)
214 $this->force_fsockopen = (bool) $enable;
217 function set_cache_name_type($type = 'sha1')
219 $type = strtolower(trim($type));
223 $this->cache_name_type = 'crc32';
227 $this->cache_name_type = 'md5';
231 $this->cache_name_type = 'rawurlencode';
235 $this->cache_name_type = 'urlencode';
239 $this->cache_name_type = 'sha1';
244 function bypass_image_hotlink($get = false)
246 $this->sanitize->bypass_image_hotlink($get);
249 function bypass_image_hotlink_page($page = false)
251 $this->sanitize->bypass_image_hotlink_page($page);
254 function replace_headers($enable = false)
256 $this->sanitize->replace_headers($enable);
259 function remove_div($enable = true)
261 $this->sanitize->remove_div($enable);
264 function strip_ads($enable = false)
266 $this->sanitize->strip_ads($enable);
269 function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'), $encode = null)
271 $this->sanitize->strip_htmltags($tags);
272 if (!is_null($encode))
274 $this->sanitize->encode_instead_of_strip($tags);
278 function encode_instead_of_strip($enable = true)
280 $this->sanitize->encode_instead_of_strip($enable);
283 function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur'))
285 $this->sanitize->strip_attributes($attribs);
288 function output_encoding($encoding = 'UTF-8')
290 $this->sanitize->output_encoding($encoding);
293 function set_item_class($class = 'SimplePie_Item')
295 return $this->sanitize->set_item_class($class);
298 function set_author_class($class = 'SimplePie_Author')
300 return $this->sanitize->set_author_class($class);
303 function set_enclosure_class($class = 'SimplePie_Enclosure')
305 return $this->sanitize->set_enclosure_class($class);
310 if (!(function_exists('version_compare') && ((version_compare(phpversion(), '4.3.2', '>=') && version_compare(phpversion(), '5', '<')) || version_compare(phpversion(), '5.0.3', '>='))) || !extension_loaded('xml') || !extension_loaded('pcre'))
314 if ($this->sanitize->bypass_image_hotlink && !empty($_GET[$this->sanitize->bypass_image_hotlink]))
316 if (get_magic_quotes_gpc())
318 $_GET[$this->sanitize->bypass_image_hotlink] = stripslashes($_GET[$this->sanitize->bypass_image_hotlink]);
320 SimplePie_Misc::display_file($_GET[$this->sanitize->bypass_image_hotlink], 10, $this->useragent);
323 if (isset($_GET['js']))
326 function embed_odeo(link) {
327 document.writeln('<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url='+link+'"></embed>');
330 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
331 if (placeholder != '') {
332 document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" href="'+link+'" src="'+placeholder+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="false" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
335 document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" src="'+link+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="true" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
339 function embed_flash(bgcolor, width, height, link, loop, type) {
340 document.writeln('<embed src="'+link+'" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" type="'+type+'" quality="high" width="'+width+'" height="'+height+'" bgcolor="'+bgcolor+'" loop="'+loop+'"></embed>');
343 function embed_wmedia(width, height, link) {
344 document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
348 if (function_exists('ob_gzhandler'))
350 ob_start('ob_gzhandler');
352 header('Content-type: text/javascript; charset: UTF-8');
353 header('Cache-Control: must-revalidate');
354 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 86400) . ' GMT');
359 if (!empty($this->rss_url) || !empty($this->raw_data))
361 $this->data = array();
364 if (!empty($this->rss_url))
366 // Decide whether to enable caching
367 if ($this->enable_cache && preg_match('/^http(s)?:\/\//i', $this->rss_url))
369 $cache = new $this->cache_class($this->cache_location, call_user_func($this->cache_name_type, $this->rss_url), 'spc');
371 // If it's enabled and we don't want an XML dump, use the cache
372 if ($cache && !$this->xml_dump)
375 $this->data = $cache->load();
376 if (!empty($this->data))
378 // If we've hit a collision just rerun it with caching disabled
379 if (isset($this->data['url']) && $this->data['url'] != $this->rss_url)
383 // If we've got a feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL
384 else if (!empty($this->data['feed_url']))
386 if ($this->data['feed_url'] == $this->data['url'])
392 $this->feed_url($this->data['feed_url']);
393 return $this->init();
396 // If the cache is new enough
397 else if ($cache->mtime() + $this->max_minutes * 60 < time())
399 // If we have last-modified and/or etag set
400 if (!empty($this->data['last-modified']) || !empty($this->data['etag']))
403 if (!empty($this->data['last-modified']))
405 $headers['if-modified-since'] = $this->data['last-modified'];
407 if (!empty($this->data['etag']))
409 $headers['if-none-match'] = $this->data['etag'];
411 $file = new $this->file_class($this->rss_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
414 $headers = $file->headers();
415 if ($headers['status']['code'] == 304)
426 // If we don't have last-modified or etag set, just clear the cache
432 // If the cache is still valid, just return true
438 // If the cache is empty, delete it
444 $this->data = array();
445 // If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it.
448 if (is_a($this->file, 'SimplePie_File') && $this->file->url == $this->rss_url)
450 $file =& $this->file;
454 $file = new $this->file_class($this->rss_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
457 // If the file connection has an error, set SimplePie::error to that and quit
460 $this->error = $file->error;
464 // Check if the supplied URL is a feed, if it isn't, look for it.
465 $locate = new $this->locator_class($file, $this->timeout, $this->useragent);
466 if (!$locate->is_feed($file))
468 $feed = $locate->find();
471 if ($cache && !$cache->save(array('url' => $this->rss_url, 'feed_url' => $feed)))
473 $this->error = "$cache->name is not writeable";
474 SimplePie_Misc::error($this->error, E_USER_WARNING, __FILE__, __LINE__);
476 $this->rss_url = $feed;
477 return $this->init();
481 $this->error = "A feed could not be found at $this->rss_url";
482 SimplePie_Misc::error($this->error, E_USER_WARNING, __FILE__, __LINE__);
487 $headers = $file->headers();
488 $data = trim($file->body());
494 $data = $this->raw_data;
497 // First check to see if input has been overridden.
498 if (!empty($this->input_encoding))
500 $encoding = $this->input_encoding;
502 // Second try HTTP headers
503 else if (!empty($headers['content-type']) && preg_match('/charset\s*=\s*([^;]*)/i', $headers['content-type'], $charset))
505 $encoding = $charset[1];
507 // Then prolog, if at the very start of the document
508 else if (preg_match('/^<\?xml(.*)?>/msiU', $data, $prolog) && preg_match('/encoding\s*=\s*("([^"]*)"|\'([^\']*)\')/Ui', $prolog[1], $encoding))
510 $encoding = substr($encoding[1], 1, -1);
512 // UTF-32 Big Endian BOM
513 else if (strpos($data, sprintf('%c%c%c%c', 0x00, 0x00, 0xFE, 0xFF)) === 0)
515 $encoding = 'UTF-32be';
517 // UTF-32 Little Endian BOM
518 else if (strpos($data, sprintf('%c%c%c%c', 0xFF, 0xFE, 0x00, 0x00)) === 0)
520 $encoding = 'UTF-32';
522 // UTF-16 Big Endian BOM
523 else if (strpos($data, sprintf('%c%c', 0xFE, 0xFF)) === 0)
525 $encoding = 'UTF-16be';
527 // UTF-16 Little Endian BOM
528 else if (strpos($data, sprintf('%c%c', 0xFF, 0xFE)) === 0)
530 $encoding = 'UTF-16le';
533 else if (strpos($data, sprintf('%c%c%c', 0xEF, 0xBB, 0xBF)) === 0)
537 // Fallback to the default
543 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
544 $data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8');
546 // Strip illegal characters (if on less than PHP5, as on PHP5 expat can manage fine)
547 if (version_compare(phpversion(), '5', '<'))
549 if (function_exists('iconv'))
551 $data = iconv('UTF-8', 'UTF-8//IGNORE', $data);
553 else if (function_exists('mb_convert_encoding'))
555 $data = mb_convert_encoding($data, 'UTF-8', 'UTF-8');
559 $data = SimplePie_Misc::utf8_bad_replace($data);
564 $data = new $this->parser_class($data, 'UTF-8', $this->xml_dump);
565 // If we want the XML, just output that and quit
568 header('Content-type: text/xml; charset=UTF-8');
572 // If it's parsed fine
573 else if (!$data->error_code)
575 // Parse the data, and make it sane
576 $this->sanitize->parse_data_array($data->data, $this->rss_url);
579 $this->data['feedinfo'] = $this->sanitize->feedinfo;
580 unset($this->sanitize->feedinfo);
581 $this->data['info'] = $this->sanitize->info;
582 unset($this->sanitize->info);
583 $this->data['items'] = $this->sanitize->items;
584 unset($this->sanitize->items);
585 $this->data['feedinfo']['encoding'] = $this->sanitize->output_encoding;
586 $this->data['url'] = $this->rss_url;
588 // Store the headers that we need
589 if (!empty($headers['last-modified']))
591 $this->data['last-modified'] = $headers['last-modified'];
593 if (!empty($headers['etag']))
595 $this->data['etag'] = $headers['etag'];
598 // If we want to order it by date, check if all items have a date, and then sort it
599 if ($this->order_by_date && !empty($this->data['items']))
602 foreach ($this->data['items'] as $item)
604 if (!$item->get_date('U'))
612 usort($this->data['items'], create_function('$a, $b', 'if ($a->get_date(\'U\') == $b->get_date(\'U\')) return 1; return ($a->get_date(\'U\') < $b->get_date(\'U\')) ? 1 : -1;'));
616 // Cache the file if caching is enabled
617 if ($cache && !$cache->save($this->data))
619 $this->error = "$cache->name is not writeable";
620 SimplePie_Misc::error($this->error, E_USER_WARNING, __FILE__, __LINE__);
624 // If we have an error, just set SimplePie::error to it and quit
627 $this->error = "XML error: $data->error_string at line $data->current_line, column $data->current_column";
628 SimplePie_Misc::error($this->error, E_USER_WARNING, __FILE__, __LINE__);
634 function get_encoding()
636 if (!empty($this->data['feedinfo']['encoding']))
638 return $this->data['feedinfo']['encoding'];
646 function handle_content_type($mime = 'text/html')
650 $header = "Content-type: $mime;";
651 if ($this->get_encoding())
653 $header .= ' charset=' . $this->get_encoding();
657 $header .= ' charset=UTF-8';
665 if (!empty($this->data['feedinfo']['type']))
667 return $this->data['feedinfo']['type'];
675 function get_version()
677 if (!empty($this->data['feedinfo']['version']))
679 return $this->data['feedinfo']['version'];
687 function get_favicon($check = false, $alternate = null)
689 if (!empty($this->data['info']['link']['alternate'][0]))
691 $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $this->get_feed_link());
695 $file = new $this->file_class($favicon, $this->timeout/10, 5, null, $this->useragent, $this->force_fsockopen);
696 $headers = $file->headers();
699 if ($headers['status']['code'] == 200)
709 if (!is_null($alternate))
719 function subscribe_url()
721 if (!empty($this->rss_url))
723 return $this->rss_url;
731 function subscribe_feed()
733 if (!empty($this->rss_url))
735 return SimplePie_Misc::fix_protocol($this->rss_url, 2);
743 function subscribe_outlook()
745 if (!empty($this->rss_url))
747 return 'outlook' . SimplePie_Misc::fix_protocol($this->rss_url, 2);
755 function subscribe_podcast()
757 if (!empty($this->rss_url))
759 return SimplePie_Misc::fix_protocol($this->rss_url, 3);
767 function subscribe_aol()
769 if ($this->subscribe_url())
771 return 'http://feeds.my.aol.com/add.jsp?url=' . rawurlencode($this->subscribe_url());
779 function subscribe_bloglines()
781 if ($this->subscribe_url())
783 return 'http://www.bloglines.com/sub/' . rawurlencode($this->subscribe_url());
791 function subscribe_eskobo()
793 if ($this->subscribe_url())
795 return 'http://www.eskobo.com/?AddToMyPage=' . rawurlencode($this->subscribe_url());
803 function subscribe_feedfeeds()
805 if ($this->subscribe_url())
807 return 'http://www.feedfeeds.com/add?feed=' . rawurlencode($this->subscribe_url());
815 function subscribe_feedlounge()
817 if ($this->subscribe_url())
819 return 'http://my.feedlounge.com/external/subscribe?url=' . rawurlencode($this->subscribe_url());
827 function subscribe_feedster()
829 if ($this->subscribe_url())
831 return 'http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=' . rawurlencode($this->subscribe_url());
839 function subscribe_google()
841 if ($this->subscribe_url())
843 return 'http://fusion.google.com/add?feedurl=' . rawurlencode($this->subscribe_url());
851 function subscribe_gritwire()
853 if ($this->subscribe_url())
855 return 'http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=' . rawurlencode($this->subscribe_url());
863 function subscribe_msn()
865 if ($this->subscribe_url())
867 $url = 'http://my.msn.com/addtomymsn.armx?id=rss&ut=' . rawurlencode($this->subscribe_url());
868 if ($this->get_feed_link())
870 $url .= '&ru=' . rawurlencode($this->get_feed_link());
880 function subscribe_netvibes()
882 if ($this->subscribe_url())
884 return 'http://www.netvibes.com/subscribe.php?url=' . rawurlencode($this->subscribe_url());
892 function subscribe_newsburst()
894 if ($this->subscribe_url())
896 return 'http://www.newsburst.com/Source/?add=' . rawurlencode($this->subscribe_url());
904 function subscribe_newsgator()
906 if ($this->subscribe_url())
908 return 'http://www.newsgator.com/ngs/subscriber/subext.aspx?url=' . rawurlencode($this->subscribe_url());
916 function subscribe_odeo()
918 if ($this->subscribe_url())
920 return 'http://www.odeo.com/listen/subscribe?feed=' . rawurlencode($this->subscribe_url());
928 function subscribe_pluck()
930 if ($this->subscribe_url())
932 return 'http://client.pluck.com/pluckit/prompt.aspx?GCID=C12286x053&a=' . rawurlencode($this->subscribe_url());
940 function subscribe_podnova()
942 if ($this->subscribe_url())
944 return 'http://www.podnova.com/index_your_podcasts.srf?action=add&url=' . rawurlencode($this->subscribe_url());
952 function subscribe_rojo()
954 if ($this->subscribe_url())
956 return 'http://www.rojo.com/add-subscription?resource=' . rawurlencode($this->subscribe_url());
964 function subscribe_yahoo()
966 if ($this->subscribe_url())
968 return 'http://add.my.yahoo.com/rss?url=' . rawurlencode($this->subscribe_url());
976 function get_feed_title()
978 if (!empty($this->data['info']['title']))
980 return $this->data['info']['title'];
988 function get_feed_link()
990 if (!empty($this->data['info']['link']['alternate'][0]))
992 return $this->data['info']['link']['alternate'][0];
1000 function get_feed_links()
1002 if (!empty($this->data['info']['link']))
1004 return $this->data['info']['link'];
1012 function get_feed_description()
1014 if (!empty($this->data['info']['description']))
1016 return $this->data['info']['description'];
1018 else if (!empty($this->data['info']['dc:description']))
1020 return $this->data['info']['dc:description'];
1022 else if (!empty($this->data['info']['tagline']))
1024 return $this->data['info']['tagline'];
1026 else if (!empty($this->data['info']['subtitle']))
1028 return $this->data['info']['subtitle'];
1036 function get_feed_copyright()
1038 if (!empty($this->data['info']['copyright']))
1040 return $this->data['info']['copyright'];
1048 function get_feed_language()
1050 if (!empty($this->data['info']['language']))
1052 return $this->data['info']['language'];
1054 else if (!empty($this->data['info']['xml:lang']))
1056 return $this->data['info']['xml:lang'];
1064 function get_image_exist()
1066 if (!empty($this->data['info']['image']['url']) || !empty($this->data['info']['image']['logo']))
1076 function get_image_title()
1078 if (!empty($this->data['info']['image']['title']))
1080 return $this->data['info']['image']['title'];
1088 function get_image_url()
1090 if (!empty($this->data['info']['image']['url']))
1092 return $this->data['info']['image']['url'];
1094 else if (!empty($this->data['info']['image']['logo']))
1096 return $this->data['info']['image']['logo'];
1104 function get_image_link()
1106 if (!empty($this->data['info']['image']['link']))
1108 return $this->data['info']['image']['link'];
1116 function get_image_width()
1118 if (!empty($this->data['info']['image']['width']))
1120 return $this->data['info']['image']['width'];
1128 function get_image_height()
1130 if (!empty($this->data['info']['image']['height']))
1132 return $this->data['info']['image']['height'];
1140 function get_item_quantity($max = 0)
1142 if (!empty($this->data['items']))
1144 $qty = sizeof($this->data['items']);
1156 return ($qty > $max) ? $max : $qty;
1160 function get_item($key = 0)
1162 if (!empty($this->data['items'][$key]))
1164 return $this->data['items'][$key];
1172 function get_items($start = 0, $end = 0)
1174 if ($this->get_item_quantity() > 0)
1178 return array_slice($this->data['items'], $start);
1182 return array_slice($this->data['items'], $start, $end);
1192 class SimplePie_Item
1196 function SimplePie_Item($data)
1198 $this->data =& $data;
1203 if (!empty($this->data['guid']['data']))
1205 return $this->data['guid']['data'];
1207 else if (!empty($this->data['id']))
1209 return $this->data['id'];
1217 function get_title()
1219 if (!empty($this->data['title']))
1221 return $this->data['title'];
1223 else if (!empty($this->data['dc:title']))
1225 return $this->data['dc:title'];
1233 function get_description()
1235 if (!empty($this->data['content']))
1237 return $this->data['content'];
1239 else if (!empty($this->data['encoded']))
1241 return $this->data['encoded'];
1243 else if (!empty($this->data['summary']))
1245 return $this->data['summary'];
1247 else if (!empty($this->data['description']))
1249 return $this->data['description'];
1251 else if (!empty($this->data['dc:description']))
1253 return $this->data['dc:description'];
1255 else if (!empty($this->data['longdesc']))
1257 return $this->data['longdesc'];
1265 function get_category($key = 0)
1267 $categories = $this->get_categories();
1268 if (!empty($categories[$key]))
1270 return $categories[$key];
1278 function get_categories()
1280 $categories = array();
1281 if (!empty($this->data['category']))
1283 $categories = array_merge($categories, $this->data['category']);
1285 if (!empty($this->data['subject']))
1287 $categories = array_merge($categories, $this->data['subject']);
1289 if (!empty($this->data['term']))
1291 $categories = array_merge($categories, $this->data['term']);
1293 if (!empty($categories))
1295 return array_unique($categories);
1303 function get_author($key = 0)
1305 $authors = $this->get_authors();
1306 if (!empty($authors[$key]))
1308 return $authors[$key];
1316 function get_authors()
1319 if (!empty($this->data['author']))
1321 $authors = array_merge($authors, $this->data['author']);
1323 if (!empty($this->data['creator']))
1325 $authors = array_merge($authors, $this->data['creator']);
1327 if (!empty($authors))
1329 return array_unique($authors);
1337 function get_date($date_format = 'j F Y, g:i a')
1339 if (!empty($this->data['pubdate']))
1341 return date($date_format, $this->data['pubdate']);
1343 else if (!empty($this->data['dc:date']))
1345 return date($date_format, $this->data['dc:date']);
1347 else if (!empty($this->data['issued']))
1349 return date($date_format, $this->data['issued']);
1351 else if (!empty($this->data['published']))
1353 return date($date_format, $this->data['published']);
1355 else if (!empty($this->data['modified']))
1357 return date($date_format, $this->data['modified']);
1359 else if (!empty($this->data['updated']))
1361 return date($date_format, $this->data['updated']);
1369 function get_permalink()
1371 $link = $this->get_link(0);
1372 $enclosure = $this->get_enclosure(0);
1377 else if (!empty($enclosure))
1379 return $enclosure->get_link();
1387 function get_link($key = 0, $rel = 'alternate')
1389 $links = $this->get_links($rel);
1390 if (!empty($links[$key]))
1392 return $links[$key];
1400 function get_links($rel = 'alternate')
1402 if ($rel == 'alternate')
1405 if (!empty($this->data['link'][$rel]))
1407 $links = $this->data['link'][$rel];
1409 if (!empty($this->data['guid']['data']) && $this->data['guid']['permalink'] == true)
1411 $links[] = $this->data['guid']['data'];
1415 else if (!empty($this->data['link'][$rel]))
1417 return $this->data['link'][$rel];
1425 function get_enclosure($key = 0)
1427 $enclosures = $this->get_enclosures();
1428 if (!empty($enclosures[$key]))
1430 return $enclosures[$key];
1438 function get_enclosures()
1440 $enclosures = array();
1441 $links = $this->get_links('enclosure');
1442 if (!empty($this->data['enclosures']))
1444 $enclosures = array_merge($enclosures, $this->data['enclosures']);
1448 $enclosures = array_merge($enclosures, $links);
1450 if (!empty($enclosures))
1452 return array_unique($enclosures);
1460 function add_to_blinklist()
1462 if ($this->get_permalink())
1464 $url = 'http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=' . rawurlencode($this->get_permalink());
1465 if ($this->get_title())
1467 $url .= '&Title=' . rawurlencode($this->get_title());
1477 function add_to_blogmarks()
1479 if ($this->get_permalink())
1481 $url = 'http://blogmarks.net/my/new.php?mini=1&simple=1&url=' . rawurlencode($this->get_permalink());
1482 if ($this->get_title())
1484 $url .= '&title=' . rawurlencode($this->get_title());
1494 function add_to_delicious()
1496 if ($this->get_permalink())
1498 $url = 'http://del.icio.us/post/?v=3&url=' . rawurlencode($this->get_permalink());
1499 if ($this->get_title())
1501 $url .= '&title=' . rawurlencode($this->get_title());
1511 function add_to_digg()
1513 if ($this->get_permalink())
1515 return 'http://digg.com/submit?phase=2&URL=' . rawurlencode($this->get_permalink());
1523 function add_to_furl()
1525 if ($this->get_permalink())
1527 $url = 'http://www.furl.net/storeIt.jsp?u=' . rawurlencode($this->get_permalink());
1528 if ($this->get_title())
1530 $url .= '&t=' . rawurlencode($this->get_title());
1540 function add_to_magnolia()
1542 if ($this->get_permalink())
1544 $url = 'http://ma.gnolia.com/bookmarklet/add?url=' . rawurlencode($this->get_permalink());
1545 if ($this->get_title())
1547 $url .= '&title=' . rawurlencode($this->get_title());
1557 function add_to_myweb20()
1559 if ($this->get_permalink())
1561 $url = 'http://myweb2.search.yahoo.com/myresults/bookmarklet?u=' . rawurlencode($this->get_permalink());
1562 if ($this->get_title())
1564 $url .= '&t=' . rawurlencode($this->get_title());
1574 function add_to_newsvine()
1576 if ($this->get_permalink())
1578 $url = 'http://www.newsvine.com/_wine/save?u=' . rawurlencode($this->get_permalink());
1579 if ($this->get_title())
1581 $url .= '&h=' . rawurlencode($this->get_title());
1591 function add_to_reddit()
1593 if ($this->get_permalink())
1595 $url = 'http://reddit.com/submit?url=' . rawurlencode($this->get_permalink());
1596 if ($this->get_title())
1598 $url .= '&title=' . rawurlencode($this->get_title());
1608 function add_to_segnalo()
1610 if ($this->get_permalink())
1612 $url = 'http://segnalo.com/post.html.php?url=' . rawurlencode($this->get_permalink());
1613 if ($this->get_title())
1615 $url .= '&title=' . rawurlencode($this->get_title());
1625 function add_to_simpy()
1627 if ($this->get_permalink())
1629 $url = 'http://www.simpy.com/simpy/LinkAdd.do?href=' . rawurlencode($this->get_permalink());
1630 if ($this->get_title())
1632 $url .= '&title=' . rawurlencode($this->get_title());
1642 function add_to_smarking()
1644 if ($this->get_permalink())
1646 return 'http://smarking.com/editbookmark/?url=' . rawurlencode($this->get_permalink());
1654 function add_to_spurl()
1656 if ($this->get_permalink())
1658 $url = 'http://www.spurl.net/spurl.php?v=3&url=' . rawurlencode($this->get_permalink());
1659 if ($this->get_title())
1661 $url .= '&title=' . rawurlencode($this->get_title());
1671 function add_to_wists()
1673 if ($this->get_permalink())
1675 $url = 'http://wists.com/r.php?c=&r=' . rawurlencode($this->get_permalink());
1676 if ($this->get_title())
1678 $url .= '&title=' . rawurlencode($this->get_title());
1688 function search_technorati()
1690 if ($this->get_permalink())
1692 return 'http://www.technorati.com/search/' . rawurlencode($this->get_permalink());
1701 class SimplePie_Author
1707 // Constructor, used to input the data
1708 function SimplePie_Author($name, $link, $email)
1710 $this->name = $name;
1711 $this->link = $link;
1712 $this->email = $email;
1717 if (!empty($this->name))
1729 if (!empty($this->link))
1739 function get_email()
1741 if (!empty($this->email))
1743 return $this->email;
1752 class SimplePie_Enclosure
1758 // Constructor, used to input the data
1759 function SimplePie_Enclosure($link, $type, $length)
1761 $this->link = $link;
1762 $this->type = $type;
1763 $this->length = $length;
1768 if (!empty($this->link))
1770 if (class_exists('idna_convert'))
1772 $idn = new idna_convert;
1773 $this->link = $idn->encode($this->link);
1783 function get_extension()
1785 if (!empty($this->link))
1787 return pathinfo($this->link, PATHINFO_EXTENSION);
1797 if (!empty($this->type))
1807 function get_length()
1809 if (!empty($this->length))
1811 return $this->length;
1821 $length = $this->get_length();
1822 if (!empty($length))
1824 return round($length/1048576, 2);
1832 function native_embed($options='')
1834 return $this->embed($options, true);
1837 function embed($options = '', $native = false)
1847 $bgcolor = '#ffffff';
1849 // Process options and reassign values as necessary
1850 if (is_array($options))
1856 $options = explode(',', $options);
1857 foreach($options as $option)
1859 $opt = explode(':', $option, 2);
1860 if (isset($opt[0], $opt[1]))
1862 $opt[0] = trim($opt[0]);
1863 $opt[1] = trim($opt[1]);
1879 $altclass = $opt[1];
1902 $type = strtolower($this->get_type());
1904 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
1905 if (!in_array($type, array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mpeg', 'audio/x-mpeg', 'audio/mp3', 'x-audio/mp3', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video', 'application/x-shockwave-flash', 'application/futuresplash', 'application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx')))
1907 switch (strtolower($this->get_extension()))
1912 $type = 'audio/acc';
1919 $type = 'audio/aiff';
1923 $type = 'audio/wav';
1930 $type = 'audio/midi';
1934 $type = 'audio/x-m4a';
1939 $type = 'audio/mp3';
1943 $type = 'audio/wav';
1947 $type = 'audio/x-ms-wax';
1951 $type = 'audio/x-ms-wma';
1957 $type = 'video/3gpp';
1962 $type = 'video/3gpp2';
1966 $type = 'video/x-ms-asf';
1980 $type = 'video/mpeg';
1984 $type = 'video/x-m4v';
1989 $type = 'video/quicktime';
1994 $type = 'video/mp4';
1998 $type = 'video/sd-video';
2002 $type = 'video/x-ms-wm';
2006 $type = 'video/x-ms-wmv';
2010 $type = 'video/x-ms-wvx';
2015 $type = 'application/futuresplash';
2019 $type = 'application/x-shockwave-flash';
2024 $mime = explode('/', $type, 2);
2027 // Process values for 'auto'
2028 if ($width == 'auto')
2030 if ($mime == 'video')
2039 if ($height == 'auto')
2041 if ($mime == 'audio')
2045 else if ($mime == 'video')
2055 // Set proper placeholder value
2056 if ($mime == 'audio')
2058 $placeholder = $audio;
2060 else if ($mime == 'video')
2062 $placeholder = $video;
2067 // Make sure the JS library is included
2068 // (I know it'll be included multiple times, but I can't think of a better way to do this automatically)
2071 $embed .= '<script type="text/javascript" src="?js"></script>';
2075 if (substr(strtolower($this->get_link()), 0, 15) == 'http://odeo.com') {
2078 $embed .= '<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url=' . $this->get_link() . '"></embed>';
2082 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
2086 // QuickTime 7 file types. Need to test with QuickTime 6.
2087 else if (in_array($type, array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mpeg', 'audio/x-mpeg', 'audio/mp3', 'x-audio/mp3', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video')))
2092 if ($placeholder != "") {
2093 $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" href=\"" . $this->get_link() . "\" src=\"$placeholder\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"false\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://www.apple.com/quicktime/download/\"></embed>";
2096 $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" src=\"" . $this->get_link() . "\" width=\"$width+\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"true\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://www.apple.com/quicktime/download/\"></embed>";
2101 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
2106 else if (in_array($type, array('application/x-shockwave-flash', 'application/futuresplash')))
2110 $embed .= "<embed src=\"" . $this->get_link() . "\" pluginspage=\"http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash\" type=\"$type\" quality=\"high\" width=\"$width\" height=\"$height\" bgcolor=\"$bgcolor\" loop=\"$loop\"></embed>";
2114 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
2119 else if (in_array($type, array('application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx')))
2124 $embed .= "<embed type=\"application/x-mplayer2\" src=\"" . $this->get_link() . "\" autosize=\"1\" width=\"$width\" height=\"$height\" showcontrols=\"1\" showstatusbar=\"0\" showdisplay=\"0\" autostart=\"0\"></embed>";
2128 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
2133 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
2139 class SimplePie_File
2143 var $success = true;
2144 var $headers = array();
2151 function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
2153 if (class_exists('idna_convert'))
2155 $idn = new idna_convert;
2156 $url = $idn->encode($url);
2159 $this->useragent = $useragent;
2160 if (preg_match('/^http(s)?:\/\//i', $url))
2162 if (empty($useragent))
2164 $useragent = ini_get('user_agent');
2165 $this->useragent = $useragent;
2167 if (!is_array($headers))
2171 if (extension_loaded('curl') && version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>=') && !$force_fsockopen)
2173 $this->method = 'curl';
2175 $headers2 = array();
2176 foreach ($headers as $key => $value)
2178 $headers2[] = "$key: $value";
2180 curl_setopt($fp, CURLOPT_ENCODING, '');
2181 curl_setopt($fp, CURLOPT_URL, $url);
2182 curl_setopt($fp, CURLOPT_HEADER, 1);
2183 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
2184 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
2185 curl_setopt($fp, CURLOPT_REFERER, $url);
2186 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
2187 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
2188 if (!ini_get('open_basedir') && !ini_get('safe_mode'))
2190 curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
2191 curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
2194 $this->headers = trim(curl_exec($fp));
2195 if (curl_errno($fp) == 23 || curl_errno($fp) == 61)
2197 curl_setopt($fp, CURLOPT_ENCODING, 'none');
2198 $this->headers = trim(curl_exec($fp));
2200 if (curl_errno($fp))
2202 $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
2203 $this->success = false;
2206 $info = curl_getinfo($fp);
2207 $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 2);
2208 if (count($this->headers) == $info['redirect_count'] + 1)
2210 $this->headers = array_pop($this->headers);
2215 $this->body = array_pop($this->headers);
2216 $this->headers = array_pop($this->headers);
2218 $this->headers = $this->parse_headers($this->headers);
2219 if (($this->headers['status']['code'] == 301 || $this->headers['status']['code'] == 302 || $this->headers['status']['code'] == 303 || $this->headers['status']['code'] == 307) && !empty($this->headers['location']) && $this->redirects < $redirects)
2222 return $this->SimplePie_File($this->headers['location'], $timeout, $redirects, $headers, $useragent, $force_fsockopen);
2227 $this->method = 'fsockopen';
2228 $url_parts = parse_url($url);
2229 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) == 'https')
2231 $url_parts['host'] = "ssl://$url_parts[host]";
2232 $url_parts['port'] = 443;
2234 if (!isset($url_parts['port']))
2236 $url_parts['port'] = 80;
2238 $this->fp = fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
2241 $this->error = 'fsockopen error: ' . $errstr;
2242 $this->success = false;
2247 stream_set_timeout($this->fp, $timeout);
2248 $get = (isset($url_parts['query'])) ? "$url_parts[path]?$url_parts[query]" : $url_parts['path'];
2249 $out = "GET $get HTTP/1.0\r\n";
2250 $out .= "Host: $url_parts[host]\r\n";
2251 $out .= "User-Agent: $useragent\r\n";
2252 if (function_exists('gzinflate'))
2254 $out .= "Accept-Encoding: gzip,deflate\r\n";
2257 if (!empty($url_parts['user']) && !empty($url_parts['pass']))
2259 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
2261 foreach ($headers as $key => $value)
2263 $out .= "$key: $value\r\n";
2265 $out .= "Connection: Close\r\n\r\n";
2266 fwrite($this->fp, $out);
2268 $info = stream_get_meta_data($this->fp);
2270 while (strpos($data, "\r\n\r\n") === false && !$info['timed_out'])
2272 $data .= fgets($this->fp, 128);
2273 $info = stream_get_meta_data($this->fp);
2275 if (!$info['timed_out'])
2277 $this->headers = $this->parse_headers($data);
2278 if (($this->headers['status']['code'] == 301 || $this->headers['status']['code'] == 302 || $this->headers['status']['code'] == 303 || $this->headers['status']['code'] == 307) && !empty($this->headers['location']) && $this->redirects < $redirects)
2281 return $this->SimplePie_File($this->headers['location'], $timeout, $redirects, $headers, $useragent, $force_fsockopen);
2287 $this->error = 'fsocket timed out';
2288 $this->success = false;
2293 return $this->headers['status']['code'];
2297 $this->method = 'fopen';
2298 if ($this->fp = fopen($url, 'r'))
2304 $this->error = 'fopen could not open the file';
2305 $this->success = false;
2313 return $this->headers;
2318 if (is_null($this->body))
2322 $info = stream_get_meta_data($this->fp);
2324 while (!$info['eof'] && !$info['timed_out'])
2326 $this->body .= fread($this->fp, 1024);
2327 $info = stream_get_meta_data($this->fp);
2329 if (!$info['timed_out'])
2331 $this->body = trim($this->body);
2332 if ($this->method == 'fsockopen' && !empty($this->headers['content-encoding']) && ($this->headers['content-encoding'] == 'gzip' || $this->headers['content-encoding'] == 'deflate'))
2334 if (substr($this->body, 0, 8) == "\x1f\x8b\x08\x00\x00\x00\x00\x00")
2336 $this->body = substr($this->body, 10);
2338 $this->body = gzinflate($this->body);
2357 if (!is_null($this->fp))
2359 if (fclose($this->fp))
2375 function parse_headers($headers)
2377 $headers = explode("\r\n", trim($headers));
2378 $status = array_shift($headers);
2379 foreach ($headers as $header)
2381 $data = explode(':', $header, 2);
2382 $head[strtolower(trim($data[0]))] = trim($data[1]);
2384 if (preg_match('/HTTP\/[0-9\.]+ ([0-9]+)(.*)$/i', $status, $matches))
2386 if (isset($head['status']))
2388 unset($head['status']);
2390 $head['status']['code'] = $matches[1];
2391 $head['status']['name'] = trim($matches[2]);
2397 class SimplePie_Cache
2404 function SimplePie_Cache($location, $filename, $extension)
2406 $this->location = $location;
2407 $this->filename = rawurlencode($filename);
2408 $this->extension = rawurlencode($extension);
2409 $this->name = "$location/$this->filename.$this->extension";
2412 function save($data)
2414 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
2416 $fp = fopen($this->name, 'w');
2419 fwrite($fp, serialize($data));
2429 if (file_exists($this->name) && is_readable($this->name))
2431 return unserialize(file_get_contents($this->name));
2438 if (file_exists($this->name))
2440 return filemtime($this->name);
2447 if (file_exists($this->name))
2449 return touch($this->name);
2456 if (file_exists($this->name))
2458 return unlink($this->name);
2464 class SimplePie_Misc
2466 function absolutize_url($relative, $base)
2468 $relative = trim($relative);
2469 $base = trim($base);
2470 if (!empty($relative))
2472 $relative = SimplePie_Misc::parse_url($relative, false);
2473 $relative = array('scheme' => $relative[2], 'authority' => $relative[3], 'path' => $relative[5], 'query' => $relative[7], 'fragment' => $relative[9]);
2474 if (!empty($relative['scheme']))
2476 $target = $relative;
2478 else if (!empty($base))
2480 $base = SimplePie_Misc::parse_url($base, false);
2481 $base = array('scheme' => $base[2], 'authority' => $base[3], 'path' => $base[5], 'query' => $base[7], 'fragment' => $base[9]);
2482 $target['scheme'] = $base['scheme'];
2483 if (!empty($relative['authority']))
2485 $target = array_merge($relative, $target);
2489 $target['authority'] = $base['authority'];
2490 if (!empty($relative['path']))
2492 if (strpos($relative['path'], '/') === 0)
2494 $target['path'] = $relative['path'];
2498 if (!empty($base['path']))
2500 $target['path'] = dirname("$base[path].") . '/' . $relative['path'];
2504 $target['path'] = '/' . $relative['path'];
2507 if (!empty($relative['query']))
2509 $target['query'] = $relative['query'];
2511 $input = $target['path'];
2512 $target['path'] = '';
2513 while (!empty($input))
2515 if (strpos($input, '../') === 0)
2517 $input = substr($input, 3);
2519 else if (strpos($input, './') === 0)
2521 $input = substr($input, 2);
2523 else if (strpos($input, '/./') === 0)
2525 $input = substr_replace($input, '/', 0, 3);
2527 else if (strpos($input, '/.') === 0 && SimplePie_Misc::strendpos($input, '/.') === 0)
2529 $input = substr_replace($input, '/', -2);
2531 else if (strpos($input, '/../') === 0)
2533 $input = substr_replace($input, '/', 0, 4);
2534 $target['path'] = preg_replace('/(\/)?([^\/]+)$/msiU', '', $target['path']);
2536 else if (strpos($input, '/..') === 0 && SimplePie_Misc::strendpos($input, '/..') === 0)
2538 $input = substr_replace($input, '/', 0, 3);
2539 $target['path'] = preg_replace('/(\/)?([^\/]+)$/msiU', '', $target['path']);
2541 else if ($input == '.' || $input == '..')
2547 if (preg_match('/^(.+)(\/|$)/msiU', $input, $match))
2549 $target['path'] .= $match[1];
2550 $input = substr_replace($input, '', 0, strlen($match[1]));
2557 if (!empty($base['path']))
2559 $target['path'] = $base['path'];
2563 $target['path'] = '/';
2565 if (!empty($relative['query']))
2567 $target['query'] = $relative['query'];
2569 else if (!empty($base['query']))
2571 $target['query'] = $base['query'];
2575 if (!empty($relative['fragment']))
2577 $target['fragment'] = $relative['fragment'];
2585 if (!empty($target['scheme']))
2587 $return .= "$target[scheme]:";
2589 if (!empty($target['authority']))
2591 $return .= $target['authority'];
2593 if (!empty($target['path']))
2595 $return .= $target['path'];
2597 if (!empty($target['query']))
2599 $return .= "?$target[query]";
2601 if (!empty($target['fragment']))
2603 $return .= "#$target[fragment]";
2613 function strendpos($haystack, $needle)
2615 return strlen($haystack) - strpos($haystack, $needle) - strlen($needle);
2618 function get_element($realname, $string)
2621 $name = preg_quote($realname, '/');
2622 preg_match_all("/<($name)((\s*((\w+:)?\w+)\s*=\s*(\"([^\"]*)\"|'([^']*)'|(.*)))*)\s*((\/)?>|>(.*)<\/$name>)/msiU", $string, $matches, PREG_SET_ORDER);
2623 for ($i = 0; $i < count($matches); $i++)
2625 $return[$i]['tag'] = $realname;
2626 $return[$i]['full'] = $matches[$i][0];
2627 if (strlen($matches[$i][10]) <= 2)
2629 $return[$i]['self_closing'] = true;
2633 $return[$i]['self_closing'] = false;
2634 $return[$i]['content'] = $matches[$i][12];
2636 $return[$i]['attribs'] = array();
2637 if (!empty($matches[$i][2]))
2639 preg_match_all('/((\w+:)?\w+)\s*=\s*("([^"]*)"|\'([^\']*)\'|(\S+))\s/msiU', ' ' . $matches[$i][2] . ' ', $attribs, PREG_SET_ORDER);
2640 for ($j = 0; $j < count($attribs); $j++)
2642 $return[$i]['attribs'][strtoupper($attribs[$j][1])]['data'] = $attribs[$j][count($attribs[$j])-1];
2643 $first = substr($attribs[$j][2], 0, 1);
2644 $return[$i]['attribs'][strtoupper($attribs[$j][1])]['split'] = ($first == '"' || $first == "'") ? $first : '"';
2651 function element_implode($element)
2653 $full = "<$element[tag]";
2654 foreach ($element['attribs'] as $key => $value)
2656 $key = strtolower($key);
2657 $full .= " $key=$value[split]$value[data]$value[split]";
2659 if ($element['self_closing'])
2665 $full .= ">$element[content]</$element[tag]>";
2670 function error($message, $level, $file, $line)
2675 $note = 'PHP Error';
2677 case E_USER_WARNING:
2678 $note = 'PHP Warning';
2681 $note = 'PHP Notice';
2684 $note = 'Unknown Error';
2687 error_log("$note: $message in $file on line $line", 0);
2691 function display_file($url, $timeout = 10, $useragent = null)
2693 $file = new SimplePie_File($url, $timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $useragent);
2694 $headers = $file->headers();
2695 if ($file->body() !== false)
2697 header('Content-type: ' . $headers['content-type']);
2703 function fix_protocol($url, $http = 1)
2705 $parsed = SimplePie_Misc::parse_url($url);
2706 if (!empty($parsed['scheme']) && strtolower($parsed['scheme']) != 'http' && strtolower($parsed['scheme']) != 'https')
2708 return SimplePie_Misc::fix_protocol("$parsed[authority]$parsed[path]$parsed[query]$parsed[fragment]", $http);
2710 if (!file_exists($url) && empty($parsed['scheme']))
2712 return SimplePie_Misc::fix_protocol("http://$url", $http);
2715 if ($http == 2 && !empty($parsed['scheme']))
2719 else if ($http == 3 && strtolower($parsed['scheme']) == 'http')
2721 return substr_replace($url, 'podcast', 0, 4);
2729 function parse_url($url, $parse_match = true)
2731 preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/i', $url, $match);
2732 if (empty($match[0]))
2738 for ($i = 6; $i < 10; $i++)
2740 if (!isset($match[$i]))
2747 $match = array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[6], 'fragment' => $match[8]);
2756 * PCRE Pattern to locate bad bytes in a UTF-8 string
2757 * Comes from W3 FAQ: Multilingual Forms
2758 * Note: modified to include full ASCII range including control chars
2760 * Modified by Geoffrey Sneddon 2006-11-19 to remove functionality
2761 * to choose what the replace string is, and to use a variable for
2762 * the output instead of PHP's output buffer
2764 function utf8_bad_replace($str)
2767 '([\x00-\x7F]' . # ASCII (including control chars)
2768 '|[\xC2-\xDF][\x80-\xBF]' . # non-overlong 2-byte
2769 '|\xE0[\xA0-\xBF][\x80-\xBF]' . # excluding overlongs
2770 '|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}' . # straight 3-byte
2771 '|\xED[\x80-\x9F][\x80-\xBF]' . # excluding surrogates
2772 '|\xF0[\x90-\xBF][\x80-\xBF]{2}' . # planes 1-3
2773 '|[\xF1-\xF3][\x80-\xBF]{3}' . # planes 4-15
2774 '|\xF4[\x80-\x8F][\x80-\xBF]{2}' . # plane 16
2775 '|(.{1}))'; # invalid byte
2777 while (preg_match('/' . $UTF8_BAD . '/S', $str, $matches))
2779 if (!isset($matches[2]))
2781 $output .= $matches[0];
2783 $str = substr($str, strlen($matches[0]));
2788 function change_encoding($data, $input, $output)
2790 $input = SimplePie_Misc::encoding($input);
2791 $output = SimplePie_Misc::encoding($output);
2793 if ($input != $output)
2795 if (function_exists('iconv') && $input['use_iconv'] && $output['use_iconv'] && iconv($input['encoding'], "$output[encoding]//TRANSLIT", $data))
2797 return iconv($input['encoding'], "$output[encoding]//TRANSLIT", $data);
2799 else if (function_exists('iconv') && $input['use_iconv'] && $output['use_iconv'] && iconv($input['encoding'], $output['encoding'], $data))
2801 return iconv($input['encoding'], $output['encoding'], $data);
2803 else if (function_exists('mb_convert_encoding') && $input['use_mbstring'] && $output['use_mbstring'])
2805 return mb_convert_encoding($data, $output['encoding'], $input['encoding']);
2807 else if ($input['encoding'] == 'ISO-8859-1' && $output['encoding'] == 'UTF-8')
2809 return utf8_encode($data);
2811 else if ($input['encoding'] == 'UTF-8' && $output['encoding'] == 'ISO-8859-1')
2813 return utf8_decode($data);
2819 function encoding($encoding)
2821 $return['use_mbstring'] = false;
2822 $return['use_iconv'] = false;
2823 switch (strtolower($encoding))
2829 $return['encoding'] = '7bit';
2830 $return['use_mbstring'] = true;
2836 $return['encoding'] = '8bit';
2837 $return['use_mbstring'] = true;
2843 $return['encoding'] = 'ARMSCII-8';
2844 $return['use_iconv'] = true;
2850 $return['encoding'] = 'US-ASCII';
2851 $return['use_iconv'] = true;
2852 $return['use_mbstring'] = true;
2858 $return['encoding'] = 'BASE64';
2859 $return['use_mbstring'] = true;
2862 // Big5 - Traditional Chinese, mainly used in Taiwan
2865 $return['encoding'] = 'BIG5';
2866 $return['use_iconv'] = true;
2867 $return['use_mbstring'] = true;
2870 // Big5 with Hong Kong extensions, Traditional Chinese
2872 $return['encoding'] = 'BIG5-HKSCS';
2873 $return['use_iconv'] = true;
2874 $return['use_mbstring'] = true;
2879 $return['encoding'] = 'byte2be';
2880 $return['use_mbstring'] = true;
2885 $return['encoding'] = 'byte2le';
2886 $return['use_mbstring'] = true;
2891 $return['encoding'] = 'byte4be';
2892 $return['use_mbstring'] = true;
2897 $return['encoding'] = 'byte4le';
2898 $return['use_mbstring'] = true;
2904 $return['encoding'] = 'EUC-CN';
2905 $return['use_iconv'] = true;
2906 $return['use_mbstring'] = true;
2910 case 'euc-jisx0213':
2912 $return['encoding'] = 'EUC-JISX0213';
2913 $return['use_iconv'] = true;
2919 $return['encoding'] = 'EUC-JP';
2920 $return['use_iconv'] = true;
2921 $return['use_mbstring'] = true;
2928 $return['encoding'] = 'EUCJP-win';
2929 $return['use_iconv'] = true;
2930 $return['use_mbstring'] = true;
2936 $return['encoding'] = 'EUC-KR';
2937 $return['use_iconv'] = true;
2938 $return['use_mbstring'] = true;
2944 $return['encoding'] = 'EUC-TW';
2945 $return['use_iconv'] = true;
2946 $return['use_mbstring'] = true;
2949 // GB18030 - Simplified Chinese, national standard character set
2950 case 'gb18030-2000':
2952 $return['encoding'] = 'GB18030';
2953 $return['use_iconv'] = true;
2956 // GB2312 - Simplified Chinese, national standard character set
2959 $return['encoding'] = 'GB2312';
2960 $return['use_mbstring'] = true;
2965 $return['encoding'] = 'GBK';
2966 $return['use_iconv'] = true;
2970 case 'georgian-academy':
2971 $return['encoding'] = 'Georgian-Academy';
2972 $return['use_iconv'] = true;
2977 $return['encoding'] = 'Georgian-PS';
2978 $return['use_iconv'] = true;
2982 case 'html-entities':
2983 case 'htmlentities':
2984 $return['encoding'] = 'HTML-ENTITIES';
2985 $return['use_mbstring'] = true;
2990 $return['encoding'] = 'HZ';
2991 $return['use_iconv'] = true;
2992 $return['use_mbstring'] = true;
2999 $return['encoding'] = 'ISO-2022-CN';
3000 $return['use_iconv'] = true;
3004 case 'iso-2022-cn-ext':
3005 case 'iso2022-cn-ext':
3006 case 'iso2022cn-ext':
3007 case 'iso2022cnext':
3008 $return['encoding'] = 'ISO-2022-CN';
3009 $return['use_iconv'] = true;
3016 $return['encoding'] = 'ISO-2022-JP';
3017 $return['use_iconv'] = true;
3018 $return['use_mbstring'] = true;
3022 case 'iso-2022-jp-1':
3023 case 'iso2022-jp-1':
3026 $return['encoding'] = 'ISO-2022-JP-1';
3027 $return['use_iconv'] = true;
3031 case 'iso-2022-jp-2':
3032 case 'iso2022-jp-2':
3035 $return['encoding'] = 'ISO-2022-JP-2';
3036 $return['use_iconv'] = true;
3040 case 'iso-2022-jp-3':
3041 case 'iso2022-jp-3':
3044 $return['encoding'] = 'ISO-2022-JP-3';
3045 $return['use_iconv'] = true;
3052 $return['encoding'] = 'ISO-2022-KR';
3053 $return['use_iconv'] = true;
3054 $return['use_mbstring'] = true;
3060 $return['encoding'] = 'ISO-8859-1';
3061 $return['use_iconv'] = true;
3062 $return['use_mbstring'] = true;
3068 $return['encoding'] = 'ISO-8859-2';
3069 $return['use_iconv'] = true;
3070 $return['use_mbstring'] = true;
3076 $return['encoding'] = 'ISO-8859-3';
3077 $return['use_iconv'] = true;
3078 $return['use_mbstring'] = true;
3084 $return['encoding'] = 'ISO-8859-4';
3085 $return['use_iconv'] = true;
3086 $return['use_mbstring'] = true;
3092 $return['encoding'] = 'ISO-8859-5';
3093 $return['use_iconv'] = true;
3094 $return['use_mbstring'] = true;
3100 $return['encoding'] = 'ISO-8859-6';
3101 $return['use_iconv'] = true;
3102 $return['use_mbstring'] = true;
3108 $return['encoding'] = 'ISO-8859-7';
3109 $return['use_iconv'] = true;
3110 $return['use_mbstring'] = true;
3116 $return['encoding'] = 'ISO-8859-8';
3117 $return['use_iconv'] = true;
3118 $return['use_mbstring'] = true;
3124 $return['encoding'] = 'ISO-8859-9';
3125 $return['use_iconv'] = true;
3126 $return['use_mbstring'] = true;
3132 $return['encoding'] = 'ISO-8859-10';
3133 $return['use_iconv'] = true;
3134 $return['use_mbstring'] = true;
3137 // mbstring/iconv functions don't appear to support 11 & 12
3142 $return['encoding'] = 'ISO-8859-13';
3143 $return['use_iconv'] = true;
3144 $return['use_mbstring'] = true;
3150 $return['encoding'] = 'ISO-8859-14';
3151 $return['use_iconv'] = true;
3152 $return['use_mbstring'] = true;
3158 $return['encoding'] = 'ISO-8859-15';
3159 $return['use_iconv'] = true;
3160 $return['use_mbstring'] = true;
3166 $return['encoding'] = 'ISO-8859-16';
3167 $return['use_iconv'] = true;
3172 $return['encoding'] = 'JIS';
3173 $return['use_mbstring'] = true;
3178 $return['encoding'] = 'JOHAB';
3179 $return['use_iconv'] = true;
3185 $return['encoding'] = 'KOI8-R';
3186 $return['use_iconv'] = true;
3187 $return['use_mbstring'] = true;
3193 $return['encoding'] = 'KOI8-T';
3194 $return['use_iconv'] = true;
3200 $return['encoding'] = 'KOI8-U';
3201 $return['use_iconv'] = true;
3204 // Russian+Ukrainian
3207 $return['encoding'] = 'KOI8-RU';
3208 $return['use_iconv'] = true;
3211 // Macintosh (Mac OS Classic)
3213 $return['encoding'] = 'Macintosh';
3214 $return['use_iconv'] = true;
3217 // MacArabic (Mac OS Classic)
3219 $return['encoding'] = 'MacArabic';
3220 $return['use_iconv'] = true;
3223 // MacCentralEurope (Mac OS Classic)
3224 case 'maccentraleurope':
3225 $return['encoding'] = 'MacCentralEurope';
3226 $return['use_iconv'] = true;
3229 // MacCroatian (Mac OS Classic)
3231 $return['encoding'] = 'MacCroatian';
3232 $return['use_iconv'] = true;
3235 // MacCyrillic (Mac OS Classic)
3237 $return['encoding'] = 'MacCyrillic';
3238 $return['use_iconv'] = true;
3241 // MacGreek (Mac OS Classic)
3243 $return['encoding'] = 'MacGreek';
3244 $return['use_iconv'] = true;
3247 // MacHebrew (Mac OS Classic)
3249 $return['encoding'] = 'MacHebrew';
3250 $return['use_iconv'] = true;
3253 // MacIceland (Mac OS Classic)
3255 $return['encoding'] = 'MacIceland';
3256 $return['use_iconv'] = true;
3259 // MacRoman (Mac OS Classic)
3261 $return['encoding'] = 'MacRoman';
3262 $return['use_iconv'] = true;
3265 // MacRomania (Mac OS Classic)
3267 $return['encoding'] = 'MacRomania';
3268 $return['use_iconv'] = true;
3271 // MacThai (Mac OS Classic)
3273 $return['encoding'] = 'MacThai';
3274 $return['use_iconv'] = true;
3277 // MacTurkish (Mac OS Classic)
3279 $return['encoding'] = 'MacTurkish';
3280 $return['use_iconv'] = true;
3283 // MacUkraine (Mac OS Classic)
3285 $return['encoding'] = 'MacUkraine';
3286 $return['use_iconv'] = true;
3292 $return['encoding'] = 'MuleLao-1';
3293 $return['use_iconv'] = true;
3300 $return['encoding'] = 'Shift_JIS';
3301 $return['use_iconv'] = true;
3302 $return['use_mbstring'] = true;
3306 case 'shift-jisx0213':
3307 case 'shiftjisx0213':
3308 $return['encoding'] = 'Shift_JISX0213';
3309 $return['use_iconv'] = true;
3315 case 'shift_jis-win':
3316 $return['encoding'] = 'SJIS-win';
3317 $return['use_iconv'] = true;
3318 $return['use_mbstring'] = true;
3321 // TCVN - Vietnamese
3323 $return['encoding'] = 'TCVN';
3324 $return['use_iconv'] = true;
3329 $return['encoding'] = 'TDS565';
3330 $return['use_iconv'] = true;
3336 $return['encoding'] = 'TIS-620';
3337 $return['use_iconv'] = true;
3338 $return['use_mbstring'] = true;
3346 $return['encoding'] = 'UCS-2';
3347 $return['use_iconv'] = true;
3348 $return['use_mbstring'] = true;
3356 $return['encoding'] = 'UCS-2BE';
3357 $return['use_iconv'] = true;
3358 $return['use_mbstring'] = true;
3366 $return['encoding'] = 'UCS-2LE';
3367 $return['use_iconv'] = true;
3368 $return['use_mbstring'] = true;
3372 case 'ucs-2-internal':
3373 case 'ucs2internal':
3374 $return['encoding'] = 'UCS-2-INTERNAL';
3375 $return['use_iconv'] = true;
3383 $return['encoding'] = 'UCS-4';
3384 $return['use_iconv'] = true;
3385 $return['use_mbstring'] = true;
3393 $return['encoding'] = 'UCS-4BE';
3394 $return['use_iconv'] = true;
3395 $return['use_mbstring'] = true;
3403 $return['encoding'] = 'UCS-4LE';
3404 $return['use_iconv'] = true;
3405 $return['use_mbstring'] = true;
3409 case 'ucs-4-internal':
3410 case 'ucs4internal':
3411 $return['encoding'] = 'UCS-4-INTERNAL';
3412 $return['use_iconv'] = true;
3418 $return['encoding'] = 'UCS-16';
3419 $return['use_iconv'] = true;
3420 $return['use_mbstring'] = true;
3426 $return['encoding'] = 'UCS-16BE';
3427 $return['use_iconv'] = true;
3428 $return['use_mbstring'] = true;
3434 $return['encoding'] = 'UCS-16LE';
3435 $return['use_iconv'] = true;
3436 $return['use_mbstring'] = true;
3442 $return['encoding'] = 'UCS-32';
3443 $return['use_iconv'] = true;
3444 $return['use_mbstring'] = true;
3450 $return['encoding'] = 'UCS-32BE';
3451 $return['use_iconv'] = true;
3452 $return['use_mbstring'] = true;
3458 $return['encoding'] = 'UCS-32LE';
3459 $return['use_iconv'] = true;
3460 $return['use_mbstring'] = true;
3466 $return['encoding'] = 'UTF-7';
3467 $return['use_iconv'] = true;
3468 $return['use_mbstring'] = true;
3475 $return['encoding'] = 'UTF7-IMAP';
3476 $return['use_mbstring'] = true;
3479 // VISCII - Vietnamese ASCII
3481 $return['encoding'] = 'VISCII';
3482 $return['use_iconv'] = true;
3485 // Windows-specific Central & Eastern Europe
3487 case 'windows-1250':
3490 $return['encoding'] = 'Windows-1250';
3491 $return['use_iconv'] = true;
3494 // Windows-specific Cyrillic
3496 case 'windows-1251':
3499 $return['encoding'] = 'Windows-1251';
3500 $return['use_iconv'] = true;
3501 $return['use_mbstring'] = true;
3504 // Windows-specific Western Europe
3506 case 'windows-1252':
3508 $return['encoding'] = 'Windows-1252';
3509 $return['use_iconv'] = true;
3510 $return['use_mbstring'] = true;
3513 // Windows-specific Greek
3515 case 'windows-1253':
3517 $return['encoding'] = 'Windows-1253';
3518 $return['use_iconv'] = true;
3521 // Windows-specific Turkish
3523 case 'windows-1254':
3525 $return['encoding'] = 'Windows-1254';
3526 $return['use_iconv'] = true;
3529 // Windows-specific Hebrew
3531 case 'windows-1255':
3533 $return['encoding'] = 'Windows-1255';
3534 $return['use_iconv'] = true;
3537 // Windows-specific Arabic
3539 case 'windows-1256':
3541 $return['encoding'] = 'Windows-1256';
3542 $return['use_iconv'] = true;
3545 // Windows-specific Baltic
3547 case 'windows-1257':
3549 $return['encoding'] = 'Windows-1257';
3550 $return['use_iconv'] = true;
3553 // Windows-specific Vietnamese
3555 case 'windows-1258':
3557 $return['encoding'] = 'Windows-1258';
3558 $return['use_iconv'] = true;
3563 $return['encoding'] = 'UTF-8';
3564 $return['use_iconv'] = true;
3565 $return['use_mbstring'] = true;
3573 function get_curl_version()
3576 if (is_array(curl_version()))
3578 $curl = curl_version();
3579 $curl = $curl['version'];
3583 $curl = curl_version();
3584 $curl = explode(' ', $curl);
3585 $curl = explode('/', $curl[0]);
3591 function is_a_class($class1, $class2)
3593 if (class_exists($class1))
3595 $classes = array(strtolower($class1));
3596 while ($class1 = get_parent_class($class1))
3598 $classes[] = strtolower($class1);
3600 return in_array(strtolower($class2), $classes);
3609 class SimplePie_Locator
3616 var $file_class = 'SimplePie_File';
3618 function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File')
3620 if (!is_a($file, 'SimplePie_File'))
3622 $this->file = new $this->file_class($file, $timeout, $useragent);
3626 $this->file =& $file;
3628 $this->file_class = $file_class;
3629 $this->useragent = $useragent;
3630 $this->timeout = $timeout;
3636 if ($this->is_feed($this->file))
3638 return $this->file->url;
3641 $autodiscovery = $this->autodiscovery($this->file);
3644 return $autodiscovery;
3647 if ($this->get_links($this->file))
3649 if (!empty($this->local))
3651 $extension_local = $this->extension($this->local);
3652 if ($extension_local)
3654 return $extension_local;
3657 $body_local = $this->body($this->local);
3664 if (!empty($this->elsewhere))
3666 $extension_elsewhere = $this->extension($this->elsewhere);
3667 if ($extension_elsewhere)
3669 return $extension_elsewhere;
3672 $body_elsewhere = $this->body($this->elsewhere);
3673 if ($body_elsewhere)
3675 return $body_elsewhere;
3682 function is_feed(&$file)
3684 if (!is_a($file, 'SimplePie_File'))
3688 $file2 = new $this->file_class($file, $this->timeout, 5, null, $this->useragent);
3692 $file2 = new $this->file_class($file);
3701 $body = preg_replace('/<\!-(.*)-\>/msiU', '', $file2->body());
3702 if (preg_match('/<(\w+\:)?rss/msiU', $body) || preg_match('/<(\w+\:)?RDF/mi', $body) || preg_match('/<(\w+\:)?feed/mi', $body))
3709 function autodiscovery(&$file)
3711 $links = SimplePie_Misc::get_element('link', $file->body());
3713 foreach ($links as $link)
3715 if (!empty($link['attribs']['TYPE']['data']) && !empty($link['attribs']['HREF']['data']) && !empty($link['attribs']['REL']['data']))
3717 $rel = preg_split('/\s+/', strtolower(trim($link['attribs']['REL']['data'])));
3718 $type = preg_match('/^(application\/rss\+xml|application\/atom\+xml|application\/rdf\+xml|application\/xml\+rss|application\/xml\+atom|application\/xml\+rdf|application\/xml|application\/x\.atom\+xml|text\/xml)(;|$)/msiU', trim($link['attribs']['TYPE']['data']));
3719 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['HREF']['data']), $this->file->url);
3720 if (!in_array($href, $done) && in_array('alternate', $rel) && $type)
3722 $feed = $this->is_feed($href);
3734 function get_links(&$file)
3736 $links = SimplePie_Misc::get_element('a', $file->body());
3737 foreach ($links as $link)
3739 if (!empty($link['attribs']['HREF']['data']))
3741 $href = trim($link['attribs']['HREF']['data']);
3742 $parsed = SimplePie_Misc::parse_url($href);
3743 if (empty($parsed['scheme']) || $parsed['scheme'] != 'javascript')
3745 $current = SimplePie_Misc::parse_url($this->file->url);
3746 if (empty($parsed['authority']) || $parsed['authority'] == $current['authority'])
3748 $this->local[] = SimplePie_Misc::absolutize_url($href, $this->file->url);
3752 $this->elsewhere[] = SimplePie_Misc::absolutize_url($href, $this->file->url);
3757 if (!empty($this->local))
3759 $this->local = array_unique($this->local);
3761 if (!empty($this->elsewhere))
3763 $this->elsewhere = array_unique($this->elsewhere);
3765 if (!empty($this->local) || !empty($this->elsewhere))
3772 function extension(&$array)
3774 foreach ($array as $key => $value)
3776 $value = SimplePie_Misc::absolutize_url($value, $this->file->url);
3777 if (in_array(strrchr($value, '.'), array('.rss', '.rdf', '.atom', '.xml')))
3779 if ($this->is_feed($value))
3785 unset($array[$key]);
3792 function body(&$array)
3794 foreach ($array as $key => $value)
3796 $value = SimplePie_Misc::absolutize_url($value, $this->file->url);
3797 if (preg_match('/(rss|rdf|atom|xml)/i', $value))
3799 if ($this->is_feed($value))
3805 unset($array[$key]);
3813 class SimplePie_Parser
3817 var $namespaces = array('xml' => 'HTTP://WWW.W3.ORG/XML/1998/NAMESPACE', 'atom' => 'ATOM', 'rss2' => 'RSS', 'rdf' => 'RDF', 'rss1' => 'RSS', 'dc' => 'DC', 'xhtml' => 'XHTML', 'content' => 'CONTENT');
3822 var $current_column;
3826 var $item_number = 0;
3827 var $inside_channel;
3828 var $author_number= 0;
3829 var $category_number = 0;
3830 var $enclosure_number = 0;
3831 var $link_number = 0;
3832 var $item_link_number = 0;
3837 var $depth_inside_item = 0;
3839 function SimplePie_Parser($data, $encoding, $return_xml = false)
3841 $this->encoding = $encoding;
3844 // UTF-32 Big Endian BOM
3845 if (strpos($data, sprintf('%c%c%c%c', 0x00, 0x00, 0xFE, 0xFF)) === 0)
3847 $data = substr($data, 4);
3849 // UTF-32 Little Endian BOM
3850 else if (strpos($data, sprintf('%c%c%c%c', 0xFF, 0xFE, 0x00, 0x00)) === 0)
3852 $data = substr($data, 4);
3854 // UTF-16 Big Endian BOM
3855 else if (strpos($data, sprintf('%c%c', 0xFE, 0xFF)) === 0)
3857 $data = substr($data, 2);
3859 // UTF-16 Little Endian BOM
3860 else if (strpos($data, sprintf('%c%c', 0xFF, 0xFE)) === 0)
3862 $data = substr($data, 2);
3865 else if (strpos($data, sprintf('%c%c%c', 0xEF, 0xBB, 0xBF)) === 0)
3867 $data = substr($data, 3);
3870 // Make sure the XML prolog is sane and has the correct encoding
3871 if (preg_match('/^<\?xml(.*)?>/msiU', $data, $prolog))
3873 $data = substr_replace($data, '', 0, strlen($prolog[0]));
3875 $data = "<?xml version='1.0' encoding='$encoding'?>\n" . $data;
3877 // Put some data into CDATA blocks
3879 if ((stristr($data, '<rss') || preg_match('/<([a-z0-9]+\:)?RDF/mi', $data)) && (preg_match('/<([a-z0-9]+\:)?channel/mi', $data) || preg_match('/<([a-z0-9]+\:)?item/mi', $data)))
3881 $sp_elements = array(
3902 $sp_elements = array(
3912 foreach ($sp_elements as $full)
3914 $data = preg_replace_callback("/<($full)((\s*((\w+:)?\w+)\s*=\s*(\"([^\"]*)\"|'([^']*)'))*)\s*(\/>|>(.*)<\/$full>)/msiU", array(&$this, 'add_cdata'), $data);
3916 foreach ($sp_elements as $full)
3918 // Deal with CDATA within CDATA (this can be caused by us inserting CDATA above)
3919 $data = preg_replace_callback("/<($full)((\s*((\w+:)?\w+)\s*=\s*(\"([^\"]*)\"|'([^']*)'))*)\s*(\/>|><!\[CDATA\[(.*)\]\]><\/$full>)/msiU", array(&$this, 'cdata_in_cdata'), $data);
3922 // Return the XML, if so desired
3925 $this->data =& $data;
3929 // Create the parser
3930 $this->xml = xml_parser_create_ns($encoding);
3931 xml_parser_set_option($this->xml, XML_OPTION_SKIP_WHITE, 1);
3932 xml_set_object($this->xml, $this);
3933 xml_set_character_data_handler($this->xml, 'data_handler');
3934 xml_set_element_handler($this->xml, 'start_handler', 'end_handler');
3935 xml_set_start_namespace_decl_handler($this->xml, 'start_name_space');
3936 xml_set_end_namespace_decl_handler($this->xml, 'end_name_space');
3939 if (!xml_parse($this->xml, $data))
3942 $this->error_code = xml_get_error_code($this->xml);
3943 $this->error_string = xml_error_string($this->error_code);
3945 $this->current_line = xml_get_current_line_number($this->xml);
3946 $this->current_column = xml_get_current_column_number($this->xml);
3947 $this->current_byte = xml_get_current_byte_index($this->xml);
3948 xml_parser_free($this->xml);
3952 function add_cdata($match)
3954 if (isset($match[10]))
3956 return "<$match[1]$match[2]><![CDATA[$match[10]]]></$match[1]>";
3961 function cdata_in_cdata($match)
3963 if (isset($match[10]))
3965 $match[10] = preg_replace_callback('/<!\[CDATA\[(.*)\]\]>/msiU', array(&$this, 'real_cdata_in_cdata'), $match[10]);
3966 return "<$match[1]$match[2]><![CDATA[$match[10]]]></$match[1]>";
3971 function real_cdata_in_cdata($match)
3973 return htmlspecialchars($match[1], ENT_NOQUOTES);
3976 function do_add_content(&$array, $data)
3978 if ($this->is_first)
3980 $array['data'] = $data;
3981 $array['attribs'] = $this->attribs;
3985 $array['data'] .= $data;
3989 function start_handler($parser, $name, $attribs)
3991 $this->tag_name = $name;
3992 $this->attribs = $attribs;
3993 $this->is_first = true;
3995 if ($this->inside_item)
3997 $this->depth_inside_item++;
4000 switch ($this->tag_name)
4003 case $this->namespaces['rss2'] . ':ITEM':
4004 case $this->namespaces['rss1'] . ':ITEM':
4006 case $this->namespaces['atom'] . ':ENTRY':
4007 $this->inside_item = true;
4008 $this->do_add_content($this->data['items'][$this->item_number], '');
4012 case $this->namespaces['rss2'] . ':CHANNEL':
4013 case $this->namespaces['rss1'] . ':CHANNEL':
4014 $this->inside_channel = true;
4018 case $this->namespaces['rss2'] . ':RSS':
4019 $this->data['feedinfo']['type'] = 'RSS';
4020 $this->do_add_content($this->data['feeddata'], '');
4021 if (!empty($attribs['VERSION']))
4023 $this->data['feedinfo']['version'] = trim($attribs['VERSION']);
4027 case $this->namespaces['rdf'] . ':RDF':
4028 $this->data['feedinfo']['type'] = 'RSS';
4029 $this->do_add_content($this->data['feeddata'], '');
4030 $this->data['feedinfo']['version'] = 1;
4034 case $this->namespaces['atom'] . ':FEED':
4035 $this->data['feedinfo']['type'] = 'Atom';
4036 $this->do_add_content($this->data['feeddata'], '');
4037 if (!empty($attribs['VERSION']))
4039 $this->data['feedinfo']['version'] = trim($attribs['VERSION']);
4044 case $this->namespaces['rss2'] . ':IMAGE':
4045 case $this->namespaces['rss1'] . ':IMAGE':
4046 if ($this->inside_channel)
4048 $this->inside_image = true;
4053 if (!empty($this->data['feedinfo']['type']) && $this->data['feedinfo']['type'] == 'Atom' && ($this->tag_name == 'AUTHOR' || $this->tag_name == $this->namespaces['atom'] . ':AUTHOR'))
4055 $this->inside_author = true;
4057 $this->data_handler($this->xml, '');
4060 function data_handler($parser, $data)
4062 if ($this->inside_item && $this->depth_inside_item == 1)
4064 switch ($this->tag_name)
4067 case $this->namespaces['rss1'] . ':TITLE':
4068 case $this->namespaces['rss2'] . ':TITLE':
4069 case $this->namespaces['atom'] . ':TITLE':
4070 $this->do_add_content($this->data['items'][$this->item_number]['title'], $data);
4073 case $this->namespaces['dc'] . ':TITLE':
4074 $this->do_add_content($this->data['items'][$this->item_number]['dc:title'], $data);
4078 case $this->namespaces['atom'] . ':CONTENT':
4079 $this->do_add_content($this->data['items'][$this->item_number]['content'], $data);
4082 case $this->namespaces['content'] . ':ENCODED':
4083 $this->do_add_content($this->data['items'][$this->item_number]['encoded'], $data);
4087 case $this->namespaces['atom'] . ':SUMMARY':
4088 $this->do_add_content($this->data['items'][$this->item_number]['summary'], $data);
4092 $this->do_add_content($this->data['items'][$this->item_number]['longdesc'], $data);
4096 case $this->namespaces['rss1'] . ':DESCRIPTION':
4097 case $this->namespaces['rss2'] . ':DESCRIPTION':
4098 $this->do_add_content($this->data['items'][$this->item_number]['description'], $data);
4101 case $this->namespaces['dc'] . ':DESCRIPTION':
4102 $this->do_add_content($this->data['items'][$this->item_number]['dc:description'], $data);
4106 case $this->namespaces['rss1'] . ':LINK':
4107 case $this->namespaces['rss2'] . ':LINK':
4108 case $this->namespaces['atom'] . ':LINK':
4109 $this->do_add_content($this->data['items'][$this->item_number]['link'][$this->item_link_number], $data);
4113 case $this->namespaces['rss1'] . ':ENCLOSURE':
4114 case $this->namespaces['rss2'] . ':ENCLOSURE':
4115 case $this->namespaces['atom'] . ':ENCLOSURE':
4116 $this->do_add_content($this->data['items'][$this->item_number]['enclosure'][$this->enclosure_number], $data);
4120 case $this->namespaces['rss1'] . ':GUID':
4121 case $this->namespaces['rss2'] . ':GUID':
4122 $this->do_add_content($this->data['items'][$this->item_number]['guid'], $data);
4126 case $this->namespaces['atom'] . ':ID':
4127 $this->do_add_content($this->data['items'][$this->item_number]['id'], $data);
4131 case $this->namespaces['rss1'] . ':PUBDATE':
4132 case $this->namespaces['rss2'] . ':PUBDATE':
4133 $this->do_add_content($this->data['items'][$this->item_number]['pubdate'], $data);
4136 case $this->namespaces['dc'] . ':DATE':
4137 $this->do_add_content($this->data['items'][$this->item_number]['dc:date'], $data);
4141 case $this->namespaces['atom'] . ':ISSUED':
4142 $this->do_add_content($this->data['items'][$this->item_number]['issued'], $data);
4146 case $this->namespaces['atom'] . ':PUBLISHED':
4147 $this->do_add_content($this->data['items'][$this->item_number]['published'], $data);
4151 case $this->namespaces['atom'] . ':MODIFIED':
4152 $this->do_add_content($this->data['items'][$this->item_number]['modified'], $data);
4156 case $this->namespaces['atom'] . ':UPDATED':
4157 $this->do_add_content($this->data['items'][$this->item_number]['updated'], $data);
4161 case $this->namespaces['rss1'] . ':CATEGORY':
4162 case $this->namespaces['rss2'] . ':CATEGORY':
4163 case $this->namespaces['atom'] . ':CATEGORY':
4164 $this->do_add_content($this->data['items'][$this->item_number]['category'][$this->category_number], $data);
4167 case $this->namespaces['dc'] . ':SUBJECT':
4168 $this->do_add_content($this->data['items'][$this->item_number]['subject'][$this->category_number], $data);
4171 case $this->namespaces['dc'] . ':CREATOR':
4172 $this->do_add_content($this->data['items'][$this->item_number]['creator'][$this->author_number], $data);
4176 case $this->namespaces['rss1'] . ':AUTHOR':
4177 case $this->namespaces['rss2'] . ':AUTHOR':
4178 $this->do_add_content($this->data['items'][$this->item_number]['author'][$this->author_number]['rss'], $data);
4182 if ($this->inside_author)
4184 switch ($this->tag_name)
4187 case $this->namespaces['atom'] . ':NAME':
4188 $this->do_add_content($this->data['items'][$this->item_number]['author'][$this->author_number]['name'], $data);
4192 case $this->namespaces['atom'] . ':URL':
4193 $this->do_add_content($this->data['items'][$this->item_number]['author'][$this->author_number]['url'], $data);
4197 case $this->namespaces['atom'] . ':URI':
4198 $this->do_add_content($this->data['items'][$this->item_number]['author'][$this->author_number]['uri'], $data);
4202 case $this->namespaces['atom'] . ':HOMEPAGE':
4203 $this->do_add_content($this->data['items'][$this->item_number]['author'][$this->author_number]['homepage'], $data);
4207 case $this->namespaces['atom'] . ':EMAIL':
4208 $this->do_add_content($this->data['items'][$this->item_number]['author'][$this->author_number]['email'], $data);
4214 else if (($this->inside_channel && !$this->inside_image) || (isset($this->data['feedinfo']['type']) && $this->data['feedinfo']['type'] == 'Atom'))
4216 switch ($this->tag_name)
4219 case $this->namespaces['rss1'] . ':TITLE':
4220 case $this->namespaces['rss2'] . ':TITLE':
4221 case $this->namespaces['atom'] . ':TITLE':
4222 $this->do_add_content($this->data['info']['title'], $data);
4226 case $this->namespaces['rss1'] . ':LINK':
4227 case $this->namespaces['rss2'] . ':LINK':
4228 case $this->namespaces['atom'] . ':LINK':
4229 $this->do_add_content($this->data['info']['link'][$this->link_number], $data);
4233 case $this->namespaces['rss1'] . ':DESCRIPTION':
4234 case $this->namespaces['rss2'] . ':DESCRIPTION':
4235 $this->do_add_content($this->data['info']['description'], $data);
4238 case $this->namespaces['dc'] . ':DESCRIPTION':
4239 $this->do_add_content($this->data['info']['dc:description'], $data);
4243 case $this->namespaces['atom'] . ':TAGLINE':
4244 $this->do_add_content($this->data['info']['tagline'], $data);
4248 case $this->namespaces['atom'] . ':SUBTITLE':
4249 $this->do_add_content($this->data['info']['subtitle'], $data);
4253 case $this->namespaces['rss1'] . ':COPYRIGHT':
4254 case $this->namespaces['rss2'] . ':COPYRIGHT':
4255 case $this->namespaces['atom'] . ':COPYRIGHT':
4256 $this->do_add_content($this->data['info']['copyright'], $data);
4260 case $this->namespaces['rss1'] . ':LANGUAGE':
4261 case $this->namespaces['rss2'] . ':LANGUAGE':
4262 $this->do_add_content($this->data['info']['language'], $data);
4266 case $this->namespaces['atom'] . ':LOGO':
4267 $this->do_add_content($this->data['info']['logo'], $data);
4273 else if ($this->inside_channel && $this->inside_image)
4275 switch ($this->tag_name)
4278 case $this->namespaces['rss1'] . ':TITLE':
4279 case $this->namespaces['rss2'] . ':TITLE':
4280 $this->do_add_content($this->data['info']['image']['title'], $data);
4284 case $this->namespaces['rss1'] . ':URL':
4285 case $this->namespaces['rss2'] . ':URL':
4286 $this->do_add_content($this->data['info']['image']['url'], $data);
4290 case $this->namespaces['rss1'] . ':LINK':
4291 case $this->namespaces['rss2'] . ':LINK':
4292 $this->do_add_content($this->data['info']['image']['link'], $data);
4296 case $this->namespaces['rss1'] . ':WIDTH':
4297 case $this->namespaces['rss2'] . ':WIDTH':
4298 $this->do_add_content($this->data['info']['image']['width'], $data);
4302 case $this->namespaces['rss1'] . ':HEIGHT':
4303 case $this->namespaces['rss2'] . ':HEIGHT':
4304 $this->do_add_content($this->data['info']['image']['height'], $data);
4308 $this->is_first = false;
4311 function end_handler($parser, $name)
4313 $this->tag_name = '';
4317 case $this->namespaces['rss1'] . ':ITEM':
4318 case $this->namespaces['rss2'] . ':ITEM':
4320 case $this->namespaces['atom'] . ':ENTRY':
4321 $this->inside_item = false;
4322 $this->item_number++;
4323 $this->author_number = 0;
4324 $this->category_number = 0;
4325 $this->enclosure_number = 0;
4326 $this->item_link_number = 0;
4330 case $this->namespaces['rss1'] . ':CHANNEL':
4331 case $this->namespaces['rss2'] . ':CHANNEL':
4332 $this->inside_channel = false;
4336 case $this->namespaces['rss1'] . ':IMAGE':
4337 case $this->namespaces['rss2'] . ':IMAGE':
4338 $this->inside_image = false;
4342 case $this->namespaces['rss1'] . ':AUTHOR':
4343 case $this->namespaces['rss2'] . ':AUTHOR':
4344 case $this->namespaces['atom'] . ':AUTHOR':
4345 $this->author_number++;
4346 $this->inside_author = false;
4350 case $this->namespaces['rss1'] . ':CATEGORY':
4351 case $this->namespaces['rss2'] . ':CATEGORY':
4352 case $this->namespaces['atom'] . ':CATEGORY':
4353 case $this->namespaces['dc'] . ':SUBJECT':
4354 $this->category_number++;
4358 case $this->namespaces['rss1'] . ':ENCLOSURE':
4359 case $this->namespaces['rss2'] . ':ENCLOSURE':
4360 $this->enclosure_number++;
4364 case $this->namespaces['rss1'] . ':LINK':
4365 case $this->namespaces['rss2'] . ':LINK':
4366 case $this->namespaces['atom'] . ':LINK':
4367 if ($this->inside_item)
4369 $this->item_link_number++;
4373 $this->link_number++;
4377 if ($this->inside_item)
4379 $this->depth_inside_item--;
4383 function start_name_space($parser, $prefix, $uri = null)
4385 $prefix = strtoupper($prefix);
4386 $uri = strtoupper($uri);
4387 if ($prefix == 'ATOM' || $uri == 'HTTP://WWW.W3.ORG/2005/ATOM' || $uri == 'HTTP://PURL.ORG/ATOM/NS#')
4389 $this->namespaces['atom'] = $uri;
4391 else if ($prefix == 'RSS2' || $uri == 'HTTP://BACKEND.USERLAND.COM/RSS2')
4393 $this->namespaces['rss2'] = $uri;
4395 else if ($prefix == 'RDF' || $uri == 'HTTP://WWW.W3.ORG/1999/02/22-RDF-SYNTAX-NS#')
4397 $this->namespaces['rdf'] = $uri;
4399 else if ($prefix == 'RSS' || $uri == 'HTTP://PURL.ORG/RSS/1.0/' || $uri == 'HTTP://MY.NETSCAPE.COM/RDF/SIMPLE/0.9/')
4401 $this->namespaces['rss1'] = $uri;
4403 else if ($prefix == 'DC' || $uri == 'HTTP://PURL.ORG/DC/ELEMENTS/1.1/')
4405 $this->namespaces['dc'] = $uri;
4407 else if ($prefix == 'XHTML' || $uri == 'HTTP://WWW.W3.ORG/1999/XHTML')
4409 $this->namespaces['xhtml'] = $uri;
4410 $this->xhtml_prefix = $prefix;
4412 else if ($prefix == 'CONTENT' || $uri == 'HTTP://PURL.ORG/RSS/1.0/MODULES/CONTENT/')
4414 $this->namespaces['content'] = $uri;
4418 function end_name_space($parser, $prefix)
4420 if ($key = array_search(strtoupper($prefix), $this->namespaces))
4424 $this->namespaces['atom'] = 'ATOM';
4426 else if ($key == 'rss2')
4428 $this->namespaces['rss2'] = 'RSS';
4430 else if ($key == 'rdf')
4432 $this->namespaces['rdf'] = 'RDF';
4434 else if ($key == 'rss1')
4436 $this->namespaces['rss1'] = 'RSS';
4438 else if ($key == 'dc')
4440 $this->namespaces['dc'] = 'DC';
4442 else if ($key == 'xhtml')
4444 $this->namespaces['xhtml'] = 'XHTML';
4445 $this->xhtml_prefix = 'XHTML';
4447 else if ($key == 'content')
4449 $this->namespaces['content'] = 'CONTENT';
4455 class SimplePie_Sanitize
4464 var $cached_entities;
4465 var $cache_convert_entities;
4468 var $remove_div = true;
4469 var $strip_ads = false;
4470 var $replace_headers = false;
4471 var $bypass_image_hotlink = false;
4472 var $bypass_image_hotlink_page = false;
4473 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
4474 var $encode_instead_of_strip = false;
4475 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur');
4476 var $input_encoding = 'UTF-8';
4477 var $output_encoding = 'UTF-8';
4478 var $item_class = 'SimplePie_Item';
4479 var $author_class = 'SimplePie_Author';
4480 var $enclosure_class = 'SimplePie_Enclosure';
4482 function remove_div($enable = true)
4484 $this->remove_div = (bool) $enable;
4487 function strip_ads($enable = false)
4489 $this->strip_ads = (bool) $enable;
4492 function replace_headers($enable = false)
4494 $this->enable_headers = (bool) $enable;
4497 function bypass_image_hotlink($get = false)
4501 $this->bypass_image_hotlink = (string) $get;
4505 $this->bypass_image_hotlink = false;
4509 function bypass_image_hotlink_page($page = false)
4513 $this->bypass_image_hotlink_page = (string) $page;
4517 $this->bypass_image_hotlink_page = false;
4521 function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
4525 if (is_array($tags))
4527 $this->strip_htmltags = $tags;
4531 $this->strip_htmltags = explode(',', $tags);
4536 $this->strip_htmltags = false;
4540 function encode_instead_of_strip($enable = false)
4542 $this->encode_instead_of_strip = (bool) $enable;
4545 function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur'))
4549 if (is_array($attribs))
4551 $this->strip_attributes = $attribs;
4555 $this->strip_attributes = explode(',', $attribs);
4560 $this->strip_attributes = false;
4564 function input_encoding($encoding = 'UTF-8')
4566 $this->input_encoding = (string) $encoding;
4569 function output_encoding($encoding = 'UTF-8')
4571 $this->output_encoding = (string) $encoding;
4574 function set_item_class($class = 'SimplePie_Item')
4576 if (SimplePie_Misc::is_a_class($class, 'SimplePie_Item'))
4578 $this->item_class = $class;
4584 function set_author_class($class = 'SimplePie_Author')
4586 if (SimplePie_Misc::is_a_class($class, 'SimplePie_Author'))
4588 $this->author_class = $class;
4594 function set_enclosure_class($class = 'SimplePie_Enclosure')
4596 if (SimplePie_Misc::is_a_class($class, 'SimplePie_Enclosure'))
4598 $this->enclosure_class = $class;
4604 function parse_data_array(&$data, $url)
4606 // Feed Info (Type and Version)
4607 if (!empty($data['feedinfo']['type']))
4609 $this->feedinfo = $data['feedinfo'];
4612 // Feed level xml:base
4613 if (!empty($data['feeddata']['attribs']['XML:BASE']))
4615 $this->feed_xmlbase = $data['feeddata']['attribs']['XML:BASE'];
4617 else if (!empty($data['feeddata']['attribs']['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:BASE']))
4619 $this->feed_xmlbase = $data['feeddata']['attribs']['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:BASE'];
4621 // FeedBurner feeds use alternate link
4622 else if (strpos($url, 'http://feeds.feedburner.com/') !== 0)
4624 $this->feed_xmlbase = SimplePie_Misc::parse_url($url);
4625 if (empty($this->feed_xmlbase['authority']))
4627 $this->feed_xmlbase = preg_replace('/^' . preg_quote(realpath($_SERVER['DOCUMENT_ROOT']), '/') . '/', '', realpath($url));
4631 $this->feed_xmlbase = $url;
4637 if (!empty($data['info']['link']))
4639 foreach ($data['info']['link'] as $link)
4641 if (empty($link['attribs']['REL']))
4647 $rel = strtolower($link['attribs']['REL']);
4649 if ($rel == 'enclosure')
4654 if (!empty($link['data']))
4656 $href = $this->sanitize($link['data'], $link['attribs'], true);
4658 else if (!empty($link['attribs']['HREF']))
4660 $href = $this->sanitize($link['attribs']['HREF'], $link['attribs'], true);
4662 if (!empty($link['attribs']['TYPE'])) {
4663 $type = $this->sanitize($link['attribs']['TYPE'], $link['attribs']);
4665 if (!empty($link['attribs']['LENGTH'])) {
4666 $length = $this->sanitize($link['attribs']['LENGTH'], $link['attribs']);
4668 $this->info['link']['enclosure'][] = new $this->enclosure_class($href, $type, $length);
4672 if (!empty($link['data']))
4674 $this->info['link'][$rel][] = $this->sanitize($link['data'], $link['attribs'], true);
4676 else if (!empty($link['attribs']['HREF']))
4678 $this->info['link'][$rel][] = $this->sanitize($link['attribs']['HREF'], $link['attribs'], true);
4684 // Use the first alternate link if we don't have any feed xml:base
4685 if (empty($this->feed_xmlbase) && !empty($this->info['link']['alternate'][0]))
4687 $this->feed_xmlbase = $this->info['link']['alternate'][0];
4691 if (!empty($data['info']['title']['data']))
4693 $this->info['title'] = $this->sanitize($data['info']['title']['data'], $data['info']['title']['attribs']);
4696 // Feed Descriptions
4697 if (!empty($data['info']['description']['data']))
4699 $this->info['description'] = $this->sanitize($data['info']['description']['data'], $data['info']['description']['attribs'], false, true);
4701 if (!empty($data['info']['dc:description']['data']))
4703 $this->info['dc:description'] = $this->sanitize($data['info']['dc:description']['data'], $data['info']['dc:description']['attribs']);
4705 if (!empty($data['info']['tagline']['data']))
4707 $this->info['tagline'] = $this->sanitize($data['info']['tagline']['data'], $data['info']['tagline']['attribs']);
4709 if (!empty($data['info']['subtitle']['data']))
4711 $this->info['subtitle'] = $this->sanitize($data['info']['subtitle']['data'], $data['info']['subtitle']['attribs']);
4715 if (!empty($data['info']['language']['data']))
4717 $this->info['language'] = $this->sanitize($data['info']['language']['data'], $data['info']['language']['attribs']);
4719 if (!empty($data['feeddata']['attribs']['XML:LANG']))
4721 $this->info['xml:lang'] = $this->sanitize($data['feeddata']['attribs']['XML:LANG'], null);
4723 else if (!empty($data['feeddata']['attribs']['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:LANG']))
4725 $this->info['xml:lang'] = $this->sanitize($data['feeddata']['attribs']['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:LANG'], null);
4729 if (!empty($data['info']['copyright']['data']))
4731 $this->info['copyright'] = $this->sanitize($data['info']['copyright']['data'], $data['info']['copyright']['attribs']);
4735 if (!empty($data['info']['image']['title']['data']))
4737 $this->info['image']['title'] = $this->sanitize($data['info']['image']['title']['data'], $data['info']['image']['title']['attribs']);
4739 if (!empty($data['info']['image']['url']['data']))
4741 $this->info['image']['url'] = $this->sanitize($data['info']['image']['url']['data'], $data['info']['image']['url']['attribs'], true);
4743 if (!empty($data['info']['logo']['data']))
4745 $this->info['image']['logo'] = $this->sanitize($data['info']['logo']['data'], $data['info']['logo']['attribs'], true);
4747 if (!empty($data['info']['image']['link']['data']))
4749 $this->info['image']['link'] = $this->sanitize($data['info']['image']['link']['data'], $data['info']['image']['link']['attribs'], true);
4751 if (!empty($data['info']['image']['width']['data']))
4753 $this->info['image']['width'] = $this->sanitize($data['info']['image']['width']['data'], $data['info']['image']['width']['attribs']);
4755 if (!empty($data['info']['image']['height']['data']))
4757 $this->info['image']['height'] = $this->sanitize($data['info']['image']['height']['data'], $data['info']['image']['height']['attribs']);
4761 if (!empty($data['items']))
4763 foreach ($data['items'] as $key => $item)
4767 // Item level xml:base
4768 if (!empty($item['attribs']['XML:BASE']))
4770 $this->item_xmlbase = SimplePie_Misc::absolutize_url($item['attribs']['XML:BASE'], $this->feed_xmlbase);
4772 else if (!empty($item['attribs']['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:BASE']))
4774 $this->item_xmlbase = SimplePie_Misc::absolutize_url($item['attribs']['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:BASE'], $this->feed_xmlbase);
4778 $this->item_xmlbase = null;
4782 if (!empty($item['title']['data'])) {
4783 $newitem['title'] = $this->sanitize($item['title']['data'], $item['title']['attribs']);
4785 if (!empty($item['dc:title']['data']))
4787 $newitem['dc:title'] = $this->sanitize($item['dc:title']['data'], $item['dc:title']['attribs']);
4791 if (!empty($item['content']['data']))
4793 $newitem['content'] = $this->sanitize($item['content']['data'], $item['content']['attribs']);
4795 if (!empty($item['encoded']['data']))
4797 $newitem['encoded'] = $this->sanitize($item['encoded']['data'], $item['encoded']['attribs']);
4799 if (!empty($item['summary']['data']))
4801 $newitem['summary'] = $this->sanitize($item['summary']['data'], $item['summary']['attribs']);
4803 if (!empty($item['description']['data']))
4805 $newitem['description'] = $this->sanitize($item['description']['data'], $item['description']['attribs'], false, true);
4807 if (!empty($item['dc:description']['data']))
4809 $newitem['dc:description'] = $this->sanitize($item['dc:description']['data'], $item['dc:description']['attribs']);
4811 if (!empty($item['longdesc']['data']))
4813 $newitem['longdesc'] = $this->sanitize($item['longdesc']['data'], $item['longdesc']['attribs']);
4817 if (!empty($item['link']))
4819 foreach ($item['link'] as $link)
4821 if (empty($link['attribs']['REL']))
4827 $rel = strtolower($link['attribs']['REL']);
4829 if ($rel == 'enclosure')
4834 if (!empty($link['data']))
4836 $href = $this->sanitize($link['data'], $link['attribs'], true);
4838 else if (!empty($link['attribs']['HREF']))
4840 $href = $this->sanitize($link['attribs']['HREF'], $link['attribs'], true);
4842 if (!empty($link['attribs']['TYPE'])) {
4843 $type = $this->sanitize($link['attribs']['TYPE'], $link['attribs']);
4845 if (!empty($link['attribs']['LENGTH'])) {
4846 $length = $this->sanitize($link['attribs']['LENGTH'], $link['attribs']);
4850 $newitem['link'][$rel][] = new $this->enclosure_class($href, $type, $length);
4855 if (!empty($link['data']))
4857 $newitem['link'][$rel][] = $this->sanitize($link['data'], $link['attribs'], true);
4859 else if (!empty($link['attribs']['HREF']))
4861 $newitem['link'][$rel][] = $this->sanitize($link['attribs']['HREF'], $link['attribs'], true);
4868 if (!empty($item['enclosure']))
4870 foreach ($item['enclosure'] as $enclosure)
4872 if (!empty($enclosure['attribs']['URL']))
4876 $href = $this->sanitize($enclosure['attribs']['URL'], $enclosure['attribs'], true);
4877 if (!empty($enclosure['attribs']['TYPE']))
4879 $type = $this->sanitize($enclosure['attribs']['TYPE'], $enclosure['attribs']);
4881 if (!empty($enclosure['attribs']['LENGTH']))
4883 $length = $this->sanitize($enclosure['attribs']['LENGTH'], $enclosure['attribs']);
4885 $newitem['enclosures'][] = new $this->enclosure_class($href, $type, $length);
4891 if (!empty($item['guid']['data']))
4893 if (!empty($item['guid']['attribs']['ISPERMALINK']) && strtolower($item['guid']['attribs']['ISPERMALINK']) == 'false')
4895 $newitem['guid']['permalink'] = false;
4899 $newitem['guid']['permalink'] = true;
4901 $newitem['guid']['data'] = $this->sanitize($item['guid']['data'], $item['guid']['attribs']);
4903 if (!empty($item['id']['data']))
4905 $newitem['id'] = $this->sanitize($item['id']['data'], $item['id']['attribs']);
4909 if (!empty($item['pubdate']['data']))
4911 $newitem['pubdate'] = $this->parse_date($this->sanitize($item['pubdate']['data'], $item['pubdate']['attribs']));
4913 if (!empty($item['dc:date']['data']))
4915 $newitem['dc:date'] = $this->parse_date($this->sanitize($item['dc:date']['data'], $item['dc:date']['attribs']));
4917 if (!empty($item['issued']['data']))
4919 $newitem['issued'] = $this->parse_date($this->sanitize($item['issued']['data'], $item['issued']['attribs']));
4921 if (!empty($item['published']['data']))
4923 $newitem['published'] = $this->parse_date($this->sanitize($item['published']['data'], $item['published']['attribs']));
4925 if (!empty($item['modified']['data']))
4927 $newitem['modified'] = $this->parse_date($this->sanitize($item['modified']['data'], $item['modified']['attribs']));
4929 if (!empty($item['updated']['data']))
4931 $newitem['updated'] = $this->parse_date($this->sanitize($item['updated']['data'], $item['updated']['attribs']));
4935 if (!empty($item['category']))
4937 foreach ($item['category'] as $category)
4939 if (!empty($category['data']))
4941 $newitem['category'][] = $this->sanitize($category['data'], $category['attribs']);
4943 else if (!empty($category['attribs']['TERM']))
4945 $newitem['term'][] = $this->sanitize($category['attribs']['TERM'], $category['attribs']);
4949 if (!empty($item['subject']))
4951 foreach ($item['subject'] as $category)
4953 if (!empty($category['data']))
4955 $newitem['subject'][] = $this->sanitize($category['data'], $category['attribs']);
4961 if (!empty($item['creator']))
4963 foreach ($item['creator'] as $creator)
4965 if (!empty($creator['data']))
4967 $newitem['creator'][] = new $this->author_class($this->sanitize($creator['data'], $creator['attribs']), null, null);
4971 if (!empty($item['author']))
4973 foreach ($item['author'] as $author)
4978 if (!empty($author['rss']))
4980 $sane = $this->sanitize($author['rss']['data'], $author['rss']['attribs']);
4981 if (preg_match('/(.*)@(.*) \((.*)\)/msiU', $sane, $matches)) {
4982 $name = trim($matches[3]);
4983 $email = trim("$matches[1]@$matches[2]");
4990 if (!empty($author['name']))
4992 $name = $this->sanitize($author['name']['data'], $author['name']['attribs']);
4994 if (!empty($author['url']))
4996 $link = $this->sanitize($author['url']['data'], $author['url']['attribs'], true);
4998 else if (!empty($author['uri']))
5000 $link = $this->sanitize($author['uri']['data'], $author['uri']['attribs'], true);
5002 else if (!empty($author['homepage']))
5004 $link = $this->sanitize($author['homepage']['data'], $author['homepage']['attribs'], true);
5006 if (!empty($author['email'])) {
5007 $email = $this->sanitize($author['email']['data'], $author['email']['attribs']);
5010 $newitem['author'][] = new $this->author_class($name, $link, $email);
5013 unset($data['items'][$key]);
5014 $this->items[] = new $this->item_class($newitem);
5019 function sanitize($data, $attribs, $is_url = false, $force_decode = false)
5021 $this->attribs = $attribs;
5022 if (isset($this->feedinfo['type']) && $this->feedinfo['type'] == 'Atom')
5024 if ((!empty($attribs['MODE']) && $attribs['MODE'] == 'base64') || (!empty($attribs['TYPE']) && $attribs['TYPE'] == 'application/octet-stream'))
5026 $data = trim($data);
5027 $data = base64_decode($data);
5029 else if ((!empty($attribs['MODE']) && $attribs['MODE'] == 'escaped' || !empty($attribs['TYPE']) && ($attribs['TYPE'] == 'html' || $attribs['TYPE'] == 'text/html')))
5031 $data = $this->entities_decode($data);
5033 if (!empty($attribs['TYPE']) && ($attribs['TYPE'] == 'xhtml' || $attribs['TYPE'] == 'application/xhtml+xml'))
5035 if ($this->remove_div)
5037 $data = preg_replace('/<div( .*)?>/msiU', '', strrev(preg_replace('/>vid\/</i', '', strrev($data), 1)), 1);
5041 $data = preg_replace('/<div( .*)?>/msiU', '<div>', $data, 1);
5043 $data = $this->convert_entities($data);
5048 $data = $this->convert_entities($data);
5052 $data = $this->entities_decode($data);
5054 $data = trim($data);
5055 $data = preg_replace('/<\!--([^-]|-[^-])*-->/msiU', '', $data);
5057 // If Strip Ads is enabled, strip them.
5058 if ($this->strip_ads)
5060 $data = preg_replace('/<a (.*)href=(.*)click\.phdo\?s=(.*)<\/a>/msiU', '', $data); // Pheedo links (tested with Dooce.com)
5061 $data = preg_replace('/<p(.*)>(.*)<a href="http:\/\/ad.doubleclick.net\/jump\/(.*)<\/p>/msiU', '', $data); // Doubleclick links (tested with InfoWorld.com)
5062 $data = preg_replace('/<p><map (.*)name=(.*)google_ad_map(.*)<\/p>/msiU', '', $data); // Google AdSense for Feeds (tested with tuaw.com).
5063 // Feedflare, from Feedburner
5066 // Replace H1, H2, and H3 tags with the less important H4 tags.
5067 // This is because on a site, the more important headers might make sense,
5068 // but it most likely doesn't fit in the context of RSS-in-a-webpage.
5069 if ($this->replace_headers)
5071 $data = preg_replace('/<h[1-3]((\s*((\w+:)?\w+)\s*=\s*("([^"]*)"|\'([^\']*)\'|(.*)))*)\s*>/msiU', '<h4\\1>', $data);
5072 $data = preg_replace('/<\/h[1-3]>/i', '</h4>', $data);
5077 $data = $this->replace_urls($data, true);
5081 $data = preg_replace_callback('/<(\S+)((\s*((\w+:)?\w+)\s*=\s*("([^"]*)"|\'([^\']*)\'|(.*)))*)\s*(\/>|>(.*)<\/\S+>)/msiU', array(&$this, 'replace_urls'), $data);
5084 // If Bypass Image Hotlink is enabled, rewrite all the image tags.
5085 if ($this->bypass_image_hotlink)
5087 $images = SimplePie_Misc::get_element('img', $data);
5088 foreach ($images as $img)
5090 if (!empty($img['attribs']['SRC']['data']))
5093 if ($this->bypass_image_hotlink_page)
5095 $pre = $this->bypass_image_hotlink_page;
5097 $pre .= "?$this->bypass_image_hotlink=";
5098 $img['attribs']['SRC']['data'] = $pre . rawurlencode(strtr($img['attribs']['SRC']['data'], array_flip(get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES))));
5099 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
5104 // Strip out HTML tags and attributes that might cause various security problems.
5105 // Based on recommendations by Mark Pilgrim at:
5106 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
5107 if ($this->strip_htmltags)
5109 foreach ($this->strip_htmltags as $tag)
5111 $data = preg_replace_callback("/<($tag)((\s*((\w+:)?\w+)(\s*=\s*(\"([^\"]*)\"|'([^']*)'|(.*)))?)*)\s*(\/>|>(.*)<\/($tag)((\s*((\w+:)?\w+)(\s*=\s*(\"([^\"]*)\"|'([^']*)'|(.*)))?)*)\s*>)/msiU", array(&$this, 'do_strip_htmltags'), $data);
5115 if ($this->strip_attributes)
5117 foreach ($this->strip_attributes as $attrib)
5119 $data = preg_replace('/ '. trim($attrib) .'=("|")(\w|\s|=|-|:|;|\/|\.|\?|&|,|#|!|\(|\)|\'|'|<|>|\+|{|})*("|")/i', '', $data);
5120 $data = preg_replace('/ '. trim($attrib) .'=(\'|')(\w|\s|=|-|:|;|\/|\.|\?|&|,|#|!|\(|\)|"|"|<|>|\+|{|})*(\'|')/i', '', $data);
5121 $data = preg_replace('/ '. trim($attrib) .'=(\w|\s|=|-|:|;|\/|\.|\?|&|,|#|!|\(|\)|\+|{|})*/i', '', $data);
5126 $data = SimplePie_Misc::change_encoding($data, $this->input_encoding, $this->output_encoding);
5131 function do_strip_htmltags($match)
5133 if ($this->encode_instead_of_strip)
5135 if (isset($match[12]) && !in_array(strtolower($match[1]), array('script', 'style')))
5137 return "<$match[1]$match[2]>$match[12]</$match[1]>";
5139 else if (isset($match[12]))
5141 return "<$match[1]$match[2]></$match[1]>";
5145 return "<$match[1]$match[2]/>";
5150 if (isset($match[12]) && !in_array(strtolower($match[1]), array('script', 'style')))
5161 function replace_urls($data, $raw_url = false)
5163 if (!empty($this->attribs['XML:BASE']))
5165 $xmlbase = $attribs['XML:BASE'];
5167 else if (!empty($this->attribs['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:BASE']))
5169 $xmlbase = $this->attribs['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:BASE'];
5171 if (!empty($xmlbase))
5173 if (!empty($this->item_xmlbase))
5175 $xmlbase = SimplePie_Misc::absolutize_url($xmlbase, $this->item_xmlbase);
5179 $xmlbase = SimplePie_Misc::absolutize_url($xmlbase, $this->feed_xmlbase);
5182 else if (!empty($this->item_xmlbase))
5184 $xmlbase = $this->item_xmlbase;
5188 $xmlbase = $this->feed_xmlbase;
5193 return SimplePie_Misc::absolutize_url($data, $xmlbase);
5197 $attributes = array(
5211 foreach ($attributes as $attribute)
5213 if (preg_match("/$attribute='(.*)'/siU", $data[0], $attrib) || preg_match("/$attribute=\"(.*)\"/siU", $data[0], $attrib) || preg_match("/$attribute=(.*)[ |\/|>]/siU", $data[0], $attrib))
5215 $new_tag = str_replace($attrib[1], SimplePie_Misc::absolutize_url($attrib[1], $xmlbase), $attrib[0]);
5216 $data[0] = str_replace($attrib[0], $new_tag, $data[0]);
5223 function entities_decode($data)
5225 return preg_replace_callback('/&(#)?(x)?([0-9a-z]+);/mi', array(&$this, 'do_entites_decode'), $data);
5228 function do_entites_decode($data)
5230 if (isset($this->cached_entities[$data[0]]))
5232 return $this->cached_entities[$data[0]];
5236 $return = SimplePie_Misc::change_encoding(html_entity_decode($data[0], ENT_QUOTES), 'ISO-8859-1', $this->input_encoding);
5237 if ($return == $data[0])
5239 $return = SimplePie_Misc::change_encoding(preg_replace_callback('/&#([x]?[0-9a-f]+);/mi', array(&$this, 'replace_num_entity'), $data[0]), 'UTF-8', $this->input_encoding);
5241 $this->cached_entities[$data[0]] = $return;
5246 function convert_entities($data)
5248 return preg_replace_callback('/&#(x)?([0-9a-z]+);/mi', array(&$this, 'do_convert_entities'), $data);
5251 function do_convert_entities($data)
5253 if (isset($this->cache_convert_entities[$data[0]]))
5255 return $this->cache_convert_entities[$data[0]];
5257 else if (isset($this->cached_entities[$data[0]]))
5259 $return = htmlentities($this->cached_entities[$data[0]], ENT_QUOTES, 'UTF-8');
5263 $return = htmlentities(preg_replace_callback('/&#([x]?[0-9a-f]+);/mi', array(&$this, 'replace_num_entity'), $data[0]), ENT_QUOTES, 'UTF-8');
5265 $this->cache_convert_entities[$data[0]] = $return;
5270 * Escape numeric entities
5271 * From a PHP Manual note (on html_entity_decode())
5272 * Copyright (c) 2005 by "php dot net at c dash ovidiu dot tk",
5273 * "emilianomartinezluque at yahoo dot com" and "hurricane at cyberworldz dot org".
5275 * This material may be distributed only subject to the terms and conditions set forth in
5276 * the Open Publication License, v1.0 or later (the latest version is presently available at
5277 * http://www.opencontent.org/openpub/).
5279 function replace_num_entity($ord)
5282 if (preg_match('/^x([0-9a-f]+)$/i', $ord, $match))
5284 $ord = hexdec($match[1]);
5288 $ord = intval($ord);
5301 else if ($ord < 65536)
5305 else if ($ord < 1114112)
5316 $prefix = array(31, 192);
5320 $prefix = array(15, 224);
5324 $prefix = array(7, 240);
5328 for ($i = 0; $i < $no_bytes; $i++)
5330 $byte[$no_bytes-$i-1] = (($ord & (63 * pow(2,6*$i))) / pow(2,6*$i)) & 63 | 128;
5332 $byte[0] = ($byte[0] & $prefix[0]) | $prefix[1];
5335 for ($i = 0; $i < $no_bytes; $i++)
5337 $ret .= chr($byte[$i]);
5342 function parse_date($date)
5344 $military_timezone = array('A' => '-0100', 'B' => '-0200', 'C' => '-0300', 'D' => '-0400', 'E' => '-0500', 'F' => '-0600', 'G' => '-0700', 'H' => '-0800', 'I' => '-0900', 'K' => '-1000', 'L' => '-1100', 'M' => '-1200', 'N' => '+0100', 'O' => '+0200', 'P' => '+0300', 'Q' => '+0400', 'R' => '+0500', 'S' => '+0600', 'T' => '+0700', 'U' => '+0800', 'V' => '+0900', 'W' => '+1000', 'X' => '+1100', 'Y' => '+1200', 'Z' => '-0000');
5345 $north_american_timezone = array('GMT' => '-0000', 'EST' => '-0500', 'EDT' => '-0400', 'CST' => '-0600', 'CDT' => '-0500', 'MST' => '-0700', 'MDT' => '-0600', 'PST' => '-0800', 'PDT' => '-0700');
5346 if (preg_match('/([0-9]{2,4})-?([0-9]{2})-?([0-9]{2})T([0-9]{2}):?([0-9]{2})(:?([0-9]{2}(\.[0-9]*)?))?(UT|GMT|EST|EDT|CST|CDT|MST|MDT|PST|PDT|[a-z]|(\\+|-)[0-9]{4}|(\\+|-)[0-9]{2}:[0-9]{2})?/i', $date, $matches))
5348 if (!isset($matches[7]))
5352 if (!isset($matches[9]))
5356 $matches[7] = str_pad(round($matches[7]), 2, '0', STR_PAD_LEFT);
5357 switch (strlen($matches[9]))
5364 $timezone = $military_timezone[strtoupper($matches[9])];
5368 $timezone = '-0000';
5372 $timezone = $north_american_timezone[strtoupper($matches[9])];
5376 $timezone = $matches[9];
5380 $timezone = substr_replace($matches[9], '', 3, 1);
5383 $date = strtotime("$matches[1]-$matches[2]-$matches[3] $matches[4]:$matches[5]:$matches[7] $timezone");
5385 else if (preg_match('/([0-9]{1,2})\s*(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s*([0-9]{2}|[0-9]{4})\s*([0-9]{2}):([0-9]{2})(:([0-9]{2}(\.[0-9]*)?))?\s*(UT|GMT|EST|EDT|CST|CDT|MST|MDT|PST|PDT|[a-z]|(\\+|-)[0-9]{4}|(\\+|-)[0-9]{2}:[0-9]{2})?/i', $date, $matches))
5387 $three_month = array('Jan' => 1, 'Feb' => 2, 'Mar' => 3, 'Apr' => 4, 'May' => 5, 'Jun' => 6, 'Jul' => 7, 'Aug' => 8, 'Sep' => 9, 'Oct' => 10, 'Nov' => 11, 'Dec' => 12);
5388 $month = $three_month[$matches[2]];
5389 if (strlen($matches[3]) == 2)
5391 $year = ($matches[3] < 70) ? "20$matches[3]" : "19$matches[3]";
5395 $year = $matches[3];
5397 if (!isset($matches[7]))
5401 if (!isset($matches[9]))
5405 $second = str_pad(round($matches[7]), 2, '0', STR_PAD_LEFT);
5406 switch (strlen($matches[9]))
5413 $timezone = $military_timezone[strtoupper($matches[9])];
5417 $timezone = '-0000';
5421 $timezone = $north_american_timezone[strtoupper($matches[9])];
5425 $timezone = $matches[9];
5429 $timezone = substr_replace($matches[9], '', 3, 1);
5432 $date = strtotime("$year-$month-$matches[1] $matches[4]:$matches[5]:$second $timezone");
5436 $date = strtotime($date);
5438 if ($date !== false && $date !== -1)