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