]> git.wh0rd.org - tt-rss.git/blob - simplepie/simplepie.inc
update_daemon2: don't expect client part to be executable
[tt-rss.git] / simplepie / simplepie.inc
1 <?php
2 /**
3 * SimplePie
4 *
5 * A PHP-Based RSS and Atom Feed Framework.
6 * Takes the hard work out of managing a complete RSS/Atom solution.
7 *
8 * Copyright (c) 2004-2007, Ryan Parman and Geoffrey Sneddon
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without modification, are
12 * permitted provided that the following conditions are met:
13 *
14 * * Redistributions of source code must retain the above copyright notice, this list of
15 * conditions and the following disclaimer.
16 *
17 * * Redistributions in binary form must reproduce the above copyright notice, this list
18 * of conditions and the following disclaimer in the documentation and/or other materials
19 * provided with the distribution.
20 *
21 * * Neither the name of the SimplePie Team nor the names of its contributors may be used
22 * to endorse or promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28 * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 * @package SimplePie
36 * @version "Razzleberry"
37 * @copyright 2004-2007 Ryan Parman, Geoffrey Sneddon
38 * @author Ryan Parman
39 * @author Geoffrey Sneddon
40 * @link http://simplepie.org/ SimplePie
41 * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
42 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
43 * @todo phpDoc comments
44 */
45
46 /**
47 * SimplePie Name
48 */
49 define('SIMPLEPIE_NAME', 'SimplePie');
50
51 /**
52 * SimplePie Version
53 */
54 define('SIMPLEPIE_VERSION', '1.0.1');
55
56 /**
57 * SimplePie Build
58 * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::parse_date() only every load of simplepie.inc)
59 */
60 define('SIMPLEPIE_BUILD', 20070719221955);
61
62 /**
63 * SimplePie Website URL
64 */
65 define('SIMPLEPIE_URL', 'http://simplepie.org/');
66
67 /**
68 * SimplePie Useragent
69 * @see SimplePie::set_useragent()
70 */
71 define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
72
73 /**
74 * SimplePie Linkback
75 */
76 define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
77
78 /**
79 * No Autodiscovery
80 * @see SimplePie::set_autodiscovery_level()
81 */
82 define('SIMPLEPIE_LOCATOR_NONE', 0);
83
84 /**
85 * Feed Link Element Autodiscovery
86 * @see SimplePie::set_autodiscovery_level()
87 */
88 define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
89
90 /**
91 * Local Feed Extension Autodiscovery
92 * @see SimplePie::set_autodiscovery_level()
93 */
94 define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
95
96 /**
97 * Local Feed Body Autodiscovery
98 * @see SimplePie::set_autodiscovery_level()
99 */
100 define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
101
102 /**
103 * Remote Feed Extension Autodiscovery
104 * @see SimplePie::set_autodiscovery_level()
105 */
106 define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
107
108 /**
109 * Remote Feed Body Autodiscovery
110 * @see SimplePie::set_autodiscovery_level()
111 */
112 define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
113
114 /**
115 * All Feed Autodiscovery
116 * @see SimplePie::set_autodiscovery_level()
117 */
118 define('SIMPLEPIE_LOCATOR_ALL', 31);
119
120 /**
121 * No known feed type
122 */
123 define('SIMPLEPIE_TYPE_NONE', 0);
124
125 /**
126 * RSS 0.90
127 */
128 define('SIMPLEPIE_TYPE_RSS_090', 1);
129
130 /**
131 * RSS 0.91 (Netscape)
132 */
133 define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
134
135 /**
136 * RSS 0.91 (Userland)
137 */
138 define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
139
140 /**
141 * RSS 0.91 (both Netscape and Userland)
142 */
143 define('SIMPLEPIE_TYPE_RSS_091', 6);
144
145 /**
146 * RSS 0.92
147 */
148 define('SIMPLEPIE_TYPE_RSS_092', 8);
149
150 /**
151 * RSS 0.93
152 */
153 define('SIMPLEPIE_TYPE_RSS_093', 16);
154
155 /**
156 * RSS 0.94
157 */
158 define('SIMPLEPIE_TYPE_RSS_094', 32);
159
160 /**
161 * RSS 1.0
162 */
163 define('SIMPLEPIE_TYPE_RSS_10', 64);
164
165 /**
166 * RSS 2.0
167 */
168 define('SIMPLEPIE_TYPE_RSS_20', 128);
169
170 /**
171 * RDF-based RSS
172 */
173 define('SIMPLEPIE_TYPE_RSS_RDF', 65);
174
175 /**
176 * Non-RDF-based RSS (truly intended as syndication format)
177 */
178 define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
179
180 /**
181 * All RSS
182 */
183 define('SIMPLEPIE_TYPE_RSS_ALL', 255);
184
185 /**
186 * Atom 0.3
187 */
188 define('SIMPLEPIE_TYPE_ATOM_03', 256);
189
190 /**
191 * Atom 1.0
192 */
193 define('SIMPLEPIE_TYPE_ATOM_10', 512);
194
195 /**
196 * All Atom
197 */
198 define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
199
200 /**
201 * All feed types
202 */
203 define('SIMPLEPIE_TYPE_ALL', 1023);
204
205 /**
206 * No construct
207 */
208 define('SIMPLEPIE_CONSTRUCT_NONE', 0);
209
210 /**
211 * Text construct
212 */
213 define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
214
215 /**
216 * HTML construct
217 */
218 define('SIMPLEPIE_CONSTRUCT_HTML', 2);
219
220 /**
221 * XHTML construct
222 */
223 define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
224
225 /**
226 * base64-encoded construct
227 */
228 define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
229
230 /**
231 * IRI construct
232 */
233 define('SIMPLEPIE_CONSTRUCT_IRI', 16);
234
235 /**
236 * A construct that might be HTML
237 */
238 define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
239
240 /**
241 * All constructs
242 */
243 define('SIMPLEPIE_CONSTRUCT_ALL', 63);
244
245 /**
246 * PCRE for HTML attributes
247 */
248 define('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)(?:\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[a-z0-9\-._:]*)))?)*)\s*');
249
250 /**
251 * PCRE for XML attributes
252 */
253 define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
254
255 /**
256 * XML Namespace
257 */
258 define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
259
260 /**
261 * Atom 1.0 Namespace
262 */
263 define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
264
265 /**
266 * Atom 0.3 Namespace
267 */
268 define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
269
270 /**
271 * RDF Namespace
272 */
273 define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
274
275 /**
276 * RSS 0.90 Namespace
277 */
278 define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
279
280 /**
281 * RSS 1.0 Namespace
282 */
283 define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
284
285 /**
286 * RSS 1.0 Content Module Namespace
287 */
288 define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
289
290 /**
291 * DC 1.0 Namespace
292 */
293 define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
294
295 /**
296 * DC 1.1 Namespace
297 */
298 define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
299
300 /**
301 * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
302 */
303 define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
304
305 /**
306 * GeoRSS Namespace
307 */
308 define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
309
310 /**
311 * Media RSS Namespace
312 */
313 define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
314
315 /**
316 * iTunes RSS Namespace
317 */
318 define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
319
320 /**
321 * XHTML Namespace
322 */
323 define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
324
325 /**
326 * IANA Link Relations Registry
327 */
328 define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
329
330 /**
331 * Whether we're running on PHP5
332 */
333 define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
334
335 /**
336 * SimplePie
337 *
338 * @package SimplePie
339 * @version "Razzleberry"
340 * @copyright 2004-2007 Ryan Parman, Geoffrey Sneddon
341 * @author Ryan Parman
342 * @author Geoffrey Sneddon
343 * @todo Option for type of fetching (cache, not modified header, fetch, etc.)
344 */
345 class SimplePie
346 {
347 /**
348 * @var array Raw data
349 * @access private
350 */
351 var $data = array();
352
353 /**
354 * @var mixed Error string
355 * @access private
356 */
357 var $error;
358
359 /**
360 * @var object Instance of SimplePie_Sanitize (or other class)
361 * @see SimplePie::set_sanitize_class()
362 * @access private
363 */
364 var $sanitize;
365
366 /**
367 * @var string SimplePie Useragent
368 * @see SimplePie::set_useragent()
369 * @access private
370 */
371 var $useragent = SIMPLEPIE_USERAGENT;
372
373 /**
374 * @var string Feed URL
375 * @see SimplePie::set_feed_url()
376 * @access private
377 */
378 var $feed_url;
379
380 /**
381 * @var object Instance of SimplePie_File to use as a feed
382 * @see SimplePie::set_file()
383 * @access private
384 */
385 var $file;
386
387 /**
388 * @var string Raw feed data
389 * @see SimplePie::set_raw_data()
390 * @access private
391 */
392 var $raw_data;
393
394 /**
395 * @var int Timeout for fetching remote files
396 * @see SimplePie::set_timeout()
397 * @access private
398 */
399 var $timeout = 10;
400
401 /**
402 * @var bool Forces fsockopen() to be used for remote files instead
403 * of cURL, even if a new enough version is installed
404 * @see SimplePie::force_fsockopen()
405 * @access private
406 */
407 var $force_fsockopen = false;
408
409 /**
410 * @var bool Enable/Disable XML dump
411 * @see SimplePie::enable_xml_dump()
412 * @access private
413 */
414 var $xml_dump = false;
415
416 /**
417 * @var bool Enable/Disable Caching
418 * @see SimplePie::enable_cache()
419 * @access private
420 */
421 var $cache = true;
422
423 /**
424 * @var int Cache duration (in seconds)
425 * @see SimplePie::set_cache_duration()
426 * @access private
427 */
428 var $cache_duration = 3600;
429
430 /**
431 * @var int Auto-discovery cache duration (in seconds)
432 * @see SimplePie::set_autodiscovery_cache_duration()
433 * @access private
434 */
435 var $autodiscovery_cache_duration = 604800; // 7 Days.
436
437 /**
438 * @var string Cache location (relative to executing script)
439 * @see SimplePie::set_cache_location()
440 * @access private
441 */
442 var $cache_location = './cache';
443
444 /**
445 * @var string Function that creates the cache filename
446 * @see SimplePie::set_cache_name_function()
447 * @access private
448 */
449 var $cache_name_function = 'md5';
450
451 /**
452 * @var bool Reorder feed by date descending
453 * @see SimplePie::enable_order_by_date()
454 * @access private
455 */
456 var $order_by_date = true;
457
458 /**
459 * @var mixed Force input encoding to be set to the follow value
460 * (false, or anything type-cast to false, disables this feature)
461 * @see SimplePie::set_input_encoding()
462 * @access private
463 */
464 var $input_encoding = false;
465
466 /**
467 * @var int Feed Autodiscovery Level
468 * @see SimplePie::set_autodiscovery_level()
469 * @access private
470 */
471 var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
472
473 /**
474 * @var string Class used for caching feeds
475 * @see SimplePie::set_cache_class()
476 * @access private
477 */
478 var $cache_class = 'SimplePie_Cache';
479
480 /**
481 * @var string Class used for locating feeds
482 * @see SimplePie::set_locator_class()
483 * @access private
484 */
485 var $locator_class = 'SimplePie_Locator';
486
487 /**
488 * @var string Class used for parsing feeds
489 * @see SimplePie::set_parser_class()
490 * @access private
491 */
492 var $parser_class = 'SimplePie_Parser';
493
494 /**
495 * @var string Class used for fetching feeds
496 * @see SimplePie::set_file_class()
497 * @access private
498 */
499 var $file_class = 'SimplePie_File';
500
501 /**
502 * @var string Class used for items
503 * @see SimplePie::set_item_class()
504 * @access private
505 */
506 var $item_class = 'SimplePie_Item';
507
508 /**
509 * @var string Class used for authors
510 * @see SimplePie::set_author_class()
511 * @access private
512 */
513 var $author_class = 'SimplePie_Author';
514
515 /**
516 * @var string Class used for categories
517 * @see SimplePie::set_category_class()
518 * @access private
519 */
520 var $category_class = 'SimplePie_Category';
521
522 /**
523 * @var string Class used for enclosures
524 * @see SimplePie::set_enclosures_class()
525 * @access private
526 */
527 var $enclosure_class = 'SimplePie_Enclosure';
528
529 /**
530 * @var string Class used for Media RSS <media:text> captions
531 * @see SimplePie::set_caption_class()
532 * @access private
533 */
534 var $caption_class = 'SimplePie_Caption';
535
536 /**
537 * @var string Class used for Media RSS <media:copyright>
538 * @see SimplePie::set_copyright_class()
539 * @access private
540 */
541 var $copyright_class = 'SimplePie_Copyright';
542
543 /**
544 * @var string Class used for Media RSS <media:credit>
545 * @see SimplePie::set_credit_class()
546 * @access private
547 */
548 var $credit_class = 'SimplePie_Credit';
549
550 /**
551 * @var string Class used for Media RSS <media:rating>
552 * @see SimplePie::set_rating_class()
553 * @access private
554 */
555 var $rating_class = 'SimplePie_Rating';
556
557 /**
558 * @var string Class used for Media RSS <media:restriction>
559 * @see SimplePie::set_restriction_class()
560 * @access private
561 */
562 var $restriction_class = 'SimplePie_Restriction';
563
564 /**
565 * @var mixed Set javascript query string parameter (false, or
566 * anything type-cast to false, disables this feature)
567 * @see SimplePie::set_javascript()
568 * @access private
569 */
570 var $javascript = 'js';
571
572 /**
573 * @var int Maximum number of feeds to check with autodiscovery
574 * @see SimplePie::set_max_checked_feeds()
575 * @access private
576 */
577 var $max_checked_feeds = 10;
578
579 /**
580 * @var string Web-accessible path to the handler_favicon.php file.
581 * @see SimplePie::set_favicon_handler()
582 * @access private
583 */
584 var $favicon_handler = '';
585
586 /**
587 * @var string Web-accessible path to the handler_image.php file.
588 * @see SimplePie::set_image_handler()
589 * @access private
590 */
591 var $image_handler = '';
592
593 /**
594 * @var array Stores the URLs when multiple feeds are being initialized.
595 * @see SimplePie::set_feed_url()
596 * @access private
597 */
598 var $multifeed_url = array();
599
600 /**
601 * @var array Stores SimplePie objects when multiple feeds initialized.
602 * @access private
603 */
604 var $multifeed_objects = array();
605
606 /**
607 * @var array Stores the get_object_vars() array for use with multifeeds.
608 * @see SimplePie::set_feed_url()
609 * @access private
610 */
611 var $config_settings = null;
612
613 /**
614 * @var array Stores the default attributes to be stripped by strip_attributes().
615 * @see SimplePie::strip_attributes()
616 * @access private
617 */
618 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
619
620 /**
621 * @var array Stores the default tags to be stripped by strip_htmltags().
622 * @see SimplePie::strip_htmltags()
623 * @access private
624 */
625 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
626
627 /**
628 * The SimplePie class contains feed level data and options
629 *
630 * There are two ways that you can create a new SimplePie object. The first
631 * is by passing a feed URL as a parameter to the SimplePie constructor
632 * (as well as optionally setting the cache location and cache expiry). This
633 * will initialise the whole feed with all of the default settings, and you
634 * can begin accessing methods and properties immediately.
635 *
636 * The second way is to create the SimplePie object with no parameters
637 * at all. This will enable you to set configuration options. After setting
638 * them, you must initialise the feed using $feed->init(). At that point the
639 * object's methods and properties will be available to you. This format is
640 * what is used throughout this documentation.
641 *
642 * @access public
643 * @since 1.0 Preview Release
644 * @param string $feed_url This is the URL you want to parse.
645 * @param string $cache_location This is where you want the cache to be stored.
646 * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
647 */
648 function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
649 {
650 // Other objects, instances created here so we can set options on them
651 $this->sanitize =& new SimplePie_Sanitize;
652
653 // Set options if they're passed to the constructor
654 if ($cache_location !== null)
655 {
656 $this->set_cache_location($cache_location);
657 }
658
659 if ($cache_duration !== null)
660 {
661 $this->set_cache_duration($cache_duration);
662 }
663
664 // Only init the script if we're passed a feed URL
665 if ($feed_url !== null)
666 {
667 $this->set_feed_url($feed_url);
668 $this->init();
669 }
670 }
671
672 /**
673 * Used for converting object to a string
674 */
675 function __toString()
676 {
677 return md5(serialize($this->data));
678 }
679
680 /**
681 * This is the URL of the feed you want to parse.
682 *
683 * This allows you to enter the URL of the feed you want to parse, or the
684 * website you want to try to use auto-discovery on. This takes priority
685 * over any set raw data.
686 *
687 * You can set multiple feeds to mash together by passing an array instead
688 * of a string for the $url. Remember that with each additional feed comes
689 * additional processing and resources.
690 *
691 * @access public
692 * @since 1.0 Preview Release
693 * @param mixed $url This is the URL (or array of URLs) that you want to parse.
694 * @see SimplePie::set_raw_data()
695 */
696 function set_feed_url($url)
697 {
698 if (is_array($url))
699 {
700 $this->multifeed_url = array();
701 foreach ($url as $value)
702 {
703 $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
704 }
705 }
706 else
707 {
708 $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
709 }
710 }
711
712 /**
713 * Provides an instance of SimplePie_File to use as a feed
714 *
715 * @access public
716 * @param object &$file Instance of SimplePie_File (or subclass)
717 * @return bool True on success, false on failure
718 */
719 function set_file(&$file)
720 {
721 if (SimplePie_Misc::is_a($file, 'SimplePie_File'))
722 {
723 $this->feed_url = $file->url;
724 $this->file =& $file;
725 return true;
726 }
727 return false;
728 }
729
730 /**
731 * Allows you to use a string of RSS/Atom data instead of a remote feed.
732 *
733 * If you have a feed available as a string in PHP, you can tell SimplePie
734 * to parse that data string instead of a remote feed. Any set feed URL
735 * takes precedence.
736 *
737 * @access public
738 * @since 1.0 Beta 3
739 * @param string $data RSS or Atom data as a string.
740 * @see SimplePie::set_feed_url()
741 */
742 function set_raw_data($data)
743 {
744 $this->raw_data = trim($data);
745 }
746
747 /**
748 * Allows you to override the default timeout for fetching remote feeds.
749 *
750 * This allows you to change the maximum time the feed's server to respond
751 * and send the feed back.
752 *
753 * @access public
754 * @since 1.0 Beta 3
755 * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
756 */
757 function set_timeout($timeout = 10)
758 {
759 $this->timeout = (int) $timeout;
760 }
761
762 /**
763 * Forces SimplePie to use fsockopen() instead of the preferred cURL
764 * functions.
765 *
766 * @access public
767 * @since 1.0 Beta 3
768 * @param bool $enable Force fsockopen() to be used
769 */
770 function force_fsockopen($enable = false)
771 {
772 $this->force_fsockopen = (bool) $enable;
773 }
774
775 /**
776 * Outputs the raw XML content of the feed, after it has gone through
777 * SimplePie's filters.
778 *
779 * Used only for debugging, this function will output the XML content as
780 * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
781 * before trying to parse it. Many parts of the feed are re-written in
782 * memory, and in the end, you have a parsable feed. XML dump shows you the
783 * actual XML that SimplePie tries to parse, which may or may not be very
784 * different from the original feed.
785 *
786 * @access public
787 * @since 1.0 Preview Release
788 * @param bool $enable Enable XML dump
789 */
790 function enable_xml_dump($enable = false)
791 {
792 $this->xml_dump = (bool) $enable;
793 }
794
795 /**
796 * Enables/disables caching in SimplePie.
797 *
798 * This option allows you to disable caching all-together in SimplePie.
799 * However, disabling the cache can lead to longer load times.
800 *
801 * @access public
802 * @since 1.0 Preview Release
803 * @param bool $enable Enable caching
804 */
805 function enable_cache($enable = true)
806 {
807 $this->cache = (bool) $enable;
808 }
809
810 /**
811 * Set the length of time (in seconds) that the contents of a feed
812 * will be cached.
813 *
814 * @access public
815 * @param int $seconds The feed content cache duration.
816 */
817 function set_cache_duration($seconds = 3600)
818 {
819 $this->cache_duration = (int) $seconds;
820 }
821
822 /**
823 * Set the length of time (in seconds) that the autodiscovered feed
824 * URL will be cached.
825 *
826 * @access public
827 * @param int $seconds The autodiscovered feed URL cache duration.
828 */
829 function set_autodiscovery_cache_duration($seconds = 604800)
830 {
831 $this->autodiscovery_cache_duration = (int) $seconds;
832 }
833
834 /**
835 * Set the file system location where the cached files should be stored.
836 *
837 * @access public
838 * @param string $location The file system location.
839 */
840 function set_cache_location($location = './cache')
841 {
842 $this->cache_location = (string) $location;
843 }
844
845 /**
846 * Determines whether feed items should be sorted into reverse chronological order.
847 *
848 * @access public
849 * @param bool $enable Sort as reverse chronological order.
850 */
851 function enable_order_by_date($enable = true)
852 {
853 $this->order_by_date = (bool) $enable;
854 }
855
856 /**
857 * Allows you to override the character encoding reported by the feed.
858 *
859 * @access public
860 * @param string $encoding Character encoding.
861 */
862 function set_input_encoding($encoding = false)
863 {
864 if ($encoding)
865 {
866 $this->input_encoding = (string) $encoding;
867 }
868 else
869 {
870 $this->input_encoding = false;
871 }
872 }
873
874 /**
875 * Set how much feed autodiscovery to do
876 *
877 * @access public
878 * @see SIMPLEPIE_LOCATOR_NONE
879 * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
880 * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
881 * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
882 * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
883 * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
884 * @see SIMPLEPIE_LOCATOR_ALL
885 * @param int $level Feed Autodiscovery Level (level can be a
886 * combination of the above constants, see bitwise OR operator)
887 */
888 function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
889 {
890 $this->autodiscovery = (int) $level;
891 }
892
893 /**
894 * Allows you to change which class SimplePie uses for caching.
895 * Useful when you are overloading or extending SimplePie's default classes.
896 *
897 * @access public
898 * @param string $class Name of custom class.
899 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
900 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
901 */
902 function set_cache_class($class = 'SimplePie_Cache')
903 {
904 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
905 {
906 $this->cache_class = $class;
907 return true;
908 }
909 return false;
910 }
911
912 /**
913 * Allows you to change which class SimplePie uses for auto-discovery.
914 * Useful when you are overloading or extending SimplePie's default classes.
915 *
916 * @access public
917 * @param string $class Name of custom class.
918 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
919 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
920 */
921 function set_locator_class($class = 'SimplePie_Locator')
922 {
923 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
924 {
925 $this->locator_class = $class;
926 return true;
927 }
928 return false;
929 }
930
931 /**
932 * Allows you to change which class SimplePie uses for XML parsing.
933 * Useful when you are overloading or extending SimplePie's default classes.
934 *
935 * @access public
936 * @param string $class Name of custom class.
937 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
938 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
939 */
940 function set_parser_class($class = 'SimplePie_Parser')
941 {
942 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
943 {
944 $this->parser_class = $class;
945 return true;
946 }
947 return false;
948 }
949
950 /**
951 * Allows you to change which class SimplePie uses for remote file fetching.
952 * Useful when you are overloading or extending SimplePie's default classes.
953 *
954 * @access public
955 * @param string $class Name of custom class.
956 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
957 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
958 */
959 function set_file_class($class = 'SimplePie_File')
960 {
961 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
962 {
963 $this->file_class = $class;
964 return true;
965 }
966 return false;
967 }
968
969 /**
970 * Allows you to change which class SimplePie uses for data sanitization.
971 * Useful when you are overloading or extending SimplePie's default classes.
972 *
973 * @access public
974 * @param string $class Name of custom class.
975 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
976 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
977 */
978 function set_sanitize_class($class = 'SimplePie_Sanitize')
979 {
980 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
981 {
982 $this->sanitize =& new $class;
983 return true;
984 }
985 return false;
986 }
987
988 /**
989 * Allows you to change which class SimplePie uses for handling feed items.
990 * Useful when you are overloading or extending SimplePie's default classes.
991 *
992 * @access public
993 * @param string $class Name of custom class.
994 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
995 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
996 */
997 function set_item_class($class = 'SimplePie_Item')
998 {
999 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
1000 {
1001 $this->item_class = $class;
1002 return true;
1003 }
1004 return false;
1005 }
1006
1007 /**
1008 * Allows you to change which class SimplePie uses for handling author data.
1009 * Useful when you are overloading or extending SimplePie's default classes.
1010 *
1011 * @access public
1012 * @param string $class Name of custom class.
1013 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1014 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1015 */
1016 function set_author_class($class = 'SimplePie_Author')
1017 {
1018 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
1019 {
1020 $this->author_class = $class;
1021 return true;
1022 }
1023 return false;
1024 }
1025
1026 /**
1027 * Allows you to change which class SimplePie uses for handling category data.
1028 * Useful when you are overloading or extending SimplePie's default classes.
1029 *
1030 * @access public
1031 * @param string $class Name of custom class.
1032 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1033 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1034 */
1035 function set_category_class($class = 'SimplePie_Category')
1036 {
1037 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
1038 {
1039 $this->category_class = $class;
1040 return true;
1041 }
1042 return false;
1043 }
1044
1045 /**
1046 * Allows you to change which class SimplePie uses for feed enclosures.
1047 * Useful when you are overloading or extending SimplePie's default classes.
1048 *
1049 * @access public
1050 * @param string $class Name of custom class.
1051 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1052 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1053 */
1054 function set_enclosure_class($class = 'SimplePie_Enclosure')
1055 {
1056 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
1057 {
1058 $this->enclosure_class = $class;
1059 return true;
1060 }
1061 return false;
1062 }
1063
1064 /**
1065 * Allows you to change which class SimplePie uses for <media:text> captions
1066 * Useful when you are overloading or extending SimplePie's default classes.
1067 *
1068 * @access public
1069 * @param string $class Name of custom class.
1070 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1071 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1072 */
1073 function set_caption_class($class = 'SimplePie_Caption')
1074 {
1075 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
1076 {
1077 $this->caption_class = $class;
1078 return true;
1079 }
1080 return false;
1081 }
1082
1083 /**
1084 * Allows you to change which class SimplePie uses for <media:copyright>
1085 * Useful when you are overloading or extending SimplePie's default classes.
1086 *
1087 * @access public
1088 * @param string $class Name of custom class.
1089 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1090 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1091 */
1092 function set_copyright_class($class = 'SimplePie_Copyright')
1093 {
1094 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
1095 {
1096 $this->copyright_class = $class;
1097 return true;
1098 }
1099 return false;
1100 }
1101
1102 /**
1103 * Allows you to change which class SimplePie uses for <media:credit>
1104 * Useful when you are overloading or extending SimplePie's default classes.
1105 *
1106 * @access public
1107 * @param string $class Name of custom class.
1108 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1109 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1110 */
1111 function set_credit_class($class = 'SimplePie_Credit')
1112 {
1113 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
1114 {
1115 $this->credit_class = $class;
1116 return true;
1117 }
1118 return false;
1119 }
1120
1121 /**
1122 * Allows you to change which class SimplePie uses for <media:rating>
1123 * Useful when you are overloading or extending SimplePie's default classes.
1124 *
1125 * @access public
1126 * @param string $class Name of custom class.
1127 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1128 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1129 */
1130 function set_rating_class($class = 'SimplePie_Rating')
1131 {
1132 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
1133 {
1134 $this->rating_class = $class;
1135 return true;
1136 }
1137 return false;
1138 }
1139
1140 /**
1141 * Allows you to change which class SimplePie uses for <media:restriction>
1142 * Useful when you are overloading or extending SimplePie's default classes.
1143 *
1144 * @access public
1145 * @param string $class Name of custom class.
1146 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1147 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1148 */
1149 function set_restriction_class($class = 'SimplePie_Restriction')
1150 {
1151 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
1152 {
1153 $this->restriction_class = $class;
1154 return true;
1155 }
1156 return false;
1157 }
1158
1159 /**
1160 * Allows you to override the default user agent string.
1161 *
1162 * @access public
1163 * @param string $ua New user agent string.
1164 */
1165 function set_useragent($ua = SIMPLEPIE_USERAGENT)
1166 {
1167 $this->useragent = (string) $ua;
1168 }
1169
1170 /**
1171 * Set callback function to create cache filename with
1172 *
1173 * @access public
1174 * @param mixed $function Callback function
1175 */
1176 function set_cache_name_function($function = 'md5')
1177 {
1178 if (is_callable($function))
1179 {
1180 $this->cache_name_function = $function;
1181 }
1182 }
1183
1184 /**
1185 * Set javascript query string parameter
1186 *
1187 * @access public
1188 * @param mixed $get Javascript query string parameter
1189 */
1190 function set_javascript($get = 'js')
1191 {
1192 if ($get)
1193 {
1194 $this->javascript = (string) $get;
1195 }
1196 else
1197 {
1198 $this->javascript = false;
1199 }
1200 }
1201
1202 /**
1203 * Set options to make SP as fast as possible. Forgoes a
1204 * substantial amount of data sanitization in favor of speed.
1205 *
1206 * @access public
1207 * @param bool $set Whether to set them or not
1208 */
1209 function set_stupidly_fast($set = false)
1210 {
1211 if ($set)
1212 {
1213 $this->enable_order_by_date(false);
1214 $this->remove_div(false);
1215 $this->strip_comments(false);
1216 $this->strip_htmltags(false);
1217 $this->strip_attributes(false);
1218 $this->set_image_handler(false);
1219 }
1220 }
1221
1222 /**
1223 * Set maximum number of feeds to check with autodiscovery
1224 *
1225 * @access public
1226 * @param int $max Maximum number of feeds to check
1227 */
1228 function set_max_checked_feeds($max = 10)
1229 {
1230 $this->max_checked_feeds = (int) $max;
1231 }
1232
1233 function remove_div($enable = true)
1234 {
1235 $this->sanitize->remove_div($enable);
1236 }
1237
1238 function strip_htmltags($tags = '', $encode = null)
1239 {
1240 if ($tags === '')
1241 {
1242 $tags = $this->strip_htmltags;
1243 }
1244 $this->sanitize->strip_htmltags($tags);
1245 if ($encode !== null)
1246 {
1247 $this->sanitize->encode_instead_of_strip($tags);
1248 }
1249 }
1250
1251 function encode_instead_of_strip($enable = true)
1252 {
1253 $this->sanitize->encode_instead_of_strip($enable);
1254 }
1255
1256 function strip_attributes($attribs = '')
1257 {
1258 if ($attribs === '')
1259 {
1260 $attribs = $this->strip_attributes;
1261 }
1262 $this->sanitize->strip_attributes($attribs);
1263 }
1264
1265 function set_output_encoding($encoding = 'UTF-8')
1266 {
1267 $this->sanitize->set_output_encoding($encoding);
1268 }
1269
1270 function strip_comments($strip = false)
1271 {
1272 $this->sanitize->strip_comments($strip);
1273 }
1274
1275 /**
1276 * Set element/attribute key/value pairs of HTML attributes
1277 * containing URLs that need to be resolved relative to the feed
1278 *
1279 * @access public
1280 * @since 1.0
1281 * @param array $element_attribute Element/attribute key/value pairs
1282 */
1283 function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
1284 {
1285 $this->sanitize->set_url_replacements($element_attribute);
1286 }
1287
1288 /**
1289 * Set the handler to enable the display of cached favicons.
1290 *
1291 * @access public
1292 * @param str $page Web-accessible path to the handler_favicon.php file.
1293 * @param str $qs The query string that the value should be passed to.
1294 */
1295 function set_favicon_handler($page = false, $qs = 'i')
1296 {
1297 if ($page != false)
1298 {
1299 $this->favicon_handler = $page . '?' . $qs . '=';
1300 }
1301 else
1302 {
1303 $this->favicon_handler = '';
1304 }
1305 }
1306
1307 /**
1308 * Set the handler to enable the display of cached images.
1309 *
1310 * @access public
1311 * @param str $page Web-accessible path to the handler_image.php file.
1312 * @param str $qs The query string that the value should be passed to.
1313 */
1314 function set_image_handler($page = false, $qs = 'i')
1315 {
1316 if ($page != false)
1317 {
1318 $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1319 }
1320 else
1321 {
1322 $this->image_handler = '';
1323 }
1324 }
1325
1326 function init()
1327 {
1328 if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.1.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
1329 {
1330 return false;
1331 }
1332 if (isset($_GET[$this->javascript]))
1333 {
1334 if (function_exists('ob_gzhandler'))
1335 {
1336 ob_start('ob_gzhandler');
1337 }
1338 header('Content-type: text/javascript; charset: UTF-8');
1339 header('Cache-Control: must-revalidate');
1340 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
1341 ?>
1342 function embed_odeo(link) {
1343 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>');
1344 }
1345
1346 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
1347 if (placeholder != '') {
1348 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>');
1349 }
1350 else {
1351 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>');
1352 }
1353 }
1354
1355 function embed_flash(bgcolor, width, height, link, loop, type) {
1356 document.writeln('<embed src="'+link+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="'+type+'" quality="high" width="'+width+'" height="'+height+'" bgcolor="'+bgcolor+'" loop="'+loop+'"></embed>');
1357 }
1358
1359 function embed_flv(width, height, link, placeholder, loop, player) {
1360 document.writeln('<embed src="'+player+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="'+width+'" height="'+height+'" wmode="transparent" flashvars="file='+link+'&autostart=false&repeat='+loop+'&showdigits=true&showfsbutton=false"></embed>');
1361 }
1362
1363 function embed_wmedia(width, height, link) {
1364 document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
1365 }
1366 <?php
1367 exit;
1368 }
1369
1370 // Pass whatever was set with config options over to the sanitizer.
1371 $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
1372 $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
1373
1374 if ($this->feed_url !== null || $this->raw_data !== null)
1375 {
1376 $this->data = array();
1377 $this->multifeed_objects = array();
1378 $cache = false;
1379
1380 if ($this->feed_url !== null)
1381 {
1382 $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
1383 // Decide whether to enable caching
1384 if ($this->cache && $parsed_feed_url['scheme'] !== '')
1385 {
1386 $cache =& new $this->cache_class($this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
1387 }
1388 // If it's enabled and we don't want an XML dump, use the cache
1389 if ($cache && !$this->xml_dump)
1390 {
1391 // Load the Cache
1392 $this->data = $cache->load();
1393 if (!empty($this->data))
1394 {
1395 // If the cache is for an outdated build of SimplePie
1396 if (!isset($this->data['build']) || $this->data['build'] != SIMPLEPIE_BUILD)
1397 {
1398 $cache->unlink();
1399 $this->data = array();
1400 }
1401 // If we've hit a collision just rerun it with caching disabled
1402 elseif (isset($this->data['url']) && $this->data['url'] != $this->feed_url)
1403 {
1404 $cache = false;
1405 $this->data = array();
1406 }
1407 // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1408 elseif (isset($this->data['feed_url']))
1409 {
1410 // If the autodiscovery cache is still valid use it.
1411 if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1412 {
1413 // Do not need to do feed autodiscovery yet.
1414 if ($this->data['feed_url'] == $this->data['url'])
1415 {
1416 $cache->unlink();
1417 $this->data = array();
1418 }
1419 else
1420 {
1421 $this->set_feed_url($this->data['feed_url']);
1422 return $this->init();
1423 }
1424 }
1425 }
1426 // Check if the cache has been updated
1427 elseif ($cache->mtime() + $this->cache_duration < time())
1428 {
1429 // If we have last-modified and/or etag set
1430 if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1431 {
1432 $headers = array();
1433 if (isset($this->data['headers']['last-modified']))
1434 {
1435 $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1436 }
1437 if (isset($this->data['headers']['etag']))
1438 {
1439 $headers['if-none-match'] = $this->data['headers']['etag'];
1440 }
1441 $file =& new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
1442 if ($file->success)
1443 {
1444 if ($file->status_code == 304)
1445 {
1446 $cache->touch();
1447 return true;
1448 }
1449 else
1450 {
1451 $headers = $file->headers;
1452 }
1453 }
1454 else
1455 {
1456 unset($file);
1457 }
1458 }
1459 }
1460 // If the cache is still valid, just return true
1461 else
1462 {
1463 return true;
1464 }
1465 }
1466 // If the cache is empty, delete it
1467 else
1468 {
1469 $cache->unlink();
1470 $this->data = array();
1471 }
1472 }
1473 // 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.
1474 if (!isset($file))
1475 {
1476 if (SimplePie_Misc::is_a($this->file, 'SimplePie_File') && $this->file->url == $this->feed_url)
1477 {
1478 $file =& $this->file;
1479 }
1480 else
1481 {
1482 $file =& new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
1483 }
1484 }
1485 // If the file connection has an error, set SimplePie::error to that and quit
1486 if (!$file->success)
1487 {
1488 $this->error = $file->error;
1489 if (!empty($this->data))
1490 {
1491 return true;
1492 }
1493 else
1494 {
1495 return false;
1496 }
1497 }
1498
1499 // Check if the supplied URL is a feed, if it isn't, look for it.
1500 $locate =& new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds);
1501 if (!$locate->is_feed($file))
1502 {
1503 // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1504 unset($file);
1505 if ($file = $locate->find($this->autodiscovery))
1506 {
1507 if ($cache)
1508 {
1509 if (!$cache->save(array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD)))
1510 {
1511 trigger_error("$cache->name is not writeable", E_USER_WARNING);
1512 }
1513 $cache =& new $this->cache_class($this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
1514 }
1515 $this->feed_url = $file->url;
1516 }
1517 else
1518 {
1519 $this->error = "A feed could not be found at $this->feed_url";
1520 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1521 return false;
1522 }
1523 }
1524 $locate = null;
1525
1526 $headers = $file->headers;
1527 $data = trim($file->body);
1528 unset($file);
1529 }
1530 else
1531 {
1532 $data = $this->raw_data;
1533 }
1534
1535 // First check to see if input has been overridden.
1536 if ($this->input_encoding !== false)
1537 {
1538 $encoding = $this->input_encoding;
1539 }
1540 // Second try HTTP headers
1541 elseif (isset($headers['content-type']) && preg_match('/;[\x09\x20]*charset=([^;]*)/i', $headers['content-type'], $charset))
1542 {
1543 $encoding = $charset[1];
1544 }
1545 // Then prolog, if at the very start of the document
1546 elseif (preg_match("/^<\?xml[\x20\x9\xD\xA]+version([\x20\x9\xD\xA]+)?=([\x20\x9\xD\xA]+)?(\"1.0\"|'1.0'|\"1.1\"|'1.1')[\x20\x9\xD\xA]+encoding([\x20\x9\xD\xA]+)?=([\x20\x9\xD\xA]+)?(\"[A-Za-z][A-Za-z0-9._\-]*\"|'[A-Za-z][A-Za-z0-9._\-]*')([\x20\x9\xD\xA]+standalone([\x20\x9\xD\xA]+)?=([\x20\x9\xD\xA]+)?(\"(yes|no)\"|'(yes|no)'))?([\x20\x9\xD\xA]+)?\?>/", $data, $prolog))
1547 {
1548 $encoding = substr($prolog[6], 1, -1);
1549 }
1550 // UTF-32 Big Endian BOM
1551 elseif (strpos($data, "\x0\x0\xFE\xFF") === 0)
1552 {
1553 $encoding = 'UTF-32be';
1554 }
1555 // UTF-32 Little Endian BOM
1556 elseif (strpos($data, "\xFF\xFE\x0\x0") === 0)
1557 {
1558 $encoding = 'UTF-32';
1559 }
1560 // UTF-16 Big Endian BOM
1561 elseif (strpos($data, "\xFE\xFF") === 0)
1562 {
1563 $encoding = 'UTF-16be';
1564 }
1565 // UTF-16 Little Endian BOM
1566 elseif (strpos($data, "\xFF\xFE") === 0)
1567 {
1568 $encoding = 'UTF-16le';
1569 }
1570 // UTF-8 BOM
1571 elseif (strpos($data, "\xEF\xBB\xBF") === 0)
1572 {
1573 $encoding = 'UTF-8';
1574 }
1575 // Fallback to the default (US-ASCII for text/xml, ISO-8859-1 for text/* MIME types, UTF-8 otherwise)
1576 elseif (isset($headers['content-type']) && strtolower(SimplePie_Misc::parse_mime($headers['content-type'])) == 'text/xml')
1577 {
1578 $encoding = 'US-ASCII';
1579 }
1580 elseif (isset($headers['content-type']) && SimplePie_Misc::stripos(SimplePie_Misc::parse_mime($headers['content-type']), 'text/') === 0)
1581 {
1582 $encoding = 'ISO-8859-1';
1583 }
1584 else
1585 {
1586 $encoding = 'UTF-8';
1587 }
1588
1589 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1590 if ($encoding != 'UTF-8')
1591 {
1592 $data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8');
1593 }
1594
1595 // Strip illegal characters
1596 $data = SimplePie_Misc::utf8_bad_replace($data);
1597
1598 $parser =& new $this->parser_class();
1599 $parser->pre_process($data, 'UTF-8');
1600 // If we want the XML, just output that and quit
1601 if ($this->xml_dump)
1602 {
1603 header('Content-type: text/xml; charset=UTF-8');
1604 echo $data;
1605 exit;
1606 }
1607 // If it's parsed fine
1608 elseif ($parser->parse($data))
1609 {
1610 unset($data);
1611 $this->data = $parser->get_data();
1612 if (isset($this->data['child']))
1613 {
1614 if (isset($headers))
1615 {
1616 $this->data['headers'] = $headers;
1617 }
1618 $this->data['build'] = SIMPLEPIE_BUILD;
1619
1620 // Cache the file if caching is enabled
1621 if ($cache && !$cache->save($this->data))
1622 {
1623 trigger_error("$cache->name is not writeable", E_USER_WARNING);
1624 }
1625 return true;
1626 }
1627 else
1628 {
1629 $this->error = "A feed could not be found at $this->feed_url";
1630 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1631 return false;
1632 }
1633 }
1634 // If we have an error, just set SimplePie::error to it and quit
1635 else
1636 {
1637 $this->error = sprintf('XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
1638 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1639 return false;
1640 }
1641 }
1642 elseif (!empty($this->multifeed_url))
1643 {
1644 $i = 0;
1645 $success = 0;
1646 $this->multifeed_objects = array();
1647 foreach ($this->multifeed_url as $url)
1648 {
1649 if (SIMPLEPIE_PHP5)
1650 {
1651 // This keyword needs to defy coding standards for PHP4 compatibility
1652 $this->multifeed_objects[$i] = clone($this);
1653 }
1654 else
1655 {
1656 $this->multifeed_objects[$i] = $this;
1657 }
1658 $this->multifeed_objects[$i]->set_feed_url($url);
1659 $success |= $this->multifeed_objects[$i]->init();
1660 $i++;
1661 }
1662 return (bool) $success;
1663 }
1664 else
1665 {
1666 return false;
1667 }
1668 }
1669
1670 /**
1671 * Return the error message for the occured error
1672 *
1673 * @access public
1674 * @return string Error message
1675 */
1676 function error()
1677 {
1678 return $this->error;
1679 }
1680
1681 function get_encoding()
1682 {
1683 return $this->sanitize->output_encoding;
1684 }
1685
1686 function handle_content_type($mime = 'text/html')
1687 {
1688 if (!headers_sent())
1689 {
1690 $header = "Content-type: $mime;";
1691 if ($this->get_encoding())
1692 {
1693 $header .= ' charset=' . $this->get_encoding();
1694 }
1695 else
1696 {
1697 $header .= ' charset=UTF-8';
1698 }
1699 header($header);
1700 }
1701 }
1702
1703 function get_type()
1704 {
1705 if (!isset($this->data['type']))
1706 {
1707 $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1708 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1709 {
1710 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1711 }
1712 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1713 {
1714 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1715 }
1716 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1717 {
1718 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1719 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1720 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1721 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1722 {
1723 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1724 }
1725 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1726 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1727 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1728 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1729 {
1730 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1731 }
1732 }
1733 elseif (isset($this->data['child']['']['rss']))
1734 {
1735 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1736 if (isset($this->data['child']['']['rss'][0]['attribs']['']['version']))
1737 {
1738 switch (trim($this->data['child']['']['rss'][0]['attribs']['']['version']))
1739 {
1740 case '0.91':
1741 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1742 if (isset($this->data['child']['']['rss'][0]['child']['']['skiphours']['hour'][0]['data']))
1743 {
1744 switch (trim($this->data['child']['']['rss'][0]['child']['']['skiphours']['hour'][0]['data']))
1745 {
1746 case '0':
1747 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1748 break;
1749
1750 case '24':
1751 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1752 break;
1753 }
1754 }
1755 break;
1756
1757 case '0.92':
1758 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1759 break;
1760
1761 case '0.93':
1762 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1763 break;
1764
1765 case '0.94':
1766 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1767 break;
1768
1769 case '2.0':
1770 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1771 break;
1772 }
1773 }
1774 }
1775 else
1776 {
1777 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1778 }
1779 }
1780 return $this->data['type'];
1781 }
1782
1783 /**
1784 * Returns the URL for the favicon of the feed's website.
1785 *
1786 * @access public
1787 * @since 1.0
1788 */
1789 function get_favicon()
1790 {
1791 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
1792 {
1793 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
1794 }
1795 elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
1796 {
1797 $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
1798
1799 if ($this->cache && $this->favicon_handler)
1800 {
1801 $cache =& new $this->cache_class($this->cache_location, call_user_func($this->cache_name_function, $favicon), 'spi');
1802
1803 if ($cache->load())
1804 {
1805 return $this->sanitize($this->favicon_handler . rawurlencode($favicon), SIMPLEPIE_CONSTRUCT_IRI);
1806 }
1807 else
1808 {
1809 $file =& new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
1810
1811 if ($file->success && ($file->status_code == 200 || ($file->status_code > 206 && $file->status_code < 300)) && strlen($file->body) > 0)
1812 {
1813 if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
1814 {
1815 return $this->sanitize($this->favicon_handler . rawurlencode($favicon), SIMPLEPIE_CONSTRUCT_IRI);
1816 }
1817 else
1818 {
1819 trigger_error("$cache->name is not writeable", E_USER_WARNING);
1820 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
1821 }
1822 }
1823 }
1824 }
1825 else
1826 {
1827 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
1828 }
1829 }
1830 return false;
1831 }
1832
1833 /**
1834 * @todo If we have a perm redirect we should return the new URL
1835 * @todo When we make the above change, let's support <itunes:new-feed-url> as well
1836 * @todo Also, |atom:link|@rel=self
1837 */
1838 function subscribe_url()
1839 {
1840 if ($this->feed_url !== null)
1841 {
1842 return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
1843 }
1844 else
1845 {
1846 return null;
1847 }
1848 }
1849
1850 function subscribe_feed()
1851 {
1852 if ($this->feed_url !== null)
1853 {
1854 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
1855 }
1856 else
1857 {
1858 return null;
1859 }
1860 }
1861
1862 function subscribe_outlook()
1863 {
1864 if ($this->feed_url !== null)
1865 {
1866 return 'outlook' . $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
1867 }
1868 else
1869 {
1870 return null;
1871 }
1872 }
1873
1874 function subscribe_podcast()
1875 {
1876 if ($this->feed_url !== null)
1877 {
1878 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
1879 }
1880 else
1881 {
1882 return null;
1883 }
1884 }
1885
1886 function subscribe_itunes()
1887 {
1888 if ($this->feed_url !== null)
1889 {
1890 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
1891 }
1892 else
1893 {
1894 return null;
1895 }
1896 }
1897
1898 /**
1899 * Creates the subscribe_* methods' return data
1900 *
1901 * @access private
1902 * @param string $feed_url String to prefix to the feed URL
1903 * @param string $site_url String to prefix to the site URL (and
1904 * suffix to the feed URL)
1905 * @return mixed URL if feed exists, false otherwise
1906 */
1907 function subscribe_service($feed_url, $site_url = null)
1908 {
1909 if ($this->subscribe_url())
1910 {
1911 $return = $this->sanitize($feed_url, SIMPLEPIE_CONSTRUCT_IRI) . rawurlencode($this->subscribe_url());
1912 if ($site_url !== null && $this->get_link() !== null)
1913 {
1914 $return .= $this->sanitize($site_url, SIMPLEPIE_CONSTRUCT_IRI) . rawurlencode($this->get_link());
1915 }
1916 return $return;
1917 }
1918 else
1919 {
1920 return null;
1921 }
1922 }
1923
1924 function subscribe_aol()
1925 {
1926 return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
1927 }
1928
1929 function subscribe_bloglines()
1930 {
1931 return urldecode($this->subscribe_service('http://www.bloglines.com/sub/'));
1932 }
1933
1934 function subscribe_eskobo()
1935 {
1936 return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
1937 }
1938
1939 function subscribe_feedfeeds()
1940 {
1941 return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
1942 }
1943
1944 function subscribe_feedster()
1945 {
1946 return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
1947 }
1948
1949 function subscribe_google()
1950 {
1951 return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
1952 }
1953
1954 function subscribe_gritwire()
1955 {
1956 return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
1957 }
1958
1959 function subscribe_msn()
1960 {
1961 return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
1962 }
1963
1964 function subscribe_netvibes()
1965 {
1966 return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
1967 }
1968
1969 function subscribe_newsburst()
1970 {
1971 return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
1972 }
1973
1974 function subscribe_newsgator()
1975 {
1976 return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
1977 }
1978
1979 function subscribe_odeo()
1980 {
1981 return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
1982 }
1983
1984 function subscribe_podnova()
1985 {
1986 return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
1987 }
1988
1989 function subscribe_rojo()
1990 {
1991 return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
1992 }
1993
1994 function subscribe_yahoo()
1995 {
1996 return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
1997 }
1998
1999 function get_feed_tags($namespace, $tag)
2000 {
2001 $type = $this->get_type();
2002 if ($type & SIMPLEPIE_TYPE_ATOM_10)
2003 {
2004 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
2005 {
2006 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
2007 }
2008 }
2009 if ($type & SIMPLEPIE_TYPE_ATOM_03)
2010 {
2011 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
2012 {
2013 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
2014 }
2015 }
2016 if ($type & SIMPLEPIE_TYPE_RSS_RDF)
2017 {
2018 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
2019 {
2020 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
2021 }
2022 }
2023 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2024 {
2025 if (isset($this->data['child']['']['rss'][0]['child'][$namespace][$tag]))
2026 {
2027 return $this->data['child']['']['rss'][0]['child'][$namespace][$tag];
2028 }
2029 }
2030 return null;
2031 }
2032
2033 function get_channel_tags($namespace, $tag)
2034 {
2035 $type = $this->get_type();
2036 if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
2037 {
2038 if ($return = $this->get_feed_tags($namespace, $tag))
2039 {
2040 return $return;
2041 }
2042 }
2043 if ($type & SIMPLEPIE_TYPE_RSS_10)
2044 {
2045 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
2046 {
2047 if (isset($channel[0]['child'][$namespace][$tag]))
2048 {
2049 return $channel[0]['child'][$namespace][$tag];
2050 }
2051 }
2052 }
2053 if ($type & SIMPLEPIE_TYPE_RSS_090)
2054 {
2055 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
2056 {
2057 if (isset($channel[0]['child'][$namespace][$tag]))
2058 {
2059 return $channel[0]['child'][$namespace][$tag];
2060 }
2061 }
2062 }
2063 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2064 {
2065 if ($channel = $this->get_feed_tags('', 'channel'))
2066 {
2067 if (isset($channel[0]['child'][$namespace][$tag]))
2068 {
2069 return $channel[0]['child'][$namespace][$tag];
2070 }
2071 }
2072 }
2073 return null;
2074 }
2075
2076 function get_image_tags($namespace, $tag)
2077 {
2078 $type = $this->get_type();
2079 if ($type & SIMPLEPIE_TYPE_RSS_10)
2080 {
2081 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
2082 {
2083 if (isset($image[0]['child'][$namespace][$tag]))
2084 {
2085 return $image[0]['child'][$namespace][$tag];
2086 }
2087 }
2088 }
2089 if ($type & SIMPLEPIE_TYPE_RSS_090)
2090 {
2091 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2092 {
2093 if (isset($image[0]['child'][$namespace][$tag]))
2094 {
2095 return $image[0]['child'][$namespace][$tag];
2096 }
2097 }
2098 }
2099 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2100 {
2101 if ($image = $this->get_channel_tags('', 'image'))
2102 {
2103 if (isset($image[0]['child'][$namespace][$tag]))
2104 {
2105 return $image[0]['child'][$namespace][$tag];
2106 }
2107 }
2108 }
2109 return null;
2110 }
2111
2112 function get_base($element = array())
2113 {
2114 if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2115 {
2116 return $element['xml_base'];
2117 }
2118 elseif ($this->get_link() !== null)
2119 {
2120 return $this->get_link();
2121 }
2122 elseif (isset($this->data['headers']['content-location']))
2123 {
2124 return SimplePie_Misc::absolutize_url($this->data['headers']['content-location'], $this->subscribe_url());
2125 }
2126 else
2127 {
2128 return $this->subscribe_url();
2129 }
2130 }
2131
2132 function sanitize($data, $type, $base = '')
2133 {
2134 return $this->sanitize->sanitize($data, $type, $base);
2135 }
2136
2137 function get_title()
2138 {
2139 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2140 {
2141 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2142 }
2143 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2144 {
2145 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2146 }
2147 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2148 {
2149 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2150 }
2151 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2152 {
2153 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2154 }
2155 elseif ($return = $this->get_channel_tags('', 'title'))
2156 {
2157 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2158 }
2159 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2160 {
2161 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2162 }
2163 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2164 {
2165 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2166 }
2167 else
2168 {
2169 return null;
2170 }
2171 }
2172
2173 function get_link($key = 0, $rel = 'alternate')
2174 {
2175 $links = $this->get_links($rel);
2176 if (isset($links[$key]))
2177 {
2178 return $links[$key];
2179 }
2180 else
2181 {
2182 return null;
2183 }
2184 }
2185
2186 /**
2187 * Added for parity between the parent-level and the item/entry-level.
2188 */
2189 function get_permalink()
2190 {
2191 return $this->get_link(0);
2192 }
2193
2194 function get_links($rel = 'alternate')
2195 {
2196 if (!isset($this->data['links']))
2197 {
2198 $this->data['links'] = array();
2199 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2200 {
2201 foreach ($links as $link)
2202 {
2203 if (isset($link['attribs']['']['href']))
2204 {
2205 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2206 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2207 }
2208 }
2209 }
2210 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2211 {
2212 foreach ($links as $link)
2213 {
2214 if (isset($link['attribs']['']['href']))
2215 {
2216 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2217 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2218
2219 }
2220 }
2221 }
2222 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2223 {
2224 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2225 }
2226 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2227 {
2228 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2229 }
2230 if ($links = $this->get_channel_tags('', 'link'))
2231 {
2232 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2233 }
2234
2235 $keys = array_keys($this->data['links']);
2236 foreach ($keys as $key)
2237 {
2238 if (SimplePie_Misc::is_isegment_nz_nc($key))
2239 {
2240 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2241 {
2242 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2243 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2244 }
2245 else
2246 {
2247 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2248 }
2249 }
2250 elseif (substr($key, 0, 41) == SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2251 {
2252 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2253 }
2254 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2255 }
2256 }
2257
2258 if (isset($this->data['links'][$rel]))
2259 {
2260 return $this->data['links'][$rel];
2261 }
2262 else
2263 {
2264 return null;
2265 }
2266 }
2267
2268 function get_description()
2269 {
2270 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2271 {
2272 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2273 }
2274 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2275 {
2276 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2277 }
2278 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2279 {
2280 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2281 }
2282 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2283 {
2284 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2285 }
2286 elseif ($return = $this->get_channel_tags('', 'description'))
2287 {
2288 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2289 }
2290 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2291 {
2292 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2293 }
2294 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2295 {
2296 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2297 }
2298 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2299 {
2300 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2301 }
2302 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2303 {
2304 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2305 }
2306 else
2307 {
2308 return null;
2309 }
2310 }
2311
2312 function get_copyright()
2313 {
2314 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2315 {
2316 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2317 }
2318 elseif ($return = $this->get_channel_tags('', 'copyright'))
2319 {
2320 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2321 }
2322 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2323 {
2324 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2325 }
2326 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2327 {
2328 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2329 }
2330 else
2331 {
2332 return null;
2333 }
2334 }
2335
2336 function get_language()
2337 {
2338 if ($return = $this->get_channel_tags('', 'language'))
2339 {
2340 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2341 }
2342 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2343 {
2344 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2345 }
2346 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2347 {
2348 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2349 }
2350 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2351 {
2352 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2353 }
2354 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2355 {
2356 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2357 }
2358 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2359 {
2360 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2361 }
2362 elseif (isset($this->data['headers']['content-language']))
2363 {
2364 return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2365 }
2366 else
2367 {
2368 return null;
2369 }
2370 }
2371
2372 function get_latitude()
2373 {
2374 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2375 {
2376 return (float) $return[0]['data'];
2377 }
2378 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
2379 {
2380 return (float) $match[1];
2381 }
2382 else
2383 {
2384 return null;
2385 }
2386 }
2387
2388 function get_longitude()
2389 {
2390 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2391 {
2392 return (float) $return[0]['data'];
2393 }
2394 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2395 {
2396 return (float) $return[0]['data'];
2397 }
2398 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
2399 {
2400 return (float) $match[2];
2401 }
2402 else
2403 {
2404 return null;
2405 }
2406 }
2407
2408 function get_image_title()
2409 {
2410 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2411 {
2412 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2413 }
2414 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2415 {
2416 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2417 }
2418 elseif ($return = $this->get_image_tags('', 'title'))
2419 {
2420 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2421 }
2422 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2423 {
2424 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2425 }
2426 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2427 {
2428 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2429 }
2430 else
2431 {
2432 return null;
2433 }
2434 }
2435
2436 function get_image_url()
2437 {
2438 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2439 {
2440 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2441 }
2442 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2443 {
2444 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2445 }
2446 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2447 {
2448 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2449 }
2450 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2451 {
2452 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2453 }
2454 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2455 {
2456 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2457 }
2458 elseif ($return = $this->get_image_tags('', 'url'))
2459 {
2460 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2461 }
2462 else
2463 {
2464 return null;
2465 }
2466 }
2467
2468 function get_image_link()
2469 {
2470 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2471 {
2472 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2473 }
2474 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2475 {
2476 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2477 }
2478 elseif ($return = $this->get_image_tags('', 'link'))
2479 {
2480 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2481 }
2482 else
2483 {
2484 return null;
2485 }
2486 }
2487
2488 function get_image_width()
2489 {
2490 if ($return = $this->get_image_tags('', 'width'))
2491 {
2492 return round($return[0]['data']);
2493 }
2494 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags('', 'url'))
2495 {
2496 return 88.0;
2497 }
2498 else
2499 {
2500 return null;
2501 }
2502 }
2503
2504 function get_image_height()
2505 {
2506 if ($return = $this->get_image_tags('', 'height'))
2507 {
2508 return round($return[0]['data']);
2509 }
2510 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags('', 'url'))
2511 {
2512 return 31.0;
2513 }
2514 else
2515 {
2516 return null;
2517 }
2518 }
2519
2520 function get_item_quantity($max = 0)
2521 {
2522 $qty = count($this->get_items());
2523 if ($max == 0)
2524 {
2525 return $qty;
2526 }
2527 else
2528 {
2529 return ($qty > $max) ? $max : $qty;
2530 }
2531 }
2532
2533 function get_item($key = 0)
2534 {
2535 $items = $this->get_items();
2536 if (isset($items[$key]))
2537 {
2538 return $items[$key];
2539 }
2540 else
2541 {
2542 return null;
2543 }
2544 }
2545
2546 function get_items($start = 0, $end = 0)
2547 {
2548 if (!empty($this->multifeed_objects))
2549 {
2550 return SimplePie::merge_items($this->multifeed_objects, $start, $end);
2551 }
2552 elseif (!isset($this->data['items']))
2553 {
2554 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2555 {
2556 $keys = array_keys($items);
2557 foreach ($keys as $key)
2558 {
2559 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2560 }
2561 }
2562 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2563 {
2564 $keys = array_keys($items);
2565 foreach ($keys as $key)
2566 {
2567 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2568 }
2569 }
2570 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
2571 {
2572 $keys = array_keys($items);
2573 foreach ($keys as $key)
2574 {
2575 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2576 }
2577 }
2578 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2579 {
2580 $keys = array_keys($items);
2581 foreach ($keys as $key)
2582 {
2583 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2584 }
2585 }
2586 if ($items = $this->get_channel_tags('', 'item'))
2587 {
2588 $keys = array_keys($items);
2589 foreach ($keys as $key)
2590 {
2591 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2592 }
2593 }
2594 }
2595
2596 if (!empty($this->data['items']))
2597 {
2598 // If we want to order it by date, check if all items have a date, and then sort it
2599 if ($this->order_by_date)
2600 {
2601 if (!isset($this->data['ordered_items']))
2602 {
2603 $do_sort = true;
2604 foreach ($this->data['items'] as $item)
2605 {
2606 if (!$item->get_date('U'))
2607 {
2608 $do_sort = false;
2609 break;
2610 }
2611 }
2612 $item = null;
2613 $this->data['ordered_items'] = $this->data['items'];
2614 if ($do_sort)
2615 {
2616 usort($this->data['ordered_items'], array(&$this, 'sort_items'));
2617 }
2618 }
2619 $items = $this->data['ordered_items'];
2620 }
2621 else
2622 {
2623 $items = $this->data['items'];
2624 }
2625
2626 // Slice the data as desired
2627 if ($end == 0)
2628 {
2629 return array_slice($items, $start);
2630 }
2631 else
2632 {
2633 return array_slice($items, $start, $end);
2634 }
2635 }
2636 else
2637 {
2638 return array();
2639 }
2640 }
2641
2642 function sort_items($a, $b)
2643 {
2644 return $a->get_date('U') <= $b->get_date('U');
2645 }
2646
2647 function merge_items($urls, $start = 0, $end = 0)
2648 {
2649 if (is_array($urls) && sizeof($urls) > 0)
2650 {
2651 $items = array();
2652 foreach ($urls as $arg)
2653 {
2654 if (SimplePie_Misc::is_a($arg, 'SimplePie'))
2655 {
2656 $items = array_merge($items, $arg->get_items());
2657 }
2658 else
2659 {
2660 trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
2661 }
2662 }
2663
2664 $do_sort = true;
2665 foreach ($items as $item)
2666 {
2667 if (!$item->get_date('U'))
2668 {
2669 $do_sort = false;
2670 break;
2671 }
2672 }
2673 $item = null;
2674 if ($do_sort)
2675 {
2676 usort($items, array('SimplePie', 'sort_items'));
2677 }
2678
2679 if ($end == 0)
2680 {
2681 return array_slice($items, $start);
2682 }
2683 else
2684 {
2685 return array_slice($items, $start, $end);
2686 }
2687 }
2688 else
2689 {
2690 trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
2691 return array();
2692 }
2693 }
2694 }
2695
2696 class SimplePie_Item
2697 {
2698 var $feed;
2699 var $data = array();
2700
2701 function SimplePie_Item($feed, $data)
2702 {
2703 $this->feed = $feed;
2704 $this->data = $data;
2705 }
2706
2707 function __toString()
2708 {
2709 return md5(serialize($this->data));
2710 }
2711
2712 function get_item_tags($namespace, $tag)
2713 {
2714 if (isset($this->data['child'][$namespace][$tag]))
2715 {
2716 return $this->data['child'][$namespace][$tag];
2717 }
2718 else
2719 {
2720 return null;
2721 }
2722 }
2723
2724 function get_base($element = array())
2725 {
2726 return $this->feed->get_base($element);
2727 }
2728
2729 function sanitize($data, $type, $base = '')
2730 {
2731 return $this->feed->sanitize($data, $type, $base);
2732 }
2733
2734 function get_feed()
2735 {
2736 return $this->feed;
2737 }
2738
2739 function get_id($hash = false)
2740 {
2741 if ($hash)
2742 {
2743 return $this->__toString();
2744 }
2745 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
2746 {
2747 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2748 }
2749 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
2750 {
2751 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2752 }
2753 elseif ($return = $this->get_item_tags('', 'guid'))
2754 {
2755 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2756 }
2757 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
2758 {
2759 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2760 }
2761 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
2762 {
2763 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2764 }
2765 elseif (($return = $this->get_permalink()) !== null)
2766 {
2767 return $return;
2768 }
2769 elseif (($return = $this->get_title()) !== null)
2770 {
2771 return $return;
2772 }
2773 else
2774 {
2775 return $this->__toString();
2776 }
2777 }
2778
2779 function get_title()
2780 {
2781 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2782 {
2783 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2784 }
2785 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2786 {
2787 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2788 }
2789 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2790 {
2791 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2792 }
2793 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2794 {
2795 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2796 }
2797 elseif ($return = $this->get_item_tags('', 'title'))
2798 {
2799 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2800 }
2801 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2802 {
2803 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2804 }
2805 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2806 {
2807 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2808 }
2809 else
2810 {
2811 return null;
2812 }
2813 }
2814
2815 function get_description($description_only = false)
2816 {
2817 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
2818 {
2819 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2820 }
2821 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
2822 {
2823 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2824 }
2825 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2826 {
2827 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2828 }
2829 elseif ($return = $this->get_item_tags('', 'description'))
2830 {
2831 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2832 }
2833 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2834 {
2835 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2836 }
2837 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2838 {
2839 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2840 }
2841 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2842 {
2843 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2844 }
2845 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2846 {
2847 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2848 }
2849 elseif (!$description_only)
2850 {
2851 return $this->get_content(true);
2852 }
2853 else
2854 {
2855 return null;
2856 }
2857 }
2858
2859 function get_content($content_only = false)
2860 {
2861 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
2862 {
2863 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2864 }
2865 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
2866 {
2867 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2868 }
2869 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
2870 {
2871 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2872 }
2873 elseif (!$content_only)
2874 {
2875 return $this->get_description(true);
2876 }
2877 else
2878 {
2879 return null;
2880 }
2881 }
2882
2883 function get_category($key = 0)
2884 {
2885 $categories = $this->get_categories();
2886 if (isset($categories[$key]))
2887 {
2888 return $categories[$key];
2889 }
2890 else
2891 {
2892 return null;
2893 }
2894 }
2895
2896 function get_categories()
2897 {
2898 $categories = array();
2899
2900 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2901 {
2902 $term = null;
2903 $scheme = null;
2904 $label = null;
2905 if (isset($category['attribs']['']['term']))
2906 {
2907 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2908 }
2909 if (isset($category['attribs']['']['scheme']))
2910 {
2911 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2912 }
2913 if (isset($category['attribs']['']['label']))
2914 {
2915 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2916 }
2917 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
2918 }
2919 foreach ((array) $this->get_item_tags('', 'category') as $category)
2920 {
2921 $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2922 }
2923 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2924 {
2925 $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2926 }
2927 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2928 {
2929 $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2930 }
2931
2932 if (!empty($categories))
2933 {
2934 return SimplePie_Misc::array_unique($categories);
2935 }
2936 else
2937 {
2938 return null;
2939 }
2940 }
2941
2942 function get_author($key = 0)
2943 {
2944 $authors = $this->get_authors();
2945 if (isset($authors[$key]))
2946 {
2947 return $authors[$key];
2948 }
2949 else
2950 {
2951 return null;
2952 }
2953 }
2954
2955 /**
2956 * @todo Atom inheritance (item author, source author, feed author)
2957 */
2958 function get_authors()
2959 {
2960 $authors = array();
2961 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2962 {
2963 $name = null;
2964 $uri = null;
2965 $email = null;
2966 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2967 {
2968 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2969 }
2970 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2971 {
2972 $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
2973 }
2974 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2975 {
2976 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2977 }
2978 if ($name !== null || $email !== null || $uri !== null)
2979 {
2980 $authors[] =& new $this->feed->author_class($name, $uri, $email);
2981 }
2982 }
2983 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2984 {
2985 $name = null;
2986 $url = null;
2987 $email = null;
2988 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2989 {
2990 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2991 }
2992 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2993 {
2994 $uri = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
2995 }
2996 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2997 {
2998 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2999 }
3000 if ($name !== null || $email !== null || $uri !== null)
3001 {
3002 $authors[] =& new $this->feed->author_class($name, $url, $email);
3003 }
3004 }
3005 if ($author = $this->get_item_tags('', 'author'))
3006 {
3007 $authors[] =& new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3008 }
3009 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3010 {
3011 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3012 }
3013 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3014 {
3015 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3016 }
3017 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3018 {
3019 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3020 }
3021
3022 if (!empty($authors))
3023 {
3024 return SimplePie_Misc::array_unique($authors);
3025 }
3026 else
3027 {
3028 return null;
3029 }
3030 }
3031
3032 function get_date($date_format = 'j F Y, g:i a')
3033 {
3034 if (!isset($this->data['date']))
3035 {
3036 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3037 {
3038 $this->data['date']['raw'] = $return[0]['data'];
3039 }
3040 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3041 {
3042 $this->data['date']['raw'] = $return[0]['data'];
3043 }
3044 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3045 {
3046 $this->data['date']['raw'] = $return[0]['data'];
3047 }
3048 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3049 {
3050 $this->data['date']['raw'] = $return[0]['data'];
3051 }
3052 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3053 {
3054 $this->data['date']['raw'] = $return[0]['data'];
3055 }
3056 elseif ($return = $this->get_item_tags('', 'pubDate'))
3057 {
3058 $this->data['date']['raw'] = $return[0]['data'];
3059 }
3060 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3061 {
3062 $this->data['date']['raw'] = $return[0]['data'];
3063 }
3064 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3065 {
3066 $this->data['date']['raw'] = $return[0]['data'];
3067 }
3068
3069 if (!empty($this->data['date']['raw']))
3070 {
3071 $this->data['date']['parsed'] = SimplePie_Misc::parse_date($this->data['date']['raw']);
3072 }
3073 else
3074 {
3075 $this->data['date'] = null;
3076 }
3077 }
3078 if ($this->data['date'])
3079 {
3080 $date_format = (string) $date_format;
3081 switch ($date_format)
3082 {
3083 case '':
3084 return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3085
3086 case 'U':
3087 return $this->data['date']['parsed'];
3088
3089 default:
3090 return date($date_format, $this->data['date']['parsed']);
3091 }
3092 }
3093 else
3094 {
3095 return null;
3096 }
3097 }
3098
3099 function get_local_date($date_format = '%c')
3100 {
3101 if (!$date_format)
3102 {
3103 return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3104 }
3105 elseif (($date = $this->get_date('U')) !== null)
3106 {
3107 return strftime($date_format, $date);
3108 }
3109 else
3110 {
3111 return null;
3112 }
3113 }
3114
3115 function get_permalink()
3116 {
3117 $link = $this->get_link();
3118 $enclosure = $this->get_enclosure(0);
3119 if ($link !== null)
3120 {
3121 return $link;
3122 }
3123 elseif ($enclosure !== null)
3124 {
3125 return $enclosure->get_link();
3126 }
3127 else
3128 {
3129 return null;
3130 }
3131 }
3132
3133 function get_link($key = 0, $rel = 'alternate')
3134 {
3135 $links = $this->get_links($rel);
3136 if ($links[$key] !== null)
3137 {
3138 return $links[$key];
3139 }
3140 else
3141 {
3142 return null;
3143 }
3144 }
3145
3146 function get_links($rel = 'alternate')
3147 {
3148 if (!isset($this->data['links']))
3149 {
3150 $this->data['links'] = array();
3151 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3152 {
3153 if (isset($link['attribs']['']['href']))
3154 {
3155 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3156 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3157
3158 }
3159 }
3160 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3161 {
3162 if (isset($link['attribs']['']['href']))
3163 {
3164 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3165 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3166 }
3167 }
3168 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3169 {
3170 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3171 }
3172 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3173 {
3174 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3175 }
3176 if ($links = $this->get_item_tags('', 'link'))
3177 {
3178 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3179 }
3180 if ($links = $this->get_item_tags('', 'guid'))
3181 {
3182 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) == 'true')
3183 {
3184 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3185 }
3186 }
3187
3188 $keys = array_keys($this->data['links']);
3189 foreach ($keys as $key)
3190 {
3191 if (SimplePie_Misc::is_isegment_nz_nc($key))
3192 {
3193 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3194 {
3195 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3196 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3197 }
3198 else
3199 {
3200 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3201 }
3202 }
3203 elseif (substr($key, 0, 41) == SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
3204 {
3205 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3206 }
3207 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3208 }
3209 }
3210 if (isset($this->data['links'][$rel]))
3211 {
3212 return $this->data['links'][$rel];
3213 }
3214 else
3215 {
3216 return null;
3217 }
3218 }
3219
3220 /**
3221 * @todo Add ability to prefer one type of content over another (in a media group).
3222 */
3223 function get_enclosure($key = 0, $prefer = null)
3224 {
3225 $enclosures = $this->get_enclosures();
3226 if (isset($enclosures[$key]))
3227 {
3228 return $enclosures[$key];
3229 }
3230 else
3231 {
3232 return null;
3233 }
3234 }
3235
3236 /**
3237 * Grabs all available enclosures (podcasts, etc.)
3238 *
3239 * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3240 *
3241 * At this point, we're pretty much assuming that all enclosures for an item are the same content. Anything else is too complicated to properly support.
3242 *
3243 * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3244 * @todo Add support for itunes: tags. These should be relatively simple compared to media:.
3245 * @todo If an element exists at a level, but it's value is empty, we should fall back to the value from the parent (if it exists).
3246 */
3247 function get_enclosures()
3248 {
3249 if (!isset($this->data['enclosures']))
3250 {
3251 $this->data['enclosures'] = array();
3252
3253 // Elements
3254 $captions_parent = null;
3255 $categories_parent = null;
3256 $copyrights_parent = null;
3257 $credits_parent = null;
3258 $description_parent = null;
3259 $duration_parent = null;
3260 $hashes_parent = null;
3261 $keywords_parent = null;
3262 $player_parent = null;
3263 $ratings_parent = null;
3264 $restrictions_parent = null;
3265 $thumbnails_parent = null;
3266 $title_parent = null;
3267
3268 // Let's do the channel and item-level ones first, and just re-use them if we need to.
3269 $parent = $this->get_feed();
3270
3271 // CAPTIONS
3272 if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3273 {
3274 foreach ($captions as $caption)
3275 {
3276 $caption_type = null;
3277 $caption_lang = null;
3278 $caption_startTime = null;
3279 $caption_endTime = null;
3280 $caption_text = null;
3281 if (isset($caption['attribs']['']['type']))
3282 {
3283 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3284 }
3285 if (isset($caption['attribs']['']['lang']))
3286 {
3287 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3288 }
3289 if (isset($caption['attribs']['']['start']))
3290 {
3291 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3292 }
3293 if (isset($caption['attribs']['']['end']))
3294 {
3295 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3296 }
3297 if (isset($caption['data']))
3298 {
3299 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3300 }
3301 $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3302 }
3303 }
3304 elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3305 {
3306 foreach ($captions as $caption)
3307 {
3308 $caption_type = null;
3309 $caption_lang = null;
3310 $caption_startTime = null;
3311 $caption_endTime = null;
3312 $caption_text = null;
3313 if (isset($caption['attribs']['']['type']))
3314 {
3315 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3316 }
3317 if (isset($caption['attribs']['']['lang']))
3318 {
3319 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3320 }
3321 if (isset($caption['attribs']['']['start']))
3322 {
3323 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3324 }
3325 if (isset($caption['attribs']['']['end']))
3326 {
3327 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3328 }
3329 if (isset($caption['data']))
3330 {
3331 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3332 }
3333 $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3334 }
3335 }
3336 if (is_array($captions_parent))
3337 {
3338 $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
3339 }
3340
3341 // CATEGORIES
3342 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3343 {
3344 $term = null;
3345 $scheme = null;
3346 $label = null;
3347 if (isset($category['data']))
3348 {
3349 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3350 }
3351 if (isset($category['attribs']['']['scheme']))
3352 {
3353 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3354 }
3355 else
3356 {
3357 $scheme = 'http://search.yahoo.com/mrss/category_schema';
3358 }
3359 if (isset($category['attribs']['']['label']))
3360 {
3361 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3362 }
3363 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3364 }
3365 foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3366 {
3367 $term = null;
3368 $scheme = null;
3369 $label = null;
3370 if (isset($category['data']))
3371 {
3372 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3373 }
3374 if (isset($category['attribs']['']['scheme']))
3375 {
3376 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3377 }
3378 else
3379 {
3380 $scheme = 'http://search.yahoo.com/mrss/category_schema';
3381 }
3382 if (isset($category['attribs']['']['label']))
3383 {
3384 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3385 }
3386 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3387 }
3388 foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
3389 {
3390 $term = null;
3391 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
3392 $label = null;
3393 if (isset($category['attribs']['']['text']))
3394 {
3395 $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3396 }
3397 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3398
3399 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
3400 {
3401 foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
3402 {
3403 if (isset($subcategory['attribs']['']['text']))
3404 {
3405 $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3406 }
3407 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3408 }
3409 }
3410 }
3411 if (is_array($categories_parent))
3412 {
3413 $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
3414 }
3415
3416 // COPYRIGHT
3417 if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3418 {
3419 $copyright_url = null;
3420 $copyright_label = null;
3421 if (isset($copyright[0]['attribs']['']['url']))
3422 {
3423 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3424 }
3425 if (isset($copyright[0]['data']))
3426 {
3427 $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3428 }
3429 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3430 }
3431 elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3432 {
3433 $copyright_url = null;
3434 $copyright_label = null;
3435 if (isset($copyright[0]['attribs']['']['url']))
3436 {
3437 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3438 }
3439 if (isset($copyright[0]['data']))
3440 {
3441 $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3442 }
3443 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3444 }
3445
3446 // CREDITS
3447 if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
3448 {
3449 foreach ($credits as $credit)
3450 {
3451 $credit_role = null;
3452 $credit_scheme = null;
3453 $credit_name = null;
3454 if (isset($credit['attribs']['']['role']))
3455 {
3456 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
3457 }
3458 if (isset($credit['attribs']['']['scheme']))
3459 {
3460 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3461 }
3462 else
3463 {
3464 $credit_scheme = 'urn:ebu';
3465 }
3466 if (isset($credit['data']))
3467 {
3468 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3469 }
3470 $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
3471 }
3472 }
3473 elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
3474 {
3475 foreach ($credits as $credit)
3476 {
3477 $credit_role = null;
3478 $credit_scheme = null;
3479 $credit_name = null;
3480 if (isset($credit['attribs']['']['role']))
3481 {
3482 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
3483 }
3484 if (isset($credit['attribs']['']['scheme']))
3485 {
3486 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3487 }
3488 else
3489 {
3490 $credit_scheme = 'urn:ebu';
3491 }
3492 if (isset($credit['data']))
3493 {
3494 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3495 }
3496 $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
3497 }
3498 }
3499 if (is_array($credits_parent))
3500 {
3501 $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
3502 }
3503
3504 // DESCRIPTION
3505 if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
3506 {
3507 if (isset($description_parent[0]['data']))
3508 {
3509 $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3510 }
3511 }
3512 elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
3513 {
3514 if (isset($description_parent[0]['data']))
3515 {
3516 $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3517 }
3518 }
3519
3520 // DURATION
3521 if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
3522 {
3523 $seconds = null;
3524 $minutes = null;
3525 $hours = null;
3526 if (isset($duration_parent[0]['data']))
3527 {
3528 $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3529 if (sizeof($temp) > 0)
3530 {
3531 (int) $seconds = array_pop($temp);
3532 }
3533 if (sizeof($temp) > 0)
3534 {
3535 (int) $minutes = array_pop($temp);
3536 $seconds += $minutes * 60;
3537 }
3538 if (sizeof($temp) > 0)
3539 {
3540 (int) $hours = array_pop($temp);
3541 $seconds += $hours * 3600;
3542 }
3543 unset($temp);
3544 $duration_parent = $seconds;
3545 }
3546 }
3547
3548 // HASHES
3549 if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
3550 {
3551 foreach ($hashes_iterator as $hash)
3552 {
3553 $value = null;
3554 $algo = null;
3555 if (isset($hash['data']))
3556 {
3557 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3558 }
3559 if (isset($hash['attribs']['']['algo']))
3560 {
3561 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
3562 }
3563 else
3564 {
3565 $algo = 'md5';
3566 }
3567 $hashes_parent[] = $algo.':'.$value;
3568 }
3569 }
3570 elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
3571 {
3572 foreach ($hashes_iterator as $hash)
3573 {
3574 $value = null;
3575 $algo = null;
3576 if (isset($hash['data']))
3577 {
3578 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3579 }
3580 if (isset($hash['attribs']['']['algo']))
3581 {
3582 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
3583 }
3584 else
3585 {
3586 $algo = 'md5';
3587 }
3588 $hashes_parent[] = $algo.':'.$value;
3589 }
3590 }
3591 if (is_array($hashes_parent))
3592 {
3593 $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
3594 }
3595
3596 // KEYWORDS
3597 if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
3598 {
3599 if (isset($keywords[0]['data']))
3600 {
3601 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3602 foreach ($temp as $word)
3603 {
3604 $keywords_parent[] = trim($word);
3605 }
3606 }
3607 unset($temp);
3608 }
3609 elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
3610 {
3611 if (isset($keywords[0]['data']))
3612 {
3613 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3614 foreach ($temp as $word)
3615 {
3616 $keywords_parent[] = trim($word);
3617 }
3618 }
3619 unset($temp);
3620 }
3621 elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
3622 {
3623 if (isset($keywords[0]['data']))
3624 {
3625 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3626 foreach ($temp as $word)
3627 {
3628 $keywords_parent[] = trim($word);
3629 }
3630 }
3631 unset($temp);
3632 }
3633 elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
3634 {
3635 if (isset($keywords[0]['data']))
3636 {
3637 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3638 foreach ($temp as $word)
3639 {
3640 $keywords_parent[] = trim($word);
3641 }
3642 }
3643 unset($temp);
3644 }
3645 if (is_array($keywords_parent))
3646 {
3647 $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
3648 }
3649
3650 // PLAYER
3651 if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
3652 {
3653 if (isset($player_parent[0]['attribs']['']['url']))
3654 {
3655 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
3656 }
3657 }
3658 elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
3659 {
3660 if (isset($player_parent[0]['attribs']['']['url']))
3661 {
3662 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
3663 }
3664 }
3665
3666 // RATINGS
3667 if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
3668 {
3669 foreach ($ratings as $rating)
3670 {
3671 $rating_scheme = null;
3672 $rating_value = null;
3673 if (isset($rating['attribs']['']['scheme']))
3674 {
3675 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3676 }
3677 else
3678 {
3679 $rating_scheme = 'urn:simple';
3680 }
3681 if (isset($rating['data']))
3682 {
3683 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3684 }
3685 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
3686 }
3687 }
3688 elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
3689 {
3690 foreach ($ratings as $rating)
3691 {
3692 $rating_scheme = 'urn:itunes';
3693 $rating_value = null;
3694 if (isset($rating['data']))
3695 {
3696 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3697 }
3698 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
3699 }
3700 }
3701 elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
3702 {
3703 foreach ($ratings as $rating)
3704 {
3705 $rating_scheme = null;
3706 $rating_value = null;
3707 if (isset($rating['attribs']['']['scheme']))
3708 {
3709 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3710 }
3711 else
3712 {
3713 $rating_scheme = 'urn:simple';
3714 }
3715 if (isset($rating['data']))
3716 {
3717 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3718 }
3719 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
3720 }
3721 }
3722 elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
3723 {
3724 foreach ($ratings as $rating)
3725 {
3726 $rating_scheme = 'urn:itunes';
3727 $rating_value = null;
3728 if (isset($rating['data']))
3729 {
3730 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3731 }
3732 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
3733 }
3734 }
3735 if (is_array($ratings_parent))
3736 {
3737 $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
3738 }
3739
3740 // RESTRICTIONS
3741 if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
3742 {
3743 foreach ($restrictions as $restriction)
3744 {
3745 $restriction_relationship = null;
3746 $restriction_type = null;
3747 $restriction_value = null;
3748 if (isset($restriction['attribs']['']['relationship']))
3749 {
3750 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
3751 }
3752 if (isset($restriction['attribs']['']['type']))
3753 {
3754 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3755 }
3756 if (isset($restriction['data']))
3757 {
3758 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3759 }
3760 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
3761 }
3762 }
3763 elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
3764 {
3765 foreach ($restrictions as $restriction)
3766 {
3767 $restriction_relationship = 'allow';
3768 $restriction_type = null;
3769 $restriction_value = 'itunes';
3770 if (isset($restriction['data']) && strtolower($restriction['data']) == 'yes')
3771 {
3772 $restriction_relationship = 'deny';
3773 }
3774 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
3775 }
3776 }
3777 elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
3778 {
3779 foreach ($restrictions as $restriction)
3780 {
3781 $restriction_relationship = null;
3782 $restriction_type = null;
3783 $restriction_value = null;
3784 if (isset($restriction['attribs']['']['relationship']))
3785 {
3786 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
3787 }
3788 if (isset($restriction['attribs']['']['type']))
3789 {
3790 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3791 }
3792 if (isset($restriction['data']))
3793 {
3794 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3795 }
3796 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
3797 }
3798 }
3799 elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
3800 {
3801 foreach ($restrictions as $restriction)
3802 {
3803 $restriction_relationship = 'allow';
3804 $restriction_type = null;
3805 $restriction_value = 'itunes';
3806 if (isset($restriction['data']) && strtolower($restriction['data']) == 'yes')
3807 {
3808 $restriction_relationship = 'deny';
3809 }
3810 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
3811 }
3812 }
3813 if (is_array($restrictions_parent))
3814 {
3815 $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
3816 }
3817
3818 // THUMBNAILS
3819 if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
3820 {
3821 foreach ($thumbnails as $thumbnail)
3822 {
3823 if (isset($thumbnail['attribs']['']['url']))
3824 {
3825 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
3826 }
3827 }
3828 }
3829 elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
3830 {
3831 foreach ($thumbnails as $thumbnail)
3832 {
3833 if (isset($thumbnail['attribs']['']['url']))
3834 {
3835 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
3836 }
3837 }
3838 }
3839
3840 // TITLES
3841 if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
3842 {
3843 if (isset($title_parent[0]['data']))
3844 {
3845 $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3846 }
3847 }
3848 elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
3849 {
3850 if (isset($title_parent[0]['data']))
3851 {
3852 $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3853 }
3854 }
3855
3856 // Clear the memory
3857 unset($parent);
3858
3859 // If we have media:group tags, loop through them.
3860 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
3861 {
3862 // If we have media:content tags, loop through them.
3863 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
3864 {
3865 if (isset($content['attribs']['']['url']))
3866 {
3867 // Attributes
3868 $bitrate = null;
3869 $channels = null;
3870 $duration = null;
3871 $expression = null;
3872 $framerate = null;
3873 $height = null;
3874 $javascript = null;
3875 $lang = null;
3876 $length = null;
3877 $medium = null;
3878 $samplingrate = null;
3879 $type = null;
3880 $url = null;
3881 $width = null;
3882
3883 // Elements
3884 $captions = null;
3885 $categories = null;
3886 $copyrights = null;
3887 $credits = null;
3888 $description = null;
3889 $hashes = null;
3890 $keywords = null;
3891 $player = null;
3892 $ratings = null;
3893 $restrictions = null;
3894 $thumbnails = null;
3895 $title = null;
3896
3897 // Start checking the attributes of media:content
3898 if (isset($content['attribs']['']['bitrate']))
3899 {
3900 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
3901 }
3902 if (isset($content['attribs']['']['channels']))
3903 {
3904 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
3905 }
3906 if (isset($content['attribs']['']['duration']))
3907 {
3908 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
3909 }
3910 else
3911 {
3912 $duration = $duration_parent;
3913 }
3914 if (isset($content['attribs']['']['expression']))
3915 {
3916 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
3917 }
3918 if (isset($content['attribs']['']['framerate']))
3919 {
3920 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
3921 }
3922 if (isset($content['attribs']['']['height']))
3923 {
3924 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
3925 }
3926 if (isset($content['attribs']['']['lang']))
3927 {
3928 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3929 }
3930 if (isset($content['attribs']['']['fileSize']))
3931 {
3932 $length = ceil($content['attribs']['']['fileSize']);
3933 }
3934 if (isset($content['attribs']['']['medium']))
3935 {
3936 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
3937 }
3938 if (isset($content['attribs']['']['samplingrate']))
3939 {
3940 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
3941 }
3942 if (isset($content['attribs']['']['type']))
3943 {
3944 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3945 }
3946 if (isset($content['attribs']['']['width']))
3947 {
3948 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
3949 }
3950 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
3951
3952 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
3953
3954 // CAPTIONS
3955 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
3956 {
3957 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
3958 {
3959 $caption_type = null;
3960 $caption_lang = null;
3961 $caption_startTime = null;
3962 $caption_endTime = null;
3963 $caption_text = null;
3964 if (isset($caption['attribs']['']['type']))
3965 {
3966 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3967 }
3968 if (isset($caption['attribs']['']['lang']))
3969 {
3970 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3971 }
3972 if (isset($caption['attribs']['']['start']))
3973 {
3974 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3975 }
3976 if (isset($caption['attribs']['']['end']))
3977 {
3978 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3979 }
3980 if (isset($caption['data']))
3981 {
3982 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3983 }
3984 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3985 }
3986 if (is_array($captions))
3987 {
3988 $captions = array_values(SimplePie_Misc::array_unique($captions));
3989 }
3990 }
3991 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
3992 {
3993 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
3994 {
3995 $caption_type = null;
3996 $caption_lang = null;
3997 $caption_startTime = null;
3998 $caption_endTime = null;
3999 $caption_text = null;
4000 if (isset($caption['attribs']['']['type']))
4001 {
4002 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4003 }
4004 if (isset($caption['attribs']['']['lang']))
4005 {
4006 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4007 }
4008 if (isset($caption['attribs']['']['start']))
4009 {
4010 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4011 }
4012 if (isset($caption['attribs']['']['end']))
4013 {
4014 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4015 }
4016 if (isset($caption['data']))
4017 {
4018 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4019 }
4020 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4021 }
4022 if (is_array($captions))
4023 {
4024 $captions = array_values(SimplePie_Misc::array_unique($captions));
4025 }
4026 }
4027 else
4028 {
4029 $captions = $captions_parent;
4030 }
4031
4032 // CATEGORIES
4033 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4034 {
4035 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4036 {
4037 $term = null;
4038 $scheme = null;
4039 $label = null;
4040 if (isset($category['data']))
4041 {
4042 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4043 }
4044 if (isset($category['attribs']['']['scheme']))
4045 {
4046 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4047 }
4048 else
4049 {
4050 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4051 }
4052 if (isset($category['attribs']['']['label']))
4053 {
4054 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4055 }
4056 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4057 }
4058 }
4059 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4060 {
4061 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4062 {
4063 $term = null;
4064 $scheme = null;
4065 $label = null;
4066 if (isset($category['data']))
4067 {
4068 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4069 }
4070 if (isset($category['attribs']['']['scheme']))
4071 {
4072 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4073 }
4074 else
4075 {
4076 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4077 }
4078 if (isset($category['attribs']['']['label']))
4079 {
4080 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4081 }
4082 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4083 }
4084 }
4085 if (is_array($categories) && is_array($categories_parent))
4086 {
4087 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4088 }
4089 elseif (is_array($categories))
4090 {
4091 $categories = array_values(SimplePie_Misc::array_unique($categories));
4092 }
4093 elseif (is_array($categories_parent))
4094 {
4095 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4096 }
4097
4098 // COPYRIGHTS
4099 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4100 {
4101 $copyright_url = null;
4102 $copyright_label = null;
4103 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4104 {
4105 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4106 }
4107 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4108 {
4109 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4110 }
4111 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4112 }
4113 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4114 {
4115 $copyright_url = null;
4116 $copyright_label = null;
4117 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4118 {
4119 $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4120 }
4121 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4122 {
4123 $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4124 }
4125 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4126 }
4127 else
4128 {
4129 $copyrights = $copyrights_parent;
4130 }
4131
4132 // CREDITS
4133 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4134 {
4135 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4136 {
4137 $credit_role = null;
4138 $credit_scheme = null;
4139 $credit_name = null;
4140 if (isset($credit['attribs']['']['role']))
4141 {
4142 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4143 }
4144 if (isset($credit['attribs']['']['scheme']))
4145 {
4146 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4147 }
4148 else
4149 {
4150 $credit_scheme = 'urn:ebu';
4151 }
4152 if (isset($credit['data']))
4153 {
4154 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4155 }
4156 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4157 }
4158 if (is_array($credits))
4159 {
4160 $credits = array_values(SimplePie_Misc::array_unique($credits));
4161 }
4162 }
4163 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4164 {
4165 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4166 {
4167 $credit_role = null;
4168 $credit_scheme = null;
4169 $credit_name = null;
4170 if (isset($credit['attribs']['']['role']))
4171 {
4172 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4173 }
4174 if (isset($credit['attribs']['']['scheme']))
4175 {
4176 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4177 }
4178 else
4179 {
4180 $credit_scheme = 'urn:ebu';
4181 }
4182 if (isset($credit['data']))
4183 {
4184 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4185 }
4186 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4187 }
4188 if (is_array($credits))
4189 {
4190 $credits = array_values(SimplePie_Misc::array_unique($credits));
4191 }
4192 }
4193 else
4194 {
4195 $credits = $credits_parent;
4196 }
4197
4198 // DESCRIPTION
4199 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4200 {
4201 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4202 }
4203 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4204 {
4205 $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4206 }
4207 else
4208 {
4209 $description = $description_parent;
4210 }
4211
4212 // HASHES
4213 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4214 {
4215 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4216 {
4217 $value = null;
4218 $algo = null;
4219 if (isset($hash['data']))
4220 {
4221 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4222 }
4223 if (isset($hash['attribs']['']['algo']))
4224 {
4225 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4226 }
4227 else
4228 {
4229 $algo = 'md5';
4230 }
4231 $hashes[] = $algo.':'.$value;
4232 }
4233 if (is_array($hashes))
4234 {
4235 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4236 }
4237 }
4238 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4239 {
4240 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4241 {
4242 $value = null;
4243 $algo = null;
4244 if (isset($hash['data']))
4245 {
4246 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4247 }
4248 if (isset($hash['attribs']['']['algo']))
4249 {
4250 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4251 }
4252 else
4253 {
4254 $algo = 'md5';
4255 }
4256 $hashes[] = $algo.':'.$value;
4257 }
4258 if (is_array($hashes))
4259 {
4260 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4261 }
4262 }
4263 else
4264 {
4265 $hashes = $hashes_parent;
4266 }
4267
4268 // KEYWORDS
4269 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4270 {
4271 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4272 {
4273 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4274 foreach ($temp as $word)
4275 {
4276 $keywords[] = trim($word);
4277 }
4278 unset($temp);
4279 }
4280 if (is_array($keywords))
4281 {
4282 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4283 }
4284 }
4285 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4286 {
4287 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4288 {
4289 $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4290 foreach ($temp as $word)
4291 {
4292 $keywords[] = trim($word);
4293 }
4294 unset($temp);
4295 }
4296 if (is_array($keywords))
4297 {
4298 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4299 }
4300 }
4301 else
4302 {
4303 $keywords = $keywords_parent;
4304 }
4305
4306 // PLAYER
4307 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4308 {
4309 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4310 }
4311 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4312 {
4313 $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4314 }
4315 else
4316 {
4317 $player = $player_parent;
4318 }
4319
4320 // RATINGS
4321 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4322 {
4323 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4324 {
4325 $rating_scheme = null;
4326 $rating_value = null;
4327 if (isset($rating['attribs']['']['scheme']))
4328 {
4329 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4330 }
4331 else
4332 {
4333 $rating_scheme = 'urn:simple';
4334 }
4335 if (isset($rating['data']))
4336 {
4337 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4338 }
4339 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4340 }
4341 if (is_array($ratings))
4342 {
4343 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4344 }
4345 }
4346 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4347 {
4348 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4349 {
4350 $rating_scheme = null;
4351 $rating_value = null;
4352 if (isset($rating['attribs']['']['scheme']))
4353 {
4354 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4355 }
4356 else
4357 {
4358 $rating_scheme = 'urn:simple';
4359 }
4360 if (isset($rating['data']))
4361 {
4362 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4363 }
4364 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4365 }
4366 if (is_array($ratings))
4367 {
4368 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4369 }
4370 }
4371 else
4372 {
4373 $ratings = $ratings_parent;
4374 }
4375
4376 // RESTRICTIONS
4377 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4378 {
4379 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4380 {
4381 $restriction_relationship = null;
4382 $restriction_type = null;
4383 $restriction_value = null;
4384 if (isset($restriction['attribs']['']['relationship']))
4385 {
4386 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4387 }
4388 if (isset($restriction['attribs']['']['type']))
4389 {
4390 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4391 }
4392 if (isset($restriction['data']))
4393 {
4394 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4395 }
4396 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4397 }
4398 if (is_array($restrictions))
4399 {
4400 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4401 }
4402 }
4403 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4404 {
4405 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4406 {
4407 $restriction_relationship = null;
4408 $restriction_type = null;
4409 $restriction_value = null;
4410 if (isset($restriction['attribs']['']['relationship']))
4411 {
4412 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4413 }
4414 if (isset($restriction['attribs']['']['type']))
4415 {
4416 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4417 }
4418 if (isset($restriction['data']))
4419 {
4420 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4421 }
4422 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4423 }
4424 if (is_array($restrictions))
4425 {
4426 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4427 }
4428 }
4429 else
4430 {
4431 $restrictions = $restrictions_parent;
4432 }
4433
4434 // THUMBNAILS
4435 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
4436 {
4437 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
4438 {
4439 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4440 }
4441 if (is_array($thumbnails))
4442 {
4443 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
4444 }
4445 }
4446 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
4447 {
4448 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
4449 {
4450 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4451 }
4452 if (is_array($thumbnails))
4453 {
4454 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
4455 }
4456 }
4457 else
4458 {
4459 $thumbnails = $thumbnails_parent;
4460 }
4461
4462 // TITLES
4463 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
4464 {
4465 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4466 }
4467 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
4468 {
4469 $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4470 }
4471 else
4472 {
4473 $title = $title_parent;
4474 }
4475
4476 $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
4477 }
4478 }
4479 }
4480
4481 // If we have standalone media:content tags, loop through them.
4482 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
4483 {
4484 foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4485 {
4486 if (isset($content['attribs']['']['url']))
4487 {
4488 // Attributes
4489 $bitrate = null;
4490 $channels = null;
4491 $duration = null;
4492 $expression = null;
4493 $framerate = null;
4494 $height = null;
4495 $javascript = null;
4496 $lang = null;
4497 $length = null;
4498 $medium = null;
4499 $samplingrate = null;
4500 $type = null;
4501 $url = null;
4502 $width = null;
4503
4504 // Elements
4505 $captions = null;
4506 $categories = null;
4507 $copyrights = null;
4508 $credits = null;
4509 $description = null;
4510 $hashes = null;
4511 $keywords = null;
4512 $player = null;
4513 $ratings = null;
4514 $restrictions = null;
4515 $thumbnails = null;
4516 $title = null;
4517
4518 // Start checking the attributes of media:content
4519 if (isset($content['attribs']['']['bitrate']))
4520 {
4521 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4522 }
4523 if (isset($content['attribs']['']['channels']))
4524 {
4525 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4526 }
4527 if (isset($content['attribs']['']['duration']))
4528 {
4529 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4530 }
4531 else
4532 {
4533 $duration = $duration_parent;
4534 }
4535 if (isset($content['attribs']['']['expression']))
4536 {
4537 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4538 }
4539 if (isset($content['attribs']['']['framerate']))
4540 {
4541 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4542 }
4543 if (isset($content['attribs']['']['height']))
4544 {
4545 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4546 }
4547 if (isset($content['attribs']['']['lang']))
4548 {
4549 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4550 }
4551 if (isset($content['attribs']['']['fileSize']))
4552 {
4553 $length = ceil($content['attribs']['']['fileSize']);
4554 }
4555 if (isset($content['attribs']['']['medium']))
4556 {
4557 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4558 }
4559 if (isset($content['attribs']['']['samplingrate']))
4560 {
4561 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4562 }
4563 if (isset($content['attribs']['']['type']))
4564 {
4565 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4566 }
4567 if (isset($content['attribs']['']['width']))
4568 {
4569 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4570 }
4571 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4572
4573 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4574
4575 // CAPTIONS
4576 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4577 {
4578 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4579 {
4580 $caption_type = null;
4581 $caption_lang = null;
4582 $caption_startTime = null;
4583 $caption_endTime = null;
4584 $caption_text = null;
4585 if (isset($caption['attribs']['']['type']))
4586 {
4587 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4588 }
4589 if (isset($caption['attribs']['']['lang']))
4590 {
4591 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4592 }
4593 if (isset($caption['attribs']['']['start']))
4594 {
4595 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4596 }
4597 if (isset($caption['attribs']['']['end']))
4598 {
4599 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4600 }
4601 if (isset($caption['data']))
4602 {
4603 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4604 }
4605 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4606 }
4607 if (is_array($captions))
4608 {
4609 $captions = array_values(SimplePie_Misc::array_unique($captions));
4610 }
4611 }
4612 else
4613 {
4614 $captions = $captions_parent;
4615 }
4616
4617 // CATEGORIES
4618 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4619 {
4620 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4621 {
4622 $term = null;
4623 $scheme = null;
4624 $label = null;
4625 if (isset($category['data']))
4626 {
4627 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4628 }
4629 if (isset($category['attribs']['']['scheme']))
4630 {
4631 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4632 }
4633 else
4634 {
4635 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4636 }
4637 if (isset($category['attribs']['']['label']))
4638 {
4639 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4640 }
4641 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4642 }
4643 }
4644 if (is_array($categories) && is_array($categories_parent))
4645 {
4646 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4647 }
4648 elseif (is_array($categories))
4649 {
4650 $categories = array_values(SimplePie_Misc::array_unique($categories));
4651 }
4652 elseif (is_array($categories_parent))
4653 {
4654 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4655 }
4656 else
4657 {
4658 $categories = null;
4659 }
4660
4661 // COPYRIGHTS
4662 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4663 {
4664 $copyright_url = null;
4665 $copyright_label = null;
4666 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4667 {
4668 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4669 }
4670 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4671 {
4672 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4673 }
4674 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4675 }
4676 else
4677 {
4678 $copyrights = $copyrights_parent;
4679 }
4680
4681 // CREDITS
4682 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4683 {
4684 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4685 {
4686 $credit_role = null;
4687 $credit_scheme = null;
4688 $credit_name = null;
4689 if (isset($credit['attribs']['']['role']))
4690 {
4691 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4692 }
4693 if (isset($credit['attribs']['']['scheme']))
4694 {
4695 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4696 }
4697 else
4698 {
4699 $credit_scheme = 'urn:ebu';
4700 }
4701 if (isset($credit['data']))
4702 {
4703 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4704 }
4705 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4706 }
4707 if (is_array($credits))
4708 {
4709 $credits = array_values(SimplePie_Misc::array_unique($credits));
4710 }
4711 }
4712 else
4713 {
4714 $credits = $credits_parent;
4715 }
4716
4717 // DESCRIPTION
4718 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4719 {
4720 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4721 }
4722 else
4723 {
4724 $description = $description_parent;
4725 }
4726
4727 // HASHES
4728 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4729 {
4730 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4731 {
4732 $value = null;
4733 $algo = null;
4734 if (isset($hash['data']))
4735 {
4736 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4737 }
4738 if (isset($hash['attribs']['']['algo']))
4739 {
4740 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4741 }
4742 else
4743 {
4744 $algo = 'md5';
4745 }
4746 $hashes[] = $algo.':'.$value;
4747 }
4748 if (is_array($hashes))
4749 {
4750 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4751 }
4752 }
4753 else
4754 {
4755 $hashes = $hashes_parent;
4756 }
4757
4758 // KEYWORDS
4759 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4760 {
4761 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4762 {
4763 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4764 foreach ($temp as $word)
4765 {
4766 $keywords[] = trim($word);
4767 }
4768 unset($temp);
4769 }
4770 if (is_array($keywords))
4771 {
4772 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4773 }
4774 }
4775 else
4776 {
4777 $keywords = $keywords_parent;
4778 }
4779
4780 // PLAYER
4781 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4782 {
4783 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4784 }
4785 else
4786 {
4787 $player = $player_parent;
4788 }
4789
4790 // RATINGS
4791 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4792 {
4793 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4794 {
4795 $rating_scheme = null;
4796 $rating_value = null;
4797 if (isset($rating['attribs']['']['scheme']))
4798 {
4799 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4800 }
4801 else
4802 {
4803 $rating_scheme = 'urn:simple';
4804 }
4805 if (isset($rating['data']))
4806 {
4807 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4808 }
4809 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4810 }
4811 if (is_array($ratings))
4812 {
4813 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4814 }
4815 }
4816 else
4817 {
4818 $ratings = $ratings_parent;
4819 }
4820
4821 // RESTRICTIONS
4822 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4823 {
4824 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4825 {
4826 $restriction_relationship = null;
4827 $restriction_type = null;
4828 $restriction_value = null;
4829 if (isset($restriction['attribs']['']['relationship']))
4830 {
4831 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4832 }
4833 if (isset($restriction['attribs']['']['type']))
4834 {
4835 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4836 }
4837 if (isset($restriction['data']))
4838 {
4839 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4840 }
4841 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4842 }
4843 if (is_array($restrictions))
4844 {
4845 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4846 }
4847 }
4848 else
4849 {
4850 $restrictions = $restrictions_parent;
4851 }
4852
4853 // THUMBNAILS
4854 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
4855 {
4856 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
4857 {
4858 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4859 }
4860 if (is_array($thumbnails))
4861 {
4862 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
4863 }
4864 }
4865 else
4866 {
4867 $thumbnails = $thumbnails_parent;
4868 }
4869
4870 // TITLES
4871 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
4872 {
4873 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4874 }
4875 else
4876 {
4877 $title = $title_parent;
4878 }
4879
4880 $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
4881 }
4882 }
4883 }
4884
4885 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
4886 {
4887 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] == 'enclosure')
4888 {
4889 // Attributes
4890 $bitrate = null;
4891 $channels = null;
4892 $duration = null;
4893 $expression = null;
4894 $framerate = null;
4895 $height = null;
4896 $javascript = null;
4897 $lang = null;
4898 $length = null;
4899 $medium = null;
4900 $samplingrate = null;
4901 $type = null;
4902 $url = null;
4903 $width = null;
4904
4905 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
4906 if (isset($link['attribs']['']['type']))
4907 {
4908 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4909 }
4910 if (isset($link['attribs']['']['length']))
4911 {
4912 $length = ceil($link['attribs']['']['length']);
4913 }
4914
4915 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
4916 $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
4917 }
4918 }
4919
4920 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
4921 {
4922 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] == 'enclosure')
4923 {
4924 // Attributes
4925 $bitrate = null;
4926 $channels = null;
4927 $duration = null;
4928 $expression = null;
4929 $framerate = null;
4930 $height = null;
4931 $javascript = null;
4932 $lang = null;
4933 $length = null;
4934 $medium = null;
4935 $samplingrate = null;
4936 $type = null;
4937 $url = null;
4938 $width = null;
4939
4940 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
4941 if (isset($link['attribs']['']['type']))
4942 {
4943 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4944 }
4945 if (isset($link['attribs']['']['length']))
4946 {
4947 $length = ceil($link['attribs']['']['length']);
4948 }
4949
4950 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
4951 $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
4952 }
4953 }
4954
4955 if ($enclosure = $this->get_item_tags('', 'enclosure'))
4956 {
4957 if (isset($enclosure[0]['attribs']['']['url']))
4958 {
4959 // Attributes
4960 $bitrate = null;
4961 $channels = null;
4962 $duration = null;
4963 $expression = null;
4964 $framerate = null;
4965 $height = null;
4966 $javascript = null;
4967 $lang = null;
4968 $length = null;
4969 $medium = null;
4970 $samplingrate = null;
4971 $type = null;
4972 $url = null;
4973 $width = null;
4974
4975 $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
4976 if (isset($enclosure[0]['attribs']['']['type']))
4977 {
4978 $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4979 }
4980 if (isset($enclosure[0]['attribs']['']['length']))
4981 {
4982 $length = ceil($enclosure[0]['attribs']['']['length']);
4983 }
4984
4985 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
4986 $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
4987 }
4988 }
4989 $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
4990 }
4991 if (!empty($this->data['enclosures']))
4992 {
4993 return $this->data['enclosures'];
4994 }
4995 else
4996 {
4997 return null;
4998 }
4999 }
5000
5001 function get_latitude()
5002 {
5003 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5004 {
5005 return (float) $return[0]['data'];
5006 }
5007 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
5008 {
5009 return (float) $match[1];
5010 }
5011 else
5012 {
5013 return null;
5014 }
5015 }
5016
5017 function get_longitude()
5018 {
5019 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5020 {
5021 return (float) $return[0]['data'];
5022 }
5023 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5024 {
5025 return (float) $return[0]['data'];
5026 }
5027 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
5028 {
5029 return (float) $match[2];
5030 }
5031 else
5032 {
5033 return null;
5034 }
5035 }
5036
5037 /**
5038 * Creates the add_to_* methods' return data
5039 *
5040 * @access private
5041 * @param string $item_url String to prefix to the item permalink
5042 * @param string $title_url String to prefix to the item title
5043 * (and suffix to the item permalink)
5044 * @return mixed URL if feed exists, false otherwise
5045 */
5046 function add_to_service($item_url, $title_url = null)
5047 {
5048 if ($this->get_permalink() !== null)
5049 {
5050 $return = $this->sanitize($item_url, SIMPLEPIE_CONSTRUCT_IRI) . rawurlencode($this->get_permalink());
5051 if ($title_url !== null && $this->get_title() !== null)
5052 {
5053 $return .= $this->sanitize($title_url, SIMPLEPIE_CONSTRUCT_IRI) . rawurlencode($this->get_title());
5054 }
5055 return $return;
5056 }
5057 else
5058 {
5059 return null;
5060 }
5061 }
5062
5063 function add_to_blinklist()
5064 {
5065 return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5066 }
5067
5068 function add_to_blogmarks()
5069 {
5070 return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5071 }
5072
5073 function add_to_delicious()
5074 {
5075 return $this->add_to_service('http://del.icio.us/post/?v=3&url=', '&title=');
5076 }
5077
5078 function add_to_digg()
5079 {
5080 return $this->add_to_service('http://digg.com/submit?phase=2&URL=');
5081 }
5082
5083 function add_to_furl()
5084 {
5085 return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5086 }
5087
5088 function add_to_magnolia()
5089 {
5090 return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5091 }
5092
5093 function add_to_myweb20()
5094 {
5095 return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5096 }
5097
5098 function add_to_newsvine()
5099 {
5100 return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5101 }
5102
5103 function add_to_reddit()
5104 {
5105 return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5106 }
5107
5108 function add_to_segnalo()
5109 {
5110 return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5111 }
5112
5113 function add_to_simpy()
5114 {
5115 return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5116 }
5117
5118 function add_to_spurl()
5119 {
5120 return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5121 }
5122
5123 function add_to_wists()
5124 {
5125 return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5126 }
5127
5128 function search_technorati()
5129 {
5130 return $this->add_to_service('http://www.technorati.com/search/');
5131 }
5132 }
5133
5134 class SimplePie_Author
5135 {
5136 var $name;
5137 var $link;
5138 var $email;
5139
5140 // Constructor, used to input the data
5141 function SimplePie_Author($name = null, $link = null, $email = null)
5142 {
5143 $this->name = $name;
5144 $this->link = $link;
5145 $this->email = $email;
5146 }
5147
5148 function __toString()
5149 {
5150 // There is no $this->data here
5151 return md5(serialize($this));
5152 }
5153
5154 function get_name()
5155 {
5156 if ($this->name !== null)
5157 {
5158 return $this->name;
5159 }
5160 else
5161 {
5162 return null;
5163 }
5164 }
5165
5166 function get_link()
5167 {
5168 if ($this->link !== null)
5169 {
5170 return $this->link;
5171 }
5172 else
5173 {
5174 return null;
5175 }
5176 }
5177
5178 function get_email()
5179 {
5180 if ($this->email !== null)
5181 {
5182 return $this->email;
5183 }
5184 else
5185 {
5186 return null;
5187 }
5188 }
5189 }
5190
5191 class SimplePie_Category
5192 {
5193 var $term;
5194 var $scheme;
5195 var $label;
5196
5197 // Constructor, used to input the data
5198 function SimplePie_Category($term = null, $scheme = null, $label = null)
5199 {
5200 $this->term = $term;
5201 $this->scheme = $scheme;
5202 $this->label = $label;
5203 }
5204
5205 function __toString()
5206 {
5207 // There is no $this->data here
5208 return md5(serialize($this));
5209 }
5210
5211 function get_term()
5212 {
5213 if ($this->term !== null)
5214 {
5215 return $this->term;
5216 }
5217 else
5218 {
5219 return null;
5220 }
5221 }
5222
5223 function get_scheme()
5224 {
5225 if ($this->scheme !== null)
5226 {
5227 return $this->scheme;
5228 }
5229 else
5230 {
5231 return null;
5232 }
5233 }
5234
5235 function get_label()
5236 {
5237 if ($this->label !== null)
5238 {
5239 return $this->label;
5240 }
5241 else
5242 {
5243 return $this->get_term();
5244 }
5245 }
5246 }
5247
5248 class SimplePie_Enclosure
5249 {
5250 var $bitrate;
5251 var $captions;
5252 var $categories;
5253 var $channels;
5254 var $copyright;
5255 var $credits;
5256 var $description;
5257 var $duration;
5258 var $expression;
5259 var $framerate;
5260 var $handler;
5261 var $hashes;
5262 var $height;
5263 var $javascript;
5264 var $keywords;
5265 var $lang;
5266 var $length;
5267 var $link;
5268 var $medium;
5269 var $player;
5270 var $ratings;
5271 var $restrictions;
5272 var $samplingrate;
5273 var $thumbnails;
5274 var $title;
5275 var $type;
5276 var $width;
5277
5278 // Constructor, used to input the data
5279 function SimplePie_Enclosure($link = null, $type = null, $length = null, $javascript = null, $bitrate = null, $captions = null, $categories = null, $channels = null, $copyright = null, $credits = null, $description = null, $duration = null, $expression = null, $framerate = null, $hashes = null, $height = null, $keywords = null, $lang = null, $medium = null, $player = null, $ratings = null, $restrictions = null, $samplingrate = null, $thumbnails = null, $title = null, $width = null)
5280 {
5281 $this->bitrate = $bitrate;
5282 $this->captions = $captions;
5283 $this->categories = $categories;
5284 $this->channels = $channels;
5285 $this->copyright = $copyright;
5286 $this->credits = $credits;
5287 $this->description = $description;
5288 $this->duration = $duration;
5289 $this->expression = $expression;
5290 $this->framerate = $framerate;
5291 $this->hashes = $hashes;
5292 $this->height = $height;
5293 $this->javascript = $javascript;
5294 $this->keywords = $keywords;
5295 $this->lang = $lang;
5296 $this->length = $length;
5297 $this->link = $link;
5298 $this->medium = $medium;
5299 $this->player = $player;
5300 $this->ratings = $ratings;
5301 $this->restrictions = $restrictions;
5302 $this->samplingrate = $samplingrate;
5303 $this->thumbnails = $thumbnails;
5304 $this->title = $title;
5305 $this->type = $type;
5306 $this->width = $width;
5307 if (class_exists('idna_convert'))
5308 {
5309 $idn =& new idna_convert;
5310 $parsed = SimplePie_Misc::parse_url($link);
5311 $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
5312 }
5313 $this->handler = $this->get_handler(); // Needs to load last
5314 }
5315
5316 function __toString()
5317 {
5318 // There is no $this->data here
5319 return md5(serialize($this));
5320 }
5321
5322 function get_bitrate()
5323 {
5324 if ($this->bitrate !== null)
5325 {
5326 return $this->bitrate;
5327 }
5328 else
5329 {
5330 return null;
5331 }
5332 }
5333
5334 function get_caption($key = 0)
5335 {
5336 $captions = $this->get_captions();
5337 if (isset($captions[$key]))
5338 {
5339 return $captions[$key];
5340 }
5341 else
5342 {
5343 return null;
5344 }
5345 }
5346
5347 function get_captions()
5348 {
5349 if ($this->captions !== null)
5350 {
5351 return $this->captions;
5352 }
5353 else
5354 {
5355 return null;
5356 }
5357 }
5358
5359 function get_category($key = 0)
5360 {
5361 $categories = $this->get_categories();
5362 if (isset($categories[$key]))
5363 {
5364 return $categories[$key];
5365 }
5366 else
5367 {
5368 return null;
5369 }
5370 }
5371
5372 function get_categories()
5373 {
5374 if ($this->categories !== null)
5375 {
5376 return $this->categories;
5377 }
5378 else
5379 {
5380 return null;
5381 }
5382 }
5383
5384 function get_channels()
5385 {
5386 if ($this->channels !== null)
5387 {
5388 return $this->channels;
5389 }
5390 else
5391 {
5392 return null;
5393 }
5394 }
5395
5396 function get_copyright()
5397 {
5398 if ($this->copyright !== null)
5399 {
5400 return $this->copyright;
5401 }
5402 else
5403 {
5404 return null;
5405 }
5406 }
5407
5408 function get_credit($key = 0)
5409 {
5410 $credits = $this->get_credits();
5411 if (isset($credits[$key]))
5412 {
5413 return $credits[$key];
5414 }
5415 else
5416 {
5417 return null;
5418 }
5419 }
5420
5421 function get_credits()
5422 {
5423 if ($this->credits !== null)
5424 {
5425 return $this->credits;
5426 }
5427 else
5428 {
5429 return null;
5430 }
5431 }
5432
5433 function get_description()
5434 {
5435 if ($this->description !== null)
5436 {
5437 return $this->description;
5438 }
5439 else
5440 {
5441 return null;
5442 }
5443 }
5444
5445 function get_duration($convert = false)
5446 {
5447 if ($this->duration !== null)
5448 {
5449 if ($convert)
5450 {
5451 $time = SimplePie_Misc::time_hms($this->duration);
5452 return $time;
5453 }
5454 else
5455 {
5456 return $this->duration;
5457 }
5458 }
5459 else
5460 {
5461 return null;
5462 }
5463 }
5464
5465 function get_expression()
5466 {
5467 if ($this->expression !== null)
5468 {
5469 return $this->expression;
5470 }
5471 else
5472 {
5473 return 'full';
5474 }
5475 }
5476
5477 function get_extension()
5478 {
5479 if ($this->link !== null)
5480 {
5481 $url = SimplePie_Misc::parse_url($this->link);
5482 if ($url['path'] !== '')
5483 {
5484 return pathinfo($url['path'], PATHINFO_EXTENSION);
5485 }
5486 }
5487 return null;
5488 }
5489
5490 function get_framerate()
5491 {
5492 if ($this->framerate !== null)
5493 {
5494 return $this->framerate;
5495 }
5496 else
5497 {
5498 return null;
5499 }
5500 }
5501
5502 function get_handler()
5503 {
5504 return $this->get_real_type(true);
5505 }
5506
5507 function get_hash($key = 0)
5508 {
5509 $hashes = $this->get_hashes();
5510 if (isset($hashes[$key]))
5511 {
5512 return $hashes[$key];
5513 }
5514 else
5515 {
5516 return null;
5517 }
5518 }
5519
5520 function get_hashes()
5521 {
5522 if ($this->hashes !== null)
5523 {
5524 return $this->hashes;
5525 }
5526 else
5527 {
5528 return null;
5529 }
5530 }
5531
5532 function get_height()
5533 {
5534 if ($this->height !== null)
5535 {
5536 return $this->height;
5537 }
5538 else
5539 {
5540 return null;
5541 }
5542 }
5543
5544 function get_language()
5545 {
5546 if ($this->lang !== null)
5547 {
5548 return $this->lang;
5549 }
5550 else
5551 {
5552 return null;
5553 }
5554 }
5555
5556 function get_keyword($key = 0)
5557 {
5558 $keywords = $this->get_keywords();
5559 if (isset($keywords[$key]))
5560 {
5561 return $keywords[$key];
5562 }
5563 else
5564 {
5565 return null;
5566 }
5567 }
5568
5569 function get_keywords()
5570 {
5571 if ($this->keywords !== null)
5572 {
5573 return $this->keywords;
5574 }
5575 else
5576 {
5577 return null;
5578 }
5579 }
5580
5581 function get_length()
5582 {
5583 if ($this->length !== null)
5584 {
5585 return $this->length;
5586 }
5587 else
5588 {
5589 return null;
5590 }
5591 }
5592
5593 function get_link()
5594 {
5595 if ($this->link !== null)
5596 {
5597 return urldecode($this->link);
5598 }
5599 else
5600 {
5601 return null;
5602 }
5603 }
5604
5605 function get_medium()
5606 {
5607 if ($this->medium !== null)
5608 {
5609 return $this->medium;
5610 }
5611 else
5612 {
5613 return null;
5614 }
5615 }
5616
5617 function get_player()
5618 {
5619 if ($this->player !== null)
5620 {
5621 return $this->player;
5622 }
5623 else
5624 {
5625 return null;
5626 }
5627 }
5628
5629 function get_rating($key = 0)
5630 {
5631 $ratings = $this->get_ratings();
5632 if (isset($ratings[$key]))
5633 {
5634 return $ratings[$key];
5635 }
5636 else
5637 {
5638 return null;
5639 }
5640 }
5641
5642 function get_ratings()
5643 {
5644 if ($this->ratings !== null)
5645 {
5646 return $this->ratings;
5647 }
5648 else
5649 {
5650 return null;
5651 }
5652 }
5653
5654 function get_restriction($key = 0)
5655 {
5656 $restrictions = $this->get_restrictions();
5657 if (isset($restrictions[$key]))
5658 {
5659 return $restrictions[$key];
5660 }
5661 else
5662 {
5663 return null;
5664 }
5665 }
5666
5667 function get_restrictions()
5668 {
5669 if ($this->restrictions !== null)
5670 {
5671 return $this->restrictions;
5672 }
5673 else
5674 {
5675 return null;
5676 }
5677 }
5678
5679 function get_sampling_rate()
5680 {
5681 if ($this->samplingrate !== null)
5682 {
5683 return $this->samplingrate;
5684 }
5685 else
5686 {
5687 return null;
5688 }
5689 }
5690
5691 function get_size()
5692 {
5693 $length = $this->get_length();
5694 if ($length !== null)
5695 {
5696 return round($length/1048576, 2);
5697 }
5698 else
5699 {
5700 return null;
5701 }
5702 }
5703
5704 function get_thumbnail($key = 0)
5705 {
5706 $thumbnails = $this->get_thumbnails();
5707 if (isset($thumbnails[$key]))
5708 {
5709 return $thumbnails[$key];
5710 }
5711 else
5712 {
5713 return null;
5714 }
5715 }
5716
5717 function get_thumbnails()
5718 {
5719 if ($this->thumbnails !== null)
5720 {
5721 return $this->thumbnails;
5722 }
5723 else
5724 {
5725 return null;
5726 }
5727 }
5728
5729 function get_title()
5730 {
5731 if ($this->title !== null)
5732 {
5733 return $this->title;
5734 }
5735 else
5736 {
5737 return null;
5738 }
5739 }
5740
5741 function get_type()
5742 {
5743 if ($this->type !== null)
5744 {
5745 return $this->type;
5746 }
5747 else
5748 {
5749 return null;
5750 }
5751 }
5752
5753 function get_width()
5754 {
5755 if ($this->width !== null)
5756 {
5757 return $this->width;
5758 }
5759 else
5760 {
5761 return null;
5762 }
5763 }
5764
5765 function native_embed($options='')
5766 {
5767 return $this->embed($options, true);
5768 }
5769
5770 /**
5771 * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
5772 */
5773 function embed($options = '', $native = false)
5774 {
5775 // Set up defaults
5776 $audio = '';
5777 $video = '';
5778 $alt = '';
5779 $altclass = '';
5780 $loop = 'false';
5781 $width = 'auto';
5782 $height = 'auto';
5783 $bgcolor = '#ffffff';
5784 $mediaplayer = '';
5785 $widescreen = false;
5786 $handler = $this->get_handler();
5787 $type = $this->get_real_type();
5788
5789 // Process options and reassign values as necessary
5790 if (is_array($options))
5791 {
5792 extract($options);
5793 }
5794 else
5795 {
5796 $options = explode(',', $options);
5797 foreach($options as $option)
5798 {
5799 $opt = explode(':', $option, 2);
5800 if (isset($opt[0], $opt[1]))
5801 {
5802 $opt[0] = trim($opt[0]);
5803 $opt[1] = trim($opt[1]);
5804 switch ($opt[0])
5805 {
5806 case 'audio':
5807 $audio = $opt[1];
5808 break;
5809
5810 case 'video':
5811 $video = $opt[1];
5812 break;
5813
5814 case 'alt':
5815 $alt = $opt[1];
5816 break;
5817
5818 case 'altclass':
5819 $altclass = $opt[1];
5820 break;
5821
5822 case 'loop':
5823 $loop = $opt[1];
5824 break;
5825
5826 case 'width':
5827 $width = $opt[1];
5828 break;
5829
5830 case 'height':
5831 $height = $opt[1];
5832 break;
5833
5834 case 'bgcolor':
5835 $bgcolor = $opt[1];
5836 break;
5837
5838 case 'mediaplayer':
5839 $mediaplayer = $opt[1];
5840 break;
5841
5842 case 'widescreen':
5843 $widescreen = $opt[1];
5844 break;
5845 }
5846 }
5847 }
5848 }
5849
5850 $mime = explode('/', $type, 2);
5851 $mime = $mime[0];
5852
5853 // Process values for 'auto'
5854 if ($width == 'auto')
5855 {
5856 if ($mime == 'video')
5857 {
5858 if ($height == 'auto')
5859 {
5860 $width = 480;
5861 }
5862 elseif ($widescreen)
5863 {
5864 $width = round((intval($height)/9)*16);
5865 }
5866 else
5867 {
5868 $width = round((intval($height)/3)*4);
5869 }
5870 }
5871 else
5872 {
5873 $width = '100%';
5874 }
5875 }
5876
5877 if ($height == 'auto')
5878 {
5879 if ($mime == 'audio')
5880 {
5881 $height = 0;
5882 }
5883 elseif ($mime == 'video')
5884 {
5885 if ($width == 'auto')
5886 {
5887 if ($widescreen)
5888 {
5889 $height = 270;
5890 }
5891 else
5892 {
5893 $height = 360;
5894 }
5895 }
5896 elseif ($widescreen)
5897 {
5898 $height = round((intval($width)/16)*9);
5899 }
5900 else
5901 {
5902 $height = round((intval($width)/4)*3);
5903 }
5904 }
5905 else
5906 {
5907 $height = 376;
5908 }
5909 }
5910 elseif ($mime == 'audio')
5911 {
5912 $height = 0;
5913 }
5914
5915 // Set proper placeholder value
5916 if ($mime == 'audio')
5917 {
5918 $placeholder = $audio;
5919 }
5920 elseif ($mime == 'video')
5921 {
5922 $placeholder = $video;
5923 }
5924
5925 $embed = '';
5926
5927 // Make sure the JS library is included
5928 if (!$native)
5929 {
5930 static $javascript_outputted = null;
5931 if (!$javascript_outputted && $this->javascript)
5932 {
5933 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
5934 $javascript_outputted = true;
5935 }
5936 }
5937
5938 // Odeo Feed MP3's
5939 if ($handler == 'odeo')
5940 {
5941 if ($native)
5942 {
5943 $embed .= '<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://adobe.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>';
5944 }
5945 else
5946 {
5947 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
5948 }
5949 }
5950
5951 // Flash
5952 elseif ($handler == 'flash')
5953 {
5954 if ($native)
5955 {
5956 $embed .= "<embed src=\"" . $this->get_link() . "\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"$type\" quality=\"high\" width=\"$width\" height=\"$height\" bgcolor=\"$bgcolor\" loop=\"$loop\"></embed>";
5957 }
5958 else
5959 {
5960 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
5961 }
5962 }
5963
5964 // Flash Media Player file types.
5965 // Preferred handler for MP3 file types.
5966 elseif ($handler == 'fmedia' || ($handler == 'mp3' && $mediaplayer != ''))
5967 {
5968 $height += 20;
5969 if ($native)
5970 {
5971 $embed .= "<embed src=\"$mediaplayer\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" quality=\"high\" width=\"$width\" height=\"$height\" wmode=\"transparent\" flashvars=\"file=" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "&autostart=false&repeat=$loop&showdigits=true&showfsbutton=false\"></embed>";
5972 }
5973 else
5974 {
5975 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
5976 }
5977 }
5978
5979 // QuickTime 7 file types. Need to test with QuickTime 6.
5980 // Only handle MP3's if the Flash Media Player is not present.
5981 elseif ($handler == 'quicktime' || ($handler == 'mp3' && $mediaplayer == ''))
5982 {
5983 $height += 16;
5984 if ($native)
5985 {
5986 if ($placeholder != ""){
5987 $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://apple.com/quicktime/download/\"></embed>";
5988 }
5989 else {
5990 $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://apple.com/quicktime/download/\"></embed>";
5991 }
5992 }
5993 else
5994 {
5995 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
5996 }
5997 }
5998
5999 // Windows Media
6000 elseif ($handler == 'wmedia')
6001 {
6002 $height += 45;
6003 if ($native)
6004 {
6005 $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>";
6006 }
6007 else
6008 {
6009 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
6010 }
6011 }
6012
6013 // Everything else
6014 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
6015
6016 return $embed;
6017 }
6018
6019 function get_real_type($find_handler = false)
6020 {
6021 // If it's Odeo, let's get it out of the way.
6022 if (substr(strtolower($this->get_link()), 0, 15) == 'http://odeo.com')
6023 {
6024 return 'odeo';
6025 }
6026
6027 // Mime-types by handler.
6028 $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
6029 $types_fmedia = array('video/flv', 'video/x-flv'); // Flash Media Player
6030 $types_quicktime = array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', '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'); // QuickTime
6031 $types_wmedia = 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'); // Windows Media
6032 $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
6033
6034 if ($this->get_type() !== null)
6035 {
6036 $type = strtolower($this->type);
6037 }
6038 else
6039 {
6040 $type = null;
6041 }
6042
6043 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
6044 if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
6045 {
6046 switch (strtolower($this->get_extension()))
6047 {
6048 // Audio mime-types
6049 case 'aac':
6050 case 'adts':
6051 $type = 'audio/acc';
6052 break;
6053
6054 case 'aif':
6055 case 'aifc':
6056 case 'aiff':
6057 case 'cdda':
6058 $type = 'audio/aiff';
6059 break;
6060
6061 case 'bwf':
6062 $type = 'audio/wav';
6063 break;
6064
6065 case 'kar':
6066 case 'mid':
6067 case 'midi':
6068 case 'smf':
6069 $type = 'audio/midi';
6070 break;
6071
6072 case 'm4a':
6073 $type = 'audio/x-m4a';
6074 break;
6075
6076 case 'mp3':
6077 case 'swa':
6078 $type = 'audio/mp3';
6079 break;
6080
6081 case 'wav':
6082 $type = 'audio/wav';
6083 break;
6084
6085 case 'wax':
6086 $type = 'audio/x-ms-wax';
6087 break;
6088
6089 case 'wma':
6090 $type = 'audio/x-ms-wma';
6091 break;
6092
6093 // Video mime-types
6094 case '3gp':
6095 case '3gpp':
6096 $type = 'video/3gpp';
6097 break;
6098
6099 case '3g2':
6100 case '3gp2':
6101 $type = 'video/3gpp2';
6102 break;
6103
6104 case 'asf':
6105 $type = 'video/x-ms-asf';
6106 break;
6107
6108 case 'flv':
6109 $type = 'video/x-flv';
6110 break;
6111
6112 case 'm1a':
6113 case 'm1s':
6114 case 'm1v':
6115 case 'm15':
6116 case 'm75':
6117 case 'mp2':
6118 case 'mpa':
6119 case 'mpeg':
6120 case 'mpg':
6121 case 'mpm':
6122 case 'mpv':
6123 $type = 'video/mpeg';
6124 break;
6125
6126 case 'm4v':
6127 $type = 'video/x-m4v';
6128 break;
6129
6130 case 'mov':
6131 case 'qt':
6132 $type = 'video/quicktime';
6133 break;
6134
6135 case 'mp4':
6136 case 'mpg4':
6137 $type = 'video/mp4';
6138 break;
6139
6140 case 'sdv':
6141 $type = 'video/sd-video';
6142 break;
6143
6144 case 'wm':
6145 $type = 'video/x-ms-wm';
6146 break;
6147
6148 case 'wmv':
6149 $type = 'video/x-ms-wmv';
6150 break;
6151
6152 case 'wvx':
6153 $type = 'video/x-ms-wvx';
6154 break;
6155
6156 // Flash mime-types
6157 case 'spl':
6158 $type = 'application/futuresplash';
6159 break;
6160
6161 case 'swf':
6162 $type = 'application/x-shockwave-flash';
6163 break;
6164 }
6165 }
6166
6167 if ($find_handler)
6168 {
6169 if (in_array($type, $types_flash))
6170 {
6171 return 'flash';
6172 }
6173 elseif (in_array($type, $types_fmedia))
6174 {
6175 return 'fmedia';
6176 }
6177 elseif (in_array($type, $types_quicktime))
6178 {
6179 return 'quicktime';
6180 }
6181 elseif (in_array($type, $types_wmedia))
6182 {
6183 return 'wmedia';
6184 }
6185 elseif (in_array($type, $types_mp3))
6186 {
6187 return 'mp3';
6188 }
6189 else
6190 {
6191 return null;
6192 }
6193 }
6194 else
6195 {
6196 return $type;
6197 }
6198 }
6199 }
6200
6201 class SimplePie_Caption
6202 {
6203 var $type;
6204 var $lang;
6205 var $startTime;
6206 var $endTime;
6207 var $text;
6208
6209 // Constructor, used to input the data
6210 function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
6211 {
6212 $this->type = $type;
6213 $this->lang = $lang;
6214 $this->startTime = $startTime;
6215 $this->endTime = $endTime;
6216 $this->text = $text;
6217 }
6218
6219 function __toString()
6220 {
6221 // There is no $this->data here
6222 return md5(serialize($this));
6223 }
6224
6225 function get_endtime()
6226 {
6227 if ($this->endTime !== null)
6228 {
6229 return $this->endTime;
6230 }
6231 else
6232 {
6233 return null;
6234 }
6235 }
6236
6237 function get_language()
6238 {
6239 if ($this->language !== null)
6240 {
6241 return $this->language;
6242 }
6243 else
6244 {
6245 return null;
6246 }
6247 }
6248
6249 function get_starttime()
6250 {
6251 if ($this->startTime !== null)
6252 {
6253 return $this->startTime;
6254 }
6255 else
6256 {
6257 return null;
6258 }
6259 }
6260
6261 function get_text()
6262 {
6263 if ($this->text !== null)
6264 {
6265 return $this->text;
6266 }
6267 else
6268 {
6269 return null;
6270 }
6271 }
6272
6273 function get_type()
6274 {
6275 if ($this->type !== null)
6276 {
6277 return $this->type;
6278 }
6279 else
6280 {
6281 return null;
6282 }
6283 }
6284 }
6285
6286 class SimplePie_Credit
6287 {
6288 var $role;
6289 var $scheme;
6290 var $name;
6291
6292 // Constructor, used to input the data
6293 function SimplePie_Credit($role = null, $scheme = null, $name = null)
6294 {
6295 $this->role = $role;
6296 $this->scheme = $scheme;
6297 $this->name = $name;
6298 }
6299
6300 function __toString()
6301 {
6302 // There is no $this->data here
6303 return md5(serialize($this));
6304 }
6305
6306 function get_role()
6307 {
6308 if ($this->role !== null)
6309 {
6310 return $this->role;
6311 }
6312 else
6313 {
6314 return null;
6315 }
6316 }
6317
6318 function get_scheme()
6319 {
6320 if ($this->scheme !== null)
6321 {
6322 return $this->scheme;
6323 }
6324 else
6325 {
6326 return null;
6327 }
6328 }
6329
6330 function get_name()
6331 {
6332 if ($this->name !== null)
6333 {
6334 return $this->name;
6335 }
6336 else
6337 {
6338 return null;
6339 }
6340 }
6341 }
6342
6343 class SimplePie_Copyright
6344 {
6345 var $url;
6346 var $label;
6347
6348 // Constructor, used to input the data
6349 function SimplePie_Copyright($url = null, $label = null)
6350 {
6351 $this->url = $url;
6352 $this->label = $label;
6353 }
6354
6355 function __toString()
6356 {
6357 // There is no $this->data here
6358 return md5(serialize($this));
6359 }
6360
6361 function get_url()
6362 {
6363 if ($this->url !== null)
6364 {
6365 return $this->url;
6366 }
6367 else
6368 {
6369 return null;
6370 }
6371 }
6372
6373 function get_attribution()
6374 {
6375 if ($this->label !== null)
6376 {
6377 return $this->label;
6378 }
6379 else
6380 {
6381 return null;
6382 }
6383 }
6384 }
6385
6386 class SimplePie_Rating
6387 {
6388 var $scheme;
6389 var $value;
6390
6391 // Constructor, used to input the data
6392 function SimplePie_Rating($scheme = null, $value = null)
6393 {
6394 $this->scheme = $scheme;
6395 $this->value = $value;
6396 }
6397
6398 function __toString()
6399 {
6400 // There is no $this->data here
6401 return md5(serialize($this));
6402 }
6403
6404 function get_scheme()
6405 {
6406 if ($this->scheme !== null)
6407 {
6408 return $this->scheme;
6409 }
6410 else
6411 {
6412 return null;
6413 }
6414 }
6415
6416 function get_value()
6417 {
6418 if ($this->value !== null)
6419 {
6420 return $this->value;
6421 }
6422 else
6423 {
6424 return null;
6425 }
6426 }
6427 }
6428
6429 class SimplePie_Restriction
6430 {
6431 var $relationship;
6432 var $type;
6433 var $value;
6434
6435 // Constructor, used to input the data
6436 function SimplePie_Restriction($relationship = null, $type = null, $value = null)
6437 {
6438 $this->relationship = $relationship;
6439 $this->type = $type;
6440 $this->value = $value;
6441 }
6442
6443 function __toString()
6444 {
6445 // There is no $this->data here
6446 return md5(serialize($this));
6447 }
6448
6449 function get_relationship()
6450 {
6451 if ($this->relationship !== null)
6452 {
6453 return $this->relationship;
6454 }
6455 else
6456 {
6457 return null;
6458 }
6459 }
6460
6461 function get_type()
6462 {
6463 if ($this->type !== null)
6464 {
6465 return $this->type;
6466 }
6467 else
6468 {
6469 return null;
6470 }
6471 }
6472
6473 function get_value()
6474 {
6475 if ($this->value !== null)
6476 {
6477 return $this->value;
6478 }
6479 else
6480 {
6481 return null;
6482 }
6483 }
6484 }
6485
6486 /**
6487 * @todo Move to properly supporting RFC2616 (HTTP/1.1)
6488 */
6489 class SimplePie_File
6490 {
6491 var $url;
6492 var $useragent;
6493 var $success = true;
6494 var $headers = array();
6495 var $body;
6496 var $status_code;
6497 var $redirects = 0;
6498 var $error;
6499 var $method;
6500
6501 function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
6502 {
6503 if (class_exists('idna_convert'))
6504 {
6505 $idn =& new idna_convert;
6506 $parsed = SimplePie_Misc::parse_url($url);
6507 $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6508 }
6509 $this->url = $url;
6510 $this->useragent = $useragent;
6511 if (preg_match('/^http(s)?:\/\//i', $url))
6512 {
6513 if ($useragent === null)
6514 {
6515 $useragent = ini_get('user_agent');
6516 $this->useragent = $useragent;
6517 }
6518 if (!is_array($headers))
6519 {
6520 $headers = array();
6521 }
6522 if (!$force_fsockopen && extension_loaded('curl'))
6523 {
6524 $this->method = 'curl';
6525 $fp = curl_init();
6526 $headers2 = array();
6527 foreach ($headers as $key => $value)
6528 {
6529 $headers2[] = "$key: $value";
6530 }
6531 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
6532 {
6533 curl_setopt($fp, CURLOPT_ENCODING, '');
6534 }
6535 curl_setopt($fp, CURLOPT_URL, $url);
6536 curl_setopt($fp, CURLOPT_HEADER, 1);
6537 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
6538 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
6539 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
6540 curl_setopt($fp, CURLOPT_REFERER, $url);
6541 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
6542 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
6543 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
6544 {
6545 curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
6546 curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
6547 }
6548
6549 curl_setopt($fp, CURLOPT_SSL_VERIFYPEER, false);
6550 curl_setopt($fp, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
6551
6552 $this->headers = curl_exec($fp);
6553 if (curl_errno($fp) == 23 || curl_errno($fp) == 61)
6554 {
6555 curl_setopt($fp, CURLOPT_ENCODING, 'none');
6556 $this->headers = curl_exec($fp);
6557 }
6558 if (curl_errno($fp))
6559 {
6560 $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
6561 $this->success = false;
6562 }
6563 else
6564 {
6565 $info = curl_getinfo($fp);
6566 curl_close($fp);
6567 $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
6568 $this->headers = array_pop($this->headers);
6569 $parser =& new SimplePie_HTTP_Parser($this->headers);
6570 if ($parser->parse())
6571 {
6572 $this->headers = $parser->headers;
6573 $this->body = $parser->body;
6574 $this->status_code = $parser->status_code;
6575 if (($this->status_code == 300 || $this->status_code == 301 || $this->status_code == 302 || $this->status_code == 303 || $this->status_code == 307 || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
6576 {
6577 $this->redirects++;
6578 if (isset($this->headers['content-location']))
6579 {
6580 $location = SimplePie_Misc::absolutize_url($this->headers['location'], SimplePie_Misc::absolutize_url($this->headers['content-location'], $url));
6581 }
6582 else
6583 {
6584 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
6585 }
6586 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
6587 }
6588 }
6589 }
6590 }
6591 else
6592 {
6593 $this->method = 'fsockopen';
6594 $url_parts = parse_url($url);
6595 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) == 'https')
6596 {
6597 $url_parts['host'] = "ssl://$url_parts[host]";
6598 $url_parts['port'] = 443;
6599 }
6600 if (!isset($url_parts['port']))
6601 {
6602 $url_parts['port'] = 80;
6603 }
6604 $fp = fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
6605 if (!$fp)
6606 {
6607 $this->error = 'fsockopen error: ' . $errstr;
6608 $this->success = false;
6609 }
6610 else
6611 {
6612 if (function_exists('stream_set_timeout'))
6613 {
6614 stream_set_timeout($fp, $timeout);
6615 }
6616 else
6617 {
6618 socket_set_timeout($fp, $timeout);
6619 }
6620 if (isset($url_parts['path']))
6621 {
6622 if (isset($url_parts['query']))
6623 {
6624 $get = "$url_parts[path]?$url_parts[query]";
6625 }
6626 else
6627 {
6628 $get = $url_parts['path'];
6629 }
6630 }
6631 else
6632 {
6633 $get = '/';
6634 }
6635 $out = "GET $get HTTP/1.0\r\n";
6636 $out .= "Host: $url_parts[host]\r\n";
6637 $out .= "User-Agent: $useragent\r\n";
6638 if (function_exists('gzinflate'))
6639 {
6640 $out .= "Accept-Encoding: gzip,deflate\r\n";
6641 }
6642
6643 if (isset($url_parts['user']) && isset($url_parts['pass']))
6644 {
6645 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
6646 }
6647 foreach ($headers as $key => $value)
6648 {
6649 $out .= "$key: $value\r\n";
6650 }
6651 $out .= "Connection: Close\r\n\r\n";
6652 fwrite($fp, $out);
6653
6654 if (function_exists('stream_get_meta_data'))
6655 {
6656 $info = stream_get_meta_data($fp);
6657 }
6658 else
6659 {
6660 $info = socket_get_status($fp);
6661 }
6662
6663 $this->headers = '';
6664 while (!$info['eof'] && !$info['timed_out'])
6665 {
6666 $this->headers .= fread($fp, 1160);
6667 if (function_exists('stream_get_meta_data'))
6668 {
6669 $info = stream_get_meta_data($fp);
6670 }
6671 else
6672 {
6673 $info = socket_get_status($fp);
6674 }
6675 }
6676 if (!$info['timed_out'])
6677 {
6678 $parser =& new SimplePie_HTTP_Parser($this->headers);
6679 if ($parser->parse())
6680 {
6681 $this->headers = $parser->headers;
6682 $this->body = $parser->body;
6683 $this->status_code = $parser->status_code;
6684 if (($this->status_code == 300 || $this->status_code == 301 || $this->status_code == 302 || $this->status_code == 303 || $this->status_code == 307 || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
6685 {
6686 $this->redirects++;
6687 if (isset($this->headers['content-location']))
6688 {
6689 $location = SimplePie_Misc::absolutize_url($this->headers['location'], SimplePie_Misc::absolutize_url($this->headers['content-location'], $url));
6690 }
6691 else
6692 {
6693 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
6694 }
6695 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
6696 }
6697 if (isset($this->headers['content-encoding']) && ($this->headers['content-encoding'] == 'gzip' || $this->headers['content-encoding'] == 'deflate'))
6698 {
6699 if (substr($this->body, 0, 8) == "\x1f\x8b\x08\x00\x00\x00\x00\x00")
6700 {
6701 $this->body = substr($this->body, 10);
6702 }
6703 $this->body = gzinflate($this->body);
6704 }
6705 }
6706 }
6707 else
6708 {
6709 $this->error = 'fsocket timed out';
6710 $this->success = false;
6711 }
6712 fclose($fp);
6713 }
6714 }
6715 }
6716 elseif (function_exists('file_get_contents'))
6717 {
6718 $this->method = 'file_get_contents';
6719 if (!$this->body = file_get_contents($url))
6720 {
6721 $this->error = 'file_get_contents could not read the file';
6722 $this->success = false;
6723 }
6724 }
6725 else
6726 {
6727 $this->method = 'fopen';
6728 if (($fp = fopen($url, 'rb')) === false)
6729 {
6730 $this->error = 'failed to open stream: No such file or directory';
6731 $this->success = false;
6732 }
6733 else
6734 {
6735 $this->body = '';
6736 while (!feof($fp))
6737 {
6738 $this->body .= fread($fp, 8192);
6739 }
6740 fclose($fp);
6741 }
6742 }
6743 }
6744 }
6745
6746 /**
6747 * HTTP Response Parser
6748 *
6749 * @package SimplePie
6750 * @todo Support HTTP Requests
6751 */
6752 class SimplePie_HTTP_Parser
6753 {
6754 /**
6755 * HTTP Version
6756 *
6757 * @access public
6758 * @var string
6759 */
6760 var $http_version = '';
6761
6762 /**
6763 * Status code
6764 *
6765 * @access public
6766 * @var string
6767 */
6768 var $status_code = '';
6769
6770 /**
6771 * Reason phrase
6772 *
6773 * @access public
6774 * @var string
6775 */
6776 var $reason = '';
6777
6778 /**
6779 * Key/value pairs of the headers
6780 *
6781 * @access public
6782 * @var array
6783 */
6784 var $headers = array();
6785
6786 /**
6787 * Body of the response
6788 *
6789 * @access public
6790 * @var string
6791 */
6792 var $body = '';
6793
6794 /**
6795 * Current state of the state machine
6796 *
6797 * @access private
6798 * @var string
6799 */
6800 var $state = 'start';
6801
6802 /**
6803 * Input data
6804 *
6805 * @access private
6806 * @var string
6807 */
6808 var $data = '';
6809
6810 /**
6811 * Input data length (to avoid calling strlen() everytime this is needed)
6812 *
6813 * @access private
6814 * @var int
6815 */
6816 var $data_length = 0;
6817
6818 /**
6819 * Current position of the pointer
6820 *
6821 * @access private
6822 * @var int
6823 */
6824 var $position = 0;
6825
6826 /**
6827 * Name of the hedaer currently being parsed
6828 *
6829 * @access private
6830 * @var string
6831 */
6832 var $name = '';
6833
6834 /**
6835 * Value of the hedaer currently being parsed
6836 *
6837 * @access private
6838 * @var string
6839 */
6840 var $value = '';
6841
6842 /**
6843 * Create an instance of the class with the input data
6844 *
6845 * @access public
6846 * @param string $data Input data
6847 */
6848 function SimplePie_HTTP_Parser($data)
6849 {
6850 $this->data = $data;
6851 $this->data_length = strlen($this->data);
6852 }
6853
6854 /**
6855 * Parse the input data
6856 *
6857 * @access public
6858 * @return bool true on success, false on failure
6859 */
6860 function parse()
6861 {
6862 while ($this->state && $this->state != 'emit' && $this->has_data())
6863 {
6864 $state = $this->state;
6865 $this->$state();
6866 }
6867 $this->data = '';
6868 if ($this->state == 'emit')
6869 {
6870 return true;
6871 }
6872 else
6873 {
6874 $this->http_version = '';
6875 $this->status_code = '';
6876 $this->headers = array();
6877 $this->body = '';
6878 return false;
6879 }
6880 }
6881
6882 /**
6883 * Check whether there is data beyond the pointer
6884 *
6885 * @access private
6886 * @return bool true if there is further data, false if not
6887 */
6888 function has_data()
6889 {
6890 return (bool) ($this->position < $this->data_length);
6891 }
6892
6893 /**
6894 * See if the next character is LWS
6895 *
6896 * @access private
6897 * @return bool true if the next character is LWS, false if not
6898 */
6899 function is_linear_whitespace()
6900 {
6901 return (bool) (strspn($this->data, "\x09\x20", $this->position, 1)
6902 || (substr($this->data, $this->position, 2) == "\r\n" && strspn($this->data, "\x09\x20", $this->position + 2, 1))
6903 || (strspn($this->data, "\r\n", $this->position, 1) && strspn($this->data, "\x09\x20", $this->position + 1, 1)));
6904 }
6905
6906 /**
6907 * The starting state of the state machine, see if the data is a response or request
6908 *
6909 * @access private
6910 */
6911 function start()
6912 {
6913 $this->state = 'http_version_response';
6914 }
6915
6916 /**
6917 * Parse an HTTP-version string
6918 *
6919 * @access private
6920 */
6921 function http_version()
6922 {
6923 if (preg_match('/^HTTP\/([0-9]+\.[0-9]+)/i', substr($this->data, $this->position, strcspn($this->data, "\r\n", $this->position)), $match))
6924 {
6925 $this->position += strlen($match[0]);
6926 $this->http_version = $match[1];
6927 return true;
6928 }
6929 else
6930 {
6931 return false;
6932 }
6933 }
6934
6935 /**
6936 * Parse LWS, replacing consecutive characters with a single space
6937 *
6938 * @access private
6939 */
6940 function linear_whitespace()
6941 {
6942 do
6943 {
6944 if (substr($this->data, $this->position, 2) == "\r\n")
6945 {
6946 $this->position += 2;
6947 }
6948 elseif (strspn($this->data, "\r\n", $this->position, 1))
6949 {
6950 $this->position++;
6951 }
6952 $this->position += strspn($this->data, "\x09\x20", $this->position);
6953 } while ($this->is_linear_whitespace());
6954 $this->value .= "\x20";
6955 }
6956
6957 /**
6958 * Parse an HTTP-version string within a response
6959 *
6960 * @access private
6961 */
6962 function http_version_response()
6963 {
6964 if ($this->http_version() && $this->data[$this->position] == "\x20")
6965 {
6966 $this->state = 'status_code';
6967 $this->position++;
6968 }
6969 else
6970 {
6971 $this->state = false;
6972 }
6973 }
6974
6975 /**
6976 * Parse a status code
6977 *
6978 * @access private
6979 */
6980 function status_code()
6981 {
6982 if (strspn($this->data, '1234567890', $this->position, 3) == 3)
6983 {
6984 $this->status_code = substr($this->data, $this->position, 3);
6985 $this->state = 'reason_phrase';
6986 $this->position += 3;
6987 }
6988 else
6989 {
6990 $this->state = false;
6991 }
6992 }
6993
6994 /**
6995 * Skip over the reason phrase (it has no normative value, and you can send absolutely anything here)
6996 *
6997 * @access private
6998 */
6999 function reason_phrase()
7000 {
7001 $len = strcspn($this->data, "\r\n", $this->position);
7002 $this->reason = substr($this->data, $this->position, $len);
7003 $this->position += $len;
7004 if ($this->has_data())
7005 {
7006 if (substr($this->data, $this->position, 2) == "\r\n")
7007 {
7008 $this->position += 2;
7009 }
7010 elseif (strspn($this->data, "\r\n", $this->position, 1))
7011 {
7012 $this->position++;
7013 }
7014 $this->state = 'name';
7015 }
7016 }
7017
7018 /**
7019 * Parse a header name
7020 *
7021 * @access private
7022 */
7023 function name()
7024 {
7025 $len = strcspn($this->data, ':', $this->position);
7026 $this->name = substr($this->data, $this->position, $len);
7027 $this->position += $len;
7028
7029 if ($this->has_data() && $this->data[$this->position] == ':')
7030 {
7031 $this->state = 'value_next';
7032 $this->position++;
7033 }
7034 else
7035 {
7036 $this->state = false;
7037 }
7038 }
7039
7040 /**
7041 * See what state to move the state machine to while within non-quoted header values
7042 *
7043 * @access private
7044 */
7045 function value_next()
7046 {
7047 if ($this->is_linear_whitespace())
7048 {
7049 $this->state = 'value_linear_whitespace';
7050 }
7051 elseif ($this->data[$this->position] == '"')
7052 {
7053 $this->state = 'value_quote_next';
7054 $this->position++;
7055 }
7056 elseif (substr($this->data, $this->position, 2) == "\r\n")
7057 {
7058 $this->state = 'end_crlf';
7059 $this->position += 2;
7060 }
7061 elseif (strspn($this->data, "\r\n", $this->position, 1))
7062 {
7063 $this->state = 'end_crlf';
7064 $this->position++;
7065 }
7066 else
7067 {
7068 $this->state = 'value_no_quote';
7069 }
7070 }
7071
7072 /**
7073 * Parse a header value while outside quotes
7074 *
7075 * @access private
7076 */
7077 function value_no_quote()
7078 {
7079 $len = strcspn($this->data, "\x09\x20\r\n\"", $this->position);
7080 $this->value .= substr($this->data, $this->position, $len);
7081 $this->state = 'value_next';
7082 $this->position += $len;
7083 }
7084
7085 /**
7086 * Parse LWS outside quotes
7087 *
7088 * @access private
7089 */
7090 function value_linear_whitespace()
7091 {
7092 $this->linear_whitespace();
7093 $this->state = 'value_next';
7094 }
7095
7096 /**
7097 * See what state to move the state machine to while within quoted header values
7098 *
7099 * @access private
7100 */
7101 function value_quote_next()
7102 {
7103 if ($this->is_linear_whitespace())
7104 {
7105 $this->state = 'value_linear_whitespace_quote';
7106 }
7107 else
7108 {
7109 switch ($this->data[$this->position])
7110 {
7111 case '"':
7112 $this->state = 'value_next';
7113 $this->position++;
7114 break;
7115
7116 case '\\':
7117 $this->state = 'value_quote_char';
7118 $this->position++;
7119 break;
7120
7121 default:
7122 $this->state = 'value_quote';
7123 break;
7124 }
7125 }
7126 }
7127
7128 /**
7129 * Parse a header value while within quotes
7130 *
7131 * @access private
7132 */
7133 function value_quote()
7134 {
7135 $len = strcspn($this->data, "\x09\x20\r\n\"\\", $this->position);
7136 $this->value .= substr($this->data, $this->position, $len);
7137 $this->position += $len;
7138 $this->state = 'value_quote_next';
7139 }
7140
7141 /**
7142 * Parse an escaped character within quotes
7143 *
7144 * @access private
7145 */
7146 function value_quote_char()
7147 {
7148 $this->value .= $this->data[$this->position];
7149 $this->state = 'value_quote_next';
7150 $this->position++;
7151 }
7152
7153 /**
7154 * Parse LWS within quotes
7155 *
7156 * @access private
7157 */
7158 function value_linear_whitespace_quote()
7159 {
7160 $this->linear_whitespace();
7161 $this->state = 'value_quote_next';
7162 }
7163
7164 /**
7165 * Parse a CRLF, and see whether we have a further header, or whether we are followed by the body
7166 *
7167 * @access private
7168 */
7169 function end_crlf()
7170 {
7171 $this->name = strtolower($this->name);
7172 $this->value = trim($this->value, "\x20");
7173 if (isset($this->headers[$this->name]))
7174 {
7175 $this->headers[$this->name] .= ', ' . $this->value;
7176 }
7177 else
7178 {
7179 $this->headers[$this->name] = $this->value;
7180 }
7181
7182 if (substr($this->data, $this->position, 2) == "\r\n")
7183 {
7184 $this->body = substr($this->data, $this->position + 2);
7185 $this->state = 'emit';
7186 }
7187 elseif (strspn($this->data, "\r\n", $this->position, 1))
7188 {
7189 $this->body = substr($this->data, $this->position + 1);
7190 $this->state = 'emit';
7191 }
7192 else
7193 {
7194 $this->name = '';
7195 $this->value = '';
7196 $this->state = 'name';
7197 }
7198 }
7199 }
7200
7201 class SimplePie_Cache
7202 {
7203 var $location;
7204 var $filename;
7205 var $extension;
7206 var $name;
7207
7208 function SimplePie_Cache($location, $filename, $extension)
7209 {
7210 $this->location = $location;
7211 $this->filename = rawurlencode($filename);
7212 $this->extension = rawurlencode($extension);
7213 $this->name = "$location/$this->filename.$this->extension";
7214 }
7215
7216 function save($data)
7217 {
7218 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
7219 {
7220 if (function_exists('file_put_contents'))
7221 {
7222 return (bool) file_put_contents($this->name, serialize($data));
7223 }
7224 else
7225 {
7226 $fp = fopen($this->name, 'wb');
7227 if ($fp)
7228 {
7229 fwrite($fp, serialize($data));
7230 fclose($fp);
7231 return true;
7232 }
7233 }
7234 }
7235 return false;
7236 }
7237
7238 function load()
7239 {
7240 if (file_exists($this->name) && is_readable($this->name))
7241 {
7242 if (function_exists('file_get_contents'))
7243 {
7244 return unserialize(file_get_contents($this->name));
7245 }
7246 elseif (($fp = fopen($this->name, 'rb')) !== false)
7247 {
7248 $data = '';
7249 while (!feof($fp))
7250 {
7251 $data .= fread($fp, 8192);
7252 }
7253 fclose($fp);
7254 return unserialize($data);
7255 }
7256 }
7257 return false;
7258 }
7259
7260 function mtime()
7261 {
7262 if (file_exists($this->name))
7263 {
7264 return filemtime($this->name);
7265 }
7266 return false;
7267 }
7268
7269 function touch()
7270 {
7271 if (file_exists($this->name))
7272 {
7273 return touch($this->name);
7274 }
7275 return false;
7276 }
7277
7278 function unlink()
7279 {
7280 if (file_exists($this->name))
7281 {
7282 return unlink($this->name);
7283 }
7284 return false;
7285 }
7286 }
7287
7288 class SimplePie_Misc
7289 {
7290 function time_hms($seconds)
7291 {
7292 $time = '';
7293
7294 $hours = floor($seconds / 3600);
7295 $remainder = $seconds % 3600;
7296 if ($hours > 0)
7297 {
7298 $time .= $hours.':';
7299 }
7300
7301 $minutes = floor($remainder / 60);
7302 $seconds = $remainder % 60;
7303 if ($minutes < 10 && $hours > 0)
7304 {
7305 $minutes = '0' . $minutes;
7306 }
7307 if ($seconds < 10)
7308 {
7309 $seconds = '0' . $seconds;
7310 }
7311
7312 $time .= $minutes.':';
7313 $time .= $seconds;
7314
7315 return $time;
7316 }
7317
7318 function absolutize_url($relative, $base)
7319 {
7320 if ($relative !== '')
7321 {
7322 $relative = SimplePie_Misc::parse_url($relative);
7323 if ($relative['scheme'] !== '')
7324 {
7325 $target = $relative;
7326 }
7327 elseif ($base !== '')
7328 {
7329 $base = SimplePie_Misc::parse_url($base);
7330 $target = SimplePie_Misc::parse_url('');
7331 if ($relative['authority'] !== '')
7332 {
7333 $target = $relative;
7334 $target['scheme'] = $base['scheme'];
7335 }
7336 else
7337 {
7338 $target['scheme'] = $base['scheme'];
7339 $target['authority'] = $base['authority'];
7340 if ($relative['path'] !== '')
7341 {
7342 if (strpos($relative['path'], '/') === 0)
7343 {
7344 $target['path'] = $relative['path'];
7345 }
7346 elseif (($target['path'] = dirname("$base[path].")) == '/')
7347 {
7348 $target['path'] .= $relative['path'];
7349 }
7350 else
7351 {
7352 $target['path'] .= '/' . $relative['path'];
7353 }
7354 if ($relative['query'] !== '')
7355 {
7356 $target['query'] = $relative['query'];
7357 }
7358 }
7359 else
7360 {
7361 if ($base['path'] !== '')
7362 {
7363 $target['path'] = $base['path'];
7364 }
7365 else
7366 {
7367 $target['path'] = '/';
7368 }
7369 if ($relative['query'] !== '')
7370 {
7371 $target['query'] = $relative['query'];
7372 }
7373 elseif ($base['query'] !== '')
7374 {
7375 $target['query'] = $base['query'];
7376 }
7377 }
7378 }
7379 if ($relative['fragment'] !== '')
7380 {
7381 $target['fragment'] = $relative['fragment'];
7382 }
7383 }
7384 else
7385 {
7386 // No base URL, just return the relative URL
7387 $target = $relative;
7388 }
7389 $return = SimplePie_Misc::compress_parse_url($target['scheme'], $target['authority'], $target['path'], $target['query'], $target['fragment']);
7390 }
7391 else
7392 {
7393 $return = $base;
7394 }
7395 $return = SimplePie_Misc::normalize_url($return);
7396 return $return;
7397 }
7398
7399 function remove_dot_segments($input)
7400 {
7401 $output = '';
7402 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input == '.' || $input == '..')
7403 {
7404 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
7405 if (strpos($input, '../') === 0)
7406 {
7407 $input = substr($input, 3);
7408 }
7409 elseif (strpos($input, './') === 0)
7410 {
7411 $input = substr($input, 2);
7412 }
7413 // B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise,
7414 elseif (strpos($input, '/./') === 0)
7415 {
7416 $input = substr_replace($input, '/', 0, 3);
7417 }
7418 elseif ($input == '/.')
7419 {
7420 $input = '/';
7421 }
7422 // C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise,
7423 elseif (strpos($input, '/../') === 0)
7424 {
7425 $input = substr_replace($input, '/', 0, 4);
7426 $output = substr_replace($output, '', strrpos($output, '/'));
7427 }
7428 elseif ($input == '/..')
7429 {
7430 $input = '/';
7431 $output = substr_replace($output, '', strrpos($output, '/'));
7432 }
7433 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
7434 elseif ($input == '.' || $input == '..')
7435 {
7436 $input = '';
7437 }
7438 // E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer
7439 elseif (($pos = strpos($input, '/', 1)) !== false)
7440 {
7441 $output .= substr($input, 0, $pos);
7442 $input = substr_replace($input, '', 0, $pos);
7443 }
7444 else
7445 {
7446 $output .= $input;
7447 $input = '';
7448 }
7449 }
7450 return $output . $input;
7451 }
7452
7453 function get_element($realname, $string)
7454 {
7455 $return = array();
7456 $name = preg_quote($realname, '/');
7457 if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
7458 {
7459 for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
7460 {
7461 $return[$i]['tag'] = $realname;
7462 $return[$i]['full'] = $matches[$i][0][0];
7463 $return[$i]['offset'] = $matches[$i][0][1];
7464 if (strlen($matches[$i][3][0]) <= 2)
7465 {
7466 $return[$i]['self_closing'] = true;
7467 }
7468 else
7469 {
7470 $return[$i]['self_closing'] = false;
7471 $return[$i]['content'] = $matches[$i][4][0];
7472 }
7473 $return[$i]['attribs'] = array();
7474 if (isset($matches[$i][2][0]) && preg_match_all('/((?:[^\s:]+:)?[^\s:]+)(?:\s*=\s*(?:"([^"]*)"|\'([^\']*)\'|([a-z0-9\-._:]*)))?\s/U', ' ' . $matches[$i][2][0] . ' ', $attribs, PREG_SET_ORDER))
7475 {
7476 for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
7477 {
7478 if (count($attribs[$j]) == 2)
7479 {
7480 $attribs[$j][2] = $attribs[$j][1];
7481 }
7482 $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
7483 }
7484 }
7485 }
7486 }
7487 return $return;
7488 }
7489
7490 function element_implode($element)
7491 {
7492 $full = "<$element[tag]";
7493 foreach ($element['attribs'] as $key => $value)
7494 {
7495 $key = strtolower($key);
7496 $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
7497 }
7498 if ($element['self_closing'])
7499 {
7500 $full .= ' />';
7501 }
7502 else
7503 {
7504 $full .= ">$element[content]</$element[tag]>";
7505 }
7506 return $full;
7507 }
7508
7509 function error($message, $level, $file, $line)
7510 {
7511 switch ($level)
7512 {
7513 case E_USER_ERROR:
7514 $note = 'PHP Error';
7515 break;
7516 case E_USER_WARNING:
7517 $note = 'PHP Warning';
7518 break;
7519 case E_USER_NOTICE:
7520 $note = 'PHP Notice';
7521 break;
7522 default:
7523 $note = 'Unknown Error';
7524 break;
7525 }
7526 error_log("$note: $message in $file on line $line", 0);
7527 return $message;
7528 }
7529
7530 /**
7531 * If a file has been cached, retrieve and display it.
7532 *
7533 * This is most useful for caching images (get_favicon(), etc.),
7534 * however it works for all cached files. This WILL NOT display ANY
7535 * file/image/page/whatever, but rather only display what has already
7536 * been cached by SimplePie.
7537 *
7538 * @access public
7539 * @see SimplePie::get_favicon()
7540 * @param str $identifier_url URL that is used to identify the content.
7541 * This may or may not be the actual URL of the live content.
7542 * @param str $cache_location Location of SimplePie's cache. Defaults
7543 * to './cache'.
7544 * @param str $cache_extension The file extension that the file was
7545 * cached with. Defaults to 'spc'.
7546 * @param str $cache_class Name of the cache-handling class being used
7547 * in SimplePie. Defaults to 'SimplePie_Cache', and should be left
7548 * as-is unless you've overloaded the class.
7549 * @param str $cache_name_function Function that converts the filename
7550 * for saving. Defaults to 'md5'.
7551 */
7552 function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
7553 {
7554 $cache =& new $cache_class($cache_location, call_user_func($cache_name_function, $identifier_url), $cache_extension);
7555
7556 if ($file = $cache->load())
7557 {
7558 header('Content-type:' . $file['headers']['content-type']);
7559 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
7560 echo $file['body'];
7561 exit;
7562 }
7563
7564 die('Cached file for ' . $identifier_url . ' cannot be found.');
7565 }
7566
7567 function fix_protocol($url, $http = 1)
7568 {
7569 $url = SimplePie_Misc::normalize_url($url);
7570 $parsed = SimplePie_Misc::parse_url($url);
7571 if ($parsed['scheme'] !== '' && $parsed['scheme'] != 'http' && $parsed['scheme'] != 'https')
7572 {
7573 return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
7574 }
7575
7576 if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
7577 {
7578 return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
7579 }
7580
7581 if ($http == 2 && $parsed['scheme'] !== '')
7582 {
7583 return "feed:$url";
7584 }
7585 elseif ($http == 3 && strtolower($parsed['scheme']) == 'http')
7586 {
7587 return substr_replace($url, 'podcast', 0, 4);
7588 }
7589 elseif ($http == 4 && strtolower($parsed['scheme']) == 'http')
7590 {
7591 return substr_replace($url, 'itpc', 0, 4);
7592 }
7593 else
7594 {
7595 return $url;
7596 }
7597 }
7598
7599 function parse_url($url)
7600 {
7601 static $cache = array();
7602 if (isset($cache[$url]))
7603 {
7604 return $cache[$url];
7605 }
7606 elseif (preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $url, $match))
7607 {
7608 for ($i = count($match); $i <= 9; $i++)
7609 {
7610 $match[$i] = '';
7611 }
7612 return $cache[$url] = array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
7613 }
7614 else
7615 {
7616 return $cache[$url] = array('scheme' => '', 'authority' => '', 'path' => '', 'query' => '', 'fragment' => '');
7617 }
7618 }
7619
7620 function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
7621 {
7622 $return = '';
7623 if ($scheme !== '')
7624 {
7625 $return .= "$scheme:";
7626 }
7627 if ($authority !== '')
7628 {
7629 $return .= "//$authority";
7630 }
7631 if ($path !== '')
7632 {
7633 $return .= $path;
7634 }
7635 if ($query !== '')
7636 {
7637 $return .= "?$query";
7638 }
7639 if ($fragment !== '')
7640 {
7641 $return .= "#$fragment";
7642 }
7643 return $return;
7644 }
7645
7646 function normalize_url($url)
7647 {
7648 $url = preg_replace_callback('/%([0-9A-Fa-f]{2})/', array('SimplePie_Misc', 'percent_encoding_normalization'), $url);
7649 $url = SimplePie_Misc::parse_url($url);
7650 $url['scheme'] = strtolower($url['scheme']);
7651 if ($url['authority'] !== '')
7652 {
7653 $url['authority'] = strtolower($url['authority']);
7654 $url['path'] = SimplePie_Misc::remove_dot_segments($url['path']);
7655 }
7656 return SimplePie_Misc::compress_parse_url($url['scheme'], $url['authority'], $url['path'], $url['query'], $url['fragment']);
7657 }
7658
7659 function percent_encoding_normalization($match)
7660 {
7661 $integer = hexdec($match[1]);
7662 if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer == 0x2D || $integer == 0x2E || $integer == 0x5F || $integer == 0x7E)
7663 {
7664 return chr($integer);
7665 }
7666 else
7667 {
7668 return strtoupper($match[0]);
7669 }
7670 }
7671
7672 /**
7673 * Remove bad UTF-8 bytes
7674 *
7675 * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
7676 * FAQ: Multilingual Forms (modified to include full ASCII range)
7677 *
7678 * @author Geoffrey Sneddon
7679 * @see http://www.w3.org/International/questions/qa-forms-utf-8
7680 * @param string $str String to remove bad UTF-8 bytes from
7681 * @return string UTF-8 string
7682 */
7683 function utf8_bad_replace($str)
7684 {
7685 if (function_exists('iconv'))
7686 {
7687 return iconv('UTF-8', 'UTF-8//IGNORE', $str);
7688 }
7689 elseif (function_exists('mb_convert_encoding'))
7690 {
7691 return mb_convert_encoding($str, 'UTF-8', 'UTF-8');
7692 }
7693 elseif (preg_match_all('/([\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})/', $str, $matches))
7694 {
7695 return implode("\xEF\xBF\xBD", $matches[0]);
7696 }
7697 elseif ($str !== '')
7698 {
7699 return "\xEF\xBF\xBD";
7700 }
7701 else
7702 {
7703 return '';
7704 }
7705 }
7706
7707 function change_encoding($data, $input, $output)
7708 {
7709 $input = SimplePie_Misc::encoding($input);
7710 $output = SimplePie_Misc::encoding($output);
7711
7712 if (function_exists('iconv') && ($return = @iconv($input, "$output//IGNORE", $data)))
7713 {
7714 return $return;
7715 }
7716 elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
7717 {
7718 return $return;
7719 }
7720 elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($data, $output, $input)))
7721 {
7722 return $return;
7723 }
7724 elseif ($input == 'ISO-8859-1' && $output == 'UTF-8')
7725 {
7726 return utf8_encode($data);
7727 }
7728 elseif ($input == 'UTF-8' && $output == 'ISO-8859-1')
7729 {
7730 return utf8_decode($data);
7731 }
7732 return $data;
7733 }
7734
7735 function encoding($encoding)
7736 {
7737 // Character sets are case-insensitive (though we'll return them in the form given in their registration)
7738 switch (strtoupper($encoding))
7739 {
7740 case 'ANSI_X3.4-1968':
7741 case 'ISO-IR-6':
7742 case 'ANSI_X3.4-1986':
7743 case 'ISO_646.IRV:1991':
7744 case 'ASCII':
7745 case 'ISO646-US':
7746 case 'US-ASCII':
7747 case 'US':
7748 case 'IBM367':
7749 case 'CP367':
7750 case 'CSASCII':
7751 return 'US-ASCII';
7752
7753 case 'ISO_8859-1:1987':
7754 case 'ISO-IR-100':
7755 case 'ISO_8859-1':
7756 case 'ISO-8859-1':
7757 case 'LATIN1':
7758 case 'L1':
7759 case 'IBM819':
7760 case 'CP819':
7761 case 'CSISOLATIN1':
7762 return 'ISO-8859-1';
7763
7764 case 'ISO_8859-2:1987':
7765 case 'ISO-IR-101':
7766 case 'ISO_8859-2':
7767 case 'ISO-8859-2':
7768 case 'LATIN2':
7769 case 'L2':
7770 case 'CSISOLATIN2':
7771 return 'ISO-8859-2';
7772
7773 case 'ISO_8859-3:1988':
7774 case 'ISO-IR-109':
7775 case 'ISO_8859-3':
7776 case 'ISO-8859-3':
7777 case 'LATIN3':
7778 case 'L3':
7779 case 'CSISOLATIN3':
7780 return 'ISO-8859-3';
7781
7782 case 'ISO_8859-4:1988':
7783 case 'ISO-IR-110':
7784 case 'ISO_8859-4':
7785 case 'ISO-8859-4':
7786 case 'LATIN4':
7787 case 'L4':
7788 case 'CSISOLATIN4':
7789 return 'ISO-8859-4';
7790
7791 case 'ISO_8859-5:1988':
7792 case 'ISO-IR-144':
7793 case 'ISO_8859-5':
7794 case 'ISO-8859-5':
7795 case 'CYRILLIC':
7796 case 'CSISOLATINCYRILLIC':
7797 return 'ISO-8859-5';
7798
7799 case 'ISO_8859-6:1987':
7800 case 'ISO-IR-127':
7801 case 'ISO_8859-6':
7802 case 'ISO-8859-6':
7803 case 'ECMA-114':
7804 case 'ASMO-708':
7805 case 'ARABIC':
7806 case 'CSISOLATINARABIC':
7807 return 'ISO-8859-6';
7808
7809 case 'ISO_8859-7:1987':
7810 case 'ISO-IR-126':
7811 case 'ISO_8859-7':
7812 case 'ISO-8859-7':
7813 case 'ELOT_928':
7814 case 'ECMA-118':
7815 case 'GREEK':
7816 case 'GREEK8':
7817 case 'CSISOLATINGREEK':
7818 return 'ISO-8859-7';
7819
7820 case 'ISO_8859-8:1988':
7821 case 'ISO-IR-138':
7822 case 'ISO_8859-8':
7823 case 'ISO-8859-8':
7824 case 'HEBREW':
7825 case 'CSISOLATINHEBREW':
7826 return 'ISO-8859-8';
7827
7828 case 'ISO_8859-9:1989':
7829 case 'ISO-IR-148':
7830 case 'ISO_8859-9':
7831 case 'ISO-8859-9':
7832 case 'LATIN5':
7833 case 'L5':
7834 case 'CSISOLATIN5':
7835 return 'ISO-8859-9';
7836
7837 case 'ISO-8859-10':
7838 case 'ISO-IR-157':
7839 case 'L6':
7840 case 'ISO_8859-10:1992':
7841 case 'CSISOLATIN6':
7842 case 'LATIN6':
7843 return 'ISO-8859-10';
7844
7845 case 'ISO_6937-2-ADD':
7846 case 'ISO-IR-142':
7847 case 'CSISOTEXTCOMM':
7848 return 'ISO_6937-2-add';
7849
7850 case 'JIS_X0201':
7851 case 'X0201':
7852 case 'CSHALFWIDTHKATAKANA':
7853 return 'JIS_X0201';
7854
7855 case 'JIS_ENCODING':
7856 case 'CSJISENCODING':
7857 return 'JIS_Encoding';
7858
7859 case 'SHIFT_JIS':
7860 case 'MS_KANJI':
7861 case 'CSSHIFTJIS':
7862 return 'Shift_JIS';
7863
7864 case 'EXTENDED_UNIX_CODE_PACKED_FORMAT_FOR_JAPANESE':
7865 case 'CSEUCPKDFMTJAPANESE':
7866 case 'EUC-JP':
7867 return 'EUC-JP';
7868
7869 case 'EXTENDED_UNIX_CODE_FIXED_WIDTH_FOR_JAPANESE':
7870 case 'CSEUCFIXWIDJAPANESE':
7871 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
7872
7873 case 'BS_4730':
7874 case 'ISO-IR-4':
7875 case 'ISO646-GB':
7876 case 'GB':
7877 case 'UK':
7878 case 'CSISO4UNITEDKINGDOM':
7879 return 'BS_4730';
7880
7881 case 'SEN_850200_C':
7882 case 'ISO-IR-11':
7883 case 'ISO646-SE2':
7884 case 'SE2':
7885 case 'CSISO11SWEDISHFORNAMES':
7886 return 'SEN_850200_C';
7887
7888 case 'IT':
7889 case 'ISO-IR-15':
7890 case 'ISO646-IT':
7891 case 'CSISO15ITALIAN':
7892 return 'IT';
7893
7894 case 'ES':
7895 case 'ISO-IR-17':
7896 case 'ISO646-ES':
7897 case 'CSISO17SPANISH':
7898 return 'ES';
7899
7900 case 'DIN_66003':
7901 case 'ISO-IR-21':
7902 case 'DE':
7903 case 'ISO646-DE':
7904 case 'CSISO21GERMAN':
7905 return 'DIN_66003';
7906
7907 case 'NS_4551-1':
7908 case 'ISO-IR-60':
7909 case 'ISO646-NO':
7910 case 'NO':
7911 case 'CSISO60DANISHNORWEGIAN':
7912 case 'CSISO60NORWEGIAN1':
7913 return 'NS_4551-1';
7914
7915 case 'NF_Z_62-010':
7916 case 'ISO-IR-69':
7917 case 'ISO646-FR':
7918 case 'FR':
7919 case 'CSISO69FRENCH':
7920 return 'NF_Z_62-010';
7921
7922 case 'ISO-10646-UTF-1':
7923 case 'CSISO10646UTF1':
7924 return 'ISO-10646-UTF-1';
7925
7926 case 'ISO_646.BASIC:1983':
7927 case 'REF':
7928 case 'CSISO646BASIC1983':
7929 return 'ISO_646.basic:1983';
7930
7931 case 'INVARIANT':
7932 case 'CSINVARIANT':
7933 return 'INVARIANT';
7934
7935 case 'ISO_646.IRV:1983':
7936 case 'ISO-IR-2':
7937 case 'IRV':
7938 case 'CSISO2INTLREFVERSION':
7939 return 'ISO_646.irv:1983';
7940
7941 case 'NATS-SEFI':
7942 case 'ISO-IR-8-1':
7943 case 'CSNATSSEFI':
7944 return 'NATS-SEFI';
7945
7946 case 'NATS-SEFI-ADD':
7947 case 'ISO-IR-8-2':
7948 case 'CSNATSSEFIADD':
7949 return 'NATS-SEFI-ADD';
7950
7951 case 'NATS-DANO':
7952 case 'ISO-IR-9-1':
7953 case 'CSNATSDANO':
7954 return 'NATS-DANO';
7955
7956 case 'NATS-DANO-ADD':
7957 case 'ISO-IR-9-2':
7958 case 'CSNATSDANOADD':
7959 return 'NATS-DANO-ADD';
7960
7961 case 'SEN_850200_B':
7962 case 'ISO-IR-10':
7963 case 'FI':
7964 case 'ISO646-FI':
7965 case 'ISO646-SE':
7966 case 'SE':
7967 case 'CSISO10SWEDISH':
7968 return 'SEN_850200_B';
7969
7970 case 'KS_C_5601-1987':
7971 case 'ISO-IR-149':
7972 case 'KS_C_5601-1989':
7973 case 'KSC_5601':
7974 case 'KOREAN':
7975 case 'CSKSC56011987':
7976 return 'KS_C_5601-1987';
7977
7978 case 'ISO-2022-KR':
7979 case 'CSISO2022KR':
7980 return 'ISO-2022-KR';
7981
7982 case 'EUC-KR':
7983 case 'CSEUCKR':
7984 return 'EUC-KR';
7985
7986 case 'ISO-2022-JP':
7987 case 'CSISO2022JP':
7988 return 'ISO-2022-JP';
7989
7990 case 'ISO-2022-JP-2':
7991 case 'CSISO2022JP2':
7992 return 'ISO-2022-JP-2';
7993
7994 case 'JIS_C6220-1969-JP':
7995 case 'JIS_C6220-1969':
7996 case 'ISO-IR-13':
7997 case 'KATAKANA':
7998 case 'X0201-7':
7999 case 'CSISO13JISC6220JP':
8000 return 'JIS_C6220-1969-jp';
8001
8002 case 'JIS_C6220-1969-RO':
8003 case 'ISO-IR-14':
8004 case 'JP':
8005 case 'ISO646-JP':
8006 case 'CSISO14JISC6220RO':
8007 return 'JIS_C6220-1969-ro';
8008
8009 case 'PT':
8010 case 'ISO-IR-16':
8011 case 'ISO646-PT':
8012 case 'CSISO16PORTUGUESE':
8013 return 'PT';
8014
8015 case 'GREEK7-OLD':
8016 case 'ISO-IR-18':
8017 case 'CSISO18GREEK7OLD':
8018 return 'greek7-old';
8019
8020 case 'LATIN-GREEK':
8021 case 'ISO-IR-19':
8022 case 'CSISO19LATINGREEK':
8023 return 'latin-greek';
8024
8025 case 'NF_Z_62-010_(1973)':
8026 case 'ISO-IR-25':
8027 case 'ISO646-FR1':
8028 case 'CSISO25FRENCH':
8029 return 'NF_Z_62-010_(1973)';
8030
8031 case 'LATIN-GREEK-1':
8032 case 'ISO-IR-27':
8033 case 'CSISO27LATINGREEK1':
8034 return 'Latin-greek-1';
8035
8036 case 'ISO_5427':
8037 case 'ISO-IR-37':
8038 case 'CSISO5427CYRILLIC':
8039 return 'ISO_5427';
8040
8041 case 'JIS_C6226-1978':
8042 case 'ISO-IR-42':
8043 case 'CSISO42JISC62261978':
8044 return 'JIS_C6226-1978';
8045
8046 case 'BS_VIEWDATA':
8047 case 'ISO-IR-47':
8048 case 'CSISO47BSVIEWDATA':
8049 return 'BS_viewdata';
8050
8051 case 'INIS':
8052 case 'ISO-IR-49':
8053 case 'CSISO49INIS':
8054 return 'INIS';
8055
8056 case 'INIS-8':
8057 case 'ISO-IR-50':
8058 case 'CSISO50INIS8':
8059 return 'INIS-8';
8060
8061 case 'INIS-CYRILLIC':
8062 case 'ISO-IR-51':
8063 case 'CSISO51INISCYRILLIC':
8064 return 'INIS-cyrillic';
8065
8066 case 'ISO_5427:1981':
8067 case 'ISO-IR-54':
8068 case 'ISO5427CYRILLIC1981':
8069 return 'ISO_5427:1981';
8070
8071 case 'ISO_5428:1980':
8072 case 'ISO-IR-55':
8073 case 'CSISO5428GREEK':
8074 return 'ISO_5428:1980';
8075
8076 case 'GB_1988-80':
8077 case 'ISO-IR-57':
8078 case 'CN':
8079 case 'ISO646-CN':
8080 case 'CSISO57GB1988':
8081 return 'GB_1988-80';
8082
8083 case 'GB_2312-80':
8084 case 'ISO-IR-58':
8085 case 'CHINESE':
8086 case 'CSISO58GB231280':
8087 return 'GB_2312-80';
8088
8089 case 'NS_4551-2':
8090 case 'ISO646-NO2':
8091 case 'ISO-IR-61':
8092 case 'NO2':
8093 case 'CSISO61NORWEGIAN2':
8094 return 'NS_4551-2';
8095
8096 case 'VIDEOTEX-SUPPL':
8097 case 'ISO-IR-70':
8098 case 'CSISO70VIDEOTEXSUPP1':
8099 return 'videotex-suppl';
8100
8101 case 'PT2':
8102 case 'ISO-IR-84':
8103 case 'ISO646-PT2':
8104 case 'CSISO84PORTUGUESE2':
8105 return 'PT2';
8106
8107 case 'ES2':
8108 case 'ISO-IR-85':
8109 case 'ISO646-ES2':
8110 case 'CSISO85SPANISH2':
8111 return 'ES2';
8112
8113 case 'MSZ_7795.3':
8114 case 'ISO-IR-86':
8115 case 'ISO646-HU':
8116 case 'HU':
8117 case 'CSISO86HUNGARIAN':
8118 return 'MSZ_7795.3';
8119
8120 case 'JIS_C6226-1983':
8121 case 'ISO-IR-87':
8122 case 'X0208':
8123 case 'JIS_X0208-1983':
8124 case 'CSISO87JISX0208':
8125 return 'JIS_C6226-1983';
8126
8127 case 'GREEK7':
8128 case 'ISO-IR-88':
8129 case 'CSISO88GREEK7':
8130 return 'greek7';
8131
8132 case 'ASMO_449':
8133 case 'ISO_9036':
8134 case 'ARABIC7':
8135 case 'ISO-IR-89':
8136 case 'CSISO89ASMO449':
8137 return 'ASMO_449';
8138
8139 case 'ISO-IR-90':
8140 case 'CSISO90':
8141 return 'iso-ir-90';
8142
8143 case 'JIS_C6229-1984-A':
8144 case 'ISO-IR-91':
8145 case 'JP-OCR-A':
8146 case 'CSISO91JISC62291984A':
8147 return 'JIS_C6229-1984-a';
8148
8149 case 'JIS_C6229-1984-B':
8150 case 'ISO-IR-92':
8151 case 'ISO646-JP-OCR-B':
8152 case 'JP-OCR-B':
8153 case 'CSISO92JISC62991984B':
8154 return 'JIS_C6229-1984-b';
8155
8156 case 'JIS_C6229-1984-B-ADD':
8157 case 'ISO-IR-93':
8158 case 'JP-OCR-B-ADD':
8159 case 'CSISO93JIS62291984BADD':
8160 return 'JIS_C6229-1984-b-add';
8161
8162 case 'JIS_C6229-1984-HAND':
8163 case 'ISO-IR-94':
8164 case 'JP-OCR-HAND':
8165 case 'CSISO94JIS62291984HAND':
8166 return 'JIS_C6229-1984-hand';
8167
8168 case 'JIS_C6229-1984-HAND-ADD':
8169 case 'ISO-IR-95':
8170 case 'JP-OCR-HAND-ADD':
8171 case 'CSISO95JIS62291984HANDADD':
8172 return 'JIS_C6229-1984-hand-add';
8173
8174 case 'JIS_C6229-1984-KANA':
8175 case 'ISO-IR-96':
8176 case 'CSISO96JISC62291984KANA':
8177 return 'JIS_C6229-1984-kana';
8178
8179 case 'ISO_2033-1983':
8180 case 'ISO-IR-98':
8181 case 'E13B':
8182 case 'CSISO2033':
8183 return 'ISO_2033-1983';
8184
8185 case 'ANSI_X3.110-1983':
8186 case 'ISO-IR-99':
8187 case 'CSA_T500-1983':
8188 case 'NAPLPS':
8189 case 'CSISO99NAPLPS':
8190 return 'ANSI_X3.110-1983';
8191
8192 case 'T.61-7BIT':
8193 case 'ISO-IR-102':
8194 case 'CSISO102T617BIT':
8195 return 'T.61-7bit';
8196
8197 case 'T.61-8BIT':
8198 case 'T.61':
8199 case 'ISO-IR-103':
8200 case 'CSISO103T618BIT':
8201 return 'T.61-8bit';
8202
8203 case 'ECMA-CYRILLIC':
8204 case 'ISO-IR-111':
8205 case 'KOI8-E':
8206 case 'CSISO111ECMACYRILLIC':
8207 return 'ECMA-cyrillic';
8208
8209 case 'CSA_Z243.4-1985-1':
8210 case 'ISO-IR-121':
8211 case 'ISO646-CA':
8212 case 'CSA7-1':
8213 case 'CA':
8214 case 'CSISO121CANADIAN1':
8215 return 'CSA_Z243.4-1985-1';
8216
8217 case 'CSA_Z243.4-1985-2':
8218 case 'ISO-IR-122':
8219 case 'ISO646-CA2':
8220 case 'CSA7-2':
8221 case 'CSISO122CANADIAN2':
8222 return 'CSA_Z243.4-1985-2';
8223
8224 case 'CSA_Z243.4-1985-GR':
8225 case 'ISO-IR-123':
8226 case 'CSISO123CSAZ24341985GR':
8227 return 'CSA_Z243.4-1985-gr';
8228
8229 case 'ISO_8859-6-E':
8230 case 'CSISO88596E':
8231 case 'ISO-8859-6-E':
8232 return 'ISO-8859-6-E';
8233
8234 case 'ISO_8859-6-I':
8235 case 'CSISO88596I':
8236 case 'ISO-8859-6-I':
8237 return 'ISO-8859-6-I';
8238
8239 case 'T.101-G2':
8240 case 'ISO-IR-128':
8241 case 'CSISO128T101G2':
8242 return 'T.101-G2';
8243
8244 case 'ISO_8859-8-E':
8245 case 'CSISO88598E':
8246 case 'ISO-8859-8-E':
8247 return 'ISO-8859-8-E';
8248
8249 case 'ISO_8859-8-I':
8250 case 'CSISO88598I':
8251 case 'ISO-8859-8-I':
8252 return 'ISO-8859-8-I';
8253
8254 case 'CSN_369103':
8255 case 'ISO-IR-139':
8256 case 'CSISO139CSN369103':
8257 return 'CSN_369103';
8258
8259 case 'JUS_I.B1.002':
8260 case 'ISO-IR-141':
8261 case 'ISO646-YU':
8262 case 'JS':
8263 case 'YU':
8264 case 'CSISO141JUSIB1002':
8265 return 'JUS_I.B1.002';
8266
8267 case 'IEC_P27-1':
8268 case 'ISO-IR-143':
8269 case 'CSISO143IECP271':
8270 return 'IEC_P27-1';
8271
8272 case 'JUS_I.B1.003-SERB':
8273 case 'ISO-IR-146':
8274 case 'SERBIAN':
8275 case 'CSISO146SERBIAN':
8276 return 'JUS_I.B1.003-serb';
8277
8278 case 'JUS_I.B1.003-MAC':
8279 case 'MACEDONIAN':
8280 case 'ISO-IR-147':
8281 case 'CSISO147MACEDONIAN':
8282 return 'JUS_I.B1.003-mac';
8283
8284 case 'GREEK-CCITT':
8285 case 'ISO-IR-150':
8286 case 'CSISO150':
8287 case 'CSISO150GREEKCCITT':
8288 return 'greek-ccitt';
8289
8290 case 'NC_NC00-10:81':
8291 case 'CUBA':
8292 case 'ISO-IR-151':
8293 case 'ISO646-CU':
8294 case 'CSISO151CUBA':
8295 return 'NC_NC00-10:81';
8296
8297 case 'ISO_6937-2-25':
8298 case 'ISO-IR-152':
8299 case 'CSISO6937ADD':
8300 return 'ISO_6937-2-25';
8301
8302 case 'GOST_19768-74':
8303 case 'ST_SEV_358-88':
8304 case 'ISO-IR-153':
8305 case 'CSISO153GOST1976874':
8306 return 'GOST_19768-74';
8307
8308 case 'ISO_8859-SUPP':
8309 case 'ISO-IR-154':
8310 case 'LATIN1-2-5':
8311 case 'CSISO8859SUPP':
8312 return 'ISO_8859-supp';
8313
8314 case 'ISO_10367-BOX':
8315 case 'ISO-IR-155':
8316 case 'CSISO10367BOX':
8317 return 'ISO_10367-box';
8318
8319 case 'LATIN-LAP':
8320 case 'LAP':
8321 case 'ISO-IR-158':
8322 case 'CSISO158LAP':
8323 return 'latin-lap';
8324
8325 case 'JIS_X0212-1990':
8326 case 'X0212':
8327 case 'ISO-IR-159':
8328 case 'CSISO159JISX02121990':
8329 return 'JIS_X0212-1990';
8330
8331 case 'DS_2089':
8332 case 'DS2089':
8333 case 'ISO646-DK':
8334 case 'DK':
8335 case 'CSISO646DANISH':
8336 return 'DS_2089';
8337
8338 case 'US-DK':
8339 case 'CSUSDK':
8340 return 'us-dk';
8341
8342 case 'DK-US':
8343 case 'CSDKUS':
8344 return 'dk-us';
8345
8346 case 'KSC5636':
8347 case 'ISO646-KR':
8348 case 'CSKSC5636':
8349 return 'KSC5636';
8350
8351 case 'UNICODE-1-1-UTF-7':
8352 case 'CSUNICODE11UTF7':
8353 return 'UNICODE-1-1-UTF-7';
8354
8355 case 'ISO-2022-CN':
8356 return 'ISO-2022-CN';
8357
8358 case 'ISO-2022-CN-EXT':
8359 return 'ISO-2022-CN-EXT';
8360
8361 case 'UTF-8':
8362 return 'UTF-8';
8363
8364 case 'ISO-8859-13':
8365 return 'ISO-8859-13';
8366
8367 case 'ISO-8859-14':
8368 case 'ISO-IR-199':
8369 case 'ISO_8859-14:1998':
8370 case 'ISO_8859-14':
8371 case 'LATIN8':
8372 case 'ISO-CELTIC':
8373 case 'L8':
8374 return 'ISO-8859-14';
8375
8376 case 'ISO-8859-15':
8377 case 'ISO_8859-15':
8378 case 'LATIN-9':
8379 return 'ISO-8859-15';
8380
8381 case 'ISO-8859-16':
8382 case 'ISO-IR-226':
8383 case 'ISO_8859-16:2001':
8384 case 'ISO_8859-16':
8385 case 'LATIN10':
8386 case 'L10':
8387 return 'ISO-8859-16';
8388
8389 case 'GBK':
8390 case 'CP936':
8391 case 'MS936':
8392 case 'WINDOWS-936':
8393 return 'GBK';
8394
8395 case 'GB18030':
8396 return 'GB18030';
8397
8398 case 'OSD_EBCDIC_DF04_15':
8399 return 'OSD_EBCDIC_DF04_15';
8400
8401 case 'OSD_EBCDIC_DF03_IRV':
8402 return 'OSD_EBCDIC_DF03_IRV';
8403
8404 case 'OSD_EBCDIC_DF04_1':
8405 return 'OSD_EBCDIC_DF04_1';
8406
8407 case 'ISO-11548-1':
8408 case 'ISO_11548-1':
8409 case 'ISO_TR_11548-1':
8410 case 'CSISO115481':
8411 return 'ISO-11548-1';
8412
8413 case 'KZ-1048':
8414 case 'STRK1048-2002':
8415 case 'RK1048':
8416 case 'CSKZ1048':
8417 return 'KZ-1048';
8418
8419 case 'ISO-10646-UCS-2':
8420 case 'CSUNICODE':
8421 return 'ISO-10646-UCS-2';
8422
8423 case 'ISO-10646-UCS-4':
8424 case 'CSUCS4':
8425 return 'ISO-10646-UCS-4';
8426
8427 case 'ISO-10646-UCS-BASIC':
8428 case 'CSUNICODEASCII':
8429 return 'ISO-10646-UCS-Basic';
8430
8431 case 'ISO-10646-UNICODE-LATIN1':
8432 case 'CSUNICODELATIN1':
8433 case 'ISO-10646':
8434 return 'ISO-10646-Unicode-Latin1';
8435
8436 case 'ISO-10646-J-1':
8437 return 'ISO-10646-J-1';
8438
8439 case 'ISO-UNICODE-IBM-1261':
8440 case 'CSUNICODEIBM1261':
8441 return 'ISO-Unicode-IBM-1261';
8442
8443 case 'ISO-UNICODE-IBM-1268':
8444 case 'CSUNICODEIBM1268':
8445 return 'ISO-Unicode-IBM-1268';
8446
8447 case 'ISO-UNICODE-IBM-1276':
8448 case 'CSUNICODEIBM1276':
8449 return 'ISO-Unicode-IBM-1276';
8450
8451 case 'ISO-UNICODE-IBM-1264':
8452 case 'CSUNICODEIBM1264':
8453 return 'ISO-Unicode-IBM-1264';
8454
8455 case 'ISO-UNICODE-IBM-1265':
8456 case 'CSUNICODEIBM1265':
8457 return 'ISO-Unicode-IBM-1265';
8458
8459 case 'UNICODE-1-1':
8460 case 'CSUNICODE11':
8461 return 'UNICODE-1-1';
8462
8463 case 'SCSU':
8464 return 'SCSU';
8465
8466 case 'UTF-7':
8467 return 'UTF-7';
8468
8469 case 'UTF-16BE':
8470 return 'UTF-16BE';
8471
8472 case 'UTF-16LE':
8473 return 'UTF-16LE';
8474
8475 case 'UTF-16':
8476 return 'UTF-16';
8477
8478 case 'CESU-8':
8479 case 'CSCESU-8':
8480 return 'CESU-8';
8481
8482 case 'UTF-32':
8483 return 'UTF-32';
8484
8485 case 'UTF-32BE':
8486 return 'UTF-32BE';
8487
8488 case 'UTF-32LE':
8489 return 'UTF-32LE';
8490
8491 case 'BOCU-1':
8492 case 'CSBOCU-1':
8493 return 'BOCU-1';
8494
8495 case 'ISO-8859-1-WINDOWS-3.0-LATIN-1':
8496 case 'CSWINDOWS30LATIN1':
8497 return 'ISO-8859-1-Windows-3.0-Latin-1';
8498
8499 case 'ISO-8859-1-WINDOWS-3.1-LATIN-1':
8500 case 'CSWINDOWS31LATIN1':
8501 return 'ISO-8859-1-Windows-3.1-Latin-1';
8502
8503 case 'ISO-8859-2-WINDOWS-LATIN-2':
8504 case 'CSWINDOWS31LATIN2':
8505 return 'ISO-8859-2-Windows-Latin-2';
8506
8507 case 'ISO-8859-9-WINDOWS-LATIN-5':
8508 case 'CSWINDOWS31LATIN5':
8509 return 'ISO-8859-9-Windows-Latin-5';
8510
8511 case 'HP-ROMAN8':
8512 case 'ROMAN8':
8513 case 'R8':
8514 case 'CSHPROMAN8':
8515 return 'hp-roman8';
8516
8517 case 'ADOBE-STANDARD-ENCODING':
8518 case 'CSADOBESTANDARDENCODING':
8519 return 'Adobe-Standard-Encoding';
8520
8521 case 'VENTURA-US':
8522 case 'CSVENTURAUS':
8523 return 'Ventura-US';
8524
8525 case 'VENTURA-INTERNATIONAL':
8526 case 'CSVENTURAINTERNATIONAL':
8527 return 'Ventura-International';
8528
8529 case 'DEC-MCS':
8530 case 'DEC':
8531 case 'CSDECMCS':
8532 return 'DEC-MCS';
8533
8534 case 'IBM850':
8535 case 'CP850':
8536 case '850':
8537 case 'CSPC850MULTILINGUAL':
8538 return 'IBM850';
8539
8540 case 'PC8-DANISH-NORWEGIAN':
8541 case 'CSPC8DANISHNORWEGIAN':
8542 return 'PC8-Danish-Norwegian';
8543
8544 case 'IBM862':
8545 case 'CP862':
8546 case '862':
8547 case 'CSPC862LATINHEBREW':
8548 return 'IBM862';
8549
8550 case 'PC8-TURKISH':
8551 case 'CSPC8TURKISH':
8552 return 'PC8-Turkish';
8553
8554 case 'IBM-SYMBOLS':
8555 case 'CSIBMSYMBOLS':
8556 return 'IBM-Symbols';
8557
8558 case 'IBM-THAI':
8559 case 'CSIBMTHAI':
8560 return 'IBM-Thai';
8561
8562 case 'HP-LEGAL':
8563 case 'CSHPLEGAL':
8564 return 'HP-Legal';
8565
8566 case 'HP-PI-FONT':
8567 case 'CSHPPIFONT':
8568 return 'HP-Pi-font';
8569
8570 case 'HP-MATH8':
8571 case 'CSHPMATH8':
8572 return 'HP-Math8';
8573
8574 case 'ADOBE-SYMBOL-ENCODING':
8575 case 'CSHPPSMATH':
8576 return 'Adobe-Symbol-Encoding';
8577
8578 case 'HP-DESKTOP':
8579 case 'CSHPDESKTOP':
8580 return 'HP-DeskTop';
8581
8582 case 'VENTURA-MATH':
8583 case 'CSVENTURAMATH':
8584 return 'Ventura-Math';
8585
8586 case 'MICROSOFT-PUBLISHING':
8587 case 'CSMICROSOFTPUBLISHING':
8588 return 'Microsoft-Publishing';
8589
8590 case 'WINDOWS-31J':
8591 case 'CSWINDOWS31J':
8592 return 'Windows-31J';
8593
8594 case 'GB2312':
8595 case 'CSGB2312':
8596 return 'GB2312';
8597
8598 case 'BIG5':
8599 case 'CSBIG5':
8600 return 'Big5';
8601
8602 case 'MACINTOSH':
8603 case 'MAC':
8604 case 'CSMACINTOSH':
8605 return 'macintosh';
8606
8607 case 'IBM037':
8608 case 'CP037':
8609 case 'EBCDIC-CP-US':
8610 case 'EBCDIC-CP-CA':
8611 case 'EBCDIC-CP-WT':
8612 case 'EBCDIC-CP-NL':
8613 case 'CSIBM037':
8614 return 'IBM037';
8615
8616 case 'IBM038':
8617 case 'EBCDIC-INT':
8618 case 'CP038':
8619 case 'CSIBM038':
8620 return 'IBM038';
8621
8622 case 'IBM273':
8623 case 'CP273':
8624 case 'CSIBM273':
8625 return 'IBM273';
8626
8627 case 'IBM274':
8628 case 'EBCDIC-BE':
8629 case 'CP274':
8630 case 'CSIBM274':
8631 return 'IBM274';
8632
8633 case 'IBM275':
8634 case 'EBCDIC-BR':
8635 case 'CP275':
8636 case 'CSIBM275':
8637 return 'IBM275';
8638
8639 case 'IBM277':
8640 case 'EBCDIC-CP-DK':
8641 case 'EBCDIC-CP-NO':
8642 case 'CSIBM277':
8643 return 'IBM277';
8644
8645 case 'IBM278':
8646 case 'CP278':
8647 case 'EBCDIC-CP-FI':
8648 case 'EBCDIC-CP-SE':
8649 case 'CSIBM278':
8650 return 'IBM278';
8651
8652 case 'IBM280':
8653 case 'CP280':
8654 case 'EBCDIC-CP-IT':
8655 case 'CSIBM280':
8656 return 'IBM280';
8657
8658 case 'IBM281':
8659 case 'EBCDIC-JP-E':
8660 case 'CP281':
8661 case 'CSIBM281':
8662 return 'IBM281';
8663
8664 case 'IBM284':
8665 case 'CP284':
8666 case 'EBCDIC-CP-ES':
8667 case 'CSIBM284':
8668 return 'IBM284';
8669
8670 case 'IBM285':
8671 case 'CP285':
8672 case 'EBCDIC-CP-GB':
8673 case 'CSIBM285':
8674 return 'IBM285';
8675
8676 case 'IBM290':
8677 case 'CP290':
8678 case 'EBCDIC-JP-KANA':
8679 case 'CSIBM290':
8680 return 'IBM290';
8681
8682 case 'IBM297':
8683 case 'CP297':
8684 case 'EBCDIC-CP-FR':
8685 case 'CSIBM297':
8686 return 'IBM297';
8687
8688 case 'IBM420':
8689 case 'CP420':
8690 case 'EBCDIC-CP-AR1':
8691 case 'CSIBM420':
8692 return 'IBM420';
8693
8694 case 'IBM423':
8695 case 'CP423':
8696 case 'EBCDIC-CP-GR':
8697 case 'CSIBM423':
8698 return 'IBM423';
8699
8700 case 'IBM424':
8701 case 'CP424':
8702 case 'EBCDIC-CP-HE':
8703 case 'CSIBM424':
8704 return 'IBM424';
8705
8706 case 'IBM437':
8707 case 'CP437':
8708 case '437':
8709 case 'CSPC8CODEPAGE437':
8710 return 'IBM437';
8711
8712 case 'IBM500':
8713 case 'CP500':
8714 case 'EBCDIC-CP-BE':
8715 case 'EBCDIC-CP-CH':
8716 case 'CSIBM500':
8717 return 'IBM500';
8718
8719 case 'IBM851':
8720 case 'CP851':
8721 case '851':
8722 case 'CSIBM851':
8723 return 'IBM851';
8724
8725 case 'IBM852':
8726 case 'CP852':
8727 case '852':
8728 case 'CSPCP852':
8729 return 'IBM852';
8730
8731 case 'IBM855':
8732 case 'CP855':
8733 case '855':
8734 case 'CSIBM855':
8735 return 'IBM855';
8736
8737 case 'IBM857':
8738 case 'CP857':
8739 case '857':
8740 case 'CSIBM857':
8741 return 'IBM857';
8742
8743 case 'IBM860':
8744 case 'CP860':
8745 case '860':
8746 case 'CSIBM860':
8747 return 'IBM860';
8748
8749 case 'IBM861':
8750 case 'CP861':
8751 case '861':
8752 case 'CP-IS':
8753 case 'CSIBM861':
8754 return 'IBM861';
8755
8756 case 'IBM863':
8757 case 'CP863':
8758 case '863':
8759 case 'CSIBM863':
8760 return 'IBM863';
8761
8762 case 'IBM864':
8763 case 'CP864':
8764 case 'CSIBM864':
8765 return 'IBM864';
8766
8767 case 'IBM865':
8768 case 'CP865':
8769 case '865':
8770 case 'CSIBM865':
8771 return 'IBM865';
8772
8773 case 'IBM868':
8774 case 'CP868':
8775 case 'CP-AR':
8776 case 'CSIBM868':
8777 return 'IBM868';
8778
8779 case 'IBM869':
8780 case 'CP869':
8781 case '869':
8782 case 'CP-GR':
8783 case 'CSIBM869':
8784 return 'IBM869';
8785
8786 case 'IBM870':
8787 case 'CP870':
8788 case 'EBCDIC-CP-ROECE':
8789 case 'EBCDIC-CP-YU':
8790 case 'CSIBM870':
8791 return 'IBM870';
8792
8793 case 'IBM871':
8794 case 'CP871':
8795 case 'EBCDIC-CP-IS':
8796 case 'CSIBM871':
8797 return 'IBM871';
8798
8799 case 'IBM880':
8800 case 'CP880':
8801 case 'EBCDIC-CYRILLIC':
8802 case 'CSIBM880':
8803 return 'IBM880';
8804
8805 case 'IBM891':
8806 case 'CP891':
8807 case 'CSIBM891':
8808 return 'IBM891';
8809
8810 case 'IBM903':
8811 case 'CP903':
8812 case 'CSIBM903':
8813 return 'IBM903';
8814
8815 case 'IBM904':
8816 case 'CP904':
8817 case '904':
8818 case 'CSIBBM904':
8819 return 'IBM904';
8820
8821 case 'IBM905':
8822 case 'CP905':
8823 case 'EBCDIC-CP-TR':
8824 case 'CSIBM905':
8825 return 'IBM905';
8826
8827 case 'IBM918':
8828 case 'CP918':
8829 case 'EBCDIC-CP-AR2':
8830 case 'CSIBM918':
8831 return 'IBM918';
8832
8833 case 'IBM1026':
8834 case 'CP1026':
8835 case 'CSIBM1026':
8836 return 'IBM1026';
8837
8838 case 'EBCDIC-AT-DE':
8839 case 'CSIBMEBCDICATDE':
8840 return 'EBCDIC-AT-DE';
8841
8842 case 'EBCDIC-AT-DE-A':
8843 case 'CSEBCDICATDEA':
8844 return 'EBCDIC-AT-DE-A';
8845
8846 case 'EBCDIC-CA-FR':
8847 case 'CSEBCDICCAFR':
8848 return 'EBCDIC-CA-FR';
8849
8850 case 'EBCDIC-DK-NO':
8851 case 'CSEBCDICDKNO':
8852 return 'EBCDIC-DK-NO';
8853
8854 case 'EBCDIC-DK-NO-A':
8855 case 'CSEBCDICDKNOA':
8856 return 'EBCDIC-DK-NO-A';
8857
8858 case 'EBCDIC-FI-SE':
8859 case 'CSEBCDICFISE':
8860 return 'EBCDIC-FI-SE';
8861
8862 case 'EBCDIC-FI-SE-A':
8863 case 'CSEBCDICFISEA':
8864 return 'EBCDIC-FI-SE-A';
8865
8866 case 'EBCDIC-FR':
8867 case 'CSEBCDICFR':
8868 return 'EBCDIC-FR';
8869
8870 case 'EBCDIC-IT':
8871 case 'CSEBCDICIT':
8872 return 'EBCDIC-IT';
8873
8874 case 'EBCDIC-PT':
8875 case 'CSEBCDICPT':
8876 return 'EBCDIC-PT';
8877
8878 case 'EBCDIC-ES':
8879 case 'CSEBCDICES':
8880 return 'EBCDIC-ES';
8881
8882 case 'EBCDIC-ES-A':
8883 case 'CSEBCDICESA':
8884 return 'EBCDIC-ES-A';
8885
8886 case 'EBCDIC-ES-S':
8887 case 'CSEBCDICESS':
8888 return 'EBCDIC-ES-S';
8889
8890 case 'EBCDIC-UK':
8891 case 'CSEBCDICUK':
8892 return 'EBCDIC-UK';
8893
8894 case 'EBCDIC-US':
8895 case 'CSEBCDICUS':
8896 return 'EBCDIC-US';
8897
8898 case 'UNKNOWN-8BIT':
8899 case 'CSUNKNOWN8BIT':
8900 return 'UNKNOWN-8BIT';
8901
8902 case 'MNEMONIC':
8903 case 'CSMNEMONIC':
8904 return 'MNEMONIC';
8905
8906 case 'MNEM':
8907 case 'CSMNEM':
8908 return 'MNEM';
8909
8910 case 'VISCII':
8911 case 'CSVISCII':
8912 return 'VISCII';
8913
8914 case 'VIQR':
8915 case 'CSVIQR':
8916 return 'VIQR';
8917
8918 case 'KOI8-R':
8919 case 'CSKOI8R':
8920 return 'KOI8-R';
8921
8922 case 'HZ-GB-2312':
8923 return 'HZ-GB-2312';
8924
8925 case 'IBM866':
8926 case 'CP866':
8927 case '866':
8928 case 'CSIBM866':
8929 return 'IBM866';
8930
8931 case 'IBM775':
8932 case 'CP775':
8933 case 'CSPC775BALTIC':
8934 return 'IBM775';
8935
8936 case 'KOI8-U':
8937 return 'KOI8-U';
8938
8939 case 'IBM00858':
8940 case 'CCSID00858':
8941 case 'CP00858':
8942 case 'PC-MULTILINGUAL-850+EURO':
8943 return 'IBM00858';
8944
8945 case 'IBM00924':
8946 case 'CCSID00924':
8947 case 'CP00924':
8948 case 'EBCDIC-LATIN9--EURO':
8949 return 'IBM00924';
8950
8951 case 'IBM01140':
8952 case 'CCSID01140':
8953 case 'CP01140':
8954 case 'EBCDIC-US-37+EURO':
8955 return 'IBM01140';
8956
8957 case 'IBM01141':
8958 case 'CCSID01141':
8959 case 'CP01141':
8960 case 'EBCDIC-DE-273+EURO':
8961 return 'IBM01141';
8962
8963 case 'IBM01142':
8964 case 'CCSID01142':
8965 case 'CP01142':
8966 case 'EBCDIC-DK-277+EURO':
8967 case 'EBCDIC-NO-277+EURO':
8968 return 'IBM01142';
8969
8970 case 'IBM01143':
8971 case 'CCSID01143':
8972 case 'CP01143':
8973 case 'EBCDIC-FI-278+EURO':
8974 case 'EBCDIC-SE-278+EURO':
8975 return 'IBM01143';
8976
8977 case 'IBM01144':
8978 case 'CCSID01144':
8979 case 'CP01144':
8980 case 'EBCDIC-IT-280+EURO':
8981 return 'IBM01144';
8982
8983 case 'IBM01145':
8984 case 'CCSID01145':
8985 case 'CP01145':
8986 case 'EBCDIC-ES-284+EURO':
8987 return 'IBM01145';
8988
8989 case 'IBM01146':
8990 case 'CCSID01146':
8991 case 'CP01146':
8992 case 'EBCDIC-GB-285+EURO':
8993 return 'IBM01146';
8994
8995 case 'IBM01147':
8996 case 'CCSID01147':
8997 case 'CP01147':
8998 case 'EBCDIC-FR-297+EURO':
8999 return 'IBM01147';
9000
9001 case 'IBM01148':
9002 case 'CCSID01148':
9003 case 'CP01148':
9004 case 'EBCDIC-INTERNATIONAL-500+EURO':
9005 return 'IBM01148';
9006
9007 case 'IBM01149':
9008 case 'CCSID01149':
9009 case 'CP01149':
9010 case 'EBCDIC-IS-871+EURO':
9011 return 'IBM01149';
9012
9013 case 'BIG5-HKSCS':
9014 return 'Big5-HKSCS';
9015
9016 case 'IBM1047':
9017 case 'IBM-1047':
9018 return 'IBM1047';
9019
9020 case 'PTCP154':
9021 case 'CSPTCP154':
9022 case 'PT154':
9023 case 'CP154':
9024 case 'CYRILLIC-ASIAN':
9025 return 'PTCP154';
9026
9027 case 'AMIGA-1251':
9028 case 'AMI1251':
9029 case 'AMIGA1251':
9030 case 'AMI-1251':
9031 return 'Amiga-1251';
9032
9033 case 'KOI7-SWITCHED':
9034 return 'KOI7-switched';
9035
9036 case 'BRF':
9037 case 'CSBRF':
9038 return 'BRF';
9039
9040 case 'TSCII':
9041 case 'CSTSCII':
9042 return 'TSCII';
9043
9044 case 'WINDOWS-1250':
9045 return 'windows-1250';
9046
9047 case 'WINDOWS-1251':
9048 return 'windows-1251';
9049
9050 case 'WINDOWS-1252':
9051 return 'windows-1252';
9052
9053 case 'WINDOWS-1253':
9054 return 'windows-1253';
9055
9056 case 'WINDOWS-1254':
9057 return 'windows-1254';
9058
9059 case 'WINDOWS-1255':
9060 return 'windows-1255';
9061
9062 case 'WINDOWS-1256':
9063 return 'windows-1256';
9064
9065 case 'WINDOWS-1257':
9066 return 'windows-1257';
9067
9068 case 'WINDOWS-1258':
9069 return 'windows-1258';
9070
9071 default:
9072 return (string) $encoding;
9073 }
9074 }
9075
9076 function get_curl_version()
9077 {
9078 if (is_array($curl = curl_version()))
9079 {
9080 $curl = $curl['version'];
9081 }
9082 elseif (substr($curl, 0, 5) == 'curl/')
9083 {
9084 $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
9085 }
9086 elseif (substr($curl, 0, 8) == 'libcurl/')
9087 {
9088 $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
9089 }
9090 else
9091 {
9092 $curl = 0;
9093 }
9094 return $curl;
9095 }
9096
9097 function is_subclass_of($class1, $class2)
9098 {
9099 if (func_num_args() != 2)
9100 {
9101 trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
9102 }
9103 elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
9104 {
9105 return is_subclass_of($class1, $class2);
9106 }
9107 elseif (is_string($class1) && is_string($class2))
9108 {
9109 if (class_exists($class1))
9110 {
9111 if (class_exists($class2))
9112 {
9113 $class2 = strtolower($class2);
9114 while ($class1 = strtolower(get_parent_class($class1)))
9115 {
9116 if ($class1 == $class2)
9117 {
9118 return true;
9119 }
9120 }
9121 }
9122 }
9123 else
9124 {
9125 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
9126 }
9127 }
9128 return false;
9129 }
9130
9131 /**
9132 * Strip HTML comments
9133 *
9134 * @access public
9135 * @param string $data Data to strip comments from
9136 * @return string Comment stripped string
9137 */
9138 function strip_comments($data)
9139 {
9140 $output = '';
9141 while (($start = strpos($data, '<!--')) !== false)
9142 {
9143 $output .= substr($data, 0, $start);
9144 if (($end = strpos($data, '-->', $start)) !== false)
9145 {
9146 $data = substr_replace($data, '', 0, $end + 3);
9147 }
9148 else
9149 {
9150 $data = '';
9151 }
9152 }
9153 return $output . $data;
9154 }
9155
9156 function parse_date($dt, $rfc822_tz = true)
9157 {
9158 static $cache = array();
9159 if (!isset($cache[$dt][$rfc822_tz]))
9160 {
9161 $dt = SimplePie_Misc::uncomment_rfc822($dt);
9162 /*
9163 Capturing subpatterns:
9164 1: RFC 822 date
9165 2: RFC 822 day
9166 3: RFC 822 month
9167 4: RFC 822 year
9168 5: ISO 8601 date
9169 6: ISO 8601 century
9170 7: ISO 8601 year
9171 8: ISO 8601 month
9172 9: ISO 8601 day
9173 10: ISO 8601 ordinal day
9174 11: ISO 8601 month
9175 12: ISO 8601 day
9176 13: ISO 8601 week
9177 14: ISO 8601 day of week
9178 15: Time
9179 16: Hour
9180 17: Hour Decimal
9181 18: Minute
9182 19: Minute Decimal
9183 20: Second
9184 21: Second Decimal
9185 22: Timezone
9186 23: Diff ±
9187 24: Hour
9188 25: Hour Decimal
9189 26: Minute
9190 27: Minute Decimal
9191 28: Alphabetic Timezone
9192 */
9193 if (preg_match('/^(?:(?:(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)[,\s]+)?(([0-9]{1,2})\s*(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s*([0-9]{4}|[0-9]{2}))|(([0-9]{2})(?:([0-9]{2})(?:(?:-|\s)*(?:([0-9]{2})([0-9]{2})|([0-9]{3})|([0-9]{2})(?:(?:-|\s)*([0-9]{2}))?|W([0-9]{2})(?:(?:-|\s)*([0-9]))?))?)?))((?:T|\s)+([0-9]{2})(?:(?:,|\.)([0-9]*)|(?:\:|\s)*([0-9]{2})(?:(?:,|\.)([0-9]*)|(?:\:|\s)*([0-9]{2})(?:(?:,|\.)([0-9]*))?)?)?(?:\s)*((?:(\+|-)([0-9]{2})(?:(?:,|\.)([0-9]*)|(?:\:|\s)*(?:([0-9]{2})(?:(?:,|\.)([0-9]*))?))?)|(UTC|GMT|EST|CST|MST|PST|EDT|CDT|MDT|PDT|UT|[A-IK-Z]))?)?$/i', $dt, $match))
9194 {
9195 // Fill all matches
9196 for ($i = count($match); $i <= 28; $i++)
9197 {
9198 $match[$i] = '';
9199 }
9200
9201 // Set blank vars
9202 $year = 1970;
9203 $month = 1;
9204 $day = 1;
9205 $hour = 0;
9206 $minute = 0;
9207 $second = 0;
9208 $timezone = false;
9209
9210 // RFC 822
9211 if ($match[1] !== '')
9212 {
9213 if (strlen($match[4]) == 2)
9214 {
9215 $year = ($match[4] < 70) ? "20$match[4]" : "19$match[4]";
9216 }
9217 else
9218 {
9219 $year = $match[4];
9220 }
9221 switch (strtolower($match[3]))
9222 {
9223 case 'jan':
9224 $month = 1;
9225 break;
9226
9227 case 'feb':
9228 $month = 2;
9229 break;
9230
9231 case 'mar':
9232 $month = 3;
9233 break;
9234
9235 case 'apr':
9236 $month = 4;
9237 break;
9238
9239 case 'may':
9240 $month = 5;
9241 break;
9242
9243 case 'jun':
9244 $month = 6;
9245 break;
9246
9247 case 'jul':
9248 $month = 7;
9249 break;
9250
9251 case 'aug':
9252 $month = 8;
9253 break;
9254
9255 case 'sep':
9256 $month = 9;
9257 break;
9258
9259 case 'oct':
9260 $month = 10;
9261 break;
9262
9263 case 'nov':
9264 $month = 11;
9265 break;
9266
9267 case 'dec':
9268 $month = 12;
9269 break;
9270 }
9271 $day = $match[2];
9272 }
9273 // ISO 8601
9274 else
9275 {
9276 // Year
9277 if ($match[7] !== '')
9278 {
9279 $year = "$match[6]$match[7]";
9280
9281 // Two Digit Month/Day
9282 if ($match[11] !== '')
9283 {
9284 $month = $match[11];
9285 if ($match[12] !== '')
9286 {
9287 $day = $match[12];
9288 }
9289 }
9290
9291 // Four Digit Month/Day
9292 elseif ($match[8] !== '')
9293 {
9294 $month = $match[8];
9295 $day = $match[9];
9296 }
9297
9298 // Ordinal Day
9299 elseif ($match[10] !== '')
9300 {
9301 $day = $match[10];
9302 }
9303
9304 // Week Date
9305 elseif ($match[13] !== '')
9306 {
9307 // Week Day
9308 if ($match[14] !== '')
9309 {
9310 $day = $match[14];
9311 }
9312
9313 $first_day_of_year = date('w', mktime(0, 0, 0, 1, 1, $year));
9314 if ($first_day_of_year == 0)
9315 {
9316 $first_day_of_year = 7;
9317 }
9318
9319 $day = 7 * ($match[13] - 1) + $day - ($first_day_of_year - 1);
9320 }
9321 }
9322 else
9323 {
9324 $year = "$match[6]00";
9325 }
9326 }
9327 // Time
9328 if ($match[15] !== '')
9329 {
9330 $time = 0;
9331 $time += ($match[16] + ('.' . $match[17])) * 3600;
9332 $time += ($match[18] + ('.' . $match[19])) * 60;
9333 $time += $match[20] + ('.' . $match[21]);
9334 $hour = floor($time / 3600);
9335 $time -= $hour * 3600;
9336 $minute = floor($time / 60);
9337 $time -= $minute * 60;
9338 $second = round($time);
9339
9340 // Timezone
9341 if ($match[22] !== '')
9342 {
9343 // Alphabetic Timezone
9344 if ($match[28] !== '')
9345 {
9346 // Military
9347 if (strlen($match[28]) == 1)
9348 {
9349 if ($match[28] == 'Z' || $match[28] == 'z' || !$rfc822_tz)
9350 {
9351 $timezone = 0;
9352 }
9353 else
9354 {
9355 $timezone = ord(strtoupper($match[28]));
9356
9357 if ($timezone > 74)
9358 {
9359 $timezone--;
9360 }
9361
9362 if ($timezone <= 76)
9363 {
9364 $timezone = -($timezone - 64);
9365 }
9366 else
9367 {
9368 $timezone -= 76;
9369 }
9370
9371 $timezone *= 3600;
9372 }
9373 }
9374 // Code
9375 else
9376 {
9377 switch (strtoupper($match[28]))
9378 {
9379 case 'UT':
9380 case 'UTC':
9381 case 'GMT':
9382 $timezone = 0;
9383 break;
9384
9385 case 'EST':
9386 $timezone = -18000;
9387 break;
9388
9389 case 'CST':
9390 $timezone = -21600;
9391 break;
9392
9393 case 'MST':
9394 $timezone = -25200;
9395 break;
9396
9397 case 'PST':
9398 $timezone = -28800;
9399 break;
9400
9401 case 'EDT':
9402 $timezone = -14400;
9403 break;
9404
9405 case 'CDT':
9406 $timezone = -18000;
9407 break;
9408
9409 case 'MDT':
9410 $timezone = -21600;
9411 break;
9412
9413 case 'PDT':
9414 $timezone = -25200;
9415 break;
9416 }
9417 }
9418 }
9419 // Timezone difference from UTC
9420 else
9421 {
9422 $timezone = 0;
9423 $timezone += ($match[24] + ('.' . $match[25])) * 3600;
9424 $timezone += ($match[26] + ('.' . $match[27])) * 60;
9425 $timezone = (int) round($timezone);
9426
9427 if ($match[23] == '-')
9428 {
9429 $timezone = -$timezone;
9430 }
9431 }
9432 }
9433 }
9434 if ($timezone === false)
9435 {
9436 $cache[$dt][$rfc822_tz] = mktime($hour, $minute, $second, $month, $day, $year);
9437 }
9438 else
9439 {
9440 $cache[$dt][$rfc822_tz] = gmmktime($hour, $minute, $second, $month, $day, $year) - $timezone;
9441 }
9442 }
9443 elseif (($time = strtotime($dt)) > 0)
9444 {
9445 $cache[$dt][$rfc822_tz] = $time;
9446 }
9447 else
9448 {
9449 $cache[$dt][$rfc822_tz] = false;
9450 }
9451 }
9452 return $cache[$dt][$rfc822_tz];
9453 }
9454
9455 /**
9456 * Decode HTML entities
9457 *
9458 * @static
9459 * @access public
9460 * @param string $data Input data
9461 * @return string Output data
9462 */
9463 function entities_decode($data)
9464 {
9465 $decoder = new SimplePie_Decode_HTML_Entities($data);
9466 return $decoder->parse();
9467 }
9468
9469 /**
9470 * Remove RFC822 comments
9471 *
9472 * @author Tomas V.V.Cox <cox@idecnet.com>
9473 * @author Pierre-Alain Joye <pajoye@php.net>
9474 * @author Amir Mohammad Saied <amir@php.net>
9475 * @copyright 1997-2006 Pierre-Alain Joye,Tomas V.V.Cox,Amir Mohammad Saied
9476 * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
9477 * @version CVS: $Id: Validate.php,v 1.104 2006/11/17 16:32:06 amir Exp $
9478 * @link http://pear.php.net/package/Validate
9479 * @access public
9480 * @param string $data Data to strip comments from
9481 * @return string Comment stripped string
9482 */
9483 function uncomment_rfc822($data)
9484 {
9485 if ((version_compare(PHP_VERSION, '4.4.6', '>=') && version_compare(PHP_VERSION, '5', '<')) || version_compare(PHP_VERSION, '5.2.2', '>='))
9486 {
9487 return $data;
9488 }
9489 else
9490 {
9491 return preg_replace('/((?:(?:\\\\"|[^("])*(?:"(?:[^"\\\\\r]|\\\\.)*"\s*)?)*)((?<!\\\\)\((?:(?2)|.)*?(?<!\\\\)\))/', '$1', $data);
9492 }
9493 }
9494
9495 function parse_mime($mime)
9496 {
9497 if (($pos = strpos($mime, ';')) === false)
9498 {
9499 return trim($mime);
9500 }
9501 else
9502 {
9503 return trim(substr($mime, 0, $pos));
9504 }
9505 }
9506
9507 function htmlspecialchars_decode($string, $quote_style)
9508 {
9509 if (function_exists('htmlspecialchars_decode'))
9510 {
9511 return htmlspecialchars_decode($string, $quote_style);
9512 }
9513 else
9514 {
9515 return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
9516 }
9517 }
9518
9519 function atom_03_construct_type($attribs)
9520 {
9521 if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) == 'base64'))
9522 {
9523 $mode = SIMPLEPIE_CONSTRUCT_BASE64;
9524 }
9525 else
9526 {
9527 $mode = SIMPLEPIE_CONSTRUCT_NONE;
9528 }
9529 if (isset($attribs['']['type']))
9530 {
9531 switch (strtolower(trim($attribs['']['type'])))
9532 {
9533 case 'text':
9534 case 'text/plain':
9535 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
9536
9537 case 'html':
9538 case 'text/html':
9539 return SIMPLEPIE_CONSTRUCT_HTML | $mode;
9540
9541 case 'xhtml':
9542 case 'application/xhtml+xml':
9543 return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
9544
9545 default:
9546 return SIMPLEPIE_CONSTRUCT_NONE | $mode;
9547 }
9548 }
9549 else
9550 {
9551 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
9552 }
9553 }
9554
9555 function atom_10_construct_type($attribs)
9556 {
9557 if (isset($attribs['']['type']))
9558 {
9559 switch (strtolower(trim($attribs['']['type'])))
9560 {
9561 case 'text':
9562 return SIMPLEPIE_CONSTRUCT_TEXT;
9563
9564 case 'html':
9565 return SIMPLEPIE_CONSTRUCT_HTML;
9566
9567 case 'xhtml':
9568 return SIMPLEPIE_CONSTRUCT_XHTML;
9569
9570 default:
9571 return SIMPLEPIE_CONSTRUCT_NONE;
9572 }
9573 }
9574 return SIMPLEPIE_CONSTRUCT_TEXT;
9575 }
9576
9577 function atom_10_content_construct_type($attribs)
9578 {
9579 if (isset($attribs['']['type']))
9580 {
9581 $type = strtolower(trim($attribs['']['type']));
9582 switch ($type)
9583 {
9584 case 'text':
9585 return SIMPLEPIE_CONSTRUCT_TEXT;
9586
9587 case 'html':
9588 return SIMPLEPIE_CONSTRUCT_HTML;
9589
9590 case 'xhtml':
9591 return SIMPLEPIE_CONSTRUCT_XHTML;
9592 }
9593 if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) == 'text/')
9594 {
9595 return SIMPLEPIE_CONSTRUCT_NONE;
9596 }
9597 else
9598 {
9599 return SIMPLEPIE_CONSTRUCT_BASE64;
9600 }
9601 }
9602 else
9603 {
9604 return SIMPLEPIE_CONSTRUCT_TEXT;
9605 }
9606 }
9607
9608 function is_isegment_nz_nc($string)
9609 {
9610 return (bool) preg_match('/^([A-Za-z0-9\-._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!$&\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/u', $string);
9611 }
9612
9613 function space_seperated_tokens($string)
9614 {
9615 $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
9616 $string_length = strlen($string);
9617
9618 $position = strspn($string, $space_characters);
9619 $tokens = array();
9620
9621 while ($position < $string_length)
9622 {
9623 $len = strcspn($string, $space_characters, $position);
9624 $tokens[] = substr($string, $position, $len);
9625 $position += $len;
9626 $position += strspn($string, $space_characters, $position);
9627 }
9628
9629 return $tokens;
9630 }
9631
9632 function array_unique($array)
9633 {
9634 if (version_compare(PHP_VERSION, '5.2', '>='))
9635 {
9636 return array_unique($array);
9637 }
9638 else
9639 {
9640 $array = (array) $array;
9641 $new_array = array();
9642 $new_array_strings = array();
9643 foreach ($array as $key => $value)
9644 {
9645 if (is_object($value))
9646 {
9647 if (method_exists($value, '__toString'))
9648 {
9649 $cmp = $value->__toString();
9650 }
9651 else
9652 {
9653 trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
9654 }
9655 }
9656 elseif (is_array($value))
9657 {
9658 $cmp = (string) reset($value);
9659 }
9660 else
9661 {
9662 $cmp = (string) $value;
9663 }
9664 if (!in_array($cmp, $new_array_strings))
9665 {
9666 $new_array[$key] = $value;
9667 $new_array_strings[] = $cmp;
9668 }
9669 }
9670 return $new_array;
9671 }
9672 }
9673
9674 /**
9675 * Converts a unicode codepoint to a UTF-8 character
9676 *
9677 * @static
9678 * @access public
9679 * @param int $codepoint Unicode codepoint
9680 * @return string UTF-8 character
9681 */
9682 function codepoint_to_utf8($codepoint)
9683 {
9684 static $cache = array();
9685 $codepoint = (int) $codepoint;
9686 if (isset($cache[$codepoint]))
9687 {
9688 return $cache[$codepoint];
9689 }
9690 elseif ($codepoint < 0)
9691 {
9692 return $cache[$codepoint] = false;
9693 }
9694 else if ($codepoint <= 0x7f)
9695 {
9696 return $cache[$codepoint] = chr($codepoint);
9697 }
9698 else if ($codepoint <= 0x7ff)
9699 {
9700 return $cache[$codepoint] = chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
9701 }
9702 else if ($codepoint <= 0xffff)
9703 {
9704 return $cache[$codepoint] = chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
9705 }
9706 else if ($codepoint <= 0x10ffff)
9707 {
9708 return $cache[$codepoint] = chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
9709 }
9710 else
9711 {
9712 // U+FFFD REPLACEMENT CHARACTER
9713 return $cache[$codepoint] = "\xEF\xBF\xBD";
9714 }
9715 }
9716
9717 /**
9718 * Re-implementation of PHP 4.2.0's is_a()
9719 *
9720 * @static
9721 * @access public
9722 * @param object $object The tested object
9723 * @param string $class_name The class name
9724 * @return bool Returns true if the object is of this class or has this class as one of its parents, false otherwise
9725 */
9726 function is_a($object, $class_name)
9727 {
9728 if (function_exists('is_a'))
9729 {
9730 return is_a($object, $class_name);
9731 }
9732 elseif (!is_object($object))
9733 {
9734 return false;
9735 }
9736 elseif (get_class($object) == strtolower($class_name))
9737 {
9738 return true;
9739 }
9740 else
9741 {
9742 return is_subclass_of($object, $class_name);
9743 }
9744 }
9745
9746 /**
9747 * Re-implementation of PHP 5's stripos()
9748 *
9749 * Returns the numeric position of the first occurrence of needle in the
9750 * haystack string.
9751 *
9752 * @static
9753 * @access string
9754 * @param object $haystack
9755 * @param string $needle Note that the needle may be a string of one or more
9756 * characters. If needle is not a string, it is converted to an integer
9757 * and applied as the ordinal value of a character.
9758 * @param int $offset The optional offset parameter allows you to specify which
9759 * character in haystack to start searching. The position returned is still
9760 * relative to the beginning of haystack.
9761 * @return bool If needle is not found, stripos() will return boolean false.
9762 */
9763 function stripos($haystack, $needle, $offset = 0)
9764 {
9765 if (function_exists('stripos'))
9766 {
9767 return stripos($haystack, $needle, $offset);
9768 }
9769 else
9770 {
9771 if (is_string($needle))
9772 {
9773 $needle = strtolower($needle);
9774 }
9775 elseif (is_int($needle) || is_bool($needle) || is_double($needle))
9776 {
9777 $needle = strtolower(chr($needle));
9778 }
9779 else
9780 {
9781 trigger_error('needle is not a string or an integer', E_USER_WARNING);
9782 return false;
9783 }
9784
9785 return strpos(strtolower($haystack), $needle, $offset);
9786 }
9787 }
9788 }
9789
9790 /**
9791 * Decode HTML Entities
9792 *
9793 * This implements HTML5 as of revision 967 (2007-06-28)
9794 *
9795 * @package SimplePie
9796 */
9797 class SimplePie_Decode_HTML_Entities
9798 {
9799 /**
9800 * Data to be parsed
9801 *
9802 * @access private
9803 * @var string
9804 */
9805 var $data = '';
9806
9807 /**
9808 * Currently consumed bytes
9809 *
9810 * @access private
9811 * @var string
9812 */
9813 var $consumed = '';
9814
9815 /**
9816 * Position of the current byte being parsed
9817 *
9818 * @access private
9819 * @var int
9820 */
9821 var $position = 0;
9822
9823 /**
9824 * Create an instance of the class with the input data
9825 *
9826 * @access public
9827 * @param string $data Input data
9828 */
9829 function SimplePie_Decode_HTML_Entities($data)
9830 {
9831 $this->data = $data;
9832 }
9833
9834 /**
9835 * Parse the input data
9836 *
9837 * @access public
9838 * @return string Output data
9839 */
9840 function parse()
9841 {
9842 while (($this->position = strpos($this->data, '&', $this->position)) !== false)
9843 {
9844 $this->consume();
9845 $this->entity();
9846 $this->consumed = '';
9847 }
9848 return $this->data;
9849 }
9850
9851 /**
9852 * Consume the next byte
9853 *
9854 * @access private
9855 * @return mixed The next byte, or false, if there is no more data
9856 */
9857 function consume()
9858 {
9859 if (isset($this->data[$this->position]))
9860 {
9861 $this->consumed .= $this->data[$this->position];
9862 return $this->data[$this->position++];
9863 }
9864 else
9865 {
9866 $this->consumed = false;
9867 return false;
9868 }
9869 }
9870
9871 /**
9872 * Consume a range of characters
9873 *
9874 * @access private
9875 * @param string $chars Characters to consume
9876 * @return mixed A series of characters that match the range, or false
9877 */
9878 function consume_range($chars)
9879 {
9880 if ($len = strspn($this->data, $chars, $this->position))
9881 {
9882 $data = substr($this->data, $this->position, $len);
9883 $this->consumed .= $data;
9884 $this->position += $len;
9885 return $data;
9886 }
9887 else
9888 {
9889 $this->consumed = false;
9890 return false;
9891 }
9892 }
9893
9894 /**
9895 * Unconsume one byte
9896 *
9897 * @access private
9898 */
9899 function unconsume()
9900 {
9901 $this->consumed = substr($this->consumed, 0, -1);
9902 $this->position--;
9903 }
9904
9905 /**
9906 * Decode an entity
9907 *
9908 * @access private
9909 */
9910 function entity()
9911 {
9912 switch ($this->consume())
9913 {
9914 case "\x09":
9915 case "\x0A":
9916 case "\x0B":
9917 case "\x0B":
9918 case "\x0C":
9919 case "\x20":
9920 case "\x3C":
9921 case "\x26":
9922 case false:
9923 break;
9924
9925 case "\x23":
9926 switch ($this->consume())
9927 {
9928 case "\x78":
9929 case "\x58":
9930 $range = '0123456789ABCDEFabcdef';
9931 $hex = true;
9932 break;
9933
9934 default:
9935 $range = '0123456789';
9936 $hex = false;
9937 $this->unconsume();
9938 break;
9939 }
9940
9941 if ($codepoint = $this->consume_range($range))
9942 {
9943 static $windows_1252_specials = array(0x0D => "\x0A", 0x80 => "\xE2\x82\xAC", 0x81 => "\xEF\xBF\xBD", 0x82 => "\xE2\x80\x9A", 0x83 => "\xC6\x92", 0x84 => "\xE2\x80\x9E", 0x85 => "\xE2\x80\xA6", 0x86 => "\xE2\x80\xA0", 0x87 => "\xE2\x80\xA1", 0x88 => "\xCB\x86", 0x89 => "\xE2\x80\xB0", 0x8A => "\xC5\xA0", 0x8B => "\xE2\x80\xB9", 0x8C => "\xC5\x92", 0x8D => "\xEF\xBF\xBD", 0x8E => "\xC5\xBD", 0x8F => "\xEF\xBF\xBD", 0x90 => "\xEF\xBF\xBD", 0x91 => "\xE2\x80\x98", 0x92 => "\xE2\x80\x99", 0x93 => "\xE2\x80\x9C", 0x94 => "\xE2\x80\x9D", 0x95 => "\xE2\x80\xA2", 0x96 => "\xE2\x80\x93", 0x97 => "\xE2\x80\x94", 0x98 => "\xCB\x9C", 0x99 => "\xE2\x84\xA2", 0x9A => "\xC5\xA1", 0x9B => "\xE2\x80\xBA", 0x9C => "\xC5\x93", 0x9D => "\xEF\xBF\xBD", 0x9E => "\xC5\xBE", 0x9F => "\xC5\xB8");
9944
9945 if ($hex)
9946 {
9947 $codepoint = hexdec($codepoint);
9948 }
9949 else
9950 {
9951 $codepoint = intval($codepoint);
9952 }
9953
9954 if (isset($windows_1252_specials[$codepoint]))
9955 {
9956 $replacement = $windows_1252_specials[$codepoint];
9957 }
9958 else
9959 {
9960 $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
9961 }
9962
9963 if ($this->consume() != ';')
9964 {
9965 $this->unconsume();
9966 }
9967
9968 $consumed_length = strlen($this->consumed);
9969 $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
9970 $this->position += strlen($replacement) - $consumed_length;
9971 }
9972 break;
9973
9974 default:
9975 static $entities = array('Aacute' => "\xC3\x81", 'aacute' => "\xC3\xA1", 'Aacute;' => "\xC3\x81", 'aacute;' => "\xC3\xA1", 'Acirc' => "\xC3\x82", 'acirc' => "\xC3\xA2", 'Acirc;' => "\xC3\x82", 'acirc;' => "\xC3\xA2", 'acute' => "\xC2\xB4", 'acute;' => "\xC2\xB4", 'AElig' => "\xC3\x86", 'aelig' => "\xC3\xA6", 'AElig;' => "\xC3\x86", 'aelig;' => "\xC3\xA6", 'Agrave' => "\xC3\x80", 'agrave' => "\xC3\xA0", 'Agrave;' => "\xC3\x80", 'agrave;' => "\xC3\xA0", 'alefsym;' => "\xE2\x84\xB5", 'Alpha;' => "\xCE\x91", 'alpha;' => "\xCE\xB1", 'AMP' => "\x26", 'amp' => "\x26", 'AMP;' => "\x26", 'amp;' => "\x26", 'and;' => "\xE2\x88\xA7", 'ang;' => "\xE2\x88\xA0", 'apos;' => "\x27", 'Aring' => "\xC3\x85", 'aring' => "\xC3\xA5", 'Aring;' => "\xC3\x85", 'aring;' => "\xC3\xA5", 'asymp;' => "\xE2\x89\x88", 'Atilde' => "\xC3\x83", 'atilde' => "\xC3\xA3", 'Atilde;' => "\xC3\x83", 'atilde;' => "\xC3\xA3", 'Auml' => "\xC3\x84", 'auml' => "\xC3\xA4", 'Auml;' => "\xC3\x84", 'auml;' => "\xC3\xA4", 'bdquo;' => "\xE2\x80\x9E", 'Beta;' => "\xCE\x92", 'beta;' => "\xCE\xB2", 'brvbar' => "\xC2\xA6", 'brvbar;' => "\xC2\xA6", 'bull;' => "\xE2\x80\xA2", 'cap;' => "\xE2\x88\xA9", 'Ccedil' => "\xC3\x87", 'ccedil' => "\xC3\xA7", 'Ccedil;' => "\xC3\x87", 'ccedil;' => "\xC3\xA7", 'cedil' => "\xC2\xB8", 'cedil;' => "\xC2\xB8", 'cent' => "\xC2\xA2", 'cent;' => "\xC2\xA2", 'Chi;' => "\xCE\xA7", 'chi;' => "\xCF\x87", 'circ;' => "\xCB\x86", 'clubs;' => "\xE2\x99\xA3", 'cong;' => "\xE2\x89\x85", 'COPY' => "\xC2\xA9", 'copy' => "\xC2\xA9", 'COPY;' => "\xC2\xA9", 'copy;' => "\xC2\xA9", 'crarr;' => "\xE2\x86\xB5", 'cup;' => "\xE2\x88\xAA", 'curren' => "\xC2\xA4", 'curren;' => "\xC2\xA4", 'Dagger;' => "\xE2\x80\xA1", 'dagger;' => "\xE2\x80\xA0", 'dArr;' => "\xE2\x87\x93", 'darr;' => "\xE2\x86\x93", 'deg' => "\xC2\xB0", 'deg;' => "\xC2\xB0", 'Delta;' => "\xCE\x94", 'delta;' => "\xCE\xB4", 'diams;' => "\xE2\x99\xA6", 'divide' => "\xC3\xB7", 'divide;' => "\xC3\xB7", 'Eacute' => "\xC3\x89", 'eacute' => "\xC3\xA9", 'Eacute;' => "\xC3\x89", 'eacute;' => "\xC3\xA9", 'Ecirc' => "\xC3\x8A", 'ecirc' => "\xC3\xAA", 'Ecirc;' => "\xC3\x8A", 'ecirc;' => "\xC3\xAA", 'Egrave' => "\xC3\x88", 'egrave' => "\xC3\xA8", 'Egrave;' => "\xC3\x88", 'egrave;' => "\xC3\xA8", 'empty;' => "\xE2\x88\x85", 'emsp;' => "\xE2\x80\x83", 'ensp;' => "\xE2\x80\x82", 'Epsilon;' => "\xCE\x95", 'epsilon;' => "\xCE\xB5", 'equiv;' => "\xE2\x89\xA1", 'Eta;' => "\xCE\x97", 'eta;' => "\xCE\xB7", 'ETH' => "\xC3\x90", 'eth' => "\xC3\xB0", 'ETH;' => "\xC3\x90", 'eth;' => "\xC3\xB0", 'Euml' => "\xC3\x8B", 'euml' => "\xC3\xAB", 'Euml;' => "\xC3\x8B", 'euml;' => "\xC3\xAB", 'euro;' => "\xE2\x82\xAC", 'exist;' => "\xE2\x88\x83", 'fnof;' => "\xC6\x92", 'forall;' => "\xE2\x88\x80", 'frac12' => "\xC2\xBD", 'frac12;' => "\xC2\xBD", 'frac14' => "\xC2\xBC", 'frac14;' => "\xC2\xBC", 'frac34' => "\xC2\xBE", 'frac34;' => "\xC2\xBE", 'frasl;' => "\xE2\x81\x84", 'Gamma;' => "\xCE\x93", 'gamma;' => "\xCE\xB3", 'ge;' => "\xE2\x89\xA5", 'GT' => "\x3E", 'gt' => "\x3E", 'GT;' => "\x3E", 'gt;' => "\x3E", 'hArr;' => "\xE2\x87\x94", 'harr;' => "\xE2\x86\x94", 'hearts;' => "\xE2\x99\xA5", 'hellip;' => "\xE2\x80\xA6", 'Iacute' => "\xC3\x8D", 'iacute' => "\xC3\xAD", 'Iacute;' => "\xC3\x8D", 'iacute;' => "\xC3\xAD", 'Icirc' => "\xC3\x8E", 'icirc' => "\xC3\xAE", 'Icirc;' => "\xC3\x8E", 'icirc;' => "\xC3\xAE", 'iexcl' => "\xC2\xA1", 'iexcl;' => "\xC2\xA1", 'Igrave' => "\xC3\x8C", 'igrave' => "\xC3\xAC", 'Igrave;' => "\xC3\x8C", 'igrave;' => "\xC3\xAC", 'image;' => "\xE2\x84\x91", 'infin;' => "\xE2\x88\x9E", 'int;' => "\xE2\x88\xAB", 'Iota;' => "\xCE\x99", 'iota;' => "\xCE\xB9", 'iquest' => "\xC2\xBF", 'iquest;' => "\xC2\xBF", 'isin;' => "\xE2\x88\x88", 'Iuml' => "\xC3\x8F", 'iuml' => "\xC3\xAF", 'Iuml;' => "\xC3\x8F", 'iuml;' => "\xC3\xAF", 'Kappa;' => "\xCE\x9A", 'kappa;' => "\xCE\xBA", 'Lambda;' => "\xCE\x9B", 'lambda;' => "\xCE\xBB", 'lang;' => "\xE3\x80\x88", 'laquo' => "\xC2\xAB", 'laquo;' => "\xC2\xAB", 'lArr;' => "\xE2\x87\x90", 'larr;' => "\xE2\x86\x90", 'lceil;' => "\xE2\x8C\x88", 'ldquo;' => "\xE2\x80\x9C", 'le;' => "\xE2\x89\xA4", 'lfloor;' => "\xE2\x8C\x8A", 'lowast;' => "\xE2\x88\x97", 'loz;' => "\xE2\x97\x8A", 'lrm;' => "\xE2\x80\x8E", 'lsaquo;' => "\xE2\x80\xB9", 'lsquo;' => "\xE2\x80\x98", 'LT' => "\x3C", 'lt' => "\x3C", 'LT;' => "\x3C", 'lt;' => "\x3C", 'macr' => "\xC2\xAF", 'macr;' => "\xC2\xAF", 'mdash;' => "\xE2\x80\x94", 'micro' => "\xC2\xB5", 'micro;' => "\xC2\xB5", 'middot' => "\xC2\xB7", 'middot;' => "\xC2\xB7", 'minus;' => "\xE2\x88\x92", 'Mu;' => "\xCE\x9C", 'mu;' => "\xCE\xBC", 'nabla;' => "\xE2\x88\x87", 'nbsp' => "\xC2\xA0", 'nbsp;' => "\xC2\xA0", 'ndash;' => "\xE2\x80\x93", 'ne;' => "\xE2\x89\xA0", 'ni;' => "\xE2\x88\x8B", 'not' => "\xC2\xAC", 'not;' => "\xC2\xAC", 'notin;' => "\xE2\x88\x89", 'nsub;' => "\xE2\x8A\x84", 'Ntilde' => "\xC3\x91", 'ntilde' => "\xC3\xB1", 'Ntilde;' => "\xC3\x91", 'ntilde;' => "\xC3\xB1", 'Nu;' => "\xCE\x9D", 'nu;' => "\xCE\xBD", 'Oacute' => "\xC3\x93", 'oacute' => "\xC3\xB3", 'Oacute;' => "\xC3\x93", 'oacute;' => "\xC3\xB3", 'Ocirc' => "\xC3\x94", 'ocirc' => "\xC3\xB4", 'Ocirc;' => "\xC3\x94", 'ocirc;' => "\xC3\xB4", 'OElig;' => "\xC5\x92", 'oelig;' => "\xC5\x93", 'Ograve' => "\xC3\x92", 'ograve' => "\xC3\xB2", 'Ograve;' => "\xC3\x92", 'ograve;' => "\xC3\xB2", 'oline;' => "\xE2\x80\xBE", 'Omega;' => "\xCE\xA9", 'omega;' => "\xCF\x89", 'Omicron;' => "\xCE\x9F", 'omicron;' => "\xCE\xBF", 'oplus;' => "\xE2\x8A\x95", 'or;' => "\xE2\x88\xA8", 'ordf' => "\xC2\xAA", 'ordf;' => "\xC2\xAA", 'ordm' => "\xC2\xBA", 'ordm;' => "\xC2\xBA", 'Oslash' => "\xC3\x98", 'oslash' => "\xC3\xB8", 'Oslash;' => "\xC3\x98", 'oslash;' => "\xC3\xB8", 'Otilde' => "\xC3\x95", 'otilde' => "\xC3\xB5", 'Otilde;' => "\xC3\x95", 'otilde;' => "\xC3\xB5", 'otimes;' => "\xE2\x8A\x97", 'Ouml' => "\xC3\x96", 'ouml' => "\xC3\xB6", 'Ouml;' => "\xC3\x96", 'ouml;' => "\xC3\xB6", 'para' => "\xC2\xB6", 'para;' => "\xC2\xB6", 'part;' => "\xE2\x88\x82", 'permil;' => "\xE2\x80\xB0", 'perp;' => "\xE2\x8A\xA5", 'Phi;' => "\xCE\xA6", 'phi;' => "\xCF\x86", 'Pi;' => "\xCE\xA0", 'pi;' => "\xCF\x80", 'piv;' => "\xCF\x96", 'plusmn' => "\xC2\xB1", 'plusmn;' => "\xC2\xB1", 'pound' => "\xC2\xA3", 'pound;' => "\xC2\xA3", 'Prime;' => "\xE2\x80\xB3", 'prime;' => "\xE2\x80\xB2", 'prod;' => "\xE2\x88\x8F", 'prop;' => "\xE2\x88\x9D", 'Psi;' => "\xCE\xA8", 'psi;' => "\xCF\x88", 'QUOT' => "\x22", 'quot' => "\x22", 'QUOT;' => "\x22", 'quot;' => "\x22", 'radic;' => "\xE2\x88\x9A", 'rang;' => "\xE3\x80\x89", 'raquo' => "\xC2\xBB", 'raquo;' => "\xC2\xBB", 'rArr;' => "\xE2\x87\x92", 'rarr;' => "\xE2\x86\x92", 'rceil;' => "\xE2\x8C\x89", 'rdquo;' => "\xE2\x80\x9D", 'real;' => "\xE2\x84\x9C", 'REG' => "\xC2\xAE", 'reg' => "\xC2\xAE", 'REG;' => "\xC2\xAE", 'reg;' => "\xC2\xAE", 'rfloor;' => "\xE2\x8C\x8B", 'Rho;' => "\xCE\xA1", 'rho;' => "\xCF\x81", 'rlm;' => "\xE2\x80\x8F", 'rsaquo;' => "\xE2\x80\xBA", 'rsquo;' => "\xE2\x80\x99", 'sbquo;' => "\xE2\x80\x9A", 'Scaron;' => "\xC5\xA0", 'scaron;' => "\xC5\xA1", 'sdot;' => "\xE2\x8B\x85", 'sect' => "\xC2\xA7", 'sect;' => "\xC2\xA7", 'shy' => "\xC2\xAD", 'shy;' => "\xC2\xAD", 'Sigma;' => "\xCE\xA3", 'sigma;' => "\xCF\x83", 'sigmaf;' => "\xCF\x82", 'sim;' => "\xE2\x88\xBC", 'spades;' => "\xE2\x99\xA0", 'sub;' => "\xE2\x8A\x82", 'sube;' => "\xE2\x8A\x86", 'sum;' => "\xE2\x88\x91", 'sup;' => "\xE2\x8A\x83", 'sup1' => "\xC2\xB9", 'sup1;' => "\xC2\xB9", 'sup2' => "\xC2\xB2", 'sup2;' => "\xC2\xB2", 'sup3' => "\xC2\xB3", 'sup3;' => "\xC2\xB3", 'supe;' => "\xE2\x8A\x87", 'szlig' => "\xC3\x9F", 'szlig;' => "\xC3\x9F", 'Tau;' => "\xCE\xA4", 'tau;' => "\xCF\x84", 'there4;' => "\xE2\x88\xB4", 'Theta;' => "\xCE\x98", 'theta;' => "\xCE\xB8", 'thetasym;' => "\xCF\x91", 'thinsp;' => "\xE2\x80\x89", 'THORN' => "\xC3\x9E", 'thorn' => "\xC3\xBE", 'THORN;' => "\xC3\x9E", 'thorn;' => "\xC3\xBE", 'tilde;' => "\xCB\x9C", 'times' => "\xC3\x97", 'times;' => "\xC3\x97", 'TRADE;' => "\xE2\x84\xA2", 'trade;' => "\xE2\x84\xA2", 'Uacute' => "\xC3\x9A", 'uacute' => "\xC3\xBA", 'Uacute;' => "\xC3\x9A", 'uacute;' => "\xC3\xBA", 'uArr;' => "\xE2\x87\x91", 'uarr;' => "\xE2\x86\x91", 'Ucirc' => "\xC3\x9B", 'ucirc' => "\xC3\xBB", 'Ucirc;' => "\xC3\x9B", 'ucirc;' => "\xC3\xBB", 'Ugrave' => "\xC3\x99", 'ugrave' => "\xC3\xB9", 'Ugrave;' => "\xC3\x99", 'ugrave;' => "\xC3\xB9", 'uml' => "\xC2\xA8", 'uml;' => "\xC2\xA8", 'upsih;' => "\xCF\x92", 'Upsilon;' => "\xCE\xA5", 'upsilon;' => "\xCF\x85", 'Uuml' => "\xC3\x9C", 'uuml' => "\xC3\xBC", 'Uuml;' => "\xC3\x9C", 'uuml;' => "\xC3\xBC", 'weierp;' => "\xE2\x84\x98", 'Xi;' => "\xCE\x9E", 'xi;' => "\xCE\xBE", 'Yacute' => "\xC3\x9D", 'yacute' => "\xC3\xBD", 'Yacute;' => "\xC3\x9D", 'yacute;' => "\xC3\xBD", 'yen' => "\xC2\xA5", 'yen;' => "\xC2\xA5", 'yuml' => "\xC3\xBF", 'Yuml;' => "\xC5\xB8", 'yuml;' => "\xC3\xBF", 'Zeta;' => "\xCE\x96", 'zeta;' => "\xCE\xB6", 'zwj;' => "\xE2\x80\x8D", 'zwnj;' => "\xE2\x80\x8C");
9976
9977 for ($i = 0, $match = null; $i < 9 && $this->consume(); $i++)
9978 {
9979 $consumed = substr($this->consumed, 1);
9980 if (isset($entities[$consumed]))
9981 {
9982 $match = $consumed;
9983 }
9984 }
9985
9986 if ($match !== null)
9987 {
9988 $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
9989 $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
9990 }
9991 break;
9992 }
9993 }
9994 }
9995
9996 class SimplePie_Locator
9997 {
9998 var $useragent;
9999 var $timeout;
10000 var $file;
10001 var $local = array();
10002 var $elsewhere = array();
10003 var $file_class = 'SimplePie_File';
10004 var $cached_entities = array();
10005 var $http_base;
10006 var $base;
10007 var $base_location = 0;
10008 var $checked_feeds = 0;
10009 var $max_checked_feeds = 10;
10010
10011 function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10)
10012 {
10013 $this->file =& $file;
10014 $this->file_class = $file_class;
10015 $this->useragent = $useragent;
10016 $this->timeout = $timeout;
10017 $this->max_checked_feeds = $max_checked_feeds;
10018 }
10019
10020 function find($type = SIMPLEPIE_LOCATOR_ALL)
10021 {
10022 if ($this->is_feed($this->file))
10023 {
10024 return $this->file;
10025 }
10026
10027 if ($type & ~SIMPLEPIE_LOCATOR_NONE)
10028 {
10029 $this->get_base();
10030 }
10031
10032 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
10033 {
10034 return $working;
10035 }
10036
10037 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
10038 {
10039 if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
10040 {
10041 return $working;
10042 }
10043
10044 if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
10045 {
10046 return $working;
10047 }
10048
10049 if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
10050 {
10051 return $working;
10052 }
10053
10054 if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
10055 {
10056 return $working;
10057 }
10058 }
10059 return null;
10060 }
10061
10062 function is_feed(&$file)
10063 {
10064 $body = SimplePie_Misc::strip_comments($file->body);
10065 if (preg_match('/<([^\s:]+:)?(rss|RDF|feed)' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/i', $body))
10066 {
10067 return true;
10068 }
10069 return false;
10070 }
10071
10072 function get_base()
10073 {
10074 if (isset($this->file->headers['content-location']))
10075 {
10076 $this->http_base = SimplePie_Misc::absolutize_url(trim($this->file->headers['content-location']), $this->file->url);
10077 }
10078 else
10079 {
10080 $this->http_base = $this->file->url;
10081 }
10082 $this->base = $this->http_base;
10083 $elements = SimplePie_Misc::get_element('base', $this->file->body);
10084 foreach ($elements as $element)
10085 {
10086 if ($element['attribs']['href']['data'] !== '')
10087 {
10088 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
10089 $this->base_location = $element['offset'];
10090 break;
10091 }
10092 }
10093 }
10094
10095 function autodiscovery()
10096 {
10097 $links = array_merge(SimplePie_Misc::get_element('link', $this->file->body), SimplePie_Misc::get_element('a', $this->file->body), SimplePie_Misc::get_element('area', $this->file->body));
10098 $done = array();
10099 foreach ($links as $link)
10100 {
10101 if ($this->checked_feeds == $this->max_checked_feeds)
10102 {
10103 break;
10104 }
10105 if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
10106 {
10107 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
10108
10109 if ($this->base_location < $link['offset'])
10110 {
10111 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
10112 }
10113 else
10114 {
10115 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
10116 }
10117
10118 if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !empty($link['attribs']['type']['data']) && in_array(strtolower(SimplePie_Misc::parse_mime($link['attribs']['type']['data'])), array('application/rss+xml', 'application/atom+xml'))))
10119 {
10120 $this->checked_feeds++;
10121 $feed =& new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
10122 if ($this->is_feed($feed))
10123 {
10124 return $feed;
10125 }
10126 }
10127 $done[] = $href;
10128 }
10129 }
10130 return null;
10131 }
10132
10133 function get_links()
10134 {
10135 $links = SimplePie_Misc::get_element('a', $this->file->body);
10136 foreach ($links as $link)
10137 {
10138 if (isset($link['attribs']['href']['data']))
10139 {
10140 $href = trim($link['attribs']['href']['data']);
10141 $parsed = SimplePie_Misc::parse_url($href);
10142 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
10143 {
10144 if ($this->base_location < $link['offset'])
10145 {
10146 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
10147 }
10148 else
10149 {
10150 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
10151 }
10152
10153 $current = SimplePie_Misc::parse_url($this->file->url);
10154
10155 if ($parsed['authority'] === '' || $parsed['authority'] == $current['authority'])
10156 {
10157 $this->local[] = $href;
10158 }
10159 else
10160 {
10161 $this->elsewhere[] = $href;
10162 }
10163 }
10164 }
10165 }
10166 $this->local = array_unique($this->local);
10167 $this->elsewhere = array_unique($this->elsewhere);
10168 if (!empty($this->local) || !empty($this->elsewhere))
10169 {
10170 return true;
10171 }
10172 return null;
10173 }
10174
10175 function extension(&$array)
10176 {
10177 foreach ($array as $key => $value)
10178 {
10179 if ($this->checked_feeds == $this->max_checked_feeds)
10180 {
10181 break;
10182 }
10183 if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
10184 {
10185 $this->checked_feeds++;
10186 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
10187 if ($this->is_feed($feed))
10188 {
10189 return $feed;
10190 }
10191 else
10192 {
10193 unset($array[$key]);
10194 }
10195 }
10196 }
10197 return null;
10198 }
10199
10200 function body(&$array)
10201 {
10202 foreach ($array as $key => $value)
10203 {
10204 if ($this->checked_feeds == $this->max_checked_feeds)
10205 {
10206 break;
10207 }
10208 if (preg_match('/(rss|rdf|atom|xml)/i', $value))
10209 {
10210 $this->checked_feeds++;
10211 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
10212 if ($this->is_feed($feed))
10213 {
10214 return $feed;
10215 }
10216 else
10217 {
10218 unset($array[$key]);
10219 }
10220 }
10221 }
10222 return null;
10223 }
10224 }
10225
10226 class SimplePie_Parser
10227 {
10228 var $xml;
10229 var $error_code;
10230 var $error_string;
10231 var $current_line;
10232 var $current_column;
10233 var $current_byte;
10234 var $separator = ' ';
10235 var $feed = false;
10236 var $namespace = array('');
10237 var $element = array('');
10238 var $xml_base = array('');
10239 var $xml_base_explicit = array(false);
10240 var $xml_lang = array('');
10241 var $data = array();
10242 var $datas = array(array());
10243 var $current_xhtml_construct = -1;
10244 var $encoding;
10245
10246 function pre_process(&$data, $encoding)
10247 {
10248 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
10249 if (strtoupper($encoding) == 'US-ASCII')
10250 {
10251 $this->encoding = 'UTF-8';
10252 }
10253 else
10254 {
10255 $this->encoding = $encoding;
10256 }
10257
10258 // Strip BOM:
10259 // UTF-32 Big Endian BOM
10260 if (strpos($data, "\x0\x0\xFE\xFF") === 0)
10261 {
10262 $data = substr($data, 4);
10263 }
10264 // UTF-32 Little Endian BOM
10265 elseif (strpos($data, "\xFF\xFE\x0\x0") === 0)
10266 {
10267 $data = substr($data, 4);
10268 }
10269 // UTF-16 Big Endian BOM
10270 elseif (strpos($data, "\xFE\xFF") === 0)
10271 {
10272 $data = substr($data, 2);
10273 }
10274 // UTF-16 Little Endian BOM
10275 elseif (strpos($data, "\xFF\xFE") === 0)
10276 {
10277 $data = substr($data, 2);
10278 }
10279 // UTF-8 BOM
10280 elseif (strpos($data, "\xEF\xBB\xBF") === 0)
10281 {
10282 $data = substr($data, 3);
10283 }
10284
10285 // Make sure the XML prolog is sane and has the correct encoding
10286 $data = preg_replace("/^<\?xml[\x20\x9\xD\xA]+version([\x20\x9\xD\xA]+)?=([\x20\x9\xD\xA]+)?(\"1.0\"|'1.0'|\"1.1\"|'1.1')([\x20\x9\xD\xA]+encoding([\x20\x9\xD\xA]+)?=([\x20\x9\xD\xA]+)?(\"[A-Za-z][A-Za-z0-9._\-]*\"|'[A-Za-z][A-Za-z0-9._\-]*'))?([\x20\x9\xD\xA]+standalone([\x20\x9\xD\xA]+)?=([\x20\x9\xD\xA]+)?(\"(yes|no)\"|'(yes|no)'))?([\x20\x9\xD\xA]+)?\?>/", '', $data);
10287 $data = "<?xml version='1.0' encoding='$encoding'?>\n" . $data;
10288 }
10289
10290 function parse(&$data)
10291 {
10292 $return = true;
10293
10294 // Create the parser
10295 $this->xml = xml_parser_create_ns($this->encoding, $this->separator);
10296 xml_parser_set_option($this->xml, XML_OPTION_SKIP_WHITE, 1);
10297 xml_parser_set_option($this->xml, XML_OPTION_CASE_FOLDING, 0);
10298 xml_set_object($this->xml, $this);
10299 xml_set_character_data_handler($this->xml, 'cdata');
10300 xml_set_element_handler($this->xml, 'tag_open', 'tag_close');
10301
10302 // Parse!
10303 if (!xml_parse($this->xml, $data, true))
10304 {
10305 $this->data = null;
10306 $this->error_code = xml_get_error_code($this->xml);
10307 $this->error_string = xml_error_string($this->error_code);
10308 $return = false;
10309 }
10310 $this->current_line = xml_get_current_line_number($this->xml);
10311 $this->current_column = xml_get_current_column_number($this->xml);
10312 $this->current_byte = xml_get_current_byte_index($this->xml);
10313 xml_parser_free($this->xml);
10314 return $return;
10315 }
10316
10317 function get_error_code()
10318 {
10319 return $this->error_code;
10320 }
10321
10322 function get_error_string()
10323 {
10324 return $this->error_string;
10325 }
10326
10327 function get_current_line()
10328 {
10329 return $this->current_line;
10330 }
10331
10332 function get_current_column()
10333 {
10334 return $this->current_column;
10335 }
10336
10337 function get_current_byte()
10338 {
10339 return $this->current_byte;
10340 }
10341
10342 function get_data()
10343 {
10344 return $this->data;
10345 }
10346
10347 function tag_open($parser, $tag, $attributes)
10348 {
10349 if ($this->feed === 0)
10350 {
10351 return;
10352 }
10353 elseif ($this->feed == false)
10354 {
10355 if (in_array($tag, array(
10356 SIMPLEPIE_NAMESPACE_ATOM_10 . $this->separator . 'feed',
10357 SIMPLEPIE_NAMESPACE_ATOM_03 . $this->separator . 'feed',
10358 'rss',
10359 SIMPLEPIE_NAMESPACE_RDF . $this->separator . 'RDF'
10360 )))
10361 {
10362 $this->feed = 1;
10363 }
10364 }
10365 else
10366 {
10367 $this->feed++;
10368 }
10369
10370 list($this->namespace[], $this->element[]) = $this->split_ns($tag);
10371
10372 $attribs = array();
10373 foreach ($attributes as $name => $value)
10374 {
10375 list($attrib_namespace, $attribute) = $this->split_ns($name);
10376 $attribs[$attrib_namespace][$attribute] = $value;
10377 }
10378
10379 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
10380 {
10381 $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
10382 $this->xml_base_explicit[] = true;
10383 }
10384 else
10385 {
10386 $this->xml_base[] = end($this->xml_base);
10387 $this->xml_base_explicit[] = end($this->xml_base_explicit);
10388 }
10389
10390 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
10391 {
10392 $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
10393 }
10394 else
10395 {
10396 $this->xml_lang[] = end($this->xml_lang);
10397 }
10398
10399 if ($this->current_xhtml_construct >= 0)
10400 {
10401 $this->current_xhtml_construct++;
10402 if (end($this->namespace) == SIMPLEPIE_NAMESPACE_XHTML)
10403 {
10404 $this->data['data'] .= '<' . end($this->element);
10405 if (isset($attribs['']))
10406 {
10407 foreach ($attribs[''] as $name => $value)
10408 {
10409 $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
10410 }
10411 }
10412 $this->data['data'] .= '>';
10413 }
10414 }
10415 else
10416 {
10417 $this->datas[] =& $this->data;
10418 $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
10419 $this->data = array('data' => '', 'attribs' => $attribs, 'xml_base' => end($this->xml_base), 'xml_base_explicit' => end($this->xml_base_explicit), 'xml_lang' => end($this->xml_lang));
10420 if ((end($this->namespace) == SIMPLEPIE_NAMESPACE_ATOM_03 && in_array(end($this->element), array('title', 'tagline', 'copyright', 'info', 'summary', 'content')) && isset($attribs['']['mode']) && $attribs['']['mode'] == 'xml')
10421 || (end($this->namespace) == SIMPLEPIE_NAMESPACE_ATOM_10 && in_array(end($this->element), array('rights', 'subtitle', 'summary', 'info', 'title', 'content')) && isset($attribs['']['type']) && $attribs['']['type'] == 'xhtml'))
10422 {
10423 $this->current_xhtml_construct = 0;
10424 }
10425 }
10426 }
10427
10428 function cdata($parser, $cdata)
10429 {
10430 if ($this->current_xhtml_construct >= 0)
10431 {
10432 $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
10433 }
10434 elseif ($this->feed > 1)
10435 {
10436 $this->data['data'] .= $cdata;
10437 }
10438 }
10439
10440 function tag_close($parser, $tag)
10441 {
10442 if (!$this->feed)
10443 {
10444 return;
10445 }
10446
10447 if ($this->current_xhtml_construct >= 0)
10448 {
10449 $this->current_xhtml_construct--;
10450 if (end($this->namespace) == SIMPLEPIE_NAMESPACE_XHTML && !in_array(end($this->element), array('area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param')))
10451 {
10452 $this->data['data'] .= '</' . end($this->element) . '>';
10453 }
10454 }
10455 if ($this->current_xhtml_construct == -1)
10456 {
10457 $this->data =& $this->datas[$this->feed];
10458 array_pop($this->datas);
10459 }
10460
10461 array_pop($this->element);
10462 array_pop($this->namespace);
10463 array_pop($this->xml_base);
10464 array_pop($this->xml_base_explicit);
10465 array_pop($this->xml_lang);
10466 $this->feed--;
10467 }
10468
10469 function split_ns($string)
10470 {
10471 static $cache = array();
10472 if (!isset($cache[$string]))
10473 {
10474 if ($pos = strpos($string, $this->separator))
10475 {
10476 static $separator_length;
10477 if (!$separator_length)
10478 {
10479 $separator_length = strlen($this->separator);
10480 }
10481 $cache[$string] = array(substr($string, 0, $pos), substr($string, $pos + $separator_length));
10482 }
10483 else
10484 {
10485 $cache[$string] = array('', $string);
10486 }
10487 }
10488 return $cache[$string];
10489 }
10490 }
10491
10492 /**
10493 * @todo Move to using an actual HTML parser (this will allow tags to be properly stripped, and to switch between HTML and XHTML), this will also make it easier to shortern a string while preserving HTML tags
10494 */
10495 class SimplePie_Sanitize
10496 {
10497 // Private vars
10498 var $base;
10499
10500 // Options
10501 var $remove_div = true;
10502 var $image_handler = '';
10503 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
10504 var $encode_instead_of_strip = false;
10505 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
10506 var $strip_comments = false;
10507 var $output_encoding = 'UTF-8';
10508 var $enable_cache = true;
10509 var $cache_location = './cache';
10510 var $cache_name_function = 'md5';
10511 var $cache_class = 'SimplePie_Cache';
10512 var $file_class = 'SimplePie_File';
10513 var $timeout = 10;
10514 var $useragent = '';
10515 var $force_fsockopen = false;
10516
10517 var $replace_url_attributes = array(
10518 'a' => 'href',
10519 'area' => 'href',
10520 'blockquote' => 'cite',
10521 'del' => 'cite',
10522 'form' => 'action',
10523 'img' => array('longdesc', 'src'),
10524 'input' => 'src',
10525 'ins' => 'cite',
10526 'q' => 'cite'
10527 );
10528
10529 function remove_div($enable = true)
10530 {
10531 $this->remove_div = (bool) $enable;
10532 }
10533
10534 function set_image_handler($page = false)
10535 {
10536 if ($page)
10537 {
10538 $this->image_handler = (string) $page;
10539 }
10540 else
10541 {
10542 $this->image_handler = false;
10543 }
10544 }
10545
10546 function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
10547 {
10548 if (isset($enable_cache))
10549 {
10550 $this->enable_cache = (bool) $enable_cache;
10551 }
10552
10553 if ($cache_location)
10554 {
10555 $this->cache_location = (string) $cache_location;
10556 }
10557
10558 if ($cache_name_function)
10559 {
10560 $this->cache_name_function = (string) $cache_name_function;
10561 }
10562
10563 if ($cache_class)
10564 {
10565 $this->cache_class = (string) $cache_class;
10566 }
10567 }
10568
10569 function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
10570 {
10571 if ($file_class)
10572 {
10573 $this->file_class = (string) $file_class;
10574 }
10575
10576 if ($timeout)
10577 {
10578 $this->timeout = (string) $timeout;
10579 }
10580
10581 if ($useragent)
10582 {
10583 $this->useragent = (string) $useragent;
10584 }
10585
10586 if ($force_fsockopen)
10587 {
10588 $this->force_fsockopen = (string) $force_fsockopen;
10589 }
10590 }
10591
10592 function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
10593 {
10594 if ($tags)
10595 {
10596 if (is_array($tags))
10597 {
10598 $this->strip_htmltags = $tags;
10599 }
10600 else
10601 {
10602 $this->strip_htmltags = explode(',', $tags);
10603 }
10604 }
10605 else
10606 {
10607 $this->strip_htmltags = false;
10608 }
10609 }
10610
10611 function encode_instead_of_strip($encode = false)
10612 {
10613 $this->encode_instead_of_strip = (bool) $encode;
10614 }
10615
10616 function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
10617 {
10618 if ($attribs)
10619 {
10620 if (is_array($attribs))
10621 {
10622 $this->strip_attributes = $attribs;
10623 }
10624 else
10625 {
10626 $this->strip_attributes = explode(',', $attribs);
10627 }
10628 }
10629 else
10630 {
10631 $this->strip_attributes = false;
10632 }
10633 }
10634
10635 function strip_comments($strip = false)
10636 {
10637 $this->strip_comments = (bool) $strip;
10638 }
10639
10640 function set_output_encoding($encoding = 'UTF-8')
10641 {
10642 $this->output_encoding = (string) $encoding;
10643 }
10644
10645 /**
10646 * Set element/attribute key/value pairs of HTML attributes
10647 * containing URLs that need to be resolved relative to the feed
10648 *
10649 * @access public
10650 * @since 1.0
10651 * @param array $element_attribute Element/attribute key/value pairs
10652 */
10653 function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
10654 {
10655 $this->replace_url_attributes = (array) $element_attribute;
10656 }
10657
10658 function sanitize($data, $type, $base = '')
10659 {
10660 $data = trim($data);
10661 if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
10662 {
10663 if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
10664 {
10665 if (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\/(\w+)' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data))
10666 {
10667 $type |= SIMPLEPIE_CONSTRUCT_HTML;
10668 }
10669 else
10670 {
10671 $type |= SIMPLEPIE_CONSTRUCT_TEXT;
10672 }
10673 }
10674
10675 if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
10676 {
10677 $data = base64_decode($data);
10678 }
10679
10680 if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
10681 {
10682 if ($this->remove_div)
10683 {
10684 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
10685 $data = preg_replace('/<\/div>$/', '', $data);
10686 }
10687 else
10688 {
10689 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
10690 }
10691 }
10692
10693 if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
10694 {
10695 // Strip comments
10696 if ($this->strip_comments)
10697 {
10698 $data = SimplePie_Misc::strip_comments($data);
10699 }
10700
10701 // Strip out HTML tags and attributes that might cause various security problems.
10702 // Based on recommendations by Mark Pilgrim at:
10703 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
10704 if ($this->strip_htmltags)
10705 {
10706 foreach ($this->strip_htmltags as $tag)
10707 {
10708 $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
10709 while (preg_match($pcre, $data))
10710 {
10711 $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
10712 }
10713 }
10714 }
10715
10716 if ($this->strip_attributes)
10717 {
10718 foreach ($this->strip_attributes as $attrib)
10719 {
10720 $data = preg_replace('/ '. trim($attrib) .'=("|&quot;)(\w|\s|=|-|:|;|\/|\.|\?|&|,|#|!|\(|\)|\'|&apos;|<|>|\+|{|})*("|&quot;)/i', '', $data);
10721 $data = preg_replace('/ '. trim($attrib) .'=(\'|&apos;)(\w|\s|=|-|:|;|\/|\.|\?|&|,|#|!|\(|\)|"|&quot;|<|>|\+|{|})*(\'|&apos;)/i', '', $data);
10722 $data = preg_replace('/ '. trim($attrib) .'=(\w|\s|=|-|:|;|\/|\.|\?|&|,|#|!|\(|\)|\+|{|})*/i', '', $data);
10723 }
10724 }
10725
10726 // Replace relative URLs
10727 $this->base = $base;
10728 foreach ($this->replace_url_attributes as $element => $attributes)
10729 {
10730 $data = $this->replace_urls($data, $element, $attributes);
10731 }
10732
10733 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
10734 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
10735 {
10736 $images = SimplePie_Misc::get_element('img', $data);
10737 foreach ($images as $img)
10738 {
10739 if (isset($img['attribs']['src']['data']))
10740 {
10741 $image_url = $img['attribs']['src']['data'];
10742 $cache =& new $this->cache_class($this->cache_location, call_user_func($this->cache_name_function, $image_url), 'spi');
10743
10744 if ($cache->load())
10745 {
10746 $img['attribs']['src']['data'] = $this->image_handler . rawurlencode($img['attribs']['src']['data']);
10747 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
10748 }
10749 else
10750 {
10751 $file =& new $this->file_class($image_url, $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
10752 $headers = $file->headers;
10753
10754 if ($file->success && ($file->status_code == 200 || ($file->status_code > 206 && $file->status_code < 300)))
10755 {
10756 if (!$cache->save(array('headers' => $file->headers, 'body' => $file->body)))
10757 {
10758 trigger_error("$cache->name is not writeable", E_USER_WARNING);
10759 }
10760 $img['attribs']['src']['data'] = $this->image_handler . rawurlencode($img['attribs']['src']['data']);
10761 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
10762 }
10763 }
10764 }
10765 }
10766 }
10767
10768 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
10769 $data = trim($data);
10770 }
10771
10772 if ($type & SIMPLEPIE_CONSTRUCT_IRI)
10773 {
10774 $data = SimplePie_Misc::absolutize_url($data, $base);
10775 }
10776
10777 if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
10778 {
10779 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
10780 }
10781
10782 if ($this->output_encoding != 'UTF-8')
10783 {
10784 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
10785 }
10786 }
10787 return $data;
10788 }
10789
10790 function replace_urls($data, $tag, $attributes)
10791 {
10792 if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
10793 {
10794 $elements = SimplePie_Misc::get_element($tag, $data);
10795 foreach ($elements as $element)
10796 {
10797 if (is_array($attributes))
10798 {
10799 foreach ($attributes as $attribute)
10800 {
10801 if (isset($element['attribs'][$attribute]['data']))
10802 {
10803 $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
10804 $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
10805 }
10806 }
10807 }
10808 elseif (isset($element['attribs'][$attributes]['data']))
10809 {
10810 $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
10811 $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
10812 }
10813 }
10814 }
10815 return $data;
10816 }
10817
10818 function do_strip_htmltags($match)
10819 {
10820 if ($this->encode_instead_of_strip)
10821 {
10822 if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
10823 {
10824 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
10825 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
10826 return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
10827 }
10828 else
10829 {
10830 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
10831 }
10832 }
10833 elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
10834 {
10835 return $match[4];
10836 }
10837 else
10838 {
10839 return '';
10840 }
10841 }
10842 }
10843
10844 ?>