Assignment MDL-22843
[moodle.git] / lib / simplepie / simplepie.inc
CommitLineData
80d72d56 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 *
ec00bfc5 8 * Copyright (c) 2004-2009, Ryan Parman and Geoffrey Sneddon
80d72d56 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
ec00bfc5 36 * @version 1.2
37 * @copyright 2004-2009 Ryan Parman, Geoffrey Sneddon
80d72d56 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 */
49define('SIMPLEPIE_NAME', 'SimplePie');
50
51/**
52 * SimplePie Version
53 */
ec00bfc5 54define('SIMPLEPIE_VERSION', '1.2');
80d72d56 55
56/**
57 * SimplePie Build
58 */
ec00bfc5 59define('SIMPLEPIE_BUILD', '20090627192103');
80d72d56 60
61/**
62 * SimplePie Website URL
63 */
64define('SIMPLEPIE_URL', 'http://simplepie.org');
65
66/**
67 * SimplePie Useragent
68 * @see SimplePie::set_useragent()
69 */
70define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
71
72/**
73 * SimplePie Linkback
74 */
75define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
76
77/**
78 * No Autodiscovery
79 * @see SimplePie::set_autodiscovery_level()
80 */
81define('SIMPLEPIE_LOCATOR_NONE', 0);
82
83/**
84 * Feed Link Element Autodiscovery
85 * @see SimplePie::set_autodiscovery_level()
86 */
87define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
88
89/**
90 * Local Feed Extension Autodiscovery
91 * @see SimplePie::set_autodiscovery_level()
92 */
93define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
94
95/**
96 * Local Feed Body Autodiscovery
97 * @see SimplePie::set_autodiscovery_level()
98 */
99define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
100
101/**
102 * Remote Feed Extension Autodiscovery
103 * @see SimplePie::set_autodiscovery_level()
104 */
105define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
106
107/**
108 * Remote Feed Body Autodiscovery
109 * @see SimplePie::set_autodiscovery_level()
110 */
111define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
112
113/**
114 * All Feed Autodiscovery
115 * @see SimplePie::set_autodiscovery_level()
116 */
117define('SIMPLEPIE_LOCATOR_ALL', 31);
118
119/**
120 * No known feed type
121 */
122define('SIMPLEPIE_TYPE_NONE', 0);
123
124/**
125 * RSS 0.90
126 */
127define('SIMPLEPIE_TYPE_RSS_090', 1);
128
129/**
130 * RSS 0.91 (Netscape)
131 */
132define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
133
134/**
135 * RSS 0.91 (Userland)
136 */
137define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
138
139/**
140 * RSS 0.91 (both Netscape and Userland)
141 */
142define('SIMPLEPIE_TYPE_RSS_091', 6);
143
144/**
145 * RSS 0.92
146 */
147define('SIMPLEPIE_TYPE_RSS_092', 8);
148
149/**
150 * RSS 0.93
151 */
152define('SIMPLEPIE_TYPE_RSS_093', 16);
153
154/**
155 * RSS 0.94
156 */
157define('SIMPLEPIE_TYPE_RSS_094', 32);
158
159/**
160 * RSS 1.0
161 */
162define('SIMPLEPIE_TYPE_RSS_10', 64);
163
164/**
165 * RSS 2.0
166 */
167define('SIMPLEPIE_TYPE_RSS_20', 128);
168
169/**
170 * RDF-based RSS
171 */
172define('SIMPLEPIE_TYPE_RSS_RDF', 65);
173
174/**
175 * Non-RDF-based RSS (truly intended as syndication format)
176 */
177define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
178
179/**
180 * All RSS
181 */
182define('SIMPLEPIE_TYPE_RSS_ALL', 255);
183
184/**
185 * Atom 0.3
186 */
187define('SIMPLEPIE_TYPE_ATOM_03', 256);
188
189/**
190 * Atom 1.0
191 */
192define('SIMPLEPIE_TYPE_ATOM_10', 512);
193
194/**
195 * All Atom
196 */
197define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
198
199/**
200 * All feed types
201 */
202define('SIMPLEPIE_TYPE_ALL', 1023);
203
204/**
205 * No construct
206 */
207define('SIMPLEPIE_CONSTRUCT_NONE', 0);
208
209/**
210 * Text construct
211 */
212define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
213
214/**
215 * HTML construct
216 */
217define('SIMPLEPIE_CONSTRUCT_HTML', 2);
218
219/**
220 * XHTML construct
221 */
222define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
223
224/**
225 * base64-encoded construct
226 */
227define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
228
229/**
230 * IRI construct
231 */
232define('SIMPLEPIE_CONSTRUCT_IRI', 16);
233
234/**
235 * A construct that might be HTML
236 */
237define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
238
239/**
240 * All constructs
241 */
242define('SIMPLEPIE_CONSTRUCT_ALL', 63);
243
ec00bfc5 244/**
245 * Don't change case
246 */
247define('SIMPLEPIE_SAME_CASE', 1);
248
249/**
250 * Change to lowercase
251 */
252define('SIMPLEPIE_LOWERCASE', 2);
253
254/**
255 * Change to uppercase
256 */
257define('SIMPLEPIE_UPPERCASE', 4);
258
80d72d56 259/**
260 * PCRE for HTML attributes
261 */
262define('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*');
263
264/**
265 * PCRE for XML attributes
266 */
267define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
268
269/**
270 * XML Namespace
271 */
272define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
273
274/**
275 * Atom 1.0 Namespace
276 */
277define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
278
279/**
280 * Atom 0.3 Namespace
281 */
282define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
283
284/**
285 * RDF Namespace
286 */
287define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
288
289/**
290 * RSS 0.90 Namespace
291 */
292define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
293
294/**
295 * RSS 1.0 Namespace
296 */
297define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
298
299/**
300 * RSS 1.0 Content Module Namespace
301 */
302define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
303
304/**
305 * RSS 2.0 Namespace
306 * (Stupid, I know, but I'm certain it will confuse people less with support.)
307 */
308define('SIMPLEPIE_NAMESPACE_RSS_20', '');
309
310/**
311 * DC 1.0 Namespace
312 */
313define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
314
315/**
316 * DC 1.1 Namespace
317 */
318define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
319
320/**
321 * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
322 */
323define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
324
325/**
326 * GeoRSS Namespace
327 */
328define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
329
330/**
331 * Media RSS Namespace
332 */
333define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
334
335/**
336 * Wrong Media RSS Namespace
337 */
338define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
339
340/**
341 * iTunes RSS Namespace
342 */
343define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
344
345/**
346 * XHTML Namespace
347 */
348define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
349
350/**
351 * IANA Link Relations Registry
352 */
353define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
354
355/**
356 * Whether we're running on PHP5
357 */
358define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
359
360/**
361 * No file source
362 */
363define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
364
365/**
366 * Remote file source
367 */
368define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
369
370/**
371 * Local file source
372 */
373define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
374
375/**
376 * fsockopen() file source
377 */
378define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
379
380/**
381 * cURL file source
382 */
383define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
384
385/**
386 * file_get_contents() file source
387 */
388define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
389
390/**
391 * SimplePie
392 *
393 * @package SimplePie
80d72d56 394 */
395class SimplePie
396{
397 /**
398 * @var array Raw data
399 * @access private
400 */
401 var $data = array();
402
403 /**
404 * @var mixed Error string
405 * @access private
406 */
407 var $error;
408
409 /**
410 * @var object Instance of SimplePie_Sanitize (or other class)
411 * @see SimplePie::set_sanitize_class()
412 * @access private
413 */
414 var $sanitize;
415
416 /**
417 * @var string SimplePie Useragent
418 * @see SimplePie::set_useragent()
419 * @access private
420 */
421 var $useragent = SIMPLEPIE_USERAGENT;
422
423 /**
424 * @var string Feed URL
425 * @see SimplePie::set_feed_url()
426 * @access private
427 */
428 var $feed_url;
429
430 /**
431 * @var object Instance of SimplePie_File to use as a feed
432 * @see SimplePie::set_file()
433 * @access private
434 */
435 var $file;
436
437 /**
438 * @var string Raw feed data
439 * @see SimplePie::set_raw_data()
440 * @access private
441 */
442 var $raw_data;
443
444 /**
445 * @var int Timeout for fetching remote files
446 * @see SimplePie::set_timeout()
447 * @access private
448 */
449 var $timeout = 10;
450
451 /**
452 * @var bool Forces fsockopen() to be used for remote files instead
453 * of cURL, even if a new enough version is installed
454 * @see SimplePie::force_fsockopen()
455 * @access private
456 */
457 var $force_fsockopen = false;
458
459 /**
460 * @var bool Force the given data/URL to be treated as a feed no matter what
461 * it appears like
462 * @see SimplePie::force_feed()
463 * @access private
464 */
465 var $force_feed = false;
466
467 /**
468 * @var bool Enable/Disable XML dump
469 * @see SimplePie::enable_xml_dump()
470 * @access private
471 */
472 var $xml_dump = false;
473
474 /**
475 * @var bool Enable/Disable Caching
476 * @see SimplePie::enable_cache()
477 * @access private
478 */
479 var $cache = true;
480
481 /**
482 * @var int Cache duration (in seconds)
483 * @see SimplePie::set_cache_duration()
484 * @access private
485 */
486 var $cache_duration = 3600;
487
488 /**
489 * @var int Auto-discovery cache duration (in seconds)
490 * @see SimplePie::set_autodiscovery_cache_duration()
491 * @access private
492 */
493 var $autodiscovery_cache_duration = 604800; // 7 Days.
494
495 /**
496 * @var string Cache location (relative to executing script)
497 * @see SimplePie::set_cache_location()
498 * @access private
499 */
500 var $cache_location = './cache';
501
502 /**
503 * @var string Function that creates the cache filename
504 * @see SimplePie::set_cache_name_function()
505 * @access private
506 */
507 var $cache_name_function = 'md5';
508
509 /**
510 * @var bool Reorder feed by date descending
511 * @see SimplePie::enable_order_by_date()
512 * @access private
513 */
514 var $order_by_date = true;
515
516 /**
517 * @var mixed Force input encoding to be set to the follow value
518 * (false, or anything type-cast to false, disables this feature)
519 * @see SimplePie::set_input_encoding()
520 * @access private
521 */
522 var $input_encoding = false;
523
524 /**
525 * @var int Feed Autodiscovery Level
526 * @see SimplePie::set_autodiscovery_level()
527 * @access private
528 */
529 var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
530
531 /**
532 * @var string Class used for caching feeds
533 * @see SimplePie::set_cache_class()
534 * @access private
535 */
536 var $cache_class = 'SimplePie_Cache';
537
538 /**
539 * @var string Class used for locating feeds
540 * @see SimplePie::set_locator_class()
541 * @access private
542 */
543 var $locator_class = 'SimplePie_Locator';
544
545 /**
546 * @var string Class used for parsing feeds
547 * @see SimplePie::set_parser_class()
548 * @access private
549 */
550 var $parser_class = 'SimplePie_Parser';
551
552 /**
553 * @var string Class used for fetching feeds
554 * @see SimplePie::set_file_class()
555 * @access private
556 */
557 var $file_class = 'SimplePie_File';
558
559 /**
560 * @var string Class used for items
561 * @see SimplePie::set_item_class()
562 * @access private
563 */
564 var $item_class = 'SimplePie_Item';
565
566 /**
567 * @var string Class used for authors
568 * @see SimplePie::set_author_class()
569 * @access private
570 */
571 var $author_class = 'SimplePie_Author';
572
573 /**
574 * @var string Class used for categories
575 * @see SimplePie::set_category_class()
576 * @access private
577 */
578 var $category_class = 'SimplePie_Category';
579
580 /**
581 * @var string Class used for enclosures
582 * @see SimplePie::set_enclosures_class()
583 * @access private
584 */
585 var $enclosure_class = 'SimplePie_Enclosure';
586
587 /**
588 * @var string Class used for Media RSS <media:text> captions
589 * @see SimplePie::set_caption_class()
590 * @access private
591 */
592 var $caption_class = 'SimplePie_Caption';
593
594 /**
595 * @var string Class used for Media RSS <media:copyright>
596 * @see SimplePie::set_copyright_class()
597 * @access private
598 */
599 var $copyright_class = 'SimplePie_Copyright';
600
601 /**
602 * @var string Class used for Media RSS <media:credit>
603 * @see SimplePie::set_credit_class()
604 * @access private
605 */
606 var $credit_class = 'SimplePie_Credit';
607
608 /**
609 * @var string Class used for Media RSS <media:rating>
610 * @see SimplePie::set_rating_class()
611 * @access private
612 */
613 var $rating_class = 'SimplePie_Rating';
614
615 /**
616 * @var string Class used for Media RSS <media:restriction>
617 * @see SimplePie::set_restriction_class()
618 * @access private
619 */
620 var $restriction_class = 'SimplePie_Restriction';
621
622 /**
623 * @var string Class used for content-type sniffing
624 * @see SimplePie::set_content_type_sniffer_class()
625 * @access private
626 */
627 var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
628
629 /**
630 * @var string Class used for item sources.
631 * @see SimplePie::set_source_class()
632 * @access private
633 */
634 var $source_class = 'SimplePie_Source';
635
636 /**
637 * @var mixed Set javascript query string parameter (false, or
638 * anything type-cast to false, disables this feature)
639 * @see SimplePie::set_javascript()
640 * @access private
641 */
642 var $javascript = 'js';
643
644 /**
645 * @var int Maximum number of feeds to check with autodiscovery
646 * @see SimplePie::set_max_checked_feeds()
647 * @access private
648 */
649 var $max_checked_feeds = 10;
650
ec00bfc5 651 /**
652 * @var array All the feeds found during the autodiscovery process
653 * @see SimplePie::get_all_discovered_feeds()
654 * @access private
655 */
656 var $all_discovered_feeds = array();
657
80d72d56 658 /**
659 * @var string Web-accessible path to the handler_favicon.php file.
660 * @see SimplePie::set_favicon_handler()
661 * @access private
662 */
663 var $favicon_handler = '';
664
665 /**
666 * @var string Web-accessible path to the handler_image.php file.
667 * @see SimplePie::set_image_handler()
668 * @access private
669 */
670 var $image_handler = '';
671
672 /**
673 * @var array Stores the URLs when multiple feeds are being initialized.
674 * @see SimplePie::set_feed_url()
675 * @access private
676 */
677 var $multifeed_url = array();
678
679 /**
680 * @var array Stores SimplePie objects when multiple feeds initialized.
681 * @access private
682 */
683 var $multifeed_objects = array();
684
685 /**
686 * @var array Stores the get_object_vars() array for use with multifeeds.
687 * @see SimplePie::set_feed_url()
688 * @access private
689 */
690 var $config_settings = null;
691
692 /**
693 * @var integer Stores the number of items to return per-feed with multifeeds.
694 * @see SimplePie::set_item_limit()
695 * @access private
696 */
697 var $item_limit = 0;
698
699 /**
700 * @var array Stores the default attributes to be stripped by strip_attributes().
701 * @see SimplePie::strip_attributes()
702 * @access private
703 */
704 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
705
706 /**
707 * @var array Stores the default tags to be stripped by strip_htmltags().
708 * @see SimplePie::strip_htmltags()
709 * @access private
710 */
711 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
712
713 /**
714 * The SimplePie class contains feed level data and options
715 *
716 * There are two ways that you can create a new SimplePie object. The first
717 * is by passing a feed URL as a parameter to the SimplePie constructor
718 * (as well as optionally setting the cache location and cache expiry). This
719 * will initialise the whole feed with all of the default settings, and you
720 * can begin accessing methods and properties immediately.
721 *
722 * The second way is to create the SimplePie object with no parameters
723 * at all. This will enable you to set configuration options. After setting
724 * them, you must initialise the feed using $feed->init(). At that point the
725 * object's methods and properties will be available to you. This format is
726 * what is used throughout this documentation.
727 *
728 * @access public
729 * @since 1.0 Preview Release
730 * @param string $feed_url This is the URL you want to parse.
731 * @param string $cache_location This is where you want the cache to be stored.
732 * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
733 */
734 function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
735 {
736 // Other objects, instances created here so we can set options on them
737 $this->sanitize =& new SimplePie_Sanitize;
738
739 // Set options if they're passed to the constructor
740 if ($cache_location !== null)
741 {
742 $this->set_cache_location($cache_location);
743 }
744
745 if ($cache_duration !== null)
746 {
747 $this->set_cache_duration($cache_duration);
748 }
749
750 // Only init the script if we're passed a feed URL
751 if ($feed_url !== null)
752 {
753 $this->set_feed_url($feed_url);
754 $this->init();
755 }
756 }
757
758 /**
759 * Used for converting object to a string
760 */
761 function __toString()
762 {
763 return md5(serialize($this->data));
764 }
765
766 /**
767 * Remove items that link back to this before destroying this object
768 */
769 function __destruct()
770 {
ec00bfc5 771 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
80d72d56 772 {
ec00bfc5 773 if (!empty($this->data['items']))
80d72d56 774 {
ec00bfc5 775 foreach ($this->data['items'] as $item)
776 {
777 $item->__destruct();
778 }
779 unset($item, $this->data['items']);
80d72d56 780 }
ec00bfc5 781 if (!empty($this->data['ordered_items']))
80d72d56 782 {
ec00bfc5 783 foreach ($this->data['ordered_items'] as $item)
784 {
785 $item->__destruct();
786 }
787 unset($item, $this->data['ordered_items']);
80d72d56 788 }
80d72d56 789 }
790 }
791
792 /**
793 * Force the given data/URL to be treated as a feed no matter what it
794 * appears like
795 *
796 * @access public
797 * @since 1.1
798 * @param bool $enable Force the given data/URL to be treated as a feed
799 */
800 function force_feed($enable = false)
801 {
802 $this->force_feed = (bool) $enable;
803 }
804
805 /**
806 * This is the URL of the feed you want to parse.
807 *
808 * This allows you to enter the URL of the feed you want to parse, or the
809 * website you want to try to use auto-discovery on. This takes priority
810 * over any set raw data.
811 *
812 * You can set multiple feeds to mash together by passing an array instead
813 * of a string for the $url. Remember that with each additional feed comes
814 * additional processing and resources.
815 *
816 * @access public
817 * @since 1.0 Preview Release
818 * @param mixed $url This is the URL (or array of URLs) that you want to parse.
819 * @see SimplePie::set_raw_data()
820 */
821 function set_feed_url($url)
822 {
823 if (is_array($url))
824 {
825 $this->multifeed_url = array();
826 foreach ($url as $value)
827 {
828 $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
829 }
830 }
831 else
832 {
833 $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
834 }
835 }
836
837 /**
838 * Provides an instance of SimplePie_File to use as a feed
839 *
840 * @access public
841 * @param object &$file Instance of SimplePie_File (or subclass)
842 * @return bool True on success, false on failure
843 */
844 function set_file(&$file)
845 {
846 if (is_a($file, 'SimplePie_File'))
847 {
848 $this->feed_url = $file->url;
849 $this->file =& $file;
850 return true;
851 }
852 return false;
853 }
854
855 /**
856 * Allows you to use a string of RSS/Atom data instead of a remote feed.
857 *
858 * If you have a feed available as a string in PHP, you can tell SimplePie
859 * to parse that data string instead of a remote feed. Any set feed URL
860 * takes precedence.
861 *
862 * @access public
863 * @since 1.0 Beta 3
864 * @param string $data RSS or Atom data as a string.
865 * @see SimplePie::set_feed_url()
866 */
867 function set_raw_data($data)
868 {
869 $this->raw_data = $data;
870 }
871
872 /**
873 * Allows you to override the default timeout for fetching remote feeds.
874 *
875 * This allows you to change the maximum time the feed's server to respond
876 * and send the feed back.
877 *
878 * @access public
879 * @since 1.0 Beta 3
880 * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
881 */
882 function set_timeout($timeout = 10)
883 {
884 $this->timeout = (int) $timeout;
885 }
886
887 /**
888 * Forces SimplePie to use fsockopen() instead of the preferred cURL
889 * functions.
890 *
891 * @access public
892 * @since 1.0 Beta 3
893 * @param bool $enable Force fsockopen() to be used
894 */
895 function force_fsockopen($enable = false)
896 {
897 $this->force_fsockopen = (bool) $enable;
898 }
899
900 /**
901 * Outputs the raw XML content of the feed, after it has gone through
902 * SimplePie's filters.
903 *
904 * Used only for debugging, this function will output the XML content as
905 * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
906 * before trying to parse it. Many parts of the feed are re-written in
907 * memory, and in the end, you have a parsable feed. XML dump shows you the
908 * actual XML that SimplePie tries to parse, which may or may not be very
909 * different from the original feed.
910 *
911 * @access public
912 * @since 1.0 Preview Release
913 * @param bool $enable Enable XML dump
914 */
915 function enable_xml_dump($enable = false)
916 {
917 $this->xml_dump = (bool) $enable;
918 }
919
920 /**
921 * Enables/disables caching in SimplePie.
922 *
923 * This option allows you to disable caching all-together in SimplePie.
924 * However, disabling the cache can lead to longer load times.
925 *
926 * @access public
927 * @since 1.0 Preview Release
928 * @param bool $enable Enable caching
929 */
930 function enable_cache($enable = true)
931 {
932 $this->cache = (bool) $enable;
933 }
934
935 /**
936 * Set the length of time (in seconds) that the contents of a feed
937 * will be cached.
938 *
939 * @access public
940 * @param int $seconds The feed content cache duration.
941 */
942 function set_cache_duration($seconds = 3600)
943 {
944 $this->cache_duration = (int) $seconds;
945 }
946
947 /**
948 * Set the length of time (in seconds) that the autodiscovered feed
949 * URL will be cached.
950 *
951 * @access public
952 * @param int $seconds The autodiscovered feed URL cache duration.
953 */
954 function set_autodiscovery_cache_duration($seconds = 604800)
955 {
956 $this->autodiscovery_cache_duration = (int) $seconds;
957 }
958
959 /**
960 * Set the file system location where the cached files should be stored.
961 *
962 * @access public
963 * @param string $location The file system location.
964 */
965 function set_cache_location($location = './cache')
966 {
967 $this->cache_location = (string) $location;
968 }
969
970 /**
971 * Determines whether feed items should be sorted into reverse chronological order.
972 *
973 * @access public
974 * @param bool $enable Sort as reverse chronological order.
975 */
976 function enable_order_by_date($enable = true)
977 {
978 $this->order_by_date = (bool) $enable;
979 }
980
981 /**
982 * Allows you to override the character encoding reported by the feed.
983 *
984 * @access public
985 * @param string $encoding Character encoding.
986 */
987 function set_input_encoding($encoding = false)
988 {
989 if ($encoding)
990 {
991 $this->input_encoding = (string) $encoding;
992 }
993 else
994 {
995 $this->input_encoding = false;
996 }
997 }
998
999 /**
1000 * Set how much feed autodiscovery to do
1001 *
1002 * @access public
1003 * @see SIMPLEPIE_LOCATOR_NONE
1004 * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
1005 * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
1006 * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
1007 * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
1008 * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
1009 * @see SIMPLEPIE_LOCATOR_ALL
1010 * @param int $level Feed Autodiscovery Level (level can be a
1011 * combination of the above constants, see bitwise OR operator)
1012 */
1013 function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
1014 {
1015 $this->autodiscovery = (int) $level;
1016 }
1017
1018 /**
1019 * Allows you to change which class SimplePie uses for caching.
1020 * Useful when you are overloading or extending SimplePie's default classes.
1021 *
1022 * @access public
1023 * @param string $class Name of custom class.
1024 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1025 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1026 */
1027 function set_cache_class($class = 'SimplePie_Cache')
1028 {
1029 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
1030 {
1031 $this->cache_class = $class;
1032 return true;
1033 }
1034 return false;
1035 }
1036
1037 /**
1038 * Allows you to change which class SimplePie uses for auto-discovery.
1039 * Useful when you are overloading or extending SimplePie's default classes.
1040 *
1041 * @access public
1042 * @param string $class Name of custom class.
1043 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1044 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1045 */
1046 function set_locator_class($class = 'SimplePie_Locator')
1047 {
1048 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
1049 {
1050 $this->locator_class = $class;
1051 return true;
1052 }
1053 return false;
1054 }
1055
1056 /**
1057 * Allows you to change which class SimplePie uses for XML parsing.
1058 * Useful when you are overloading or extending SimplePie's default classes.
1059 *
1060 * @access public
1061 * @param string $class Name of custom class.
1062 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1063 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1064 */
1065 function set_parser_class($class = 'SimplePie_Parser')
1066 {
1067 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
1068 {
1069 $this->parser_class = $class;
1070 return true;
1071 }
1072 return false;
1073 }
1074
1075 /**
1076 * Allows you to change which class SimplePie uses for remote file fetching.
1077 * Useful when you are overloading or extending SimplePie's default classes.
1078 *
1079 * @access public
1080 * @param string $class Name of custom class.
1081 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1082 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1083 */
1084 function set_file_class($class = 'SimplePie_File')
1085 {
1086 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
1087 {
1088 $this->file_class = $class;
1089 return true;
1090 }
1091 return false;
1092 }
1093
1094 /**
1095 * Allows you to change which class SimplePie uses for data sanitization.
1096 * Useful when you are overloading or extending SimplePie's default classes.
1097 *
1098 * @access public
1099 * @param string $class Name of custom class.
1100 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1101 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1102 */
1103 function set_sanitize_class($class = 'SimplePie_Sanitize')
1104 {
1105 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
1106 {
1107 $this->sanitize =& new $class;
1108 return true;
1109 }
1110 return false;
1111 }
1112
1113 /**
1114 * Allows you to change which class SimplePie uses for handling feed items.
1115 * Useful when you are overloading or extending SimplePie's default classes.
1116 *
1117 * @access public
1118 * @param string $class Name of custom class.
1119 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1120 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1121 */
1122 function set_item_class($class = 'SimplePie_Item')
1123 {
1124 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
1125 {
1126 $this->item_class = $class;
1127 return true;
1128 }
1129 return false;
1130 }
1131
1132 /**
1133 * Allows you to change which class SimplePie uses for handling author data.
1134 * Useful when you are overloading or extending SimplePie's default classes.
1135 *
1136 * @access public
1137 * @param string $class Name of custom class.
1138 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1139 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1140 */
1141 function set_author_class($class = 'SimplePie_Author')
1142 {
1143 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
1144 {
1145 $this->author_class = $class;
1146 return true;
1147 }
1148 return false;
1149 }
1150
1151 /**
1152 * Allows you to change which class SimplePie uses for handling category data.
1153 * Useful when you are overloading or extending SimplePie's default classes.
1154 *
1155 * @access public
1156 * @param string $class Name of custom class.
1157 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1158 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1159 */
1160 function set_category_class($class = 'SimplePie_Category')
1161 {
1162 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
1163 {
1164 $this->category_class = $class;
1165 return true;
1166 }
1167 return false;
1168 }
1169
1170 /**
1171 * Allows you to change which class SimplePie uses for feed enclosures.
1172 * Useful when you are overloading or extending SimplePie's default classes.
1173 *
1174 * @access public
1175 * @param string $class Name of custom class.
1176 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1177 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1178 */
1179 function set_enclosure_class($class = 'SimplePie_Enclosure')
1180 {
1181 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
1182 {
1183 $this->enclosure_class = $class;
1184 return true;
1185 }
1186 return false;
1187 }
1188
1189 /**
1190 * Allows you to change which class SimplePie uses for <media:text> captions
1191 * Useful when you are overloading or extending SimplePie's default classes.
1192 *
1193 * @access public
1194 * @param string $class Name of custom class.
1195 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1196 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1197 */
1198 function set_caption_class($class = 'SimplePie_Caption')
1199 {
1200 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
1201 {
1202 $this->caption_class = $class;
1203 return true;
1204 }
1205 return false;
1206 }
1207
1208 /**
1209 * Allows you to change which class SimplePie uses for <media:copyright>
1210 * Useful when you are overloading or extending SimplePie's default classes.
1211 *
1212 * @access public
1213 * @param string $class Name of custom class.
1214 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1215 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1216 */
1217 function set_copyright_class($class = 'SimplePie_Copyright')
1218 {
1219 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
1220 {
1221 $this->copyright_class = $class;
1222 return true;
1223 }
1224 return false;
1225 }
1226
1227 /**
1228 * Allows you to change which class SimplePie uses for <media:credit>
1229 * Useful when you are overloading or extending SimplePie's default classes.
1230 *
1231 * @access public
1232 * @param string $class Name of custom class.
1233 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1234 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1235 */
1236 function set_credit_class($class = 'SimplePie_Credit')
1237 {
1238 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
1239 {
1240 $this->credit_class = $class;
1241 return true;
1242 }
1243 return false;
1244 }
1245
1246 /**
1247 * Allows you to change which class SimplePie uses for <media:rating>
1248 * Useful when you are overloading or extending SimplePie's default classes.
1249 *
1250 * @access public
1251 * @param string $class Name of custom class.
1252 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1253 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1254 */
1255 function set_rating_class($class = 'SimplePie_Rating')
1256 {
1257 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
1258 {
1259 $this->rating_class = $class;
1260 return true;
1261 }
1262 return false;
1263 }
1264
1265 /**
1266 * Allows you to change which class SimplePie uses for <media:restriction>
1267 * Useful when you are overloading or extending SimplePie's default classes.
1268 *
1269 * @access public
1270 * @param string $class Name of custom class.
1271 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1272 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1273 */
1274 function set_restriction_class($class = 'SimplePie_Restriction')
1275 {
1276 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
1277 {
1278 $this->restriction_class = $class;
1279 return true;
1280 }
1281 return false;
1282 }
1283
1284 /**
1285 * Allows you to change which class SimplePie uses for content-type sniffing.
1286 * Useful when you are overloading or extending SimplePie's default classes.
1287 *
1288 * @access public
1289 * @param string $class Name of custom class.
1290 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1291 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1292 */
1293 function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1294 {
1295 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
1296 {
1297 $this->content_type_sniffer_class = $class;
1298 return true;
1299 }
1300 return false;
1301 }
1302
1303 /**
1304 * Allows you to change which class SimplePie uses item sources.
1305 * Useful when you are overloading or extending SimplePie's default classes.
1306 *
1307 * @access public
1308 * @param string $class Name of custom class.
1309 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1310 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1311 */
1312 function set_source_class($class = 'SimplePie_Source')
1313 {
1314 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
1315 {
1316 $this->source_class = $class;
1317 return true;
1318 }
1319 return false;
1320 }
1321
1322 /**
1323 * Allows you to override the default user agent string.
1324 *
1325 * @access public
1326 * @param string $ua New user agent string.
1327 */
1328 function set_useragent($ua = SIMPLEPIE_USERAGENT)
1329 {
1330 $this->useragent = (string) $ua;
1331 }
1332
1333 /**
1334 * Set callback function to create cache filename with
1335 *
1336 * @access public
1337 * @param mixed $function Callback function
1338 */
1339 function set_cache_name_function($function = 'md5')
1340 {
1341 if (is_callable($function))
1342 {
1343 $this->cache_name_function = $function;
1344 }
1345 }
1346
1347 /**
1348 * Set javascript query string parameter
1349 *
1350 * @access public
1351 * @param mixed $get Javascript query string parameter
1352 */
1353 function set_javascript($get = 'js')
1354 {
1355 if ($get)
1356 {
1357 $this->javascript = (string) $get;
1358 }
1359 else
1360 {
1361 $this->javascript = false;
1362 }
1363 }
1364
1365 /**
1366 * Set options to make SP as fast as possible. Forgoes a
1367 * substantial amount of data sanitization in favor of speed.
1368 *
1369 * @access public
1370 * @param bool $set Whether to set them or not
1371 */
1372 function set_stupidly_fast($set = false)
1373 {
1374 if ($set)
1375 {
1376 $this->enable_order_by_date(false);
1377 $this->remove_div(false);
1378 $this->strip_comments(false);
1379 $this->strip_htmltags(false);
1380 $this->strip_attributes(false);
1381 $this->set_image_handler(false);
1382 }
1383 }
1384
1385 /**
1386 * Set maximum number of feeds to check with autodiscovery
1387 *
1388 * @access public
1389 * @param int $max Maximum number of feeds to check
1390 */
1391 function set_max_checked_feeds($max = 10)
1392 {
1393 $this->max_checked_feeds = (int) $max;
1394 }
1395
1396 function remove_div($enable = true)
1397 {
1398 $this->sanitize->remove_div($enable);
1399 }
1400
1401 function strip_htmltags($tags = '', $encode = null)
1402 {
1403 if ($tags === '')
1404 {
1405 $tags = $this->strip_htmltags;
1406 }
1407 $this->sanitize->strip_htmltags($tags);
1408 if ($encode !== null)
1409 {
1410 $this->sanitize->encode_instead_of_strip($tags);
1411 }
1412 }
1413
1414 function encode_instead_of_strip($enable = true)
1415 {
1416 $this->sanitize->encode_instead_of_strip($enable);
1417 }
1418
1419 function strip_attributes($attribs = '')
1420 {
1421 if ($attribs === '')
1422 {
1423 $attribs = $this->strip_attributes;
1424 }
1425 $this->sanitize->strip_attributes($attribs);
1426 }
1427
1428 function set_output_encoding($encoding = 'UTF-8')
1429 {
1430 $this->sanitize->set_output_encoding($encoding);
1431 }
1432
1433 function strip_comments($strip = false)
1434 {
1435 $this->sanitize->strip_comments($strip);
1436 }
1437
1438 /**
1439 * Set element/attribute key/value pairs of HTML attributes
1440 * containing URLs that need to be resolved relative to the feed
1441 *
1442 * @access public
1443 * @since 1.0
1444 * @param array $element_attribute Element/attribute key/value pairs
1445 */
1446 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'))
1447 {
1448 $this->sanitize->set_url_replacements($element_attribute);
1449 }
1450
1451 /**
1452 * Set the handler to enable the display of cached favicons.
1453 *
1454 * @access public
1455 * @param str $page Web-accessible path to the handler_favicon.php file.
1456 * @param str $qs The query string that the value should be passed to.
1457 */
1458 function set_favicon_handler($page = false, $qs = 'i')
1459 {
ec00bfc5 1460 if ($page !== false)
80d72d56 1461 {
1462 $this->favicon_handler = $page . '?' . $qs . '=';
1463 }
1464 else
1465 {
1466 $this->favicon_handler = '';
1467 }
1468 }
1469
1470 /**
1471 * Set the handler to enable the display of cached images.
1472 *
1473 * @access public
1474 * @param str $page Web-accessible path to the handler_image.php file.
1475 * @param str $qs The query string that the value should be passed to.
1476 */
1477 function set_image_handler($page = false, $qs = 'i')
1478 {
ec00bfc5 1479 if ($page !== false)
80d72d56 1480 {
1481 $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1482 }
1483 else
1484 {
1485 $this->image_handler = '';
1486 }
1487 }
1488
1489 /**
1490 * Set the limit for items returned per-feed with multifeeds.
1491 *
1492 * @access public
1493 * @param integer $limit The maximum number of items to return.
1494 */
1495 function set_item_limit($limit = 0)
1496 {
1497 $this->item_limit = (int) $limit;
1498 }
1499
1500 function init()
1501 {
ec00bfc5 1502 // Check absolute bare minimum requirements.
80d72d56 1503 if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
1504 {
1505 return false;
1506 }
ec00bfc5 1507 // Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader.
1508 elseif (!extension_loaded('xmlreader'))
80d72d56 1509 {
ec00bfc5 1510 static $xml_is_sane = null;
1511 if ($xml_is_sane === null)
80d72d56 1512 {
ec00bfc5 1513 $parser_check = xml_parser_create();
1514 xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
1515 xml_parser_free($parser_check);
1516 $xml_is_sane = isset($values[0]['value']);
80d72d56 1517 }
ec00bfc5 1518 if (!$xml_is_sane)
1519 {
1520 return false;
1521 }
1522 }
80d72d56 1523
ec00bfc5 1524 if (isset($_GET[$this->javascript]))
1525 {
1526 SimplePie_Misc::output_javascript();
80d72d56 1527 exit;
1528 }
1529
1530 // Pass whatever was set with config options over to the sanitizer.
1531 $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
1532 $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
1533
1534 if ($this->feed_url !== null || $this->raw_data !== null)
1535 {
1536 $this->data = array();
1537 $this->multifeed_objects = array();
1538 $cache = false;
1539
1540 if ($this->feed_url !== null)
1541 {
1542 $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
1543 // Decide whether to enable caching
1544 if ($this->cache && $parsed_feed_url['scheme'] !== '')
1545 {
1546 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
1547 }
1548 // If it's enabled and we don't want an XML dump, use the cache
1549 if ($cache && !$this->xml_dump)
1550 {
1551 // Load the Cache
1552 $this->data = $cache->load();
1553 if (!empty($this->data))
1554 {
1555 // If the cache is for an outdated build of SimplePie
ec00bfc5 1556 if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
80d72d56 1557 {
1558 $cache->unlink();
1559 $this->data = array();
1560 }
1561 // If we've hit a collision just rerun it with caching disabled
ec00bfc5 1562 elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
80d72d56 1563 {
1564 $cache = false;
1565 $this->data = array();
1566 }
1567 // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1568 elseif (isset($this->data['feed_url']))
1569 {
1570 // If the autodiscovery cache is still valid use it.
1571 if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1572 {
1573 // Do not need to do feed autodiscovery yet.
ec00bfc5 1574 if ($this->data['feed_url'] === $this->data['url'])
80d72d56 1575 {
1576 $cache->unlink();
1577 $this->data = array();
1578 }
1579 else
1580 {
1581 $this->set_feed_url($this->data['feed_url']);
1582 return $this->init();
1583 }
1584 }
1585 }
1586 // Check if the cache has been updated
1587 elseif ($cache->mtime() + $this->cache_duration < time())
1588 {
1589 // If we have last-modified and/or etag set
1590 if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1591 {
1592 $headers = array();
1593 if (isset($this->data['headers']['last-modified']))
1594 {
1595 $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1596 }
1597 if (isset($this->data['headers']['etag']))
1598 {
1599 $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
1600 }
1601 $file =& new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
1602 if ($file->success)
1603 {
ec00bfc5 1604 if ($file->status_code === 304)
80d72d56 1605 {
1606 $cache->touch();
1607 return true;
1608 }
1609 else
1610 {
1611 $headers = $file->headers;
1612 }
1613 }
1614 else
1615 {
1616 unset($file);
1617 }
1618 }
1619 }
1620 // If the cache is still valid, just return true
1621 else
1622 {
1623 return true;
1624 }
1625 }
1626 // If the cache is empty, delete it
1627 else
1628 {
1629 $cache->unlink();
1630 $this->data = array();
1631 }
1632 }
1633 // 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.
1634 if (!isset($file))
1635 {
ec00bfc5 1636 if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
80d72d56 1637 {
1638 $file =& $this->file;
1639 }
1640 else
1641 {
1642 $file =& new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
1643 }
1644 }
1645 // If the file connection has an error, set SimplePie::error to that and quit
ec00bfc5 1646 if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
80d72d56 1647 {
1648 $this->error = $file->error;
1649 if (!empty($this->data))
1650 {
1651 return true;
1652 }
1653 else
1654 {
1655 return false;
1656 }
1657 }
1658
1659 if (!$this->force_feed)
1660 {
1661 // Check if the supplied URL is a feed, if it isn't, look for it.
1662 $locate =& new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
1663 if (!$locate->is_feed($file))
1664 {
1665 // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1666 unset($file);
ec00bfc5 1667 if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
80d72d56 1668 {
1669 if ($cache)
1670 {
1671 $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1672 if (!$cache->save($this))
1673 {
ec00bfc5 1674 trigger_error("$this->cache_location is not writeable", E_USER_WARNING);
80d72d56 1675 }
1676 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
1677 }
1678 $this->feed_url = $file->url;
1679 }
1680 else
1681 {
1682 $this->error = "A feed could not be found at $this->feed_url";
1683 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1684 return false;
1685 }
1686 }
1687 $locate = null;
1688 }
1689
1690 $headers = $file->headers;
1691 $data = $file->body;
ec00bfc5 1692 $sniffer =& new $this->content_type_sniffer_class($file);
80d72d56 1693 $sniffed = $sniffer->get_type();
1694 }
1695 else
1696 {
1697 $data = $this->raw_data;
1698 }
1699
1700 // Set up array of possible encodings
1701 $encodings = array();
1702
1703 // First check to see if input has been overridden.
1704 if ($this->input_encoding !== false)
1705 {
1706 $encodings[] = $this->input_encoding;
1707 }
1708
1709 $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1710 $text_types = array('text/xml', 'text/xml-external-parsed-entity');
1711
1712 // RFC 3023 (only applies to sniffed content)
1713 if (isset($sniffed))
1714 {
1715 if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1716 {
1717 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1718 {
1719 $encodings[] = strtoupper($charset[1]);
1720 }
1721 $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1722 $encodings[] = 'UTF-8';
1723 }
1724 elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1725 {
1726 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1727 {
1728 $encodings[] = $charset[1];
1729 }
1730 $encodings[] = 'US-ASCII';
1731 }
1732 // Text MIME-type default
1733 elseif (substr($sniffed, 0, 5) === 'text/')
1734 {
1735 $encodings[] = 'US-ASCII';
1736 }
1737 }
1738
1739 // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1740 $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1741 $encodings[] = 'UTF-8';
1742 $encodings[] = 'ISO-8859-1';
1743
1744 // There's no point in trying an encoding twice
1745 $encodings = array_unique($encodings);
1746
1747 // If we want the XML, just output that with the most likely encoding and quit
1748 if ($this->xml_dump)
1749 {
1750 header('Content-type: text/xml; charset=' . $encodings[0]);
1751 echo $data;
1752 exit;
1753 }
1754
1755 // Loop through each possible encoding, till we return something, or run out of possibilities
1756 foreach ($encodings as $encoding)
1757 {
1758 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1759 if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
1760 {
1761 // Create new parser
1762 $parser =& new $this->parser_class();
1763
1764 // If it's parsed fine
1765 if ($parser->parse($utf8_data, 'UTF-8'))
1766 {
1767 $this->data = $parser->get_data();
1768 if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
1769 {
1770 if (isset($headers))
1771 {
1772 $this->data['headers'] = $headers;
1773 }
1774 $this->data['build'] = SIMPLEPIE_BUILD;
1775
1776 // Cache the file if caching is enabled
1777 if ($cache && !$cache->save($this))
1778 {
1779 trigger_error("$cache->name is not writeable", E_USER_WARNING);
1780 }
1781 return true;
1782 }
1783 else
1784 {
1785 $this->error = "A feed could not be found at $this->feed_url";
1786 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1787 return false;
1788 }
1789 }
1790 }
1791 }
ec00bfc5 1792 if(isset($parser))
1793 {
1794 // We have an error, just set SimplePie_Misc::error to it and quit
1795 $this->error = sprintf('XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
1796 }
1797 else
1798 {
1799 $this->error = 'The data could not be converted to UTF-8';
1800 }
80d72d56 1801 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1802 return false;
1803 }
1804 elseif (!empty($this->multifeed_url))
1805 {
1806 $i = 0;
1807 $success = 0;
1808 $this->multifeed_objects = array();
1809 foreach ($this->multifeed_url as $url)
1810 {
1811 if (SIMPLEPIE_PHP5)
1812 {
1813 // This keyword needs to defy coding standards for PHP4 compatibility
1814 $this->multifeed_objects[$i] = clone($this);
1815 }
1816 else
1817 {
1818 $this->multifeed_objects[$i] = $this;
1819 }
1820 $this->multifeed_objects[$i]->set_feed_url($url);
1821 $success |= $this->multifeed_objects[$i]->init();
1822 $i++;
1823 }
1824 return (bool) $success;
1825 }
1826 else
1827 {
1828 return false;
1829 }
1830 }
1831
1832 /**
1833 * Return the error message for the occured error
1834 *
1835 * @access public
1836 * @return string Error message
1837 */
1838 function error()
1839 {
1840 return $this->error;
1841 }
1842
1843 function get_encoding()
1844 {
1845 return $this->sanitize->output_encoding;
1846 }
1847
1848 function handle_content_type($mime = 'text/html')
1849 {
1850 if (!headers_sent())
1851 {
1852 $header = "Content-type: $mime;";
1853 if ($this->get_encoding())
1854 {
1855 $header .= ' charset=' . $this->get_encoding();
1856 }
1857 else
1858 {
1859 $header .= ' charset=UTF-8';
1860 }
1861 header($header);
1862 }
1863 }
1864
1865 function get_type()
1866 {
1867 if (!isset($this->data['type']))
1868 {
1869 $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1870 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1871 {
1872 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1873 }
1874 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1875 {
1876 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1877 }
1878 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1879 {
1880 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1881 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1882 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1883 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1884 {
1885 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1886 }
1887 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1888 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1889 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1890 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1891 {
1892 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1893 }
1894 }
ec00bfc5 1895 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
80d72d56 1896 {
1897 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
ec00bfc5 1898 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
80d72d56 1899 {
ec00bfc5 1900 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
80d72d56 1901 {
1902 case '0.91':
1903 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
ec00bfc5 1904 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
80d72d56 1905 {
ec00bfc5 1906 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
80d72d56 1907 {
1908 case '0':
1909 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1910 break;
1911
1912 case '24':
1913 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1914 break;
1915 }
1916 }
1917 break;
1918
1919 case '0.92':
1920 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1921 break;
1922
1923 case '0.93':
1924 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1925 break;
1926
1927 case '0.94':
1928 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1929 break;
1930
1931 case '2.0':
1932 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1933 break;
1934 }
1935 }
1936 }
1937 else
1938 {
1939 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1940 }
1941 }
1942 return $this->data['type'];
1943 }
1944
1945 /**
1946 * Returns the URL for the favicon of the feed's website.
1947 *
1948 * @todo Cache atom:icon
1949 * @access public
1950 * @since 1.0
1951 */
1952 function get_favicon()
1953 {
1954 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
1955 {
1956 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
1957 }
1958 elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
1959 {
1960 $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
1961
1962 if ($this->cache && $this->favicon_handler)
1963 {
1964 $favicon_filename = call_user_func($this->cache_name_function, $favicon);
1965 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
1966
1967 if ($cache->load())
1968 {
1969 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1970 }
1971 else
1972 {
1973 $file =& new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
1974
ec00bfc5 1975 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)) && strlen($file->body) > 0)
80d72d56 1976 {
ec00bfc5 1977 $sniffer =& new $this->content_type_sniffer_class($file);
80d72d56 1978 if (substr($sniffer->get_type(), 0, 6) === 'image/')
1979 {
1980 if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
1981 {
1982 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1983 }
1984 else
1985 {
1986 trigger_error("$cache->name is not writeable", E_USER_WARNING);
1987 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
1988 }
1989 }
ec00bfc5 1990 // not an image
1991 else
1992 {
1993 return false;
1994 }
80d72d56 1995 }
1996 }
1997 }
1998 else
1999 {
2000 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
2001 }
2002 }
2003 return false;
2004 }
2005
2006 /**
2007 * @todo If we have a perm redirect we should return the new URL
2008 * @todo When we make the above change, let's support <itunes:new-feed-url> as well
2009 * @todo Also, |atom:link|@rel=self
2010 */
2011 function subscribe_url()
2012 {
2013 if ($this->feed_url !== null)
2014 {
2015 return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
2016 }
2017 else
2018 {
2019 return null;
2020 }
2021 }
2022
2023 function subscribe_feed()
2024 {
2025 if ($this->feed_url !== null)
2026 {
2027 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2028 }
2029 else
2030 {
2031 return null;
2032 }
2033 }
2034
2035 function subscribe_outlook()
2036 {
2037 if ($this->feed_url !== null)
2038 {
ec00bfc5 2039 return $this->sanitize('outlook' . SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
80d72d56 2040 }
2041 else
2042 {
2043 return null;
2044 }
2045 }
2046
2047 function subscribe_podcast()
2048 {
2049 if ($this->feed_url !== null)
2050 {
2051 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
2052 }
2053 else
2054 {
2055 return null;
2056 }
2057 }
2058
2059 function subscribe_itunes()
2060 {
2061 if ($this->feed_url !== null)
2062 {
2063 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
2064 }
2065 else
2066 {
2067 return null;
2068 }
2069 }
2070
2071 /**
2072 * Creates the subscribe_* methods' return data
2073 *
2074 * @access private
2075 * @param string $feed_url String to prefix to the feed URL
2076 * @param string $site_url String to prefix to the site URL (and
2077 * suffix to the feed URL)
2078 * @return mixed URL if feed exists, false otherwise
2079 */
2080 function subscribe_service($feed_url, $site_url = null)
2081 {
2082 if ($this->subscribe_url())
2083 {
ec00bfc5 2084 $return = $feed_url . rawurlencode($this->feed_url);
80d72d56 2085 if ($site_url !== null && $this->get_link() !== null)
2086 {
ec00bfc5 2087 $return .= $site_url . rawurlencode($this->get_link());
80d72d56 2088 }
ec00bfc5 2089 return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
80d72d56 2090 }
2091 else
2092 {
2093 return null;
2094 }
2095 }
2096
2097 function subscribe_aol()
2098 {
2099 return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
2100 }
2101
2102 function subscribe_bloglines()
2103 {
ec00bfc5 2104 return $this->subscribe_service('http://www.bloglines.com/sub/');
80d72d56 2105 }
2106
2107 function subscribe_eskobo()
2108 {
2109 return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
2110 }
2111
2112 function subscribe_feedfeeds()
2113 {
2114 return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
2115 }
2116
2117 function subscribe_feedster()
2118 {
2119 return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
2120 }
2121
2122 function subscribe_google()
2123 {
2124 return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
2125 }
2126
2127 function subscribe_gritwire()
2128 {
2129 return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
2130 }
2131
2132 function subscribe_msn()
2133 {
2134 return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
2135 }
2136
2137 function subscribe_netvibes()
2138 {
2139 return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
2140 }
2141
2142 function subscribe_newsburst()
2143 {
2144 return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
2145 }
2146
2147 function subscribe_newsgator()
2148 {
2149 return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
2150 }
2151
2152 function subscribe_odeo()
2153 {
2154 return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
2155 }
2156
2157 function subscribe_podnova()
2158 {
2159 return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
2160 }
2161
2162 function subscribe_rojo()
2163 {
2164 return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
2165 }
2166
2167 function subscribe_yahoo()
2168 {
2169 return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
2170 }
2171
2172 function get_feed_tags($namespace, $tag)
2173 {
2174 $type = $this->get_type();
2175 if ($type & SIMPLEPIE_TYPE_ATOM_10)
2176 {
2177 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
2178 {
2179 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
2180 }
2181 }
2182 if ($type & SIMPLEPIE_TYPE_ATOM_03)
2183 {
2184 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
2185 {
2186 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
2187 }
2188 }
2189 if ($type & SIMPLEPIE_TYPE_RSS_RDF)
2190 {
2191 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
2192 {
2193 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
2194 }
2195 }
2196 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2197 {
ec00bfc5 2198 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
80d72d56 2199 {
ec00bfc5 2200 return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
80d72d56 2201 }
2202 }
2203 return null;
2204 }
2205
2206 function get_channel_tags($namespace, $tag)
2207 {
2208 $type = $this->get_type();
2209 if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
2210 {
2211 if ($return = $this->get_feed_tags($namespace, $tag))
2212 {
2213 return $return;
2214 }
2215 }
2216 if ($type & SIMPLEPIE_TYPE_RSS_10)
2217 {
2218 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
2219 {
2220 if (isset($channel[0]['child'][$namespace][$tag]))
2221 {
2222 return $channel[0]['child'][$namespace][$tag];
2223 }
2224 }
2225 }
2226 if ($type & SIMPLEPIE_TYPE_RSS_090)
2227 {
2228 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
2229 {
2230 if (isset($channel[0]['child'][$namespace][$tag]))
2231 {
2232 return $channel[0]['child'][$namespace][$tag];
2233 }
2234 }
2235 }
2236 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2237 {
ec00bfc5 2238 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
80d72d56 2239 {
2240 if (isset($channel[0]['child'][$namespace][$tag]))
2241 {
2242 return $channel[0]['child'][$namespace][$tag];
2243 }
2244 }
2245 }
2246 return null;
2247 }
2248
2249 function get_image_tags($namespace, $tag)
2250 {
2251 $type = $this->get_type();
2252 if ($type & SIMPLEPIE_TYPE_RSS_10)
2253 {
2254 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
2255 {
2256 if (isset($image[0]['child'][$namespace][$tag]))
2257 {
2258 return $image[0]['child'][$namespace][$tag];
2259 }
2260 }
2261 }
2262 if ($type & SIMPLEPIE_TYPE_RSS_090)
2263 {
2264 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2265 {
2266 if (isset($image[0]['child'][$namespace][$tag]))
2267 {
2268 return $image[0]['child'][$namespace][$tag];
2269 }
2270 }
2271 }
2272 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2273 {
ec00bfc5 2274 if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
80d72d56 2275 {
2276 if (isset($image[0]['child'][$namespace][$tag]))
2277 {
2278 return $image[0]['child'][$namespace][$tag];
2279 }
2280 }
2281 }
2282 return null;
2283 }
2284
2285 function get_base($element = array())
2286 {
2287 if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2288 {
2289 return $element['xml_base'];
2290 }
2291 elseif ($this->get_link() !== null)
2292 {
2293 return $this->get_link();
2294 }
2295 else
2296 {
2297 return $this->subscribe_url();
2298 }
2299 }
2300
2301 function sanitize($data, $type, $base = '')
2302 {
2303 return $this->sanitize->sanitize($data, $type, $base);
2304 }
2305
2306 function get_title()
2307 {
2308 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2309 {
2310 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2311 }
2312 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2313 {
2314 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2315 }
2316 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2317 {
2318 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2319 }
2320 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2321 {
2322 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2323 }
ec00bfc5 2324 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
80d72d56 2325 {
2326 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2327 }
2328 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2329 {
2330 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2331 }
2332 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2333 {
2334 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2335 }
2336 else
2337 {
2338 return null;
2339 }
2340 }
2341
2342 function get_category($key = 0)
2343 {
2344 $categories = $this->get_categories();
2345 if (isset($categories[$key]))
2346 {
2347 return $categories[$key];
2348 }
2349 else
2350 {
2351 return null;
2352 }
2353 }
2354
2355 function get_categories()
2356 {
2357 $categories = array();
2358
2359 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2360 {
2361 $term = null;
2362 $scheme = null;
2363 $label = null;
2364 if (isset($category['attribs']['']['term']))
2365 {
2366 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2367 }
2368 if (isset($category['attribs']['']['scheme']))
2369 {
2370 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2371 }
2372 if (isset($category['attribs']['']['label']))
2373 {
2374 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2375 }
2376 $categories[] =& new $this->category_class($term, $scheme, $label);
2377 }
ec00bfc5 2378 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
80d72d56 2379 {
ec00bfc5 2380 // This is really the label, but keep this as the term also for BC.
2381 // Label will also work on retrieving because that falls back to term.
2382 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2383 if (isset($category['attribs']['']['domain']))
2384 {
2385 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
2386 }
2387 else
2388 {
2389 $scheme = null;
2390 }
2391 $categories[] =& new $this->category_class($term, $scheme, null);
80d72d56 2392 }
2393 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2394 {
2395 $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2396 }
2397 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2398 {
2399 $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2400 }
2401
2402 if (!empty($categories))
2403 {
2404 return SimplePie_Misc::array_unique($categories);
2405 }
2406 else
2407 {
2408 return null;
2409 }
2410 }
2411
2412 function get_author($key = 0)
2413 {
2414 $authors = $this->get_authors();
2415 if (isset($authors[$key]))
2416 {
2417 return $authors[$key];
2418 }
2419 else
2420 {
2421 return null;
2422 }
2423 }
2424
2425 function get_authors()
2426 {
2427 $authors = array();
2428 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2429 {
2430 $name = null;
2431 $uri = null;
2432 $email = null;
2433 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2434 {
2435 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2436 }
2437 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2438 {
2439 $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]));
2440 }
2441 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2442 {
2443 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2444 }
2445 if ($name !== null || $email !== null || $uri !== null)
2446 {
2447 $authors[] =& new $this->author_class($name, $uri, $email);
2448 }
2449 }
2450 if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2451 {
2452 $name = null;
2453 $url = null;
2454 $email = null;
2455 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2456 {
2457 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2458 }
2459 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2460 {
2461 $url = $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]));
2462 }
2463 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2464 {
2465 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2466 }
2467 if ($name !== null || $email !== null || $url !== null)
2468 {
2469 $authors[] =& new $this->author_class($name, $url, $email);
2470 }
2471 }
2472 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2473 {
2474 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2475 }
2476 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2477 {
2478 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2479 }
2480 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2481 {
2482 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2483 }
2484
2485 if (!empty($authors))
2486 {
2487 return SimplePie_Misc::array_unique($authors);
2488 }
2489 else
2490 {
2491 return null;
2492 }
2493 }
2494
2495 function get_contributor($key = 0)
2496 {
2497 $contributors = $this->get_contributors();
2498 if (isset($contributors[$key]))
2499 {
2500 return $contributors[$key];
2501 }
2502 else
2503 {
2504 return null;
2505 }
2506 }
2507
2508 function get_contributors()
2509 {
2510 $contributors = array();
2511 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2512 {
2513 $name = null;
2514 $uri = null;
2515 $email = null;
2516 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2517 {
2518 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2519 }
2520 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2521 {
2522 $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
2523 }
2524 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2525 {
2526 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2527 }
2528 if ($name !== null || $email !== null || $uri !== null)
2529 {
2530 $contributors[] =& new $this->author_class($name, $uri, $email);
2531 }
2532 }
2533 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2534 {
2535 $name = null;
2536 $url = null;
2537 $email = null;
2538 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2539 {
2540 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2541 }
2542 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2543 {
2544 $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
2545 }
2546 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2547 {
2548 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2549 }
2550 if ($name !== null || $email !== null || $url !== null)
2551 {
2552 $contributors[] =& new $this->author_class($name, $url, $email);
2553 }
2554 }
2555
2556 if (!empty($contributors))
2557 {
2558 return SimplePie_Misc::array_unique($contributors);
2559 }
2560 else
2561 {
2562 return null;
2563 }
2564 }
2565
2566 function get_link($key = 0, $rel = 'alternate')
2567 {
2568 $links = $this->get_links($rel);
2569 if (isset($links[$key]))
2570 {
2571 return $links[$key];
2572 }
2573 else
2574 {
2575 return null;
2576 }
2577 }
2578
2579 /**
2580 * Added for parity between the parent-level and the item/entry-level.
2581 */
2582 function get_permalink()
2583 {
2584 return $this->get_link(0);
2585 }
2586
2587 function get_links($rel = 'alternate')
2588 {
2589 if (!isset($this->data['links']))
2590 {
2591 $this->data['links'] = array();
2592 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2593 {
2594 foreach ($links as $link)
2595 {
2596 if (isset($link['attribs']['']['href']))
2597 {
2598 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2599 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2600 }
2601 }
2602 }
2603 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2604 {
2605 foreach ($links as $link)
2606 {
2607 if (isset($link['attribs']['']['href']))
2608 {
2609 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2610 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2611
2612 }
2613 }
2614 }
2615 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2616 {
2617 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2618 }
2619 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2620 {
2621 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2622 }
ec00bfc5 2623 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
80d72d56 2624 {
2625 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2626 }
2627
2628 $keys = array_keys($this->data['links']);
2629 foreach ($keys as $key)
2630 {
2631 if (SimplePie_Misc::is_isegment_nz_nc($key))
2632 {
2633 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2634 {
2635 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2636 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2637 }
2638 else
2639 {
2640 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2641 }
2642 }
ec00bfc5 2643 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
80d72d56 2644 {
2645 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2646 }
2647 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2648 }
2649 }
2650
2651 if (isset($this->data['links'][$rel]))
2652 {
2653 return $this->data['links'][$rel];
2654 }
2655 else
2656 {
2657 return null;
2658 }
2659 }
2660
ec00bfc5 2661 function get_all_discovered_feeds()
2662 {
2663 return $this->all_discovered_feeds;
2664 }
2665
80d72d56 2666 function get_description()
2667 {
2668 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2669 {
2670 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2671 }
2672 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2673 {
2674 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2675 }
2676 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2677 {
2678 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2679 }
2680 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2681 {
2682 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2683 }
ec00bfc5 2684 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
80d72d56 2685 {
ec00bfc5 2686 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
80d72d56 2687 }
2688 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2689 {
2690 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2691 }
2692 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2693 {
2694 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2695 }
2696 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2697 {
2698 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2699 }
2700 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2701 {
2702 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2703 }
2704 else
2705 {
2706 return null;
2707 }
2708 }
2709
2710 function get_copyright()
2711 {
2712 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2713 {
2714 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2715 }
2716 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2717 {
2718 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2719 }
ec00bfc5 2720 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
80d72d56 2721 {
2722 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2723 }
2724 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2725 {
2726 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2727 }
2728 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2729 {
2730 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2731 }
2732 else
2733 {
2734 return null;
2735 }
2736 }
2737
2738 function get_language()
2739 {
ec00bfc5 2740 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
80d72d56 2741 {
2742 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2743 }
2744 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2745 {
2746 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2747 }
2748 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2749 {
2750 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2751 }
2752 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2753 {
2754 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2755 }
2756 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2757 {
2758 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2759 }
2760 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2761 {
2762 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2763 }
2764 elseif (isset($this->data['headers']['content-language']))
2765 {
2766 return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2767 }
2768 else
2769 {
2770 return null;
2771 }
2772 }
2773
2774 function get_latitude()
2775 {
2776 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2777 {
2778 return (float) $return[0]['data'];
2779 }
2780 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
2781 {
2782 return (float) $match[1];
2783 }
2784 else
2785 {
2786 return null;
2787 }
2788 }
2789
2790 function get_longitude()
2791 {
2792 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2793 {
2794 return (float) $return[0]['data'];
2795 }
2796 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2797 {
2798 return (float) $return[0]['data'];
2799 }
2800 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
2801 {
2802 return (float) $match[2];
2803 }
2804 else
2805 {
2806 return null;
2807 }
2808 }
2809
2810 function get_image_title()
2811 {
2812 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2813 {
2814 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2815 }
2816 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2817 {
2818 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2819 }
ec00bfc5 2820 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
80d72d56 2821 {
2822 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2823 }
2824 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2825 {
2826 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2827 }
2828 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2829 {
2830 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2831 }
2832 else
2833 {
2834 return null;
2835 }
2836 }
2837
2838 function get_image_url()
2839 {
2840 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2841 {
2842 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2843 }
2844 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2845 {
2846 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2847 }
2848 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2849 {
2850 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2851 }
2852 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2853 {
2854 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2855 }
2856 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2857 {
2858 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2859 }
ec00bfc5 2860 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
80d72d56 2861 {
2862 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2863 }
2864 else
2865 {
2866 return null;
2867 }
2868 }
2869
2870 function get_image_link()
2871 {
2872 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2873 {
2874 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2875 }
2876 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2877 {
2878 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2879 }
ec00bfc5 2880 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
80d72d56 2881 {
2882 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2883 }
2884 else
2885 {
2886 return null;
2887 }
2888 }
2889
2890 function get_image_width()
2891 {
ec00bfc5 2892 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
80d72d56 2893 {
2894 return round($return[0]['data']);
2895 }
ec00bfc5 2896 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
80d72d56 2897 {
2898 return 88.0;
2899 }
2900 else
2901 {
2902 return null;
2903 }
2904 }
2905
2906 function get_image_height()
2907 {
ec00bfc5 2908 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
80d72d56 2909 {
2910 return round($return[0]['data']);
2911 }
ec00bfc5 2912 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
80d72d56 2913 {
2914 return 31.0;
2915 }
2916 else
2917 {
2918 return null;
2919 }
2920 }
2921
2922 function get_item_quantity($max = 0)
2923 {
ec00bfc5 2924 $max = (int) $max;
80d72d56 2925 $qty = count($this->get_items());
ec00bfc5 2926 if ($max === 0)
80d72d56 2927 {
2928 return $qty;
2929 }
2930 else
2931 {
2932 return ($qty > $max) ? $max : $qty;
2933 }
2934 }
2935
2936 function get_item($key = 0)
2937 {
2938 $items = $this->get_items();
2939 if (isset($items[$key]))
2940 {
2941 return $items[$key];
2942 }
2943 else
2944 {
2945 return null;
2946 }
2947 }
2948
2949 function get_items($start = 0, $end = 0)
2950 {
ec00bfc5 2951 if (!isset($this->data['items']))
80d72d56 2952 {
ec00bfc5 2953 if (!empty($this->multifeed_objects))
80d72d56 2954 {
ec00bfc5 2955 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
80d72d56 2956 }
ec00bfc5 2957 else
80d72d56 2958 {
ec00bfc5 2959 $this->data['items'] = array();
2960 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
80d72d56 2961 {
ec00bfc5 2962 $keys = array_keys($items);
2963 foreach ($keys as $key)
2964 {
2965 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2966 }
80d72d56 2967 }
ec00bfc5 2968 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
80d72d56 2969 {
ec00bfc5 2970 $keys = array_keys($items);
2971 foreach ($keys as $key)
2972 {
2973 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2974 }
80d72d56 2975 }
ec00bfc5 2976 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
80d72d56 2977 {
ec00bfc5 2978 $keys = array_keys($items);
2979 foreach ($keys as $key)
2980 {
2981 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2982 }
80d72d56 2983 }
ec00bfc5 2984 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2985 {
2986 $keys = array_keys($items);
2987 foreach ($keys as $key)
2988 {
2989 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2990 }
2991 }
2992 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
80d72d56 2993 {
ec00bfc5 2994 $keys = array_keys($items);
2995 foreach ($keys as $key)
2996 {
2997 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2998 }
80d72d56 2999 }
3000 }
3001 }
3002
3003 if (!empty($this->data['items']))
3004 {
3005 // If we want to order it by date, check if all items have a date, and then sort it
ec00bfc5 3006 if ($this->order_by_date && empty($this->multifeed_objects))
80d72d56 3007 {
3008 if (!isset($this->data['ordered_items']))
3009 {
3010 $do_sort = true;
3011 foreach ($this->data['items'] as $item)
3012 {
3013 if (!$item->get_date('U'))
3014 {
3015 $do_sort = false;
3016 break;
3017 }
3018 }
3019 $item = null;
3020 $this->data['ordered_items'] = $this->data['items'];
3021 if ($do_sort)
3022 {
3023 usort($this->data['ordered_items'], array(&$this, 'sort_items'));
3024 }
3025 }
3026 $items = $this->data['ordered_items'];
3027 }
3028 else
3029 {
3030 $items = $this->data['items'];
3031 }
3032
3033 // Slice the data as desired
ec00bfc5 3034 if ($end === 0)
80d72d56 3035 {
3036 return array_slice($items, $start);
3037 }
3038 else
3039 {
3040 return array_slice($items, $start, $end);
3041 }
3042 }
3043 else
3044 {
3045 return array();
3046 }
3047 }
3048
ec00bfc5 3049 /**
3050 * @static
3051 */
80d72d56 3052 function sort_items($a, $b)
3053 {
3054 return $a->get_date('U') <= $b->get_date('U');
3055 }
3056
ec00bfc5 3057 /**
3058 * @static
3059 */
80d72d56 3060 function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3061 {
3062 if (is_array($urls) && sizeof($urls) > 0)
3063 {
3064 $items = array();
3065 foreach ($urls as $arg)
3066 {
3067 if (is_a($arg, 'SimplePie'))
3068 {
3069 $items = array_merge($items, $arg->get_items(0, $limit));
3070 }
3071 else
3072 {
3073 trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3074 }
3075 }
3076
3077 $do_sort = true;
3078 foreach ($items as $item)
3079 {
3080 if (!$item->get_date('U'))
3081 {
3082 $do_sort = false;
3083 break;
3084 }
3085 }
3086 $item = null;
3087 if ($do_sort)
3088 {
3089 usort($items, array('SimplePie', 'sort_items'));
3090 }
3091
ec00bfc5 3092 if ($end === 0)
80d72d56 3093 {
3094 return array_slice($items, $start);
3095 }
3096 else
3097 {
3098 return array_slice($items, $start, $end);
3099 }
3100 }
3101 else
3102 {
3103 trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3104 return array();
3105 }
3106 }
3107}
3108
3109class SimplePie_Item
3110{
3111 var $feed;
3112 var $data = array();
3113
3114 function SimplePie_Item($feed, $data)
3115 {
3116 $this->feed = $feed;
3117 $this->data = $data;
3118 }
3119
3120 function __toString()
3121 {
3122 return md5(serialize($this->data));
3123 }
3124
3125 /**
3126 * Remove items that link back to this before destroying this object
3127 */
3128 function __destruct()
3129 {
ec00bfc5 3130 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
3131 {
3132 unset($this->feed);
3133 }
80d72d56 3134 }
3135
3136 function get_item_tags($namespace, $tag)
3137 {
3138 if (isset($this->data['child'][$namespace][$tag]))
3139 {
3140 return $this->data['child'][$namespace][$tag];
3141 }
3142 else
3143 {
3144 return null;
3145 }
3146 }
3147
3148 function get_base($element = array())
3149 {
3150 return $this->feed->get_base($element);
3151 }
3152
3153 function sanitize($data, $type, $base = '')
3154 {
3155 return $this->feed->sanitize($data, $type, $base);
3156 }
3157
3158 function get_feed()
3159 {
3160 return $this->feed;
3161 }
3162
3163 function get_id($hash = false)
3164 {
3165 if (!$hash)
3166 {
3167 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
3168 {
3169 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3170 }
3171 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
3172 {
3173 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3174 }
ec00bfc5 3175 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
80d72d56 3176 {
3177 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3178 }
3179 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
3180 {
3181 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3182 }
3183 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
3184 {
3185 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3186 }
3187 elseif (($return = $this->get_permalink()) !== null)
3188 {
3189 return $return;
3190 }
3191 elseif (($return = $this->get_title()) !== null)
3192 {
3193 return $return;
3194 }
3195 }
3196 if ($this->get_permalink() !== null || $this->get_title() !== null)
3197 {
3198 return md5($this->get_permalink() . $this->get_title());
3199 }
3200 else
3201 {
3202 return md5(serialize($this->data));
3203 }
3204 }
3205
3206 function get_title()
3207 {
3208 if (!isset($this->data['title']))
3209 {
3210 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
3211 {
3212 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3213 }
3214 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
3215 {
3216 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3217 }
3218 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
3219 {
3220 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3221 }
3222 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
3223 {
3224 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3225 }
ec00bfc5 3226 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
80d72d56 3227 {
3228 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3229 }
3230 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
3231 {
3232 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3233 }
3234 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
3235 {
3236 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3237 }
3238 else
3239 {
3240 $this->data['title'] = null;
3241 }
3242 }
3243 return $this->data['title'];
3244 }
3245
3246 function get_description($description_only = false)
3247 {
3248 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
3249 {
3250 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3251 }
3252 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
3253 {
3254 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3255 }
3256 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
3257 {
3258 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3259 }
ec00bfc5 3260 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
80d72d56 3261 {
3262 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3263 }
3264 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3265 {
3266 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3267 }
3268 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3269 {
3270 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3271 }
3272 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3273 {
3274 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3275 }
3276 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3277 {
3278 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3279 }
3280 elseif (!$description_only)
3281 {
3282 return $this->get_content(true);
3283 }
3284 else
3285 {
3286 return null;
3287 }
3288 }
3289
3290 function get_content($content_only = false)
3291 {
3292 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3293 {
3294 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3295 }
3296 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3297 {
3298 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3299 }
3300 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3301 {
3302 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3303 }
3304 elseif (!$content_only)
3305 {
3306 return $this->get_description(true);
3307 }
3308 else
3309 {
3310 return null;
3311 }
3312 }
3313
3314 function get_category($key = 0)
3315 {
3316 $categories = $this->get_categories();
3317 if (isset($categories[$key]))
3318 {
3319 return $categories[$key];
3320 }
3321 else
3322 {
3323 return null;
3324 }
3325 }
3326
3327 function get_categories()
3328 {
3329 $categories = array();
3330
3331 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3332 {
3333 $term = null;
3334 $scheme = null;
3335 $label = null;
3336 if (isset($category['attribs']['']['term']))
3337 {
3338 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3339 }
3340 if (isset($category['attribs']['']['scheme']))
3341 {
3342 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3343 }
3344 if (isset($category['attribs']['']['label']))
3345 {
3346 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3347 }
3348 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
3349 }
ec00bfc5 3350 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
80d72d56 3351 {
ec00bfc5 3352 // This is really the label, but keep this as the term also for BC.
3353 // Label will also work on retrieving because that falls back to term.
3354 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3355 if (isset($category['attribs']['']['domain']))
3356 {
3357 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
3358 }
3359 else
3360 {
3361 $scheme = null;
3362 }
3363 $categories[] =& new $this->feed->category_class($term, $scheme, null);
80d72d56 3364 }
3365 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3366 {
3367 $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3368 }
3369 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3370 {
3371 $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3372 }
3373
3374 if (!empty($categories))
3375 {
3376 return SimplePie_Misc::array_unique($categories);
3377 }
3378 else
3379 {
3380 return null;
3381 }
3382 }
3383
3384 function get_author($key = 0)
3385 {
3386 $authors = $this->get_authors();
3387 if (isset($authors[$key]))
3388 {
3389 return $authors[$key];
3390 }
3391 else
3392 {
3393 return null;
3394 }
3395 }
3396
3397 function get_contributor($key = 0)
3398 {
3399 $contributors = $this->get_contributors();
3400 if (isset($contributors[$key]))
3401 {
3402 return $contributors[$key];
3403 }
3404 else
3405 {
3406 return null;
3407 }
3408 }
3409
3410 function get_contributors()
3411 {
3412 $contributors = array();
3413 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3414 {
3415 $name = null;
3416 $uri = null;
3417 $email = null;
3418 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3419 {
3420 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3421 }
3422 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3423 {
3424 $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
3425 }
3426 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3427 {
3428 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3429 }
3430 if ($name !== null || $email !== null || $uri !== null)
3431 {
3432 $contributors[] =& new $this->feed->author_class($name, $uri, $email);
3433 }
3434 }
3435 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3436 {
3437 $name = null;
3438 $url = null;
3439 $email = null;
3440 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3441 {
3442 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3443 }
3444 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3445 {
3446 $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
3447 }
3448 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3449 {
3450 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3451 }
3452 if ($name !== null || $email !== null || $url !== null)
3453 {
3454 $contributors[] =& new $this->feed->author_class($name, $url, $email);
3455 }
3456 }
3457
3458 if (!empty($contributors))
3459 {
3460 return SimplePie_Misc::array_unique($contributors);
3461 }
3462 else
3463 {
3464 return null;
3465 }
3466 }
3467
80d72d56 3468 function get_authors()
3469 {
3470 $authors = array();
3471 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3472 {
3473 $name = null;
3474 $uri = null;
3475 $email = null;
3476 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3477 {
3478 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3479 }
3480 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3481 {
3482 $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]));
3483 }
3484 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3485 {
3486 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3487 }
3488 if ($name !== null || $email !== null || $uri !== null)
3489 {
3490 $authors[] =& new $this->feed->author_class($name, $uri, $email);
3491 }
3492 }
3493 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3494 {
3495 $name = null;
3496 $url = null;
3497 $email = null;
3498 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3499 {
3500 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3501 }
3502 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3503 {
3504 $url = $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]));
3505 }
3506 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3507 {
3508 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3509 }
3510 if ($name !== null || $email !== null || $url !== null)
3511 {
3512 $authors[] =& new $this->feed->author_class($name, $url, $email);
3513 }
3514 }
ec00bfc5 3515 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
80d72d56 3516 {
3517 $authors[] =& new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3518 }
3519 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3520 {
3521 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3522 }
3523 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3524 {
3525 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3526 }
3527 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3528 {
3529 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3530 }
3531
3532 if (!empty($authors))
3533 {
3534 return SimplePie_Misc::array_unique($authors);
3535 }
3536 elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3537 {
3538 return $authors;
3539 }
3540 elseif ($authors = $this->feed->get_authors())
3541 {
3542 return $authors;
3543 }
3544 else
3545 {
3546 return null;
3547 }
3548 }
3549
3550 function get_copyright()
3551 {
3552 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3553 {
3554 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3555 }
3556 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3557 {
3558 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3559 }
3560 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3561 {
3562 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3563 }
3564 else
3565 {
3566 return null;
3567 }
3568 }
3569
3570 function get_date($date_format = 'j F Y, g:i a')
3571 {
3572 if (!isset($this->data['date']))
3573 {
3574 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3575 {
3576 $this->data['date']['raw'] = $return[0]['data'];
3577 }
3578 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3579 {
3580 $this->data['date']['raw'] = $return[0]['data'];
3581 }
3582 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3583 {
3584 $this->data['date']['raw'] = $return[0]['data'];
3585 }
3586 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3587 {
3588 $this->data['date']['raw'] = $return[0]['data'];
3589 }
3590 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3591 {
3592 $this->data['date']['raw'] = $return[0]['data'];
3593 }
ec00bfc5 3594 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
80d72d56 3595 {
3596 $this->data['date']['raw'] = $return[0]['data'];
3597 }
3598 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3599 {
3600 $this->data['date']['raw'] = $return[0]['data'];
3601 }
3602 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3603 {
3604 $this->data['date']['raw'] = $return[0]['data'];
3605 }
3606
3607 if (!empty($this->data['date']['raw']))
3608 {
3609 $parser = SimplePie_Parse_Date::get();
3610 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3611 }
3612 else
3613 {
3614 $this->data['date'] = null;
3615 }
3616 }
3617 if ($this->data['date'])
3618 {
3619 $date_format = (string) $date_format;
3620 switch ($date_format)
3621 {
3622 case '':
3623 return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3624
3625 case 'U':
3626 return $this->data['date']['parsed'];
3627
3628 default:
3629 return date($date_format, $this->data['date']['parsed']);
3630 }
3631 }
3632 else
3633 {
3634 return null;
3635 }
3636 }
3637
3638 function get_local_date($date_format = '%c')
3639 {
3640 if (!$date_format)
3641 {
3642 return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3643 }
3644 elseif (($date = $this->get_date('U')) !== null)
3645 {
3646 return strftime($date_format, $date);
3647 }
3648 else
3649 {
3650 return null;
3651 }
3652 }
3653
3654 function get_permalink()
3655 {
3656 $link = $this->get_link();
3657 $enclosure = $this->get_enclosure(0);
3658 if ($link !== null)
3659 {
3660 return $link;
3661 }
3662 elseif ($enclosure !== null)
3663 {
3664 return $enclosure->get_link();
3665 }
3666 else
3667 {
3668 return null;
3669 }
3670 }
3671
3672 function get_link($key = 0, $rel = 'alternate')
3673 {
3674 $links = $this->get_links($rel);
3675 if ($links[$key] !== null)
3676 {
3677 return $links[$key];
3678 }
3679 else
3680 {
3681 return null;
3682 }
3683 }
3684
3685 function get_links($rel = 'alternate')
3686 {
3687 if (!isset($this->data['links']))
3688 {
3689 $this->data['links'] = array();
3690 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3691 {
3692 if (isset($link['attribs']['']['href']))
3693 {
3694 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3695 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3696
3697 }
3698 }
3699 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3700 {
3701 if (isset($link['attribs']['']['href']))
3702 {
3703 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3704 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3705 }
3706 }
3707 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3708 {
3709 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3710 }
3711 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3712 {
3713 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3714 }
ec00bfc5 3715 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
80d72d56 3716 {
3717 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3718 }
ec00bfc5 3719 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
80d72d56 3720 {
ec00bfc5 3721 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
80d72d56 3722 {
3723 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3724 }
3725 }
3726
3727 $keys = array_keys($this->data['links']);
3728 foreach ($keys as $key)
3729 {
3730 if (SimplePie_Misc::is_isegment_nz_nc($key))
3731 {
3732 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3733 {
3734 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3735 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3736 }
3737 else
3738 {
3739 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3740 }
3741 }
ec00bfc5 3742 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
80d72d56 3743 {
3744 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3745 }
3746 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3747 }
3748 }
3749 if (isset($this->data['links'][$rel]))
3750 {
3751 return $this->data['links'][$rel];
3752 }
3753 else
3754 {
3755 return null;
3756 }
3757 }
3758
3759 /**
3760 * @todo Add ability to prefer one type of content over another (in a media group).
3761 */
3762 function get_enclosure($key = 0, $prefer = null)
3763 {
3764 $enclosures = $this->get_enclosures();
3765 if (isset($enclosures[$key]))
3766 {
3767 return $enclosures[$key];
3768 }
3769 else
3770 {
3771 return null;
3772 }
3773 }
3774
3775 /**
3776 * Grabs all available enclosures (podcasts, etc.)
3777 *
3778 * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3779 *
3780 * 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.
3781 *
3782 * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3783 * @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).
3784 */
3785 function get_enclosures()
3786 {
3787 if (!isset($this->data['enclosures']))
3788 {
3789 $this->data['enclosures'] = array();
3790
3791 // Elements
3792 $captions_parent = null;
3793 $categories_parent = null;
3794 $copyrights_parent = null;
3795 $credits_parent = null;
3796 $description_parent = null;
3797 $duration_parent = null;
3798 $hashes_parent = null;
3799 $keywords_parent = null;
3800 $player_parent = null;
3801 $ratings_parent = null;
3802 $restrictions_parent = null;
3803 $thumbnails_parent = null;
3804 $title_parent = null;
3805
3806 // Let's do the channel and item-level ones first, and just re-use them if we need to.
3807 $parent = $this->get_feed();
3808
3809 // CAPTIONS
3810 if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3811 {
3812 foreach ($captions as $caption)
3813 {
3814 $caption_type = null;
3815 $caption_lang = null;
3816 $caption_startTime = null;
3817 $caption_endTime = null;
3818 $caption_text = null;
3819 if (isset($caption['attribs']['']['type']))
3820 {
3821 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3822 }
3823 if (isset($caption['attribs']['']['lang']))
3824 {
3825 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3826 }
3827 if (isset($caption['attribs']['']['start']))
3828 {
3829 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3830 }
3831 if (isset($caption['attribs']['']['end']))
3832 {
3833 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3834 }
3835 if (isset($caption['data']))
3836 {
3837 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3838 }
3839 $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3840 }
3841 }
3842 elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3843 {
3844 foreach ($captions as $caption)
3845 {
3846 $caption_type = null;
3847 $caption_lang = null;
3848 $caption_startTime = null;
3849 $caption_endTime = null;
3850 $caption_text = null;
3851 if (isset($caption['attribs']['']['type']))
3852 {
3853 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3854 }
3855 if (isset($caption['attribs']['']['lang']))
3856 {
3857 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);