MDL-23980 importing latest 1.3dev - this should fix the url encode problem
[moodle.git] / lib / simplepie / simplepie.class.php
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.
a762ba72 1452 if ((function_exists('version_compare') && version_compare(PHP_VERSION, '5.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
80d72d56 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 {
a762ba72 1767 $this->multifeed_objects[$i] = clone $this;
80d72d56 1768 $this->multifeed_objects[$i]->set_feed_url($url);
1769 $success |= $this->multifeed_objects[$i]->init();
1770 $i++;
1771 }
1772 return (bool) $success;
1773 }
1774 else
1775 {
1776 return false;
1777 }
1778 }
1779
1780 /**
1781 * Return the error message for the occured error
1782 *
1783 * @access public
1784 * @return string Error message
1785 */
73f27201 1786 public function error()
80d72d56 1787 {
1788 return $this->error;
1789 }
1790
73f27201 1791 public function get_encoding()
80d72d56 1792 {
1793 return $this->sanitize->output_encoding;
1794 }
1795
73f27201 1796 public function handle_content_type($mime = 'text/html')
80d72d56 1797 {
1798 if (!headers_sent())
1799 {
1800 $header = "Content-type: $mime;";
1801 if ($this->get_encoding())
1802 {
1803 $header .= ' charset=' . $this->get_encoding();
1804 }
1805 else
1806 {
1807 $header .= ' charset=UTF-8';
1808 }
1809 header($header);
1810 }
1811 }
1812
73f27201 1813 public function get_type()
80d72d56 1814 {
1815 if (!isset($this->data['type']))
1816 {
1817 $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1818 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1819 {
1820 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1821 }
1822 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1823 {
1824 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1825 }
1826 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1827 {
1828 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1829 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1830 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1831 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1832 {
1833 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1834 }
1835 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1836 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1837 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1838 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1839 {
1840 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1841 }
1842 }
ec00bfc5 1843 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
80d72d56 1844 {
1845 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
ec00bfc5 1846 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
80d72d56 1847 {
ec00bfc5 1848 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
80d72d56 1849 {
1850 case '0.91':
1851 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
ec00bfc5 1852 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
80d72d56 1853 {
ec00bfc5 1854 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
80d72d56 1855 {
1856 case '0':
1857 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1858 break;
1859
1860 case '24':
1861 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1862 break;
1863 }
1864 }
1865 break;
1866
1867 case '0.92':
1868 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1869 break;
1870
1871 case '0.93':
1872 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1873 break;
1874
1875 case '0.94':
1876 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1877 break;
1878
1879 case '2.0':
1880 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1881 break;
1882 }
1883 }
1884 }
1885 else
1886 {
1887 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1888 }
1889 }
1890 return $this->data['type'];
1891 }
1892
80d72d56 1893 /**
1894 * @todo If we have a perm redirect we should return the new URL
1895 * @todo When we make the above change, let's support <itunes:new-feed-url> as well
1896 * @todo Also, |atom:link|@rel=self
1897 */
73f27201 1898 public function subscribe_url()
80d72d56 1899 {
1900 if ($this->feed_url !== null)
1901 {
1902 return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
1903 }
1904 else
1905 {
1906 return null;
1907 }
1908 }
1909
73f27201 1910 public function get_feed_tags($namespace, $tag)
80d72d56 1911 {
1912 $type = $this->get_type();
1913 if ($type & SIMPLEPIE_TYPE_ATOM_10)
1914 {
1915 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
1916 {
1917 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
1918 }
1919 }
1920 if ($type & SIMPLEPIE_TYPE_ATOM_03)
1921 {
1922 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
1923 {
1924 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
1925 }
1926 }
1927 if ($type & SIMPLEPIE_TYPE_RSS_RDF)
1928 {
1929 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
1930 {
1931 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
1932 }
1933 }
1934 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
1935 {
ec00bfc5 1936 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
80d72d56 1937 {
ec00bfc5 1938 return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
80d72d56 1939 }
1940 }
1941 return null;
1942 }
1943
73f27201 1944 public function get_channel_tags($namespace, $tag)
80d72d56 1945 {
1946 $type = $this->get_type();
1947 if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
1948 {
1949 if ($return = $this->get_feed_tags($namespace, $tag))
1950 {
1951 return $return;
1952 }
1953 }
1954 if ($type & SIMPLEPIE_TYPE_RSS_10)
1955 {
1956 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
1957 {
1958 if (isset($channel[0]['child'][$namespace][$tag]))
1959 {
1960 return $channel[0]['child'][$namespace][$tag];
1961 }
1962 }
1963 }
1964 if ($type & SIMPLEPIE_TYPE_RSS_090)
1965 {
1966 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
1967 {
1968 if (isset($channel[0]['child'][$namespace][$tag]))
1969 {
1970 return $channel[0]['child'][$namespace][$tag];
1971 }
1972 }
1973 }
1974 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
1975 {
ec00bfc5 1976 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
80d72d56 1977 {
1978 if (isset($channel[0]['child'][$namespace][$tag]))
1979 {
1980 return $channel[0]['child'][$namespace][$tag];
1981 }
1982 }
1983 }
1984 return null;
1985 }
1986
73f27201 1987 public function get_image_tags($namespace, $tag)
80d72d56 1988 {
1989 $type = $this->get_type();
1990 if ($type & SIMPLEPIE_TYPE_RSS_10)
1991 {
1992 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
1993 {
1994 if (isset($image[0]['child'][$namespace][$tag]))
1995 {
1996 return $image[0]['child'][$namespace][$tag];
1997 }
1998 }
1999 }
2000 if ($type & SIMPLEPIE_TYPE_RSS_090)
2001 {
2002 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2003 {
2004 if (isset($image[0]['child'][$namespace][$tag]))
2005 {
2006 return $image[0]['child'][$namespace][$tag];
2007 }
2008 }
2009 }
2010 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2011 {
ec00bfc5 2012 if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
80d72d56 2013 {
2014 if (isset($image[0]['child'][$namespace][$tag]))
2015 {
2016 return $image[0]['child'][$namespace][$tag];
2017 }
2018 }
2019 }
2020 return null;
2021 }
2022
73f27201 2023 public function get_base($element = array())
80d72d56 2024 {
2025 if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2026 {
2027 return $element['xml_base'];
2028 }
2029 elseif ($this->get_link() !== null)
2030 {
2031 return $this->get_link();
2032 }
2033 else
2034 {
2035 return $this->subscribe_url();
2036 }
2037 }
2038
73f27201 2039 public function sanitize($data, $type, $base = '')
80d72d56 2040 {
2041 return $this->sanitize->sanitize($data, $type, $base);
2042 }
2043
73f27201 2044 public function get_title()
80d72d56 2045 {
2046 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2047 {
2048 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2049 }
2050 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2051 {
2052 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2053 }
2054 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2055 {
2056 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2057 }
2058 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2059 {
2060 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2061 }
ec00bfc5 2062 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
80d72d56 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_DC_11, 'title'))
2067 {
2068 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2069 }
2070 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2071 {
2072 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2073 }
2074 else
2075 {
2076 return null;
2077 }
2078 }
2079
73f27201 2080 public function get_category($key = 0)
80d72d56 2081 {
2082 $categories = $this->get_categories();
2083 if (isset($categories[$key]))
2084 {
2085 return $categories[$key];
2086 }
2087 else
2088 {
2089 return null;
2090 }
2091 }
2092
73f27201 2093 public function get_categories()
80d72d56 2094 {
2095 $categories = array();
2096
2097 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2098 {
2099 $term = null;
2100 $scheme = null;
2101 $label = null;
2102 if (isset($category['attribs']['']['term']))
2103 {
2104 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2105 }
2106 if (isset($category['attribs']['']['scheme']))
2107 {
2108 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2109 }
2110 if (isset($category['attribs']['']['label']))
2111 {
2112 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2113 }
73f27201 2114 $categories[] = new $this->category_class($term, $scheme, $label);
80d72d56 2115 }
ec00bfc5 2116 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
80d72d56 2117 {
ec00bfc5 2118 // This is really the label, but keep this as the term also for BC.
2119 // Label will also work on retrieving because that falls back to term.
2120 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2121 if (isset($category['attribs']['']['domain']))
2122 {
2123 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
2124 }
2125 else
2126 {
2127 $scheme = null;
2128 }
73f27201 2129 $categories[] = new $this->category_class($term, $scheme, null);
80d72d56 2130 }
2131 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2132 {
73f27201 2133 $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
80d72d56 2134 }
2135 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2136 {
73f27201 2137 $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
80d72d56 2138 }
2139
2140 if (!empty($categories))
2141 {
2142 return SimplePie_Misc::array_unique($categories);
2143 }
2144 else
2145 {
2146 return null;
2147 }
2148 }
2149
73f27201 2150 public function get_author($key = 0)
80d72d56 2151 {
2152 $authors = $this->get_authors();
2153 if (isset($authors[$key]))
2154 {
2155 return $authors[$key];
2156 }
2157 else
2158 {
2159 return null;
2160 }
2161 }
2162
73f27201 2163 public function get_authors()
80d72d56 2164 {
2165 $authors = array();
2166 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2167 {
2168 $name = null;
2169 $uri = null;
2170 $email = null;
2171 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2172 {
2173 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2174 }
2175 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2176 {
2177 $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]));
2178 }
2179 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2180 {
2181 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2182 }
2183 if ($name !== null || $email !== null || $uri !== null)
2184 {
73f27201 2185 $authors[] = new $this->author_class($name, $uri, $email);
80d72d56 2186 }
2187 }
2188 if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2189 {
2190 $name = null;
2191 $url = null;
2192 $email = null;
2193 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2194 {
2195 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2196 }
2197 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2198 {
2199 $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]));
2200 }
2201 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2202 {
2203 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2204 }
2205 if ($name !== null || $email !== null || $url !== null)
2206 {
73f27201 2207 $authors[] = new $this->author_class($name, $url, $email);
80d72d56 2208 }
2209 }
2210 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2211 {
73f27201 2212 $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
80d72d56 2213 }
2214 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2215 {
73f27201 2216 $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
80d72d56 2217 }
2218 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2219 {
73f27201 2220 $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
80d72d56 2221 }
2222
2223 if (!empty($authors))
2224 {
2225 return SimplePie_Misc::array_unique($authors);
2226 }
2227 else
2228 {
2229 return null;
2230 }
2231 }
2232
73f27201 2233 public function get_contributor($key = 0)
80d72d56 2234 {
2235 $contributors = $this->get_contributors();
2236 if (isset($contributors[$key]))
2237 {
2238 return $contributors[$key];
2239 }
2240 else
2241 {
2242 return null;
2243 }
2244 }
2245
73f27201 2246 public function get_contributors()
80d72d56 2247 {
2248 $contributors = array();
2249 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2250 {
2251 $name = null;
2252 $uri = null;
2253 $email = null;
2254 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2255 {
2256 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2257 }
2258 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2259 {
2260 $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]));
2261 }
2262 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2263 {
2264 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2265 }
2266 if ($name !== null || $email !== null || $uri !== null)
2267 {
73f27201 2268 $contributors[] = new $this->author_class($name, $uri, $email);
80d72d56 2269 }
2270 }
2271 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2272 {
2273 $name = null;
2274 $url = null;
2275 $email = null;
2276 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2277 {
2278 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2279 }
2280 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2281 {
2282 $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]));
2283 }
2284 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2285 {
2286 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2287 }
2288 if ($name !== null || $email !== null || $url !== null)
2289 {
73f27201 2290 $contributors[] = new $this->author_class($name, $url, $email);
80d72d56 2291 }
2292 }
2293
2294 if (!empty($contributors))
2295 {
2296 return SimplePie_Misc::array_unique($contributors);
2297 }
2298 else
2299 {
2300 return null;
2301 }
2302 }
2303
73f27201 2304 public function get_link($key = 0, $rel = 'alternate')
80d72d56 2305 {
2306 $links = $this->get_links($rel);
2307 if (isset($links[$key]))
2308 {
2309 return $links[$key];
2310 }
2311 else
2312 {
2313 return null;
2314 }
2315 }
2316
2317 /**
2318 * Added for parity between the parent-level and the item/entry-level.
2319 */
73f27201 2320 public function get_permalink()
80d72d56 2321 {
2322 return $this->get_link(0);
2323 }
2324
73f27201 2325 public function get_links($rel = 'alternate')
80d72d56 2326 {
2327 if (!isset($this->data['links']))
2328 {
2329 $this->data['links'] = array();
2330 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2331 {
2332 foreach ($links as $link)
2333 {
2334 if (isset($link['attribs']['']['href']))
2335 {
2336 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2337 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2338 }
2339 }
2340 }
2341 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2342 {
2343 foreach ($links as $link)
2344 {
2345 if (isset($link['attribs']['']['href']))
2346 {
2347 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2348 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2349
2350 }
2351 }
2352 }
2353 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2354 {
2355 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2356 }
2357 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2358 {
2359 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2360 }
ec00bfc5 2361 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
80d72d56 2362 {
2363 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2364 }
2365
2366 $keys = array_keys($this->data['links']);
2367 foreach ($keys as $key)
2368 {
2369 if (SimplePie_Misc::is_isegment_nz_nc($key))
2370 {
2371 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2372 {
2373 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2374 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2375 }
2376 else
2377 {
2378 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2379 }
2380 }
ec00bfc5 2381 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
80d72d56 2382 {
2383 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2384 }
2385 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2386 }
2387 }
2388
2389 if (isset($this->data['links'][$rel]))
2390 {
2391 return $this->data['links'][$rel];
2392 }
2393 else
2394 {
2395 return null;
2396 }
2397 }
2398
73f27201 2399 public function get_all_discovered_feeds()
ec00bfc5 2400 {
2401 return $this->all_discovered_feeds;
2402 }
2403
73f27201 2404 public function get_description()
80d72d56 2405 {
2406 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2407 {
2408 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2409 }
2410 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2411 {
2412 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2413 }
2414 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2415 {
2416 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2417 }
2418 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2419 {
2420 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2421 }
ec00bfc5 2422 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
80d72d56 2423 {
ec00bfc5 2424 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
80d72d56 2425 }
2426 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2427 {
2428 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2429 }
2430 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2431 {
2432 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2433 }
2434 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2435 {
2436 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2437 }
2438 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2439 {
2440 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2441 }
2442 else
2443 {
2444 return null;
2445 }
2446 }
2447
73f27201 2448 public function get_copyright()
80d72d56 2449 {
2450 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2451 {
2452 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2453 }
2454 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2455 {
2456 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2457 }
ec00bfc5 2458 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
80d72d56 2459 {
2460 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2461 }
2462 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2463 {
2464 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2465 }
2466 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2467 {
2468 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2469 }
2470 else
2471 {
2472 return null;
2473 }
2474 }
2475
73f27201 2476 public function get_language()
80d72d56 2477 {
ec00bfc5 2478 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
80d72d56 2479 {
2480 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2481 }
2482 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2483 {
2484 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2485 }
2486 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2487 {
2488 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2489 }
2490 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2491 {
2492 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2493 }
2494 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2495 {
2496 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2497 }
2498 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2499 {
2500 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2501 }
2502 elseif (isset($this->data['headers']['content-language']))
2503 {
2504 return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2505 }
2506 else
2507 {
2508 return null;
2509 }
2510 }
2511
73f27201 2512 public function get_latitude()
80d72d56 2513 {
73f27201 2514
80d72d56 2515 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2516 {
2517 return (float) $return[0]['data'];
2518 }
73f27201 2519 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 2520 {
2521 return (float) $match[1];
2522 }
2523 else
2524 {
2525 return null;
2526 }
2527 }
2528
73f27201 2529 public function get_longitude()
80d72d56 2530 {
2531 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2532 {
2533 return (float) $return[0]['data'];
2534 }
2535 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2536 {
2537 return (float) $return[0]['data'];
2538 }
73f27201 2539 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 2540 {
2541 return (float) $match[2];
2542 }
2543 else
2544 {
2545 return null;
2546 }
2547 }
2548
73f27201 2549 public function get_image_title()
80d72d56 2550 {
2551 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2552 {
2553 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2554 }
2555 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2556 {
2557 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2558 }
ec00bfc5 2559 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
80d72d56 2560 {
2561 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2562 }
2563 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2564 {
2565 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2566 }
2567 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2568 {
2569 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2570 }
2571 else
2572 {
2573 return null;
2574 }
2575 }
2576
73f27201 2577 public function get_image_url()
80d72d56 2578 {
2579 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2580 {
2581 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2582 }
2583 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2584 {
2585 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2586 }
2587 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2588 {
2589 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2590 }
2591 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2592 {
2593 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2594 }
2595 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2596 {
2597 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2598 }
ec00bfc5 2599 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
80d72d56 2600 {
2601 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2602 }
2603 else
2604 {
2605 return null;
2606 }
2607 }
2608
73f27201 2609 public function get_image_link()
80d72d56 2610 {
2611 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2612 {
2613 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2614 }
2615 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2616 {
2617 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2618 }
ec00bfc5 2619 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
80d72d56 2620 {
2621 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2622 }
2623 else
2624 {
2625 return null;
2626 }
2627 }
2628
73f27201 2629 public function get_image_width()
80d72d56 2630 {
ec00bfc5 2631 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
80d72d56 2632 {
2633 return round($return[0]['data']);
2634 }
ec00bfc5 2635 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
80d72d56 2636 {
2637 return 88.0;
2638 }
2639 else
2640 {
2641 return null;
2642 }
2643 }
2644
73f27201 2645 public function get_image_height()
80d72d56 2646 {
ec00bfc5 2647 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
80d72d56 2648 {
2649 return round($return[0]['data']);
2650 }
ec00bfc5 2651 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
80d72d56 2652 {
2653 return 31.0;
2654 }
2655 else
2656 {
2657 return null;
2658 }
2659 }
2660
73f27201 2661 public function get_item_quantity($max = 0)
80d72d56 2662 {
ec00bfc5 2663 $max = (int) $max;
80d72d56 2664 $qty = count($this->get_items());
ec00bfc5 2665 if ($max === 0)
80d72d56 2666 {
2667 return $qty;
2668 }
2669 else
2670 {
2671 return ($qty > $max) ? $max : $qty;
2672 }
2673 }
2674
73f27201 2675 public function get_item($key = 0)
80d72d56 2676 {
2677 $items = $this->get_items();
2678 if (isset($items[$key]))
2679 {
2680 return $items[$key];
2681 }
2682 else
2683 {
2684 return null;
2685 }
2686 }
2687
73f27201 2688 public function get_items($start = 0, $end = 0)
80d72d56 2689 {
ec00bfc5 2690 if (!isset($this->data['items']))
80d72d56 2691 {
ec00bfc5 2692 if (!empty($this->multifeed_objects))
80d72d56 2693 {
ec00bfc5 2694 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
80d72d56 2695 }
ec00bfc5 2696 else
80d72d56 2697 {
ec00bfc5 2698 $this->data['items'] = array();
2699 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
80d72d56 2700 {
ec00bfc5 2701 $keys = array_keys($items);
2702 foreach ($keys as $key)
2703 {
73f27201 2704 $this->data['items'][] = new $this->item_class($this, $items[$key]);
ec00bfc5 2705 }
80d72d56 2706 }
ec00bfc5 2707 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, '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_RSS_10, 'item'))
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_090, 'item'))
2724 {
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 }
2730 }
2731 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
80d72d56 2732 {
ec00bfc5 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 }
80d72d56 2738 }
2739 }
2740 }
2741
2742 if (!empty($this->data['items']))
2743 {
2744 // If we want to order it by date, check if all items have a date, and then sort it
ec00bfc5 2745 if ($this->order_by_date && empty($this->multifeed_objects))
80d72d56 2746 {
2747 if (!isset($this->data['ordered_items']))
2748 {
2749 $do_sort = true;
2750 foreach ($this->data['items'] as $item)
2751 {
2752 if (!$item->get_date('U'))
2753 {
2754 $do_sort = false;
2755 break;
2756 }
2757 }
2758 $item = null;
2759 $this->data['ordered_items'] = $this->data['items'];
2760 if ($do_sort)
2761 {
2762 usort($this->data['ordered_items'], array(&$this, 'sort_items'));
2763 }
2764 }
2765 $items = $this->data['ordered_items'];
2766 }
2767 else
2768 {
2769 $items = $this->data['items'];
2770 }
2771
2772 // Slice the data as desired
ec00bfc5 2773 if ($end === 0)
80d72d56 2774 {
2775 return array_slice($items, $start);
2776 }
2777 else
2778 {
2779 return array_slice($items, $start, $end);
2780 }
2781 }
2782 else
2783 {
2784 return array();
2785 }
2786 }
2787
ec00bfc5 2788 /**
2789 * @static
2790 */
73f27201 2791 public function sort_items($a, $b)
80d72d56 2792 {
2793 return $a->get_date('U') <= $b->get_date('U');
2794 }
2795
ec00bfc5 2796 /**
2797 * @static
2798 */
73f27201 2799 public function merge_items($urls, $start = 0, $end = 0, $limit = 0)
80d72d56 2800 {
2801 if (is_array($urls) && sizeof($urls) > 0)
2802 {
2803 $items = array();
2804 foreach ($urls as $arg)
2805 {
2806 if (is_a($arg, 'SimplePie'))
2807 {
2808 $items = array_merge($items, $arg->get_items(0, $limit));
2809 }
2810 else
2811 {
2812 trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
2813 }
2814 }
2815
2816 $do_sort = true;
2817 foreach ($items as $item)
2818 {
2819 if (!$item->get_date('U'))
2820 {
2821 $do_sort = false;
2822 break;
2823 }
2824 }
2825 $item = null;
2826 if ($do_sort)
2827 {
2828 usort($items, array('SimplePie', 'sort_items'));
2829 }
2830
ec00bfc5 2831 if ($end === 0)
80d72d56 2832 {
2833 return array_slice($items, $start);
2834 }
2835 else
2836 {
2837 return array_slice($items, $start, $end);
2838 }
2839 }
2840 else
2841 {
2842 trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
2843 return array();
2844 }
2845 }
2846}
2847
2848class SimplePie_Item
2849{
2850 var $feed;
2851 var $data = array();
2852
73f27201 2853 public function __construct($feed, $data)
80d72d56 2854 {
2855 $this->feed = $feed;
2856 $this->data = $data;
2857 }
2858
73f27201 2859 public function __toString()
80d72d56 2860 {
2861 return md5(serialize($this->data));
2862 }
2863
2864 /**
2865 * Remove items that link back to this before destroying this object
2866 */
73f27201 2867 public function __destruct()
80d72d56 2868 {
ec00bfc5 2869 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
2870 {
2871 unset($this->feed);
2872 }
80d72d56 2873 }
2874
73f27201 2875 public function get_item_tags($namespace, $tag)
80d72d56 2876 {
2877 if (isset($this->data['child'][$namespace][$tag]))
2878 {
2879 return $this->data['child'][$namespace][$tag];
2880 }
2881 else
2882 {
2883 return null;
2884 }
2885 }
2886
73f27201 2887 public function get_base($element = array())
80d72d56 2888 {
2889 return $this->feed->get_base($element);
2890 }
2891
73f27201 2892 public function sanitize($data, $type, $base = '')
80d72d56 2893 {
2894 return $this->feed->sanitize($data, $type, $base);
2895 }
2896
73f27201 2897 public function get_feed()
80d72d56 2898 {
2899 return $this->feed;
2900 }
2901
73f27201 2902 public function get_id($hash = false)
80d72d56 2903 {
2904 if (!$hash)
2905 {
2906 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
2907 {
2908 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2909 }
2910 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
2911 {
2912 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2913 }
ec00bfc5 2914 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
80d72d56 2915 {
2916 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2917 }
2918 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
2919 {
2920 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2921 }
2922 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
2923 {
2924 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2925 }
2926 elseif (($return = $this->get_permalink()) !== null)
2927 {
2928 return $return;
2929 }
2930 elseif (($return = $this->get_title()) !== null)
2931 {
2932 return $return;
2933 }
2934 }
2935 if ($this->get_permalink() !== null || $this->get_title() !== null)
2936 {
2937 return md5($this->get_permalink() . $this->get_title());
2938 }
2939 else
2940 {
2941 return md5(serialize($this->data));
2942 }
2943 }
2944
73f27201 2945 public function get_title()
80d72d56 2946 {
2947 if (!isset($this->data['title']))
2948 {
2949 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2950 {
2951 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2952 }
2953 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2954 {
2955 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2956 }
2957 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2958 {
2959 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2960 }
2961 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2962 {
2963 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2964 }
ec00bfc5 2965 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
80d72d56 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_DC_11, 'title'))
2970 {
2971 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2972 }
2973 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2974 {
2975 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2976 }
2977 else
2978 {
2979 $this->data['title'] = null;
2980 }
2981 }
2982 return $this->data['title'];
2983 }
2984
73f27201 2985 public function get_description($description_only = false)
80d72d56 2986 {
2987 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
2988 {
2989 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2990 }
2991 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
2992 {
2993 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2994 }
2995 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2996 {
2997 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2998 }
ec00bfc5 2999 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
80d72d56 3000 {
3001 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3002 }
3003 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3004 {
3005 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3006 }
3007 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3008 {
3009 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3010 }
3011 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3012 {
3013 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3014 }
3015 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3016 {
3017 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3018 }
a762ba72
PS
3019 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
3020 {
3021 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML);
3022 }
3023
80d72d56 3024 elseif (!$description_only)
3025 {
3026 return $this->get_content(true);
3027 }
3028 else
3029 {
3030 return null;
3031 }
3032 }
3033
73f27201 3034 public function get_content($content_only = false)
80d72d56 3035 {
3036 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3037 {
3038 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3039 }
3040 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3041 {
3042 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3043 }
3044 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3045 {
3046 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3047 }
3048 elseif (!$content_only)
3049 {
3050 return $this->get_description(true);
3051 }
3052 else
3053 {
3054 return null;
3055 }
3056 }
3057
73f27201 3058 public function get_category($key = 0)
80d72d56 3059 {
3060 $categories = $this->get_categories();
3061 if (isset($categories[$key]))
3062 {
3063 return $categories[$key];
3064 }
3065 else
3066 {
3067 return null;
3068 }
3069 }
3070
73f27201 3071 public function get_categories()
80d72d56 3072 {
3073 $categories = array();
3074
3075 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3076 {
3077 $term = null;
3078 $scheme = null;
3079 $label = null;
3080 if (isset($category['attribs']['']['term']))
3081 {
3082 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3083 }
3084 if (isset($category['attribs']['']['scheme']))
3085 {
3086 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3087 }
3088 if (isset($category['attribs']['']['label']))
3089 {
3090 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3091 }
73f27201 3092 $categories[] = new $this->feed->category_class($term, $scheme, $label);
80d72d56 3093 }
ec00bfc5 3094 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
80d72d56 3095 {
ec00bfc5 3096 // This is really the label, but keep this as the term also for BC.
3097 // Label will also work on retrieving because that falls back to term.
3098 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3099 if (isset($category['attribs']['']['domain']))
3100 {
3101 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
3102 }
3103 else
3104 {
3105 $scheme = null;
3106 }
73f27201 3107 $categories[] = new $this->feed->category_class($term, $scheme, null);
80d72d56 3108 }
3109 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3110 {
73f27201 3111 $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
80d72d56 3112 }
3113 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3114 {
73f27201 3115 $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
80d72d56 3116 }
3117
3118 if (!empty($categories))
3119 {
3120 return SimplePie_Misc::array_unique($categories);
3121 }
3122 else
3123 {
3124 return null;
3125 }
3126 }
3127
73f27201 3128 public function get_author($key = 0)
80d72d56 3129 {
3130 $authors = $this->get_authors();
3131 if (isset($authors[$key]))
3132 {
3133 return $authors[$key];
3134 }
3135 else
3136 {
3137 return null;
3138 }
3139 }
3140
73f27201 3141 public function get_contributor($key = 0)
80d72d56 3142 {
3143 $contributors = $this->get_contributors();
3144 if (isset($contributors[$key]))
3145 {
3146 return $contributors[$key];
3147 }
3148 else
3149 {
3150 return null;
3151 }
3152 }
3153
73f27201 3154 public function get_contributors()
80d72d56 3155 {
3156 $contributors = array();
3157 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3158 {
3159 $name = null;
3160 $uri = null;
3161 $email = null;
3162 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3163 {
3164 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3165 }
3166 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3167 {
3168 $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]));
3169 }
3170 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3171 {
3172 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3173 }
3174 if ($name !== null || $email !== null || $uri !== null)
3175 {
73f27201 3176 $contributors[] = new $this->feed->author_class($name, $uri, $email);
80d72d56 3177 }
3178 }
3179 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3180 {
3181 $name = null;
3182 $url = null;
3183 $email = null;
3184 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3185 {
3186 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3187 }
3188 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3189 {
3190 $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]));
3191 }
3192 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3193 {
3194 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3195 }
3196 if ($name !== null || $email !== null || $url !== null)
3197 {
73f27201 3198 $contributors[] = new $this->feed->author_class($name, $url, $email);
80d72d56 3199 }
3200 }
3201
3202 if (!empty($contributors))
3203 {
3204 return SimplePie_Misc::array_unique($contributors);
3205 }
3206 else
3207 {
3208 return null;
3209 }
3210 }
3211
73f27201 3212 public function get_authors()
80d72d56 3213 {
3214 $authors = array();
3215 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3216 {
3217 $name = null;
3218 $uri = null;
3219 $email = null;
3220 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3221 {
3222 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3223 }
3224 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3225 {
3226 $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]));
3227 }
3228 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3229 {
3230 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3231 }
3232 if ($name !== null || $email !== null || $uri !== null)
3233 {
73f27201 3234 $authors[] = new $this->feed->author_class($name, $uri, $email);
80d72d56 3235 }
3236 }
3237 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3238 {
3239 $name = null;
3240 $url = null;
3241 $email = null;
3242 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3243 {
3244 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3245 }
3246 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3247 {
3248 $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]));
3249 }
3250 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3251 {
3252 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3253 }
3254 if ($name !== null || $email !== null || $url !== null)
3255 {
73f27201 3256 $authors[] = new $this->feed->author_class($name, $url, $email);
80d72d56 3257 }
3258 }
ec00bfc5 3259 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
80d72d56 3260 {
73f27201 3261 $authors[] = new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
80d72d56 3262 }
3263 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3264 {
73f27201 3265 $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
80d72d56 3266 }
3267 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3268 {
73f27201 3269 $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
80d72d56 3270 }
3271 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3272 {
73f27201 3273 $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
80d72d56 3274 }
3275
3276 if (!empty($authors))
3277 {
3278 return SimplePie_Misc::array_unique($authors);
3279 }
3280 elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3281 {
3282 return $authors;
3283 }
3284 elseif ($authors = $this->feed->get_authors())
3285 {
3286 return $authors;
3287 }
3288 else
3289 {
3290 return null;
3291 }
3292 }
3293
73f27201 3294 public function get_copyright()
80d72d56 3295 {
3296 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3297 {
3298 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3299 }
3300 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3301 {
3302 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3303 }
3304 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3305 {
3306 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3307 }
3308 else
3309 {
3310 return null;
3311 }
3312 }
3313
73f27201 3314 public function get_date($date_format = 'j F Y, g:i a')
80d72d56 3315 {
3316 if (!isset($this->data['date']))
3317 {
3318 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3319 {
3320 $this->data['date']['raw'] = $return[0]['data'];
3321 }
3322 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3323 {
3324 $this->data['date']['raw'] = $return[0]['data'];
3325 }
3326 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3327 {
3328 $this->data['date']['raw'] = $return[0]['data'];
3329 }
3330 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3331 {
3332 $this->data['date']['raw'] = $return[0]['data'];
3333 }
3334 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3335 {
3336 $this->data['date']['raw'] = $return[0]['data'];
3337 }
ec00bfc5 3338 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
80d72d56 3339 {
3340 $this->data['date']['raw'] = $return[0]['data'];
3341 }
3342 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3343 {
3344 $this->data['date']['raw'] = $return[0]['data'];
3345 }
3346 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3347 {
3348 $this->data['date']['raw'] = $return[0]['data'];
3349 }
3350
3351 if (!empty($this->data['date']['raw']))
3352 {
3353 $parser = SimplePie_Parse_Date::get();
3354 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3355 }
3356 else
3357 {
3358 $this->data['date'] = null;
3359 }
3360 }
3361 if ($this->data['date'])
3362 {
3363 $date_format = (string) $date_format;
3364 switch ($date_format)
3365 {
3366 case '':
3367 return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3368
3369 case 'U':
3370 return $this->data['date']['parsed'];
3371
3372 default:
3373 return date($date_format, $this->data['date']['parsed']);
3374 }
3375 }
3376 else
3377 {
3378 return null;
3379 }
3380 }
3381
73f27201 3382 public function get_local_date($date_format = '%c')
80d72d56 3383 {
3384 if (!$date_format)
3385 {
3386 return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3387 }
a762ba72 3388 elseif (($date = $this->get_date('U')) !== null && $date !== false)
80d72d56 3389 {
3390 return strftime($date_format, $date);
3391 }
3392 else
3393 {
3394 return null;
3395 }
3396 }
3397
73f27201 3398 public function get_permalink()
80d72d56 3399 {
3400 $link = $this->get_link();
3401 $enclosure = $this->get_enclosure(0);
3402 if ($link !== null)
3403 {
3404 return $link;
3405 }
3406 elseif ($enclosure !== null)
3407 {
3408 return $enclosure->get_link();
3409 }
3410 else
3411 {
3412 return null;
3413 }
3414 }
3415
73f27201 3416 public function get_link($key = 0, $rel = 'alternate')
80d72d56 3417 {
3418 $links = $this->get_links($rel);
3419 if ($links[$key] !== null)
3420 {
3421 return $links[$key];
3422 }
3423 else
3424 {
3425 return null;
3426 }
3427 }
3428
73f27201 3429 public function get_links($rel = 'alternate')
80d72d56 3430 {
3431 if (!isset($this->data['links']))
3432 {
3433 $this->data['links'] = array();
3434 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3435 {
3436 if (isset($link['attribs']['']['href']))
3437 {
3438 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3439 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3440
3441 }
3442 }
3443 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3444 {
3445 if (isset($link['attribs']['']['href']))
3446 {
3447 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3448 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3449 }
3450 }
3451 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3452 {
3453 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3454 }
3455 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3456 {
3457 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3458 }
ec00bfc5 3459 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
80d72d56 3460 {
3461 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3462 }
ec00bfc5 3463 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
80d72d56 3464 {
ec00bfc5 3465 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
80d72d56 3466 {
3467 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3468 }
3469 }
3470
3471 $keys = array_keys($this->data['links']);
3472 foreach ($keys as $key)
3473 {
3474 if (SimplePie_Misc::is_isegment_nz_nc($key))
3475 {
3476 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3477 {
3478 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3479 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3480 }
3481 else
3482 {
3483 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3484 }
3485 }
ec00bfc5 3486 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
80d72d56 3487 {
3488 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3489 }
3490 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3491 }
3492 }
3493 if (isset($this->data['links'][$rel]))
3494 {
3495 return $this->data['links'][$rel];
3496 }
3497 else
3498 {
3499 return null;
3500 }
3501 }
3502
3503 /**
3504 * @todo Add ability to prefer one type of content over another (in a media group).
3505 */
73f27201 3506 public function get_enclosure($key = 0, $prefer = null)
80d72d56 3507 {
3508 $enclosures = $this->get_enclosures();
3509 if (isset($enclosures[$key]))
3510 {
3511 return $enclosures[$key];
3512 }
3513 else
3514 {
3515 return null;
3516 }
3517 }
3518
3519 /**
3520 * Grabs all available enclosures (podcasts, etc.)
3521 *
3522 * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3523 *
3524 * 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.
3525 *
3526 * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3527 * @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).
3528 */
73f27201 3529 public function get_enclosures()
80d72d56 3530 {
3531 if (!isset($this->data['enclosures']))
3532 {
3533 $this->data['enclosures'] = array();
3534
3535 // Elements
3536 $captions_parent = null;
3537 $categories_parent = null;