Marius Cramer
2013-11-20 56364927166c1a0e15166433613add7f300ef7f6
commit | author | age
fd9ef2 1 <?php
T 2 /**
3  * SimplePie
4  *
5  * A PHP-Based RSS and Atom Feed Framework.
6  * Takes the hard work out of managing a complete RSS/Atom solution.
7  *
8  * Copyright (c) 2004-2009, Ryan Parman and Geoffrey Sneddon
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without modification, are
12  * permitted provided that the following conditions are met:
13  *
b1a6a5 14  *  * Redistributions of source code must retain the above copyright notice, this list of
MC 15  *    conditions and the following disclaimer.
fd9ef2 16  *
b1a6a5 17  *  * Redistributions in binary form must reproduce the above copyright notice, this list
MC 18  *    of conditions and the following disclaimer in the documentation and/or other materials
19  *    provided with the distribution.
fd9ef2 20  *
b1a6a5 21  *  * Neither the name of the SimplePie Team nor the names of its contributors may be used
MC 22  *    to endorse or promote products derived from this software without specific prior
23  *    written permission.
fd9ef2 24  *
T 25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28  * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * @package SimplePie
36  * @version 1.2.1-dev
37  * @copyright 2004-2009 Ryan Parman, Geoffrey Sneddon
38  * @author Ryan Parman
39  * @author Geoffrey Sneddon
40  * @link http://simplepie.org/ SimplePie
41  * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
42  * @license http://www.opensource.org/licenses/bsd-license.php BSD License
43  * @todo phpDoc comments
44  */
b1a6a5 45
fd9ef2 46
T 47 /**
48  * SimplePie Name
49  */
50 define('SIMPLEPIE_NAME', 'SimplePie');
51
52 /**
53  * SimplePie Version
54  */
55 define('SIMPLEPIE_VERSION', '1.2.1-dev');
56
57 /**
58  * SimplePie Build
59  * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::parse_date() only every load of simplepie.inc)
60  */
61 define('SIMPLEPIE_BUILD', gmdate('YmdHis', SimplePie_Misc::parse_date(substr('$Date$', 7, 25)) ? SimplePie_Misc::parse_date(substr('$Date$', 7, 25)) : filemtime(__FILE__)));
62
63 /**
64  * SimplePie Website URL
65  */
66 define('SIMPLEPIE_URL', 'http://simplepie.org');
67
68 /**
69  * SimplePie Useragent
70  * @see SimplePie::set_useragent()
71  */
72 define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
73
74 /**
75  * SimplePie Linkback
76  */
77 define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
78
79 /**
80  * No Autodiscovery
81  * @see SimplePie::set_autodiscovery_level()
82  */
83 define('SIMPLEPIE_LOCATOR_NONE', 0);
84
85 /**
86  * Feed Link Element Autodiscovery
87  * @see SimplePie::set_autodiscovery_level()
88  */
89 define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
90
91 /**
92  * Local Feed Extension Autodiscovery
93  * @see SimplePie::set_autodiscovery_level()
94  */
95 define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
96
97 /**
98  * Local Feed Body Autodiscovery
99  * @see SimplePie::set_autodiscovery_level()
100  */
101 define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
102
103 /**
104  * Remote Feed Extension Autodiscovery
105  * @see SimplePie::set_autodiscovery_level()
106  */
107 define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
108
109 /**
110  * Remote Feed Body Autodiscovery
111  * @see SimplePie::set_autodiscovery_level()
112  */
113 define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
114
115 /**
116  * All Feed Autodiscovery
117  * @see SimplePie::set_autodiscovery_level()
118  */
119 define('SIMPLEPIE_LOCATOR_ALL', 31);
120
121 /**
122  * No known feed type
123  */
124 define('SIMPLEPIE_TYPE_NONE', 0);
125
126 /**
127  * RSS 0.90
128  */
129 define('SIMPLEPIE_TYPE_RSS_090', 1);
130
131 /**
132  * RSS 0.91 (Netscape)
133  */
134 define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
135
136 /**
137  * RSS 0.91 (Userland)
138  */
139 define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
140
141 /**
142  * RSS 0.91 (both Netscape and Userland)
143  */
144 define('SIMPLEPIE_TYPE_RSS_091', 6);
145
146 /**
147  * RSS 0.92
148  */
149 define('SIMPLEPIE_TYPE_RSS_092', 8);
150
151 /**
152  * RSS 0.93
153  */
154 define('SIMPLEPIE_TYPE_RSS_093', 16);
155
156 /**
157  * RSS 0.94
158  */
159 define('SIMPLEPIE_TYPE_RSS_094', 32);
160
161 /**
162  * RSS 1.0
163  */
164 define('SIMPLEPIE_TYPE_RSS_10', 64);
165
166 /**
167  * RSS 2.0
168  */
169 define('SIMPLEPIE_TYPE_RSS_20', 128);
170
171 /**
172  * RDF-based RSS
173  */
174 define('SIMPLEPIE_TYPE_RSS_RDF', 65);
175
176 /**
177  * Non-RDF-based RSS (truly intended as syndication format)
178  */
179 define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
180
181 /**
182  * All RSS
183  */
184 define('SIMPLEPIE_TYPE_RSS_ALL', 255);
185
186 /**
187  * Atom 0.3
188  */
189 define('SIMPLEPIE_TYPE_ATOM_03', 256);
190
191 /**
192  * Atom 1.0
193  */
194 define('SIMPLEPIE_TYPE_ATOM_10', 512);
195
196 /**
197  * All Atom
198  */
199 define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
200
201 /**
202  * All feed types
203  */
204 define('SIMPLEPIE_TYPE_ALL', 1023);
205
206 /**
207  * No construct
208  */
209 define('SIMPLEPIE_CONSTRUCT_NONE', 0);
210
211 /**
212  * Text construct
213  */
214 define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
215
216 /**
217  * HTML construct
218  */
219 define('SIMPLEPIE_CONSTRUCT_HTML', 2);
220
221 /**
222  * XHTML construct
223  */
224 define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
225
226 /**
227  * base64-encoded construct
228  */
229 define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
230
231 /**
232  * IRI construct
233  */
234 define('SIMPLEPIE_CONSTRUCT_IRI', 16);
235
236 /**
237  * A construct that might be HTML
238  */
239 define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
240
241 /**
242  * All constructs
243  */
244 define('SIMPLEPIE_CONSTRUCT_ALL', 63);
245
246 /**
247  * Don't change case
248  */
249 define('SIMPLEPIE_SAME_CASE', 1);
250
251 /**
252  * Change to lowercase
253  */
254 define('SIMPLEPIE_LOWERCASE', 2);
255
256 /**
257  * Change to uppercase
258  */
259 define('SIMPLEPIE_UPPERCASE', 4);
260
261 /**
262  * PCRE for HTML attributes
263  */
264 define('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]*');
265
266 /**
267  * PCRE for XML attributes
268  */
269 define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
270
271 /**
272  * XML Namespace
273  */
274 define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
275
276 /**
277  * Atom 1.0 Namespace
278  */
279 define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
280
281 /**
282  * Atom 0.3 Namespace
283  */
284 define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
285
286 /**
287  * RDF Namespace
288  */
289 define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
290
291 /**
292  * RSS 0.90 Namespace
293  */
294 define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
295
296 /**
297  * RSS 1.0 Namespace
298  */
299 define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
300
301 /**
302  * RSS 1.0 Content Module Namespace
303  */
304 define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
305
306 /**
307  * RSS 2.0 Namespace
308  * (Stupid, I know, but I'm certain it will confuse people less with support.)
309  */
310 define('SIMPLEPIE_NAMESPACE_RSS_20', '');
311
312 /**
313  * DC 1.0 Namespace
314  */
315 define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
316
317 /**
318  * DC 1.1 Namespace
319  */
320 define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
321
322 /**
323  * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
324  */
325 define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
326
327 /**
328  * GeoRSS Namespace
329  */
330 define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
331
332 /**
333  * Media RSS Namespace
334  */
335 define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
336
337 /**
338  * Wrong Media RSS Namespace
339  */
340 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
341
342 /**
343  * iTunes RSS Namespace
344  */
345 define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
346
347 /**
348  * XHTML Namespace
349  */
350 define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
351
352 /**
353  * IANA Link Relations Registry
354  */
355 define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
356
357 /**
358  * Whether we're running on PHP5
359  */
360 define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
361
362 /**
363  * No file source
364  */
365 define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
366
367 /**
368  * Remote file source
369  */
370 define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
371
372 /**
373  * Local file source
374  */
375 define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
376
377 /**
378  * fsockopen() file source
379  */
380 define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
381
382 /**
383  * cURL file source
384  */
385 define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
386
387 /**
388  * file_get_contents() file source
389  */
390 define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
391
392 /**
393  * SimplePie
394  *
395  * @package SimplePie
396  */
397 class simplepie
398 {
b1a6a5 399
fd9ef2 400     /**
T 401      * @var array Raw data
402      * @access private
403      */
404     var $data = array();
405
406     /**
407      * @var mixed Error string
408      * @access private
409      */
410     var $error;
411
412     /**
413      * @var object Instance of SimplePie_Sanitize (or other class)
414      * @see SimplePie::set_sanitize_class()
415      * @access private
416      */
417     var $sanitize;
418
419     /**
420      * @var string SimplePie Useragent
421      * @see SimplePie::set_useragent()
422      * @access private
423      */
424     var $useragent = SIMPLEPIE_USERAGENT;
425
426     /**
427      * @var string Feed URL
428      * @see SimplePie::set_feed_url()
429      * @access private
430      */
431     var $feed_url;
432
433     /**
434      * @var object Instance of SimplePie_File to use as a feed
435      * @see SimplePie::set_file()
436      * @access private
437      */
438     var $file;
439
440     /**
441      * @var string Raw feed data
442      * @see SimplePie::set_raw_data()
443      * @access private
444      */
445     var $raw_data;
446
447     /**
448      * @var int Timeout for fetching remote files
449      * @see SimplePie::set_timeout()
450      * @access private
451      */
452     var $timeout = 10;
453
454     /**
455      * @var bool Forces fsockopen() to be used for remote files instead
456      * of cURL, even if a new enough version is installed
457      * @see SimplePie::force_fsockopen()
458      * @access private
459      */
460     var $force_fsockopen = false;
461
462     /**
463      * @var bool Force the given data/URL to be treated as a feed no matter what
464      * it appears like
465      * @see SimplePie::force_feed()
466      * @access private
467      */
468     var $force_feed = false;
469
470     /**
471      * @var bool Enable/Disable XML dump
472      * @see SimplePie::enable_xml_dump()
473      * @access private
474      */
475     var $xml_dump = false;
476
477     /**
478      * @var bool Enable/Disable Caching
479      * @see SimplePie::enable_cache()
480      * @access private
481      */
482     var $cache = true;
483
484     /**
485      * @var int Cache duration (in seconds)
486      * @see SimplePie::set_cache_duration()
487      * @access private
488      */
489     var $cache_duration = 3600;
490
491     /**
492      * @var int Auto-discovery cache duration (in seconds)
493      * @see SimplePie::set_autodiscovery_cache_duration()
494      * @access private
495      */
496     var $autodiscovery_cache_duration = 604800; // 7 Days.
497
498     /**
499      * @var string Cache location (relative to executing script)
500      * @see SimplePie::set_cache_location()
501      * @access private
502      */
503     var $cache_location = './cache';
504
505     /**
506      * @var string Function that creates the cache filename
507      * @see SimplePie::set_cache_name_function()
508      * @access private
509      */
510     var $cache_name_function = 'md5';
511
512     /**
513      * @var bool Reorder feed by date descending
514      * @see SimplePie::enable_order_by_date()
515      * @access private
516      */
517     var $order_by_date = true;
518
519     /**
520      * @var mixed Force input encoding to be set to the follow value
521      * (false, or anything type-cast to false, disables this feature)
522      * @see SimplePie::set_input_encoding()
523      * @access private
524      */
525     var $input_encoding = false;
526
527     /**
528      * @var int Feed Autodiscovery Level
529      * @see SimplePie::set_autodiscovery_level()
530      * @access private
531      */
532     var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
533
534     /**
535      * @var string Class used for caching feeds
536      * @see SimplePie::set_cache_class()
537      * @access private
538      */
539     var $cache_class = 'SimplePie_Cache';
540
541     /**
542      * @var string Class used for locating feeds
543      * @see SimplePie::set_locator_class()
544      * @access private
545      */
546     var $locator_class = 'SimplePie_Locator';
547
548     /**
549      * @var string Class used for parsing feeds
550      * @see SimplePie::set_parser_class()
551      * @access private
552      */
553     var $parser_class = 'SimplePie_Parser';
554
555     /**
556      * @var string Class used for fetching feeds
557      * @see SimplePie::set_file_class()
558      * @access private
559      */
560     var $file_class = 'SimplePie_File';
561
562     /**
563      * @var string Class used for items
564      * @see SimplePie::set_item_class()
565      * @access private
566      */
567     var $item_class = 'SimplePie_Item';
568
569     /**
570      * @var string Class used for authors
571      * @see SimplePie::set_author_class()
572      * @access private
573      */
574     var $author_class = 'SimplePie_Author';
575
576     /**
577      * @var string Class used for categories
578      * @see SimplePie::set_category_class()
579      * @access private
580      */
581     var $category_class = 'SimplePie_Category';
582
583     /**
584      * @var string Class used for enclosures
585      * @see SimplePie::set_enclosures_class()
586      * @access private
587      */
588     var $enclosure_class = 'SimplePie_Enclosure';
589
590     /**
591      * @var string Class used for Media RSS <media:text> captions
592      * @see SimplePie::set_caption_class()
593      * @access private
594      */
595     var $caption_class = 'SimplePie_Caption';
596
597     /**
598      * @var string Class used for Media RSS <media:copyright>
599      * @see SimplePie::set_copyright_class()
600      * @access private
601      */
602     var $copyright_class = 'SimplePie_Copyright';
603
604     /**
605      * @var string Class used for Media RSS <media:credit>
606      * @see SimplePie::set_credit_class()
607      * @access private
608      */
609     var $credit_class = 'SimplePie_Credit';
610
611     /**
612      * @var string Class used for Media RSS <media:rating>
613      * @see SimplePie::set_rating_class()
614      * @access private
615      */
616     var $rating_class = 'SimplePie_Rating';
617
618     /**
619      * @var string Class used for Media RSS <media:restriction>
620      * @see SimplePie::set_restriction_class()
621      * @access private
622      */
623     var $restriction_class = 'SimplePie_Restriction';
624
625     /**
626      * @var string Class used for content-type sniffing
627      * @see SimplePie::set_content_type_sniffer_class()
628      * @access private
629      */
630     var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
631
632     /**
633      * @var string Class used for item sources.
634      * @see SimplePie::set_source_class()
635      * @access private
636      */
637     var $source_class = 'SimplePie_Source';
638
639     /**
640      * @var mixed Set javascript query string parameter (false, or
641      * anything type-cast to false, disables this feature)
642      * @see SimplePie::set_javascript()
643      * @access private
644      */
645     var $javascript = 'js';
646
647     /**
648      * @var int Maximum number of feeds to check with autodiscovery
649      * @see SimplePie::set_max_checked_feeds()
650      * @access private
651      */
652     var $max_checked_feeds = 10;
653
654     /**
655      * @var array All the feeds found during the autodiscovery process
656      * @see SimplePie::get_all_discovered_feeds()
657      * @access private
658      */
659     var $all_discovered_feeds = array();
660
661     /**
662      * @var string Web-accessible path to the handler_favicon.php file.
663      * @see SimplePie::set_favicon_handler()
664      * @access private
665      */
666     var $favicon_handler = '';
667
668     /**
669      * @var string Web-accessible path to the handler_image.php file.
670      * @see SimplePie::set_image_handler()
671      * @access private
672      */
673     var $image_handler = '';
674
675     /**
676      * @var array Stores the URLs when multiple feeds are being initialized.
677      * @see SimplePie::set_feed_url()
678      * @access private
679      */
680     var $multifeed_url = array();
681
682     /**
683      * @var array Stores SimplePie objects when multiple feeds initialized.
684      * @access private
685      */
686     var $multifeed_objects = array();
687
688     /**
689      * @var array Stores the get_object_vars() array for use with multifeeds.
690      * @see SimplePie::set_feed_url()
691      * @access private
692      */
693     var $config_settings = null;
694
695     /**
696      * @var integer Stores the number of items to return per-feed with multifeeds.
697      * @see SimplePie::set_item_limit()
698      * @access private
699      */
700     var $item_limit = 0;
701
702     /**
703      * @var array Stores the default attributes to be stripped by strip_attributes().
704      * @see SimplePie::strip_attributes()
705      * @access private
706      */
707     var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
708
709     /**
710      * @var array Stores the default tags to be stripped by strip_htmltags().
711      * @see SimplePie::strip_htmltags()
712      * @access private
713      */
714     var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
715
b1a6a5 716
fd9ef2 717     /**
T 718      * The SimplePie class contains feed level data and options
719      *
720      * There are two ways that you can create a new SimplePie object. The first
721      * is by passing a feed URL as a parameter to the SimplePie constructor
722      * (as well as optionally setting the cache location and cache expiry). This
723      * will initialise the whole feed with all of the default settings, and you
724      * can begin accessing methods and properties immediately.
725      *
726      * The second way is to create the SimplePie object with no parameters
727      * at all. This will enable you to set configuration options. After setting
728      * them, you must initialise the feed using $feed->init(). At that point the
729      * object's methods and properties will be available to you. This format is
730      * what is used throughout this documentation.
731      *
732      * @access public
733      * @since 1.0 Preview Release
734      * @param string $feed_url This is the URL you want to parse.
735      * @param string $cache_location This is where you want the cache to be stored.
736      * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
737      */
738     function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
739     {
740         // Other objects, instances created here so we can set options on them
f64c86 741         $this->sanitize = new SimplePie_Sanitize;
fd9ef2 742
T 743         // Set options if they're passed to the constructor
744         if ($cache_location !== null)
745         {
746             $this->set_cache_location($cache_location);
747         }
748
749         if ($cache_duration !== null)
750         {
751             $this->set_cache_duration($cache_duration);
752         }
753
754         // Only init the script if we're passed a feed URL
755         if ($feed_url !== null)
756         {
757             $this->set_feed_url($feed_url);
758             $this->init();
759         }
760     }
761
b1a6a5 762
fd9ef2 763     /**
T 764      * Used for converting object to a string
765      */
766     function __toString()
767     {
768         return md5(serialize($this->data));
769     }
b1a6a5 770
fd9ef2 771
T 772     /**
773      * Remove items that link back to this before destroying this object
774      */
775     function __destruct()
776     {
777         if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
778         {
779             if (!empty($this->data['items']))
780             {
781                 foreach ($this->data['items'] as $item)
782                 {
783                     $item->__destruct();
784                 }
785                 unset($item, $this->data['items']);
786             }
787             if (!empty($this->data['ordered_items']))
788             {
789                 foreach ($this->data['ordered_items'] as $item)
790                 {
791                     $item->__destruct();
792                 }
793                 unset($item, $this->data['ordered_items']);
794             }
795         }
796     }
797
b1a6a5 798
fd9ef2 799     /**
T 800      * Force the given data/URL to be treated as a feed no matter what it
801      * appears like
802      *
803      * @access public
804      * @since 1.1
805      * @param bool $enable Force the given data/URL to be treated as a feed
806      */
807     function force_feed($enable = false)
808     {
809         $this->force_feed = (bool) $enable;
810     }
b1a6a5 811
fd9ef2 812
T 813     /**
814      * This is the URL of the feed you want to parse.
815      *
816      * This allows you to enter the URL of the feed you want to parse, or the
817      * website you want to try to use auto-discovery on. This takes priority
818      * over any set raw data.
819      *
820      * You can set multiple feeds to mash together by passing an array instead
821      * of a string for the $url. Remember that with each additional feed comes
822      * additional processing and resources.
823      *
824      * @access public
825      * @since 1.0 Preview Release
826      * @param mixed $url This is the URL (or array of URLs) that you want to parse.
827      * @see SimplePie::set_raw_data()
828      */
829     function set_feed_url($url)
830     {
831         if (is_array($url))
832         {
833             $this->multifeed_url = array();
834             foreach ($url as $value)
835             {
836                 $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
837             }
838         }
839         else
840         {
841             $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
842         }
843     }
844
b1a6a5 845
fd9ef2 846     /**
T 847      * Provides an instance of SimplePie_File to use as a feed
848      *
849      * @access public
850      * @param object &$file Instance of SimplePie_File (or subclass)
851      * @return bool True on success, false on failure
852      */
853     function set_file(&$file)
854     {
855         if (is_a($file, 'SimplePie_File'))
856         {
857             $this->feed_url = $file->url;
858             $this->file =& $file;
859             return true;
860         }
861         return false;
862     }
863
b1a6a5 864
fd9ef2 865     /**
T 866      * Allows you to use a string of RSS/Atom data instead of a remote feed.
867      *
868      * If you have a feed available as a string in PHP, you can tell SimplePie
869      * to parse that data string instead of a remote feed. Any set feed URL
870      * takes precedence.
871      *
872      * @access public
873      * @since 1.0 Beta 3
874      * @param string $data RSS or Atom data as a string.
875      * @see SimplePie::set_feed_url()
876      */
877     function set_raw_data($data)
878     {
879         $this->raw_data = $data;
880     }
881
b1a6a5 882
fd9ef2 883     /**
T 884      * Allows you to override the default timeout for fetching remote feeds.
885      *
886      * This allows you to change the maximum time the feed's server to respond
887      * and send the feed back.
888      *
889      * @access public
890      * @since 1.0 Beta 3
891      * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
892      */
893     function set_timeout($timeout = 10)
894     {
895         $this->timeout = (int) $timeout;
896     }
897
b1a6a5 898
fd9ef2 899     /**
T 900      * Forces SimplePie to use fsockopen() instead of the preferred cURL
901      * functions.
902      *
903      * @access public
904      * @since 1.0 Beta 3
905      * @param bool $enable Force fsockopen() to be used
906      */
907     function force_fsockopen($enable = false)
908     {
909         $this->force_fsockopen = (bool) $enable;
910     }
b1a6a5 911
fd9ef2 912
T 913     /**
914      * Outputs the raw XML content of the feed, after it has gone through
915      * SimplePie's filters.
916      *
917      * Used only for debugging, this function will output the XML content as
918      * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
919      * before trying to parse it. Many parts of the feed are re-written in
920      * memory, and in the end, you have a parsable feed. XML dump shows you the
921      * actual XML that SimplePie tries to parse, which may or may not be very
922      * different from the original feed.
923      *
924      * @access public
925      * @since 1.0 Preview Release
926      * @param bool $enable Enable XML dump
927      */
928     function enable_xml_dump($enable = false)
929     {
930         $this->xml_dump = (bool) $enable;
931     }
932
b1a6a5 933
fd9ef2 934     /**
T 935      * Enables/disables caching in SimplePie.
936      *
937      * This option allows you to disable caching all-together in SimplePie.
938      * However, disabling the cache can lead to longer load times.
939      *
940      * @access public
941      * @since 1.0 Preview Release
942      * @param bool $enable Enable caching
943      */
944     function enable_cache($enable = true)
945     {
946         $this->cache = (bool) $enable;
947     }
948
b1a6a5 949
fd9ef2 950     /**
T 951      * Set the length of time (in seconds) that the contents of a feed
952      * will be cached.
953      *
954      * @access public
955      * @param int $seconds The feed content cache duration.
956      */
957     function set_cache_duration($seconds = 3600)
958     {
959         $this->cache_duration = (int) $seconds;
960     }
b1a6a5 961
fd9ef2 962
T 963     /**
964      * Set the length of time (in seconds) that the autodiscovered feed
965      * URL will be cached.
966      *
967      * @access public
968      * @param int $seconds The autodiscovered feed URL cache duration.
969      */
970     function set_autodiscovery_cache_duration($seconds = 604800)
971     {
972         $this->autodiscovery_cache_duration = (int) $seconds;
973     }
974
b1a6a5 975
fd9ef2 976     /**
T 977      * Set the file system location where the cached files should be stored.
978      *
979      * @access public
980      * @param string $location The file system location.
981      */
982     function set_cache_location($location = './cache')
983     {
984         $this->cache_location = (string) $location;
985     }
986
b1a6a5 987
fd9ef2 988     /**
T 989      * Determines whether feed items should be sorted into reverse chronological order.
990      *
991      * @access public
992      * @param bool $enable Sort as reverse chronological order.
993      */
994     function enable_order_by_date($enable = true)
995     {
996         $this->order_by_date = (bool) $enable;
997     }
b1a6a5 998
fd9ef2 999
T 1000     /**
1001      * Allows you to override the character encoding reported by the feed.
1002      *
1003      * @access public
1004      * @param string $encoding Character encoding.
1005      */
1006     function set_input_encoding($encoding = false)
1007     {
1008         if ($encoding)
1009         {
1010             $this->input_encoding = (string) $encoding;
1011         }
1012         else
1013         {
1014             $this->input_encoding = false;
1015         }
1016     }
b1a6a5 1017
fd9ef2 1018
T 1019     /**
1020      * Set how much feed autodiscovery to do
1021      *
1022      * @access public
1023      * @see SIMPLEPIE_LOCATOR_NONE
1024      * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
1025      * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
1026      * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
1027      * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
1028      * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
1029      * @see SIMPLEPIE_LOCATOR_ALL
1030      * @param int $level Feed Autodiscovery Level (level can be a
1031      * combination of the above constants, see bitwise OR operator)
1032      */
1033     function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
1034     {
1035         $this->autodiscovery = (int) $level;
1036     }
1037
b1a6a5 1038
fd9ef2 1039     /**
T 1040      * Allows you to change which class SimplePie uses for caching.
1041      * Useful when you are overloading or extending SimplePie's default classes.
1042      *
1043      * @access public
1044      * @param string $class Name of custom class.
1045      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1046      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1047      */
1048     function set_cache_class($class = 'SimplePie_Cache')
1049     {
1050         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
1051         {
1052             $this->cache_class = $class;
1053             return true;
1054         }
1055         return false;
1056     }
b1a6a5 1057
fd9ef2 1058
T 1059     /**
1060      * Allows you to change which class SimplePie uses for auto-discovery.
1061      * Useful when you are overloading or extending SimplePie's default classes.
1062      *
1063      * @access public
1064      * @param string $class Name of custom class.
1065      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1066      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1067      */
1068     function set_locator_class($class = 'SimplePie_Locator')
1069     {
1070         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
1071         {
1072             $this->locator_class = $class;
1073             return true;
1074         }
1075         return false;
1076     }
1077
b1a6a5 1078
fd9ef2 1079     /**
T 1080      * Allows you to change which class SimplePie uses for XML parsing.
1081      * Useful when you are overloading or extending SimplePie's default classes.
1082      *
1083      * @access public
1084      * @param string $class Name of custom class.
1085      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1086      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1087      */
1088     function set_parser_class($class = 'SimplePie_Parser')
1089     {
1090         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
1091         {
1092             $this->parser_class = $class;
1093             return true;
1094         }
1095         return false;
1096     }
b1a6a5 1097
fd9ef2 1098
T 1099     /**
1100      * Allows you to change which class SimplePie uses for remote file fetching.
1101      * Useful when you are overloading or extending SimplePie's default classes.
1102      *
1103      * @access public
1104      * @param string $class Name of custom class.
1105      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1106      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1107      */
1108     function set_file_class($class = 'SimplePie_File')
1109     {
1110         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
1111         {
1112             $this->file_class = $class;
1113             return true;
1114         }
1115         return false;
1116     }
1117
b1a6a5 1118
fd9ef2 1119     /**
T 1120      * Allows you to change which class SimplePie uses for data sanitization.
1121      * Useful when you are overloading or extending SimplePie's default classes.
1122      *
1123      * @access public
1124      * @param string $class Name of custom class.
1125      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1126      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1127      */
1128     function set_sanitize_class($class = 'SimplePie_Sanitize')
1129     {
1130         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
1131         {
f64c86 1132             $this->sanitize = new $class;
fd9ef2 1133             return true;
T 1134         }
1135         return false;
1136     }
b1a6a5 1137
fd9ef2 1138
T 1139     /**
1140      * Allows you to change which class SimplePie uses for handling feed items.
1141      * Useful when you are overloading or extending SimplePie's default classes.
1142      *
1143      * @access public
1144      * @param string $class Name of custom class.
1145      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1146      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1147      */
1148     function set_item_class($class = 'SimplePie_Item')
1149     {
1150         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
1151         {
1152             $this->item_class = $class;
1153             return true;
1154         }
1155         return false;
1156     }
1157
b1a6a5 1158
fd9ef2 1159     /**
T 1160      * Allows you to change which class SimplePie uses for handling author data.
1161      * Useful when you are overloading or extending SimplePie's default classes.
1162      *
1163      * @access public
1164      * @param string $class Name of custom class.
1165      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1166      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1167      */
1168     function set_author_class($class = 'SimplePie_Author')
1169     {
1170         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
1171         {
1172             $this->author_class = $class;
1173             return true;
1174         }
1175         return false;
1176     }
b1a6a5 1177
fd9ef2 1178
T 1179     /**
1180      * Allows you to change which class SimplePie uses for handling category data.
1181      * Useful when you are overloading or extending SimplePie's default classes.
1182      *
1183      * @access public
1184      * @param string $class Name of custom class.
1185      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1186      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1187      */
1188     function set_category_class($class = 'SimplePie_Category')
1189     {
1190         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
1191         {
1192             $this->category_class = $class;
1193             return true;
1194         }
1195         return false;
1196     }
1197
b1a6a5 1198
fd9ef2 1199     /**
T 1200      * Allows you to change which class SimplePie uses for feed enclosures.
1201      * Useful when you are overloading or extending SimplePie's default classes.
1202      *
1203      * @access public
1204      * @param string $class Name of custom class.
1205      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1206      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1207      */
1208     function set_enclosure_class($class = 'SimplePie_Enclosure')
1209     {
1210         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
1211         {
1212             $this->enclosure_class = $class;
1213             return true;
1214         }
1215         return false;
1216     }
b1a6a5 1217
fd9ef2 1218
T 1219     /**
1220      * Allows you to change which class SimplePie uses for <media:text> captions
1221      * Useful when you are overloading or extending SimplePie's default classes.
1222      *
1223      * @access public
1224      * @param string $class Name of custom class.
1225      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1226      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1227      */
1228     function set_caption_class($class = 'SimplePie_Caption')
1229     {
1230         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
1231         {
1232             $this->caption_class = $class;
1233             return true;
1234         }
1235         return false;
1236     }
1237
b1a6a5 1238
fd9ef2 1239     /**
T 1240      * Allows you to change which class SimplePie uses for <media:copyright>
1241      * Useful when you are overloading or extending SimplePie's default classes.
1242      *
1243      * @access public
1244      * @param string $class Name of custom class.
1245      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1246      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1247      */
1248     function set_copyright_class($class = 'SimplePie_Copyright')
1249     {
1250         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
1251         {
1252             $this->copyright_class = $class;
1253             return true;
1254         }
1255         return false;
1256     }
b1a6a5 1257
fd9ef2 1258
T 1259     /**
1260      * Allows you to change which class SimplePie uses for <media:credit>
1261      * Useful when you are overloading or extending SimplePie's default classes.
1262      *
1263      * @access public
1264      * @param string $class Name of custom class.
1265      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1266      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1267      */
1268     function set_credit_class($class = 'SimplePie_Credit')
1269     {
1270         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
1271         {
1272             $this->credit_class = $class;
1273             return true;
1274         }
1275         return false;
1276     }
1277
b1a6a5 1278
fd9ef2 1279     /**
T 1280      * Allows you to change which class SimplePie uses for <media:rating>
1281      * Useful when you are overloading or extending SimplePie's default classes.
1282      *
1283      * @access public
1284      * @param string $class Name of custom class.
1285      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1286      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1287      */
1288     function set_rating_class($class = 'SimplePie_Rating')
1289     {
1290         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
1291         {
1292             $this->rating_class = $class;
1293             return true;
1294         }
1295         return false;
1296     }
b1a6a5 1297
fd9ef2 1298
T 1299     /**
1300      * Allows you to change which class SimplePie uses for <media:restriction>
1301      * Useful when you are overloading or extending SimplePie's default classes.
1302      *
1303      * @access public
1304      * @param string $class Name of custom class.
1305      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1306      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1307      */
1308     function set_restriction_class($class = 'SimplePie_Restriction')
1309     {
1310         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
1311         {
1312             $this->restriction_class = $class;
1313             return true;
1314         }
1315         return false;
1316     }
1317
b1a6a5 1318
fd9ef2 1319     /**
T 1320      * Allows you to change which class SimplePie uses for content-type sniffing.
1321      * Useful when you are overloading or extending SimplePie's default classes.
1322      *
1323      * @access public
1324      * @param string $class Name of custom class.
1325      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1326      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1327      */
1328     function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1329     {
1330         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
1331         {
1332             $this->content_type_sniffer_class = $class;
1333             return true;
1334         }
1335         return false;
1336     }
b1a6a5 1337
fd9ef2 1338
T 1339     /**
1340      * Allows you to change which class SimplePie uses item sources.
1341      * Useful when you are overloading or extending SimplePie's default classes.
1342      *
1343      * @access public
1344      * @param string $class Name of custom class.
1345      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1346      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1347      */
1348     function set_source_class($class = 'SimplePie_Source')
1349     {
1350         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
1351         {
1352             $this->source_class = $class;
1353             return true;
1354         }
1355         return false;
1356     }
1357
b1a6a5 1358
fd9ef2 1359     /**
T 1360      * Allows you to override the default user agent string.
1361      *
1362      * @access public
1363      * @param string $ua New user agent string.
1364      */
1365     function set_useragent($ua = SIMPLEPIE_USERAGENT)
1366     {
1367         $this->useragent = (string) $ua;
1368     }
b1a6a5 1369
fd9ef2 1370
T 1371     /**
1372      * Set callback function to create cache filename with
1373      *
1374      * @access public
1375      * @param mixed $function Callback function
1376      */
1377     function set_cache_name_function($function = 'md5')
1378     {
1379         if (is_callable($function))
1380         {
1381             $this->cache_name_function = $function;
1382         }
1383     }
b1a6a5 1384
fd9ef2 1385
T 1386     /**
1387      * Set javascript query string parameter
1388      *
1389      * @access public
1390      * @param mixed $get Javascript query string parameter
1391      */
1392     function set_javascript($get = 'js')
1393     {
1394         if ($get)
1395         {
1396             $this->javascript = (string) $get;
1397         }
1398         else
1399         {
1400             $this->javascript = false;
1401         }
1402     }
b1a6a5 1403
fd9ef2 1404
T 1405     /**
1406      * Set options to make SP as fast as possible.  Forgoes a
1407      * substantial amount of data sanitization in favor of speed.
1408      *
1409      * @access public
1410      * @param bool $set Whether to set them or not
1411      */
1412     function set_stupidly_fast($set = false)
1413     {
1414         if ($set)
1415         {
1416             $this->enable_order_by_date(false);
1417             $this->remove_div(false);
1418             $this->strip_comments(false);
1419             $this->strip_htmltags(false);
1420             $this->strip_attributes(false);
1421             $this->set_image_handler(false);
1422         }
1423     }
b1a6a5 1424
fd9ef2 1425
T 1426     /**
1427      * Set maximum number of feeds to check with autodiscovery
1428      *
1429      * @access public
1430      * @param int $max Maximum number of feeds to check
1431      */
1432     function set_max_checked_feeds($max = 10)
1433     {
1434         $this->max_checked_feeds = (int) $max;
1435     }
1436
1437     function remove_div($enable = true)
1438     {
1439         $this->sanitize->remove_div($enable);
1440     }
1441
1442     function strip_htmltags($tags = '', $encode = null)
1443     {
1444         if ($tags === '')
1445         {
1446             $tags = $this->strip_htmltags;
1447         }
1448         $this->sanitize->strip_htmltags($tags);
1449         if ($encode !== null)
1450         {
1451             $this->sanitize->encode_instead_of_strip($tags);
1452         }
1453     }
1454
1455     function encode_instead_of_strip($enable = true)
1456     {
1457         $this->sanitize->encode_instead_of_strip($enable);
1458     }
1459
1460     function strip_attributes($attribs = '')
1461     {
1462         if ($attribs === '')
1463         {
1464             $attribs = $this->strip_attributes;
1465         }
1466         $this->sanitize->strip_attributes($attribs);
1467     }
1468
1469     function set_output_encoding($encoding = 'UTF-8')
1470     {
1471         $this->sanitize->set_output_encoding($encoding);
1472     }
1473
1474     function strip_comments($strip = false)
1475     {
1476         $this->sanitize->strip_comments($strip);
1477     }
1478
b1a6a5 1479
fd9ef2 1480     /**
T 1481      * Set element/attribute key/value pairs of HTML attributes
1482      * containing URLs that need to be resolved relative to the feed
1483      *
1484      * @access public
1485      * @since 1.0
1486      * @param array $element_attribute Element/attribute key/value pairs
1487      */
1488     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'))
1489     {
1490         $this->sanitize->set_url_replacements($element_attribute);
1491     }
b1a6a5 1492
fd9ef2 1493
T 1494     /**
1495      * Set the handler to enable the display of cached favicons.
1496      *
1497      * @access public
1498      * @param str $page Web-accessible path to the handler_favicon.php file.
1499      * @param str $qs The query string that the value should be passed to.
1500      */
1501     function set_favicon_handler($page = false, $qs = 'i')
1502     {
1503         if ($page !== false)
1504         {
1505             $this->favicon_handler = $page . '?' . $qs . '=';
1506         }
1507         else
1508         {
1509             $this->favicon_handler = '';
1510         }
1511     }
1512
b1a6a5 1513
fd9ef2 1514     /**
T 1515      * Set the handler to enable the display of cached images.
1516      *
1517      * @access public
1518      * @param str $page Web-accessible path to the handler_image.php file.
1519      * @param str $qs The query string that the value should be passed to.
1520      */
1521     function set_image_handler($page = false, $qs = 'i')
1522     {
1523         if ($page !== false)
1524         {
1525             $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1526         }
1527         else
1528         {
1529             $this->image_handler = '';
1530         }
1531     }
b1a6a5 1532
fd9ef2 1533
T 1534     /**
1535      * Set the limit for items returned per-feed with multifeeds.
1536      *
1537      * @access public
1538      * @param integer $limit The maximum number of items to return.
1539      */
1540     function set_item_limit($limit = 0)
1541     {
1542         $this->item_limit = (int) $limit;
1543     }
1544
1545     function init()
1546     {
1547         // Check absolute bare minimum requirements.
1548         if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
1549         {
1550             return false;
1551         }
1552         // 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.
1553         elseif (!extension_loaded('xmlreader'))
1554         {
1555             static $xml_is_sane = null;
1556             if ($xml_is_sane === null)
1557             {
1558                 $parser_check = xml_parser_create();
1559                 xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
1560                 xml_parser_free($parser_check);
1561                 $xml_is_sane = isset($values[0]['value']);
1562             }
1563             if (!$xml_is_sane)
1564             {
1565                 return false;
1566             }
1567         }
1568
1569         if (isset($_GET[$this->javascript]))
1570         {
1571             SimplePie_Misc::output_javascript();
1572             exit;
1573         }
1574
1575         // Pass whatever was set with config options over to the sanitizer.
1576         $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
1577         $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
1578
1579         if ($this->feed_url !== null || $this->raw_data !== null)
1580         {
1581             $this->data = array();
1582             $this->multifeed_objects = array();
1583             $cache = false;
1584
1585             if ($this->feed_url !== null)
1586             {
1587                 $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
1588                 // Decide whether to enable caching
1589                 if ($this->cache && $parsed_feed_url['scheme'] !== '')
1590                 {
1591                     $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
1592                 }
1593                 // If it's enabled and we don't want an XML dump, use the cache
1594                 if ($cache && !$this->xml_dump)
1595                 {
1596                     // Load the Cache
1597                     $this->data = $cache->load();
1598                     if (!empty($this->data))
1599                     {
1600                         // If the cache is for an outdated build of SimplePie
1601                         if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
1602                         {
1603                             $cache->unlink();
1604                             $this->data = array();
1605                         }
1606                         // If we've hit a collision just rerun it with caching disabled
1607                         elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
1608                         {
1609                             $cache = false;
1610                             $this->data = array();
1611                         }
1612                         // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1613                         elseif (isset($this->data['feed_url']))
1614                         {
1615                             // If the autodiscovery cache is still valid use it.
1616                             if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1617                             {
1618                                 // Do not need to do feed autodiscovery yet.
1619                                 if ($this->data['feed_url'] === $this->data['url'])
1620                                 {
1621                                     $cache->unlink();
1622                                     $this->data = array();
1623                                 }
1624                                 else
1625                                 {
1626                                     $this->set_feed_url($this->data['feed_url']);
1627                                     return $this->init();
1628                                 }
1629                             }
1630                         }
1631                         // Check if the cache has been updated
1632                         elseif ($cache->mtime() + $this->cache_duration < time())
1633                         {
1634                             // If we have last-modified and/or etag set
1635                             if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1636                             {
1637                                 $headers = array();
1638                                 if (isset($this->data['headers']['last-modified']))
1639                                 {
1640                                     $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1641                                 }
1642                                 if (isset($this->data['headers']['etag']))
1643                                 {
1644                                     $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
1645                                 }
f64c86 1646                                 $file = new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
fd9ef2 1647                                 if ($file->success)
T 1648                                 {
1649                                     if ($file->status_code === 304)
1650                                     {
1651                                         $cache->touch();
1652                                         return true;
1653                                     }
1654                                     else
1655                                     {
1656                                         $headers = $file->headers;
1657                                     }
1658                                 }
1659                                 else
1660                                 {
1661                                     unset($file);
1662                                 }
1663                             }
1664                         }
1665                         // If the cache is still valid, just return true
1666                         else
1667                         {
1668                             return true;
1669                         }
1670                     }
1671                     // If the cache is empty, delete it
1672                     else
1673                     {
1674                         $cache->unlink();
1675                         $this->data = array();
1676                     }
1677                 }
1678                 // 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.
1679                 if (!isset($file))
1680                 {
1681                     if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
1682                     {
1683                         $file =& $this->file;
1684                     }
1685                     else
1686                     {
f64c86 1687                         $file = new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
fd9ef2 1688                     }
T 1689                 }
1690                 // If the file connection has an error, set SimplePie::error to that and quit
1691                 if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
1692                 {
1693                     $this->error = $file->error;
1694                     if (!empty($this->data))
1695                     {
1696                         return true;
1697                     }
1698                     else
1699                     {
1700                         return false;
1701                     }
1702                 }
1703
1704                 if (!$this->force_feed)
1705                 {
1706                     // Check if the supplied URL is a feed, if it isn't, look for it.
f64c86 1707                     $locate = new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
fd9ef2 1708                     if (!$locate->is_feed($file))
T 1709                     {
1710                         // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1711                         unset($file);
1712                         if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
1713                         {
1714                             if ($cache)
1715                             {
1716                                 $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1717                                 if (!$cache->save($this))
1718                                 {
1719                                     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);
1720                                 }
1721                                 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
1722                             }
1723                             $this->feed_url = $file->url;
1724                         }
1725                         else
1726                         {
1727                             $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.";
1728                             SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1729                             return false;
1730                         }
1731                     }
1732                     $locate = null;
1733                 }
1734
1735                 $headers = $file->headers;
1736                 $data = $file->body;
f64c86 1737                 $sniffer = new $this->content_type_sniffer_class($file);
fd9ef2 1738                 $sniffed = $sniffer->get_type();
T 1739             }
1740             else
1741             {
1742                 $data = $this->raw_data;
1743             }
1744
1745             // Set up array of possible encodings
1746             $encodings = array();
1747
1748             // First check to see if input has been overridden.
1749             if ($this->input_encoding !== false)
1750             {
1751                 $encodings[] = $this->input_encoding;
1752             }
1753
1754             $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1755             $text_types = array('text/xml', 'text/xml-external-parsed-entity');
1756
1757             // RFC 3023 (only applies to sniffed content)
1758             if (isset($sniffed))
1759             {
1760                 if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1761                 {
1762                     if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1763                     {
1764                         $encodings[] = strtoupper($charset[1]);
1765                     }
1766                     $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1767                     $encodings[] = 'UTF-8';
1768                 }
1769                 elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1770                 {
1771                     if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1772                     {
1773                         $encodings[] = $charset[1];
1774                     }
1775                     $encodings[] = 'US-ASCII';
1776                 }
1777                 // Text MIME-type default
1778                 elseif (substr($sniffed, 0, 5) === 'text/')
1779                 {
1780                     $encodings[] = 'US-ASCII';
1781                 }
1782             }
1783
1784             // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1785             $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1786             $encodings[] = 'UTF-8';
1787             $encodings[] = 'ISO-8859-1';
1788
1789             // There's no point in trying an encoding twice
1790             $encodings = array_unique($encodings);
1791
1792             // If we want the XML, just output that with the most likely encoding and quit
1793             if ($this->xml_dump)
1794             {
1795                 header('Content-type: text/xml; charset=' . $encodings[0]);
1796                 echo $data;
1797                 exit;
1798             }
1799
1800             // Loop through each possible encoding, till we return something, or run out of possibilities
1801             foreach ($encodings as $encoding)
1802             {
1803                 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1804                 if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
1805                 {
1806                     // Create new parser
f64c86 1807                     $parser = new $this->parser_class();
fd9ef2 1808
T 1809                     // If it's parsed fine
1810                     if ($parser->parse($utf8_data, 'UTF-8'))
1811                     {
1812                         $this->data = $parser->get_data();
1813                         if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
1814                         {
1815                             if (isset($headers))
1816                             {
1817                                 $this->data['headers'] = $headers;
1818                             }
1819                             $this->data['build'] = SIMPLEPIE_BUILD;
1820
1821                             // Cache the file if caching is enabled
1822                             if ($cache && !$cache->save($this))
1823                             {
1824                                 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);
1825                             }
1826                             return true;
1827                         }
1828                         else
1829                         {
1830                             $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
1831                             SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1832                             return false;
1833                         }
1834                     }
1835                 }
1836             }
1837             if (isset($parser))
1838             {
1839                 // We have an error, just set SimplePie_Misc::error to it and quit
1840                 $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());
1841             }
1842             else
1843             {
1844                 $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.';
1845             }
1846             SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1847             return false;
1848         }
1849         elseif (!empty($this->multifeed_url))
1850         {
1851             $i = 0;
1852             $success = 0;
1853             $this->multifeed_objects = array();
1854             foreach ($this->multifeed_url as $url)
1855             {
1856                 if (SIMPLEPIE_PHP5)
1857                 {
1858                     // This keyword needs to defy coding standards for PHP4 compatibility
1859                     $this->multifeed_objects[$i] = clone($this);
1860                 }
1861                 else
1862                 {
1863                     $this->multifeed_objects[$i] = $this;
1864                 }
1865                 $this->multifeed_objects[$i]->set_feed_url($url);
1866                 $success |= $this->multifeed_objects[$i]->init();
1867                 $i++;
1868             }
1869             return (bool) $success;
1870         }
1871         else
1872         {
1873             return false;
1874         }
1875     }
1876
b1a6a5 1877
fd9ef2 1878     /**
T 1879      * Return the error message for the occured error
1880      *
1881      * @access public
1882      * @return string Error message
1883      */
1884     function error()
1885     {
1886         return $this->error;
1887     }
1888
1889     function get_encoding()
1890     {
1891         return $this->sanitize->output_encoding;
1892     }
1893
1894     function handle_content_type($mime = 'text/html')
1895     {
1896         if (!headers_sent())
1897         {
1898             $header = "Content-type: $mime;";
1899             if ($this->get_encoding())
1900             {
1901                 $header .= ' charset=' . $this->get_encoding();
1902             }
1903             else
1904             {
1905                 $header .= ' charset=UTF-8';
1906             }
1907             header($header);
1908         }
1909     }
1910
1911     function get_type()
1912     {
1913         if (!isset($this->data['type']))
1914         {
1915             $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1916             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1917             {
1918                 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1919             }
1920             elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1921             {
1922                 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1923             }
1924             elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1925             {
1926                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
b1a6a5 1927                     || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
MC 1928                     || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1929                     || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
fd9ef2 1930                 {
T 1931                     $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1932                 }
1933                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
b1a6a5 1934                     || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
MC 1935                     || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1936                     || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
fd9ef2 1937                 {
T 1938                     $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1939                 }
1940             }
1941             elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
1942             {
1943                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1944                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1945                 {
1946                     switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1947                     {
b1a6a5 1948                     case '0.91':
MC 1949                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1950                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1951                         {
1952                             switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
fd9ef2 1953                             {
b1a6a5 1954                             case '0':
MC 1955                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1956                                 break;
fd9ef2 1957
b1a6a5 1958                             case '24':
MC 1959                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1960                                 break;
fd9ef2 1961                             }
b1a6a5 1962                         }
MC 1963                         break;
fd9ef2 1964
b1a6a5 1965                     case '0.92':
MC 1966                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1967                         break;
fd9ef2 1968
b1a6a5 1969                     case '0.93':
MC 1970                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1971                         break;
fd9ef2 1972
b1a6a5 1973                     case '0.94':
MC 1974                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1975                         break;
fd9ef2 1976
b1a6a5 1977                     case '2.0':
MC 1978                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1979                         break;
fd9ef2 1980                     }
T 1981                 }
1982             }
1983             else
1984             {
1985                 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1986             }
1987         }
1988         return $this->data['type'];
1989     }
b1a6a5 1990
fd9ef2 1991
T 1992     /**
1993      * Returns the URL for the favicon of the feed's website.
1994      *
1995      * @todo Cache atom:icon
1996      * @access public
1997      * @since 1.0
1998      */
1999     function get_favicon()
2000     {
2001         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2002         {
2003             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2004         }
2005         elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
2006         {
2007             $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
2008
2009             if ($this->cache && $this->favicon_handler)
2010             {
2011                 $favicon_filename = call_user_func($this->cache_name_function, $favicon);
2012                 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
2013
2014                 if ($cache->load())
2015                 {
2016                     return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
2017                 }
2018                 else
2019                 {
f64c86 2020                     $file = new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
fd9ef2 2021
T 2022                     if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)) && strlen($file->body) > 0)
2023                     {
f64c86 2024                         $sniffer = new $this->content_type_sniffer_class($file);
fd9ef2 2025                         if (substr($sniffer->get_type(), 0, 6) === 'image/')
T 2026                         {
2027                             if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
2028                             {
2029                                 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
2030                             }
2031                             else
2032                             {
2033                                 trigger_error("$cache->name is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
2034                                 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
2035                             }
2036                         }
2037                         // not an image
2038                         else
2039                         {
2040                             return false;
2041                         }
2042                     }
2043                 }
2044             }
2045             else
2046             {
2047                 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
2048             }
2049         }
2050         return false;
2051     }
b1a6a5 2052
fd9ef2 2053
T 2054     /**
2055      * @todo If we have a perm redirect we should return the new URL
2056      * @todo When we make the above change, let's support <itunes:new-feed-url> as well
2057      * @todo Also, |atom:link|@rel=self
2058      */
2059     function subscribe_url()
2060     {
2061         if ($this->feed_url !== null)
2062         {
2063             return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
2064         }
2065         else
2066         {
2067             return null;
2068         }
2069     }
2070
2071     function subscribe_feed()
2072     {
2073         if ($this->feed_url !== null)
2074         {
2075             return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2076         }
2077         else
2078         {
2079             return null;
2080         }
2081     }
2082
2083     function subscribe_outlook()
2084     {
2085         if ($this->feed_url !== null)
2086         {
2087             return $this->sanitize('outlook' . SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2088         }
2089         else
2090         {
2091             return null;
2092         }
2093     }
2094
2095     function subscribe_podcast()
2096     {
2097         if ($this->feed_url !== null)
2098         {
2099             return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
2100         }
2101         else
2102         {
2103             return null;
2104         }
2105     }
2106
2107     function subscribe_itunes()
2108     {
2109         if ($this->feed_url !== null)
2110         {
2111             return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
2112         }
2113         else
2114         {
2115             return null;
2116         }
2117     }
b1a6a5 2118
fd9ef2 2119
T 2120     /**
2121      * Creates the subscribe_* methods' return data
2122      *
2123      * @access private
2124      * @param string $feed_url String to prefix to the feed URL
2125      * @param string $site_url String to prefix to the site URL (and
2126      * suffix to the feed URL)
2127      * @return mixed URL if feed exists, false otherwise
2128      */
2129     function subscribe_service($feed_url, $site_url = null)
2130     {
2131         if ($this->subscribe_url())
2132         {
2133             $return = $feed_url . rawurlencode($this->feed_url);
2134             if ($site_url !== null && $this->get_link() !== null)
2135             {
2136                 $return .= $site_url . rawurlencode($this->get_link());
2137             }
2138             return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
2139         }
2140         else
2141         {
2142             return null;
2143         }
2144     }
2145
2146     function subscribe_aol()
2147     {
2148         return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
2149     }
2150
2151     function subscribe_bloglines()
2152     {
2153         return $this->subscribe_service('http://www.bloglines.com/sub/');
2154     }
2155
2156     function subscribe_eskobo()
2157     {
2158         return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
2159     }
2160
2161     function subscribe_feedfeeds()
2162     {
2163         return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
2164     }
2165
2166     function subscribe_feedster()
2167     {
2168         return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
2169     }
2170
2171     function subscribe_google()
2172     {
2173         return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
2174     }
2175
2176     function subscribe_gritwire()
2177     {
2178         return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
2179     }
2180
2181     function subscribe_msn()
2182     {
2183         return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
2184     }
2185
2186     function subscribe_netvibes()
2187     {
2188         return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
2189     }
2190
2191     function subscribe_newsburst()
2192     {
2193         return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
2194     }
2195
2196     function subscribe_newsgator()
2197     {
2198         return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
2199     }
2200
2201     function subscribe_odeo()
2202     {
2203         return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
2204     }
2205
2206     function subscribe_podnova()
2207     {
2208         return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
2209     }
2210
2211     function subscribe_rojo()
2212     {
2213         return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
2214     }
2215
2216     function subscribe_yahoo()
2217     {
2218         return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
2219     }
2220
2221     function get_feed_tags($namespace, $tag)
2222     {
2223         $type = $this->get_type();
2224         if ($type & SIMPLEPIE_TYPE_ATOM_10)
2225         {
2226             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
2227             {
2228                 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
2229             }
2230         }
2231         if ($type & SIMPLEPIE_TYPE_ATOM_03)
2232         {
2233             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
2234             {
2235                 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
2236             }
2237         }
2238         if ($type & SIMPLEPIE_TYPE_RSS_RDF)
2239         {
2240             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
2241             {
2242                 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
2243             }
2244         }
2245         if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2246         {
2247             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
2248             {
2249                 return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
2250             }
2251         }
2252         return null;
2253     }
2254
2255     function get_channel_tags($namespace, $tag)
2256     {
2257         $type = $this->get_type();
2258         if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
2259         {
2260             if ($return = $this->get_feed_tags($namespace, $tag))
2261             {
2262                 return $return;
2263             }
2264         }
2265         if ($type & SIMPLEPIE_TYPE_RSS_10)
2266         {
2267             if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
2268             {
2269                 if (isset($channel[0]['child'][$namespace][$tag]))
2270                 {
2271                     return $channel[0]['child'][$namespace][$tag];
2272                 }
2273             }
2274         }
2275         if ($type & SIMPLEPIE_TYPE_RSS_090)
2276         {
2277             if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
2278             {
2279                 if (isset($channel[0]['child'][$namespace][$tag]))
2280                 {
2281                     return $channel[0]['child'][$namespace][$tag];
2282                 }
2283             }
2284         }
2285         if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2286         {
2287             if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
2288             {
2289                 if (isset($channel[0]['child'][$namespace][$tag]))
2290                 {
2291                     return $channel[0]['child'][$namespace][$tag];
2292                 }
2293             }
2294         }
2295         return null;
2296     }
2297
2298     function get_image_tags($namespace, $tag)
2299     {
2300         $type = $this->get_type();
2301         if ($type & SIMPLEPIE_TYPE_RSS_10)
2302         {
2303             if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
2304             {
2305                 if (isset($image[0]['child'][$namespace][$tag]))
2306                 {
2307                     return $image[0]['child'][$namespace][$tag];
2308                 }
2309             }
2310         }
2311         if ($type & SIMPLEPIE_TYPE_RSS_090)
2312         {
2313             if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2314             {
2315                 if (isset($image[0]['child'][$namespace][$tag]))
2316                 {
2317                     return $image[0]['child'][$namespace][$tag];
2318                 }
2319             }
2320         }
2321         if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2322         {
2323             if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
2324             {
2325                 if (isset($image[0]['child'][$namespace][$tag]))
2326                 {
2327                     return $image[0]['child'][$namespace][$tag];
2328                 }
2329             }
2330         }
2331         return null;
2332     }
2333
2334     function get_base($element = array())
2335     {
2336         if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2337         {
2338             return $element['xml_base'];
2339         }
2340         elseif ($this->get_link() !== null)
2341         {
2342             return $this->get_link();
2343         }
2344         else
2345         {
2346             return $this->subscribe_url();
2347         }
2348     }
2349
2350     function sanitize($data, $type, $base = '')
2351     {
2352         return $this->sanitize->sanitize($data, $type, $base);
2353     }
2354
2355     function get_title()
2356     {
2357         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2358         {
2359             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2360         }
2361         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2362         {
2363             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2364         }
2365         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2366         {
2367             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2368         }
2369         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2370         {
2371             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2372         }
2373         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2374         {
2375             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2376         }
2377         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2378         {
2379             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2380         }
2381         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2382         {
2383             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2384         }
2385         else
2386         {
2387             return null;
2388         }
2389     }
2390
2391     function get_category($key = 0)
2392     {
2393         $categories = $this->get_categories();
2394         if (isset($categories[$key]))
2395         {
2396             return $categories[$key];
2397         }
2398         else
2399         {
2400             return null;
2401         }
2402     }
2403
2404     function get_categories()
2405     {
2406         $categories = array();
2407
2408         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2409         {
2410             $term = null;
2411             $scheme = null;
2412             $label = null;
2413             if (isset($category['attribs']['']['term']))
2414             {
2415                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2416             }
2417             if (isset($category['attribs']['']['scheme']))
2418             {
2419                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2420             }
2421             if (isset($category['attribs']['']['label']))
2422             {
2423                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2424             }
f64c86 2425             $categories[] = new $this->category_class($term, $scheme, $label);
fd9ef2 2426         }
T 2427         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
2428         {
2429             // This is really the label, but keep this as the term also for BC.
2430             // Label will also work on retrieving because that falls back to term.
2431             $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2432             if (isset($category['attribs']['']['domain']))
2433             {
2434                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
2435             }
2436             else
2437             {
2438                 $scheme = null;
2439             }
f64c86 2440             $categories[] = new $this->category_class($term, $scheme, null);
fd9ef2 2441         }
T 2442         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2443         {
f64c86 2444             $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 2445         }
T 2446         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2447         {
f64c86 2448             $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 2449         }
T 2450
2451         if (!empty($categories))
2452         {
2453             return SimplePie_Misc::array_unique($categories);
2454         }
2455         else
2456         {
2457             return null;
2458         }
2459     }
2460
2461     function get_author($key = 0)
2462     {
2463         $authors = $this->get_authors();
2464         if (isset($authors[$key]))
2465         {
2466             return $authors[$key];
2467         }
2468         else
2469         {
2470             return null;
2471         }
2472     }
2473
2474     function get_authors()
2475     {
2476         $authors = array();
2477         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2478         {
2479             $name = null;
2480             $uri = null;
2481             $email = null;
2482             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2483             {
2484                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2485             }
2486             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2487             {
2488                 $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]));
2489             }
2490             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2491             {
2492                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2493             }
2494             if ($name !== null || $email !== null || $uri !== null)
2495             {
f64c86 2496                 $authors[] = new $this->author_class($name, $uri, $email);
fd9ef2 2497             }
T 2498         }
2499         if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2500         {
2501             $name = null;
2502             $url = null;
2503             $email = null;
2504             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2505             {
2506                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2507             }
2508             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2509             {
2510                 $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]));
2511             }
2512             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2513             {
2514                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2515             }
2516             if ($name !== null || $email !== null || $url !== null)
2517             {
f64c86 2518                 $authors[] = new $this->author_class($name, $url, $email);
fd9ef2 2519             }
T 2520         }
2521         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2522         {
f64c86 2523             $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 2524         }
T 2525         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2526         {
f64c86 2527             $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 2528         }
T 2529         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2530         {
f64c86 2531             $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 2532         }
T 2533
2534         if (!empty($authors))
2535         {
2536             return SimplePie_Misc::array_unique($authors);
2537         }
2538         else
2539         {
2540             return null;
2541         }
2542     }
2543
2544     function get_contributor($key = 0)
2545     {
2546         $contributors = $this->get_contributors();
2547         if (isset($contributors[$key]))
2548         {
2549             return $contributors[$key];
2550         }
2551         else
2552         {
2553             return null;
2554         }
2555     }
2556
2557     function get_contributors()
2558     {
2559         $contributors = array();
2560         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2561         {
2562             $name = null;
2563             $uri = null;
2564             $email = null;
2565             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2566             {
2567                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2568             }
2569             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2570             {
2571                 $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]));
2572             }
2573             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2574             {
2575                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2576             }
2577             if ($name !== null || $email !== null || $uri !== null)
2578             {
f64c86 2579                 $contributors[] = new $this->author_class($name, $uri, $email);
fd9ef2 2580             }
T 2581         }
2582         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2583         {
2584             $name = null;
2585             $url = null;
2586             $email = null;
2587             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2588             {
2589                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2590             }
2591             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2592             {
2593                 $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]));
2594             }
2595             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2596             {
2597                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2598             }
2599             if ($name !== null || $email !== null || $url !== null)
2600             {
f64c86 2601                 $contributors[] = new $this->author_class($name, $url, $email);
fd9ef2 2602             }
T 2603         }
2604
2605         if (!empty($contributors))
2606         {
2607             return SimplePie_Misc::array_unique($contributors);
2608         }
2609         else
2610         {
2611             return null;
2612         }
2613     }
2614
2615     function get_link($key = 0, $rel = 'alternate')
2616     {
2617         $links = $this->get_links($rel);
2618         if (isset($links[$key]))
2619         {
2620             return $links[$key];
2621         }
2622         else
2623         {
2624             return null;
2625         }
2626     }
2627
b1a6a5 2628
fd9ef2 2629     /**
T 2630      * Added for parity between the parent-level and the item/entry-level.
2631      */
2632     function get_permalink()
2633     {
2634         return $this->get_link(0);
2635     }
2636
2637     function get_links($rel = 'alternate')
2638     {
2639         if (!isset($this->data['links']))
2640         {
2641             $this->data['links'] = array();
2642             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2643             {
2644                 foreach ($links as $link)
2645                 {
2646                     if (isset($link['attribs']['']['href']))
2647                     {
2648                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2649                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2650                     }
2651                 }
2652             }
2653             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2654             {
2655                 foreach ($links as $link)
2656                 {
2657                     if (isset($link['attribs']['']['href']))
2658                     {
2659                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2660                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2661
2662                     }
2663                 }
2664             }
2665             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2666             {
2667                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2668             }
2669             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2670             {
2671                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2672             }
2673             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2674             {
2675                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2676             }
2677
2678             $keys = array_keys($this->data['links']);
2679             foreach ($keys as $key)
2680             {
2681                 if (SimplePie_Misc::is_isegment_nz_nc($key))
2682                 {
2683                     if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2684                     {
2685                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2686                         $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2687                     }
2688                     else
2689                     {
2690                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2691                     }
2692                 }
2693                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2694                 {
2695                     $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2696                 }
2697                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2698             }
2699         }
2700
2701         if (isset($this->data['links'][$rel]))
2702         {
2703             return $this->data['links'][$rel];
2704         }
2705         else
2706         {
2707             return null;
2708         }
2709     }
2710
2711     function get_all_discovered_feeds()
2712     {
2713         return $this->all_discovered_feeds;
2714     }
2715
2716     function get_description()
2717     {
2718         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2719         {
2720             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2721         }
2722         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2723         {
2724             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2725         }
2726         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2727         {
2728             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2729         }
2730         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2731         {
2732             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2733         }
2734         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2735         {
2736             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2737         }
2738         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2739         {
2740             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2741         }
2742         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2743         {
2744             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2745         }
2746         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2747         {
2748             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2749         }
2750         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2751         {
2752             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2753         }
2754         else
2755         {
2756             return null;
2757         }
2758     }
2759
2760     function get_copyright()
2761     {
2762         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2763         {
2764             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2765         }
2766         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2767         {
2768             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2769         }
2770         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2771         {
2772             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2773         }
2774         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2775         {
2776             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2777         }
2778         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2779         {
2780             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2781         }
2782         else
2783         {
2784             return null;
2785         }
2786     }
2787
2788     function get_language()
2789     {
2790         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2791         {
2792             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2793         }
2794         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2795         {
2796             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2797         }
2798         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2799         {
2800             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2801         }
2802         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2803         {
2804             return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2805         }
2806         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2807         {
2808             return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2809         }
2810         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2811         {
2812             return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2813         }
2814         elseif (isset($this->data['headers']['content-language']))
2815         {
2816             return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2817         }
2818         else
2819         {
2820             return null;
2821         }
2822     }
2823
2824     function get_latitude()
2825     {
b1a6a5 2826
fd9ef2 2827         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
T 2828         {
2829             return (float) $return[0]['data'];
2830         }
2831         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))
2832         {
2833             return (float) $match[1];
2834         }
2835         else
2836         {
2837             return null;
2838         }
2839     }
2840
2841     function get_longitude()
2842     {
2843         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2844         {
2845             return (float) $return[0]['data'];
2846         }
2847         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2848         {
2849             return (float) $return[0]['data'];
2850         }
2851         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))
2852         {
2853             return (float) $match[2];
2854         }
2855         else
2856         {
2857             return null;
2858         }
2859     }
2860
2861     function get_image_title()
2862     {
2863         if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2864         {
2865             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2866         }
2867         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2868         {
2869             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2870         }
2871         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2872         {
2873             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2874         }
2875         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2876         {
2877             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2878         }
2879         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2880         {
2881             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2882         }
2883         else
2884         {
2885             return null;
2886         }
2887     }
2888
2889     function get_image_url()
2890     {
2891         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2892         {
2893             return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2894         }
2895         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2896         {
2897             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2898         }
2899         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2900         {
2901             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2902         }
2903         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2904         {
2905             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2906         }
2907         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2908         {
2909             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2910         }
2911         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2912         {
2913             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2914         }
2915         else
2916         {
2917             return null;
2918         }
2919     }
2920
2921     function get_image_link()
2922     {
2923         if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2924         {
2925             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2926         }
2927         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2928         {
2929             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2930         }
2931         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2932         {
2933             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2934         }
2935         else
2936         {
2937             return null;
2938         }
2939     }
2940
2941     function get_image_width()
2942     {
2943         if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2944         {
2945             return round($return[0]['data']);
2946         }
2947         elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2948         {
2949             return 88.0;
2950         }
2951         else
2952         {
2953             return null;
2954         }
2955     }
2956
2957     function get_image_height()
2958     {
2959         if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2960         {
2961             return round($return[0]['data']);
2962         }
2963         elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2964         {
2965             return 31.0;
2966         }
2967         else
2968         {
2969             return null;
2970         }
2971     }
2972
2973     function get_item_quantity($max = 0)
2974     {
2975         $max = (int) $max;
2976         $qty = count($this->get_items());
2977         if ($max === 0)
2978         {
2979             return $qty;
2980         }
2981         else
2982         {
2983             return ($qty > $max) ? $max : $qty;
2984         }
2985     }
2986
2987     function get_item($key = 0)
2988     {
2989         $items = $this->get_items();
2990         if (isset($items[$key]))
2991         {
2992             return $items[$key];
2993         }
2994         else
2995         {
2996             return null;
2997         }
2998     }
2999
3000     function get_items($start = 0, $end = 0)
3001     {
3002         if (!isset($this->data['items']))
3003         {
3004             if (!empty($this->multifeed_objects))
3005             {
3006                 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
3007             }
3008             else
3009             {
3010                 $this->data['items'] = array();
3011                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
3012                 {
3013                     $keys = array_keys($items);
3014                     foreach ($keys as $key)
3015                     {
f64c86 3016                         $this->data['items'][] = new $this->item_class($this, $items[$key]);
fd9ef2 3017                     }
T 3018                 }
3019                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
3020                 {
3021                     $keys = array_keys($items);
3022                     foreach ($keys as $key)
3023                     {
f64c86 3024                         $this->data['items'][] = new $this->item_class($this, $items[$key]);
fd9ef2 3025                     }
T 3026                 }
3027                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
3028                 {
3029                     $keys = array_keys($items);
3030                     foreach ($keys as $key)
3031                     {
f64c86 3032                         $this->data['items'][] = new $this->item_class($this, $items[$key]);
fd9ef2 3033                     }
T 3034                 }
3035                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
3036                 {
3037                     $keys = array_keys($items);
3038                     foreach ($keys as $key)
3039                     {
f64c86 3040                         $this->data['items'][] = new $this->item_class($this, $items[$key]);
fd9ef2 3041                     }
T 3042                 }
3043                 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
3044                 {
3045                     $keys = array_keys($items);
3046                     foreach ($keys as $key)
3047                     {
f64c86 3048                         $this->data['items'][] = new $this->item_class($this, $items[$key]);
fd9ef2 3049                     }
T 3050                 }
3051             }
3052         }
3053
3054         if (!empty($this->data['items']))
3055         {
3056             // If we want to order it by date, check if all items have a date, and then sort it
3057             if ($this->order_by_date && empty($this->multifeed_objects))
3058             {
3059                 if (!isset($this->data['ordered_items']))
3060                 {
3061                     $do_sort = true;
3062                     foreach ($this->data['items'] as $item)
3063                     {
3064                         if (!$item->get_date('U'))
3065                         {
3066                             $do_sort = false;
3067                             break;
3068                         }
3069                     }
3070                     $item = null;
3071                     $this->data['ordered_items'] = $this->data['items'];
3072                     if ($do_sort)
3073                     {
3074                         usort($this->data['ordered_items'], array(&$this, 'sort_items'));
3075                     }
3076                 }
3077                 $items = $this->data['ordered_items'];
3078             }
3079             else
3080             {
3081                 $items = $this->data['items'];
3082             }
3083
3084             // Slice the data as desired
3085             if ($end === 0)
3086             {
3087                 return array_slice($items, $start);
3088             }
3089             else
3090             {
3091                 return array_slice($items, $start, $end);
3092             }
3093         }
3094         else
3095         {
3096             return array();
3097         }
3098     }
3099
b1a6a5 3100
fd9ef2 3101     /**
T 3102      * @static
3103      */
3104     function sort_items($a, $b)
3105     {
3106         return $a->get_date('U') <= $b->get_date('U');
3107     }
b1a6a5 3108
fd9ef2 3109
T 3110     /**
3111      * @static
3112      */
3113     function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3114     {
3115         if (is_array($urls) && sizeof($urls) > 0)
3116         {
3117             $items = array();
3118             foreach ($urls as $arg)
3119             {
3120                 if (is_a($arg, 'SimplePie'))
3121                 {
3122                     $items = array_merge($items, $arg->get_items(0, $limit));
3123                 }
3124                 else
3125                 {
3126                     trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3127                 }
3128             }
3129
3130             $do_sort = true;
3131             foreach ($items as $item)
3132             {
3133                 if (!$item->get_date('U'))
3134                 {
3135                     $do_sort = false;
3136                     break;
3137                 }
3138             }
3139             $item = null;
3140             if ($do_sort)
3141             {
3142                 usort($items, array('SimplePie', 'sort_items'));
3143             }
3144
3145             if ($end === 0)
3146             {
3147                 return array_slice($items, $start);
3148             }
3149             else
3150             {
3151                 return array_slice($items, $start, $end);
3152             }
3153         }
3154         else
3155         {
3156             trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3157             return array();
3158         }
3159     }
b1a6a5 3160
fd9ef2 3161 }
T 3162
3163 class SimplePie_Item
3164 {
3165     var $feed;
3166     var $data = array();
3167
3168     function SimplePie_Item($feed, $data)
3169     {
3170         $this->feed = $feed;
3171         $this->data = $data;
3172     }
3173
3174     function __toString()
3175     {
3176         return md5(serialize($this->data));
3177     }
b1a6a5 3178
fd9ef2 3179
T 3180     /**
3181      * Remove items that link back to this before destroying this object
3182      */
3183     function __destruct()
3184     {
3185         if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
3186         {
3187             unset($this->feed);
3188         }
3189     }
3190
3191     function get_item_tags($namespace, $tag)
3192     {
3193         if (isset($this->data['child'][$namespace][$tag]))
3194         {
3195             return $this->data['child'][$namespace][$tag];
3196         }
3197         else
3198         {
3199             return null;
3200         }
3201     }
3202
3203     function get_base($element = array())
3204     {
3205         return $this->feed->get_base($element);
3206     }
3207
3208     function sanitize($data, $type, $base = '')
3209     {
3210         return $this->feed->sanitize($data, $type, $base);
3211     }
3212
3213     function get_feed()
3214     {
3215         return $this->feed;
3216     }
3217
3218     function get_id($hash = false)
3219     {
3220         if (!$hash)
3221         {
3222             if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
3223             {
3224                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3225             }
3226             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
3227             {
3228                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3229             }
3230             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3231             {
3232                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3233             }
3234             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
3235             {
3236                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3237             }
3238             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
3239             {
3240                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3241             }
3242             elseif (($return = $this->get_permalink()) !== null)
3243             {
3244                 return $return;
3245             }
3246             elseif (($return = $this->get_title()) !== null)
3247             {
3248                 return $return;
3249             }
3250         }
3251         if ($this->get_permalink() !== null || $this->get_title() !== null)
3252         {
3253             return md5($this->get_permalink() . $this->get_title());
3254         }
3255         else
3256         {
3257             return md5(serialize($this->data));
3258         }
3259     }
3260
3261     function get_title()
3262     {
3263         if (!isset($this->data['title']))
3264         {
3265             if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
3266             {
3267                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3268             }
3269             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
3270             {
3271                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3272             }
3273             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
3274             {
3275                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3276             }
3277             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
3278             {
3279                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3280             }
3281             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
3282             {
3283                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3284             }
3285             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
3286             {
3287                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3288             }
3289             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
3290             {
3291                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3292             }
3293             else
3294             {
3295                 $this->data['title'] = null;
3296             }
3297         }
3298         return $this->data['title'];
3299     }
3300
3301     function get_description($description_only = false)
3302     {
3303         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
3304         {
3305             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3306         }
3307         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
3308         {
3309             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3310         }
3311         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
3312         {
3313             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3314         }
3315         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
3316         {
3317             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3318         }
3319         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3320         {
3321             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3322         }
3323         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3324         {
3325             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3326         }
3327         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3328         {
3329             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3330         }
3331         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3332         {
3333             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3334         }
3335         elseif (!$description_only)
3336         {
3337             return $this->get_content(true);
3338         }
3339         else
3340         {
3341             return null;
3342         }
3343     }
3344
3345     function get_content($content_only = false)
3346     {
3347         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3348         {
3349             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3350         }
3351         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3352         {
3353             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3354         }
3355         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3356         {
3357             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3358         }
3359         elseif (!$content_only)
3360         {
3361             return $this->get_description(true);
3362         }
3363         else
3364         {
3365             return null;
3366         }
3367     }
3368
3369     function get_category($key = 0)
3370     {
3371         $categories = $this->get_categories();
3372         if (isset($categories[$key]))
3373         {
3374             return $categories[$key];
3375         }
3376         else
3377         {
3378             return null;
3379         }
3380     }
3381
3382     function get_categories()
3383     {
3384         $categories = array();
3385
3386         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3387         {
3388             $term = null;
3389             $scheme = null;
3390             $label = null;
3391             if (isset($category['attribs']['']['term']))
3392             {
3393                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3394             }
3395             if (isset($category['attribs']['']['scheme']))
3396             {
3397                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3398             }
3399             if (isset($category['attribs']['']['label']))
3400             {
3401                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3402             }
f64c86 3403             $categories[] = new $this->feed->category_class($term, $scheme, $label);
fd9ef2 3404         }
T 3405         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
3406         {
3407             // This is really the label, but keep this as the term also for BC.
3408             // Label will also work on retrieving because that falls back to term.
3409             $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3410             if (isset($category['attribs']['']['domain']))
3411             {
3412                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
3413             }
3414             else
3415             {
3416                 $scheme = null;
3417             }
f64c86 3418             $categories[] = new $this->feed->category_class($term, $scheme, null);
fd9ef2 3419         }
T 3420         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3421         {
f64c86 3422             $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 3423         }
T 3424         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3425         {
f64c86 3426             $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 3427         }
T 3428
3429         if (!empty($categories))
3430         {
3431             return SimplePie_Misc::array_unique($categories);
3432         }
3433         else
3434         {
3435             return null;
3436         }
3437     }
3438
3439     function get_author($key = 0)
3440     {
3441         $authors = $this->get_authors();
3442         if (isset($authors[$key]))
3443         {
3444             return $authors[$key];
3445         }
3446         else
3447         {
3448             return null;
3449         }
3450     }
3451
3452     function get_contributor($key = 0)
3453     {
3454         $contributors = $this->get_contributors();
3455         if (isset($contributors[$key]))
3456         {
3457             return $contributors[$key];
3458         }
3459         else
3460         {
3461             return null;
3462         }
3463     }
3464
3465     function get_contributors()
3466     {
3467         $contributors = array();
3468         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3469         {
3470             $name = null;
3471             $uri = null;
3472             $email = null;
3473             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3474             {
3475                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3476             }
3477             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3478             {
3479                 $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]));
3480             }
3481             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3482             {
3483                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3484             }
3485             if ($name !== null || $email !== null || $uri !== null)
3486             {
f64c86 3487                 $contributors[] = new $this->feed->author_class($name, $uri, $email);
fd9ef2 3488             }
T 3489         }
3490         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3491         {
3492             $name = null;
3493             $url = null;
3494             $email = null;
3495             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3496             {
3497                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3498             }
3499             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3500             {
3501                 $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]));
3502             }
3503             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3504             {
3505                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3506             }
3507             if ($name !== null || $email !== null || $url !== null)
3508             {
f64c86 3509                 $contributors[] = new $this->feed->author_class($name, $url, $email);
fd9ef2 3510             }
T 3511         }
3512
3513         if (!empty($contributors))
3514         {
3515             return SimplePie_Misc::array_unique($contributors);
3516         }
3517         else
3518         {
3519             return null;
3520         }
3521     }
3522
3523     function get_authors()
3524     {
3525         $authors = array();
3526         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3527         {
3528             $name = null;
3529             $uri = null;
3530             $email = null;
3531             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3532             {
3533                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3534             }
3535             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3536             {
3537                 $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]));
3538             }
3539             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3540             {
3541                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3542             }
3543             if ($name !== null || $email !== null || $uri !== null)
3544             {
f64c86 3545                 $authors[] = new $this->feed->author_class($name, $uri, $email);
fd9ef2 3546             }
T 3547         }
3548         if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3549         {
3550             $name = null;
3551             $url = null;
3552             $email = null;
3553             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3554             {
3555                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3556             }
3557             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3558             {
3559                 $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]));
3560             }
3561             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3562             {
3563                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3564             }
3565             if ($name !== null || $email !== null || $url !== null)
3566             {
f64c86 3567                 $authors[] = new $this->feed->author_class($name, $url, $email);
fd9ef2 3568             }
T 3569         }
3570         if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
3571         {
f64c86 3572             $authors[] = new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
fd9ef2 3573         }
T 3574         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3575         {
f64c86 3576             $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 3577         }
T 3578         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3579         {
f64c86 3580             $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 3581         }
T 3582         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3583         {
f64c86 3584             $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 3585         }
T 3586
3587         if (!empty($authors))
3588         {
3589             return SimplePie_Misc::array_unique($authors);
3590         }
3591         elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3592         {
3593             return $authors;
3594         }
3595         elseif ($authors = $this->feed->get_authors())
3596         {
3597             return $authors;
3598         }
3599         else
3600         {
3601             return null;
3602         }
3603     }
3604
3605     function get_copyright()
3606     {
3607         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3608         {
3609             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3610         }
3611         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3612         {
3613             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3614         }
3615         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3616         {
3617             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3618         }
3619         else
3620         {
3621             return null;
3622         }
3623     }
3624
3625     function get_date($date_format = 'j F Y, g:i a')
3626     {
3627         if (!isset($this->data['date']))
3628         {
3629             if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3630             {
3631                 $this->data['date']['raw'] = $return[0]['data'];
3632             }
3633             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3634             {
3635                 $this->data['date']['raw'] = $return[0]['data'];
3636             }
3637             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3638             {
3639                 $this->data['date']['raw'] = $return[0]['data'];
3640             }
3641             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3642             {
3643                 $this->data['date']['raw'] = $return[0]['data'];
3644             }
3645             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3646             {
3647                 $this->data['date']['raw'] = $return[0]['data'];
3648             }
3649             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
3650             {
3651                 $this->data['date']['raw'] = $return[0]['data'];
3652             }
3653             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3654             {
3655                 $this->data['date']['raw'] = $return[0]['data'];
3656             }
3657             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3658             {
3659                 $this->data['date']['raw'] = $return[0]['data'];
3660             }
3661
3662             if (!empty($this->data['date']['raw']))
3663             {
3664                 $parser = SimplePie_Parse_Date::get();
3665                 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3666             }
3667             else
3668             {
3669                 $this->data['date'] = null;
3670             }
3671         }
3672         if ($this->data['date'])
3673         {
3674             $date_format = (string) $date_format;
3675             switch ($date_format)
3676             {
b1a6a5 3677             case '':
MC 3678                 return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
fd9ef2 3679
b1a6a5 3680             case 'U':
MC 3681                 return $this->data['date']['parsed'];
fd9ef2 3682
b1a6a5 3683             default:
MC 3684                 return date($date_format, $this->data['date']['parsed']);
fd9ef2 3685             }
T 3686         }
3687         else
3688         {
3689             return null;
3690         }
3691     }
3692
3693     function get_local_date($date_format = '%c')
3694     {
3695         if (!$date_format)
3696         {
3697             return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3698         }
3699         elseif (($date = $this->get_date('U')) !== null)
3700         {
3701             return strftime($date_format, $date);
3702         }
3703         else
3704         {
3705             return null;
3706         }
3707     }
3708
3709     function get_permalink()
3710     {
3711         $link = $this->get_link();
3712         $enclosure = $this->get_enclosure(0);
3713         if ($link !== null)
3714         {
3715             return $link;
3716         }
3717         elseif ($enclosure !== null)
3718         {
3719             return $enclosure->get_link();
3720         }
3721         else
3722         {
3723             return null;
3724         }
3725     }
3726
3727     function get_link($key = 0, $rel = 'alternate')
3728     {
3729         $links = $this->get_links($rel);
3730         if ($links[$key] !== null)
3731         {
3732             return $links[$key];
3733         }
3734         else
3735         {
3736             return null;
3737         }
3738     }
3739
3740     function get_links($rel = 'alternate')
3741     {
3742         if (!isset($this->data['links']))
3743         {
3744             $this->data['links'] = array();
3745             foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3746             {
3747                 if (isset($link['attribs']['']['href']))
3748                 {
3749                     $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3750                     $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3751
3752                 }
3753             }
3754             foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3755             {
3756                 if (isset($link['attribs']['']['href']))
3757                 {
3758                     $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3759                     $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3760                 }
3761             }
3762             if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3763             {
3764                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3765             }
3766             if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3767             {
3768                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3769             }
3770             if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
3771             {
3772                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3773             }
3774             if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3775             {
3776                 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
3777                 {
3778                     $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3779                 }
3780             }
3781
3782             $keys = array_keys($this->data['links']);
3783             foreach ($keys as $key)
3784             {
3785                 if (SimplePie_Misc::is_isegment_nz_nc($key))
3786                 {
3787                     if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3788                     {
3789                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3790                         $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3791                     }
3792                     else
3793                     {
3794                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3795                     }
3796                 }
3797                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
3798                 {
3799                     $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3800                 }
3801                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3802             }
3803         }
3804         if (isset($this->data['links'][$rel]))
3805         {
3806             return $this->data['links'][$rel];
3807         }
3808         else
3809         {
3810             return null;
3811         }
3812     }
3813
b1a6a5 3814
fd9ef2 3815     /**
T 3816      * @todo Add ability to prefer one type of content over another (in a media group).
3817      */
3818     function get_enclosure($key = 0, $prefer = null)
3819     {
3820         $enclosures = $this->get_enclosures();
3821         if (isset($enclosures[$key]))
3822         {
3823             return $enclosures[$key];
3824         }
3825         else
3826         {
3827             return null;
3828         }
3829     }
b1a6a5 3830
fd9ef2 3831
T 3832     /**
3833      * Grabs all available enclosures (podcasts, etc.)
3834      *
3835      * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3836      *
3837      * 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.
3838      *
3839      * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3840      * @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).
3841      */
3842     function get_enclosures()
3843     {
3844         if (!isset($this->data['enclosures']))
3845         {
3846             $this->data['enclosures'] = array();
3847
3848             // Elements
3849             $captions_parent = null;
3850             $categories_parent = null;
3851             $copyrights_parent = null;
3852             $credits_parent = null;
3853             $description_parent = null;
3854             $duration_parent = null;
3855             $hashes_parent = null;
3856             $keywords_parent = null;
3857             $player_parent = null;
3858             $ratings_parent = null;
3859             $restrictions_parent = null;
3860             $thumbnails_parent = null;
3861             $title_parent = null;
3862
3863             // Let's do the channel and item-level ones first, and just re-use them if we need to.
3864             $parent = $this->get_feed();
3865
3866             // CAPTIONS
3867             if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3868             {
3869                 foreach ($captions as $caption)
3870                 {
3871                     $caption_type = null;
3872                     $caption_lang = null;
3873                     $caption_startTime = null;
3874                     $caption_endTime = null;
3875                     $caption_text = null;
3876                     if (isset($caption['attribs']['']['type']))
3877                     {
3878                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3879                     }
3880                     if (isset($caption['attribs']['']['lang']))
3881                     {
3882                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3883                     }
3884                     if (isset($caption['attribs']['']['start']))
3885                     {
3886                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3887                     }
3888                     if (isset($caption['attribs']['']['end']))
3889                     {
3890                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3891                     }
3892                     if (isset($caption['data']))
3893                     {
3894                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3895                     }
f64c86 3896                     $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
fd9ef2 3897                 }
T 3898             }
3899             elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3900             {
3901                 foreach ($captions as $caption)
3902                 {
3903                     $caption_type = null;
3904                     $caption_lang = null;
3905                     $caption_startTime = null;
3906                     $caption_endTime = null;
3907                     $caption_text = null;
3908                     if (isset($caption['attribs']['']['type']))
3909                     {
3910                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3911                     }
3912                     if (isset($caption['attribs']['']['lang']))
3913                     {
3914                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3915                     }
3916                     if (isset($caption['attribs']['']['start']))
3917                     {
3918                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3919                     }
3920                     if (isset($caption['attribs']['']['end']))
3921                     {
3922                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3923                     }
3924                     if (isset($caption['data']))
3925                     {
3926                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3927                     }
f64c86 3928                     $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
fd9ef2 3929                 }
T 3930             }
3931             if (is_array($captions_parent))
3932             {
3933                 $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
3934             }
3935
3936             // CATEGORIES
3937             foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3938             {
3939                 $term = null;
3940                 $scheme = null;
3941                 $label = null;
3942                 if (isset($category['data']))
3943                 {
3944                     $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3945                 }
3946                 if (isset($category['attribs']['']['scheme']))
3947                 {
3948                     $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3949                 }
3950                 else
3951                 {
3952                     $scheme = 'http://search.yahoo.com/mrss/category_schema';
3953                 }
3954                 if (isset($category['attribs']['']['label']))
3955                 {
3956                     $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3957                 }
f64c86 3958                 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
fd9ef2 3959             }
T 3960             foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3961             {
3962                 $term = null;
3963                 $scheme = null;
3964                 $label = null;
3965                 if (isset($category['data']))
3966                 {
3967                     $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3968                 }
3969                 if (isset($category['attribs']['']['scheme']))
3970                 {
3971                     $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3972                 }
3973                 else
3974                 {
3975                     $scheme = 'http://search.yahoo.com/mrss/category_schema';
3976                 }
3977                 if (isset($category['attribs']['']['label']))
3978                 {
3979                     $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3980                 }
f64c86 3981                 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
fd9ef2 3982             }
T 3983             foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
3984             {
3985                 $term = null;
3986                 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
3987                 $label = null;
3988                 if (isset($category['attribs']['']['text']))
3989                 {
3990                     $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3991                 }
f64c86 3992                 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
fd9ef2 3993
T 3994                 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
3995                 {
3996                     foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
3997                     {
3998                         if (isset($subcategory['attribs']['']['text']))
3999                         {
4000                             $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
4001                         }
f64c86 4002                         $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
fd9ef2 4003                     }
T 4004                 }
4005             }
4006             if (is_array($categories_parent))
4007             {
4008                 $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
4009             }
4010
4011             // COPYRIGHT
4012             if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
4013             {
4014                 $copyright_url = null;
4015                 $copyright_label = null;
4016                 if (isset($copyright[0]['attribs']['']['url']))
4017                 {
4018                     $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4019                 }
4020                 if (isset($copyright[0]['data']))
4021                 {
4022                     $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4023                 }
f64c86 4024                 $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
fd9ef2 4025             }
T 4026             elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
4027             {
4028                 $copyright_url = null;
4029                 $copyright_label = null;
4030                 if (isset($copyright[0]['attribs']['']['url']))
4031                 {
4032                     $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4033                 }
4034                 if (isset($copyright[0]['data']))
4035                 {
4036                     $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4037                 }
f64c86 4038                 $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
fd9ef2 4039             }
T 4040
4041             // CREDITS
4042             if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4043             {
4044                 foreach ($credits as $credit)
4045                 {
4046                     $credit_role = null;
4047                     $credit_scheme = null;
4048                     $credit_name = null;
4049                     if (isset($credit['attribs']['']['role']))
4050                     {
4051                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4052                     }
4053                     if (isset($credit['attribs']['']['scheme']))
4054                     {
4055                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4056                     }
4057                     else
4058                     {
4059                         $credit_scheme = 'urn:ebu';
4060                     }
4061                     if (isset($credit['data']))
4062                     {
4063                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4064                     }
f64c86 4065                     $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
fd9ef2 4066                 }
T 4067             }
4068             elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4069             {
4070                 foreach ($credits as $credit)
4071                 {
4072                     $credit_role = null;
4073                     $credit_scheme = null;
4074                     $credit_name = null;
4075                     if (isset($credit['attribs']['']['role']))
4076                     {
4077                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4078                     }
4079                     if (isset($credit['attribs']['']['scheme']))
4080                     {
4081                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4082                     }
4083                     else
4084                     {
4085                         $credit_scheme = 'urn:ebu';
4086                     }
4087                     if (isset($credit['data']))
4088                     {
4089                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4090                     }
f64c86 4091                     $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
fd9ef2 4092                 }
T 4093             }
4094             if (is_array($credits_parent))
4095             {
4096                 $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
4097             }
4098
4099             // DESCRIPTION
4100             if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4101             {
4102                 if (isset($description_parent[0]['data']))
4103                 {
4104                     $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4105                 }
4106             }
4107             elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4108             {
4109                 if (isset($description_parent[0]['data']))
4110                 {
4111                     $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4112                 }
4113             }
4114
4115             // DURATION
4116             if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
4117             {
4118                 $seconds = null;
4119                 $minutes = null;
4120                 $hours = null;
4121                 if (isset($duration_parent[0]['data']))
4122                 {
4123                     $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4124                     if (sizeof($temp) > 0)
4125                     {
4126                         (int) $seconds = array_pop($temp);
4127                     }
4128                     if (sizeof($temp) > 0)
4129                     {
4130                         (int) $minutes = array_pop($temp);
4131                         $seconds += $minutes * 60;
4132                     }
4133                     if (sizeof($temp) > 0)
4134                     {
4135                         (int) $hours = array_pop($temp);
4136                         $seconds += $hours * 3600;
4137                     }
4138                     unset($temp);
4139                     $duration_parent = $seconds;
4140                 }
4141             }
4142
4143             // HASHES
4144             if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4145             {
4146                 foreach ($hashes_iterator as $hash)
4147                 {
4148                     $value = null;
4149                     $algo = null;
4150                     if (isset($hash['data']))
4151                     {
4152                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4153                     }
4154                     if (isset($hash['attribs']['']['algo']))
4155                     {
4156                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4157                     }
4158                     else
4159                     {
4160                         $algo = 'md5';
4161                     }
4162                     $hashes_parent[] = $algo.':'.$value;
4163                 }
4164             }
4165             elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4166             {
4167                 foreach ($hashes_iterator as $hash)
4168                 {
4169                     $value = null;
4170                     $algo = null;
4171                     if (isset($hash['data']))
4172                     {
4173                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4174                     }
4175                     if (isset($hash['attribs']['']['algo']))
4176                     {
4177                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4178                     }
4179                     else
4180                     {
4181                         $algo = 'md5';
4182                     }
4183                     $hashes_parent[] = $algo.':'.$value;
4184                 }
4185             }
4186             if (is_array($hashes_parent))
4187             {
4188                 $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
4189             }
4190
4191             // KEYWORDS
4192             if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4193             {
4194                 if (isset($keywords[0]['data']))
4195                 {
4196                     $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4197                     foreach ($temp as $word)
4198                     {
4199                         $keywords_parent[] = trim($word);
4200                     }
4201                 }
4202                 unset($temp);
4203             }
4204             elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4205             {
4206                 if (isset($keywords[0]['data']))
4207                 {
4208                     $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4209                     foreach ($temp as $word)
4210                     {
4211                         $keywords_parent[] = trim($word);
4212                     }
4213                 }
4214                 unset($temp);
4215             }
4216             elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4217             {
4218                 if (isset($keywords[0]['data']))
4219                 {
4220                     $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4221                     foreach ($temp as $word)
4222                     {
4223                         $keywords_parent[] = trim($word);
4224                     }
4225                 }
4226                 unset($temp);
4227             }
4228             elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4229             {
4230                 if (isset($keywords[0]['data']))
4231                 {
4232                     $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4233                     foreach ($temp as $word)
4234                     {
4235                         $keywords_parent[] = trim($word);
4236                     }
4237                 }
4238                 unset($temp);
4239             }
4240             if (is_array($keywords_parent))
4241             {
4242                 $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
4243             }
4244
4245             // PLAYER
4246             if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4247             {
4248                 if (isset($player_parent[0]['attribs']['']['url']))
4249                 {
4250                     $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4251                 }
4252             }
4253             elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4254             {
4255                 if (isset($player_parent[0]['attribs']['']['url']))
4256                 {
4257                     $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4258                 }
4259             }
4260
4261             // RATINGS
4262             if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4263             {
4264                 foreach ($ratings as $rating)
4265                 {
4266                     $rating_scheme = null;
4267                     $rating_value = null;
4268                     if (isset($rating['attribs']['']['scheme']))
4269                     {
4270                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4271                     }
4272                     else
4273                     {
4274                         $rating_scheme = 'urn:simple';
4275                     }
4276                     if (isset($rating['data']))
4277                     {
4278                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4279                     }
f64c86 4280                     $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
fd9ef2 4281                 }
T 4282             }
4283             elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4284             {
4285                 foreach ($ratings as $rating)
4286                 {
4287                     $rating_scheme = 'urn:itunes';
4288                     $rating_value = null;
4289                     if (isset($rating['data']))
4290                     {
4291                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4292                     }
f64c86 4293                     $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
fd9ef2 4294                 }
T 4295             }
4296             elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4297             {
4298                 foreach ($ratings as $rating)
4299                 {
4300                     $rating_scheme = null;
4301                     $rating_value = null;
4302                     if (isset($rating['attribs']['']['scheme']))
4303                     {
4304                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4305                     }
4306                     else
4307                     {
4308                         $rating_scheme = 'urn:simple';
4309                     }
4310                     if (isset($rating['data']))
4311                     {
4312                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4313                     }
f64c86 4314                     $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
fd9ef2 4315                 }
T 4316             }
4317             elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4318             {
4319                 foreach ($ratings as $rating)
4320                 {
4321                     $rating_scheme = 'urn:itunes';
4322                     $rating_value = null;
4323                     if (isset($rating['data']))
4324                     {
4325                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4326                     }
f64c86 4327                     $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
fd9ef2 4328                 }
T 4329             }
4330             if (is_array($ratings_parent))
4331             {
4332                 $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
4333             }
4334
4335             // RESTRICTIONS
4336             if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4337             {
4338                 foreach ($restrictions as $restriction)
4339                 {
4340                     $restriction_relationship = null;
4341                     $restriction_type = null;
4342                     $restriction_value = null;
4343                     if (isset($restriction['attribs']['']['relationship']))
4344                     {
4345                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4346                     }
4347                     if (isset($restriction['attribs']['']['type']))
4348                     {
4349                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4350                     }
4351                     if (isset($restriction['data']))
4352                     {
4353                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4354                     }
f64c86 4355                     $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
fd9ef2 4356                 }
T 4357             }
4358             elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4359             {
4360                 foreach ($restrictions as $restriction)
4361                 {
4362                     $restriction_relationship = 'allow';
4363                     $restriction_type = null;
4364                     $restriction_value = 'itunes';
4365                     if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4366                     {
4367                         $restriction_relationship = 'deny';
4368                     }
f64c86 4369                     $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
fd9ef2 4370                 }
T 4371             }
4372             elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4373             {
4374                 foreach ($restrictions as $restriction)
4375                 {
4376                     $restriction_relationship = null;
4377                     $restriction_type = null;
4378                     $restriction_value = null;
4379                     if (isset($restriction['attribs']['']['relationship']))
4380                     {
4381                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4382                     }
4383                     if (isset($restriction['attribs']['']['type']))
4384                     {
4385                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4386                     }
4387                     if (isset($restriction['data']))
4388                     {
4389                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4390                     }
f64c86 4391                     $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
fd9ef2 4392                 }
T 4393             }
4394             elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4395             {
4396                 foreach ($restrictions as $restriction)
4397                 {
4398                     $restriction_relationship = 'allow';
4399                     $restriction_type = null;
4400                     $restriction_value = 'itunes';
4401                     if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4402                     {
4403                         $restriction_relationship = 'deny';
4404                     }
f64c86 4405                     $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
fd9ef2 4406                 }
T 4407             }
4408             if (is_array($restrictions_parent))
4409             {
4410                 $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
4411             }
4412
4413             // THUMBNAILS
4414             if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4415             {
4416                 foreach ($thumbnails as $thumbnail)
4417                 {
4418                     if (isset($thumbnail['attribs']['']['url']))
4419                     {
4420                         $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4421                     }
4422                 }
4423             }
4424             elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4425             {
4426                 foreach ($thumbnails as $thumbnail)
4427                 {
4428                     if (isset($thumbnail['attribs']['']['url']))
4429                     {
4430                         $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4431                     }
4432                 }
4433             }
4434
4435             // TITLES
4436             if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4437             {
4438                 if (isset($title_parent[0]['data']))
4439                 {
4440                     $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4441                 }
4442             }
4443             elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4444             {
4445                 if (isset($title_parent[0]['data']))
4446                 {
4447                     $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4448                 }
4449             }
4450
4451             // Clear the memory
4452             unset($parent);
4453
4454             // Attributes
4455             $bitrate = null;
4456             $channels = null;
4457             $duration = null;
4458             $expression = null;
4459             $framerate = null;
4460             $height = null;
4461             $javascript = null;
4462             $lang = null;
4463             $length = null;
4464             $medium = null;
4465             $samplingrate = null;
4466             $type = null;
4467             $url = null;
4468             $width = null;
4469
4470             // Elements
4471             $captions = null;
4472             $categories = null;
4473             $copyrights = null;
4474             $credits = null;
4475             $description = null;
4476             $hashes = null;
4477             $keywords = null;
4478             $player = null;
4479             $ratings = null;
4480             $restrictions = null;
4481             $thumbnails = null;
4482             $title = null;
4483
4484             // If we have media:group tags, loop through them.
4485             foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
4486             {
4487                 if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
4488                 {
4489                     // If we have media:content tags, loop through them.
4490                     foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4491                     {
4492                         if (isset($content['attribs']['']['url']))
4493                         {
4494                             // Attributes
4495                             $bitrate = null;
4496                             $channels = null;
4497                             $duration = null;
4498                             $expression = null;
4499                             $framerate = null;
4500                             $height = null;
4501                             $javascript = null;
4502                             $lang = null;
4503                             $length = null;
4504                             $medium = null;
4505                             $samplingrate = null;
4506                             $type = null;
4507                             $url = null;
4508                             $width = null;
4509
4510                             // Elements
4511                             $captions = null;
4512                             $categories = null;
4513                             $copyrights = null;
4514                             $credits = null;
4515                             $description = null;
4516                             $hashes = null;
4517                             $keywords = null;
4518                             $player = null;
4519                             $ratings = null;
4520                             $restrictions = null;
4521                             $thumbnails = null;
4522                             $title = null;
4523
4524                             // Start checking the attributes of media:content
4525                             if (isset($content['attribs']['']['bitrate']))
4526                             {
4527                                 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4528                             }
4529                             if (isset($content['attribs']['']['channels']))
4530                             {
4531                                 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4532                             }
4533                             if (isset($content['attribs']['']['duration']))
4534                             {
4535                                 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4536                             }
4537                             else
4538                             {
4539                                 $duration = $duration_parent;
4540                             }
4541                             if (isset($content['attribs']['']['expression']))
4542                             {
4543                                 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4544                             }
4545                             if (isset($content['attribs']['']['framerate']))
4546                             {
4547                                 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4548                             }
4549                             if (isset($content['attribs']['']['height']))
4550                             {
4551                                 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4552                             }
4553                             if (isset($content['attribs']['']['lang']))
4554                             {
4555                                 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4556                             }
4557                             if (isset($content['attribs']['']['fileSize']))
4558                             {
4559                                 $length = ceil($content['attribs']['']['fileSize']);
4560                             }
4561                             if (isset($content['attribs']['']['medium']))
4562                             {
4563                                 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4564                             }
4565                             if (isset($content['attribs']['']['samplingrate']))
4566                             {
4567                                 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4568                             }
4569                             if (isset($content['attribs']['']['type']))
4570                             {
4571                                 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4572                             }
4573                             if (isset($content['attribs']['']['width']))
4574                             {
4575                                 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4576                             }
4577                             $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4578
4579                             // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4580
4581                             // CAPTIONS
4582                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4583                             {
4584                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4585                                 {
4586                                     $caption_type = null;
4587                                     $caption_lang = null;
4588                                     $caption_startTime = null;
4589                                     $caption_endTime = null;
4590                                     $caption_text = null;
4591                                     if (isset($caption['attribs']['']['type']))
4592                                     {
4593                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4594                                     }
4595                                     if (isset($caption['attribs']['']['lang']))
4596                                     {
4597                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4598                                     }
4599                                     if (isset($caption['attribs']['']['start']))
4600                                     {
4601                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4602                                     }
4603                                     if (isset($caption['attribs']['']['end']))
4604                                     {
4605                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4606                                     }
4607                                     if (isset($caption['data']))
4608                                     {
4609                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4610                                     }
f64c86 4611                                     $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
fd9ef2 4612                                 }
T 4613                                 if (is_array($captions))
4614                                 {
4615                                     $captions = array_values(SimplePie_Misc::array_unique($captions));
4616                                 }
4617                             }
4618                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4619                             {
4620                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4621                                 {
4622                                     $caption_type = null;
4623                                     $caption_lang = null;
4624                                     $caption_startTime = null;
4625                                     $caption_endTime = null;
4626                                     $caption_text = null;
4627                                     if (isset($caption['attribs']['']['type']))
4628                                     {
4629                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4630                                     }
4631                                     if (isset($caption['attribs']['']['lang']))
4632                                     {
4633                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4634                                     }
4635                                     if (isset($caption['attribs']['']['start']))
4636                                     {
4637                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4638                                     }
4639                                     if (isset($caption['attribs']['']['end']))
4640                                     {
4641                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4642                                     }
4643                                     if (isset($caption['data']))
4644                                     {
4645                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4646                                     }
f64c86 4647                                     $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
fd9ef2 4648                                 }
T 4649                                 if (is_array($captions))
4650                                 {
4651                                     $captions = array_values(SimplePie_Misc::array_unique($captions));
4652                                 }
4653                             }
4654                             else
4655                             {
4656                                 $captions = $captions_parent;
4657                             }
4658
4659                             // CATEGORIES
4660                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4661                             {
4662                                 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4663                                 {
4664                                     $term = null;
4665                                     $scheme = null;
4666                                     $label = null;
4667                                     if (isset($category['data']))
4668                                     {
4669                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4670                                     }
4671                                     if (isset($category['attribs']['']['scheme']))
4672                                     {
4673                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4674                                     }
4675                                     else
4676                                     {
4677                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
4678                                     }
4679                                     if (isset($category['attribs']['']['label']))
4680                                     {
4681                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4682                                     }
f64c86 4683                                     $categories[] = new $this->feed->category_class($term, $scheme, $label);
fd9ef2 4684                                 }
T 4685                             }
4686                             if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4687                             {
4688                                 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4689                                 {
4690                                     $term = null;
4691                                     $scheme = null;
4692                                     $label = null;
4693                                     if (isset($category['data']))
4694                                     {
4695                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4696                                     }
4697                                     if (isset($category['attribs']['']['scheme']))
4698                                     {
4699                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4700                                     }
4701                                     else
4702                                     {
4703                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
4704                                     }
4705                                     if (isset($category['attribs']['']['label']))
4706                                     {
4707                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4708                                     }
f64c86 4709                                     $categories[] = new $this->feed->category_class($term, $scheme, $label);
fd9ef2 4710                                 }
T 4711                             }
4712                             if (is_array($categories) && is_array($categories_parent))
4713                             {
4714                                 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4715                             }
4716                             elseif (is_array($categories))
4717                             {
4718                                 $categories = array_values(SimplePie_Misc::array_unique($categories));
4719                             }
4720                             elseif (is_array($categories_parent))
4721                             {
4722                                 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4723                             }
4724
4725                             // COPYRIGHTS
4726                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4727                             {
4728                                 $copyright_url = null;
4729                                 $copyright_label = null;
4730                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4731                                 {
4732                                     $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4733                                 }
4734                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4735                                 {
4736                                     $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4737                                 }
f64c86 4738                                 $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
fd9ef2 4739                             }
T 4740                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4741                             {
4742                                 $copyright_url = null;
4743                                 $copyright_label = null;
4744                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4745                                 {
4746                                     $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4747                                 }
4748                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4749                                 {
4750                                     $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4751                                 }
f64c86 4752                                 $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
fd9ef2 4753                             }
T 4754                             else
4755                             {
4756                                 $copyrights = $copyrights_parent;
4757                             }
4758
4759                             // CREDITS
4760                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4761                             {
4762                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4763                                 {
4764                                     $credit_role = null;
4765                                     $credit_scheme = null;
4766                                     $credit_name = null;
4767                                     if (isset($credit['attribs']['']['role']))
4768                                     {
4769                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4770                                     }
4771                                     if (isset($credit['attribs']['']['scheme']))
4772                                     {
4773                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4774                                     }
4775                                     else
4776                                     {
4777                                         $credit_scheme = 'urn:ebu';
4778                                     }
4779                                     if (isset($credit['data']))
4780                                     {
4781                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4782                                     }
f64c86 4783                                     $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
fd9ef2 4784                                 }
T 4785                                 if (is_array($credits))
4786                                 {
4787                                     $credits = array_values(SimplePie_Misc::array_unique($credits));
4788                                 }
4789                             }
4790                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4791                             {
4792                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4793                                 {
4794                                     $credit_role = null;
4795                                     $credit_scheme = null;
4796                                     $credit_name = null;
4797                                     if (isset($credit['attribs']['']['role']))
4798                                     {
4799                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4800                                     }
4801                                     if (isset($credit['attribs']['']['scheme']))
4802                                     {
4803                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4804                                     }
4805                                     else
4806                                     {
4807                                         $credit_scheme = 'urn:ebu';
4808                                     }
4809                                     if (isset($credit['data']))
4810                                     {
4811                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4812                                     }
f64c86 4813                                     $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
fd9ef2 4814                                 }
T 4815                                 if (is_array($credits))
4816                                 {
4817                                     $credits = array_values(SimplePie_Misc::array_unique($credits));
4818                                 }
4819                             }
4820                             else
4821                             {
4822                                 $credits = $credits_parent;
4823                             }
4824
4825                             // DESCRIPTION
4826                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4827                             {
4828                                 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4829                             }
4830                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4831                             {
4832                                 $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4833                             }
4834                             else
4835                             {
4836                                 $description = $description_parent;
4837                             }
4838
4839                             // HASHES
4840                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4841                             {
4842                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4843                                 {
4844                                     $value = null;
4845                                     $algo = null;
4846                                     if (isset($hash['data']))
4847                                     {
4848                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4849                                     }
4850                                     if (isset($hash['attribs']['']['algo']))
4851                                     {
4852                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4853                                     }
4854                                     else
4855                                     {
4856                                         $algo = 'md5';
4857                                     }
4858                                     $hashes[] = $algo.':'.$value;
4859                                 }
4860                                 if (is_array($hashes))
4861                                 {
4862                                     $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4863                                 }
4864                             }
4865                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4866                             {
4867                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4868                                 {
4869                                     $value = null;
4870                                     $algo = null;
4871                                     if (isset($hash['data']))
4872                                     {
4873                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4874                                     }
4875                                     if (isset($hash['attribs']['']['algo']))
4876                                     {
4877                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4878                                     }
4879                                     else
4880                                     {
4881                                         $algo = 'md5';
4882                                     }
4883                                     $hashes[] = $algo.':'.$value;
4884                                 }
4885                                 if (is_array($hashes))
4886                                 {
4887                                     $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4888                                 }
4889                             }
4890                             else
4891                             {
4892                                 $hashes = $hashes_parent;
4893                             }
4894
4895                             // KEYWORDS
4896                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4897                             {
4898                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4899                                 {
4900                                     $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4901                                     foreach ($temp as $word)
4902                                     {
4903                                         $keywords[] = trim($word);
4904                                     }
4905                                     unset($temp);
4906                                 }
4907                                 if (is_array($keywords))
4908                                 {
4909                                     $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4910                                 }
4911                             }
4912                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4913                             {
4914                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4915                                 {
4916                                     $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4917                                     foreach ($temp as $word)
4918                                     {
4919                                         $keywords[] = trim($word);
4920                                     }
4921                                     unset($temp);
4922                                 }
4923                                 if (is_array($keywords))
4924                                 {
4925                                     $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4926                                 }
4927                             }
4928                             else
4929                             {
4930                                 $keywords = $keywords_parent;
4931                             }
4932
4933                             // PLAYER
4934                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4935                             {
4936                                 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4937                             }
4938                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4939                             {
4940                                 $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4941                             }
4942                             else
4943                             {
4944                                 $player = $player_parent;
4945                             }
4946
4947                             // RATINGS
4948                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4949                             {
4950                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4951                                 {
4952                                     $rating_scheme = null;
4953                                     $rating_value = null;
4954                                     if (isset($rating['attribs']['']['scheme']))
4955                                     {
4956                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4957                                     }
4958                                     else
4959                                     {
4960                                         $rating_scheme = 'urn:simple';
4961                                     }
4962                                     if (isset($rating['data']))
4963                                     {
4964                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4965                                     }
f64c86 4966                                     $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
fd9ef2 4967                                 }
T 4968                                 if (is_array($ratings))
4969                                 {
4970                                     $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4971                                 }
4972                             }
4973                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4974                             {
4975                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4976                                 {
4977                                     $rating_scheme = null;
4978                                     $rating_value = null;
4979                                     if (isset($rating['attribs']['']['scheme']))
4980                                     {
4981                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4982                                     }
4983                                     else
4984                                     {
4985                                         $rating_scheme = 'urn:simple';
4986                                     }
4987                                     if (isset($rating['data']))
4988                                     {
4989                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4990                                     }
f64c86 4991                                     $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
fd9ef2 4992                                 }
T 4993                                 if (is_array($ratings))
4994                                 {
4995                                     $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4996                                 }
4997                             }
4998                             else
4999                             {
5000                                 $ratings = $ratings_parent;
5001                             }
5002
5003                             // RESTRICTIONS
5004                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5005                             {
5006                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5007                                 {
5008                                     $restriction_relationship = null;
5009                                     $restriction_type = null;
5010                                     $restriction_value = null;
5011                                     if (isset($restriction['attribs']['']['relationship']))
5012                                     {
5013                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5014                                     }
5015                                     if (isset($restriction['attribs']['']['type']))
5016                                     {
5017                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5018                                     }
5019                                     if (isset($restriction['data']))
5020                                     {
5021                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5022                                     }
f64c86 5023                                     $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
fd9ef2 5024                                 }
T 5025                                 if (is_array($restrictions))
5026                                 {
5027                                     $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5028                                 }
5029                             }
5030                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5031                             {
5032                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5033                                 {
5034                                     $restriction_relationship = null;
5035                                     $restriction_type = null;
5036                                     $restriction_value = null;
5037                                     if (isset($restriction['attribs']['']['relationship']))
5038                                     {
5039                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5040                                     }
5041                                     if (isset($restriction['attribs']['']['type']))
5042                                     {
5043                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5044                                     }
5045                                     if (isset($restriction['data']))
5046                                     {
5047                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5048                                     }
f64c86 5049                                     $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
fd9ef2 5050                                 }
T 5051                                 if (is_array($restrictions))
5052                                 {
5053                                     $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5054                                 }
5055                             }
5056                             else
5057                             {
5058                                 $restrictions = $restrictions_parent;
5059                             }
5060
5061                             // THUMBNAILS
5062                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5063                             {
5064                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5065                                 {
5066                                     $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5067                                 }
5068                                 if (is_array($thumbnails))
5069                                 {
5070                                     $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5071                                 }
5072                             }
5073                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5074                             {
5075                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5076                                 {
5077                                     $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5078                                 }
5079                                 if (is_array($thumbnails))
5080                                 {
5081                                     $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5082                                 }
5083                             }
5084                             else
5085                             {
5086                                 $thumbnails = $thumbnails_parent;
5087                             }
5088
5089                             // TITLES
5090                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5091                             {
5092                                 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5093                             }
5094                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5095                             {
5096                                 $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5097                             }
5098                             else
5099                             {
5100                                 $title = $title_parent;
5101                             }
5102
f64c86 5103                             $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
fd9ef2 5104                         }
T 5105                     }
5106                 }
5107             }
5108
5109             // If we have standalone media:content tags, loop through them.
5110             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
5111             {
5112                 foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
5113                 {
5114                     if (isset($content['attribs']['']['url']))
5115                     {
5116                         // Attributes
5117                         $bitrate = null;
5118                         $channels = null;
5119                         $duration = null;
5120                         $expression = null;
5121                         $framerate = null;
5122                         $height = null;
5123                         $javascript = null;
5124                         $lang = null;
5125                         $length = null;
5126                         $medium = null;
5127                         $samplingrate = null;
5128                         $type = null;
5129                         $url = null;
5130                         $width = null;
5131
5132                         // Elements
5133                         $captions = null;
5134                         $categories = null;
5135                         $copyrights = null;
5136                         $credits = null;
5137                         $description = null;
5138                         $hashes = null;
5139                         $keywords = null;
5140                         $player = null;
5141                         $ratings = null;
5142                         $restrictions = null;
5143                         $thumbnails = null;
5144                         $title = null;
5145
5146                         // Start checking the attributes of media:content
5147                         if (isset($content['attribs']['']['bitrate']))
5148                         {
5149                             $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5150                         }
5151                         if (isset($content['attribs']['']['channels']))
5152                         {
5153                             $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
5154                         }
5155                         if (isset($content['attribs']['']['duration']))
5156                         {
5157                             $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
5158                         }
5159                         else
5160                         {
5161                             $duration = $duration_parent;
5162                         }
5163                         if (isset($content['attribs']['']['expression']))
5164                         {
5165                             $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
5166                         }
5167                         if (isset($content['attribs']['']['framerate']))
5168                         {
5169                             $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
5170                         }
5171                         if (isset($content['attribs']['']['height']))
5172                         {
5173                             $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
5174                         }
5175                         if (isset($content['attribs']['']['lang']))
5176                         {
5177                             $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5178                         }
5179                         if (isset($content['attribs']['']['fileSize']))
5180                         {
5181                             $length = ceil($content['attribs']['']['fileSize']);
5182                         }
5183                         if (isset($content['attribs']['']['medium']))
5184                         {
5185                             $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
5186                         }
5187                         if (isset($content['attribs']['']['samplingrate']))
5188                         {
5189                             $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5190                         }
5191                         if (isset($content['attribs']['']['type']))
5192                         {
5193                             $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5194                         }
5195                         if (isset($content['attribs']['']['width']))
5196                         {
5197                             $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
5198                         }
5199                         $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5200
5201                         // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
5202
5203                         // CAPTIONS
5204                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
5205                         {
5206                             foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
5207                             {
5208                                 $caption_type = null;
5209                                 $caption_lang = null;
5210                                 $caption_startTime = null;
5211                                 $caption_endTime = null;
5212                                 $caption_text = null;
5213                                 if (isset($caption['attribs']['']['type']))
5214                                 {
5215                                     $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5216                                 }
5217                                 if (isset($caption['attribs']['']['lang']))
5218                                 {
5219                                     $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5220                                 }
5221                                 if (isset($caption['attribs']['']['start']))
5222                                 {
5223                                     $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
5224                                 }
5225                                 if (isset($caption['attribs']['']['end']))
5226                                 {
5227                                     $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
5228                                 }
5229                                 if (isset($caption['data']))
5230                                 {
5231                                     $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5232                                 }
f64c86 5233                                 $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
fd9ef2 5234                             }
T 5235                             if (is_array($captions))
5236                             {
5237                                 $captions = array_values(SimplePie_Misc::array_unique($captions));
5238                             }
5239                         }
5240                         else
5241                         {
5242                             $captions = $captions_parent;
5243                         }
5244
5245                         // CATEGORIES
5246                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
5247                         {
5248                             foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
5249                             {
5250                                 $term = null;
5251                                 $scheme = null;
5252                                 $label = null;
5253                                 if (isset($category['data']))
5254                                 {
5255                                     $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5256                                 }
5257                                 if (isset($category['attribs']['']['scheme']))
5258                                 {
5259                                     $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5260                                 }
5261                                 else
5262                                 {
5263                                     $scheme = 'http://search.yahoo.com/mrss/category_schema';
5264                                 }
5265                                 if (isset($category['attribs']['']['label']))
5266                                 {
5267                                     $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5268                                 }
f64c86 5269                                 $categories[] = new $this->feed->category_class($term, $scheme, $label);
fd9ef2 5270                             }
T 5271                         }
5272                         if (is_array($categories) && is_array($categories_parent))
5273                         {
5274                             $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
5275                         }
5276                         elseif (is_array($categories))
5277                         {
5278                             $categories = array_values(SimplePie_Misc::array_unique($categories));
5279                         }
5280                         elseif (is_array($categories_parent))
5281                         {
5282                             $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
5283                         }
5284                         else
5285                         {
5286                             $categories = null;
5287                         }
5288
5289                         // COPYRIGHTS
5290                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
5291                         {
5292                             $copyright_url = null;
5293                             $copyright_label = null;
5294                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
5295                             {
5296                                 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
5297                             }
5298                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
5299                             {
5300                                 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5301                             }
f64c86 5302                             $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
fd9ef2 5303                         }
T 5304                         else
5305                         {
5306                             $copyrights = $copyrights_parent;
5307                         }
5308
5309                         // CREDITS
5310                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
5311                         {
5312                             foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
5313                             {
5314                                 $credit_role = null;
5315                                 $credit_scheme = null;
5316                                 $credit_name = null;
5317                                 if (isset($credit['attribs']['']['role']))
5318                                 {
5319                                     $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
5320                                 }
5321                                 if (isset($credit['attribs']['']['scheme']))
5322                                 {
5323                                     $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5324                                 }
5325                                 else
5326                                 {
5327                                     $credit_scheme = 'urn:ebu';
5328                                 }
5329                                 if (isset($credit['data']))
5330                                 {
5331                                     $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5332                                 }
f64c86 5333                                 $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
fd9ef2 5334                             }
T 5335                             if (is_array($credits))
5336                             {
5337                                 $credits = array_values(SimplePie_Misc::array_unique($credits));
5338                             }
5339                         }
5340                         else
5341                         {
5342                             $credits = $credits_parent;
5343                         }
5344
5345                         // DESCRIPTION
5346                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
5347                         {
5348                             $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5349                         }
5350                         else
5351                         {
5352                             $description = $description_parent;
5353                         }
5354
5355                         // HASHES
5356                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
5357                         {
5358                             foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
5359                             {
5360                                 $value = null;
5361                                 $algo = null;
5362                                 if (isset($hash['data']))
5363                                 {
5364                                     $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5365                                 }
5366                                 if (isset($hash['attribs']['']['algo']))
5367                                 {
5368                                     $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
5369                                 }
5370                                 else
5371                                 {
5372                                     $algo = 'md5';
5373                                 }
5374                                 $hashes[] = $algo.':'.$value;
5375                             }
5376                             if (is_array($hashes))
5377                             {
5378                                 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
5379                             }
5380                         }
5381                         else
5382                         {
5383                             $hashes = $hashes_parent;
5384                         }
5385
5386                         // KEYWORDS
5387                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
5388                         {
5389                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
5390                             {
5391                                 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
5392                                 foreach ($temp as $word)
5393                                 {
5394                                     $keywords[] = trim($word);
5395                                 }
5396                                 unset($temp);
5397                             }
5398                             if (is_array($keywords))
5399                             {
5400                                 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
5401                             }
5402                         }
5403                         else
5404                         {
5405                             $keywords = $keywords_parent;
5406                         }
5407
5408                         // PLAYER
5409                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5410                         {
5411                             $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5412                         }
5413                         else
5414                         {
5415                             $player = $player_parent;
5416                         }
5417
5418                         // RATINGS
5419                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
5420                         {
5421                             foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
5422                             {
5423                                 $rating_scheme = null;
5424                                 $rating_value = null;
5425                                 if (isset($rating['attribs']['']['scheme']))
5426                                 {
5427                                     $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5428                                 }
5429                                 else
5430                                 {
5431                                     $rating_scheme = 'urn:simple';
5432                                 }
5433                                 if (isset($rating['data']))
5434                                 {
5435                                     $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5436                                 }
f64c86 5437                                 $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
fd9ef2 5438                             }
T 5439                             if (is_array($ratings))
5440                             {
5441                                 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
5442                             }
5443                         }
5444                         else
5445                         {
5446                             $ratings = $ratings_parent;
5447                         }
5448
5449                         // RESTRICTIONS
5450                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5451                         {
5452                             foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5453                             {
5454                                 $restriction_relationship = null;
5455                                 $restriction_type = null;
5456                                 $restriction_value = null;
5457                                 if (isset($restriction['attribs']['']['relationship']))
5458                                 {
5459                                     $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5460                                 }
5461                                 if (isset($restriction['attribs']['']['type']))
5462                                 {
5463                                     $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5464                                 }
5465                                 if (isset($restriction['data']))
5466                                 {
5467                                     $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5468                                 }
f64c86 5469                                 $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
fd9ef2 5470                             }
T 5471                             if (is_array($restrictions))
5472                             {
5473                                 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5474                             }
5475                         }
5476                         else
5477                         {
5478                             $restrictions = $restrictions_parent;
5479                         }
5480
5481                         // THUMBNAILS
5482                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5483                         {
5484                             foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5485                             {
5486                                 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5487                             }
5488                             if (is_array($thumbnails))
5489                             {
5490                                 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5491                             }
5492                         }
5493                         else
5494                         {
5495                             $thumbnails = $thumbnails_parent;
5496                         }
5497
5498                         // TITLES
5499                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5500                         {
5501                             $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5502                         }
5503                         else
5504                         {
5505                             $title = $title_parent;
5506                         }
5507
f64c86 5508                         $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
fd9ef2 5509                     }
T 5510                 }
5511             }
5512
5513             foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
5514             {
5515                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5516                 {
5517                     // Attributes
5518                     $bitrate = null;
5519                     $channels = null;
5520                     $duration = null;
5521                     $expression = null;
5522                     $framerate = null;
5523                     $height = null;
5524                     $javascript = null;
5525                     $lang = null;
5526                     $length = null;
5527                     $medium = null;
5528                     $samplingrate = null;
5529                     $type = null;
5530                     $url = null;
5531                     $width = null;
5532
5533                     $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5534                     if (isset($link['attribs']['']['type']))
5535                     {
5536                         $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5537                     }
5538                     if (isset($link['attribs']['']['length']))
5539                     {
5540                         $length = ceil($link['attribs']['']['length']);
5541                     }
5542
5543                     // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
f64c86 5544                     $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
fd9ef2 5545                 }
T 5546             }
5547
5548             foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5549             {
5550                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5551                 {
5552                     // Attributes
5553                     $bitrate = null;
5554                     $channels = null;
5555                     $duration = null;
5556                     $expression = null;
5557                     $framerate = null;
5558                     $height = null;
5559                     $javascript = null;
5560                     $lang = null;
5561                     $length = null;
5562                     $medium = null;
5563                     $samplingrate = null;
5564                     $type = null;
5565                     $url = null;
5566                     $width = null;
5567
5568                     $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5569                     if (isset($link['attribs']['']['type']))
5570                     {
5571                         $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5572                     }
5573                     if (isset($link['attribs']['']['length']))
5574                     {
5575                         $length = ceil($link['attribs']['']['length']);
5576                     }
5577
5578                     // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
f64c86 5579                     $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
fd9ef2 5580                 }
T 5581             }
5582
5583             if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
5584             {
5585                 if (isset($enclosure[0]['attribs']['']['url']))
5586                 {
5587                     // Attributes
5588                     $bitrate = null;
5589                     $channels = null;
5590                     $duration = null;
5591                     $expression = null;
5592                     $framerate = null;
5593                     $height = null;
5594                     $javascript = null;
5595                     $lang = null;
5596                     $length = null;
5597                     $medium = null;
5598                     $samplingrate = null;
5599                     $type = null;
5600                     $url = null;
5601                     $width = null;
5602
5603                     $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5604                     if (isset($enclosure[0]['attribs']['']['type']))
5605                     {
5606                         $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5607                     }
5608                     if (isset($enclosure[0]['attribs']['']['length']))
5609                     {
5610                         $length = ceil($enclosure[0]['attribs']['']['length']);
5611                     }
5612
5613                     // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
f64c86 5614                     $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
fd9ef2 5615                 }
T 5616             }
5617
5618             if (sizeof($this->data['enclosures']) === 0 && ($url || $type || $length || $bitrate || $captions_parent || $categories_parent || $channels || $copyrights_parent || $credits_parent || $description_parent || $duration_parent || $expression || $framerate || $hashes_parent || $height || $keywords_parent || $lang || $medium || $player_parent || $ratings_parent || $restrictions_parent || $samplingrate || $thumbnails_parent || $title_parent || $width))
5619             {
5620                 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
f64c86 5621                 $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
fd9ef2 5622             }
T 5623
5624             $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5625         }
5626         if (!empty($this->data['enclosures']))
5627         {
5628             return $this->data['enclosures'];
5629         }
5630         else
5631         {
5632             return null;
5633         }
5634     }
5635
5636     function get_latitude()
5637     {
5638         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5639         {
5640             return (float) $return[0]['data'];
5641         }
5642         elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
5643         {
5644             return (float) $match[1];
5645         }
5646         else
5647         {
5648             return null;
5649         }
5650     }
5651
5652     function get_longitude()
5653     {
5654         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5655         {
5656             return (float) $return[0]['data'];
5657         }
5658         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5659         {
5660             return (float) $return[0]['data'];
5661         }
5662         elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
5663         {
5664             return (float) $match[2];
5665         }
5666         else
5667         {
5668             return null;
5669         }
5670     }
5671
5672     function get_source()
5673     {
5674         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5675         {
5676             return new $this->feed->source_class($this, $return[0]);
5677         }
5678         else
5679         {
5680             return null;
5681         }
5682     }
5683
b1a6a5 5684
fd9ef2 5685     /**
T 5686      * Creates the add_to_* methods' return data
5687      *
5688      * @access private
5689      * @param string $item_url String to prefix to the item permalink
5690      * @param string $title_url String to prefix to the item title
5691      * (and suffix to the item permalink)
5692      * @return mixed URL if feed exists, false otherwise
5693      */
5694     function add_to_service($item_url, $title_url = null, $summary_url = null)
5695     {
5696         if ($this->get_permalink() !== null)
5697         {
5698             $return = $item_url . rawurlencode($this->get_permalink());
5699             if ($title_url !== null && $this->get_title() !== null)
5700             {
5701                 $return .= $title_url . rawurlencode($this->get_title());
5702             }
5703             if ($summary_url !== null && $this->get_description() !== null)
5704             {
5705                 $return .= $summary_url . rawurlencode($this->get_description());
5706             }
5707             return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
5708         }
5709         else
5710         {
5711             return null;
5712         }
5713     }
5714
5715     function add_to_blinklist()
5716     {
5717         return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5718     }
5719
5720     function add_to_blogmarks()
5721     {
5722         return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5723     }
5724
5725     function add_to_delicious()
5726     {
5727         return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
5728     }
5729
5730     function add_to_digg()
5731     {
5732         return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
5733     }
5734
5735     function add_to_furl()
5736     {
5737         return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5738     }
5739
5740     function add_to_magnolia()
5741     {
5742         return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5743     }
5744
5745     function add_to_myweb20()
5746     {
5747         return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5748     }
5749
5750     function add_to_newsvine()
5751     {
5752         return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5753     }
5754
5755     function add_to_reddit()
5756     {
5757         return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5758     }
5759
5760     function add_to_segnalo()
5761     {
5762         return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5763     }
5764
5765     function add_to_simpy()
5766     {
5767         return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5768     }
5769
5770     function add_to_spurl()
5771     {
5772         return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5773     }
5774
5775     function add_to_wists()
5776     {
5777         return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5778     }
5779
5780     function search_technorati()
5781     {
5782         return $this->add_to_service('http://www.technorati.com/search/');
5783     }
b1a6a5 5784
fd9ef2 5785 }
T 5786
5787 class SimplePie_Source
5788 {
5789     var $item;
5790     var $data = array();
5791
5792     function SimplePie_Source($item, $data)
5793     {
5794         $this->item = $item;
5795         $this->data = $data;
5796     }
5797
5798     function __toString()
5799     {
5800         return md5(serialize($this->data));
5801     }
5802
5803     function get_source_tags($namespace, $tag)
5804     {
5805         if (isset($this->data['child'][$namespace][$tag]))
5806         {
5807             return $this->data['child'][$namespace][$tag];
5808         }
5809         else
5810         {
5811             return null;
5812         }
5813     }
5814
5815     function get_base($element = array())
5816     {
5817         return $this->item->get_base($element);
5818     }
5819
5820     function sanitize($data, $type, $base = '')
5821     {
5822         return $this->item->sanitize($data, $type, $base);
5823     }
5824
5825     function get_item()
5826     {
5827         return $this->item;
5828     }
5829
5830     function get_title()
5831     {
5832         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5833         {
5834             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5835         }
5836         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5837         {
5838             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5839         }
5840         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5841         {
5842             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5843         }
5844         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5845         {
5846             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5847         }
5848         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
5849         {
5850             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5851         }
5852         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5853         {
5854             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5855         }
5856         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5857         {
5858             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5859         }
5860         else
5861         {
5862             return null;
5863         }
5864     }
5865
5866     function get_category($key = 0)
5867     {
5868         $categories = $this->get_categories();
5869         if (isset($categories[$key]))
5870         {
5871             return $categories[$key];
5872         }
5873         else
5874         {
5875             return null;
5876         }
5877     }
5878
5879     function get_categories()
5880     {
5881         $categories = array();
5882
5883         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5884         {
5885             $term = null;
5886             $scheme = null;
5887             $label = null;
5888             if (isset($category['attribs']['']['term']))
5889             {
5890                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5891             }
5892             if (isset($category['attribs']['']['scheme']))
5893             {
5894                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5895             }
5896             if (isset($category['attribs']['']['label']))
5897             {
5898                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5899             }
f64c86 5900             $categories[] = new $this->item->feed->category_class($term, $scheme, $label);
fd9ef2 5901         }
T 5902         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
5903         {
5904             // This is really the label, but keep this as the term also for BC.
5905             // Label will also work on retrieving because that falls back to term.
5906             $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5907             if (isset($category['attribs']['']['domain']))
5908             {
5909                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
5910             }
5911             else
5912             {
5913                 $scheme = null;
5914             }
f64c86 5915             $categories[] = new $this->item->feed->category_class($term, $scheme, null);
fd9ef2 5916         }
T 5917         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5918         {
f64c86 5919             $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 5920         }
T 5921         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5922         {
f64c86 5923             $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 5924         }
T 5925
5926         if (!empty($categories))
5927         {
5928             return SimplePie_Misc::array_unique($categories);
5929         }
5930         else
5931         {
5932             return null;
5933         }
5934     }
5935
5936     function get_author($key = 0)
5937     {
5938         $authors = $this->get_authors();
5939         if (isset($authors[$key]))
5940         {
5941             return $authors[$key];
5942         }
5943         else
5944         {
5945             return null;
5946         }
5947     }
5948
5949     function get_authors()
5950     {
5951         $authors = array();
5952         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5953         {
5954             $name = null;
5955             $uri = null;
5956             $email = null;
5957             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5958             {
5959                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5960             }
5961             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5962             {
5963                 $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]));
5964             }
5965             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5966             {
5967                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5968             }
5969             if ($name !== null || $email !== null || $uri !== null)
5970             {
f64c86 5971                 $authors[] = new $this->item->feed->author_class($name, $uri, $email);
fd9ef2 5972             }
T 5973         }
5974         if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5975         {
5976             $name = null;
5977             $url = null;
5978             $email = null;
5979             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5980             {
5981                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5982             }
5983             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5984             {
5985                 $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]));
5986             }
5987             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5988             {
5989                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5990             }
5991             if ($name !== null || $email !== null || $url !== null)
5992             {
f64c86 5993                 $authors[] = new $this->item->feed->author_class($name, $url, $email);
fd9ef2 5994             }
T 5995         }
5996         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
5997         {
f64c86 5998             $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 5999         }
T 6000         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
6001         {
f64c86 6002             $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 6003         }
T 6004         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
6005         {
f64c86 6006             $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 6007         }
T 6008
6009         if (!empty($authors))
6010         {
6011             return SimplePie_Misc::array_unique($authors);
6012         }
6013         else
6014         {
6015             return null;
6016         }
6017     }
6018
6019     function get_contributor($key = 0)
6020     {
6021         $contributors = $this->get_contributors();
6022         if (isset($contributors[$key]))
6023         {
6024             return $contributors[$key];
6025         }
6026         else
6027         {
6028             return null;
6029         }
6030     }
6031
6032     function get_contributors()
6033     {
6034         $contributors = array();
6035         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
6036         {
6037             $name = null;
6038             $uri = null;
6039             $email = null;
6040             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
6041             {
6042                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6043             }
6044             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
6045             {
6046                 $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]));
6047             }
6048             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
6049             {
6050                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6051             }
6052             if ($name !== null || $email !== null || $uri !== null)
6053             {
f64c86 6054                 $contributors[] = new $this->item->feed->author_class($name, $uri, $email);
fd9ef2 6055             }
T 6056         }
6057         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
6058         {
6059             $name = null;
6060             $url = null;
6061             $email = null;
6062             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
6063             {
6064                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6065             }
6066             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
6067             {
6068                 $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]));
6069             }
6070             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6071             {
6072                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6073             }
6074             if ($name !== null || $email !== null || $url !== null)
6075             {
f64c86 6076                 $contributors[] = new $this->item->feed->author_class($name, $url, $email);
fd9ef2 6077             }
T 6078         }
6079
6080         if (!empty($contributors))
6081         {
6082             return SimplePie_Misc::array_unique($contributors);
6083         }
6084         else
6085         {
6086             return null;
6087         }
6088     }
6089
6090     function get_link($key = 0, $rel = 'alternate')
6091     {
6092         $links = $this->get_links($rel);
6093         if (isset($links[$key]))
6094         {
6095             return $links[$key];
6096         }
6097         else
6098         {
6099             return null;
6100         }
6101     }
6102
b1a6a5 6103
fd9ef2 6104     /**
T 6105      * Added for parity between the parent-level and the item/entry-level.
6106      */
6107     function get_permalink()
6108     {
6109         return $this->get_link(0);
6110     }
6111
6112     function get_links($rel = 'alternate')
6113     {
6114         if (!isset($this->data['links']))
6115         {
6116             $this->data['links'] = array();
6117             if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
6118             {
6119                 foreach ($links as $link)
6120                 {
6121                     if (isset($link['attribs']['']['href']))
6122                     {
6123                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6124                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6125                     }
6126                 }
6127             }
6128             if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
6129             {
6130                 foreach ($links as $link)
6131                 {
6132                     if (isset($link['attribs']['']['href']))
6133                     {
6134                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6135                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6136
6137                     }
6138                 }
6139             }
6140             if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
6141             {
6142                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6143             }
6144             if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
6145             {
6146                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6147             }
6148             if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
6149             {
6150                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6151             }
6152
6153             $keys = array_keys($this->data['links']);
6154             foreach ($keys as $key)
6155             {
6156                 if (SimplePie_Misc::is_isegment_nz_nc($key))
6157                 {
6158                     if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
6159                     {
6160                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
6161                         $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
6162                     }
6163                     else
6164                     {
6165                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
6166                     }
6167                 }
6168                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
6169                 {
6170                     $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
6171                 }
6172                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
6173             }
6174         }
6175
6176         if (isset($this->data['links'][$rel]))
6177         {
6178             return $this->data['links'][$rel];
6179         }
6180         else
6181         {
6182             return null;
6183         }
6184     }
6185
6186     function get_description()
6187     {
6188         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
6189         {
6190             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6191         }
6192         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
6193         {
6194             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6195         }
6196         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
6197         {
6198             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6199         }
6200         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
6201         {
6202             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6203         }
6204         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
6205         {
6206             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6207         }
6208         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
6209         {
6210             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6211         }
6212         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
6213         {
6214             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6215         }
6216         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
6217         {
6218             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6219         }
6220         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
6221         {
6222             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6223         }
6224         else
6225         {
6226             return null;
6227         }
6228     }
6229
6230     function get_copyright()
6231     {
6232         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
6233         {
6234             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6235         }
6236         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
6237         {
6238             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6239         }
6240         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
6241         {
6242             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6243         }
6244         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
6245         {
6246             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6247         }
6248         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
6249         {
6250             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6251         }
6252         else
6253         {
6254             return null;
6255         }
6256     }
6257
6258     function get_language()
6259     {
6260         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
6261         {
6262             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6263         }
6264         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
6265         {
6266             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6267         }
6268         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
6269         {
6270             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6271         }
6272         elseif (isset($this->data['xml_lang']))
6273         {
6274             return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
6275         }
6276         else
6277         {
6278             return null;
6279         }
6280     }
6281
6282     function get_latitude()
6283     {
6284         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
6285         {
6286             return (float) $return[0]['data'];
6287         }
6288         elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
6289         {
6290             return (float) $match[1];
6291         }
6292         else
6293         {
6294             return null;
6295         }
6296     }
6297
6298     function get_longitude()
6299     {
6300         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
6301         {
6302             return (float) $return[0]['data'];
6303         }
6304         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
6305         {
6306             return (float) $return[0]['data'];
6307         }
6308         elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
6309         {
6310             return (float) $match[2];
6311         }
6312         else
6313         {
6314             return null;
6315         }
6316     }
6317
6318     function get_image_url()
6319     {
6320         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
6321         {
6322             return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
6323         }
6324         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
6325         {
6326             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6327         }
6328         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
6329         {
6330             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6331         }
6332         else
6333         {
6334             return null;
6335         }
6336     }
b1a6a5 6337
fd9ef2 6338 }
T 6339
6340 class SimplePie_Author
6341 {
6342     var $name;
6343     var $link;
6344     var $email;
6345
6346     // Constructor, used to input the data
6347     function SimplePie_Author($name = null, $link = null, $email = null)
6348     {
6349         $this->name = $name;
6350         $this->link = $link;
6351         $this->email = $email;
6352     }
6353
6354     function __toString()
6355     {
6356         // There is no $this->data here
6357         return md5(serialize($this));
6358     }
6359
6360     function get_name()
6361     {
6362         if ($this->name !== null)
6363         {
6364             return $this->name;
6365         }
6366         else
6367         {
6368             return null;
6369         }
6370     }
6371
6372     function get_link()
6373     {
6374         if ($this->link !== null)
6375         {
6376             return $this->link;
6377         }
6378         else
6379         {
6380             return null;
6381         }
6382     }
6383
6384     function get_email()
6385     {
6386         if ($this->email !== null)
6387         {
6388             return $this->email;
6389         }
6390         else
6391         {
6392             return null;
6393         }
6394     }
b1a6a5 6395
fd9ef2 6396 }
T 6397
6398 class SimplePie_Category
6399 {
6400     var $term;
6401     var $scheme;
6402     var $label;
6403
6404     // Constructor, used to input the data
6405     function SimplePie_Category($term = null, $scheme = null, $label = null)
6406     {
6407         $this->term = $term;
6408         $this->scheme = $scheme;
6409         $this->label = $label;
6410     }
6411
6412     function __toString()
6413     {
6414         // There is no $this->data here
6415         return md5(serialize($this));
6416     }
6417
6418     function get_term()
6419     {
6420         if ($this->term !== null)
6421         {
6422             return $this->term;
6423         }
6424         else
6425         {
6426             return null;
6427         }
6428     }
6429
6430     function get_scheme()
6431     {
6432         if ($this->scheme !== null)
6433         {
6434             return $this->scheme;
6435         }
6436         else
6437         {
6438             return null;
6439         }
6440     }
6441
6442     function get_label()
6443     {
6444         if ($this->label !== null)
6445         {
6446             return $this->label;
6447         }
6448         else
6449         {
6450             return $this->get_term();
6451         }
6452     }
b1a6a5 6453
fd9ef2 6454 }
T 6455
6456 class SimplePie_Enclosure
6457 {
6458     var $bitrate;
6459     var $captions;
6460     var $categories;
6461     var $channels;
6462     var $copyright;
6463     var $credits;
6464     var $description;
6465     var $duration;
6466     var $expression;
6467     var $framerate;
6468     var $handler;
6469     var $hashes;
6470     var $height;
6471     var $javascript;
6472     var $keywords;
6473     var $lang;
6474     var $length;
6475     var $link;
6476     var $medium;
6477     var $player;
6478     var $ratings;
6479     var $restrictions;
6480     var $samplingrate;
6481     var $thumbnails;
6482     var $title;
6483     var $type;
6484     var $width;
6485
6486     // Constructor, used to input the data
6487     function SimplePie_Enclosure($link = null, $type = null, $length = null, $javascript = null, $bitrate = null, $captions = null, $categories = null, $channels = null, $copyright = null, $credits = null, $description = null, $duration = null, $expression = null, $framerate = null, $hashes = null, $height = null, $keywords = null, $lang = null, $medium = null, $player = null, $ratings = null, $restrictions = null, $samplingrate = null, $thumbnails = null, $title = null, $width = null)
6488     {
6489         $this->bitrate = $bitrate;
6490         $this->captions = $captions;
6491         $this->categories = $categories;
6492         $this->channels = $channels;
6493         $this->copyright = $copyright;
6494         $this->credits = $credits;
6495         $this->description = $description;
6496         $this->duration = $duration;
6497         $this->expression = $expression;
6498         $this->framerate = $framerate;
6499         $this->hashes = $hashes;
6500         $this->height = $height;
6501         $this->javascript = $javascript;
6502         $this->keywords = $keywords;
6503         $this->lang = $lang;
6504         $this->length = $length;
6505         $this->link = $link;
6506         $this->medium = $medium;
6507         $this->player = $player;
6508         $this->ratings = $ratings;
6509         $this->restrictions = $restrictions;
6510         $this->samplingrate = $samplingrate;
6511         $this->thumbnails = $thumbnails;
6512         $this->title = $title;
6513         $this->type = $type;
6514         $this->width = $width;
6515         if (class_exists('idna_convert'))
6516         {
f64c86 6517             $idn = new idna_convert;
fd9ef2 6518             $parsed = SimplePie_Misc::parse_url($link);
T 6519             $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6520         }
6521         $this->handler = $this->get_handler(); // Needs to load last
6522     }
6523
6524     function __toString()
6525     {
6526         // There is no $this->data here
6527         return md5(serialize($this));
6528     }
6529
6530     function get_bitrate()
6531     {
6532         if ($this->bitrate !== null)
6533         {
6534             return $this->bitrate;
6535         }
6536         else
6537         {
6538             return null;
6539         }
6540     }
6541
6542     function get_caption($key = 0)
6543     {
6544         $captions = $this->get_captions();
6545         if (isset($captions[$key]))
6546         {
6547             return $captions[$key];
6548         }
6549         else
6550         {
6551             return null;
6552         }
6553     }
6554
6555     function get_captions()
6556     {
6557         if ($this->captions !== null)
6558         {
6559             return $this->captions;
6560         }
6561         else
6562         {
6563             return null;
6564         }
6565     }
6566
6567     function get_category($key = 0)
6568     {
6569         $categories = $this->get_categories();
6570         if (isset($categories[$key]))
6571         {
6572             return $categories[$key];
6573         }
6574         else
6575         {
6576             return null;
6577         }
6578     }
6579
6580     function get_categories()
6581     {
6582         if ($this->categories !== null)
6583         {
6584             return $this->categories;
6585         }
6586         else
6587         {
6588             return null;
6589         }
6590     }
6591
6592     function get_channels()
6593     {
6594         if ($this->channels !== null)
6595         {
6596             return $this->channels;
6597         }
6598         else
6599         {
6600             return null;
6601         }
6602     }
6603
6604     function get_copyright()
6605     {
6606         if ($this->copyright !== null)
6607         {
6608             return $this->copyright;
6609         }
6610         else
6611         {
6612             return null;
6613         }
6614     }
6615
6616     function get_credit($key = 0)
6617     {
6618         $credits = $this->get_credits();
6619         if (isset($credits[$key]))
6620         {
6621             return $credits[$key];
6622         }
6623         else
6624         {
6625             return null;
6626         }
6627     }
6628
6629     function get_credits()
6630     {
6631         if ($this->credits !== null)
6632         {
6633             return $this->credits;
6634         }
6635         else
6636         {
6637             return null;
6638         }
6639     }
6640
6641     function get_description()
6642     {
6643         if ($this->description !== null)
6644         {
6645             return $this->description;
6646         }
6647         else
6648         {
6649             return null;
6650         }
6651     }
6652
6653     function get_duration($convert = false)
6654     {
6655         if ($this->duration !== null)
6656         {
6657             if ($convert)
6658             {
6659                 $time = SimplePie_Misc::time_hms($this->duration);
6660                 return $time;
6661             }
6662             else
6663             {
6664                 return $this->duration;
6665             }
6666         }
6667         else
6668         {
6669             return null;
6670         }
6671     }
6672
6673     function get_expression()
6674     {
6675         if ($this->expression !== null)
6676         {
6677             return $this->expression;
6678         }
6679         else
6680         {
6681             return 'full';
6682         }
6683     }
6684
6685     function get_extension()
6686     {
6687         if ($this->link !== null)
6688         {
6689             $url = SimplePie_Misc::parse_url($this->link);
6690             if ($url['path'] !== '')
6691             {
6692                 return pathinfo($url['path'], PATHINFO_EXTENSION);
6693             }
6694         }
6695         return null;
6696     }
6697
6698     function get_framerate()
6699     {
6700         if ($this->framerate !== null)
6701         {
6702             return $this->framerate;
6703         }
6704         else
6705         {
6706             return null;
6707         }
6708     }
6709
6710     function get_handler()
6711     {
6712         return $this->get_real_type(true);
6713     }
6714
6715     function get_hash($key = 0)
6716     {
6717         $hashes = $this->get_hashes();
6718         if (isset($hashes[$key]))
6719         {
6720             return $hashes[$key];
6721         }
6722         else
6723         {
6724             return null;
6725         }
6726     }
6727
6728     function get_hashes()
6729     {
6730         if ($this->hashes !== null)
6731         {
6732             return $this->hashes;
6733         }
6734         else
6735         {
6736             return null;
6737         }
6738     }
6739
6740     function get_height()
6741     {
6742         if ($this->height !== null)
6743         {
6744             return $this->height;
6745         }
6746         else
6747         {
6748             return null;
6749         }
6750     }
6751
6752     function get_language()
6753     {
6754         if ($this->lang !== null)
6755         {
6756             return $this->lang;
6757         }
6758         else
6759         {
6760             return null;
6761         }
6762     }
6763
6764     function get_keyword($key = 0)
6765     {
6766         $keywords = $this->get_keywords();
6767         if (isset($keywords[$key]))
6768         {
6769             return $keywords[$key];
6770         }
6771         else
6772         {
6773             return null;
6774         }
6775     }
6776
6777     function get_keywords()
6778     {
6779         if ($this->keywords !== null)
6780         {
6781             return $this->keywords;
6782         }
6783         else
6784         {
6785             return null;
6786         }
6787     }
6788
6789     function get_length()
6790     {
6791         if ($this->length !== null)
6792         {
6793             return $this->length;
6794         }
6795         else
6796         {
6797             return null;
6798         }
6799     }
6800
6801     function get_link()
6802     {
6803         if ($this->link !== null)
6804         {
6805             return urldecode($this->link);
6806         }
6807         else
6808         {
6809             return null;
6810         }
6811     }
6812
6813     function get_medium()
6814     {
6815         if ($this->medium !== null)
6816         {
6817             return $this->medium;
6818         }
6819         else
6820         {
6821             return null;
6822         }
6823     }
6824
6825     function get_player()
6826     {
6827         if ($this->player !== null)
6828         {
6829             return $this->player;
6830         }
6831         else
6832         {
6833             return null;
6834         }
6835     }
6836
6837     function get_rating($key = 0)
6838     {
6839         $ratings = $this->get_ratings();
6840         if (isset($ratings[$key]))
6841         {
6842             return $ratings[$key];
6843         }
6844         else
6845         {
6846             return null;
6847         }
6848     }
6849
6850     function get_ratings()
6851     {
6852         if ($this->ratings !== null)
6853         {
6854             return $this->ratings;
6855         }
6856         else
6857         {
6858             return null;
6859         }
6860     }
6861
6862     function get_restriction($key = 0)
6863     {
6864         $restrictions = $this->get_restrictions();
6865         if (isset($restrictions[$key]))
6866         {
6867             return $restrictions[$key];
6868         }
6869         else
6870         {
6871             return null;
6872         }
6873     }
6874
6875     function get_restrictions()
6876     {
6877         if ($this->restrictions !== null)
6878         {
6879             return $this->restrictions;
6880         }
6881         else
6882         {
6883             return null;
6884         }
6885     }
6886
6887     function get_sampling_rate()
6888     {
6889         if ($this->samplingrate !== null)
6890         {
6891             return $this->samplingrate;
6892         }
6893         else
6894         {
6895             return null;
6896         }
6897     }
6898
6899     function get_size()
6900     {
6901         $length = $this->get_length();
6902         if ($length !== null)
6903         {
6904             return round($length/1048576, 2);
6905         }
6906         else
6907         {
6908             return null;
6909         }
6910     }
6911
6912     function get_thumbnail($key = 0)
6913     {
6914         $thumbnails = $this->get_thumbnails();
6915         if (isset($thumbnails[$key]))
6916         {
6917             return $thumbnails[$key];
6918         }
6919         else
6920         {
6921             return null;
6922         }
6923     }
6924
6925     function get_thumbnails()
6926     {
6927         if ($this->thumbnails !== null)
6928         {
6929             return $this->thumbnails;
6930         }
6931         else
6932         {
6933             return null;
6934         }
6935     }
6936
6937     function get_title()
6938     {
6939         if ($this->title !== null)
6940         {
6941             return $this->title;
6942         }
6943         else
6944         {
6945             return null;
6946         }
6947     }
6948
6949     function get_type()
6950     {
6951         if ($this->type !== null)
6952         {
6953             return $this->type;
6954         }
6955         else
6956         {
6957             return null;
6958         }
6959     }
6960
6961     function get_width()
6962     {
6963         if ($this->width !== null)
6964         {
6965             return $this->width;
6966         }
6967         else
6968         {
6969             return null;
6970         }
6971     }
6972
6973     function native_embed($options='')
6974     {
6975         return $this->embed($options, true);
6976     }
6977
b1a6a5 6978
fd9ef2 6979     /**
T 6980      * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
6981      */
6982     function embed($options = '', $native = false)
6983     {
6984         // Set up defaults
6985         $audio = '';
6986         $video = '';
6987         $alt = '';
6988         $altclass = '';
6989         $loop = 'false';
6990         $width = 'auto';
6991         $height = 'auto';
6992         $bgcolor = '#ffffff';
6993         $mediaplayer = '';
6994         $widescreen = false;
6995         $handler = $this->get_handler();
6996         $type = $this->get_real_type();
6997
6998         // Process options and reassign values as necessary
6999         if (is_array($options))
7000         {
7001             extract($options);
7002         }
7003         else
7004         {
7005             $options = explode(',', $options);
7006             foreach($options as $option)
7007             {
7008                 $opt = explode(':', $option, 2);
7009                 if (isset($opt[0], $opt[1]))
7010                 {
7011                     $opt[0] = trim($opt[0]);
7012                     $opt[1] = trim($opt[1]);
7013                     switch ($opt[0])
7014                     {
b1a6a5 7015                     case 'audio':
MC 7016                         $audio = $opt[1];
7017                         break;
fd9ef2 7018
b1a6a5 7019                     case 'video':
MC 7020                         $video = $opt[1];
7021                         break;
fd9ef2 7022
b1a6a5 7023                     case 'alt':
MC 7024                         $alt = $opt[1];
7025                         break;
fd9ef2 7026
b1a6a5 7027                     case 'altclass':
MC 7028                         $altclass = $opt[1];
7029                         break;
fd9ef2 7030
b1a6a5 7031                     case 'loop':
MC 7032                         $loop = $opt[1];
7033                         break;
fd9ef2 7034
b1a6a5 7035                     case 'width':
MC 7036                         $width = $opt[1];
7037                         break;
fd9ef2 7038
b1a6a5 7039                     case 'height':
MC 7040                         $height = $opt[1];
7041                         break;
fd9ef2 7042
b1a6a5 7043                     case 'bgcolor':
MC 7044                         $bgcolor = $opt[1];
7045                         break;
fd9ef2 7046
b1a6a5 7047                     case 'mediaplayer':
MC 7048                         $mediaplayer = $opt[1];
7049                         break;
fd9ef2 7050
b1a6a5 7051                     case 'widescreen':
MC 7052                         $widescreen = $opt[1];
7053                         break;
fd9ef2 7054                     }
T 7055                 }
7056             }
7057         }
7058
7059         $mime = explode('/', $type, 2);
7060         $mime = $mime[0];
7061
7062         // Process values for 'auto'
7063         if ($width === 'auto')
7064         {
7065             if ($mime === 'video')
7066             {
7067                 if ($height === 'auto')
7068                 {
7069                     $width = 480;
7070                 }
7071                 elseif ($widescreen)
7072                 {
7073                     $width = round((intval($height)/9)*16);
7074                 }
7075                 else
7076                 {
7077                     $width = round((intval($height)/3)*4);
7078                 }
7079             }
7080             else
7081             {
7082                 $width = '100%';
7083             }
7084         }
7085
7086         if ($height === 'auto')
7087         {
7088             if ($mime === 'audio')
7089             {
7090                 $height = 0;
7091             }
7092             elseif ($mime === 'video')
7093             {
7094                 if ($width === 'auto')
7095                 {
7096                     if ($widescreen)
7097                     {
7098                         $height = 270;
7099                     }
7100                     else
7101                     {
7102                         $height = 360;
7103                     }
7104                 }
7105                 elseif ($widescreen)
7106                 {
7107                     $height = round((intval($width)/16)*9);
7108                 }
7109                 else
7110                 {
7111                     $height = round((intval($width)/4)*3);
7112                 }
7113             }
7114             else
7115             {
7116                 $height = 376;
7117             }
7118         }
7119         elseif ($mime === 'audio')
7120         {
7121             $height = 0;
7122         }
7123
7124         // Set proper placeholder value
7125         if ($mime === 'audio')
7126         {
7127             $placeholder = $audio;
7128         }
7129         elseif ($mime === 'video')
7130         {
7131             $placeholder = $video;
7132         }
7133
7134         $embed = '';
7135
7136         // Make sure the JS library is included
7137         if (!$native)
7138         {
7139             static $javascript_outputted = null;
7140             if (!$javascript_outputted && $this->javascript)
7141             {
7142                 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
7143                 $javascript_outputted = true;
7144             }
7145         }
7146
7147         // Odeo Feed MP3's
7148         if ($handler === 'odeo')
7149         {
7150             if ($native)
7151             {
7152                 $embed .= '<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://adobe.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url=' . $this->get_link() . '"></embed>';
7153             }
7154             else
7155             {
7156                 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
7157             }
7158         }
7159
7160         // Flash
7161         elseif ($handler === 'flash')
7162         {
7163             if ($native)
7164             {
7165                 $embed .= "<embed src=\"" . $this->get_link() . "\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"$type\" quality=\"high\" width=\"$width\" height=\"$height\" bgcolor=\"$bgcolor\" loop=\"$loop\"></embed>";
7166             }
7167             else
7168             {
7169                 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
7170             }
7171         }
7172
7173         // Flash Media Player file types.
7174         // Preferred handler for MP3 file types.
7175         elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
7176         {
7177             $height += 20;
7178             if ($native)
7179             {
7180                 $embed .= "<embed src=\"$mediaplayer\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" quality=\"high\" width=\"$width\" height=\"$height\" wmode=\"transparent\" flashvars=\"file=" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "&autostart=false&repeat=$loop&showdigits=true&showfsbutton=false\"></embed>";
7181             }
7182             else
7183             {
7184                 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7185             }
7186         }
7187
7188         // QuickTime 7 file types.  Need to test with QuickTime 6.
7189         // Only handle MP3's if the Flash Media Player is not present.
7190         elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
7191         {
7192             $height += 16;
7193             if ($native)
7194             {
7195                 if ($placeholder !== '')
7196                 {
7197                     $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" href=\"" . $this->get_link() . "\" src=\"$placeholder\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"false\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
7198                 }
7199                 else
7200                 {
7201                     $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" src=\"" . $this->get_link() . "\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"true\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
7202                 }
7203             }
7204             else
7205             {
7206                 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7207             }
7208         }
7209
7210         // Windows Media
7211         elseif ($handler === 'wmedia')
7212         {
7213             $height += 45;
7214             if ($native)
7215             {
7216                 $embed .= "<embed type=\"application/x-mplayer2\" src=\"" . $this->get_link() . "\" autosize=\"1\" width=\"$width\" height=\"$height\" showcontrols=\"1\" showstatusbar=\"0\" showdisplay=\"0\" autostart=\"0\"></embed>";
7217             }
7218             else
7219             {
7220                 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7221             }
7222         }
7223
7224         // Everything else
7225         else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7226
7227         return $embed;
7228     }
7229
7230     function get_real_type($find_handler = false)
7231     {
7232         // If it's Odeo, let's get it out of the way.
7233         if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
7234         {
7235             return 'odeo';
7236         }
7237
7238         // Mime-types by handler.
7239         $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
b1a6a5 7240         $types_fmedia = array('video/flv', 'video/x-flv', 'flv-application/octet-stream'); // Flash Media Player
fd9ef2 7241         $types_quicktime = array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video'); // QuickTime
T 7242         $types_wmedia = array('application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx'); // Windows Media
7243         $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7244
7245         if ($this->get_type() !== null)
7246         {
7247             $type = strtolower($this->type);
7248         }
7249         else
7250         {
7251             $type = null;
7252         }
7253
7254         // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7255         if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7256         {
7257             switch (strtolower($this->get_extension()))
7258             {
7259                 // Audio mime-types
b1a6a5 7260             case 'aac':
MC 7261             case 'adts':
7262                 $type = 'audio/acc';
7263                 break;
fd9ef2 7264
b1a6a5 7265             case 'aif':
MC 7266             case 'aifc':
7267             case 'aiff':
7268             case 'cdda':
7269                 $type = 'audio/aiff';
7270                 break;
fd9ef2 7271
b1a6a5 7272             case 'bwf':
MC 7273                 $type = 'audio/wav';
7274                 break;
fd9ef2 7275
b1a6a5 7276             case 'kar':
MC 7277             case 'mid':
7278             case 'midi':
7279             case 'smf':
7280                 $type = 'audio/midi';
7281                 break;
fd9ef2 7282
b1a6a5 7283             case 'm4a':
MC 7284                 $type = 'audio/x-m4a';
7285                 break;
fd9ef2 7286
b1a6a5 7287             case 'mp3':
MC 7288             case 'swa':
7289                 $type = 'audio/mp3';
7290                 break;
fd9ef2 7291
b1a6a5 7292             case 'wav':
MC 7293                 $type = 'audio/wav';
7294                 break;
fd9ef2 7295
b1a6a5 7296             case 'wax':
MC 7297                 $type = 'audio/x-ms-wax';
7298                 break;
fd9ef2 7299
b1a6a5 7300             case 'wma':
MC 7301                 $type = 'audio/x-ms-wma';
7302                 break;
fd9ef2 7303
T 7304                 // Video mime-types
b1a6a5 7305             case '3gp':
MC 7306             case '3gpp':
7307                 $type = 'video/3gpp';
7308                 break;
fd9ef2 7309
b1a6a5 7310             case '3g2':
MC 7311             case '3gp2':
7312                 $type = 'video/3gpp2';
7313                 break;
fd9ef2 7314
b1a6a5 7315             case 'asf':
MC 7316                 $type = 'video/x-ms-asf';
7317                 break;
fd9ef2 7318
b1a6a5 7319             case 'flv':
MC 7320                 $type = 'video/x-flv';
7321                 break;
fd9ef2 7322
b1a6a5 7323             case 'm1a':
MC 7324             case 'm1s':
7325             case 'm1v':
7326             case 'm15':
7327             case 'm75':
7328             case 'mp2':
7329             case 'mpa':
7330             case 'mpeg':
7331             case 'mpg':
7332             case 'mpm':
7333             case 'mpv':
7334                 $type = 'video/mpeg';
7335                 break;
fd9ef2 7336
b1a6a5 7337             case 'm4v':
MC 7338                 $type = 'video/x-m4v';
7339                 break;
fd9ef2 7340
b1a6a5 7341             case 'mov':
MC 7342             case 'qt':
7343                 $type = 'video/quicktime';
7344                 break;
fd9ef2 7345
b1a6a5 7346             case 'mp4':
MC 7347             case 'mpg4':
7348                 $type = 'video/mp4';
7349                 break;
fd9ef2 7350
b1a6a5 7351             case 'sdv':
MC 7352                 $type = 'video/sd-video';
7353                 break;
fd9ef2 7354
b1a6a5 7355             case 'wm':
MC 7356                 $type = 'video/x-ms-wm';
7357                 break;
fd9ef2 7358
b1a6a5 7359             case 'wmv':
MC 7360                 $type = 'video/x-ms-wmv';
7361                 break;
fd9ef2 7362
b1a6a5 7363             case 'wvx':
MC 7364                 $type = 'video/x-ms-wvx';
7365                 break;
fd9ef2 7366
T 7367                 // Flash mime-types
b1a6a5 7368             case 'spl':
MC 7369                 $type = 'application/futuresplash';
7370                 break;
fd9ef2 7371
b1a6a5 7372             case 'swf':
MC 7373                 $type = 'application/x-shockwave-flash';
7374                 break;
fd9ef2 7375             }
T 7376         }
7377
7378         if ($find_handler)
7379         {
7380             if (in_array($type, $types_flash))
7381             {
7382                 return 'flash';
7383             }
7384             elseif (in_array($type, $types_fmedia))
7385             {
7386                 return 'fmedia';
7387             }
7388             elseif (in_array($type, $types_quicktime))
7389             {
7390                 return 'quicktime';
7391             }
7392             elseif (in_array($type, $types_wmedia))
7393             {
7394                 return 'wmedia';
7395             }
7396             elseif (in_array($type, $types_mp3))
7397             {
7398                 return 'mp3';
7399             }
7400             else
7401             {
7402                 return null;
7403             }
7404         }
7405         else
7406         {
7407             return $type;
7408         }
7409     }
b1a6a5 7410
fd9ef2 7411 }
T 7412
7413 class SimplePie_Caption
7414 {
7415     var $type;
7416     var $lang;
7417     var $startTime;
7418     var $endTime;
7419     var $text;
7420
7421     // Constructor, used to input the data
7422     function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7423     {
7424         $this->type = $type;
7425         $this->lang = $lang;
7426         $this->startTime = $startTime;
7427         $this->endTime = $endTime;
7428         $this->text = $text;
7429     }
7430
7431     function __toString()
7432     {
7433         // There is no $this->data here
7434         return md5(serialize($this));
7435     }
7436
7437     function get_endtime()
7438     {
7439         if ($this->endTime !== null)
7440         {
7441             return $this->endTime;
7442         }
7443         else
7444         {
7445             return null;
7446         }
7447     }
7448
7449     function get_language()
7450     {
7451         if ($this->lang !== null)
7452         {
7453             return $this->lang;
7454         }
7455         else
7456         {
7457             return null;
7458         }
7459     }
7460
7461     function get_starttime()
7462     {
7463         if ($this->startTime !== null)
7464         {
7465             return $this->startTime;
7466         }
7467         else
7468         {
7469             return null;
7470         }
7471     }
7472
7473     function get_text()
7474     {
7475         if ($this->text !== null)
7476         {
7477             return $this->text;
7478         }
7479         else
7480         {
7481             return null;
7482         }
7483     }
7484
7485     function get_type()
7486     {
7487         if ($this->type !== null)
7488         {
7489             return $this->type;
7490         }
7491         else
7492         {
7493             return null;
7494         }
7495     }
b1a6a5 7496
fd9ef2 7497 }
T 7498
7499 class SimplePie_Credit
7500 {
7501     var $role;
7502     var $scheme;
7503     var $name;
7504
7505     // Constructor, used to input the data
7506     function SimplePie_Credit($role = null, $scheme = null, $name = null)
7507     {
7508         $this->role = $role;
7509         $this->scheme = $scheme;
7510         $this->name = $name;
7511     }
7512
7513     function __toString()
7514     {
7515         // There is no $this->data here
7516         return md5(serialize($this));
7517     }
7518
7519     function get_role()
7520     {
7521         if ($this->role !== null)
7522         {
7523             return $this->role;
7524         }
7525         else
7526         {
7527             return null;
7528         }
7529     }
7530
7531     function get_scheme()
7532     {
7533         if ($this->scheme !== null)
7534         {
7535             return $this->scheme;
7536         }
7537         else
7538         {
7539             return null;
7540         }
7541     }
7542
7543     function get_name()
7544     {
7545         if ($this->name !== null)
7546         {
7547             return $this->name;
7548         }
7549         else
7550         {
7551             return null;
7552         }
7553     }
b1a6a5 7554
fd9ef2 7555 }
T 7556
7557 class SimplePie_Copyright
7558 {
7559     var $url;
7560     var $label;
7561
7562     // Constructor, used to input the data
7563     function SimplePie_Copyright($url = null, $label = null)
7564     {
7565         $this->url = $url;
7566         $this->label = $label;
7567     }
7568
7569     function __toString()
7570     {
7571         // There is no $this->data here
7572         return md5(serialize($this));
7573     }
7574
7575     function get_url()
7576     {
7577         if ($this->url !== null)
7578         {
7579             return $this->url;
7580         }
7581         else
7582         {
7583             return null;
7584         }
7585     }
7586
7587     function get_attribution()
7588     {
7589         if ($this->label !== null)
7590         {
7591             return $this->label;
7592         }
7593         else
7594         {
7595             return null;
7596         }
7597     }
b1a6a5 7598
fd9ef2 7599 }
T 7600
7601 class SimplePie_Rating
7602 {
7603     var $scheme;
7604     var $value;
7605
7606     // Constructor, used to input the data
7607     function SimplePie_Rating($scheme = null, $value = null)
7608     {
7609         $this->scheme = $scheme;
7610         $this->value = $value;
7611     }
7612
7613     function __toString()
7614     {
7615         // There is no $this->data here
7616         return md5(serialize($this));
7617     }
7618
7619     function get_scheme()
7620     {
7621         if ($this->scheme !== null)
7622         {
7623             return $this->scheme;
7624         }
7625         else
7626         {
7627             return null;
7628         }
7629     }
7630
7631     function get_value()
7632     {
7633         if ($this->value !== null)
7634         {
7635             return $this->value;
7636         }
7637         else
7638         {
7639             return null;
7640         }
7641     }
b1a6a5 7642
fd9ef2 7643 }
T 7644
7645 class SimplePie_Restriction
7646 {
7647     var $relationship;
7648     var $type;
7649     var $value;
7650
7651     // Constructor, used to input the data
7652     function SimplePie_Restriction($relationship = null, $type = null, $value = null)
7653     {
7654         $this->relationship = $relationship;
7655         $this->type = $type;
7656         $this->value = $value;
7657     }
7658
7659     function __toString()
7660     {
7661         // There is no $this->data here
7662         return md5(serialize($this));
7663     }
7664
7665     function get_relationship()
7666     {
7667         if ($this->relationship !== null)
7668         {
7669             return $this->relationship;
7670         }
7671         else
7672         {
7673             return null;
7674         }
7675     }
7676
7677     function get_type()
7678     {
7679         if ($this->type !== null)
7680         {
7681             return $this->type;
7682         }
7683         else
7684         {
7685             return null;
7686         }
7687     }
7688
7689     function get_value()
7690     {
7691         if ($this->value !== null)
7692         {
7693             return $this->value;
7694         }
7695         else
7696         {
7697             return null;
7698         }
7699     }
b1a6a5 7700
fd9ef2 7701 }
T 7702
7703 /**
7704  * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7705  */
7706 class SimplePie_File
7707 {
7708     var $url;
7709     var $useragent;
7710     var $success = true;
7711     var $headers = array();
7712     var $body;
7713     var $status_code;
7714     var $redirects = 0;
7715     var $error;
7716     var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7717
7718     function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7719     {
7720         if (class_exists('idna_convert'))
7721         {
f64c86 7722             $idn = new idna_convert;
fd9ef2 7723             $parsed = SimplePie_Misc::parse_url($url);
T 7724             $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7725         }
7726         $this->url = $url;
7727         $this->useragent = $useragent;
7728         if (preg_match('/^http(s)?:\/\//i', $url))
7729         {
7730             if ($useragent === null)
7731             {
7732                 $useragent = ini_get('user_agent');
7733                 $this->useragent = $useragent;
7734             }
7735             if (!is_array($headers))
7736             {
7737                 $headers = array();
7738             }
7739             if (!$force_fsockopen && function_exists('curl_exec'))
7740             {
7741                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7742                 $fp = curl_init();
7743                 $headers2 = array();
7744                 foreach ($headers as $key => $value)
7745                 {
7746                     $headers2[] = "$key: $value";
7747                 }
7748                 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7749                 {
7750                     curl_setopt($fp, CURLOPT_ENCODING, '');
7751                 }
7752                 curl_setopt($fp, CURLOPT_URL, $url);
7753                 curl_setopt($fp, CURLOPT_HEADER, 1);
7754                 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7755                 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7756                 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7757                 curl_setopt($fp, CURLOPT_REFERER, $url);
7758                 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7759                 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7760                 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7761                 {
7762                     curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7763                     curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7764                 }
7765
7766                 $this->headers = curl_exec($fp);
7767                 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7768                 {
7769                     curl_setopt($fp, CURLOPT_ENCODING, 'none');
7770                     $this->headers = curl_exec($fp);
7771                 }
7772                 if (curl_errno($fp))
7773                 {
7774                     $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7775                     $this->success = false;
7776                 }
7777                 else
7778                 {
7779                     $info = curl_getinfo($fp);
7780                     curl_close($fp);
7781                     $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7782                     $this->headers = array_pop($this->headers);
f64c86 7783                     $parser = new SimplePie_HTTP_Parser($this->headers);
fd9ef2 7784                     if ($parser->parse())
T 7785                     {
7786                         $this->headers = $parser->headers;
7787                         $this->body = $parser->body;
7788                         $this->status_code = $parser->status_code;
7789                         if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
7790                         {
7791                             $this->redirects++;
7792                             $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7793                             return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7794                         }
7795                     }
7796                 }
7797             }
7798             else
7799             {
7800                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7801                 $url_parts = parse_url($url);
7802                 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7803                 {
7804                     $url_parts['host'] = "ssl://$url_parts[host]";
7805                     $url_parts['port'] = 443;
7806                 }
7807                 if (!isset($url_parts['port']))
7808                 {
7809                     $url_parts['port'] = 80;
7810                 }
7811                 $fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
7812                 if (!$fp)
7813                 {
7814                     $this->error = 'fsockopen error: ' . $errstr;
7815                     $this->success = false;
7816                 }
7817                 else
7818                 {
7819                     stream_set_timeout($fp, $timeout);
7820                     if (isset($url_parts['path']))
7821                     {
7822                         if (isset($url_parts['query']))
7823                         {
7824                             $get = "$url_parts[path]?$url_parts[query]";
7825                         }
7826                         else
7827                         {
7828                             $get = $url_parts['path'];
7829                         }
7830                     }
7831                     else
7832                     {
7833                         $get = '/';
7834                     }
7835                     $out = "GET $get HTTP/1.0\r\n";
7836                     $out .= "Host: $url_parts[host]\r\n";
7837                     $out .= "User-Agent: $useragent\r\n";
7838                     if (extension_loaded('zlib'))
7839                     {
7840                         $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7841                     }
7842
7843                     if (isset($url_parts['user']) && isset($url_parts['pass']))
7844                     {
7845                         $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7846                     }
7847                     foreach ($headers as $key => $value)
7848                     {
7849                         $out .= "$key: $value\r\n";
7850                     }
7851                     $out .= "Connection: Close\r\n\r\n";
7852                     fwrite($fp, $out);
7853
7854                     $info = stream_get_meta_data($fp);
7855
7856                     $this->headers = '';
7857                     while (!$info['eof'] && !$info['timed_out'])
7858                     {
7859                         $this->headers .= fread($fp, 1160);
7860                         $info = stream_get_meta_data($fp);
7861                     }
7862                     if (!$info['timed_out'])
7863                     {
f64c86 7864                         $parser = new SimplePie_HTTP_Parser($this->headers);
fd9ef2 7865                         if ($parser->parse())
T 7866                         {
7867                             $this->headers = $parser->headers;
7868                             $this->body = $parser->body;
7869                             $this->status_code = $parser->status_code;
7870                             if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
7871                             {
7872                                 $this->redirects++;
7873                                 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7874                                 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7875                             }
7876                             if (isset($this->headers['content-encoding']))
7877                             {
7878                                 // Hey, we act dumb elsewhere, so let's do that here too
7879                                 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7880                                 {
b1a6a5 7881                                 case 'gzip':
MC 7882                                 case 'x-gzip':
7883                                     $decoder = new SimplePie_gzdecode($this->body);
7884                                     if (!$decoder->parse())
7885                                     {
7886                                         $this->error = 'Unable to decode HTTP "gzip" stream';
7887                                         $this->success = false;
7888                                     }
7889                                     else
7890                                     {
7891                                         $this->body = $decoder->data;
7892                                     }
7893                                     break;
7894
7895                                 case 'deflate':
7896                                     if (($body = gzuncompress($this->body)) === false)
7897                                     {
7898                                         if (($body = gzinflate($this->body)) === false)
fd9ef2 7899                                         {
b1a6a5 7900                                             $this->error = 'Unable to decode HTTP "deflate" stream';
fd9ef2 7901                                             $this->success = false;
T 7902                                         }
b1a6a5 7903                                     }
MC 7904                                     $this->body = $body;
7905                                     break;
fd9ef2 7906
b1a6a5 7907                                 default:
MC 7908                                     $this->error = 'Unknown content coding';
7909                                     $this->success = false;
fd9ef2 7910                                 }
T 7911                             }
7912                         }
7913                     }
7914                     else
7915                     {
7916                         $this->error = 'fsocket timed out';
7917                         $this->success = false;
7918                     }
7919                     fclose($fp);
7920                 }
7921             }
7922         }
7923         else
7924         {
7925             $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7926             if (!$this->body = file_get_contents($url))
7927             {
7928                 $this->error = 'file_get_contents could not read the file';
7929                 $this->success = false;
7930             }
7931         }
7932     }
b1a6a5 7933
fd9ef2 7934 }
T 7935
7936 /**
7937  * HTTP Response Parser
7938  *
7939  * @package SimplePie
7940  */
7941 class SimplePie_HTTP_Parser
7942 {
b1a6a5 7943
fd9ef2 7944     /**
T 7945      * HTTP Version
7946      *
7947      * @access public
7948      * @var float
7949      */
7950     var $http_version = 0.0;
7951
7952     /**
7953      * Status code
7954      *
7955      * @access public
7956      * @var int
7957      */
7958     var $status_code = 0;
7959
7960     /**
7961      * Reason phrase
7962      *
7963      * @access public
7964      * @var string
7965      */
7966     var $reason = '';
7967
7968     /**
7969      * Key/value pairs of the headers
7970      *
7971      * @access public
7972      * @var array
7973      */
7974     var $headers = array();
7975
7976     /**
7977      * Body of the response
7978      *
7979      * @access public
7980      * @var string
7981      */
7982     var $body = '';
7983
7984     /**
7985      * Current state of the state machine
7986      *
7987      * @access private
7988      * @var string
7989      */
7990     var $state = 'http_version';
7991
7992     /**
7993      * Input data
7994      *
7995      * @access private
7996      * @var string
7997      */
7998     var $data = '';
7999
8000     /**
8001      * Input data length (to avoid calling strlen() everytime this is needed)
8002      *
8003      * @access private
8004      * @var int
8005      */
8006     var $data_length = 0;
8007
8008     /**
8009      * Current position of the pointer
8010      *
8011      * @var int
8012      * @access private
8013      */
8014     var $position = 0;
8015
8016     /**
8017      * Name of the hedaer currently being parsed
8018      *
8019      * @access private
8020      * @var string
8021      */
8022     var $name = '';
8023
8024     /**
8025      * Value of the hedaer currently being parsed
8026      *
8027      * @access private
8028      * @var string
8029      */
8030     var $value = '';
8031
b1a6a5 8032
fd9ef2 8033     /**
T 8034      * Create an instance of the class with the input data
8035      *
8036      * @access public
8037      * @param string $data Input data
8038      */
8039     function SimplePie_HTTP_Parser($data)
8040     {
8041         $this->data = $data;
8042         $this->data_length = strlen($this->data);
8043     }
b1a6a5 8044
fd9ef2 8045
T 8046     /**
8047      * Parse the input data
8048      *
8049      * @access public
8050      * @return bool true on success, false on failure
8051      */
8052     function parse()
8053     {
8054         while ($this->state && $this->state !== 'emit' && $this->has_data())
8055         {
8056             $state = $this->state;
8057             $this->$state();
8058         }
8059         $this->data = '';
8060         if ($this->state === 'emit' || $this->state === 'body')
8061         {
8062             return true;
8063         }
8064         else
8065         {
8066             $this->http_version = '';
8067             $this->status_code = '';
8068             $this->reason = '';
8069             $this->headers = array();
8070             $this->body = '';
8071             return false;
8072         }
8073     }
8074
b1a6a5 8075
fd9ef2 8076     /**
T 8077      * Check whether there is data beyond the pointer
8078      *
8079      * @access private
8080      * @return bool true if there is further data, false if not
8081      */
8082     function has_data()
8083     {
8084         return (bool) ($this->position < $this->data_length);
8085     }
b1a6a5 8086
fd9ef2 8087
T 8088     /**
8089      * See if the next character is LWS
8090      *
8091      * @access private
8092      * @return bool true if the next character is LWS, false if not
8093      */
8094     function is_linear_whitespace()
8095     {
8096         return (bool) ($this->data[$this->position] === "\x09"
8097             || $this->data[$this->position] === "\x20"
8098             || ($this->data[$this->position] === "\x0A"
8099                 && isset($this->data[$this->position + 1])
8100                 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
8101     }
b1a6a5 8102
fd9ef2 8103
T 8104     /**
8105      * Parse the HTTP version
8106      *
8107      * @access private
8108      */
8109     function http_version()
8110     {
8111         if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
8112         {
8113             $len = strspn($this->data, '0123456789.', 5);
8114             $this->http_version = substr($this->data, 5, $len);
8115             $this->position += 5 + $len;
8116             if (substr_count($this->http_version, '.') <= 1)
8117             {
8118                 $this->http_version = (float) $this->http_version;
8119                 $this->position += strspn($this->data, "\x09\x20", $this->position);
8120                 $this->state = 'status';
8121             }
8122             else
8123             {
8124                 $this->state = false;
8125             }
8126         }
8127         else
8128         {
8129             $this->state = false;
8130         }
8131     }
8132
b1a6a5 8133
fd9ef2 8134     /**
T 8135      * Parse the status code
8136      *
8137      * @access private
8138      */
8139     function status()
8140     {
8141         if ($len = strspn($this->data, '0123456789', $this->position))
8142         {
8143             $this->status_code = (int) substr($this->data, $this->position, $len);
8144             $this->position += $len;
8145             $this->state = 'reason';
8146         }
8147         else
8148         {
8149             $this->state = false;
8150         }
8151     }
8152
b1a6a5 8153
fd9ef2 8154     /**
T 8155      * Parse the reason phrase
8156      *
8157      * @access private
8158      */
8159     function reason()
8160     {
8161         $len = strcspn($this->data, "\x0A", $this->position);
8162         $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
8163         $this->position += $len + 1;
8164         $this->state = 'new_line';
8165     }
b1a6a5 8166
fd9ef2 8167
T 8168     /**
8169      * Deal with a new line, shifting data around as needed
8170      *
8171      * @access private
8172      */
8173     function new_line()
8174     {
8175         $this->value = trim($this->value, "\x0D\x20");
8176         if ($this->name !== '' && $this->value !== '')
8177         {
8178             $this->name = strtolower($this->name);
8179             if (isset($this->headers[$this->name]))
8180             {
8181                 $this->headers[$this->name] .= ', ' . $this->value;
8182             }
8183             else
8184             {
8185                 $this->headers[$this->name] = $this->value;
8186             }
8187         }
8188         $this->name = '';
8189         $this->value = '';
8190         if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
8191         {
8192             $this->position += 2;
8193             $this->state = 'body';
8194         }
8195         elseif ($this->data[$this->position] === "\x0A")
8196         {
8197             $this->position++;
8198             $this->state = 'body';
8199         }
8200         else
8201         {
8202             $this->state = 'name';
8203         }
8204     }
8205
b1a6a5 8206
fd9ef2 8207     /**
T 8208      * Parse a header name
8209      *
8210      * @access private
8211      */
8212     function name()
8213     {
8214         $len = strcspn($this->data, "\x0A:", $this->position);
8215         if (isset($this->data[$this->position + $len]))
8216         {
8217             if ($this->data[$this->position + $len] === "\x0A")
8218             {
8219                 $this->position += $len;
8220                 $this->state = 'new_line';
8221             }
8222             else
8223             {
8224                 $this->name = substr($this->data, $this->position, $len);
8225                 $this->position += $len + 1;
8226                 $this->state = 'value';
8227             }
8228         }
8229         else
8230         {
8231             $this->state = false;
8232         }
8233     }
8234
b1a6a5 8235
fd9ef2 8236     /**
T 8237      * Parse LWS, replacing consecutive LWS characters with a single space
8238      *
8239      * @access private
8240      */
8241     function linear_whitespace()
8242     {
8243         do
8244         {
8245             if (substr($this->data, $this->position, 2) === "\x0D\x0A")
8246             {
8247                 $this->position += 2;
8248             }
8249             elseif ($this->data[$this->position] === "\x0A")
8250             {
8251                 $this->position++;
8252             }
8253             $this->position += strspn($this->data, "\x09\x20", $this->position);
8254         } while ($this->has_data() && $this->is_linear_whitespace());
8255         $this->value .= "\x20";
8256     }
8257
b1a6a5 8258
fd9ef2 8259     /**
T 8260      * See what state to move to while within non-quoted header values
8261      *
8262      * @access private
8263      */
8264     function value()
8265     {
8266         if ($this->is_linear_whitespace())
8267         {
8268             $this->linear_whitespace();
8269         }
8270         else
8271         {
8272             switch ($this->data[$this->position])
8273             {
b1a6a5 8274             case '"':
MC 8275                 $this->position++;
8276                 $this->state = 'quote';
8277                 break;
fd9ef2 8278
b1a6a5 8279             case "\x0A":
MC 8280                 $this->position++;
8281                 $this->state = 'new_line';
8282                 break;
fd9ef2 8283
b1a6a5 8284             default:
MC 8285                 $this->state = 'value_char';
8286                 break;
fd9ef2 8287             }
T 8288         }
8289     }
b1a6a5 8290
fd9ef2 8291
T 8292     /**
8293      * Parse a header value while outside quotes
8294      *
8295      * @access private
8296      */
8297     function value_char()
8298     {
8299         $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
8300         $this->value .= substr($this->data, $this->position, $len);
8301         $this->position += $len;
8302         $this->state = 'value';
8303     }
b1a6a5 8304
fd9ef2 8305
T 8306     /**
8307      * See what state to move to while within quoted header values
8308      *
8309      * @access private
8310      */
8311     function quote()
8312     {
8313         if ($this->is_linear_whitespace())
8314         {
8315             $this->linear_whitespace();
8316         }
8317         else
8318         {
8319             switch ($this->data[$this->position])
8320             {
b1a6a5 8321             case '"':
MC 8322                 $this->position++;
8323                 $this->state = 'value';
8324                 break;
fd9ef2 8325
b1a6a5 8326             case "\x0A":
MC 8327                 $this->position++;
8328                 $this->state = 'new_line';
8329                 break;
fd9ef2 8330
b1a6a5 8331             case '\\':
MC 8332                 $this->position++;
8333                 $this->state = 'quote_escaped';
8334                 break;
fd9ef2 8335
b1a6a5 8336             default:
MC 8337                 $this->state = 'quote_char';
8338                 break;
fd9ef2 8339             }
T 8340         }
8341     }
b1a6a5 8342
fd9ef2 8343
T 8344     /**
8345      * Parse a header value while within quotes
8346      *
8347      * @access private
8348      */
8349     function quote_char()
8350     {
8351         $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
8352         $this->value .= substr($this->data, $this->position, $len);
8353         $this->position += $len;
8354         $this->state = 'value';
8355     }
8356
b1a6a5 8357
fd9ef2 8358     /**
T 8359      * Parse an escaped character within quotes
8360      *
8361      * @access private
8362      */
8363     function quote_escaped()
8364     {
8365         $this->value .= $this->data[$this->position];
8366         $this->position++;
8367         $this->state = 'quote';
8368     }
8369
b1a6a5 8370
fd9ef2 8371     /**
T 8372      * Parse the body
8373      *
8374      * @access private
8375      */
8376     function body()
8377     {
8378         $this->body = substr($this->data, $this->position);
8379         $this->state = 'emit';
8380     }
b1a6a5 8381
fd9ef2 8382 }
T 8383
8384 /**
8385  * gzdecode
8386  *
8387  * @package SimplePie
8388  */
8389 class SimplePie_gzdecode
8390 {
b1a6a5 8391
fd9ef2 8392     /**
T 8393      * Compressed data
8394      *
8395      * @access private
8396      * @see gzdecode::$data
8397      */
8398     var $compressed_data;
8399
8400     /**
8401      * Size of compressed data
8402      *
8403      * @access private
8404      */
8405     var $compressed_size;
8406
8407     /**
8408      * Minimum size of a valid gzip string
8409      *
8410      * @access private
8411      */
8412     var $min_compressed_size = 18;
8413
8414     /**
8415      * Current position of pointer
8416      *
8417      * @access private
8418      */
8419     var $position = 0;
8420
8421     /**
8422      * Flags (FLG)
8423      *
8424      * @access private
8425      */
8426     var $flags;
8427
8428     /**
8429      * Uncompressed data
8430      *
8431      * @access public
8432      * @see gzdecode::$compressed_data
8433      */
8434     var $data;
8435
8436     /**
8437      * Modified time
8438      *
8439      * @access public
8440      */
8441     var $MTIME;
8442
8443     /**
8444      * Extra Flags
8445      *
8446      * @access public
8447      */
8448     var $XFL;
8449
8450     /**
8451      * Operating System
8452      *
8453      * @access public
8454      */
8455     var $OS;
8456
8457     /**
8458      * Subfield ID 1
8459      *
8460      * @access public
8461      * @see gzdecode::$extra_field
8462      * @see gzdecode::$SI2
8463      */
8464     var $SI1;
8465
8466     /**
8467      * Subfield ID 2
8468      *
8469      * @access public
8470      * @see gzdecode::$extra_field
8471      * @see gzdecode::$SI1
8472      */
8473     var $SI2;
8474
8475     /**
8476      * Extra field content
8477      *
8478      * @access public
8479      * @see gzdecode::$SI1
8480      * @see gzdecode::$SI2
8481      */
8482     var $extra_field;
8483
8484     /**
8485      * Original filename
8486      *
8487      * @access public
8488      */
8489     var $filename;
8490
8491     /**
8492      * Human readable comment
8493      *
8494      * @access public
8495      */
8496     var $comment;
8497
b1a6a5 8498
fd9ef2 8499     /**
T 8500      * Don't allow anything to be set
8501      *
8502      * @access public
8503      */
8504     function __set($name, $value)
8505     {
8506         trigger_error("Cannot write property $name", E_USER_ERROR);
8507     }
b1a6a5 8508
fd9ef2 8509
T 8510     /**
8511      * Set the compressed string and related properties
8512      *
8513      * @access public
8514      */
8515     function SimplePie_gzdecode($data)
8516     {
8517         $this->compressed_data = $data;
8518         $this->compressed_size = strlen($data);
8519     }
b1a6a5 8520
fd9ef2 8521
T 8522     /**
8523      * Decode the GZIP stream
8524      *
8525      * @access public
8526      */
8527     function parse()
8528     {
8529         if ($this->compressed_size >= $this->min_compressed_size)
8530         {
8531             // Check ID1, ID2, and CM
8532             if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
8533             {
8534                 return false;
8535             }
8536
8537             // Get the FLG (FLaGs)
8538             $this->flags = ord($this->compressed_data[3]);
8539
8540             // FLG bits above (1 << 4) are reserved
8541             if ($this->flags > 0x1F)
8542             {
8543                 return false;
8544             }
8545
8546             // Advance the pointer after the above
8547             $this->position += 4;
8548
8549             // MTIME
8550             $mtime = substr($this->compressed_data, $this->position, 4);
8551             // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
8552             if (current(unpack('S', "\x00\x01")) === 1)
8553             {
8554                 $mtime = strrev($mtime);
8555             }
8556             $this->MTIME = current(unpack('l', $mtime));
8557             $this->position += 4;
8558
8559             // Get the XFL (eXtra FLags)
8560             $this->XFL = ord($this->compressed_data[$this->position++]);
8561
8562             // Get the OS (Operating System)
8563             $this->OS = ord($this->compressed_data[$this->position++]);
8564
8565             // Parse the FEXTRA
8566             if ($this->flags & 4)
8567             {
8568                 // Read subfield IDs
8569                 $this->SI1 = $this->compressed_data[$this->position++];
8570                 $this->SI2 = $this->compressed_data[$this->position++];
8571
8572                 // SI2 set to zero is reserved for future use
8573                 if ($this->SI2 === "\x00")
8574                 {
8575                     return false;
8576                 }
8577
8578                 // Get the length of the extra field
8579                 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8580                 $position += 2;
8581
8582                 // Check the length of the string is still valid
8583                 $this->min_compressed_size += $len + 4;
8584                 if ($this->compressed_size >= $this->min_compressed_size)
8585                 {
8586                     // Set the extra field to the given data
8587                     $this->extra_field = substr($this->compressed_data, $this->position, $len);
8588                     $this->position += $len;
8589                 }
8590                 else
8591                 {
8592                     return false;
8593                 }
8594             }
8595
8596             // Parse the FNAME
8597             if ($this->flags & 8)
8598             {
8599                 // Get the length of the filename
8600                 $len = strcspn($this->compressed_data, "\x00", $this->position);
8601
8602                 // Check the length of the string is still valid
8603                 $this->min_compressed_size += $len + 1;
8604                 if ($this->compressed_size >= $this->min_compressed_size)
8605                 {
8606                     // Set the original filename to the given string
8607                     $this->filename = substr($this->compressed_data, $this->position, $len);
8608                     $this->position += $len + 1;
8609                 }
8610                 else
8611                 {
8612                     return false;
8613                 }
8614             }
8615
8616             // Parse the FCOMMENT
8617             if ($this->flags & 16)
8618             {
8619                 // Get the length of the comment
8620                 $len = strcspn($this->compressed_data, "\x00", $this->position);
8621
8622                 // Check the length of the string is still valid
8623                 $this->min_compressed_size += $len + 1;
8624                 if ($this->compressed_size >= $this->min_compressed_size)
8625                 {
8626                     // Set the original comment to the given string
8627                     $this->comment = substr($this->compressed_data, $this->position, $len);
8628                     $this->position += $len + 1;
8629                 }
8630                 else
8631                 {
8632                     return false;
8633                 }
8634             }
8635
8636             // Parse the FHCRC
8637             if ($this->flags & 2)
8638             {
8639                 // Check the length of the string is still valid
8640                 $this->min_compressed_size += $len + 2;
8641                 if ($this->compressed_size >= $this->min_compressed_size)
8642                 {
8643                     // Read the CRC
8644                     $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8645
8646                     // Check the CRC matches
8647                     if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
8648                     {
8649                         $this->position += 2;
8650                     }
8651                     else
8652                     {
8653                         return false;
8654                     }
8655                 }
8656                 else
8657                 {
8658                     return false;
8659                 }
8660             }
8661
8662             // Decompress the actual data
8663             if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
8664             {
8665                 return false;
8666             }
8667             else
8668             {
8669                 $this->position = $this->compressed_size - 8;
8670             }
8671
8672             // Check CRC of data
8673             $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8674             $this->position += 4;
8675             /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
8676             {
8677                 return false;
8678             }*/
8679
8680             // Check ISIZE of data
8681             $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8682             $this->position += 4;
8683             if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
8684             {
8685                 return false;
8686             }
8687
8688             // Wow, against all odds, we've actually got a valid gzip string
8689             return true;
8690         }
8691         else
8692         {
8693             return false;
8694         }
8695     }
b1a6a5 8696
fd9ef2 8697 }
T 8698
8699 class SimplePie_Cache
8700 {
b1a6a5 8701
MC 8702
fd9ef2 8703     /**
T 8704      * Don't call the constructor. Please.
8705      *
8706      * @access private
8707      */
8708     function SimplePie_Cache()
8709     {
8710         trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8711     }
b1a6a5 8712
fd9ef2 8713
T 8714     /**
8715      * Create a new SimplePie_Cache object
8716      *
8717      * @static
8718      * @access public
8719      */
8720     function create($location, $filename, $extension)
8721     {
f64c86 8722         $location_iri = new SimplePie_IRI($location);
fd9ef2 8723         switch ($location_iri->get_scheme())
T 8724         {
b1a6a5 8725         case 'mysql':
MC 8726             if (extension_loaded('mysql'))
8727             {
8728                 return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
8729             }
8730             break;
fd9ef2 8731
b1a6a5 8732         default:
MC 8733             return new SimplePie_Cache_File($location, $filename, $extension);
fd9ef2 8734         }
T 8735     }
b1a6a5 8736
fd9ef2 8737 }
T 8738
8739 class SimplePie_Cache_File
8740 {
8741     var $location;
8742     var $filename;
8743     var $extension;
8744     var $name;
8745
8746     function SimplePie_Cache_File($location, $filename, $extension)
8747     {
8748         $this->location = $location;
8749         $this->filename = $filename;
8750         $this->extension = $extension;
8751         $this->name = "$this->location/$this->filename.$this->extension";
8752     }
8753
8754     function save($data)
8755     {
8756         if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8757         {
8758             if (is_a($data, 'SimplePie'))
8759             {
8760                 $data = $data->data;
8761             }
8762
8763             $data = serialize($data);
8764
8765             if (function_exists('file_put_contents'))
8766             {
8767                 return (bool) file_put_contents($this->name, $data);
8768             }
8769             else
8770             {
8771                 $fp = fopen($this->name, 'wb');
8772                 if ($fp)
8773                 {
8774                     fwrite($fp, $data);
8775                     fclose($fp);
8776                     return true;
8777                 }
8778             }
8779         }
8780         return false;
8781     }
8782
8783     function load()
8784     {
8785         if (file_exists($this->name) && is_readable($this->name))
8786         {
8787             return unserialize(file_get_contents($this->name));
8788         }
8789         return false;
8790     }
8791
8792     function mtime()
8793     {
8794         if (file_exists($this->name))
8795         {
8796             return filemtime($this->name);
8797         }
8798         return false;
8799     }
8800
8801     function touch()
8802     {
8803         if (file_exists($this->name))
8804         {
8805             return touch($this->name);
8806         }
8807         return false;
8808     }
8809
8810     function unlink()
8811     {
8812         if (file_exists($this->name))
8813         {
8814             return unlink($this->name);
8815         }
8816         return false;
8817     }
b1a6a5 8818
fd9ef2 8819 }
T 8820
8821 class SimplePie_Cache_DB
8822 {
8823     function prepare_simplepie_object_for_cache($data)
8824     {
8825         $items = $data->get_items();
8826         $items_by_id = array();
8827
8828         if (!empty($items))
8829         {
8830             foreach ($items as $item)
8831             {
8832                 $items_by_id[$item->get_id()] = $item;
8833             }
8834
8835             if (count($items_by_id) !== count($items))
8836             {
8837                 $items_by_id = array();
8838                 foreach ($items as $item)
8839                 {
8840                     $items_by_id[$item->get_id(true)] = $item;
8841                 }
8842             }
8843
8844             if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8845             {
8846                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8847             }
8848             elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8849             {
8850                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8851             }
8852             elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8853             {
8854                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8855             }
8856             elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
8857             {
8858                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
8859             }
8860             else
8861             {
8862                 $channel = null;
8863             }
8864
8865             if ($channel !== null)
8866             {
8867                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
8868                 {
8869                     unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
8870                 }
8871                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
8872                 {
8873                     unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
8874                 }
8875                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
8876                 {
8877                     unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
8878                 }
8879                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
8880                 {
8881                     unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
8882                 }
8883                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
8884                 {
8885                     unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
8886                 }
8887             }
8888             if (isset($data->data['items']))
8889             {
8890                 unset($data->data['items']);
8891             }
8892             if (isset($data->data['ordered_items']))
8893             {
8894                 unset($data->data['ordered_items']);
8895             }
8896         }
8897         return array(serialize($data->data), $items_by_id);
8898     }
b1a6a5 8899
fd9ef2 8900 }
T 8901
8902 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
8903 {
8904     var $mysql;
8905     var $options;
8906     var $id;
8907
8908     function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
8909     {
8910         $host = $mysql_location->get_host();
8911         if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
8912         {
8913             $server = ':' . substr($host, 5, -1);
8914         }
8915         else
8916         {
8917             $server = $host;
8918             if ($mysql_location->get_port() !== null)
8919             {
8920                 $server .= ':' . $mysql_location->get_port();
8921             }
8922         }
8923
8924         if (strpos($mysql_location->get_userinfo(), ':') !== false)
8925         {
8926             list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
8927         }
8928         else
8929         {
8930             $username = $mysql_location->get_userinfo();
8931             $password = null;
8932         }
8933
8934         if ($this->mysql = mysql_connect($server, $username, $password))
8935         {
8936             $this->id = $name . $extension;
8937             $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
8938             if (!isset($this->options['prefix'][0]))
8939             {
8940                 $this->options['prefix'][0] = '';
8941             }
8942
8943             if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
8944                 && mysql_query('SET NAMES utf8')
8945                 && ($query = mysql_unbuffered_query('SHOW TABLES')))
8946             {
8947                 $db = array();
8948                 while ($row = mysql_fetch_row($query))
8949                 {
8950                     $db[] = $row[0];
8951                 }
8952
8953                 if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
8954                 {
8955                     if (!mysql_query('CREATE TABLE `' . $this->options['prefix'][0] . 'cache_data` (`id` TEXT CHARACTER SET utf8 NOT NULL, `items` SMALLINT NOT NULL DEFAULT 0, `data` BLOB NOT NULL, `mtime` INT UNSIGNED NOT NULL, UNIQUE (`id`(125)))'))
8956                     {
8957                         $this->mysql = null;
8958                     }
8959                 }
8960
8961                 if (!in_array($this->options['prefix'][0] . 'items', $db))
8962                 {
8963                     if (!mysql_query('CREATE TABLE `' . $this->options['prefix'][0] . 'items` (`feed_id` TEXT CHARACTER SET utf8 NOT NULL, `id` TEXT CHARACTER SET utf8 NOT NULL, `data` TEXT CHARACTER SET utf8 NOT NULL, `posted` INT UNSIGNED NOT NULL, INDEX `feed_id` (`feed_id`(125)))'))
8964                     {
8965                         $this->mysql = null;
8966                     }
8967                 }
8968             }
8969             else
8970             {
8971                 $this->mysql = null;
8972             }
8973         }
8974     }
8975
8976     function save($data)
8977     {
8978         if ($this->mysql)
8979         {
8980             $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
8981
8982             if (is_a($data, 'SimplePie'))
8983             {
8984                 if (SIMPLEPIE_PHP5)
8985                 {
8986                     // This keyword needs to defy coding standards for PHP4 compatibility
8987                     $data = clone($data);
8988                 }
8989
8990                 $prepared = $this->prepare_simplepie_object_for_cache($data);
8991
8992                 if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8993                 {
8994                     if (mysql_num_rows($query))
8995                     {
8996                         $items = count($prepared[1]);
8997                         if ($items)
8998                         {
8999                             $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
9000                         }
9001                         else
9002                         {
9003                             $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
9004                         }
9005
9006                         if (!mysql_query($sql, $this->mysql))
9007                         {
9008                             return false;
9009                         }
9010                     }
9011                     elseif (!mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(' . $feed_id . ', ' . count($prepared[1]) . ', \'' . mysql_real_escape_string($prepared[0]) . '\', ' . time() . ')', $this->mysql))
9012                     {
9013                         return false;
9014                     }
9015
9016                     $ids = array_keys($prepared[1]);
9017                     if (!empty($ids))
9018                     {
9019                         foreach ($ids as $id)
9020                         {
9021                             $database_ids[] = mysql_real_escape_string($id);
9022                         }
9023
9024                         if ($query = mysql_unbuffered_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'items` WHERE `id` = \'' . implode('\' OR `id` = \'', $database_ids) . '\' AND `feed_id` = ' . $feed_id, $this->mysql))
9025                         {
9026                             $existing_ids = array();
9027                             while ($row = mysql_fetch_row($query))
9028                             {
9029                                 $existing_ids[] = $row[0];
9030                             }
9031
9032                             $new_ids = array_diff($ids, $existing_ids);
9033
9034                             foreach ($new_ids as $new_id)
9035                             {
9036                                 if (!($date = $prepared[1][$new_id]->get_date('U')))
9037                                 {
9038                                     $date = time();
9039                                 }
9040
9041                                 if (!mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'items` (`feed_id`, `id`, `data`, `posted`) VALUES(' . $feed_id . ', \'' . mysql_real_escape_string($new_id) . '\', \'' . mysql_real_escape_string(serialize($prepared[1][$new_id]->data)) . '\', ' . $date . ')', $this->mysql))
9042                                 {
9043                                     return false;
9044                                 }
9045                             }
9046                             return true;
9047                         }
9048                     }
9049                     else
9050                     {
9051                         return true;
9052                     }
9053                 }
9054             }
9055             elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
9056             {
9057                 if (mysql_num_rows($query))
9058                 {
9059                     if (mysql_query('UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = 0, `data` = \'' . mysql_real_escape_string(serialize($data)) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id, $this->mysql))
9060                     {
9061                         return true;
9062                     }
9063                 }
9064                 elseif (mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(\'' . mysql_real_escape_string($this->id) . '\', 0, \'' . mysql_real_escape_string(serialize($data)) . '\', ' . time() . ')', $this->mysql))
9065                 {
9066                     return true;
9067                 }
9068             }
9069         }
9070         return false;
9071     }
9072
9073     function load()
9074     {
9075         if ($this->mysql && ($query = mysql_query('SELECT `items`, `data` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($row = mysql_fetch_row($query)))
9076         {
9077             $data = unserialize($row[1]);
9078
9079             if (isset($this->options['items'][0]))
9080             {
9081                 $items = (int) $this->options['items'][0];
9082             }
9083             else
9084             {
9085                 $items = (int) $row[0];
9086             }
9087
9088             if ($items !== 0)
9089             {
9090                 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
9091                 {
9092                     $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
9093                 }
9094                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
9095                 {
9096                     $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
9097                 }
9098                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
9099                 {
9100                     $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
9101                 }
9102                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
9103                 {
9104                     $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
9105                 }
9106                 else
9107                 {
9108                     $feed = null;
9109                 }
9110
9111                 if ($feed !== null)
9112                 {
9113                     $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
9114                     if ($items > 0)
9115                     {
9116                         $sql .= ' LIMIT ' . $items;
9117                     }
9118
9119                     if ($query = mysql_unbuffered_query($sql, $this->mysql))
9120                     {
9121                         while ($row = mysql_fetch_row($query))
9122                         {
9123                             $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
9124                         }
9125                     }
9126                     else
9127                     {
9128                         return false;
9129                     }
9130                 }
9131             }
9132             return $data;
9133         }
9134         return false;
9135     }
9136
9137     function mtime()
9138     {
9139         if ($this->mysql && ($query = mysql_query('SELECT `mtime` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($row = mysql_fetch_row($query)))
9140         {
9141             return $row[0];
9142         }
9143         else
9144         {
9145             return false;
9146         }
9147     }
9148
9149     function touch()
9150     {
9151         if ($this->mysql && ($query = mysql_query('UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `mtime` = ' . time() . ' WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && mysql_affected_rows($this->mysql))
9152         {
9153             return true;
9154         }
9155         else
9156         {
9157             return false;
9158         }
9159     }
9160
9161     function unlink()
9162     {
9163         if ($this->mysql && ($query = mysql_query('DELETE FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($query2 = mysql_query('DELETE FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)))
9164         {
9165             return true;
9166         }
9167         else
9168         {
9169             return false;
9170         }
9171     }
b1a6a5 9172
fd9ef2 9173 }
T 9174
9175 class SimplePie_Misc
9176 {
9177     function time_hms($seconds)
9178     {
9179         $time = '';
9180
9181         $hours = floor($seconds / 3600);
9182         $remainder = $seconds % 3600;
9183         if ($hours > 0)
9184         {
9185             $time .= $hours.':';
9186         }
9187
9188         $minutes = floor($remainder / 60);
9189         $seconds = $remainder % 60;
9190         if ($minutes < 10 && $hours > 0)
9191         {
9192             $minutes = '0' . $minutes;
9193         }
9194         if ($seconds < 10)
9195         {
9196             $seconds = '0' . $seconds;
9197         }
9198
9199         $time .= $minutes.':';
9200         $time .= $seconds;
9201
9202         return $time;
9203     }
9204
72695f 9205     static function absolutize_url($relative, $base)
fd9ef2 9206     {
T 9207         $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
9208         return $iri->get_iri();
9209     }
9210
9211     function remove_dot_segments($input)
9212     {
9213         $output = '';
9214         while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
9215         {
9216             // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
9217             if (strpos($input, '../') === 0)
9218             {
9219                 $input = substr($input, 3);
9220             }
9221             elseif (strpos($input, './') === 0)
9222             {
9223                 $input = substr($input, 2);
9224             }
9225             // B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise,
9226             elseif (strpos($input, '/./') === 0)
9227             {
9228                 $input = substr_replace($input, '/', 0, 3);
9229             }
9230             elseif ($input === '/.')
9231             {
9232                 $input = '/';
9233             }
9234             // C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise,
9235             elseif (strpos($input, '/../') === 0)
9236             {
9237                 $input = substr_replace($input, '/', 0, 4);
9238                 $output = substr_replace($output, '', strrpos($output, '/'));
9239             }
9240             elseif ($input === '/..')
9241             {
9242                 $input = '/';
9243                 $output = substr_replace($output, '', strrpos($output, '/'));
9244             }
9245             // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
9246             elseif ($input === '.' || $input === '..')
9247             {
9248                 $input = '';
9249             }
9250             // E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer
9251             elseif (($pos = strpos($input, '/', 1)) !== false)
9252             {
9253                 $output .= substr($input, 0, $pos);
9254                 $input = substr_replace($input, '', 0, $pos);
9255             }
9256             else
9257             {
9258                 $output .= $input;
9259                 $input = '';
9260             }
9261         }
9262         return $output . $input;
9263     }
9264
72695f 9265     static function get_element($realname, $string)
fd9ef2 9266     {
T 9267         $return = array();
9268         $name = preg_quote($realname, '/');
9269         if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
9270         {
9271             for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
9272             {
9273                 $return[$i]['tag'] = $realname;
9274                 $return[$i]['full'] = $matches[$i][0][0];
9275                 $return[$i]['offset'] = $matches[$i][0][1];
9276                 if (strlen($matches[$i][3][0]) <= 2)
9277                 {
9278                     $return[$i]['self_closing'] = true;
9279                 }
9280                 else
9281                 {
9282                     $return[$i]['self_closing'] = false;
9283                     $return[$i]['content'] = $matches[$i][4][0];
9284                 }
9285                 $return[$i]['attribs'] = array();
9286                 if (isset($matches[$i][2][0]) && preg_match_all('/[\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]*)?))?/', ' ' . $matches[$i][2][0] . ' ', $attribs, PREG_SET_ORDER))
9287                 {
9288                     for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
9289                     {
9290                         if (count($attribs[$j]) === 2)
9291                         {
9292                             $attribs[$j][2] = $attribs[$j][1];
9293                         }
9294                         $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
9295                     }
9296                 }
9297             }
9298         }
9299         return $return;
9300     }
9301
992797 9302     static function element_implode($element)
fd9ef2 9303     {
T 9304         $full = "<$element[tag]";
9305         foreach ($element['attribs'] as $key => $value)
9306         {
9307             $key = strtolower($key);
9308             $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
9309         }
9310         if ($element['self_closing'])
9311         {
9312             $full .= ' />';
9313         }
9314         else
9315         {
9316             $full .= ">$element[content]</$element[tag]>";
9317         }
9318         return $full;
9319     }
9320
9321     function error($message, $level, $file, $line)
9322     {
9323         if ((ini_get('error_reporting') & $level) > 0)
9324         {
9325             switch ($level)
9326             {
b1a6a5 9327             case E_USER_ERROR:
MC 9328                 $note = 'PHP Error';
9329                 break;
9330             case E_USER_WARNING:
9331                 $note = 'PHP Warning';
9332                 break;
9333             case E_USER_NOTICE:
9334                 $note = 'PHP Notice';
9335                 break;
9336             default:
9337                 $note = 'Unknown Error';
9338                 break;
fd9ef2 9339             }
T 9340
9341             $log_error = true;
9342             if (!function_exists('error_log'))
9343             {
9344                 $log_error = false;
9345             }
9346
9347             $log_file = @ini_get('error_log');
9348             if (!empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file))
9349             {
9350                 $log_error = false;
9351             }
9352
9353             if ($log_error)
9354             {
9355                 @error_log("$note: $message in $file on line $line", 0);
9356             }
9357         }
9358
9359         return $message;
9360     }
b1a6a5 9361
fd9ef2 9362
T 9363     /**
9364      * If a file has been cached, retrieve and display it.
9365      *
9366      * This is most useful for caching images (get_favicon(), etc.),
9367      * however it works for all cached files.  This WILL NOT display ANY
9368      * file/image/page/whatever, but rather only display what has already
9369      * been cached by SimplePie.
9370      *
9371      * @access public
9372      * @see SimplePie::get_favicon()
9373      * @param str $identifier_url URL that is used to identify the content.
9374      * This may or may not be the actual URL of the live content.
9375      * @param str $cache_location Location of SimplePie's cache.  Defaults
9376      * to './cache'.
9377      * @param str $cache_extension The file extension that the file was
9378      * cached with.  Defaults to 'spc'.
9379      * @param str $cache_class Name of the cache-handling class being used
9380      * in SimplePie.  Defaults to 'SimplePie_Cache', and should be left
9381      * as-is unless you've overloaded the class.
9382      * @param str $cache_name_function Obsolete. Exists for backwards
9383      * compatibility reasons only.
9384      */
9385     function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
9386     {
9387         $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
9388
9389         if ($file = $cache->load())
9390         {
9391             if (isset($file['headers']['content-type']))
9392             {
9393                 header('Content-type:' . $file['headers']['content-type']);
9394             }
9395             else
9396             {
9397                 header('Content-type: application/octet-stream');
9398             }
9399             header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
9400             echo $file['body'];
9401             exit;
9402         }
9403
9404         die('Cached file for ' . $identifier_url . ' cannot be found.');
9405     }
9406
526b99 9407     public static function fix_protocol($url, $http = 1)
fd9ef2 9408     {
T 9409         $url = SimplePie_Misc::normalize_url($url);
9410         $parsed = SimplePie_Misc::parse_url($url);
9411         if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
9412         {
9413             return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
9414         }
9415
9416         if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
9417         {
9418             return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
9419         }
9420
9421         if ($http === 2 && $parsed['scheme'] !== '')
9422         {
9423             return "feed:$url";
9424         }
9425         elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
9426         {
9427             return substr_replace($url, 'podcast', 0, 4);
9428         }
9429         elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
9430         {
9431             return substr_replace($url, 'itpc', 0, 4);
9432         }
9433         else
9434         {
9435             return $url;
9436         }
9437     }
9438
526b99 9439     public static function parse_url($url)
fd9ef2 9440     {
f64c86 9441         $iri = new SimplePie_IRI($url);
fd9ef2 9442         return array(
T 9443             'scheme' => (string) $iri->get_scheme(),
9444             'authority' => (string) $iri->get_authority(),
9445             'path' => (string) $iri->get_path(),
9446             'query' => (string) $iri->get_query(),
9447             'fragment' => (string) $iri->get_fragment()
9448         );
9449     }
9450
9451     function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
9452     {
f64c86 9453         $iri = new SimplePie_IRI('');
fd9ef2 9454         $iri->set_scheme($scheme);
T 9455         $iri->set_authority($authority);
9456         $iri->set_path($path);
9457         $iri->set_query($query);
9458         $iri->set_fragment($fragment);
9459         return $iri->get_iri();
9460     }
9461
526b99 9462     public static function normalize_url($url)
fd9ef2 9463     {
f64c86 9464         $iri = new SimplePie_IRI($url);
fd9ef2 9465         return $iri->get_iri();
T 9466     }
9467
9468     function percent_encoding_normalization($match)
9469     {
9470         $integer = hexdec($match[1]);
9471         if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
9472         {
9473             return chr($integer);
9474         }
9475         else
9476         {
9477             return strtoupper($match[0]);
9478         }
9479     }
9480
b1a6a5 9481
fd9ef2 9482     /**
T 9483      * Remove bad UTF-8 bytes
9484      *
9485      * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
9486      * FAQ: Multilingual Forms (modified to include full ASCII range)
9487      *
9488      * @author Geoffrey Sneddon
9489      * @see http://www.w3.org/International/questions/qa-forms-utf-8
9490      * @param string $str String to remove bad UTF-8 bytes from
9491      * @return string UTF-8 string
9492      */
9493     function utf8_bad_replace($str)
9494     {
9495         if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
9496         {
9497             return $return;
9498         }
9499         elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
9500         {
9501             return $return;
9502         }
9503         elseif (preg_match_all('/(?:[\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})+/', $str, $matches))
9504         {
9505             return implode("\xEF\xBF\xBD", $matches[0]);
9506         }
9507         elseif ($str !== '')
9508         {
9509             return "\xEF\xBF\xBD";
9510         }
9511         else
9512         {
9513             return '';
9514         }
9515     }
b1a6a5 9516
fd9ef2 9517
T 9518     /**
9519      * Converts a Windows-1252 encoded string to a UTF-8 encoded string
9520      *
9521      * @static
9522      * @access public
9523      * @param string $string Windows-1252 encoded string
9524      * @return string UTF-8 encoded string
9525      */
9526     function windows_1252_to_utf8($string)
9527     {
9528         static $convert_table = array("\x80" => "\xE2\x82\xAC", "\x81" => "\xEF\xBF\xBD", "\x82" => "\xE2\x80\x9A", "\x83" => "\xC6\x92", "\x84" => "\xE2\x80\x9E", "\x85" => "\xE2\x80\xA6", "\x86" => "\xE2\x80\xA0", "\x87" => "\xE2\x80\xA1", "\x88" => "\xCB\x86", "\x89" => "\xE2\x80\xB0", "\x8A" => "\xC5\xA0", "\x8B" => "\xE2\x80\xB9", "\x8C" => "\xC5\x92", "\x8D" => "\xEF\xBF\xBD", "\x8E" => "\xC5\xBD", "\x8F" => "\xEF\xBF\xBD", "\x90" => "\xEF\xBF\xBD", "\x91" => "\xE2\x80\x98", "\x92" => "\xE2\x80\x99", "\x93" => "\xE2\x80\x9C", "\x94" => "\xE2\x80\x9D", "\x95" => "\xE2\x80\xA2", "\x96" => "\xE2\x80\x93", "\x97" => "\xE2\x80\x94", "\x98" => "\xCB\x9C", "\x99" => "\xE2\x84\xA2", "\x9A" => "\xC5\xA1", "\x9B" => "\xE2\x80\xBA", "\x9C" => "\xC5\x93", "\x9D" => "\xEF\xBF\xBD", "\x9E" => "\xC5\xBE", "\x9F" => "\xC5\xB8", "\xA0" => "\xC2\xA0", "\xA1" => "\xC2\xA1", "\xA2" => "\xC2\xA2", "\xA3" => "\xC2\xA3", "\xA4" => "\xC2\xA4", "\xA5" => "\xC2\xA5", "\xA6" => "\xC2\xA6", "\xA7" => "\xC2\xA7", "\xA8" => "\xC2\xA8", "\xA9" => "\xC2\xA9", "\xAA" => "\xC2\xAA", "\xAB" => "\xC2\xAB", "\xAC" => "\xC2\xAC", "\xAD" => "\xC2\xAD", "\xAE" => "\xC2\xAE", "\xAF" => "\xC2\xAF", "\xB0" => "\xC2\xB0", "\xB1" => "\xC2\xB1", "\xB2" => "\xC2\xB2", "\xB3" => "\xC2\xB3", "\xB4" => "\xC2\xB4", "\xB5" => "\xC2\xB5", "\xB6" => "\xC2\xB6", "\xB7" => "\xC2\xB7", "\xB8" => "\xC2\xB8", "\xB9" => "\xC2\xB9", "\xBA" => "\xC2\xBA", "\xBB" => "\xC2\xBB", "\xBC" => "\xC2\xBC", "\xBD" => "\xC2\xBD", "\xBE" => "\xC2\xBE", "\xBF" => "\xC2\xBF", "\xC0" => "\xC3\x80", "\xC1" => "\xC3\x81", "\xC2" => "\xC3\x82", "\xC3" => "\xC3\x83", "\xC4" => "\xC3\x84", "\xC5" => "\xC3\x85", "\xC6" => "\xC3\x86", "\xC7" => "\xC3\x87", "\xC8" => "\xC3\x88", "\xC9" => "\xC3\x89", "\xCA" => "\xC3\x8A", "\xCB" => "\xC3\x8B", "\xCC" => "\xC3\x8C", "\xCD" => "\xC3\x8D", "\xCE" => "\xC3\x8E", "\xCF" => "\xC3\x8F", "\xD0" => "\xC3\x90", "\xD1" => "\xC3\x91", "\xD2" => "\xC3\x92", "\xD3" => "\xC3\x93", "\xD4" => "\xC3\x94", "\xD5" => "\xC3\x95", "\xD6" => "\xC3\x96", "\xD7" => "\xC3\x97", "\xD8" => "\xC3\x98", "\xD9" => "\xC3\x99", "\xDA" => "\xC3\x9A", "\xDB" => "\xC3\x9B", "\xDC" => "\xC3\x9C", "\xDD" => "\xC3\x9D", "\xDE" => "\xC3\x9E", "\xDF" => "\xC3\x9F", "\xE0" => "\xC3\xA0", "\xE1" => "\xC3\xA1", "\xE2" => "\xC3\xA2", "\xE3" => "\xC3\xA3", "\xE4" => "\xC3\xA4", "\xE5" => "\xC3\xA5", "\xE6" => "\xC3\xA6", "\xE7" => "\xC3\xA7", "\xE8" => "\xC3\xA8", "\xE9" => "\xC3\xA9", "\xEA" => "\xC3\xAA", "\xEB" => "\xC3\xAB", "\xEC" => "\xC3\xAC", "\xED" => "\xC3\xAD", "\xEE" => "\xC3\xAE", "\xEF" => "\xC3\xAF", "\xF0" => "\xC3\xB0", "\xF1" => "\xC3\xB1", "\xF2" => "\xC3\xB2", "\xF3" => "\xC3\xB3", "\xF4" => "\xC3\xB4", "\xF5" => "\xC3\xB5", "\xF6" => "\xC3\xB6", "\xF7" => "\xC3\xB7", "\xF8" => "\xC3\xB8", "\xF9" => "\xC3\xB9", "\xFA" => "\xC3\xBA", "\xFB" => "\xC3\xBB", "\xFC" => "\xC3\xBC", "\xFD" => "\xC3\xBD", "\xFE" => "\xC3\xBE", "\xFF" => "\xC3\xBF");
9529
9530         return strtr($string, $convert_table);
9531     }
9532
526b99 9533     public static function change_encoding($data, $input, $output)
fd9ef2 9534     {
T 9535         $input = SimplePie_Misc::encoding($input);
9536         $output = SimplePie_Misc::encoding($output);
9537
9538         // We fail to fail on non US-ASCII bytes
9539         if ($input === 'US-ASCII')
9540         {
9541             static $non_ascii_octects = '';
9542             if (!$non_ascii_octects)
9543             {
9544                 for ($i = 0x80; $i <= 0xFF; $i++)
9545                 {
9546                     $non_ascii_octects .= chr($i);
9547                 }
9548             }
9549             $data = substr($data, 0, strcspn($data, $non_ascii_octects));
9550         }
9551
9552         // This is first, as behaviour of this is completely predictable
9553         if ($input === 'Windows-1252' && $output === 'UTF-8')
9554         {
9555             return SimplePie_Misc::windows_1252_to_utf8($data);
9556         }
9557         // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
9558         elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input)))
9559         {
9560             return $return;
9561         }
9562         // This is last, as behaviour of this varies with OS userland and PHP version
9563         elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
9564         {
9565             return $return;
9566         }
9567         // If we can't do anything, just fail
9568         else
9569         {
9570             return false;
9571         }
9572     }
9573
526b99 9574     public static function encoding($charset)
fd9ef2 9575     {
T 9576         // Normalization from UTS #22
9577         switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
9578         {
b1a6a5 9579         case 'adobestandardencoding':
MC 9580         case 'csadobestandardencoding':
9581             return 'Adobe-Standard-Encoding';
fd9ef2 9582
b1a6a5 9583         case 'adobesymbolencoding':
MC 9584         case 'cshppsmath':
9585             return 'Adobe-Symbol-Encoding';
fd9ef2 9586
b1a6a5 9587         case 'ami1251':
MC 9588         case 'amiga1251':
9589             return 'Amiga-1251';
fd9ef2 9590
b1a6a5 9591         case 'ansix31101983':
MC 9592         case 'csat5001983':
9593         case 'csiso99naplps':
9594         case 'isoir99':
9595         case 'naplps':
9596             return 'ANSI_X3.110-1983';
fd9ef2 9597
b1a6a5 9598         case 'arabic7':
MC 9599         case 'asmo449':
9600         case 'csiso89asmo449':
9601         case 'iso9036':
9602         case 'isoir89':
9603             return 'ASMO_449';
fd9ef2 9604
b1a6a5 9605         case 'big5':
MC 9606         case 'csbig5':
9607         case 'xxbig5':
9608             return 'Big5';
fd9ef2 9609
b1a6a5 9610         case 'big5hkscs':
MC 9611             return 'Big5-HKSCS';
fd9ef2 9612
b1a6a5 9613         case 'bocu1':
MC 9614         case 'csbocu1':
9615             return 'BOCU-1';
fd9ef2 9616
b1a6a5 9617         case 'brf':
MC 9618         case 'csbrf':
9619             return 'BRF';
fd9ef2 9620
b1a6a5 9621         case 'bs4730':
MC 9622         case 'csiso4unitedkingdom':
9623         case 'gb':
9624         case 'iso646gb':
9625         case 'isoir4':
9626         case 'uk':
9627             return 'BS_4730';
fd9ef2 9628
b1a6a5 9629         case 'bsviewdata':
MC 9630         case 'csiso47bsviewdata':
9631         case 'isoir47':
9632             return 'BS_viewdata';
fd9ef2 9633
b1a6a5 9634         case 'cesu8':
MC 9635         case 'cscesu8':
9636             return 'CESU-8';
fd9ef2 9637
b1a6a5 9638         case 'ca':
MC 9639         case 'csa71':
9640         case 'csaz243419851':
9641         case 'csiso121canadian1':
9642         case 'iso646ca':
9643         case 'isoir121':
9644             return 'CSA_Z243.4-1985-1';
fd9ef2 9645
b1a6a5 9646         case 'csa72':
MC 9647         case 'csaz243419852':
9648         case 'csiso122canadian2':
9649         case 'iso646ca2':
9650         case 'isoir122':
9651             return 'CSA_Z243.4-1985-2';
fd9ef2 9652
b1a6a5 9653         case 'csaz24341985gr':
MC 9654         case 'csiso123csaz24341985gr':
9655         case 'isoir123':
9656             return 'CSA_Z243.4-1985-gr';
fd9ef2 9657
b1a6a5 9658         case 'csiso139csn369103':
MC 9659         case 'csn369103':
9660         case 'isoir139':
9661             return 'CSN_369103';
fd9ef2 9662
b1a6a5 9663         case 'csdecmcs':
MC 9664         case 'dec':
9665         case 'decmcs':
9666             return 'DEC-MCS';
fd9ef2 9667
b1a6a5 9668         case 'csiso21german':
MC 9669         case 'de':
9670         case 'din66003':
9671         case 'iso646de':
9672         case 'isoir21':
9673             return 'DIN_66003';
fd9ef2 9674
b1a6a5 9675         case 'csdkus':
MC 9676         case 'dkus':
9677             return 'dk-us';
fd9ef2 9678
b1a6a5 9679         case 'csiso646danish':
MC 9680         case 'dk':
9681         case 'ds2089':
9682         case 'iso646dk':
9683             return 'DS_2089';
fd9ef2 9684
b1a6a5 9685         case 'csibmebcdicatde':
MC 9686         case 'ebcdicatde':
9687             return 'EBCDIC-AT-DE';
fd9ef2 9688
b1a6a5 9689         case 'csebcdicatdea':
MC 9690         case 'ebcdicatdea':
9691             return 'EBCDIC-AT-DE-A';
fd9ef2 9692
b1a6a5 9693         case 'csebcdiccafr':
MC 9694         case 'ebcdiccafr':
9695             return 'EBCDIC-CA-FR';
fd9ef2 9696
b1a6a5 9697         case 'csebcdicdkno':
MC 9698         case 'ebcdicdkno':
9699             return 'EBCDIC-DK-NO';
fd9ef2 9700
b1a6a5 9701         case 'csebcdicdknoa':
MC 9702         case 'ebcdicdknoa':
9703             return 'EBCDIC-DK-NO-A';
fd9ef2 9704
b1a6a5 9705         case 'csebcdices':
MC 9706         case 'ebcdices':
9707             return 'EBCDIC-ES';
fd9ef2 9708
b1a6a5 9709         case 'csebcdicesa':
MC 9710         case 'ebcdicesa':
9711             return 'EBCDIC-ES-A';
fd9ef2 9712
b1a6a5 9713         case 'csebcdicess':
MC 9714         case 'ebcdicess':
9715             return 'EBCDIC-ES-S';
fd9ef2 9716
b1a6a5 9717         case 'csebcdicfise':
MC 9718         case 'ebcdicfise':
9719             return 'EBCDIC-FI-SE';
fd9ef2 9720
b1a6a5 9721         case 'csebcdicfisea':
MC 9722         case 'ebcdicfisea':
9723             return 'EBCDIC-FI-SE-A';
fd9ef2 9724
b1a6a5 9725         case 'csebcdicfr':
MC 9726         case 'ebcdicfr':
9727             return 'EBCDIC-FR';
fd9ef2 9728
b1a6a5 9729         case 'csebcdicit':
MC 9730         case 'ebcdicit':
9731             return 'EBCDIC-IT';
fd9ef2 9732
b1a6a5 9733         case 'csebcdicpt':
MC 9734         case 'ebcdicpt':
9735             return 'EBCDIC-PT';
fd9ef2 9736
b1a6a5 9737         case 'csebcdicuk':
MC 9738         case 'ebcdicuk':
9739             return 'EBCDIC-UK';
fd9ef2 9740
b1a6a5 9741         case 'csebcdicus':
MC 9742         case 'ebcdicus':
9743             return 'EBCDIC-US';
fd9ef2 9744
b1a6a5 9745         case 'csiso111ecmacyrillic':
MC 9746         case 'ecmacyrillic':
9747         case 'isoir111':
9748         case 'koi8e':
9749             return 'ECMA-cyrillic';
fd9ef2 9750
b1a6a5 9751         case 'csiso17spanish':
MC 9752         case 'es':
9753         case 'iso646es':
9754         case 'isoir17':
9755             return 'ES';
fd9ef2 9756
b1a6a5 9757         case 'csiso85spanish2':
MC 9758         case 'es2':
9759         case 'iso646es2':
9760         case 'isoir85':
9761             return 'ES2';
fd9ef2 9762
b1a6a5 9763         case 'cseucfixwidjapanese':
MC 9764         case 'extendedunixcodefixedwidthforjapanese':
9765             return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
fd9ef2 9766
b1a6a5 9767         case 'cseucpkdfmtjapanese':
MC 9768         case 'eucjp':
9769         case 'extendedunixcodepackedformatforjapanese':
9770             return 'Extended_UNIX_Code_Packed_Format_for_Japanese';
fd9ef2 9771
b1a6a5 9772         case 'gb18030':
MC 9773             return 'GB18030';
fd9ef2 9774
b1a6a5 9775         case 'chinese':
MC 9776         case 'cp936':
9777         case 'csgb2312':
9778         case 'csiso58gb231280':
9779         case 'gb2312':
9780         case 'gb231280':
9781         case 'gbk':
9782         case 'isoir58':
9783         case 'ms936':
9784         case 'windows936':
9785             return 'GBK';
fd9ef2 9786
b1a6a5 9787         case 'cn':
MC 9788         case 'csiso57gb1988':
9789         case 'gb198880':
9790         case 'iso646cn':
9791         case 'isoir57':
9792             return 'GB_1988-80';
fd9ef2 9793
b1a6a5 9794         case 'csiso153gost1976874':
MC 9795         case 'gost1976874':
9796         case 'isoir153':
9797         case 'stsev35888':
9798             return 'GOST_19768-74';
fd9ef2 9799
b1a6a5 9800         case 'csiso150':
MC 9801         case 'csiso150greekccitt':
9802         case 'greekccitt':
9803         case 'isoir150':
9804             return 'greek-ccitt';
fd9ef2 9805
b1a6a5 9806         case 'csiso88greek7':
MC 9807         case 'greek7':
9808         case 'isoir88':
9809             return 'greek7';
fd9ef2 9810
b1a6a5 9811         case 'csiso18greek7old':
MC 9812         case 'greek7old':
9813         case 'isoir18':
9814             return 'greek7-old';
fd9ef2 9815
b1a6a5 9816         case 'cshpdesktop':
MC 9817         case 'hpdesktop':
9818             return 'HP-DeskTop';
fd9ef2 9819
b1a6a5 9820         case 'cshplegal':
MC 9821         case 'hplegal':
9822             return 'HP-Legal';
fd9ef2 9823
b1a6a5 9824         case 'cshpmath8':
MC 9825         case 'hpmath8':
9826             return 'HP-Math8';
fd9ef2 9827
b1a6a5 9828         case 'cshppifont':
MC 9829         case 'hppifont':
9830             return 'HP-Pi-font';
fd9ef2 9831
b1a6a5 9832         case 'cshproman8':
MC 9833         case 'hproman8':
9834         case 'r8':
9835         case 'roman8':
9836             return 'hp-roman8';
fd9ef2 9837
b1a6a5 9838         case 'hzgb2312':
MC 9839             return 'HZ-GB-2312';
fd9ef2 9840
b1a6a5 9841         case 'csibmsymbols':
MC 9842         case 'ibmsymbols':
9843             return 'IBM-Symbols';
fd9ef2 9844
b1a6a5 9845         case 'csibmthai':
MC 9846         case 'ibmthai':
9847             return 'IBM-Thai';
fd9ef2 9848
b1a6a5 9849         case 'ccsid858':
MC 9850         case 'cp858':
9851         case 'ibm858':
9852         case 'pcmultilingual850euro':
9853             return 'IBM00858';
fd9ef2 9854
b1a6a5 9855         case 'ccsid924':
MC 9856         case 'cp924':
9857         case 'ebcdiclatin9euro':
9858         case 'ibm924':
9859             return 'IBM00924';
fd9ef2 9860
b1a6a5 9861         case 'ccsid1140':
MC 9862         case 'cp1140':
9863         case 'ebcdicus37euro':
9864         case 'ibm1140':
9865             return 'IBM01140';
fd9ef2 9866
b1a6a5 9867         case 'ccsid1141':
MC 9868         case 'cp1141':
9869         case 'ebcdicde273euro':
9870         case 'ibm1141':
9871             return 'IBM01141';
fd9ef2 9872
b1a6a5 9873         case 'ccsid1142':
MC 9874         case 'cp1142':
9875         case 'ebcdicdk277euro':
9876         case 'ebcdicno277euro':
9877         case 'ibm1142':
9878             return 'IBM01142';
fd9ef2 9879
b1a6a5 9880         case 'ccsid1143':
MC 9881         case 'cp1143':
9882         case 'ebcdicfi278euro':
9883         case 'ebcdicse278euro':
9884         case 'ibm1143':
9885             return 'IBM01143';
fd9ef2 9886
b1a6a5 9887         case 'ccsid1144':
MC 9888         case 'cp1144':
9889         case 'ebcdicit280euro':
9890         case 'ibm1144':
9891             return 'IBM01144';
fd9ef2 9892
b1a6a5 9893         case 'ccsid1145':
MC 9894         case 'cp1145':
9895         case 'ebcdices284euro':
9896         case 'ibm1145':
9897             return 'IBM01145';
fd9ef2 9898
b1a6a5 9899         case 'ccsid1146':
MC 9900         case 'cp1146':
9901         case 'ebcdicgb285euro':
9902         case 'ibm1146':
9903             return 'IBM01146';
fd9ef2 9904
b1a6a5 9905         case 'ccsid1147':
MC 9906         case 'cp1147':
9907         case 'ebcdicfr297euro':
9908         case 'ibm1147':
9909             return 'IBM01147';
fd9ef2 9910
b1a6a5 9911         case 'ccsid1148':
MC 9912         case 'cp1148':
9913         case 'ebcdicinternational500euro':
9914         case 'ibm1148':
9915             return 'IBM01148';
fd9ef2 9916
b1a6a5 9917         case 'ccsid1149':
MC 9918         case 'cp1149':
9919         case 'ebcdicis871euro':
9920         case 'ibm1149':
9921             return 'IBM01149';
fd9ef2 9922
b1a6a5 9923         case 'cp37':
MC 9924         case 'csibm37':
9925         case 'ebcdiccpca':
9926         case 'ebcdiccpnl':
9927         case 'ebcdiccpus':
9928         case 'ebcdiccpwt':
9929         case 'ibm37':
9930             return 'IBM037';
fd9ef2 9931
b1a6a5 9932         case 'cp38':
MC 9933         case 'csibm38':
9934         case 'ebcdicint':
9935         case 'ibm38':
9936             return 'IBM038';
fd9ef2 9937
b1a6a5 9938         case 'cp273':
MC 9939         case 'csibm273':
9940         case 'ibm273':
9941             return 'IBM273';
fd9ef2 9942
b1a6a5 9943         case 'cp274':
MC 9944         case 'csibm274':
9945         case 'ebcdicbe':
9946         case 'ibm274':
9947             return 'IBM274';
fd9ef2 9948
b1a6a5 9949         case 'cp275':
MC 9950         case 'csibm275':
9951         case 'ebcdicbr':
9952         case 'ibm275':
9953             return 'IBM275';
fd9ef2 9954
b1a6a5 9955         case 'csibm277':
MC 9956         case 'ebcdiccpdk':
9957         case 'ebcdiccpno':
9958         case 'ibm277':
9959             return 'IBM277';
fd9ef2 9960
b1a6a5 9961         case 'cp278':
MC 9962         case 'csibm278':
9963         case 'ebcdiccpfi':
9964         case 'ebcdiccpse':
9965         case 'ibm278':
9966             return 'IBM278';
fd9ef2 9967
b1a6a5 9968         case 'cp280':
MC 9969         case 'csibm280':
9970         case 'ebcdiccpit':
9971         case 'ibm280':
9972             return 'IBM280';
fd9ef2 9973
b1a6a5 9974         case 'cp281':
MC 9975         case 'csibm281':
9976         case 'ebcdicjpe':
9977         case 'ibm281':
9978             return 'IBM281';
fd9ef2 9979
b1a6a5 9980         case 'cp284':
MC 9981         case 'csibm284':
9982         case 'ebcdiccpes':
9983         case 'ibm284':
9984             return 'IBM284';
fd9ef2 9985
b1a6a5 9986         case 'cp285':
MC 9987         case 'csibm285':
9988         case 'ebcdiccpgb':
9989         case 'ibm285':
9990             return 'IBM285';
fd9ef2 9991
b1a6a5 9992         case 'cp290':
MC 9993         case 'csibm290':
9994         case 'ebcdicjpkana':
9995         case 'ibm290':
9996             return 'IBM290';
fd9ef2 9997
b1a6a5 9998         case 'cp297':
MC 9999         case 'csibm297':
10000         case 'ebcdiccpfr':
10001         case 'ibm297':
10002             return 'IBM297';
fd9ef2 10003
b1a6a5 10004         case 'cp420':
MC 10005         case 'csibm420':
10006         case 'ebcdiccpar1':
10007         case 'ibm420':
10008             return 'IBM420';
fd9ef2 10009
b1a6a5 10010         case 'cp423':
MC 10011         case 'csibm423':
10012         case 'ebcdiccpgr':
10013         case 'ibm423':
10014             return 'IBM423';
fd9ef2 10015
b1a6a5 10016         case 'cp424':
MC 10017         case 'csibm424':
10018         case 'ebcdiccphe':
10019         case 'ibm424':
10020             return 'IBM424';
fd9ef2 10021
b1a6a5 10022         case '437':
MC 10023         case 'cp437':
10024         case 'cspc8codepage437':
10025         case 'ibm437':
10026             return 'IBM437';
fd9ef2 10027
b1a6a5 10028         case 'cp500':
MC 10029         case 'csibm500':
10030         case 'ebcdiccpbe':
10031         case 'ebcdiccpch':
10032         case 'ibm500':
10033             return 'IBM500';
fd9ef2 10034
b1a6a5 10035         case 'cp775':
MC 10036         case 'cspc775baltic':
10037         case 'ibm775':
10038             return 'IBM775';
fd9ef2 10039
b1a6a5 10040         case '850':
MC 10041         case 'cp850':
10042         case 'cspc850multilingual':
10043         case 'ibm850':
10044             return 'IBM850';
fd9ef2 10045
b1a6a5 10046         case '851':
MC 10047         case 'cp851':
10048         case 'csibm851':
10049         case 'ibm851':
10050             return 'IBM851';
fd9ef2 10051
b1a6a5 10052         case '852':
MC 10053         case 'cp852':
10054         case 'cspcp852':
10055         case 'ibm852':
10056             return 'IBM852';
fd9ef2 10057
b1a6a5 10058         case '855':
MC 10059         case 'cp855':
10060         case 'csibm855':
10061         case 'ibm855':
10062             return 'IBM855';
fd9ef2 10063
b1a6a5 10064         case '857':
MC 10065         case 'cp857':
10066         case 'csibm857':
10067         case 'ibm857':
10068             return 'IBM857';
fd9ef2 10069
b1a6a5 10070         case '860':
MC 10071         case 'cp860':
10072         case 'csibm860':
10073         case 'ibm860':
10074             return 'IBM860';
fd9ef2 10075
b1a6a5 10076         case '861':
MC 10077         case 'cp861':
10078         case 'cpis':
10079         case 'csibm861':
10080         case 'ibm861':
10081             return 'IBM861';
fd9ef2 10082
b1a6a5 10083         case '862':
MC 10084         case 'cp862':
10085         case 'cspc862latinhebrew':
10086         case 'ibm862':
10087             return 'IBM862';
fd9ef2 10088
b1a6a5 10089         case '863':
MC 10090         case 'cp863':
10091         case 'csibm863':
10092         case 'ibm863':
10093             return 'IBM863';
fd9ef2 10094
b1a6a5 10095         case 'cp864':
MC 10096         case 'csibm864':
10097         case 'ibm864':
10098             return 'IBM864';
fd9ef2 10099
b1a6a5 10100         case '865':
MC 10101         case 'cp865':
10102         case 'csibm865':
10103         case 'ibm865':
10104             return 'IBM865';
fd9ef2 10105
b1a6a5 10106         case '866':
MC 10107         case 'cp866':
10108         case 'csibm866':
10109         case 'ibm866':
10110             return 'IBM866';
fd9ef2 10111
b1a6a5 10112         case 'cp868':
MC 10113         case 'cpar':
10114         case 'csibm868':
10115         case 'ibm868':
10116             return 'IBM868';
fd9ef2 10117
b1a6a5 10118         case '869':
MC 10119         case 'cp869':
10120         case 'cpgr':
10121         case 'csibm869':
10122         case 'ibm869':
10123             return 'IBM869';
fd9ef2 10124
b1a6a5 10125         case 'cp870':
MC 10126         case 'csibm870':
10127         case 'ebcdiccproece':
10128         case 'ebcdiccpyu':
10129         case 'ibm870':
10130             return 'IBM870';
fd9ef2 10131
b1a6a5 10132         case 'cp871':
MC 10133         case 'csibm871':
10134         case 'ebcdiccpis':
10135         case 'ibm871':
10136             return 'IBM871';
fd9ef2 10137
b1a6a5 10138         case 'cp880':
MC 10139         case 'csibm880':
10140         case 'ebcdiccyrillic':
10141         case 'ibm880':
10142             return 'IBM880';
fd9ef2 10143
b1a6a5 10144         case 'cp891':
MC 10145         case 'csibm891':
10146         case 'ibm891':
10147             return 'IBM891';
fd9ef2 10148
b1a6a5 10149         case 'cp903':
MC 10150         case 'csibm903':
10151         case 'ibm903':
10152             return 'IBM903';
fd9ef2 10153
b1a6a5 10154         case '904':
MC 10155         case 'cp904':
10156         case 'csibbm904':
10157         case 'ibm904':
10158             return 'IBM904';
fd9ef2 10159
b1a6a5 10160         case 'cp905':
MC 10161         case 'csibm905':
10162         case 'ebcdiccptr':
10163         case 'ibm905':
10164             return 'IBM905';
fd9ef2 10165
b1a6a5 10166         case 'cp918':
MC 10167         case 'csibm918':
10168         case 'ebcdiccpar2':
10169         case 'ibm918':
10170             return 'IBM918';
fd9ef2 10171
b1a6a5 10172         case 'cp1026':
MC 10173         case 'csibm1026':
10174         case 'ibm1026':
10175             return 'IBM1026';
fd9ef2 10176
b1a6a5 10177         case 'ibm1047':
MC 10178             return 'IBM1047';
fd9ef2 10179
b1a6a5 10180         case 'csiso143iecp271':
MC 10181         case 'iecp271':
10182         case 'isoir143':
10183             return 'IEC_P27-1';
fd9ef2 10184
b1a6a5 10185         case 'csiso49inis':
MC 10186         case 'inis':
10187         case 'isoir49':
10188             return 'INIS';
fd9ef2 10189
b1a6a5 10190         case 'csiso50inis8':
MC 10191         case 'inis8':
10192         case 'isoir50':
10193             return 'INIS-8';
fd9ef2 10194
b1a6a5 10195         case 'csiso51iniscyrillic':
MC 10196         case 'iniscyrillic':
10197         case 'isoir51':
10198             return 'INIS-cyrillic';
fd9ef2 10199
b1a6a5 10200         case 'csinvariant':
MC 10201         case 'invariant':
10202             return 'INVARIANT';
fd9ef2 10203
b1a6a5 10204         case 'iso2022cn':
MC 10205             return 'ISO-2022-CN';
fd9ef2 10206
b1a6a5 10207         case 'iso2022cnext':
MC 10208             return 'ISO-2022-CN-EXT';
fd9ef2 10209
b1a6a5 10210         case 'csiso2022jp':
MC 10211         case 'iso2022jp':
10212             return 'ISO-2022-JP';
fd9ef2 10213
b1a6a5 10214         case 'csiso2022jp2':
MC 10215         case 'iso2022jp2':
10216             return 'ISO-2022-JP-2';
fd9ef2 10217
b1a6a5 10218         case 'csiso2022kr':
MC 10219         case 'iso2022kr':
10220             return 'ISO-2022-KR';
fd9ef2 10221
b1a6a5 10222         case 'cswindows30latin1':
MC 10223         case 'iso88591windows30latin1':
10224             return 'ISO-8859-1-Windows-3.0-Latin-1';
fd9ef2 10225
b1a6a5 10226         case 'cswindows31latin1':
MC 10227         case 'iso88591windows31latin1':
10228             return 'ISO-8859-1-Windows-3.1-Latin-1';
fd9ef2 10229
b1a6a5 10230         case 'csisolatin2':
MC 10231         case 'iso88592':
10232         case 'iso885921987':
10233         case 'isoir101':
10234         case 'l2':
10235         case 'latin2':
10236             return 'ISO-8859-2';
fd9ef2 10237
b1a6a5 10238         case 'cswindows31latin2':
MC 10239         case 'iso88592windowslatin2':
10240             return 'ISO-8859-2-Windows-Latin-2';
fd9ef2 10241
b1a6a5 10242         case 'csisolatin3':
MC 10243         case 'iso88593':
10244         case 'iso885931988':
10245         case 'isoir109':
10246         case 'l3':
10247         case 'latin3':
10248             return 'ISO-8859-3';
fd9ef2 10249
b1a6a5 10250         case 'csisolatin4':
MC 10251         case 'iso88594':
10252         case 'iso885941988':
10253         case 'isoir110':
10254         case 'l4':
10255         case 'latin4':
10256             return 'ISO-8859-4';
fd9ef2 10257
b1a6a5 10258         case 'csisolatincyrillic':
MC 10259         case 'cyrillic':
10260         case 'iso88595':
10261         case 'iso885951988':
10262         case 'isoir144':
10263             return 'ISO-8859-5';
fd9ef2 10264
b1a6a5 10265         case 'arabic':
MC 10266         case 'asmo708':
10267         case 'csisolatinarabic':
10268         case 'ecma114':
10269         case 'iso88596':
10270         case 'iso885961987':
10271         case 'isoir127':
10272             return 'ISO-8859-6';
fd9ef2 10273
b1a6a5 10274         case 'csiso88596e':
MC 10275         case 'iso88596e':
10276             return 'ISO-8859-6-E';
fd9ef2 10277
b1a6a5 10278         case 'csiso88596i':
MC 10279         case 'iso88596i':
10280             return 'ISO-8859-6-I';
fd9ef2 10281
b1a6a5 10282         case 'csisolatingreek':
MC 10283         case 'ecma118':
10284         case 'elot928':
10285         case 'greek':
10286         case 'greek8':
10287         case 'iso88597':
10288         case 'iso885971987':
10289         case 'isoir126':
10290             return 'ISO-8859-7';
fd9ef2 10291
b1a6a5 10292         case 'csisolatinhebrew':
MC 10293         case 'hebrew':
10294         case 'iso88598':
10295         case 'iso885981988':
10296         case 'isoir138':
10297             return 'ISO-8859-8';
fd9ef2 10298
b1a6a5 10299         case 'csiso88598e':
MC 10300         case 'iso88598e':
10301             return 'ISO-8859-8-E';
fd9ef2 10302
b1a6a5 10303         case 'csiso88598i':
MC 10304         case 'iso88598i':
10305             return 'ISO-8859-8-I';
fd9ef2 10306
b1a6a5 10307         case 'cswindows31latin5':
MC 10308         case 'iso88599windowslatin5':
10309             return 'ISO-8859-9-Windows-Latin-5';
fd9ef2 10310
b1a6a5 10311         case 'csisolatin6':
MC 10312         case 'iso885910':
10313         case 'iso8859101992':
10314         case 'isoir157':
10315         case 'l6':
10316         case 'latin6':
10317             return 'ISO-8859-10';
fd9ef2 10318
b1a6a5 10319         case 'iso885913':
MC 10320             return 'ISO-8859-13';
fd9ef2 10321
b1a6a5 10322         case 'iso885914':
MC 10323         case 'iso8859141998':
10324         case 'isoceltic':
10325         case 'isoir199':
10326         case 'l8':
10327         case 'latin8':
10328             return 'ISO-8859-14';
fd9ef2 10329
b1a6a5 10330         case 'iso885915':
MC 10331         case 'latin9':
10332             return 'ISO-8859-15';
fd9ef2 10333
b1a6a5 10334         case 'iso885916':
MC 10335         case 'iso8859162001':
10336         case 'isoir226':
10337         case 'l10':
10338         case 'latin10':
10339             return 'ISO-8859-16';
fd9ef2 10340
b1a6a5 10341         case 'iso10646j1':
MC 10342             return 'ISO-10646-J-1';
fd9ef2 10343
b1a6a5 10344         case 'csunicode':
MC 10345         case 'iso10646ucs2':
10346             return 'ISO-10646-UCS-2';
fd9ef2 10347
b1a6a5 10348         case 'csucs4':
MC 10349         case 'iso10646ucs4':
10350             return 'ISO-10646-UCS-4';
fd9ef2 10351
b1a6a5 10352         case 'csunicodeascii':
MC 10353         case 'iso10646ucsbasic':
10354             return 'ISO-10646-UCS-Basic';
fd9ef2 10355
b1a6a5 10356         case 'csunicodelatin1':
MC 10357         case 'iso10646':
10358         case 'iso10646unicodelatin1':
10359             return 'ISO-10646-Unicode-Latin1';
fd9ef2 10360
b1a6a5 10361         case 'csiso10646utf1':
MC 10362         case 'iso10646utf1':
10363             return 'ISO-10646-UTF-1';
fd9ef2 10364
b1a6a5 10365         case 'csiso115481':
MC 10366         case 'iso115481':
10367         case 'isotr115481':
10368             return 'ISO-11548-1';
fd9ef2 10369
b1a6a5 10370         case 'csiso90':
MC 10371         case 'isoir90':
10372             return 'iso-ir-90';
fd9ef2 10373
b1a6a5 10374         case 'csunicodeibm1261':
MC 10375         case 'isounicodeibm1261':
10376             return 'ISO-Unicode-IBM-1261';
fd9ef2 10377
b1a6a5 10378         case 'csunicodeibm1264':
MC 10379         case 'isounicodeibm1264':
10380             return 'ISO-Unicode-IBM-1264';
fd9ef2 10381
b1a6a5 10382         case 'csunicodeibm1265':
MC 10383         case 'isounicodeibm1265':
10384             return 'ISO-Unicode-IBM-1265';
fd9ef2 10385
b1a6a5 10386         case 'csunicodeibm1268':
MC 10387         case 'isounicodeibm1268':
10388             return 'ISO-Unicode-IBM-1268';
fd9ef2 10389
b1a6a5 10390         case 'csunicodeibm1276':
MC 10391         case 'isounicodeibm1276':
10392             return 'ISO-Unicode-IBM-1276';
fd9ef2 10393
b1a6a5 10394         case 'csiso646basic1983':
MC 10395         case 'iso646basic1983':
10396         case 'ref':
10397             return 'ISO_646.basic:1983';
fd9ef2 10398
b1a6a5 10399         case 'csiso2intlrefversion':
MC 10400         case 'irv':
10401         case 'iso646irv1983':
10402         case 'isoir2':
10403             return 'ISO_646.irv:1983';
fd9ef2 10404
b1a6a5 10405         case 'csiso2033':
MC 10406         case 'e13b':
10407         case 'iso20331983':
10408         case 'isoir98':
10409             return 'ISO_2033-1983';
fd9ef2 10410
b1a6a5 10411         case 'csiso5427cyrillic':
MC 10412         case 'iso5427':
10413         case 'isoir37':
10414             return 'ISO_5427';
fd9ef2 10415
b1a6a5 10416         case 'iso5427cyrillic1981':
MC 10417         case 'iso54271981':
10418         case 'isoir54':
10419             return 'ISO_5427:1981';
fd9ef2 10420
b1a6a5 10421         case 'csiso5428greek':
MC 10422         case 'iso54281980':
10423         case 'isoir55':
10424             return 'ISO_5428:1980';
fd9ef2 10425
b1a6a5 10426         case 'csiso6937add':
MC 10427         case 'iso6937225':
10428         case 'isoir152':
10429             return 'ISO_6937-2-25';
fd9ef2 10430
b1a6a5 10431         case 'csisotextcomm':
MC 10432         case 'iso69372add':
10433         case 'isoir142':
10434             return 'ISO_6937-2-add';
fd9ef2 10435
b1a6a5 10436         case 'csiso8859supp':
MC 10437         case 'iso8859supp':
10438         case 'isoir154':
10439         case 'latin125':
10440             return 'ISO_8859-supp';
fd9ef2 10441
b1a6a5 10442         case 'csiso10367box':
MC 10443         case 'iso10367box':
10444         case 'isoir155':
10445             return 'ISO_10367-box';
fd9ef2 10446
b1a6a5 10447         case 'csiso15italian':
MC 10448         case 'iso646it':
10449         case 'isoir15':
10450         case 'it':
10451             return 'IT';
fd9ef2 10452
b1a6a5 10453         case 'csiso13jisc6220jp':
MC 10454         case 'isoir13':
10455         case 'jisc62201969':
10456         case 'jisc62201969jp':
10457         case 'katakana':
10458         case 'x2017':
10459             return 'JIS_C6220-1969-jp';
fd9ef2 10460
b1a6a5 10461         case 'csiso14jisc6220ro':
MC 10462         case 'iso646jp':
10463         case 'isoir14':
10464         case 'jisc62201969ro':
10465         case 'jp':
10466             return 'JIS_C6220-1969-ro';
fd9ef2 10467
b1a6a5 10468         case 'csiso42jisc62261978':
MC 10469         case 'isoir42':
10470         case 'jisc62261978':
10471             return 'JIS_C6226-1978';
fd9ef2 10472
b1a6a5 10473         case 'csiso87jisx208':
MC 10474         case 'isoir87':
10475         case 'jisc62261983':
10476         case 'jisx2081983':
10477         case 'x208':
10478             return 'JIS_C6226-1983';
fd9ef2 10479
b1a6a5 10480         case 'csiso91jisc62291984a':
MC 10481         case 'isoir91':
10482         case 'jisc62291984a':
10483         case 'jpocra':
10484             return 'JIS_C6229-1984-a';
fd9ef2 10485
b1a6a5 10486         case 'csiso92jisc62991984b':
MC 10487         case 'iso646jpocrb':
10488         case 'isoir92':
10489         case 'jisc62291984b':
10490         case 'jpocrb':
10491             return 'JIS_C6229-1984-b';
fd9ef2 10492
b1a6a5 10493         case 'csiso93jis62291984badd':
MC 10494         case 'isoir93':
10495         case 'jisc62291984badd':
10496         case 'jpocrbadd':
10497             return 'JIS_C6229-1984-b-add';
fd9ef2 10498
b1a6a5 10499         case 'csiso94jis62291984hand':
MC 10500         case 'isoir94':
10501         case 'jisc62291984hand':
10502         case 'jpocrhand':
10503             return 'JIS_C6229-1984-hand';
fd9ef2 10504
b1a6a5 10505         case 'csiso95jis62291984handadd':
MC 10506         case 'isoir95':
10507         case 'jisc62291984handadd':
10508         case 'jpocrhandadd':
10509             return 'JIS_C6229-1984-hand-add';
fd9ef2 10510
b1a6a5 10511         case 'csiso96jisc62291984kana':
MC 10512         case 'isoir96':
10513         case 'jisc62291984kana':
10514             return 'JIS_C6229-1984-kana';
fd9ef2 10515
b1a6a5 10516         case 'csjisencoding':
MC 10517         case 'jisencoding':
10518             return 'JIS_Encoding';
fd9ef2 10519
b1a6a5 10520         case 'cshalfwidthkatakana':
MC 10521         case 'jisx201':
10522         case 'x201':
10523             return 'JIS_X0201';
fd9ef2 10524
b1a6a5 10525         case 'csiso159jisx2121990':
MC 10526         case 'isoir159':
10527         case 'jisx2121990':
10528         case 'x212':
10529             return 'JIS_X0212-1990';
fd9ef2 10530
b1a6a5 10531         case 'csiso141jusib1002':
MC 10532         case 'iso646yu':
10533         case 'isoir141':
10534         case 'js':
10535         case 'jusib1002':
10536         case 'yu':
10537             return 'JUS_I.B1.002';
fd9ef2 10538
b1a6a5 10539         case 'csiso147macedonian':
MC 10540         case 'isoir147':
10541         case 'jusib1003mac':
10542         case 'macedonian':
10543             return 'JUS_I.B1.003-mac';
fd9ef2 10544
b1a6a5 10545         case 'csiso146serbian':
MC 10546         case 'isoir146':
10547         case 'jusib1003serb':
10548         case 'serbian':
10549             return 'JUS_I.B1.003-serb';
fd9ef2 10550
b1a6a5 10551         case 'koi7switched':
MC 10552             return 'KOI7-switched';
fd9ef2 10553
b1a6a5 10554         case 'cskoi8r':
MC 10555         case 'koi8r':
10556             return 'KOI8-R';
fd9ef2 10557
b1a6a5 10558         case 'koi8u':
MC 10559             return 'KOI8-U';
fd9ef2 10560
b1a6a5 10561         case 'csksc5636':
MC 10562         case 'iso646kr':
10563         case 'ksc5636':
10564             return 'KSC5636';
fd9ef2 10565
b1a6a5 10566         case 'cskz1048':
MC 10567         case 'kz1048':
10568         case 'rk1048':
10569         case 'strk10482002':
10570             return 'KZ-1048';
fd9ef2 10571
b1a6a5 10572         case 'csiso19latingreek':
MC 10573         case 'isoir19':
10574         case 'latingreek':
10575             return 'latin-greek';
fd9ef2 10576
b1a6a5 10577         case 'csiso27latingreek1':
MC 10578         case 'isoir27':
10579         case 'latingreek1':
10580             return 'Latin-greek-1';
fd9ef2 10581
b1a6a5 10582         case 'csiso158lap':
MC 10583         case 'isoir158':
10584         case 'lap':
10585         case 'latinlap':
10586             return 'latin-lap';
fd9ef2 10587
b1a6a5 10588         case 'csmacintosh':
MC 10589         case 'mac':
10590         case 'macintosh':
10591             return 'macintosh';
fd9ef2 10592
b1a6a5 10593         case 'csmicrosoftpublishing':
MC 10594         case 'microsoftpublishing':
10595             return 'Microsoft-Publishing';
fd9ef2 10596
b1a6a5 10597         case 'csmnem':
MC 10598         case 'mnem':
10599             return 'MNEM';
fd9ef2 10600
b1a6a5 10601         case 'csmnemonic':
MC 10602         case 'mnemonic':
10603             return 'MNEMONIC';
fd9ef2 10604
b1a6a5 10605         case 'csiso86hungarian':
MC 10606         case 'hu':
10607         case 'iso646hu':
10608         case 'isoir86':
10609         case 'msz77953':
10610             return 'MSZ_7795.3';
fd9ef2 10611
b1a6a5 10612         case 'csnatsdano':
MC 10613         case 'isoir91':
10614         case 'natsdano':
10615             return 'NATS-DANO';
fd9ef2 10616
b1a6a5 10617         case 'csnatsdanoadd':
MC 10618         case 'isoir92':
10619         case 'natsdanoadd':
10620             return 'NATS-DANO-ADD';
fd9ef2 10621
b1a6a5 10622         case 'csnatssefi':
MC 10623         case 'isoir81':
10624         case 'natssefi':
10625             return 'NATS-SEFI';
fd9ef2 10626
b1a6a5 10627         case 'csnatssefiadd':
MC 10628         case 'isoir82':
10629         case 'natssefiadd':
10630             return 'NATS-SEFI-ADD';
fd9ef2 10631
b1a6a5 10632         case 'csiso151cuba':
MC 10633         case 'cuba':
10634         case 'iso646cu':
10635         case 'isoir151':
10636         case 'ncnc1081':
10637             return 'NC_NC00-10:81';
fd9ef2 10638
b1a6a5 10639         case 'csiso69french':
MC 10640         case 'fr':
10641         case 'iso646fr':
10642         case 'isoir69':
10643         case 'nfz62010':
10644             return 'NF_Z_62-010';
fd9ef2 10645
b1a6a5 10646         case 'csiso25french':
MC 10647         case 'iso646fr1':
10648         case 'isoir25':
10649         case 'nfz620101973':
10650             return 'NF_Z_62-010_(1973)';
fd9ef2 10651
b1a6a5 10652         case 'csiso60danishnorwegian':
MC 10653         case 'csiso60norwegian1':
10654         case 'iso646no':
10655         case 'isoir60':
10656         case 'no':
10657         case 'ns45511':
10658             return 'NS_4551-1';
fd9ef2 10659
b1a6a5 10660         case 'csiso61norwegian2':
MC 10661         case 'iso646no2':
10662         case 'isoir61':
10663         case 'no2':
10664         case 'ns45512':
10665             return 'NS_4551-2';
fd9ef2 10666
b1a6a5 10667         case 'osdebcdicdf3irv':
MC 10668             return 'OSD_EBCDIC_DF03_IRV';
fd9ef2 10669
b1a6a5 10670         case 'osdebcdicdf41':
MC 10671             return 'OSD_EBCDIC_DF04_1';
fd9ef2 10672
b1a6a5 10673         case 'osdebcdicdf415':
MC 10674             return 'OSD_EBCDIC_DF04_15';
fd9ef2 10675
b1a6a5 10676         case 'cspc8danishnorwegian':
MC 10677         case 'pc8danishnorwegian':
10678             return 'PC8-Danish-Norwegian';
fd9ef2 10679
b1a6a5 10680         case 'cspc8turkish':
MC 10681         case 'pc8turkish':
10682             return 'PC8-Turkish';
fd9ef2 10683
b1a6a5 10684         case 'csiso16portuguese':
MC 10685         case 'iso646pt':
10686         case 'isoir16':
10687         case 'pt':
10688             return 'PT';
fd9ef2 10689
b1a6a5 10690         case 'csiso84portuguese2':
MC 10691         case 'iso646pt2':
10692         case 'isoir84':
10693         case 'pt2':
10694             return 'PT2';
fd9ef2 10695
b1a6a5 10696         case 'cp154':
MC 10697         case 'csptcp154':
10698         case 'cyrillicasian':
10699         case 'pt154':
10700         case 'ptcp154':
10701             return 'PTCP154';
fd9ef2 10702
b1a6a5 10703         case 'scsu':
MC 10704             return 'SCSU';
fd9ef2 10705
b1a6a5 10706         case 'csiso10swedish':
MC 10707         case 'fi':
10708         case 'iso646fi':
10709         case 'iso646se':
10710         case 'isoir10':
10711         case 'se':
10712         case 'sen850200b':
10713             return 'SEN_850200_B';
fd9ef2 10714
b1a6a5 10715         case 'csiso11swedishfornames':
MC 10716         case 'iso646se2':
10717         case 'isoir11':
10718         case 'se2':
10719         case 'sen850200c':
10720             return 'SEN_850200_C';
fd9ef2 10721
b1a6a5 10722         case 'csshiftjis':
MC 10723         case 'mskanji':
10724         case 'shiftjis':
10725             return 'Shift_JIS';
fd9ef2 10726
b1a6a5 10727         case 'csiso102t617bit':
MC 10728         case 'isoir102':
10729         case 't617bit':
10730             return 'T.61-7bit';
fd9ef2 10731
b1a6a5 10732         case 'csiso103t618bit':
MC 10733         case 'isoir103':
10734         case 't61':
10735         case 't618bit':
10736             return 'T.61-8bit';
fd9ef2 10737
b1a6a5 10738         case 'csiso128t101g2':
MC 10739         case 'isoir128':
10740         case 't101g2':
10741             return 'T.101-G2';
fd9ef2 10742
b1a6a5 10743         case 'cstscii':
MC 10744         case 'tscii':
10745             return 'TSCII';
fd9ef2 10746
b1a6a5 10747         case 'csunicode11':
MC 10748         case 'unicode11':
10749             return 'UNICODE-1-1';
fd9ef2 10750
b1a6a5 10751         case 'csunicode11utf7':
MC 10752         case 'unicode11utf7':
10753             return 'UNICODE-1-1-UTF-7';
fd9ef2 10754
b1a6a5 10755         case 'csunknown8bit':
MC 10756         case 'unknown8bit':
10757             return 'UNKNOWN-8BIT';
fd9ef2 10758
b1a6a5 10759         case 'ansix341968':
MC 10760         case 'ansix341986':
10761         case 'ascii':
10762         case 'cp367':
10763         case 'csascii':
10764         case 'ibm367':
10765         case 'iso646irv1991':
10766         case 'iso646us':
10767         case 'isoir6':
10768         case 'us':
10769         case 'usascii':
10770             return 'US-ASCII';
fd9ef2 10771
b1a6a5 10772         case 'csusdk':
MC 10773         case 'usdk':
10774             return 'us-dk';
fd9ef2 10775
b1a6a5 10776         case 'utf7':
MC 10777             return 'UTF-7';
fd9ef2 10778
b1a6a5 10779         case 'utf8':
MC 10780             return 'UTF-8';
fd9ef2 10781
b1a6a5 10782         case 'utf16':
MC 10783             return 'UTF-16';
fd9ef2 10784
b1a6a5 10785         case 'utf16be':
MC 10786             return 'UTF-16BE';
fd9ef2 10787
b1a6a5 10788         case 'utf16le':
MC 10789             return 'UTF-16LE';
fd9ef2 10790
b1a6a5 10791         case 'utf32':
MC 10792             return 'UTF-32';
fd9ef2 10793
b1a6a5 10794         case 'utf32be':
MC 10795             return 'UTF-32BE';
fd9ef2 10796
b1a6a5 10797         case 'utf32le':
MC 10798             return 'UTF-32LE';
fd9ef2 10799
b1a6a5 10800         case 'csventurainternational':
MC 10801         case 'venturainternational':
10802             return 'Ventura-International';
fd9ef2 10803
b1a6a5 10804         case 'csventuramath':
MC 10805         case 'venturamath':
10806             return 'Ventura-Math';
fd9ef2 10807
b1a6a5 10808         case 'csventuraus':
MC 10809         case 'venturaus':
10810             return 'Ventura-US';
fd9ef2 10811
b1a6a5 10812         case 'csiso70videotexsupp1':
MC 10813         case 'isoir70':
10814         case 'videotexsuppl':
10815             return 'videotex-suppl';
fd9ef2 10816
b1a6a5 10817         case 'csviqr':
MC 10818         case 'viqr':
10819             return 'VIQR';
fd9ef2 10820
b1a6a5 10821         case 'csviscii':
MC 10822         case 'viscii':
10823             return 'VISCII';
fd9ef2 10824
b1a6a5 10825         case 'cswindows31j':
MC 10826         case 'windows31j':
10827             return 'Windows-31J';
fd9ef2 10828
b1a6a5 10829         case 'iso885911':
MC 10830         case 'tis620':
10831             return 'windows-874';
fd9ef2 10832
b1a6a5 10833         case 'cseuckr':
MC 10834         case 'csksc56011987':
10835         case 'euckr':
10836         case 'isoir149':
10837         case 'korean':
10838         case 'ksc5601':
10839         case 'ksc56011987':
10840         case 'ksc56011989':
10841         case 'windows949':
10842             return 'windows-949';
fd9ef2 10843
b1a6a5 10844         case 'windows1250':
MC 10845             return 'windows-1250';
fd9ef2 10846
b1a6a5 10847         case 'windows1251':
MC 10848             return 'windows-1251';
fd9ef2 10849
b1a6a5 10850         case 'cp819':
MC 10851         case 'csisolatin1':
10852         case 'ibm819':
10853         case 'iso88591':
10854         case 'iso885911987':
10855         case 'isoir100':
10856         case 'l1':
10857         case 'latin1':
10858         case 'windows1252':
10859             return 'windows-1252';
fd9ef2 10860
b1a6a5 10861         case 'windows1253':
MC 10862             return 'windows-1253';
fd9ef2 10863
b1a6a5 10864         case 'csisolatin5':
MC 10865         case 'iso88599':
10866         case 'iso885991989':
10867         case 'isoir148':
10868         case 'l5':
10869         case 'latin5':
10870         case 'windows1254':
10871             return 'windows-1254';
fd9ef2 10872
b1a6a5 10873         case 'windows1255':
MC 10874             return 'windows-1255';
fd9ef2 10875
b1a6a5 10876         case 'windows1256':
MC 10877             return 'windows-1256';
fd9ef2 10878
b1a6a5 10879         case 'windows1257':
MC 10880             return 'windows-1257';
fd9ef2 10881
b1a6a5 10882         case 'windows1258':
MC 10883             return 'windows-1258';
fd9ef2 10884
b1a6a5 10885         default:
MC 10886             return $charset;
fd9ef2 10887         }
T 10888     }
10889
526b99 10890     public static function get_curl_version()
fd9ef2 10891     {
T 10892         if (is_array($curl = curl_version()))
10893         {
10894             $curl = $curl['version'];
10895         }
10896         elseif (substr($curl, 0, 5) === 'curl/')
10897         {
10898             $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10899         }
10900         elseif (substr($curl, 0, 8) === 'libcurl/')
10901         {
10902             $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10903         }
10904         else
10905         {
10906             $curl = 0;
10907         }
10908         return $curl;
10909     }
10910
10911     function is_subclass_of($class1, $class2)
10912     {
10913         if (func_num_args() !== 2)
10914         {
10915             trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10916         }
10917         elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10918         {
10919             return is_subclass_of($class1, $class2);
10920         }
10921         elseif (is_string($class1) && is_string($class2))
10922         {
10923             if (class_exists($class1))
10924             {
10925                 if (class_exists($class2))
10926                 {
10927                     $class2 = strtolower($class2);
10928                     while ($class1 = strtolower(get_parent_class($class1)))
10929                     {
10930                         if ($class1 === $class2)
10931                         {
10932                             return true;
10933                         }
10934                     }
10935                 }
10936             }
10937             else
10938             {
10939                 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10940             }
10941         }
10942         return false;
10943     }
10944
b1a6a5 10945
fd9ef2 10946     /**
T 10947      * Strip HTML comments
10948      *
10949      * @access public
10950      * @param string $data Data to strip comments from
10951      * @return string Comment stripped string
10952      */
10953     function strip_comments($data)
10954     {
10955         $output = '';
10956         while (($start = strpos($data, '<!--')) !== false)
10957         {
10958             $output .= substr($data, 0, $start);
10959             if (($end = strpos($data, '-->', $start)) !== false)
10960             {
10961                 $data = substr_replace($data, '', 0, $end + 3);
10962             }
10963             else
10964             {
10965                 $data = '';
10966             }
10967         }
10968         return $output . $data;
10969     }
10970
829b76 10971     static function parse_date($dt)
fd9ef2 10972     {
T 10973         $parser = SimplePie_Parse_Date::get();
10974         return $parser->parse($dt);
10975     }
10976
10977     /**
10978      * Decode HTML entities
10979      *
10980      * @static
10981      * @access public
10982      * @param string $data Input data
10983      * @return string Output data
10984      */
992797 10985     static function entities_decode($data)
fd9ef2 10986     {
f64c86 10987         $decoder = new SimplePie_Decode_HTML_Entities($data);
fd9ef2 10988         return $decoder->parse();
T 10989     }
10990
b1a6a5 10991
fd9ef2 10992     /**
T 10993      * Remove RFC822 comments
10994      *
10995      * @access public
10996      * @param string $data Data to strip comments from
10997      * @return string Comment stripped string
10998      */
10999     function uncomment_rfc822($string)
11000     {
11001         $string = (string) $string;
11002         $position = 0;
11003         $length = strlen($string);
11004         $depth = 0;
11005
11006         $output = '';
11007
11008         while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
11009         {
11010             $output .= substr($string, $position, $pos - $position);
11011             $position = $pos + 1;
11012             if ($string[$pos - 1] !== '\\')
11013             {
11014                 $depth++;
11015                 while ($depth && $position < $length)
11016                 {
11017                     $position += strcspn($string, '()', $position);
11018                     if ($string[$position - 1] === '\\')
11019                     {
11020                         $position++;
11021                         continue;
11022                     }
11023                     elseif (isset($string[$position]))
11024                     {
11025                         switch ($string[$position])
11026                         {
b1a6a5 11027                         case '(':
MC 11028                             $depth++;
11029                             break;
fd9ef2 11030
b1a6a5 11031                         case ')':
MC 11032                             $depth--;
11033                             break;
fd9ef2 11034                         }
T 11035                         $position++;
11036                     }
11037                     else
11038                     {
11039                         break;
11040                     }
11041                 }
11042             }
11043             else
11044             {
11045                 $output .= '(';
11046             }
11047         }
11048         $output .= substr($string, $position);
11049
11050         return $output;
11051     }
11052
11053     function parse_mime($mime)
11054     {
11055         if (($pos = strpos($mime, ';')) === false)
11056         {
11057             return trim($mime);
11058         }
11059         else
11060         {
11061             return trim(substr($mime, 0, $pos));
11062         }
11063     }
11064
11065     function htmlspecialchars_decode($string, $quote_style)
11066     {
11067         if (function_exists('htmlspecialchars_decode'))
11068         {
11069             return htmlspecialchars_decode($string, $quote_style);
11070         }
11071         else
11072         {
11073             return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
11074         }
11075     }
11076
11077     function atom_03_construct_type($attribs)
11078     {
11079         if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
11080         {
11081             $mode = SIMPLEPIE_CONSTRUCT_BASE64;
11082         }
11083         else
11084         {
11085             $mode = SIMPLEPIE_CONSTRUCT_NONE;
11086         }
11087         if (isset($attribs['']['type']))
11088         {
11089             switch (strtolower(trim($attribs['']['type'])))
11090             {
b1a6a5 11091             case 'text':
MC 11092             case 'text/plain':
11093                 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
fd9ef2 11094
b1a6a5 11095             case 'html':
MC 11096             case 'text/html':
11097                 return SIMPLEPIE_CONSTRUCT_HTML | $mode;
fd9ef2 11098
b1a6a5 11099             case 'xhtml':
MC 11100             case 'application/xhtml+xml':
11101                 return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
fd9ef2 11102
b1a6a5 11103             default:
MC 11104                 return SIMPLEPIE_CONSTRUCT_NONE | $mode;
fd9ef2 11105             }
T 11106         }
11107         else
11108         {
11109             return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11110         }
11111     }
11112
72695f 11113     static function atom_10_construct_type($attribs)
fd9ef2 11114     {
T 11115         if (isset($attribs['']['type']))
11116         {
11117             switch (strtolower(trim($attribs['']['type'])))
11118             {
b1a6a5 11119             case 'text':
MC 11120                 return SIMPLEPIE_CONSTRUCT_TEXT;
fd9ef2 11121
b1a6a5 11122             case 'html':
MC 11123                 return SIMPLEPIE_CONSTRUCT_HTML;
fd9ef2 11124
b1a6a5 11125             case 'xhtml':
MC 11126                 return SIMPLEPIE_CONSTRUCT_XHTML;
fd9ef2 11127
b1a6a5 11128             default:
MC 11129                 return SIMPLEPIE_CONSTRUCT_NONE;
fd9ef2 11130             }
T 11131         }
11132         return SIMPLEPIE_CONSTRUCT_TEXT;
11133     }
11134
11135     function atom_10_content_construct_type($attribs)
11136     {
11137         if (isset($attribs['']['type']))
11138         {
11139             $type = strtolower(trim($attribs['']['type']));
11140             switch ($type)
11141             {
b1a6a5 11142             case 'text':
MC 11143                 return SIMPLEPIE_CONSTRUCT_TEXT;
fd9ef2 11144
b1a6a5 11145             case 'html':
MC 11146                 return SIMPLEPIE_CONSTRUCT_HTML;
fd9ef2 11147
b1a6a5 11148             case 'xhtml':
MC 11149                 return SIMPLEPIE_CONSTRUCT_XHTML;
fd9ef2 11150             }
T 11151             if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
11152             {
11153                 return SIMPLEPIE_CONSTRUCT_NONE;
11154             }
11155             else
11156             {
11157                 return SIMPLEPIE_CONSTRUCT_BASE64;
11158             }
11159         }
11160         else
11161         {
11162             return SIMPLEPIE_CONSTRUCT_TEXT;
11163         }
11164     }
11165
72695f 11166     static function is_isegment_nz_nc($string)
fd9ef2 11167     {
T 11168         return (bool) preg_match('/^([A-Za-z0-9\-._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!$&\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/u', $string);
11169     }
11170
11171     function space_seperated_tokens($string)
11172     {
11173         $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
11174         $string_length = strlen($string);
11175
11176         $position = strspn($string, $space_characters);
11177         $tokens = array();
11178
11179         while ($position < $string_length)
11180         {
11181             $len = strcspn($string, $space_characters, $position);
11182             $tokens[] = substr($string, $position, $len);
11183             $position += $len;
11184             $position += strspn($string, $space_characters, $position);
11185         }
11186
11187         return $tokens;
11188     }
11189
11190     function array_unique($array)
11191     {
11192         if (version_compare(PHP_VERSION, '5.2', '>='))
11193         {
11194             return array_unique($array);
11195         }
11196         else
11197         {
11198             $array = (array) $array;
11199             $new_array = array();
11200             $new_array_strings = array();
11201             foreach ($array as $key => $value)
11202             {
11203                 if (is_object($value))
11204                 {
11205                     if (method_exists($value, '__toString'))
11206                     {
11207                         $cmp = $value->__toString();
11208                     }
11209                     else
11210                     {
11211                         trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
11212                     }
11213                 }
11214                 elseif (is_array($value))
11215                 {
11216                     $cmp = (string) reset($value);
11217                 }
11218                 else
11219                 {
11220                     $cmp = (string) $value;
11221                 }
11222                 if (!in_array($cmp, $new_array_strings))
11223                 {
11224                     $new_array[$key] = $value;
11225                     $new_array_strings[] = $cmp;
11226                 }
11227             }
11228             return $new_array;
11229         }
11230     }
11231
b1a6a5 11232
fd9ef2 11233     /**
T 11234      * Converts a unicode codepoint to a UTF-8 character
11235      *
11236      * @static
11237      * @access public
11238      * @param int $codepoint Unicode codepoint
11239      * @return string UTF-8 character
11240      */
11241     function codepoint_to_utf8($codepoint)
11242     {
11243         $codepoint = (int) $codepoint;
11244         if ($codepoint < 0)
11245         {
11246             return false;
11247         }
11248         else if ($codepoint <= 0x7f)
b1a6a5 11249             {
MC 11250                 return chr($codepoint);
11251             }
fd9ef2 11252         else if ($codepoint <= 0x7ff)
b1a6a5 11253             {
MC 11254                 return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
11255             }
fd9ef2 11256         else if ($codepoint <= 0xffff)
b1a6a5 11257             {
MC 11258                 return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11259             }
fd9ef2 11260         else if ($codepoint <= 0x10ffff)
b1a6a5 11261             {
MC 11262                 return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11263             }
fd9ef2 11264         else
T 11265         {
11266             // U+FFFD REPLACEMENT CHARACTER
11267             return "\xEF\xBF\xBD";
11268         }
11269     }
b1a6a5 11270
fd9ef2 11271
T 11272     /**
11273      * Re-implementation of PHP 5's stripos()
11274      *
11275      * Returns the numeric position of the first occurrence of needle in the
11276      * haystack string.
11277      *
11278      * @static
11279      * @access string
11280      * @param object $haystack
11281      * @param string $needle Note that the needle may be a string of one or more
11282      *     characters. If needle is not a string, it is converted to an integer
11283      *     and applied as the ordinal value of a character.
11284      * @param int $offset The optional offset parameter allows you to specify which
11285      *     character in haystack to start searching. The position returned is still
11286      *     relative to the beginning of haystack.
11287      * @return bool If needle is not found, stripos() will return boolean false.
11288      */
11289     function stripos($haystack, $needle, $offset = 0)
11290     {
11291         if (function_exists('stripos'))
11292         {
11293             return stripos($haystack, $needle, $offset);
11294         }
11295         else
11296         {
11297             if (is_string($needle))
11298             {
11299                 $needle = strtolower($needle);
11300             }
11301             elseif (is_int($needle) || is_bool($needle) || is_double($needle))
11302             {
11303                 $needle = strtolower(chr($needle));
11304             }
11305             else
11306             {
11307                 trigger_error('needle is not a string or an integer', E_USER_WARNING);
11308                 return false;
11309             }
11310
11311             return strpos(strtolower($haystack), $needle, $offset);
11312         }
11313     }
b1a6a5 11314
fd9ef2 11315
T 11316     /**
11317      * Similar to parse_str()
11318      *
11319      * Returns an associative array of name/value pairs, where the value is an
11320      * array of values that have used the same name
11321      *
11322      * @static
11323      * @access string
11324      * @param string $str The input string.
11325      * @return array
11326      */
11327     function parse_str($str)
11328     {
11329         $return = array();
11330         $str = explode('&', $str);
11331
11332         foreach ($str as $section)
11333         {
11334             if (strpos($section, '=') !== false)
11335             {
11336                 list($name, $value) = explode('=', $section, 2);
11337                 $return[urldecode($name)][] = urldecode($value);
11338             }
11339             else
11340             {
11341                 $return[urldecode($section)][] = null;
11342             }
11343         }
11344
11345         return $return;
11346     }
11347
11348     /**
11349      * Detect XML encoding, as per XML 1.0 Appendix F.1
11350      *
11351      * @todo Add support for EBCDIC
11352      * @param string $data XML data
11353      * @return array Possible encodings
11354      */
526b99 11355     public static function xml_encoding($data)
fd9ef2 11356     {
T 11357         // UTF-32 Big Endian BOM
11358         if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
11359         {
11360             $encoding[] = 'UTF-32BE';
11361         }
11362         // UTF-32 Little Endian BOM
11363         elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
11364         {
11365             $encoding[] = 'UTF-32LE';
11366         }
11367         // UTF-16 Big Endian BOM
11368         elseif (substr($data, 0, 2) === "\xFE\xFF")
11369         {
11370             $encoding[] = 'UTF-16BE';
11371         }
11372         // UTF-16 Little Endian BOM
11373         elseif (substr($data, 0, 2) === "\xFF\xFE")
11374         {
11375             $encoding[] = 'UTF-16LE';
11376         }
11377         // UTF-8 BOM
11378         elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
11379         {
11380             $encoding[] = 'UTF-8';
11381         }
11382         // UTF-32 Big Endian Without BOM
11383         elseif (substr($data, 0, 20) === "\x00\x00\x00\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C")
11384         {
11385             if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
11386             {
f64c86 11387                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
fd9ef2 11388                 if ($parser->parse())
T 11389                 {
11390                     $encoding[] = $parser->encoding;
11391                 }
11392             }
11393             $encoding[] = 'UTF-32BE';
11394         }
11395         // UTF-32 Little Endian Without BOM
11396         elseif (substr($data, 0, 20) === "\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C\x00\x00\x00")
11397         {
11398             if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
11399             {
f64c86 11400                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
fd9ef2 11401                 if ($parser->parse())
T 11402                 {
11403                     $encoding[] = $parser->encoding;
11404                 }
11405             }
11406             $encoding[] = 'UTF-32LE';
11407         }
11408         // UTF-16 Big Endian Without BOM
11409         elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
11410         {
11411             if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
11412             {
f64c86 11413                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
fd9ef2 11414                 if ($parser->parse())
T 11415                 {
11416                     $encoding[] = $parser->encoding;
11417                 }
11418             }
11419             $encoding[] = 'UTF-16BE';
11420         }
11421         // UTF-16 Little Endian Without BOM
11422         elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
11423         {
11424             if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
11425             {
f64c86 11426                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
fd9ef2 11427                 if ($parser->parse())
T 11428                 {
11429                     $encoding[] = $parser->encoding;
11430                 }
11431             }
11432             $encoding[] = 'UTF-16LE';
11433         }
11434         // US-ASCII (or superset)
11435         elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
11436         {
11437             if ($pos = strpos($data, "\x3F\x3E"))
11438             {
f64c86 11439                 $parser = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
fd9ef2 11440                 if ($parser->parse())
T 11441                 {
11442                     $encoding[] = $parser->encoding;
11443                 }
11444             }
11445             $encoding[] = 'UTF-8';
11446         }
11447         // Fallback to UTF-8
11448         else
11449         {
11450             $encoding[] = 'UTF-8';
11451         }
11452         return $encoding;
11453     }
11454
11455     function output_javascript()
11456     {
11457         if (function_exists('ob_gzhandler'))
11458         {
11459             ob_start('ob_gzhandler');
11460         }
11461         header('Content-type: text/javascript; charset: UTF-8');
11462         header('Cache-Control: must-revalidate');
11463         header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
b1a6a5 11464 ?>
fd9ef2 11465 function embed_odeo(link) {
T 11466     document.writeln('<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url='+link+'"></embed>');
11467 }
11468
11469 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
11470     if (placeholder != '') {
11471         document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" href="'+link+'" src="'+placeholder+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="false" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
11472     }
11473     else {
11474         document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" src="'+link+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="true" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
11475     }
11476 }
11477
11478 function embed_flash(bgcolor, width, height, link, loop, type) {
11479     document.writeln('<embed src="'+link+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="'+type+'" quality="high" width="'+width+'" height="'+height+'" bgcolor="'+bgcolor+'" loop="'+loop+'"></embed>');
11480 }
11481
11482 function embed_flv(width, height, link, placeholder, loop, player) {
11483     document.writeln('<embed src="'+player+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="'+width+'" height="'+height+'" wmode="transparent" flashvars="file='+link+'&autostart=false&repeat='+loop+'&showdigits=true&showfsbutton=false"></embed>');
11484 }
11485
11486 function embed_wmedia(width, height, link) {
11487     document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
11488 }
11489         <?php
11490     }
b1a6a5 11491
fd9ef2 11492 }
T 11493
11494 /**
11495  * Decode HTML Entities
11496  *
11497  * This implements HTML5 as of revision 967 (2007-06-28)
11498  *
11499  * @package SimplePie
11500  */
11501 class SimplePie_Decode_HTML_Entities
11502 {
b1a6a5 11503
fd9ef2 11504     /**
T 11505      * Data to be parsed
11506      *
11507      * @access private
11508      * @var string
11509      */
11510     var $data = '';
11511
11512     /**
11513      * Currently consumed bytes
11514      *
11515      * @access private
11516      * @var string
11517      */
11518     var $consumed = '';
11519
11520     /**
11521      * Position of the current byte being parsed
11522      *
11523      * @access private
11524      * @var int
11525      */
11526     var $position = 0;
11527
b1a6a5 11528
fd9ef2 11529     /**
T 11530      * Create an instance of the class with the input data
11531      *
11532      * @access public
11533      * @param string $data Input data
11534      */
11535     function SimplePie_Decode_HTML_Entities($data)
11536     {
11537         $this->data = $data;
11538     }
b1a6a5 11539
fd9ef2 11540
T 11541     /**
11542      * Parse the input data
11543      *
11544      * @access public
11545      * @return string Output data
11546      */
11547     function parse()
11548     {
11549         while (($this->position = strpos($this->data, '&', $this->position)) !== false)
11550         {
11551             $this->consume();
11552             $this->entity();
11553             $this->consumed = '';
11554         }
11555         return $this->data;
11556     }
b1a6a5 11557
fd9ef2 11558
T 11559     /**
11560      * Consume the next byte
11561      *
11562      * @access private
11563      * @return mixed The next byte, or false, if there is no more data
11564      */
11565     function consume()
11566     {
11567         if (isset($this->data[$this->position]))
11568         {
11569             $this->consumed .= $this->data[$this->position];
11570             return $this->data[$this->position++];
11571         }
11572         else
11573         {
11574             return false;
11575         }
11576     }
b1a6a5 11577
fd9ef2 11578
T 11579     /**
11580      * Consume a range of characters
11581      *
11582      * @access private
11583      * @param string $chars Characters to consume
11584      * @return mixed A series of characters that match the range, or false
11585      */
11586     function consume_range($chars)
11587     {
11588         if ($len = strspn($this->data, $chars, $this->position))
11589         {
11590             $data = substr($this->data, $this->position, $len);
11591             $this->consumed .= $data;
11592             $this->position += $len;
11593             return $data;
11594         }
11595         else
11596         {
11597             return false;
11598         }
11599     }
11600
b1a6a5 11601
fd9ef2 11602     /**
T 11603      * Unconsume one byte
11604      *
11605      * @access private
11606      */
11607     function unconsume()
11608     {
11609         $this->consumed = substr($this->consumed, 0, -1);
11610         $this->position--;
11611     }
11612
b1a6a5 11613
fd9ef2 11614     /**
T 11615      * Decode an entity
11616      *
11617      * @access private
11618      */
11619     function entity()
11620     {
11621         switch ($this->consume())
11622         {
b1a6a5 11623         case "\x09":
MC 11624         case "\x0A":
11625         case "\x0B":
11626         case "\x0B":
11627         case "\x0C":
11628         case "\x20":
11629         case "\x3C":
11630         case "\x26":
11631         case false:
11632             break;
fd9ef2 11633
b1a6a5 11634         case "\x23":
MC 11635             switch ($this->consume())
11636             {
11637             case "\x78":
11638             case "\x58":
11639                 $range = '0123456789ABCDEFabcdef';
11640                 $hex = true;
fd9ef2 11641                 break;
T 11642
11643             default:
b1a6a5 11644                 $range = '0123456789';
MC 11645                 $hex = false;
11646                 $this->unconsume();
fd9ef2 11647                 break;
b1a6a5 11648             }
MC 11649
11650             if ($codepoint = $this->consume_range($range))
11651             {
11652                 static $windows_1252_specials = array(0x0D => "\x0A", 0x80 => "\xE2\x82\xAC", 0x81 => "\xEF\xBF\xBD", 0x82 => "\xE2\x80\x9A", 0x83 => "\xC6\x92", 0x84 => "\xE2\x80\x9E", 0x85 => "\xE2\x80\xA6", 0x86 => "\xE2\x80\xA0", 0x87 => "\xE2\x80\xA1", 0x88 => "\xCB\x86", 0x89 => "\xE2\x80\xB0", 0x8A => "\xC5\xA0", 0x8B => "\xE2\x80\xB9", 0x8C => "\xC5\x92", 0x8D => "\xEF\xBF\xBD", 0x8E => "\xC5\xBD", 0x8F => "\xEF\xBF\xBD", 0x90 => "\xEF\xBF\xBD", 0x91 => "\xE2\x80\x98", 0x92 => "\xE2\x80\x99", 0x93 => "\xE2\x80\x9C", 0x94 => "\xE2\x80\x9D", 0x95 => "\xE2\x80\xA2", 0x96 => "\xE2\x80\x93", 0x97 => "\xE2\x80\x94", 0x98 => "\xCB\x9C", 0x99 => "\xE2\x84\xA2", 0x9A => "\xC5\xA1", 0x9B => "\xE2\x80\xBA", 0x9C => "\xC5\x93", 0x9D => "\xEF\xBF\xBD", 0x9E => "\xC5\xBE", 0x9F => "\xC5\xB8");
11653
11654                 if ($hex)
11655                 {
11656                     $codepoint = hexdec($codepoint);
11657                 }
11658                 else
11659                 {
11660                     $codepoint = intval($codepoint);
11661                 }
11662
11663                 if (isset($windows_1252_specials[$codepoint]))
11664                 {
11665                     $replacement = $windows_1252_specials[$codepoint];
11666                 }
11667                 else
11668                 {
11669                     $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
11670                 }
11671
11672                 if (!in_array($this->consume(), array(';', false), true))
11673                 {
11674                     $this->unconsume();
11675                 }
11676
11677                 $consumed_length = strlen($this->consumed);
11678                 $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
11679                 $this->position += strlen($replacement) - $consumed_length;
11680             }
11681             break;
11682
11683         default:
11684             static $entities = array('Aacute' => "\xC3\x81", 'aacute' => "\xC3\xA1", 'Aacute;' => "\xC3\x81", 'aacute;' => "\xC3\xA1", 'Acirc' => "\xC3\x82", 'acirc' => "\xC3\xA2", 'Acirc;' => "\xC3\x82", 'acirc;' => "\xC3\xA2", 'acute' => "\xC2\xB4", 'acute;' => "\xC2\xB4", 'AElig' => "\xC3\x86", 'aelig' => "\xC3\xA6", 'AElig;' => "\xC3\x86", 'aelig;' => "\xC3\xA6", 'Agrave' => "\xC3\x80", 'agrave' => "\xC3\xA0", 'Agrave;' => "\xC3\x80", 'agrave;' => "\xC3\xA0", 'alefsym;' => "\xE2\x84\xB5", 'Alpha;' => "\xCE\x91", 'alpha;' => "\xCE\xB1", 'AMP' => "\x26", 'amp' => "\x26", 'AMP;' => "\x26", 'amp;' => "\x26", 'and;' => "\xE2\x88\xA7", 'ang;' => "\xE2\x88\xA0", 'apos;' => "\x27", 'Aring' => "\xC3\x85", 'aring' => "\xC3\xA5", 'Aring;' => "\xC3\x85", 'aring;' => "\xC3\xA5", 'asymp;' => "\xE2\x89\x88", 'Atilde' => "\xC3\x83", 'atilde' => "\xC3\xA3", 'Atilde;' => "\xC3\x83", 'atilde;' => "\xC3\xA3", 'Auml' => "\xC3\x84", 'auml' => "\xC3\xA4", 'Auml;' => "\xC3\x84", 'auml;' => "\xC3\xA4", 'bdquo;' => "\xE2\x80\x9E", 'Beta;' => "\xCE\x92", 'beta;' => "\xCE\xB2", 'brvbar' => "\xC2\xA6", 'brvbar;' => "\xC2\xA6", 'bull;' => "\xE2\x80\xA2", 'cap;' => "\xE2\x88\xA9", 'Ccedil' => "\xC3\x87", 'ccedil' => "\xC3\xA7", 'Ccedil;' => "\xC3\x87", 'ccedil;' => "\xC3\xA7", 'cedil' => "\xC2\xB8", 'cedil;' => "\xC2\xB8", 'cent' => "\xC2\xA2", 'cent;' => "\xC2\xA2", 'Chi;' => "\xCE\xA7", 'chi;' => "\xCF\x87", 'circ;' => "\xCB\x86", 'clubs;' => "\xE2\x99\xA3", 'cong;' => "\xE2\x89\x85", 'COPY' => "\xC2\xA9", 'copy' => "\xC2\xA9", 'COPY;' => "\xC2\xA9", 'copy;' => "\xC2\xA9", 'crarr;' => "\xE2\x86\xB5", 'cup;' => "\xE2\x88\xAA", 'curren' => "\xC2\xA4", 'curren;' => "\xC2\xA4", 'Dagger;' => "\xE2\x80\xA1", 'dagger;' => "\xE2\x80\xA0", 'dArr;' => "\xE2\x87\x93", 'darr;' => "\xE2\x86\x93", 'deg' => "\xC2\xB0", 'deg;' => "\xC2\xB0", 'Delta;' => "\xCE\x94", 'delta;' => "\xCE\xB4", 'diams;' => "\xE2\x99\xA6", 'divide' => "\xC3\xB7", 'divide;' => "\xC3\xB7", 'Eacute' => "\xC3\x89", 'eacute' => "\xC3\xA9", 'Eacute;' => "\xC3\x89", 'eacute;' => "\xC3\xA9", 'Ecirc' => "\xC3\x8A", 'ecirc' => "\xC3\xAA", 'Ecirc;' => "\xC3\x8A", 'ecirc;' => "\xC3\xAA", 'Egrave' => "\xC3\x88", 'egrave' => "\xC3\xA8", 'Egrave;' => "\xC3\x88", 'egrave;' => "\xC3\xA8", 'empty;' => "\xE2\x88\x85", 'emsp;' => "\xE2\x80\x83", 'ensp;' => "\xE2\x80\x82", 'Epsilon;' => "\xCE\x95", 'epsilon;' => "\xCE\xB5", 'equiv;' => "\xE2\x89\xA1", 'Eta;' => "\xCE\x97", 'eta;' => "\xCE\xB7", 'ETH' => "\xC3\x90", 'eth' => "\xC3\xB0", 'ETH;' => "\xC3\x90", 'eth;' => "\xC3\xB0", 'Euml' => "\xC3\x8B", 'euml' => "\xC3\xAB", 'Euml;' => "\xC3\x8B", 'euml;' => "\xC3\xAB", 'euro;' => "\xE2\x82\xAC", 'exist;' => "\xE2\x88\x83", 'fnof;' => "\xC6\x92", 'forall;' => "\xE2\x88\x80", 'frac12' => "\xC2\xBD", 'frac12;' => "\xC2\xBD", 'frac14' => "\xC2\xBC", 'frac14;' => "\xC2\xBC", 'frac34' => "\xC2\xBE", 'frac34;' => "\xC2\xBE", 'frasl;' => "\xE2\x81\x84", 'Gamma;' => "\xCE\x93", 'gamma;' => "\xCE\xB3", 'ge;' => "\xE2\x89\xA5", 'GT' => "\x3E", 'gt' => "\x3E", 'GT;' => "\x3E", 'gt;' => "\x3E", 'hArr;' => "\xE2\x87\x94", 'harr;' => "\xE2\x86\x94", 'hearts;' => "\xE2\x99\xA5", 'hellip;' => "\xE2\x80\xA6", 'Iacute' => "\xC3\x8D", 'iacute' => "\xC3\xAD", 'Iacute;' => "\xC3\x8D", 'iacute;' => "\xC3\xAD", 'Icirc' => "\xC3\x8E", 'icirc' => "\xC3\xAE", 'Icirc;' => "\xC3\x8E", 'icirc;' => "\xC3\xAE", 'iexcl' => "\xC2\xA1", 'iexcl;' => "\xC2\xA1", 'Igrave' => "\xC3\x8C", 'igrave' => "\xC3\xAC", 'Igrave;' => "\xC3\x8C", 'igrave;' => "\xC3\xAC", 'image;' => "\xE2\x84\x91", 'infin;' => "\xE2\x88\x9E", 'int;' => "\xE2\x88\xAB", 'Iota;' => "\xCE\x99", 'iota;' => "\xCE\xB9", 'iquest' => "\xC2\xBF", 'iquest;' => "\xC2\xBF", 'isin;' => "\xE2\x88\x88", 'Iuml' => "\xC3\x8F", 'iuml' => "\xC3\xAF", 'Iuml;' => "\xC3\x8F", 'iuml;' => "\xC3\xAF", 'Kappa;' => "\xCE\x9A", 'kappa;' => "\xCE\xBA", 'Lambda;' => "\xCE\x9B", 'lambda;' => "\xCE\xBB", 'lang;' => "\xE3\x80\x88", 'laquo' => "\xC2\xAB", 'laquo;' => "\xC2\xAB", 'lArr;' => "\xE2\x87\x90", 'larr;' => "\xE2\x86\x90", 'lceil;' => "\xE2\x8C\x88", 'ldquo;' => "\xE2\x80\x9C", 'le;' => "\xE2\x89\xA4", 'lfloor;' => "\xE2\x8C\x8A", 'lowast;' => "\xE2\x88\x97", 'loz;' => "\xE2\x97\x8A", 'lrm;' => "\xE2\x80\x8E", 'lsaquo;' => "\xE2\x80\xB9", 'lsquo;' => "\xE2\x80\x98", 'LT' => "\x3C", 'lt' => "\x3C", 'LT;' => "\x3C", 'lt;' => "\x3C", 'macr' => "\xC2\xAF", 'macr;' => "\xC2\xAF", 'mdash;' => "\xE2\x80\x94", 'micro' => "\xC2\xB5", 'micro;' => "\xC2\xB5", 'middot' => "\xC2\xB7", 'middot;' => "\xC2\xB7", 'minus;' => "\xE2\x88\x92", 'Mu;' => "\xCE\x9C", 'mu;' => "\xCE\xBC", 'nabla;' => "\xE2\x88\x87", 'nbsp' => "\xC2\xA0", 'nbsp;' => "\xC2\xA0", 'ndash;' => "\xE2\x80\x93", 'ne;' => "\xE2\x89\xA0", 'ni;' => "\xE2\x88\x8B", 'not' => "\xC2\xAC", 'not;' => "\xC2\xAC", 'notin;' => "\xE2\x88\x89", 'nsub;' => "\xE2\x8A\x84", 'Ntilde' => "\xC3\x91", 'ntilde' => "\xC3\xB1", 'Ntilde;' => "\xC3\x91", 'ntilde;' => "\xC3\xB1", 'Nu;' => "\xCE\x9D", 'nu;' => "\xCE\xBD", 'Oacute' => "\xC3\x93", 'oacute' => "\xC3\xB3", 'Oacute;' => "\xC3\x93", 'oacute;' => "\xC3\xB3", 'Ocirc' => "\xC3\x94", 'ocirc' => "\xC3\xB4", 'Ocirc;' => "\xC3\x94", 'ocirc;' => "\xC3\xB4", 'OElig;' => "\xC5\x92", 'oelig;' => "\xC5\x93", 'Ograve' => "\xC3\x92", 'ograve' => "\xC3\xB2", 'Ograve;' => "\xC3\x92", 'ograve;' => "\xC3\xB2", 'oline;' => "\xE2\x80\xBE", 'Omega;' => "\xCE\xA9", 'omega;' => "\xCF\x89", 'Omicron;' => "\xCE\x9F", 'omicron;' => "\xCE\xBF", 'oplus;' => "\xE2\x8A\x95", 'or;' => "\xE2\x88\xA8", 'ordf' => "\xC2\xAA", 'ordf;' => "\xC2\xAA", 'ordm' => "\xC2\xBA", 'ordm;' => "\xC2\xBA", 'Oslash' => "\xC3\x98", 'oslash' => "\xC3\xB8", 'Oslash;' => "\xC3\x98", 'oslash;' => "\xC3\xB8", 'Otilde' => "\xC3\x95", 'otilde' => "\xC3\xB5", 'Otilde;' => "\xC3\x95", 'otilde;' => "\xC3\xB5", 'otimes;' => "\xE2\x8A\x97", 'Ouml' => "\xC3\x96", 'ouml' => "\xC3\xB6", 'Ouml;' => "\xC3\x96", 'ouml;' => "\xC3\xB6", 'para' => "\xC2\xB6", 'para;' => "\xC2\xB6", 'part;' => "\xE2\x88\x82", 'permil;' => "\xE2\x80\xB0", 'perp;' => "\xE2\x8A\xA5", 'Phi;' => "\xCE\xA6", 'phi;' => "\xCF\x86", 'Pi;' => "\xCE\xA0", 'pi;' => "\xCF\x80", 'piv;' => "\xCF\x96", 'plusmn' => "\xC2\xB1", 'plusmn;' => "\xC2\xB1", 'pound' => "\xC2\xA3", 'pound;' => "\xC2\xA3", 'Prime;' => "\xE2\x80\xB3", 'prime;' => "\xE2\x80\xB2", 'prod;' => "\xE2\x88\x8F", 'prop;' => "\xE2\x88\x9D", 'Psi;' => "\xCE\xA8", 'psi;' => "\xCF\x88", 'QUOT' => "\x22", 'quot' => "\x22", 'QUOT;' => "\x22", 'quot;' => "\x22", 'radic;' => "\xE2\x88\x9A", 'rang;' => "\xE3\x80\x89", 'raquo' => "\xC2\xBB", 'raquo;' => "\xC2\xBB", 'rArr;' => "\xE2\x87\x92", 'rarr;' => "\xE2\x86\x92", 'rceil;' => "\xE2\x8C\x89", 'rdquo;' => "\xE2\x80\x9D", 'real;' => "\xE2\x84\x9C", 'REG' => "\xC2\xAE", 'reg' => "\xC2\xAE", 'REG;' => "\xC2\xAE", 'reg;' => "\xC2\xAE", 'rfloor;' => "\xE2\x8C\x8B", 'Rho;' => "\xCE\xA1", 'rho;' => "\xCF\x81", 'rlm;' => "\xE2\x80\x8F", 'rsaquo;' => "\xE2\x80\xBA", 'rsquo;' => "\xE2\x80\x99", 'sbquo;' => "\xE2\x80\x9A", 'Scaron;' => "\xC5\xA0", 'scaron;' => "\xC5\xA1", 'sdot;' => "\xE2\x8B\x85", 'sect' => "\xC2\xA7", 'sect;' => "\xC2\xA7", 'shy' => "\xC2\xAD", 'shy;' => "\xC2\xAD", 'Sigma;' => "\xCE\xA3", 'sigma;' => "\xCF\x83", 'sigmaf;' => "\xCF\x82", 'sim;' => "\xE2\x88\xBC", 'spades;' => "\xE2\x99\xA0", 'sub;' => "\xE2\x8A\x82", 'sube;' => "\xE2\x8A\x86", 'sum;' => "\xE2\x88\x91", 'sup;' => "\xE2\x8A\x83", 'sup1' => "\xC2\xB9", 'sup1;' => "\xC2\xB9", 'sup2' => "\xC2\xB2", 'sup2;' => "\xC2\xB2", 'sup3' => "\xC2\xB3", 'sup3;' => "\xC2\xB3", 'supe;' => "\xE2\x8A\x87", 'szlig' => "\xC3\x9F", 'szlig;' => "\xC3\x9F", 'Tau;' => "\xCE\xA4", 'tau;' => "\xCF\x84", 'there4;' => "\xE2\x88\xB4", 'Theta;' => "\xCE\x98", 'theta;' => "\xCE\xB8", 'thetasym;' => "\xCF\x91", 'thinsp;' => "\xE2\x80\x89", 'THORN' => "\xC3\x9E", 'thorn' => "\xC3\xBE", 'THORN;' => "\xC3\x9E", 'thorn;' => "\xC3\xBE", 'tilde;' => "\xCB\x9C", 'times' => "\xC3\x97", 'times;' => "\xC3\x97", 'TRADE;' => "\xE2\x84\xA2", 'trade;' => "\xE2\x84\xA2", 'Uacute' => "\xC3\x9A", 'uacute' => "\xC3\xBA", 'Uacute;' => "\xC3\x9A", 'uacute;' => "\xC3\xBA", 'uArr;' => "\xE2\x87\x91", 'uarr;' => "\xE2\x86\x91", 'Ucirc' => "\xC3\x9B", 'ucirc' => "\xC3\xBB", 'Ucirc;' => "\xC3\x9B", 'ucirc;' => "\xC3\xBB", 'Ugrave' => "\xC3\x99", 'ugrave' => "\xC3\xB9", 'Ugrave;' => "\xC3\x99", 'ugrave;' => "\xC3\xB9", 'uml' => "\xC2\xA8", 'uml;' => "\xC2\xA8", 'upsih;' => "\xCF\x92", 'Upsilon;' => "\xCE\xA5", 'upsilon;' => "\xCF\x85", 'Uuml' => "\xC3\x9C", 'uuml' => "\xC3\xBC", 'Uuml;' => "\xC3\x9C", 'uuml;' => "\xC3\xBC", 'weierp;' => "\xE2\x84\x98", 'Xi;' => "\xCE\x9E", 'xi;' => "\xCE\xBE", 'Yacute' => "\xC3\x9D", 'yacute' => "\xC3\xBD", 'Yacute;' => "\xC3\x9D", 'yacute;' => "\xC3\xBD", 'yen' => "\xC2\xA5", 'yen;' => "\xC2\xA5", 'yuml' => "\xC3\xBF", 'Yuml;' => "\xC5\xB8", 'yuml;' => "\xC3\xBF", 'Zeta;' => "\xCE\x96", 'zeta;' => "\xCE\xB6", 'zwj;' => "\xE2\x80\x8D", 'zwnj;' => "\xE2\x80\x8C");
11685
11686             for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
11687             {
11688                 $consumed = substr($this->consumed, 1);
11689                 if (isset($entities[$consumed]))
11690                 {
11691                     $match = $consumed;
11692                 }
11693             }
11694
11695             if ($match !== null)
11696             {
11697                 $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
11698                 $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
11699             }
11700             break;
fd9ef2 11701         }
T 11702     }
b1a6a5 11703
fd9ef2 11704 }
T 11705
11706 /**
11707  * IRI parser/serialiser
11708  *
11709  * @package SimplePie
11710  */
11711 class SimplePie_IRI
11712 {
b1a6a5 11713
fd9ef2 11714     /**
T 11715      * Scheme
11716      *
11717      * @access private
11718      * @var string
11719      */
11720     var $scheme;
11721
11722     /**
11723      * User Information
11724      *
11725      * @access private
11726      * @var string
11727      */
11728     var $userinfo;
11729
11730     /**
11731      * Host
11732      *
11733      * @access private
11734      * @var string
11735      */
11736     var $host;
11737
11738     /**
11739      * Port
11740      *
11741      * @access private
11742      * @var string
11743      */
11744     var $port;
11745
11746     /**
11747      * Path
11748      *
11749      * @access private
11750      * @var string
11751      */
11752     var $path;
11753
11754     /**
11755      * Query
11756      *
11757      * @access private
11758      * @var string
11759      */
11760     var $query;
11761
11762     /**
11763      * Fragment
11764      *
11765      * @access private
11766      * @var string
11767      */
11768     var $fragment;
11769
11770     /**
11771      * Whether the object represents a valid IRI
11772      *
11773      * @access private
11774      * @var array
11775      */
11776     var $valid = array();
11777
b1a6a5 11778
fd9ef2 11779     /**
T 11780      * Return the entire IRI when you try and read the object as a string
11781      *
11782      * @access public
11783      * @return string
11784      */
11785     function __toString()
11786     {
11787         return $this->get_iri();
11788     }
b1a6a5 11789
fd9ef2 11790
T 11791     /**
11792      * Create a new IRI object, from a specified string
11793      *
11794      * @access public
11795      * @param string $iri
11796      * @return SimplePie_IRI
11797      */
11798     function SimplePie_IRI($iri)
11799     {
11800         $iri = (string) $iri;
11801         if ($iri !== '')
11802         {
11803             $parsed = $this->parse_iri($iri);
11804             $this->set_scheme($parsed['scheme']);
11805             $this->set_authority($parsed['authority']);
11806             $this->set_path($parsed['path']);
11807             $this->set_query($parsed['query']);
11808             $this->set_fragment($parsed['fragment']);
11809         }
11810     }
11811
11812     /**
11813      * Create a new IRI object by resolving a relative IRI
11814      *
11815      * @static
11816      * @access public
11817      * @param SimplePie_IRI $base Base IRI
11818      * @param string $relative Relative IRI
11819      * @return SimplePie_IRI
11820      */
72695f 11821     static function absolutize($base, $relative)
fd9ef2 11822     {
T 11823         $relative = (string) $relative;
11824         if ($relative !== '')
11825         {
f64c86 11826             $relative = new SimplePie_IRI($relative);
fd9ef2 11827             if ($relative->get_scheme() !== null)
T 11828             {
11829                 $target = $relative;
11830             }
11831             elseif ($base->get_iri() !== null)
11832             {
11833                 if ($relative->get_authority() !== null)
11834                 {
11835                     $target = $relative;
11836                     $target->set_scheme($base->get_scheme());
11837                 }
11838                 else
11839                 {
f64c86 11840                     $target = new SimplePie_IRI('');
fd9ef2 11841                     $target->set_scheme($base->get_scheme());
T 11842                     $target->set_userinfo($base->get_userinfo());
11843                     $target->set_host($base->get_host());
11844                     $target->set_port($base->get_port());
11845                     if ($relative->get_path() !== null)
11846                     {
11847                         if (strpos($relative->get_path(), '/') === 0)
11848                         {
11849                             $target->set_path($relative->get_path());
11850                         }
11851                         elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
11852                         {
11853                             $target->set_path('/' . $relative->get_path());
11854                         }
11855                         elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
11856                         {
11857                             $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
11858                         }
11859                         else
11860                         {
11861                             $target->set_path($relative->get_path());
11862                         }
11863                         $target->set_query($relative->get_query());
11864                     }
11865                     else
11866                     {
11867                         $target->set_path($base->get_path());
11868                         if ($relative->get_query() !== null)
11869                         {
11870                             $target->set_query($relative->get_query());
11871                         }
11872                         elseif ($base->get_query() !== null)
11873                         {
11874                             $target->set_query($base->get_query());
11875                         }
11876                     }
11877                 }
11878                 $target->set_fragment($relative->get_fragment());
11879             }
11880             else
11881             {
11882                 // No base URL, just return the relative URL
11883                 $target = $relative;
11884             }
11885         }
11886         else
11887         {
11888             $target = $base;
11889         }
11890         return $target;
11891     }
11892
b1a6a5 11893
fd9ef2 11894     /**
T 11895      * Parse an IRI into scheme/authority/path/query/fragment segments
11896      *
11897      * @access private
11898      * @param string $iri
11899      * @return array
11900      */
11901     function parse_iri($iri)
11902     {
11903         preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
11904         for ($i = count($match); $i <= 9; $i++)
11905         {
11906             $match[$i] = '';
11907         }
11908         return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
11909     }
b1a6a5 11910
fd9ef2 11911
T 11912     /**
11913      * Remove dot segments from a path
11914      *
11915      * @access private
11916      * @param string $input
11917      * @return string
11918      */
11919     function remove_dot_segments($input)
11920     {
11921         $output = '';
11922         while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
11923         {
11924             // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
11925             if (strpos($input, '../') === 0)
11926             {
11927                 $input = substr($input, 3);
11928             }
11929             elseif (strpos($input, './') === 0)
11930             {
11931                 $input = substr($input, 2);
11932             }
11933             // B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise,
11934             elseif (strpos($input, '/./') === 0)
11935             {
11936                 $input = substr_replace($input, '/', 0, 3);
11937             }
11938             elseif ($input === '/.')
11939             {
11940                 $input = '/';
11941             }
11942             // C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise,
11943             elseif (strpos($input, '/../') === 0)
11944             {
11945                 $input = substr_replace($input, '/', 0, 4);
11946                 $output = substr_replace($output, '', strrpos($output, '/'));
11947             }
11948             elseif ($input === '/..')
11949             {
11950                 $input = '/';
11951                 $output = substr_replace($output, '', strrpos($output, '/'));
11952             }
11953             // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
11954             elseif ($input === '.' || $input === '..')
11955             {
11956                 $input = '';
11957             }
11958             // E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer
11959             elseif (($pos = strpos($input, '/', 1)) !== false)
11960             {
11961                 $output .= substr($input, 0, $pos);
11962                 $input = substr_replace($input, '', 0, $pos);
11963             }
11964             else
11965             {
11966                 $output .= $input;
11967                 $input = '';
11968             }
11969         }
11970         return $output . $input;
11971     }
b1a6a5 11972
fd9ef2 11973
T 11974     /**
11975      * Replace invalid character with percent encoding
11976      *
11977      * @access private
11978      * @param string $string Input string
11979      * @param string $valid_chars Valid characters
11980      * @param int $case Normalise case
11981      * @return string
11982      */
11983     function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE)
11984     {
11985         // Normalise case
11986         if ($case & SIMPLEPIE_LOWERCASE)
11987         {
11988             $string = strtolower($string);
11989         }
11990         elseif ($case & SIMPLEPIE_UPPERCASE)
11991         {
11992             $string = strtoupper($string);
11993         }
11994
11995         // Store position and string length (to avoid constantly recalculating this)
11996         $position = 0;
11997         $strlen = strlen($string);
11998
11999         // Loop as long as we have invalid characters, advancing the position to the next invalid character
12000         while (($position += strspn($string, $valid_chars, $position)) < $strlen)
12001         {
12002             // If we have a % character
12003             if ($string[$position] === '%')
12004             {
12005                 // If we have a pct-encoded section
12006                 if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2)
12007                 {
12008                     // Get the the represented character
12009                     $chr = chr(hexdec(substr($string, $position + 1, 2)));
12010
12011                     // If the character is valid, replace the pct-encoded with the actual character while normalising case
12012                     if (strpos($valid_chars, $chr) !== false)
12013                     {
12014                         if ($case & SIMPLEPIE_LOWERCASE)
12015                         {
12016                             $chr = strtolower($chr);
12017                         }
12018                         elseif ($case & SIMPLEPIE_UPPERCASE)
12019                         {
12020                             $chr = strtoupper($chr);
12021                         }
12022                         $string = substr_replace($string, $chr, $position, 3);
12023                         $strlen -= 2;
12024                         $position++;
12025                     }
12026
12027                     // Otherwise just normalise the pct-encoded to uppercase
12028                     else
12029                     {
12030                         $string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2);
12031                         $position += 3;
12032                     }
12033                 }
12034                 // If we don't have a pct-encoded section, just replace the % with its own esccaped form
12035                 else
12036                 {
12037                     $string = substr_replace($string, '%25', $position, 1);
12038                     $strlen += 2;
12039                     $position += 3;
12040                 }
12041             }
12042             // If we have an invalid character, change into its pct-encoded form
12043             else
12044             {
12045                 $replacement = sprintf("%%%02X", ord($string[$position]));
12046                 $string = str_replace($string[$position], $replacement, $string);
12047                 $strlen = strlen($string);
12048             }
12049         }
12050         return $string;
12051     }
12052
b1a6a5 12053
fd9ef2 12054     /**
T 12055      * Check if the object represents a valid IRI
12056      *
12057      * @access public
12058      * @return bool
12059      */
12060     function is_valid()
12061     {
12062         return array_sum($this->valid) === count($this->valid);
12063     }
b1a6a5 12064
fd9ef2 12065
T 12066     /**
12067      * Set the scheme. Returns true on success, false on failure (if there are
12068      * any invalid characters).
12069      *
12070      * @access public
12071      * @param string $scheme
12072      * @return bool
12073      */
12074     function set_scheme($scheme)
12075     {
12076         if ($scheme === null || $scheme === '')
12077         {
12078             $this->scheme = null;
12079         }
12080         else
12081         {
12082             $len = strlen($scheme);
12083             switch (true)
12084             {
b1a6a5 12085             case $len > 1:
MC 12086                 if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
12087                 {
12088                     $this->scheme = null;
12089                     $this->valid[__FUNCTION__] = false;
12090                     return false;
12091                 }
fd9ef2 12092
b1a6a5 12093             case $len > 0:
MC 12094                 if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
12095                 {
12096                     $this->scheme = null;
12097                     $this->valid[__FUNCTION__] = false;
12098                     return false;
12099                 }
fd9ef2 12100             }
T 12101             $this->scheme = strtolower($scheme);
12102         }
12103         $this->valid[__FUNCTION__] = true;
12104         return true;
12105     }
b1a6a5 12106
fd9ef2 12107
T 12108     /**
12109      * Set the authority. Returns true on success, false on failure (if there are
12110      * any invalid characters).
12111      *
12112      * @access public
12113      * @param string $authority
12114      * @return bool
12115      */
12116     function set_authority($authority)
12117     {
12118         if (($userinfo_end = strrpos($authority, '@')) !== false)
12119         {
12120             $userinfo = substr($authority, 0, $userinfo_end);
12121             $authority = substr($authority, $userinfo_end + 1);
12122         }
12123         else
12124         {
12125             $userinfo = null;
12126         }
12127
12128         if (($port_start = strpos($authority, ':')) !== false)
12129         {
12130             $port = substr($authority, $port_start + 1);
12131             $authority = substr($authority, 0, $port_start);
12132         }
12133         else
12134         {
12135             $port = null;
12136         }
12137
12138         return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
12139     }
12140
b1a6a5 12141
fd9ef2 12142     /**
T 12143      * Set the userinfo.
12144      *
12145      * @access public
12146      * @param string $userinfo
12147      * @return bool
12148      */
12149     function set_userinfo($userinfo)
12150     {
12151         if ($userinfo === null || $userinfo === '')
12152         {
12153             $this->userinfo = null;
12154         }
12155         else
12156         {
12157             $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
12158         }
12159         $this->valid[__FUNCTION__] = true;
12160         return true;
12161     }
b1a6a5 12162
fd9ef2 12163
T 12164     /**
12165      * Set the host. Returns true on success, false on failure (if there are
12166      * any invalid characters).
12167      *
12168      * @access public
12169      * @param string $host
12170      * @return bool
12171      */
12172     function set_host($host)
12173     {
12174         if ($host === null || $host === '')
12175         {
12176             $this->host = null;
12177             $this->valid[__FUNCTION__] = true;
12178             return true;
12179         }
12180         elseif ($host[0] === '[' && substr($host, -1) === ']')
12181         {
12182             if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
12183             {
12184                 $this->host = $host;
12185                 $this->valid[__FUNCTION__] = true;
12186                 return true;
12187             }
12188             else
12189             {
12190                 $this->host = null;
12191                 $this->valid[__FUNCTION__] = false;
12192                 return false;
12193             }
12194         }
12195         else
12196         {
12197             $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
12198             $this->valid[__FUNCTION__] = true;
12199             return true;
12200         }
12201     }
12202
b1a6a5 12203
fd9ef2 12204     /**
T 12205      * Set the port. Returns true on success, false on failure (if there are
12206      * any invalid characters).
12207      *
12208      * @access public
12209      * @param string $port
12210      * @return bool
12211      */
12212     function set_port($port)
12213     {
12214         if ($port === null || $port === '')
12215         {
12216             $this->port = null;
12217             $this->valid[__FUNCTION__] = true;
12218             return true;
12219         }
12220         elseif (strspn($port, '0123456789') === strlen($port))
12221         {
12222             $this->port = (int) $port;
12223             $this->valid[__FUNCTION__] = true;
12224             return true;
12225         }
12226         else
12227         {
12228             $this->port = null;
12229             $this->valid[__FUNCTION__] = false;
12230             return false;
12231         }
12232     }
b1a6a5 12233
fd9ef2 12234
T 12235     /**
12236      * Set the path.
12237      *
12238      * @access public
12239      * @param string $path
12240      * @return bool
12241      */
12242     function set_path($path)
12243     {
12244         if ($path === null || $path === '')
12245         {
12246             $this->path = null;
12247             $this->valid[__FUNCTION__] = true;
12248             return true;
12249         }
12250         elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
12251         {
12252             $this->path = null;
12253             $this->valid[__FUNCTION__] = false;
12254             return false;
12255         }
12256         else
12257         {
12258             $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
12259             if ($this->scheme !== null)
12260             {
12261                 $this->path = $this->remove_dot_segments($this->path);
12262             }
12263             $this->valid[__FUNCTION__] = true;
12264             return true;
12265         }
12266     }
12267
b1a6a5 12268
fd9ef2 12269     /**
T 12270      * Set the query.
12271      *
12272      * @access public
12273      * @param string $query
12274      * @return bool
12275      */
12276     function set_query($query)
12277     {
12278         if ($query === null || $query === '')
12279         {
12280             $this->query = null;
12281         }
12282         else
12283         {
02bf99 12284             $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?&=');
fd9ef2 12285         }
T 12286         $this->valid[__FUNCTION__] = true;
12287         return true;
12288     }
12289
b1a6a5 12290
fd9ef2 12291     /**
T 12292      * Set the fragment.
12293      *
12294      * @access public
12295      * @param string $fragment
12296      * @return bool
12297      */
12298     function set_fragment($fragment)
12299     {
12300         if ($fragment === null || $fragment === '')
12301         {
12302             $this->fragment = null;
12303         }
12304         else
12305         {
12306             $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12307         }
12308         $this->valid[__FUNCTION__] = true;
12309         return true;
12310     }
b1a6a5 12311
fd9ef2 12312
T 12313     /**
12314      * Get the complete IRI
12315      *
12316      * @access public
12317      * @return string
12318      */
12319     function get_iri()
12320     {
12321         $iri = '';
12322         if ($this->scheme !== null)
12323         {
12324             $iri .= $this->scheme . ':';
12325         }
12326         if (($authority = $this->get_authority()) !== null)
12327         {
12328             $iri .= '//' . $authority;
12329         }
12330         if ($this->path !== null)
12331         {
12332             $iri .= $this->path;
12333         }
12334         if ($this->query !== null)
12335         {
12336             $iri .= '?' . $this->query;
12337         }
12338         if ($this->fragment !== null)
12339         {
12340             $iri .= '#' . $this->fragment;
12341         }
12342
12343         if ($iri !== '')
12344         {
12345             return $iri;
12346         }
12347         else
12348         {
12349             return null;
12350         }
12351     }
12352
b1a6a5 12353
fd9ef2 12354     /**
T 12355      * Get the scheme
12356      *
12357      * @access public
12358      * @return string
12359      */
12360     function get_scheme()
12361     {
12362         return $this->scheme;
12363     }
b1a6a5 12364
fd9ef2 12365
T 12366     /**
12367      * Get the complete authority
12368      *
12369      * @access public
12370      * @return string
12371      */
12372     function get_authority()
12373     {
12374         $authority = '';
12375         if ($this->userinfo !== null)
12376         {
12377             $authority .= $this->userinfo . '@';
12378         }
12379         if ($this->host !== null)
12380         {
12381             $authority .= $this->host;
12382         }
12383         if ($this->port !== null)
12384         {
12385             $authority .= ':' . $this->port;
12386         }
12387
12388         if ($authority !== '')
12389         {
12390             return $authority;
12391         }
12392         else
12393         {
12394             return null;
12395         }
12396     }
12397
b1a6a5 12398
fd9ef2 12399     /**
T 12400      * Get the user information
12401      *
12402      * @access public
12403      * @return string
12404      */
12405     function get_userinfo()
12406     {
12407         return $this->userinfo;
12408     }
b1a6a5 12409
fd9ef2 12410
T 12411     /**
12412      * Get the host
12413      *
12414      * @access public
12415      * @return string
12416      */
12417     function get_host()
12418     {
12419         return $this->host;
12420     }
12421
b1a6a5 12422
fd9ef2 12423     /**
T 12424      * Get the port
12425      *
12426      * @access public
12427      * @return string
12428      */
12429     function get_port()
12430     {
12431         return $this->port;
12432     }
b1a6a5 12433
fd9ef2 12434
T 12435     /**
12436      * Get the path
12437      *
12438      * @access public
12439      * @return string
12440      */
12441     function get_path()
12442     {
12443         return $this->path;
12444     }
12445
b1a6a5 12446
fd9ef2 12447     /**
T 12448      * Get the query
12449      *
12450      * @access public
12451      * @return string
12452      */
12453     function get_query()
12454     {
12455         return $this->query;
12456     }
12457
b1a6a5 12458
fd9ef2 12459     /**
T 12460      * Get the fragment
12461      *
12462      * @access public
12463      * @return string
12464      */
12465     function get_fragment()
12466     {
12467         return $this->fragment;
12468     }
b1a6a5 12469
fd9ef2 12470 }
T 12471
12472 /**
12473  * Class to validate and to work with IPv6 addresses.
12474  *
12475  * @package SimplePie
12476  * @copyright 2003-2005 The PHP Group
12477  * @license http://www.opensource.org/licenses/bsd-license.php
12478  * @link http://pear.php.net/package/Net_IPv6
12479  * @author Alexander Merz <alexander.merz@web.de>
12480  * @author elfrink at introweb dot nl
12481  * @author Josh Peck <jmp at joshpeck dot org>
12482  * @author Geoffrey Sneddon <geoffers@gmail.com>
12483  */
12484 class SimplePie_Net_IPv6
12485 {
b1a6a5 12486
MC 12487
fd9ef2 12488     /**
T 12489      * Removes a possible existing netmask specification of an IP address.
12490      *
12491      * @param string $ip the (compressed) IP as Hex representation
12492      * @return string the IP the without netmask
12493      * @since 1.1.0
12494      * @access public
12495      * @static
12496      */
12497     function removeNetmaskSpec($ip)
12498     {
12499         if (strpos($ip, '/') !== false)
12500         {
12501             list($addr, $nm) = explode('/', $ip);
12502         }
12503         else
12504         {
12505             $addr = $ip;
12506         }
12507         return $addr;
12508     }
12509
b1a6a5 12510
fd9ef2 12511     /**
T 12512      * Uncompresses an IPv6 address
12513      *
12514      * RFC 2373 allows you to compress zeros in an address to '::'. This
12515      * function expects an valid IPv6 address and expands the '::' to
12516      * the required zeros.
12517      *
b1a6a5 12518      * Example:  FF01::101 -> FF01:0:0:0:0:0:0:101
MC 12519      *    ::1  -> 0:0:0:0:0:0:0:1
fd9ef2 12520      *
T 12521      * @access public
12522      * @static
12523      * @param string $ip a valid IPv6-address (hex format)
12524      * @return string the uncompressed IPv6-address (hex format)
12525      */
12526     function Uncompress($ip)
12527     {
12528         $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
12529         $c1 = -1;
12530         $c2 = -1;
12531         if (strpos($ip, '::') !== false)
12532         {
12533             list($ip1, $ip2) = explode('::', $ip);
12534             if ($ip1 === '')
12535             {
12536                 $c1 = -1;
12537             }
12538             else
12539             {
12540                 $pos = 0;
12541                 if (($pos = substr_count($ip1, ':')) > 0)
12542                 {
12543                     $c1 = $pos;
12544                 }
12545                 else
12546                 {
12547                     $c1 = 0;
12548                 }
12549             }
12550             if ($ip2 === '')
12551             {
12552                 $c2 = -1;
12553             }
12554             else
12555             {
12556                 $pos = 0;
12557                 if (($pos = substr_count($ip2, ':')) > 0)
12558                 {
12559                     $c2 = $pos;
12560                 }
12561                 else
12562                 {
12563                     $c2 = 0;
12564                 }
12565             }
12566             if (strstr($ip2, '.'))
12567             {
12568                 $c2++;
12569             }
12570             // ::
12571             if ($c1 === -1 && $c2 === -1)
12572             {
12573                 $uip = '0:0:0:0:0:0:0:0';
12574             }
12575             // ::xxx
12576             else if ($c1 === -1)
b1a6a5 12577                 {
MC 12578                     $fill = str_repeat('0:', 7 - $c2);
12579                     $uip = str_replace('::', $fill, $uip);
12580                 }
fd9ef2 12581             // xxx::
T 12582             else if ($c2 === -1)
b1a6a5 12583                 {
MC 12584                     $fill = str_repeat(':0', 7 - $c1);
12585                     $uip = str_replace('::', $fill, $uip);
12586                 }
fd9ef2 12587             // xxx::xxx
T 12588             else
12589             {
12590                 $fill = str_repeat(':0:', 6 - $c2 - $c1);
b1a6a5 12591                 $uip = str_replace('::', $fill, $uip);
MC 12592                 $uip = str_replace('::', ':', $uip);
fd9ef2 12593             }
T 12594         }
12595         return $uip;
12596     }
b1a6a5 12597
fd9ef2 12598
T 12599     /**
12600      * Splits an IPv6 address into the IPv6 and a possible IPv4 part
12601      *
12602      * RFC 2373 allows you to note the last two parts of an IPv6 address as
12603      * an IPv4 compatible address
12604      *
b1a6a5 12605      * Example:  0:0:0:0:0:0:13.1.68.3
MC 12606      *    0:0:0:0:0:FFFF:129.144.52.38
fd9ef2 12607      *
T 12608      * @access public
12609      * @static
12610      * @param string $ip a valid IPv6-address (hex format)
12611      * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
12612      */
12613     function SplitV64($ip)
12614     {
12615         $ip = SimplePie_Net_IPv6::Uncompress($ip);
12616         if (strstr($ip, '.'))
12617         {
12618             $pos = strrpos($ip, ':');
12619             $ip[$pos] = '_';
12620             $ipPart = explode('_', $ip);
12621             return $ipPart;
12622         }
12623         else
12624         {
12625             return array($ip, '');
12626         }
12627     }
b1a6a5 12628
fd9ef2 12629
T 12630     /**
12631      * Checks an IPv6 address
12632      *
12633      * Checks if the given IP is IPv6-compatible
12634      *
12635      * @access public
12636      * @static
12637      * @param string $ip a valid IPv6-address
12638      * @return bool true if $ip is an IPv6 address
12639      */
12640     function checkIPv6($ip)
12641     {
12642         $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
12643         $count = 0;
12644         if (!empty($ipPart[0]))
12645         {
12646             $ipv6 = explode(':', $ipPart[0]);
12647             for ($i = 0; $i < count($ipv6); $i++)
12648             {
12649                 $dec = hexdec($ipv6[$i]);
12650                 $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
12651                 if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
12652                 {
12653                     $count++;
12654                 }
12655             }
12656             if ($count === 8)
12657             {
12658                 return true;
12659             }
12660             elseif ($count === 6 && !empty($ipPart[1]))
12661             {
12662                 $ipv4 = explode('.', $ipPart[1]);
12663                 $count = 0;
12664                 foreach ($ipv4 as $ipv4_part)
12665                 {
12666                     if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
12667                     {
12668                         $count++;
12669                     }
12670                 }
12671                 if ($count === 4)
12672                 {
12673                     return true;
12674                 }
12675             }
12676             else
12677             {
12678                 return false;
12679             }
12680
12681         }
12682         else
12683         {
12684             return false;
12685         }
12686     }
b1a6a5 12687
fd9ef2 12688 }
T 12689
12690 /**
12691  * Date Parser
12692  *
12693  * @package SimplePie
12694  */
12695 class SimplePie_Parse_Date
12696 {
b1a6a5 12697
fd9ef2 12698     /**
T 12699      * Input data
12700      *
12701      * @access protected
12702      * @var string
12703      */
12704     var $date;
12705
12706     /**
12707      * List of days, calendar day name => ordinal day number in the week
12708      *
12709      * @access protected
12710      * @var array
12711      */
12712     var $day = array(
12713         // English
12714         'mon' => 1,
12715         'monday' => 1,
12716         'tue' => 2,
12717         'tuesday' => 2,
12718         'wed' => 3,
12719         'wednesday' => 3,
12720         'thu' => 4,
12721         'thursday' => 4,
12722         'fri' => 5,
12723         'friday' => 5,
12724         'sat' => 6,
12725         'saturday' => 6,
12726         'sun' => 7,
12727         'sunday' => 7,
12728         // Dutch
12729         'maandag' => 1,
12730         'dinsdag' => 2,
12731         'woensdag' => 3,
12732         'donderdag' => 4,
12733         'vrijdag' => 5,
12734         'zaterdag' => 6,
12735         'zondag' => 7,
12736         // French
12737         'lundi' => 1,
12738         'mardi' => 2,
12739         'mercredi' => 3,
12740         'jeudi' => 4,
12741         'vendredi' => 5,
12742         'samedi' => 6,
12743         'dimanche' => 7,
12744         // German
12745         'montag' => 1,
12746         'dienstag' => 2,
12747         'mittwoch' => 3,
12748         'donnerstag' => 4,
12749         'freitag' => 5,
12750         'samstag' => 6,
12751         'sonnabend' => 6,
12752         'sonntag' => 7,
12753         // Italian
12754         'lunedì' => 1,
12755         'martedì' => 2,
12756         'mercoledì' => 3,
12757         'giovedì' => 4,
12758         'venerdì' => 5,
12759         'sabato' => 6,
12760         'domenica' => 7,
12761         // Spanish
12762         'lunes' => 1,
12763         'martes' => 2,
12764         'miércoles' => 3,
12765         'jueves' => 4,
12766         'viernes' => 5,
12767         'sábado' => 6,
12768         'domingo' => 7,
12769         // Finnish
12770         'maanantai' => 1,
12771         'tiistai' => 2,
12772         'keskiviikko' => 3,
12773         'torstai' => 4,
12774         'perjantai' => 5,
12775         'lauantai' => 6,
12776         'sunnuntai' => 7,
12777         // Hungarian
12778         'hétfő' => 1,
12779         'kedd' => 2,
12780         'szerda' => 3,
12781         'csütörtok' => 4,
12782         'péntek' => 5,
12783         'szombat' => 6,
12784         'vasárnap' => 7,
12785         // Greek
12786         'Δευ' => 1,
12787         'Τρι' => 2,
12788         'Τετ' => 3,
12789         'Πεμ' => 4,
12790         'Παρ' => 5,
12791         'Σαβ' => 6,
12792         'Κυρ' => 7,
12793     );
12794
12795     /**
12796      * List of months, calendar month name => calendar month number
12797      *
12798      * @access protected
12799      * @var array
12800      */
12801     var $month = array(
12802         // English
12803         'jan' => 1,
12804         'january' => 1,
12805         'feb' => 2,
12806         'february' => 2,
12807         'mar' => 3,
12808         'march' => 3,
12809         'apr' => 4,
12810         'april' => 4,
12811         'may' => 5,
12812         // No long form of May
12813         'jun' => 6,
12814         'june' => 6,
12815         'jul' => 7,
12816         'july' => 7,
12817         'aug' => 8,
12818         'august' => 8,
12819         'sep' => 9,
12820         'september' => 8,
12821         'oct' => 10,
12822         'october' => 10,
12823         'nov' => 11,
12824         'november' => 11,
12825         'dec' => 12,
12826         'december' => 12,
12827         // Dutch
12828         'januari' => 1,
12829         'februari' => 2,
12830         'maart' => 3,
12831         'april' => 4,
12832         'mei' => 5,
12833         'juni' => 6,
12834         'juli' => 7,
12835         'augustus' => 8,
12836         'september' => 9,
12837         'oktober' => 10,
12838         'november' => 11,
12839         'december' => 12,
12840         // French
12841         'janvier' => 1,
12842         'février' => 2,
12843         'mars' => 3,
12844         'avril' => 4,
12845         'mai' => 5,
12846         'juin' => 6,
12847         'juillet' => 7,
12848         'août' => 8,
12849         'septembre' => 9,
12850         'octobre' => 10,
12851         'novembre' => 11,
12852         'décembre' => 12,
12853         // German
12854         'januar' => 1,
12855         'februar' => 2,
12856         'märz' => 3,
12857         'april' => 4,
12858         'mai' => 5,
12859         'juni' => 6,
12860         'juli' => 7,
12861         'august' => 8,
12862         'september' => 9,
12863         'oktober' => 10,
12864         'november' => 11,
12865         'dezember' => 12,
12866         // Italian
12867         'gennaio' => 1,
12868         'febbraio' => 2,
12869         'marzo' => 3,
12870         'aprile' => 4,
12871         'maggio' => 5,
12872         'giugno' => 6,
12873         'luglio' => 7,
12874         'agosto' => 8,
12875         'settembre' => 9,
12876         'ottobre' => 10,
12877         'novembre' => 11,
12878         'dicembre' => 12,
12879         // Spanish
12880         'enero' => 1,
12881         'febrero' => 2,
12882         'marzo' => 3,
12883         'abril' => 4,
12884         'mayo' => 5,
12885         'junio' => 6,
12886         'julio' => 7,
12887         'agosto' => 8,
12888         'septiembre' => 9,
12889         'setiembre' => 9,
12890         'octubre' => 10,
12891         'noviembre' => 11,
12892         'diciembre' => 12,
12893         // Finnish
12894         'tammikuu' => 1,
12895         'helmikuu' => 2,
12896         'maaliskuu' => 3,
12897         'huhtikuu' => 4,
12898         'toukokuu' => 5,
12899         'kesäkuu' => 6,
12900         'heinäkuu' => 7,
12901         'elokuu' => 8,
12902         'suuskuu' => 9,
12903         'lokakuu' => 10,
12904         'marras' => 11,
12905         'joulukuu' => 12,
12906         // Hungarian
12907         'január' => 1,
12908         'február' => 2,
12909         'március' => 3,
12910         'április' => 4,
12911         'május' => 5,
12912         'június' => 6,
12913         'július' => 7,
12914         'augusztus' => 8,
12915         'szeptember' => 9,
12916         'október' => 10,
12917         'november' => 11,
12918         'december' => 12,
12919         // Greek
12920         'Ιαν' => 1,
12921         'Φεβ' => 2,
12922         'Μάώ' => 3,
12923         'Μαώ' => 3,
12924         'Απρ' => 4,
12925         'Μάι' => 5,
12926         'Μαϊ' => 5,
12927         'Μαι' => 5,
12928         'Ιούν' => 6,
12929         'Ιον' => 6,
12930         'Ιούλ' => 7,
12931         'Ιολ' => 7,
12932         'Αύγ' => 8,
12933         'Αυγ' => 8,
12934         'Σεπ' => 9,
12935         'Οκτ' => 10,
12936         'Νοέ' => 11,
12937         'Δεκ' => 12,
12938     );
12939
12940     /**
12941      * List of timezones, abbreviation => offset from UTC
12942      *
12943      * @access protected
12944      * @var array
12945      */
12946     var $timezone = array(
12947         'ACDT' => 37800,
12948         'ACIT' => 28800,
12949         'ACST' => 34200,
12950         'ACT' => -18000,
12951         'ACWDT' => 35100,
12952         'ACWST' => 31500,
12953         'AEDT' => 39600,
12954         'AEST' => 36000,
12955         'AFT' => 16200,
12956         'AKDT' => -28800,
12957         'AKST' => -32400,
12958         'AMDT' => 18000,
12959         'AMT' => -14400,
12960         'ANAST' => 46800,
12961         'ANAT' => 43200,
12962         'ART' => -10800,
12963         'AZOST' => -3600,
12964         'AZST' => 18000,
12965         'AZT' => 14400,
12966         'BIOT' => 21600,
12967         'BIT' => -43200,
12968         'BOT' => -14400,
12969         'BRST' => -7200,
12970         'BRT' => -10800,
12971         'BST' => 3600,
12972         'BTT' => 21600,
12973         'CAST' => 18000,
12974         'CAT' => 7200,
12975         'CCT' => 23400,
12976         'CDT' => -18000,
12977         'CEDT' => 7200,
12978         'CET' => 3600,
12979         'CGST' => -7200,
12980         'CGT' => -10800,
12981         'CHADT' => 49500,
12982         'CHAST' => 45900,
12983         'CIST' => -28800,
12984         'CKT' => -36000,
12985         'CLDT' => -10800,
12986         'CLST' => -14400,
12987         'COT' => -18000,
12988         'CST' => -21600,
12989         'CVT' => -3600,
12990         'CXT' => 25200,
12991         'DAVT' => 25200,
12992         'DTAT' => 36000,
12993         'EADT' => -18000,
12994         'EAST' => -21600,
12995         'EAT' => 10800,
12996         'ECT' => -18000,
12997         'EDT' => -14400,
12998         'EEST' => 10800,
12999         'EET' => 7200,
13000         'EGT' => -3600,
13001         'EKST' => 21600,
13002         'EST' => -18000,
13003         'FJT' => 43200,
13004         'FKDT' => -10800,
13005         'FKST' => -14400,
13006         'FNT' => -7200,
13007         'GALT' => -21600,
13008         'GEDT' => 14400,
13009         'GEST' => 10800,
13010         'GFT' => -10800,
13011         'GILT' => 43200,
13012         'GIT' => -32400,
13013         'GST' => 14400,
13014         'GST' => -7200,
13015         'GYT' => -14400,
13016         'HAA' => -10800,
13017         'HAC' => -18000,
13018         'HADT' => -32400,
13019         'HAE' => -14400,
13020         'HAP' => -25200,
13021         'HAR' => -21600,
13022         'HAST' => -36000,
13023         'HAT' => -9000,
13024         'HAY' => -28800,
13025         'HKST' => 28800,
13026         'HMT' => 18000,
13027         'HNA' => -14400,
13028         'HNC' => -21600,
13029         'HNE' => -18000,
13030         'HNP' => -28800,
13031         'HNR' => -25200,
13032         'HNT' => -12600,
13033         'HNY' => -32400,
13034         'IRDT' => 16200,
13035         'IRKST' => 32400,
13036         'IRKT' => 28800,
13037         'IRST' => 12600,
13038         'JFDT' => -10800,
13039         'JFST' => -14400,
13040         'JST' => 32400,
13041         'KGST' => 21600,
13042         'KGT' => 18000,
13043         'KOST' => 39600,
13044         'KOVST' => 28800,
13045         'KOVT' => 25200,
13046         'KRAST' => 28800,
13047         'KRAT' => 25200,
13048         'KST' => 32400,
13049         'LHDT' => 39600,
13050         'LHST' => 37800,
13051         'LINT' => 50400,
13052         'LKT' => 21600,
13053         'MAGST' => 43200,
13054         'MAGT' => 39600,
13055         'MAWT' => 21600,
13056         'MDT' => -21600,
13057         'MESZ' => 7200,
13058         'MEZ' => 3600,
13059         'MHT' => 43200,
13060         'MIT' => -34200,
13061         'MNST' => 32400,
13062         'MSDT' => 14400,
13063         'MSST' => 10800,
13064         'MST' => -25200,
13065         'MUT' => 14400,
13066         'MVT' => 18000,
13067         'MYT' => 28800,
13068         'NCT' => 39600,
13069         'NDT' => -9000,
13070         'NFT' => 41400,
13071         'NMIT' => 36000,
13072         'NOVST' => 25200,
13073         'NOVT' => 21600,
13074         'NPT' => 20700,
13075         'NRT' => 43200,
13076         'NST' => -12600,
13077         'NUT' => -39600,
13078         'NZDT' => 46800,
13079         'NZST' => 43200,
13080         'OMSST' => 25200,
13081         'OMST' => 21600,
13082         'PDT' => -25200,
13083         'PET' => -18000,
13084         'PETST' => 46800,
13085         'PETT' => 43200,
13086         'PGT' => 36000,
13087         'PHOT' => 46800,
13088         'PHT' => 28800,
13089         'PKT' => 18000,
13090         'PMDT' => -7200,
13091         'PMST' => -10800,
13092         'PONT' => 39600,
13093         'PST' => -28800,
13094         'PWT' => 32400,
13095         'PYST' => -10800,
13096         'PYT' => -14400,
13097         'RET' => 14400,
13098         'ROTT' => -10800,
13099         'SAMST' => 18000,
13100         'SAMT' => 14400,
13101         'SAST' => 7200,
13102         'SBT' => 39600,
13103         'SCDT' => 46800,
13104         'SCST' => 43200,
13105         'SCT' => 14400,
13106         'SEST' => 3600,
13107         'SGT' => 28800,
13108         'SIT' => 28800,
13109         'SRT' => -10800,
13110         'SST' => -39600,
13111         'SYST' => 10800,
13112         'SYT' => 7200,
13113         'TFT' => 18000,
13114         'THAT' => -36000,
13115         'TJT' => 18000,
13116         'TKT' => -36000,
13117         'TMT' => 18000,
13118         'TOT' => 46800,
13119         'TPT' => 32400,
13120         'TRUT' => 36000,
13121         'TVT' => 43200,
13122         'TWT' => 28800,
13123         'UYST' => -7200,
13124         'UYT' => -10800,
13125         'UZT' => 18000,
13126         'VET' => -14400,
13127         'VLAST' => 39600,
13128         'VLAT' => 36000,
13129         'VOST' => 21600,
13130         'VUT' => 39600,
13131         'WAST' => 7200,
13132         'WAT' => 3600,
13133         'WDT' => 32400,
13134         'WEST' => 3600,
13135         'WFT' => 43200,
13136         'WIB' => 25200,
13137         'WIT' => 32400,
13138         'WITA' => 28800,
13139         'WKST' => 18000,
13140         'WST' => 28800,
13141         'YAKST' => 36000,
13142         'YAKT' => 32400,
13143         'YAPT' => 36000,
13144         'YEKST' => 21600,
13145         'YEKT' => 18000,
13146     );
13147
13148     /**
13149      * Cached PCRE for SimplePie_Parse_Date::$day
13150      *
13151      * @access protected
13152      * @var string
13153      */
13154     var $day_pcre;
13155
13156     /**
13157      * Cached PCRE for SimplePie_Parse_Date::$month
13158      *
13159      * @access protected
13160      * @var string
13161      */
13162     var $month_pcre;
13163
13164     /**
13165      * Array of user-added callback methods
13166      *
13167      * @access private
13168      * @var array
13169      */
13170     var $built_in = array();
13171
13172     /**
13173      * Array of user-added callback methods
13174      *
13175      * @access private
13176      * @var array
13177      */
13178     var $user = array();
13179
b1a6a5 13180
fd9ef2 13181     /**
T 13182      * Create new SimplePie_Parse_Date object, and set self::day_pcre,
13183      * self::month_pcre, and self::built_in
13184      *
13185      * @access private
13186      */
13187     function SimplePie_Parse_Date()
13188     {
13189         $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
13190         $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
13191
13192         static $cache;
13193         if (!isset($cache[get_class($this)]))
13194         {
13195             $all_methods = get_class_methods($this);
13196
13197             foreach ($all_methods as $method)
13198             {
13199                 if (strtolower(substr($method, 0, 5)) === 'date_')
13200                 {
13201                     $cache[get_class($this)][] = $method;
13202                 }
13203             }
13204         }
13205
13206         foreach ($cache[get_class($this)] as $method)
13207         {
13208             $this->built_in[] = $method;
13209         }
13210     }
13211
13212     /**
13213      * Get the object
13214      *
13215      * @access public
13216      */
829b76 13217     static function get()
fd9ef2 13218     {
T 13219         static $object;
13220         if (!$object)
13221         {
f64c86 13222             $object = new SimplePie_Parse_Date;
fd9ef2 13223         }
T 13224         return $object;
13225     }
13226
b1a6a5 13227
fd9ef2 13228     /**
T 13229      * Parse a date
13230      *
13231      * @final
13232      * @access public
13233      * @param string $date Date to parse
13234      * @return int Timestamp corresponding to date string, or false on failure
13235      */
13236     function parse($date)
13237     {
13238         foreach ($this->user as $method)
13239         {
13240             if (($returned = call_user_func($method, $date)) !== false)
13241             {
13242                 return $returned;
13243             }
13244         }
13245
13246         foreach ($this->built_in as $method)
13247         {
13248             if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
13249             {
13250                 return $returned;
13251             }
13252         }
13253
13254         return false;
13255     }
13256
b1a6a5 13257
fd9ef2 13258     /**
T 13259      * Add a callback method to parse a date
13260      *
13261      * @final
13262      * @access public
13263      * @param callback $callback
13264      */
13265     function add_callback($callback)
13266     {
13267         if (is_callable($callback))
13268         {
13269             $this->user[] = $callback;
13270         }
13271         else
13272         {
13273             trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
13274         }
13275     }
b1a6a5 13276
fd9ef2 13277
T 13278     /**
13279      * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
13280      * well as allowing any of upper or lower case "T", horizontal tabs, or
13281      * spaces to be used as the time seperator (including more than one))
13282      *
13283      * @access protected
13284      * @return int Timestamp
13285      */
13286     function date_w3cdtf($date)
13287     {
13288         static $pcre;
13289         if (!$pcre)
13290         {
13291             $year = '([0-9]{4})';
13292             $month = $day = $hour = $minute = $second = '([0-9]{2})';
13293             $decimal = '([0-9]*)';
13294             $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
13295             $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
13296         }
13297         if (preg_match($pcre, $date, $match))
13298         {
13299             /*
13300             Capturing subpatterns:
13301             1: Year
13302             2: Month
13303             3: Day
13304             4: Hour
13305             5: Minute
13306             6: Second
13307             7: Decimal fraction of a second
13308             8: Zulu
13309             9: Timezone ±
13310             10: Timezone hours
13311             11: Timezone minutes
13312             */
13313
13314             // Fill in empty matches
13315             for ($i = count($match); $i <= 3; $i++)
13316             {
13317                 $match[$i] = '1';
13318             }
13319
13320             for ($i = count($match); $i <= 7; $i++)
13321             {
13322                 $match[$i] = '0';
13323             }
13324
13325             // Numeric timezone
13326             if (isset($match[9]) && $match[9] !== '')
13327             {
13328                 $timezone = $match[10] * 3600;
13329                 $timezone += $match[11] * 60;
13330                 if ($match[9] === '-')
13331                 {
13332                     $timezone = 0 - $timezone;
13333                 }
13334             }
13335             else
13336             {
13337                 $timezone = 0;
13338             }
13339
13340             // Convert the number of seconds to an integer, taking decimals into account
13341             $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
13342
13343             return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
13344         }
13345         else
13346         {
13347             return false;
13348         }
13349     }
13350
b1a6a5 13351
fd9ef2 13352     /**
T 13353      * Remove RFC822 comments
13354      *
13355      * @access protected
13356      * @param string $data Data to strip comments from
13357      * @return string Comment stripped string
13358      */
13359     function remove_rfc2822_comments($string)
13360     {
13361         $string = (string) $string;
13362         $position = 0;
13363         $length = strlen($string);
13364         $depth = 0;
13365
13366         $output = '';
13367
13368         while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
13369         {
13370             $output .= substr($string, $position, $pos - $position);
13371             $position = $pos + 1;
13372             if ($string[$pos - 1] !== '\\')
13373             {
13374                 $depth++;
13375                 while ($depth && $position < $length)
13376                 {
13377                     $position += strcspn($string, '()', $position);
13378                     if ($string[$position - 1] === '\\')
13379                     {
13380                         $position++;
13381                         continue;
13382                     }
13383                     elseif (isset($string[$position]))
13384                     {
13385                         switch ($string[$position])
13386                         {
b1a6a5 13387                         case '(':
MC 13388                             $depth++;
13389                             break;
fd9ef2 13390
b1a6a5 13391                         case ')':
MC 13392                             $depth--;
13393                             break;
fd9ef2 13394                         }
T 13395                         $position++;
13396                     }
13397                     else
13398                     {
13399                         break;
13400                     }
13401                 }
13402             }
13403             else
13404             {
13405                 $output .= '(';
13406             }
13407         }
13408         $output .= substr($string, $position);
13409
13410         return $output;
13411     }
b1a6a5 13412
fd9ef2 13413
T 13414     /**
13415      * Parse RFC2822's date format
13416      *
13417      * @access protected
13418      * @return int Timestamp
13419      */
13420     function date_rfc2822($date)
13421     {
13422         static $pcre;
13423         if (!$pcre)
13424         {
13425             $wsp = '[\x09\x20]';
13426             $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
13427             $optional_fws = $fws . '?';
13428             $day_name = $this->day_pcre;
13429             $month = $this->month_pcre;
13430             $day = '([0-9]{1,2})';
13431             $hour = $minute = $second = '([0-9]{2})';
13432             $year = '([0-9]{2,4})';
13433             $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
13434             $character_zone = '([A-Z]{1,5})';
13435             $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
13436             $pcre = '/(?:' . $optional_fws . $day_name . $optional_fws . ',)?' . $optional_fws . $day . $fws . $month . $fws . $year . $fws . $hour . $optional_fws . ':' . $optional_fws . $minute . '(?:' . $optional_fws . ':' . $optional_fws . $second . ')?' . $fws . $zone . '/i';
13437         }
13438         if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
13439         {
13440             /*
13441             Capturing subpatterns:
13442             1: Day name
13443             2: Day
13444             3: Month
13445             4: Year
13446             5: Hour
13447             6: Minute
13448             7: Second
13449             8: Timezone ±
13450             9: Timezone hours
13451             10: Timezone minutes
13452             11: Alphabetic timezone
13453             */
13454
13455             // Find the month number
13456             $month = $this->month[strtolower($match[3])];
13457
13458             // Numeric timezone
13459             if ($match[8] !== '')
13460             {
13461                 $timezone = $match[9] * 3600;
13462                 $timezone += $match[10] * 60;
13463                 if ($match[8] === '-')
13464                 {
13465                     $timezone = 0 - $timezone;
13466                 }
13467             }
13468             // Character timezone
13469             elseif (isset($this->timezone[strtoupper($match[11])]))
13470             {
13471                 $timezone = $this->timezone[strtoupper($match[11])];
13472             }
13473             // Assume everything else to be -0000
13474             else
13475             {
13476                 $timezone = 0;
13477             }
13478
13479             // Deal with 2/3 digit years
13480             if ($match[4] < 50)
13481             {
13482                 $match[4] += 2000;
13483             }
13484             elseif ($match[4] < 1000)
13485             {
13486                 $match[4] += 1900;
13487             }
13488
13489             // Second is optional, if it is empty set it to zero
13490             if ($match[7] !== '')
13491             {
13492                 $second = $match[7];
13493             }
13494             else
13495             {
13496                 $second = 0;
13497             }
13498
13499             return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
13500         }
13501         else
13502         {
13503             return false;
13504         }
13505     }
13506
b1a6a5 13507
fd9ef2 13508     /**
T 13509      * Parse RFC850's date format
13510      *
13511      * @access protected
13512      * @return int Timestamp
13513      */
13514     function date_rfc850($date)
13515     {
13516         static $pcre;
13517         if (!$pcre)
13518         {
13519             $space = '[\x09\x20]+';
13520             $day_name = $this->day_pcre;
13521             $month = $this->month_pcre;
13522             $day = '([0-9]{1,2})';
13523             $year = $hour = $minute = $second = '([0-9]{2})';
13524             $zone = '([A-Z]{1,5})';
13525             $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
13526         }
13527         if (preg_match($pcre, $date, $match))
13528         {
13529             /*
13530             Capturing subpatterns:
13531             1: Day name
13532             2: Day
13533             3: Month
13534             4: Year
13535             5: Hour
13536             6: Minute
13537             7: Second
13538             8: Timezone
13539             */
13540
13541             // Month
13542             $month = $this->month[strtolower($match[3])];
13543
13544             // Character timezone
13545             if (isset($this->timezone[strtoupper($match[8])]))
13546             {
13547                 $timezone = $this->timezone[strtoupper($match[8])];
13548             }
13549             // Assume everything else to be -0000
13550             else
13551             {
13552                 $timezone = 0;
13553             }
13554
13555             // Deal with 2 digit year
13556             if ($match[4] < 50)
13557             {
13558                 $match[4] += 2000;
13559             }
13560             else
13561             {
13562                 $match[4] += 1900;
13563             }
13564
13565             return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
13566         }
13567         else
13568         {
13569             return false;
13570         }
13571     }
13572
b1a6a5 13573
fd9ef2 13574     /**
T 13575      * Parse C99's asctime()'s date format
13576      *
13577      * @access protected
13578      * @return int Timestamp
13579      */
13580     function date_asctime($date)
13581     {
13582         static $pcre;
13583         if (!$pcre)
13584         {
13585             $space = '[\x09\x20]+';
13586             $wday_name = $this->day_pcre;
13587             $mon_name = $this->month_pcre;
13588             $day = '([0-9]{1,2})';
13589             $hour = $sec = $min = '([0-9]{2})';
13590             $year = '([0-9]{4})';
13591             $terminator = '\x0A?\x00?';
13592             $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
13593         }
13594         if (preg_match($pcre, $date, $match))
13595         {
13596             /*
13597             Capturing subpatterns:
13598             1: Day name
13599             2: Month
13600             3: Day
13601             4: Hour
13602             5: Minute
13603             6: Second
13604             7: Year
13605             */
13606
13607             $month = $this->month[strtolower($match[2])];
13608             return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
13609         }
13610         else
13611         {
13612             return false;
13613         }
13614     }
13615
b1a6a5 13616
fd9ef2 13617     /**
T 13618      * Parse dates using strtotime()
13619      *
13620      * @access protected
13621      * @return int Timestamp
13622      */
13623     function date_strtotime($date)
13624     {
13625         $strtotime = strtotime($date);
13626         if ($strtotime === -1 || $strtotime === false)
13627         {
13628             return false;
13629         }
13630         else
13631         {
13632             return $strtotime;
13633         }
13634     }
b1a6a5 13635
fd9ef2 13636 }
T 13637
13638 /**
13639  * Content-type sniffing
13640  *
13641  * @package SimplePie
13642  */
13643 class SimplePie_Content_Type_Sniffer
13644 {
b1a6a5 13645
fd9ef2 13646     /**
T 13647      * File object
13648      *
13649      * @var SimplePie_File
13650      * @access private
13651      */
13652     var $file;
b1a6a5 13653
fd9ef2 13654
T 13655     /**
13656      * Create an instance of the class with the input file
13657      *
13658      * @access public
13659      * @param SimplePie_Content_Type_Sniffer $file Input file
13660      */
13661     function SimplePie_Content_Type_Sniffer($file)
13662     {
13663         $this->file = $file;
13664     }
b1a6a5 13665
fd9ef2 13666
T 13667     /**
13668      * Get the Content-Type of the specified file
13669      *
13670      * @access public
13671      * @return string Actual Content-Type
13672      */
13673     function get_type()
13674     {
13675         if (isset($this->file->headers['content-type']))
13676         {
13677             if (!isset($this->file->headers['content-encoding'])
13678                 && ($this->file->headers['content-type'] === 'text/plain'
13679                     || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
13680                     || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
13681             {
13682                 return $this->text_or_binary();
13683             }
13684
13685             if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
13686             {
13687                 $official = substr($this->file->headers['content-type'], 0, $pos);
13688             }
13689             else
13690             {
13691                 $official = $this->file->headers['content-type'];
13692             }
13693             $official = strtolower($official);
13694
13695             if ($official === 'unknown/unknown'
13696                 || $official === 'application/unknown')
13697             {
13698                 return $this->unknown();
13699             }
13700             elseif (substr($official, -4) === '+xml'
13701                 || $official === 'text/xml'
13702                 || $official === 'application/xml')
13703             {
13704                 return $official;
13705             }
13706             elseif (substr($official, 0, 6) === 'image/')
13707             {
13708                 if ($return = $this->image())
13709                 {
13710                     return $return;
13711                 }
13712                 else
13713                 {
13714                     return $official;
13715                 }
13716             }
13717             elseif ($official === 'text/html')
13718             {
13719                 return $this->feed_or_html();
13720             }
13721             else
13722             {
13723                 return $official;
13724             }
13725         }
13726         else
13727         {
13728             return $this->unknown();
13729         }
13730     }
13731
b1a6a5 13732
fd9ef2 13733     /**
T 13734      * Sniff text or binary
13735      *
13736      * @access private
13737      * @return string Actual Content-Type
13738      */
13739     function text_or_binary()
13740     {
13741         if (substr($this->file->body, 0, 2) === "\xFE\xFF"
13742             || substr($this->file->body, 0, 2) === "\xFF\xFE"
13743             || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
13744             || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
13745         {
13746             return 'text/plain';
13747         }
13748         elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
13749         {
13750             return 'application/octect-stream';
13751         }
13752         else
13753         {
13754             return 'text/plain';
13755         }
13756     }
b1a6a5 13757
fd9ef2 13758
T 13759     /**
13760      * Sniff unknown
13761      *
13762      * @access private
13763      * @return string Actual Content-Type
13764      */
13765     function unknown()
13766     {
13767         $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
13768         if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
13769             || strtolower(substr($this->file->body, $ws, 5)) === '<html'
13770             || strtolower(substr($this->file->body, $ws, 7)) === '<script')
13771         {
13772             return 'text/html';
13773         }
13774         elseif (substr($this->file->body, 0, 5) === '%PDF-')
13775         {
13776             return 'application/pdf';
13777         }
13778         elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
13779         {
13780             return 'application/postscript';
13781         }
13782         elseif (substr($this->file->body, 0, 6) === 'GIF87a'
13783             || substr($this->file->body, 0, 6) === 'GIF89a')
13784         {
13785             return 'image/gif';
13786         }
13787         elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13788         {
13789             return 'image/png';
13790         }
13791         elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13792         {
13793             return 'image/jpeg';
13794         }
13795         elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13796         {
13797             return 'image/bmp';
13798         }
13799         else
13800         {
13801             return $this->text_or_binary();
13802         }
13803     }
13804
b1a6a5 13805
fd9ef2 13806     /**
T 13807      * Sniff images
13808      *
13809      * @access private
13810      * @return string Actual Content-Type
13811      */
13812     function image()
13813     {
13814         if (substr($this->file->body, 0, 6) === 'GIF87a'
13815             || substr($this->file->body, 0, 6) === 'GIF89a')
13816         {
13817             return 'image/gif';
13818         }
13819         elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13820         {
13821             return 'image/png';
13822         }
13823         elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13824         {
13825             return 'image/jpeg';
13826         }
13827         elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13828         {
13829             return 'image/bmp';
13830         }
13831         else
13832         {
13833             return false;
13834         }
13835     }
13836
b1a6a5 13837
fd9ef2 13838     /**
T 13839      * Sniff HTML
13840      *
13841      * @access private
13842      * @return string Actual Content-Type
13843      */
13844     function feed_or_html()
13845     {
13846         $len = strlen($this->file->body);
13847         $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
13848
13849         while ($pos < $len)
13850         {
13851             switch ($this->file->body[$pos])
13852             {
b1a6a5 13853             case "\x09":
MC 13854             case "\x0A":
13855             case "\x0D":
13856             case "\x20":
13857                 $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
13858                 continue 2;
fd9ef2 13859
b1a6a5 13860             case '<':
MC 13861                 $pos++;
13862                 break;
fd9ef2 13863
b1a6a5 13864             default:
MC 13865                 return 'text/html';
fd9ef2 13866             }
T 13867
13868             if (substr($this->file->body, $pos, 3) === '!--')
13869             {
13870                 $pos += 3;
13871                 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
13872                 {
13873                     $pos += 3;
13874                 }
13875                 else
13876                 {
13877                     return 'text/html';
13878                 }
13879             }
13880             elseif (substr($this->file->body, $pos, 1) === '!')
13881             {
13882                 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
13883                 {
13884                     $pos++;
13885                 }
13886                 else
13887                 {
13888                     return 'text/html';
13889                 }
13890             }
13891             elseif (substr($this->file->body, $pos, 1) === '?')
13892             {
13893                 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
13894                 {
13895                     $pos += 2;
13896                 }
13897                 else
13898                 {
13899                     return 'text/html';
13900                 }
13901             }
13902             elseif (substr($this->file->body, $pos, 3) === 'rss'
13903                 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
13904             {
13905                 return 'application/rss+xml';
13906             }
13907             elseif (substr($this->file->body, $pos, 4) === 'feed')
13908             {
13909                 return 'application/atom+xml';
13910             }
13911             else
13912             {
13913                 return 'text/html';
13914             }
13915         }
13916
13917         return 'text/html';
13918     }
b1a6a5 13919
fd9ef2 13920 }
T 13921
13922 /**
13923  * Parses the XML Declaration
13924  *
13925  * @package SimplePie
13926  */
13927 class SimplePie_XML_Declaration_Parser
13928 {
b1a6a5 13929
fd9ef2 13930     /**
T 13931      * XML Version
13932      *
13933      * @access public
13934      * @var string
13935      */
13936     var $version = '1.0';
13937
13938     /**
13939      * Encoding
13940      *
13941      * @access public
13942      * @var string
13943      */
13944     var $encoding = 'UTF-8';
13945
13946     /**
13947      * Standalone
13948      *
13949      * @access public
13950      * @var bool
13951      */
13952     var $standalone = false;
13953
13954     /**
13955      * Current state of the state machine
13956      *
13957      * @access private
13958      * @var string
13959      */
13960     var $state = 'before_version_name';
13961
13962     /**
13963      * Input data
13964      *
13965      * @access private
13966      * @var string
13967      */
13968     var $data = '';
13969
13970     /**
13971      * Input data length (to avoid calling strlen() everytime this is needed)
13972      *
13973      * @access private
13974      * @var int
13975      */
13976     var $data_length = 0;
13977
13978     /**
13979      * Current position of the pointer
13980      *
13981      * @var int
13982      * @access private
13983      */
13984     var $position = 0;
13985
b1a6a5 13986
fd9ef2 13987     /**
T 13988      * Create an instance of the class with the input data
13989      *
13990      * @access public
13991      * @param string $data Input data
13992      */
13993     function SimplePie_XML_Declaration_Parser($data)
13994     {
13995         $this->data = $data;
13996         $this->data_length = strlen($this->data);
13997     }
b1a6a5 13998
fd9ef2 13999
T 14000     /**
14001      * Parse the input data
14002      *
14003      * @access public
14004      * @return bool true on success, false on failure
14005      */
14006     function parse()
14007     {
14008         while ($this->state && $this->state !== 'emit' && $this->has_data())
14009         {
14010             $state = $this->state;
14011             $this->$state();
14012         }
14013         $this->data = '';
14014         if ($this->state === 'emit')
14015         {
14016             return true;
14017         }
14018         else
14019         {
14020             $this->version = '';
14021             $this->encoding = '';
14022             $this->standalone = '';
14023             return false;
14024         }
14025     }
14026
b1a6a5 14027
fd9ef2 14028     /**
T 14029      * Check whether there is data beyond the pointer
14030      *
14031      * @access private
14032      * @return bool true if there is further data, false if not
14033      */
14034     function has_data()
14035     {
14036         return (bool) ($this->position < $this->data_length);
14037     }
b1a6a5 14038
fd9ef2 14039
T 14040     /**
14041      * Advance past any whitespace
14042      *
14043      * @return int Number of whitespace characters passed
14044      */
14045     function skip_whitespace()
14046     {
14047         $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
14048         $this->position += $whitespace;
14049         return $whitespace;
14050     }
b1a6a5 14051
fd9ef2 14052
T 14053     /**
14054      * Read value
14055      */
14056     function get_value()
14057     {
14058         $quote = substr($this->data, $this->position, 1);
14059         if ($quote === '"' || $quote === "'")
14060         {
14061             $this->position++;
14062             $len = strcspn($this->data, $quote, $this->position);
14063             if ($this->has_data())
14064             {
14065                 $value = substr($this->data, $this->position, $len);
14066                 $this->position += $len + 1;
14067                 return $value;
14068             }
14069         }
14070         return false;
14071     }
14072
14073     function before_version_name()
14074     {
14075         if ($this->skip_whitespace())
14076         {
14077             $this->state = 'version_name';
14078         }
14079         else
14080         {
14081             $this->state = false;
14082         }
14083     }
14084
14085     function version_name()
14086     {
14087         if (substr($this->data, $this->position, 7) === 'version')
14088         {
14089             $this->position += 7;
14090             $this->skip_whitespace();
14091             $this->state = 'version_equals';
14092         }
14093         else
14094         {
14095             $this->state = false;
14096         }
14097     }
14098
14099     function version_equals()
14100     {
14101         if (substr($this->data, $this->position, 1) === '=')
14102         {
14103             $this->position++;
14104             $this->skip_whitespace();
14105             $this->state = 'version_value';
14106         }
14107         else
14108         {
14109             $this->state = false;
14110         }
14111     }
14112
14113     function version_value()
14114     {
14115         if ($this->version = $this->get_value())
14116         {
14117             $this->skip_whitespace();
14118             if ($this->has_data())
14119             {
14120                 $this->state = 'encoding_name';
14121             }
14122             else
14123             {
14124                 $this->state = 'emit';
14125             }
14126         }
14127         else
14128         {
14129             $this->state = false;
14130         }
14131     }
14132
14133     function encoding_name()
14134     {
14135         if (substr($this->data, $this->position, 8) === 'encoding')
14136         {
14137             $this->position += 8;
14138             $this->skip_whitespace();
14139             $this->state = 'encoding_equals';
14140         }
14141         else
14142         {
14143             $this->state = 'standalone_name';
14144         }
14145     }
14146
14147     function encoding_equals()
14148     {
14149         if (substr($this->data, $this->position, 1) === '=')
14150         {
14151             $this->position++;
14152             $this->skip_whitespace();
14153             $this->state = 'encoding_value';
14154         }
14155         else
14156         {
14157             $this->state = false;
14158         }
14159     }
14160
14161     function encoding_value()
14162     {
14163         if ($this->encoding = $this->get_value())
14164         {
14165             $this->skip_whitespace();
14166             if ($this->has_data())
14167             {
14168                 $this->state = 'standalone_name';
14169             }
14170             else
14171             {
14172                 $this->state = 'emit';
14173             }
14174         }
14175         else
14176         {
14177             $this->state = false;
14178         }
14179     }
14180
14181     function standalone_name()
14182     {
14183         if (substr($this->data, $this->position, 10) === 'standalone')
14184         {
14185             $this->position += 10;
14186             $this->skip_whitespace();
14187             $this->state = 'standalone_equals';
14188         }
14189         else
14190         {
14191             $this->state = false;
14192         }
14193     }
14194
14195     function standalone_equals()
14196     {
14197         if (substr($this->data, $this->position, 1) === '=')
14198         {
14199             $this->position++;
14200             $this->skip_whitespace();
14201             $this->state = 'standalone_value';
14202         }
14203         else
14204         {
14205             $this->state = false;
14206         }
14207     }
14208
14209     function standalone_value()
14210     {
14211         if ($standalone = $this->get_value())
14212         {
14213             switch ($standalone)
14214             {
b1a6a5 14215             case 'yes':
MC 14216                 $this->standalone = true;
14217                 break;
fd9ef2 14218
b1a6a5 14219             case 'no':
MC 14220                 $this->standalone = false;
14221                 break;
fd9ef2 14222
b1a6a5 14223             default:
MC 14224                 $this->state = false;
14225                 return;
fd9ef2 14226             }
T 14227
14228             $this->skip_whitespace();
14229             if ($this->has_data())
14230             {
14231                 $this->state = false;
14232             }
14233             else
14234             {
14235                 $this->state = 'emit';
14236             }
14237         }
14238         else
14239         {
14240             $this->state = false;
14241         }
14242     }
b1a6a5 14243
fd9ef2 14244 }
T 14245
14246 class SimplePie_Locator
14247 {
14248     var $useragent;
14249     var $timeout;
14250     var $file;
14251     var $local = array();
14252     var $elsewhere = array();
14253     var $file_class = 'SimplePie_File';
14254     var $cached_entities = array();
14255     var $http_base;
14256     var $base;
14257     var $base_location = 0;
14258     var $checked_feeds = 0;
14259     var $max_checked_feeds = 10;
14260     var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
14261
14262     function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
14263     {
14264         $this->file =& $file;
14265         $this->file_class = $file_class;
14266         $this->useragent = $useragent;
14267         $this->timeout = $timeout;
14268         $this->max_checked_feeds = $max_checked_feeds;
14269         $this->content_type_sniffer_class = $content_type_sniffer_class;
14270     }
14271
14272     function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
14273     {
14274         if ($this->is_feed($this->file))
14275         {
14276             return $this->file;
14277         }
14278
14279         if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14280         {
f64c86 14281             $sniffer = new $this->content_type_sniffer_class($this->file);
fd9ef2 14282             if ($sniffer->get_type() !== 'text/html')
T 14283             {
14284                 return null;
14285             }
14286         }
14287
14288         if ($type & ~SIMPLEPIE_LOCATOR_NONE)
14289         {
14290             $this->get_base();
14291         }
14292
14293         if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
14294         {
14295             return $working[0];
14296         }
14297
14298         if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
14299         {
14300             if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
14301             {
14302                 return $working;
14303             }
14304
14305             if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
14306             {
14307                 return $working;
14308             }
14309
14310             if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
14311             {
14312                 return $working;
14313             }
14314
14315             if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
14316             {
14317                 return $working;
14318             }
14319         }
14320         return null;
14321     }
14322
14323     function is_feed(&$file)
14324     {
14325         if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14326         {
f64c86 14327             $sniffer = new $this->content_type_sniffer_class($file);
fd9ef2 14328             $sniffed = $sniffer->get_type();
T 14329             if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
14330             {
14331                 return true;
14332             }
14333             else
14334             {
14335                 return false;
14336             }
14337         }
14338         elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
14339         {
14340             return true;
14341         }
14342         else
14343         {
14344             return false;
14345         }
14346     }
14347
14348     function get_base()
14349     {
14350         $this->http_base = $this->file->url;
14351         $this->base = $this->http_base;
14352         $elements = SimplePie_Misc::get_element('base', $this->file->body);
14353         foreach ($elements as $element)
14354         {
14355             if ($element['attribs']['href']['data'] !== '')
14356             {
14357                 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
14358                 $this->base_location = $element['offset'];
14359                 break;
14360             }
14361         }
14362     }
14363
14364     function autodiscovery()
14365     {
14366         $links = array_merge(SimplePie_Misc::get_element('link', $this->file->body), SimplePie_Misc::get_element('a', $this->file->body), SimplePie_Misc::get_element('area', $this->file->body));
14367         $done = array();
14368         $feeds = array();
14369         foreach ($links as $link)
14370         {
14371             if ($this->checked_feeds === $this->max_checked_feeds)
14372             {
14373                 break;
14374             }
14375             if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
14376             {
14377                 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
14378
14379                 if ($this->base_location < $link['offset'])
14380                 {
14381                     $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14382                 }
14383                 else
14384                 {
14385                     $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14386                 }
14387
14388                 if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !empty($link['attribs']['type']['data']) && in_array(strtolower(SimplePie_Misc::parse_mime($link['attribs']['type']['data'])), array('application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href]))
14389                 {
14390                     $this->checked_feeds++;
f64c86 14391                     $feed = new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
fd9ef2 14392                     if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
T 14393                     {
14394                         $feeds[$href] = $feed;
14395                     }
14396                 }
14397                 $done[] = $href;
14398             }
14399         }
14400
14401         if (!empty($feeds))
14402         {
14403             return array_values($feeds);
14404         }
14405         else {
14406             return null;
14407         }
14408     }
14409
14410     function get_links()
14411     {
14412         $links = SimplePie_Misc::get_element('a', $this->file->body);
14413         foreach ($links as $link)
14414         {
14415             if (isset($link['attribs']['href']['data']))
14416             {
14417                 $href = trim($link['attribs']['href']['data']);
14418                 $parsed = SimplePie_Misc::parse_url($href);
14419                 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
14420                 {
14421                     if ($this->base_location < $link['offset'])
14422                     {
14423                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14424                     }
14425                     else
14426                     {
14427                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14428                     }
14429
14430                     $current = SimplePie_Misc::parse_url($this->file->url);
14431
14432                     if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
14433                     {
14434                         $this->local[] = $href;
14435                     }
14436                     else
14437                     {
14438                         $this->elsewhere[] = $href;
14439                     }
14440                 }
14441             }
14442         }
14443         $this->local = array_unique($this->local);
14444         $this->elsewhere = array_unique($this->elsewhere);
14445         if (!empty($this->local) || !empty($this->elsewhere))
14446         {
14447             return true;
14448         }
14449         return null;
14450     }
14451
14452     function extension(&$array)
14453     {
14454         foreach ($array as $key => $value)
14455         {
14456             if ($this->checked_feeds === $this->max_checked_feeds)
14457             {
14458                 break;
14459             }
14460             if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
14461             {
14462                 $this->checked_feeds++;
f64c86 14463                 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
fd9ef2 14464                 if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
T 14465                 {
14466                     return $feed;
14467                 }
14468                 else
14469                 {
14470                     unset($array[$key]);
14471                 }
14472             }
14473         }
14474         return null;
14475     }
14476
14477     function body(&$array)
14478     {
14479         foreach ($array as $key => $value)
14480         {
14481             if ($this->checked_feeds === $this->max_checked_feeds)
14482             {
14483                 break;
14484             }
14485             if (preg_match('/(rss|rdf|atom|xml)/i', $value))
14486             {
14487                 $this->checked_feeds++;
f64c86 14488                 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
fd9ef2 14489                 if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
T 14490                 {
14491                     return $feed;
14492                 }
14493                 else
14494                 {
14495                     unset($array[$key]);
14496                 }
14497             }
14498         }
14499         return null;
14500     }
b1a6a5 14501
fd9ef2 14502 }
T 14503
14504 class SimplePie_Parser
14505 {
14506     var $error_code;
14507     var $error_string;
14508     var $current_line;
14509     var $current_column;
14510     var $current_byte;
14511     var $separator = ' ';
14512     var $namespace = array('');
14513     var $element = array('');
14514     var $xml_base = array('');
14515     var $xml_base_explicit = array(false);
14516     var $xml_lang = array('');
14517     var $data = array();
14518     var $datas = array(array());
14519     var $current_xhtml_construct = -1;
14520     var $encoding;
14521
14522     function parse(&$data, $encoding)
14523     {
14524         // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
14525         if (strtoupper($encoding) === 'US-ASCII')
14526         {
14527             $this->encoding = 'UTF-8';
14528         }
14529         else
14530         {
14531             $this->encoding = $encoding;
14532         }
14533
14534         // Strip BOM:
14535         // UTF-32 Big Endian BOM
14536         if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14537         {
14538             $data = substr($data, 4);
14539         }
14540         // UTF-32 Little Endian BOM
14541         elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14542         {
14543             $data = substr($data, 4);
14544         }
14545         // UTF-16 Big Endian BOM
14546         elseif (substr($data, 0, 2) === "\xFE\xFF")
14547         {
14548             $data = substr($data, 2);
14549         }
14550         // UTF-16 Little Endian BOM
14551         elseif (substr($data, 0, 2) === "\xFF\xFE")
14552         {
14553             $data = substr($data, 2);
14554         }
14555         // UTF-8 BOM
14556         elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14557         {
14558             $data = substr($data, 3);
14559         }
14560
14561         if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
14562         {
f64c86 14563             $declaration = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
fd9ef2 14564             if ($declaration->parse())
T 14565             {
14566                 $data = substr($data, $pos + 2);
14567                 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
14568             }
14569             else
14570             {
14571                 $this->error_string = 'SimplePie bug! Please report this!';
14572                 return false;
14573             }
14574         }
14575
14576         $return = true;
14577
14578         static $xml_is_sane = null;
14579         if ($xml_is_sane === null)
14580         {
14581             $parser_check = xml_parser_create();
14582             xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
14583             xml_parser_free($parser_check);
14584             $xml_is_sane = isset($values[0]['value']);
14585         }
14586
14587         // Create the parser
14588         if ($xml_is_sane)
14589         {
14590             $xml = xml_parser_create_ns($this->encoding, $this->separator);
14591             xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
14592             xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
14593             xml_set_object($xml, $this);
14594             xml_set_character_data_handler($xml, 'cdata');
14595             xml_set_element_handler($xml, 'tag_open', 'tag_close');
14596
14597             // Parse!
14598             if (!xml_parse($xml, $data, true))
14599             {
14600                 $this->error_code = xml_get_error_code($xml);
14601                 $this->error_string = xml_error_string($this->error_code);
14602                 $return = false;
14603             }
14604             $this->current_line = xml_get_current_line_number($xml);
14605             $this->current_column = xml_get_current_column_number($xml);
14606             $this->current_byte = xml_get_current_byte_index($xml);
14607             xml_parser_free($xml);
14608             return $return;
14609         }
14610         else
14611         {
14612             libxml_clear_errors();
f64c86 14613             $xml = new XMLReader();
fd9ef2 14614             $xml->xml($data);
T 14615             while (@$xml->read())
14616             {
14617                 switch ($xml->nodeType)
14618                 {
14619
b1a6a5 14620                 case constant('XMLReader::END_ELEMENT'):
MC 14621                     if ($xml->namespaceURI !== '')
14622                     {
14623                         $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14624                     }
14625                     else
14626                     {
14627                         $tagName = $xml->localName;
14628                     }
14629                     $this->tag_close(null, $tagName);
14630                     break;
14631                 case constant('XMLReader::ELEMENT'):
14632                     $empty = $xml->isEmptyElement;
14633                     if ($xml->namespaceURI !== '')
14634                     {
14635                         $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14636                     }
14637                     else
14638                     {
14639                         $tagName = $xml->localName;
14640                     }
14641                     $attributes = array();
14642                     while ($xml->moveToNextAttribute())
14643                     {
fd9ef2 14644                         if ($xml->namespaceURI !== '')
T 14645                         {
b1a6a5 14646                             $attrName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
fd9ef2 14647                         }
T 14648                         else
14649                         {
b1a6a5 14650                             $attrName = $xml->localName;
fd9ef2 14651                         }
b1a6a5 14652                         $attributes[$attrName] = $xml->value;
MC 14653                     }
14654                     $this->tag_open(null, $tagName, $attributes);
14655                     if ($empty)
14656                     {
fd9ef2 14657                         $this->tag_close(null, $tagName);
b1a6a5 14658                     }
MC 14659                     break;
14660                 case constant('XMLReader::TEXT'):
fd9ef2 14661
b1a6a5 14662                 case constant('XMLReader::CDATA'):
MC 14663                     $this->cdata(null, $xml->value);
14664                     break;
fd9ef2 14665                 }
T 14666             }
14667             if ($error = libxml_get_last_error())
14668             {
14669                 $this->error_code = $error->code;
14670                 $this->error_string = $error->message;
14671                 $this->current_line = $error->line;
14672                 $this->current_column = $error->column;
14673                 return false;
14674             }
14675             else
14676             {
14677                 return true;
14678             }
14679         }
14680     }
14681
14682     function get_error_code()
14683     {
14684         return $this->error_code;
14685     }
14686
14687     function get_error_string()
14688     {
14689         return $this->error_string;
14690     }
14691
14692     function get_current_line()
14693     {
14694         return $this->current_line;
14695     }
14696
14697     function get_current_column()
14698     {
14699         return $this->current_column;
14700     }
14701
14702     function get_current_byte()
14703     {
14704         return $this->current_byte;
14705     }
14706
14707     function get_data()
14708     {
14709         return $this->data;
14710     }
14711
14712     function tag_open($parser, $tag, $attributes)
14713     {
14714         list($this->namespace[], $this->element[]) = $this->split_ns($tag);
14715
14716         $attribs = array();
14717         foreach ($attributes as $name => $value)
14718         {
14719             list($attrib_namespace, $attribute) = $this->split_ns($name);
14720             $attribs[$attrib_namespace][$attribute] = $value;
14721         }
14722
14723         if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
14724         {
14725             $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
14726             $this->xml_base_explicit[] = true;
14727         }
14728         else
14729         {
14730             $this->xml_base[] = end($this->xml_base);
14731             $this->xml_base_explicit[] = end($this->xml_base_explicit);
14732         }
14733
14734         if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
14735         {
14736             $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
14737         }
14738         else
14739         {
14740             $this->xml_lang[] = end($this->xml_lang);
14741         }
14742
14743         if ($this->current_xhtml_construct >= 0)
14744         {
14745             $this->current_xhtml_construct++;
14746             if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
14747             {
14748                 $this->data['data'] .= '<' . end($this->element);
14749                 if (isset($attribs['']))
14750                 {
14751                     foreach ($attribs[''] as $name => $value)
14752                     {
14753                         $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
14754                     }
14755                 }
14756                 $this->data['data'] .= '>';
14757             }
14758         }
14759         else
14760         {
14761             $this->datas[] =& $this->data;
14762             $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
14763             $this->data = array('data' => '', 'attribs' => $attribs, 'xml_base' => end($this->xml_base), 'xml_base_explicit' => end($this->xml_base_explicit), 'xml_lang' => end($this->xml_lang));
14764             if ((end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_03 && in_array(end($this->element), array('title', 'tagline', 'copyright', 'info', 'summary', 'content')) && isset($attribs['']['mode']) && $attribs['']['mode'] === 'xml')
b1a6a5 14765                 || (end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_10 && in_array(end($this->element), array('rights', 'subtitle', 'summary', 'info', 'title', 'content')) && isset($attribs['']['type']) && $attribs['']['type'] === 'xhtml'))
fd9ef2 14766             {
T 14767                 $this->current_xhtml_construct = 0;
14768             }
14769         }
14770     }
14771
14772     function cdata($parser, $cdata)
14773     {
14774         if ($this->current_xhtml_construct >= 0)
14775         {
14776             $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
14777         }
14778         else
14779         {
14780             $this->data['data'] .= $cdata;
14781         }
14782     }
14783
14784     function tag_close($parser, $tag)
14785     {
14786         if ($this->current_xhtml_construct >= 0)
14787         {
14788             $this->current_xhtml_construct--;
14789             if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML && !in_array(end($this->element), array('area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param')))
14790             {
14791                 $this->data['data'] .= '</' . end($this->element) . '>';
14792             }
14793         }
14794         if ($this->current_xhtml_construct === -1)
14795         {
14796             $this->data =& $this->datas[count($this->datas) - 1];
14797             array_pop($this->datas);
14798         }
14799
14800         array_pop($this->element);
14801         array_pop($this->namespace);
14802         array_pop($this->xml_base);
14803         array_pop($this->xml_base_explicit);
14804         array_pop($this->xml_lang);
14805     }
14806
14807     function split_ns($string)
14808     {
14809         static $cache = array();
14810         if (!isset($cache[$string]))
14811         {
14812             if ($pos = strpos($string, $this->separator))
14813             {
14814                 static $separator_length;
14815                 if (!$separator_length)
14816                 {
14817                     $separator_length = strlen($this->separator);
14818                 }
14819                 $namespace = substr($string, 0, $pos);
14820                 $local_name = substr($string, $pos + $separator_length);
14821                 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
14822                 {
14823                     $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
14824                 }
14825
14826                 // Normalize the Media RSS namespaces
14827                 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
14828                 {
14829                     $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
14830                 }
14831                 $cache[$string] = array($namespace, $local_name);
14832             }
14833             else
14834             {
14835                 $cache[$string] = array('', $string);
14836             }
14837         }
14838         return $cache[$string];
14839     }
b1a6a5 14840
fd9ef2 14841 }
T 14842
14843 /**
14844  * @todo Move to using an actual HTML parser (this will allow tags to be properly stripped, and to switch between HTML and XHTML), this will also make it easier to shorten a string while preserving HTML tags
14845  */
14846 class SimplePie_Sanitize
14847 {
14848     // Private vars
14849     var $base;
14850
14851     // Options
14852     var $remove_div = true;
14853     var $image_handler = '';
14854     var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
14855     var $encode_instead_of_strip = false;
14856     var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
14857     var $strip_comments = false;
14858     var $output_encoding = 'UTF-8';
14859     var $enable_cache = true;
14860     var $cache_location = './cache';
14861     var $cache_name_function = 'md5';
14862     var $cache_class = 'SimplePie_Cache';
14863     var $file_class = 'SimplePie_File';
14864     var $timeout = 10;
14865     var $useragent = '';
14866     var $force_fsockopen = false;
14867
14868     var $replace_url_attributes = array(
14869         'a' => 'href',
14870         'area' => 'href',
14871         'blockquote' => 'cite',
14872         'del' => 'cite',
14873         'form' => 'action',
14874         'img' => array('longdesc', 'src'),
14875         'input' => 'src',
14876         'ins' => 'cite',
14877         'q' => 'cite'
14878     );
14879
14880     function remove_div($enable = true)
14881     {
14882         $this->remove_div = (bool) $enable;
14883     }
14884
14885     function set_image_handler($page = false)
14886     {
14887         if ($page)
14888         {
14889             $this->image_handler = (string) $page;
14890         }
14891         else
14892         {
14893             $this->image_handler = false;
14894         }
14895     }
14896
14897     function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
14898     {
14899         if (isset($enable_cache))
14900         {
14901             $this->enable_cache = (bool) $enable_cache;
14902         }
14903
14904         if ($cache_location)
14905         {
14906             $this->cache_location = (string) $cache_location;
14907         }
14908
14909         if ($cache_name_function)
14910         {
14911             $this->cache_name_function = (string) $cache_name_function;
14912         }
14913
14914         if ($cache_class)
14915         {
14916             $this->cache_class = (string) $cache_class;
14917         }
14918     }
14919
14920     function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
14921     {
14922         if ($file_class)
14923         {
14924             $this->file_class = (string) $file_class;
14925         }
14926
14927         if ($timeout)
14928         {
14929             $this->timeout = (string) $timeout;
14930         }
14931
14932         if ($useragent)
14933         {
14934             $this->useragent = (string) $useragent;
14935         }
14936
14937         if ($force_fsockopen)
14938         {
14939             $this->force_fsockopen = (string) $force_fsockopen;
14940         }
14941     }
14942
14943     function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
14944     {
14945         if ($tags)
14946         {
14947             if (is_array($tags))
14948             {
14949                 $this->strip_htmltags = $tags;
14950             }
14951             else
14952             {
14953                 $this->strip_htmltags = explode(',', $tags);
14954             }
14955         }
14956         else
14957         {
14958             $this->strip_htmltags = false;
14959         }
14960     }
14961
14962     function encode_instead_of_strip($encode = false)
14963     {
14964         $this->encode_instead_of_strip = (bool) $encode;
14965     }
14966
14967     function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
14968     {
14969         if ($attribs)
14970         {
14971             if (is_array($attribs))
14972             {
14973                 $this->strip_attributes = $attribs;
14974             }
14975             else
14976             {
14977                 $this->strip_attributes = explode(',', $attribs);
14978             }
14979         }
14980         else
14981         {
14982             $this->strip_attributes = false;
14983         }
14984     }
14985
14986     function strip_comments($strip = false)
14987     {
14988         $this->strip_comments = (bool) $strip;
14989     }
14990
14991     function set_output_encoding($encoding = 'UTF-8')
14992     {
14993         $this->output_encoding = (string) $encoding;
14994     }
b1a6a5 14995
fd9ef2 14996
T 14997     /**
14998      * Set element/attribute key/value pairs of HTML attributes
14999      * containing URLs that need to be resolved relative to the feed
15000      *
15001      * @access public
15002      * @since 1.0
15003      * @param array $element_attribute Element/attribute key/value pairs
15004      */
15005     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'))
15006     {
15007         $this->replace_url_attributes = (array) $element_attribute;
15008     }
15009
15010     function sanitize($data, $type, $base = '')
15011     {
15012         $data = trim($data);
15013         if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
15014         {
15015             if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
15016             {
15017                 if (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\/[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data))
15018                 {
15019                     $type |= SIMPLEPIE_CONSTRUCT_HTML;
15020                 }
15021                 else
15022                 {
15023                     $type |= SIMPLEPIE_CONSTRUCT_TEXT;
15024                 }
15025             }
15026
15027             if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
15028             {
15029                 $data = base64_decode($data);
15030             }
15031
15032             if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
15033             {
15034                 if ($this->remove_div)
15035                 {
15036                     $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
15037                     $data = preg_replace('/<\/div>$/', '', $data);
15038                 }
15039                 else
15040                 {
15041                     $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
15042                 }
15043             }
15044
15045             if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
15046             {
15047                 // Strip comments
15048                 if ($this->strip_comments)
15049                 {
15050                     $data = SimplePie_Misc::strip_comments($data);
15051                 }
15052
15053                 // Strip out HTML tags and attributes that might cause various security problems.
15054                 // Based on recommendations by Mark Pilgrim at:
15055                 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
15056                 if ($this->strip_htmltags)
15057                 {
15058                     foreach ($this->strip_htmltags as $tag)
15059                     {
15060                         $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
15061                         while (preg_match($pcre, $data))
15062                         {
15063                             $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
15064                         }
15065                     }
15066                 }
15067
15068                 if ($this->strip_attributes)
15069                 {
15070                     foreach ($this->strip_attributes as $attrib)
15071                     {
15072                         $data = preg_replace('/(<[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*)' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . trim($attrib) . '(?:\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>/', '\1\2\3>', $data);
15073                     }
15074                 }
15075
15076                 // Replace relative URLs
15077                 $this->base = $base;
15078                 foreach ($this->replace_url_attributes as $element => $attributes)
15079                 {
15080                     $data = $this->replace_urls($data, $element, $attributes);
15081                 }
15082
15083                 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
15084                 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
15085                 {
15086                     $images = SimplePie_Misc::get_element('img', $data);
15087                     foreach ($images as $img)
15088                     {
15089                         if (isset($img['attribs']['src']['data']))
15090                         {
15091                             $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
15092                             $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
15093
15094                             if ($cache->load())
15095                             {
15096                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15097                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15098                             }
15099                             else
15100                             {
f64c86 15101                                 $file = new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
fd9ef2 15102                                 $headers = $file->headers;
T 15103
15104                                 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
15105                                 {
15106                                     if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
15107                                     {
15108                                         $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15109                                         $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15110                                     }
15111                                     else
15112                                     {
15113                                         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);
15114                                     }
15115                                 }
15116                             }
15117                         }
15118                     }
15119                 }
15120
15121                 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
15122                 $data = trim($data);
15123             }
15124
15125             if ($type & SIMPLEPIE_CONSTRUCT_IRI)
15126             {
15127                 $data = SimplePie_Misc::absolutize_url($data, $base);
15128             }
15129
15130             if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
15131             {
15132                 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
15133             }
15134
15135             if ($this->output_encoding !== 'UTF-8')
15136             {
15137                 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
15138             }
15139         }
15140         return $data;
15141     }
15142
15143     function replace_urls($data, $tag, $attributes)
15144     {
15145         if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
15146         {
15147             $elements = SimplePie_Misc::get_element($tag, $data);
15148             foreach ($elements as $element)
15149             {
15150                 if (is_array($attributes))
15151                 {
15152                     foreach ($attributes as $attribute)
15153                     {
15154                         if (isset($element['attribs'][$attribute]['data']))
15155                         {
15156                             $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
15157                             $new_element = SimplePie_Misc::element_implode($element);
15158                             $data = str_replace($element['full'], $new_element, $data);
15159                             $element['full'] = $new_element;
15160                         }
15161                     }
15162                 }
15163                 elseif (isset($element['attribs'][$attributes]['data']))
15164                 {
15165                     $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
15166                     $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
15167                 }
15168             }
15169         }
15170         return $data;
15171     }
15172
15173     function do_strip_htmltags($match)
15174     {
15175         if ($this->encode_instead_of_strip)
15176         {
15177             if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15178             {
15179                 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
15180                 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
15181                 return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
15182             }
15183             else
15184             {
15185                 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
15186             }
15187         }
15188         elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15189         {
15190             return $match[4];
15191         }
15192         else
15193         {
15194             return '';
15195         }
15196     }
b1a6a5 15197
fd9ef2 15198 }
T 15199
15200 ?>