]> git.wh0rd.org - tt-rss.git/blob - lib/simplepie/simplepie.inc
remove twitter-specific code
[tt-rss.git] / lib / simplepie / simplepie.inc
1 <?php
2 /**
3 * SimplePie
4 *
5 * A PHP-Based RSS and Atom Feed Framework.
6 * Takes the hard work out of managing a complete RSS/Atom solution.
7 *
8 * Copyright (c) 2004-2011, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without modification, are
12 * permitted provided that the following conditions are met:
13 *
14 * * Redistributions of source code must retain the above copyright notice, this list of
15 * conditions and the following disclaimer.
16 *
17 * * Redistributions in binary form must reproduce the above copyright notice, this list
18 * of conditions and the following disclaimer in the documentation and/or other materials
19 * provided with the distribution.
20 *
21 * * Neither the name of the SimplePie Team nor the names of its contributors may be used
22 * to endorse or promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28 * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 * @package SimplePie
36 * @version 1.2.1
37 * @copyright 2004-2011 Ryan Parman, Geoffrey Sneddon, Ryan McCue
38 * @author Ryan Parman
39 * @author Geoffrey Sneddon
40 * @author Ryan McCue
41 * @link http://simplepie.org/ SimplePie
42 * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
43 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
44 * @todo phpDoc comments
45 */
46
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 */
60 define('SIMPLEPIE_BUILD', '20111015034325');
61
62 /**
63 * SimplePie Website URL
64 */
65 define('SIMPLEPIE_URL', 'http://simplepie.org');
66
67 /**
68 * SimplePie Useragent
69 * @see SimplePie::set_useragent()
70 */
71 define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
72
73 /**
74 * SimplePie Linkback
75 */
76 define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
77
78 /**
79 * No Autodiscovery
80 * @see SimplePie::set_autodiscovery_level()
81 */
82 define('SIMPLEPIE_LOCATOR_NONE', 0);
83
84 /**
85 * Feed Link Element Autodiscovery
86 * @see SimplePie::set_autodiscovery_level()
87 */
88 define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
89
90 /**
91 * Local Feed Extension Autodiscovery
92 * @see SimplePie::set_autodiscovery_level()
93 */
94 define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
95
96 /**
97 * Local Feed Body Autodiscovery
98 * @see SimplePie::set_autodiscovery_level()
99 */
100 define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
101
102 /**
103 * Remote Feed Extension Autodiscovery
104 * @see SimplePie::set_autodiscovery_level()
105 */
106 define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
107
108 /**
109 * Remote Feed Body Autodiscovery
110 * @see SimplePie::set_autodiscovery_level()
111 */
112 define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
113
114 /**
115 * All Feed Autodiscovery
116 * @see SimplePie::set_autodiscovery_level()
117 */
118 define('SIMPLEPIE_LOCATOR_ALL', 31);
119
120 /**
121 * No known feed type
122 */
123 define('SIMPLEPIE_TYPE_NONE', 0);
124
125 /**
126 * RSS 0.90
127 */
128 define('SIMPLEPIE_TYPE_RSS_090', 1);
129
130 /**
131 * RSS 0.91 (Netscape)
132 */
133 define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
134
135 /**
136 * RSS 0.91 (Userland)
137 */
138 define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
139
140 /**
141 * RSS 0.91 (both Netscape and Userland)
142 */
143 define('SIMPLEPIE_TYPE_RSS_091', 6);
144
145 /**
146 * RSS 0.92
147 */
148 define('SIMPLEPIE_TYPE_RSS_092', 8);
149
150 /**
151 * RSS 0.93
152 */
153 define('SIMPLEPIE_TYPE_RSS_093', 16);
154
155 /**
156 * RSS 0.94
157 */
158 define('SIMPLEPIE_TYPE_RSS_094', 32);
159
160 /**
161 * RSS 1.0
162 */
163 define('SIMPLEPIE_TYPE_RSS_10', 64);
164
165 /**
166 * RSS 2.0
167 */
168 define('SIMPLEPIE_TYPE_RSS_20', 128);
169
170 /**
171 * RDF-based RSS
172 */
173 define('SIMPLEPIE_TYPE_RSS_RDF', 65);
174
175 /**
176 * Non-RDF-based RSS (truly intended as syndication format)
177 */
178 define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
179
180 /**
181 * All RSS
182 */
183 define('SIMPLEPIE_TYPE_RSS_ALL', 255);
184
185 /**
186 * Atom 0.3
187 */
188 define('SIMPLEPIE_TYPE_ATOM_03', 256);
189
190 /**
191 * Atom 1.0
192 */
193 define('SIMPLEPIE_TYPE_ATOM_10', 512);
194
195 /**
196 * All Atom
197 */
198 define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
199
200 /**
201 * All feed types
202 */
203 define('SIMPLEPIE_TYPE_ALL', 1023);
204
205 /**
206 * No construct
207 */
208 define('SIMPLEPIE_CONSTRUCT_NONE', 0);
209
210 /**
211 * Text construct
212 */
213 define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
214
215 /**
216 * HTML construct
217 */
218 define('SIMPLEPIE_CONSTRUCT_HTML', 2);
219
220 /**
221 * XHTML construct
222 */
223 define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
224
225 /**
226 * base64-encoded construct
227 */
228 define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
229
230 /**
231 * IRI construct
232 */
233 define('SIMPLEPIE_CONSTRUCT_IRI', 16);
234
235 /**
236 * A construct that might be HTML
237 */
238 define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
239
240 /**
241 * All constructs
242 */
243 define('SIMPLEPIE_CONSTRUCT_ALL', 63);
244
245 /**
246 * Don't change case
247 */
248 define('SIMPLEPIE_SAME_CASE', 1);
249
250 /**
251 * Change to lowercase
252 */
253 define('SIMPLEPIE_LOWERCASE', 2);
254
255 /**
256 * Change to uppercase
257 */
258 define('SIMPLEPIE_UPPERCASE', 4);
259
260 /**
261 * PCRE for HTML attributes
262 */
263 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]*');
264
265 /**
266 * PCRE for XML attributes
267 */
268 define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
269
270 /**
271 * XML Namespace
272 */
273 define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
274
275 /**
276 * Atom 1.0 Namespace
277 */
278 define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
279
280 /**
281 * Atom 0.3 Namespace
282 */
283 define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
284
285 /**
286 * RDF Namespace
287 */
288 define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
289
290 /**
291 * RSS 0.90 Namespace
292 */
293 define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
294
295 /**
296 * RSS 1.0 Namespace
297 */
298 define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
299
300 /**
301 * RSS 1.0 Content Module Namespace
302 */
303 define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
304
305 /**
306 * RSS 2.0 Namespace
307 * (Stupid, I know, but I'm certain it will confuse people less with support.)
308 */
309 define('SIMPLEPIE_NAMESPACE_RSS_20', '');
310
311 /**
312 * DC 1.0 Namespace
313 */
314 define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
315
316 /**
317 * DC 1.1 Namespace
318 */
319 define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
320
321 /**
322 * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
323 */
324 define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
325
326 /**
327 * GeoRSS Namespace
328 */
329 define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
330
331 /**
332 * Media RSS Namespace
333 */
334 define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
335
336 /**
337 * Wrong Media RSS Namespace
338 */
339 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
340
341 /**
342 * iTunes RSS Namespace
343 */
344 define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
345
346 /**
347 * XHTML Namespace
348 */
349 define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
350
351 /**
352 * IANA Link Relations Registry
353 */
354 define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
355
356 /**
357 * Whether we're running on PHP5
358 */
359 define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
360
361 /**
362 * No file source
363 */
364 define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
365
366 /**
367 * Remote file source
368 */
369 define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
370
371 /**
372 * Local file source
373 */
374 define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
375
376 /**
377 * fsockopen() file source
378 */
379 define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
380
381 /**
382 * cURL file source
383 */
384 define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
385
386 /**
387 * file_get_contents() file source
388 */
389 define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
390
391 /**
392 * SimplePie
393 *
394 * @package SimplePie
395 */
396 class SimplePie
397 {
398 /**
399 * @var array Raw data
400 * @access private
401 */
402 var $data = array();
403
404 /**
405 * @var mixed Error string
406 * @access private
407 */
408 var $error;
409
410 /**
411 * @var object Instance of SimplePie_Sanitize (or other class)
412 * @see SimplePie::set_sanitize_class()
413 * @access private
414 */
415 var $sanitize;
416
417 /**
418 * @var string SimplePie Useragent
419 * @see SimplePie::set_useragent()
420 * @access private
421 */
422 var $useragent = SIMPLEPIE_USERAGENT;
423
424 /**
425 * @var string Feed URL
426 * @see SimplePie::set_feed_url()
427 * @access private
428 */
429 var $feed_url;
430
431 /**
432 * @var object Instance of SimplePie_File to use as a feed
433 * @see SimplePie::set_file()
434 * @access private
435 */
436 var $file;
437
438 /**
439 * @var string Raw feed data
440 * @see SimplePie::set_raw_data()
441 * @access private
442 */
443 var $raw_data;
444
445 /**
446 * @var int Timeout for fetching remote files
447 * @see SimplePie::set_timeout()
448 * @access private
449 */
450 var $timeout = 10;
451
452 /**
453 * @var bool Forces fsockopen() to be used for remote files instead
454 * of cURL, even if a new enough version is installed
455 * @see SimplePie::force_fsockopen()
456 * @access private
457 */
458 var $force_fsockopen = false;
459
460 /**
461 * @var bool Force the given data/URL to be treated as a feed no matter what
462 * it appears like
463 * @see SimplePie::force_feed()
464 * @access private
465 */
466 var $force_feed = false;
467
468 /**
469 * @var bool Enable/Disable XML dump
470 * @see SimplePie::enable_xml_dump()
471 * @access private
472 */
473 var $xml_dump = false;
474
475 /**
476 * @var bool Enable/Disable Caching
477 * @see SimplePie::enable_cache()
478 * @access private
479 */
480 var $cache = true;
481
482 /**
483 * @var int Cache duration (in seconds)
484 * @see SimplePie::set_cache_duration()
485 * @access private
486 */
487 var $cache_duration = 3600;
488
489 /**
490 * @var int Auto-discovery cache duration (in seconds)
491 * @see SimplePie::set_autodiscovery_cache_duration()
492 * @access private
493 */
494 var $autodiscovery_cache_duration = 604800; // 7 Days.
495
496 /**
497 * @var string Cache location (relative to executing script)
498 * @see SimplePie::set_cache_location()
499 * @access private
500 */
501 var $cache_location = './cache';
502
503 /**
504 * @var string Function that creates the cache filename
505 * @see SimplePie::set_cache_name_function()
506 * @access private
507 */
508 var $cache_name_function = 'md5';
509
510 /**
511 * @var bool Reorder feed by date descending
512 * @see SimplePie::enable_order_by_date()
513 * @access private
514 */
515 var $order_by_date = true;
516
517 /**
518 * @var mixed Force input encoding to be set to the follow value
519 * (false, or anything type-cast to false, disables this feature)
520 * @see SimplePie::set_input_encoding()
521 * @access private
522 */
523 var $input_encoding = false;
524
525 /**
526 * @var int Feed Autodiscovery Level
527 * @see SimplePie::set_autodiscovery_level()
528 * @access private
529 */
530 var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
531
532 /**
533 * @var string Class used for caching feeds
534 * @see SimplePie::set_cache_class()
535 * @access private
536 */
537 var $cache_class = 'SimplePie_Cache';
538
539 /**
540 * @var string Class used for locating feeds
541 * @see SimplePie::set_locator_class()
542 * @access private
543 */
544 var $locator_class = 'SimplePie_Locator';
545
546 /**
547 * @var string Class used for parsing feeds
548 * @see SimplePie::set_parser_class()
549 * @access private
550 */
551 var $parser_class = 'SimplePie_Parser';
552
553 /**
554 * @var string Class used for fetching feeds
555 * @see SimplePie::set_file_class()
556 * @access private
557 */
558 var $file_class = 'SimplePie_File';
559
560 /**
561 * @var string Class used for items
562 * @see SimplePie::set_item_class()
563 * @access private
564 */
565 var $item_class = 'SimplePie_Item';
566
567 /**
568 * @var string Class used for authors
569 * @see SimplePie::set_author_class()
570 * @access private
571 */
572 var $author_class = 'SimplePie_Author';
573
574 /**
575 * @var string Class used for categories
576 * @see SimplePie::set_category_class()
577 * @access private
578 */
579 var $category_class = 'SimplePie_Category';
580
581 /**
582 * @var string Class used for enclosures
583 * @see SimplePie::set_enclosures_class()
584 * @access private
585 */
586 var $enclosure_class = 'SimplePie_Enclosure';
587
588 /**
589 * @var string Class used for Media RSS <media:text> captions
590 * @see SimplePie::set_caption_class()
591 * @access private
592 */
593 var $caption_class = 'SimplePie_Caption';
594
595 /**
596 * @var string Class used for Media RSS <media:copyright>
597 * @see SimplePie::set_copyright_class()
598 * @access private
599 */
600 var $copyright_class = 'SimplePie_Copyright';
601
602 /**
603 * @var string Class used for Media RSS <media:credit>
604 * @see SimplePie::set_credit_class()
605 * @access private
606 */
607 var $credit_class = 'SimplePie_Credit';
608
609 /**
610 * @var string Class used for Media RSS <media:rating>
611 * @see SimplePie::set_rating_class()
612 * @access private
613 */
614 var $rating_class = 'SimplePie_Rating';
615
616 /**
617 * @var string Class used for Media RSS <media:restriction>
618 * @see SimplePie::set_restriction_class()
619 * @access private
620 */
621 var $restriction_class = 'SimplePie_Restriction';
622
623 /**
624 * @var string Class used for content-type sniffing
625 * @see SimplePie::set_content_type_sniffer_class()
626 * @access private
627 */
628 var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
629
630 /**
631 * @var string Class used for item sources.
632 * @see SimplePie::set_source_class()
633 * @access private
634 */
635 var $source_class = 'SimplePie_Source';
636
637 /**
638 * @var mixed Set javascript query string parameter (false, or
639 * anything type-cast to false, disables this feature)
640 * @see SimplePie::set_javascript()
641 * @access private
642 */
643 var $javascript = 'js';
644
645 /**
646 * @var int Maximum number of feeds to check with autodiscovery
647 * @see SimplePie::set_max_checked_feeds()
648 * @access private
649 */
650 var $max_checked_feeds = 10;
651
652 /**
653 * @var array All the feeds found during the autodiscovery process
654 * @see SimplePie::get_all_discovered_feeds()
655 * @access private
656 */
657 var $all_discovered_feeds = array();
658
659 /**
660 * @var string Web-accessible path to the handler_favicon.php file.
661 * @see SimplePie::set_favicon_handler()
662 * @access private
663 */
664 var $favicon_handler = '';
665
666 /**
667 * @var string Web-accessible path to the handler_image.php file.
668 * @see SimplePie::set_image_handler()
669 * @access private
670 */
671 var $image_handler = '';
672
673 /**
674 * @var array Stores the URLs when multiple feeds are being initialized.
675 * @see SimplePie::set_feed_url()
676 * @access private
677 */
678 var $multifeed_url = array();
679
680 /**
681 * @var array Stores SimplePie objects when multiple feeds initialized.
682 * @access private
683 */
684 var $multifeed_objects = array();
685
686 /**
687 * @var array Stores the get_object_vars() array for use with multifeeds.
688 * @see SimplePie::set_feed_url()
689 * @access private
690 */
691 var $config_settings = null;
692
693 /**
694 * @var integer Stores the number of items to return per-feed with multifeeds.
695 * @see SimplePie::set_item_limit()
696 * @access private
697 */
698 var $item_limit = 0;
699
700 /**
701 * @var array Stores the default attributes to be stripped by strip_attributes().
702 * @see SimplePie::strip_attributes()
703 * @access private
704 */
705 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
706
707 /**
708 * @var array Stores the default tags to be stripped by strip_htmltags().
709 * @see SimplePie::strip_htmltags()
710 * @access private
711 */
712 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
713
714 /**
715 * The SimplePie class contains feed level data and options
716 *
717 * There are two ways that you can create a new SimplePie object. The first
718 * is by passing a feed URL as a parameter to the SimplePie constructor
719 * (as well as optionally setting the cache location and cache expiry). This
720 * will initialise the whole feed with all of the default settings, and you
721 * can begin accessing methods and properties immediately.
722 *
723 * The second way is to create the SimplePie object with no parameters
724 * at all. This will enable you to set configuration options. After setting
725 * them, you must initialise the feed using $feed->init(). At that point the
726 * object's methods and properties will be available to you. This format is
727 * what is used throughout this documentation.
728 *
729 * @access public
730 * @since 1.0 Preview Release
731 * @param string $feed_url This is the URL you want to parse.
732 * @param string $cache_location This is where you want the cache to be stored.
733 * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
734 */
735 function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
736 {
737 // Other objects, instances created here so we can set options on them
738 $this->sanitize =& new SimplePie_Sanitize;
739
740 // Set options if they're passed to the constructor
741 if ($cache_location !== null)
742 {
743 $this->set_cache_location($cache_location);
744 }
745
746 if ($cache_duration !== null)
747 {
748 $this->set_cache_duration($cache_duration);
749 }
750
751 // Only init the script if we're passed a feed URL
752 if ($feed_url !== null)
753 {
754 $this->set_feed_url($feed_url);
755 $this->init();
756 }
757 }
758
759 /**
760 * Used for converting object to a string
761 */
762 function __toString()
763 {
764 return md5(serialize($this->data));
765 }
766
767 /**
768 * Remove items that link back to this before destroying this object
769 */
770 function __destruct()
771 {
772 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
773 {
774 if (!empty($this->data['items']))
775 {
776 foreach ($this->data['items'] as $item)
777 {
778 $item->__destruct();
779 }
780 unset($item, $this->data['items']);
781 }
782 if (!empty($this->data['ordered_items']))
783 {
784 foreach ($this->data['ordered_items'] as $item)
785 {
786 $item->__destruct();
787 }
788 unset($item, $this->data['ordered_items']);
789 }
790 }
791 }
792
793 /**
794 * Force the given data/URL to be treated as a feed no matter what it
795 * appears like
796 *
797 * @access public
798 * @since 1.1
799 * @param bool $enable Force the given data/URL to be treated as a feed
800 */
801 function force_feed($enable = false)
802 {
803 $this->force_feed = (bool) $enable;
804 }
805
806 /**
807 * This is the URL of the feed you want to parse.
808 *
809 * This allows you to enter the URL of the feed you want to parse, or the
810 * website you want to try to use auto-discovery on. This takes priority
811 * over any set raw data.
812 *
813 * You can set multiple feeds to mash together by passing an array instead
814 * of a string for the $url. Remember that with each additional feed comes
815 * additional processing and resources.
816 *
817 * @access public
818 * @since 1.0 Preview Release
819 * @param mixed $url This is the URL (or array of URLs) that you want to parse.
820 * @see SimplePie::set_raw_data()
821 */
822 function set_feed_url($url)
823 {
824 if (is_array($url))
825 {
826 $this->multifeed_url = array();
827 foreach ($url as $value)
828 {
829 $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
830 }
831 }
832 else
833 {
834 $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
835 }
836 }
837
838 /**
839 * Provides an instance of SimplePie_File to use as a feed
840 *
841 * @access public
842 * @param object &$file Instance of SimplePie_File (or subclass)
843 * @return bool True on success, false on failure
844 */
845 function set_file(&$file)
846 {
847 if (is_a($file, 'SimplePie_File'))
848 {
849 $this->feed_url = $file->url;
850 $this->file =& $file;
851 return true;
852 }
853 return false;
854 }
855
856 /**
857 * Allows you to use a string of RSS/Atom data instead of a remote feed.
858 *
859 * If you have a feed available as a string in PHP, you can tell SimplePie
860 * to parse that data string instead of a remote feed. Any set feed URL
861 * takes precedence.
862 *
863 * @access public
864 * @since 1.0 Beta 3
865 * @param string $data RSS or Atom data as a string.
866 * @see SimplePie::set_feed_url()
867 */
868 function set_raw_data($data)
869 {
870 $this->raw_data = $data;
871 }
872
873 /**
874 * Allows you to override the default timeout for fetching remote feeds.
875 *
876 * This allows you to change the maximum time the feed's server to respond
877 * and send the feed back.
878 *
879 * @access public
880 * @since 1.0 Beta 3
881 * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
882 */
883 function set_timeout($timeout = 10)
884 {
885 $this->timeout = (int) $timeout;
886 }
887
888 /**
889 * Forces SimplePie to use fsockopen() instead of the preferred cURL
890 * functions.
891 *
892 * @access public
893 * @since 1.0 Beta 3
894 * @param bool $enable Force fsockopen() to be used
895 */
896 function force_fsockopen($enable = false)
897 {
898 $this->force_fsockopen = (bool) $enable;
899 }
900
901 /**
902 * Outputs the raw XML content of the feed, after it has gone through
903 * SimplePie's filters.
904 *
905 * Used only for debugging, this function will output the XML content as
906 * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
907 * before trying to parse it. Many parts of the feed are re-written in
908 * memory, and in the end, you have a parsable feed. XML dump shows you the
909 * actual XML that SimplePie tries to parse, which may or may not be very
910 * different from the original feed.
911 *
912 * @access public
913 * @since 1.0 Preview Release
914 * @param bool $enable Enable XML dump
915 */
916 function enable_xml_dump($enable = false)
917 {
918 $this->xml_dump = (bool) $enable;
919 }
920
921 /**
922 * Enables/disables caching in SimplePie.
923 *
924 * This option allows you to disable caching all-together in SimplePie.
925 * However, disabling the cache can lead to longer load times.
926 *
927 * @access public
928 * @since 1.0 Preview Release
929 * @param bool $enable Enable caching
930 */
931 function enable_cache($enable = true)
932 {
933 $this->cache = (bool) $enable;
934 }
935
936 /**
937 * Set the length of time (in seconds) that the contents of a feed
938 * will be cached.
939 *
940 * @access public
941 * @param int $seconds The feed content cache duration.
942 */
943 function set_cache_duration($seconds = 3600)
944 {
945 $this->cache_duration = (int) $seconds;
946 }
947
948 /**
949 * Set the length of time (in seconds) that the autodiscovered feed
950 * URL will be cached.
951 *
952 * @access public
953 * @param int $seconds The autodiscovered feed URL cache duration.
954 */
955 function set_autodiscovery_cache_duration($seconds = 604800)
956 {
957 $this->autodiscovery_cache_duration = (int) $seconds;
958 }
959
960 /**
961 * Set the file system location where the cached files should be stored.
962 *
963 * @access public
964 * @param string $location The file system location.
965 */
966 function set_cache_location($location = './cache')
967 {
968 $this->cache_location = (string) $location;
969 }
970
971 /**
972 * Determines whether feed items should be sorted into reverse chronological order.
973 *
974 * @access public
975 * @param bool $enable Sort as reverse chronological order.
976 */
977 function enable_order_by_date($enable = true)
978 {
979 $this->order_by_date = (bool) $enable;
980 }
981
982 /**
983 * Allows you to override the character encoding reported by the feed.
984 *
985 * @access public
986 * @param string $encoding Character encoding.
987 */
988 function set_input_encoding($encoding = false)
989 {
990 if ($encoding)
991 {
992 $this->input_encoding = (string) $encoding;
993 }
994 else
995 {
996 $this->input_encoding = false;
997 }
998 }
999
1000 /**
1001 * Set how much feed autodiscovery to do
1002 *
1003 * @access public
1004 * @see SIMPLEPIE_LOCATOR_NONE
1005 * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
1006 * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
1007 * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
1008 * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
1009 * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
1010 * @see SIMPLEPIE_LOCATOR_ALL
1011 * @param int $level Feed Autodiscovery Level (level can be a
1012 * combination of the above constants, see bitwise OR operator)
1013 */
1014 function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
1015 {
1016 $this->autodiscovery = (int) $level;
1017 }
1018
1019 /**
1020 * Allows you to change which class SimplePie uses for caching.
1021 * Useful when you are overloading or extending SimplePie's default classes.
1022 *
1023 * @access public
1024 * @param string $class Name of custom class.
1025 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1026 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1027 */
1028 function set_cache_class($class = 'SimplePie_Cache')
1029 {
1030 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
1031 {
1032 $this->cache_class = $class;
1033 return true;
1034 }
1035 return false;
1036 }
1037
1038 /**
1039 * Allows you to change which class SimplePie uses for auto-discovery.
1040 * Useful when you are overloading or extending SimplePie's default classes.
1041 *
1042 * @access public
1043 * @param string $class Name of custom class.
1044 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1045 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1046 */
1047 function set_locator_class($class = 'SimplePie_Locator')
1048 {
1049 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
1050 {
1051 $this->locator_class = $class;
1052 return true;
1053 }
1054 return false;
1055 }
1056
1057 /**
1058 * Allows you to change which class SimplePie uses for XML parsing.
1059 * Useful when you are overloading or extending SimplePie's default classes.
1060 *
1061 * @access public
1062 * @param string $class Name of custom class.
1063 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1064 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1065 */
1066 function set_parser_class($class = 'SimplePie_Parser')
1067 {
1068 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
1069 {
1070 $this->parser_class = $class;
1071 return true;
1072 }
1073 return false;
1074 }
1075
1076 /**
1077 * Allows you to change which class SimplePie uses for remote file fetching.
1078 * Useful when you are overloading or extending SimplePie's default classes.
1079 *
1080 * @access public
1081 * @param string $class Name of custom class.
1082 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1083 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1084 */
1085 function set_file_class($class = 'SimplePie_File')
1086 {
1087 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
1088 {
1089 $this->file_class = $class;
1090 return true;
1091 }
1092 return false;
1093 }
1094
1095 /**
1096 * Allows you to change which class SimplePie uses for data sanitization.
1097 * Useful when you are overloading or extending SimplePie's default classes.
1098 *
1099 * @access public
1100 * @param string $class Name of custom class.
1101 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1102 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1103 */
1104 function set_sanitize_class($class = 'SimplePie_Sanitize')
1105 {
1106 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
1107 {
1108 $this->sanitize =& new $class;
1109 return true;
1110 }
1111 return false;
1112 }
1113
1114 /**
1115 * Allows you to change which class SimplePie uses for handling feed items.
1116 * Useful when you are overloading or extending SimplePie's default classes.
1117 *
1118 * @access public
1119 * @param string $class Name of custom class.
1120 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1121 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1122 */
1123 function set_item_class($class = 'SimplePie_Item')
1124 {
1125 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
1126 {
1127 $this->item_class = $class;
1128 return true;
1129 }
1130 return false;
1131 }
1132
1133 /**
1134 * Allows you to change which class SimplePie uses for handling author data.
1135 * Useful when you are overloading or extending SimplePie's default classes.
1136 *
1137 * @access public
1138 * @param string $class Name of custom class.
1139 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1140 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1141 */
1142 function set_author_class($class = 'SimplePie_Author')
1143 {
1144 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
1145 {
1146 $this->author_class = $class;
1147 return true;
1148 }
1149 return false;
1150 }
1151
1152 /**
1153 * Allows you to change which class SimplePie uses for handling category data.
1154 * Useful when you are overloading or extending SimplePie's default classes.
1155 *
1156 * @access public
1157 * @param string $class Name of custom class.
1158 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1159 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1160 */
1161 function set_category_class($class = 'SimplePie_Category')
1162 {
1163 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
1164 {
1165 $this->category_class = $class;
1166 return true;
1167 }
1168 return false;
1169 }
1170
1171 /**
1172 * Allows you to change which class SimplePie uses for feed enclosures.
1173 * Useful when you are overloading or extending SimplePie's default classes.
1174 *
1175 * @access public
1176 * @param string $class Name of custom class.
1177 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1178 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1179 */
1180 function set_enclosure_class($class = 'SimplePie_Enclosure')
1181 {
1182 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
1183 {
1184 $this->enclosure_class = $class;
1185 return true;
1186 }
1187 return false;
1188 }
1189
1190 /**
1191 * Allows you to change which class SimplePie uses for <media:text> captions
1192 * Useful when you are overloading or extending SimplePie's default classes.
1193 *
1194 * @access public
1195 * @param string $class Name of custom class.
1196 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1197 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1198 */
1199 function set_caption_class($class = 'SimplePie_Caption')
1200 {
1201 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
1202 {
1203 $this->caption_class = $class;
1204 return true;
1205 }
1206 return false;
1207 }
1208
1209 /**
1210 * Allows you to change which class SimplePie uses for <media:copyright>
1211 * Useful when you are overloading or extending SimplePie's default classes.
1212 *
1213 * @access public
1214 * @param string $class Name of custom class.
1215 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1216 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1217 */
1218 function set_copyright_class($class = 'SimplePie_Copyright')
1219 {
1220 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
1221 {
1222 $this->copyright_class = $class;
1223 return true;
1224 }
1225 return false;
1226 }
1227
1228 /**
1229 * Allows you to change which class SimplePie uses for <media:credit>
1230 * Useful when you are overloading or extending SimplePie's default classes.
1231 *
1232 * @access public
1233 * @param string $class Name of custom class.
1234 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1235 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1236 */
1237 function set_credit_class($class = 'SimplePie_Credit')
1238 {
1239 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
1240 {
1241 $this->credit_class = $class;
1242 return true;
1243 }
1244 return false;
1245 }
1246
1247 /**
1248 * Allows you to change which class SimplePie uses for <media:rating>
1249 * Useful when you are overloading or extending SimplePie's default classes.
1250 *
1251 * @access public
1252 * @param string $class Name of custom class.
1253 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1254 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1255 */
1256 function set_rating_class($class = 'SimplePie_Rating')
1257 {
1258 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
1259 {
1260 $this->rating_class = $class;
1261 return true;
1262 }
1263 return false;
1264 }
1265
1266 /**
1267 * Allows you to change which class SimplePie uses for <media:restriction>
1268 * Useful when you are overloading or extending SimplePie's default classes.
1269 *
1270 * @access public
1271 * @param string $class Name of custom class.
1272 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1273 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1274 */
1275 function set_restriction_class($class = 'SimplePie_Restriction')
1276 {
1277 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
1278 {
1279 $this->restriction_class = $class;
1280 return true;
1281 }
1282 return false;
1283 }
1284
1285 /**
1286 * Allows you to change which class SimplePie uses for content-type sniffing.
1287 * Useful when you are overloading or extending SimplePie's default classes.
1288 *
1289 * @access public
1290 * @param string $class Name of custom class.
1291 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1292 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1293 */
1294 function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1295 {
1296 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
1297 {
1298 $this->content_type_sniffer_class = $class;
1299 return true;
1300 }
1301 return false;
1302 }
1303
1304 /**
1305 * Allows you to change which class SimplePie uses item sources.
1306 * Useful when you are overloading or extending SimplePie's default classes.
1307 *
1308 * @access public
1309 * @param string $class Name of custom class.
1310 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1311 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1312 */
1313 function set_source_class($class = 'SimplePie_Source')
1314 {
1315 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
1316 {
1317 $this->source_class = $class;
1318 return true;
1319 }
1320 return false;
1321 }
1322
1323 /**
1324 * Allows you to override the default user agent string.
1325 *
1326 * @access public
1327 * @param string $ua New user agent string.
1328 */
1329 function set_useragent($ua = SIMPLEPIE_USERAGENT)
1330 {
1331 $this->useragent = (string) $ua;
1332 }
1333
1334 /**
1335 * Set callback function to create cache filename with
1336 *
1337 * @access public
1338 * @param mixed $function Callback function
1339 */
1340 function set_cache_name_function($function = 'md5')
1341 {
1342 if (is_callable($function))
1343 {
1344 $this->cache_name_function = $function;
1345 }
1346 }
1347
1348 /**
1349 * Set javascript query string parameter
1350 *
1351 * @access public
1352 * @param mixed $get Javascript query string parameter
1353 */
1354 function set_javascript($get = 'js')
1355 {
1356 if ($get)
1357 {
1358 $this->javascript = (string) $get;
1359 }
1360 else
1361 {
1362 $this->javascript = false;
1363 }
1364 }
1365
1366 /**
1367 * Set options to make SP as fast as possible. Forgoes a
1368 * substantial amount of data sanitization in favor of speed.
1369 *
1370 * @access public
1371 * @param bool $set Whether to set them or not
1372 */
1373 function set_stupidly_fast($set = false)
1374 {
1375 if ($set)
1376 {
1377 $this->enable_order_by_date(false);
1378 $this->remove_div(false);
1379 $this->strip_comments(false);
1380 $this->strip_htmltags(false);
1381 $this->strip_attributes(false);
1382 $this->set_image_handler(false);
1383 }
1384 }
1385
1386 /**
1387 * Set maximum number of feeds to check with autodiscovery
1388 *
1389 * @access public
1390 * @param int $max Maximum number of feeds to check
1391 */
1392 function set_max_checked_feeds($max = 10)
1393 {
1394 $this->max_checked_feeds = (int) $max;
1395 }
1396
1397 function remove_div($enable = true)
1398 {
1399 $this->sanitize->remove_div($enable);
1400 }
1401
1402 function strip_htmltags($tags = '', $encode = null)
1403 {
1404 if ($tags === '')
1405 {
1406 $tags = $this->strip_htmltags;
1407 }
1408 $this->sanitize->strip_htmltags($tags);
1409 if ($encode !== null)
1410 {
1411 $this->sanitize->encode_instead_of_strip($tags);
1412 }
1413 }
1414
1415 function encode_instead_of_strip($enable = true)
1416 {
1417 $this->sanitize->encode_instead_of_strip($enable);
1418 }
1419
1420 function strip_attributes($attribs = '')
1421 {
1422 if ($attribs === '')
1423 {
1424 $attribs = $this->strip_attributes;
1425 }
1426 $this->sanitize->strip_attributes($attribs);
1427 }
1428
1429 function set_output_encoding($encoding = 'UTF-8')
1430 {
1431 $this->sanitize->set_output_encoding($encoding);
1432 }
1433
1434 function strip_comments($strip = false)
1435 {
1436 $this->sanitize->strip_comments($strip);
1437 }
1438
1439 /**
1440 * Set element/attribute key/value pairs of HTML attributes
1441 * containing URLs that need to be resolved relative to the feed
1442 *
1443 * @access public
1444 * @since 1.0
1445 * @param array $element_attribute Element/attribute key/value pairs
1446 */
1447 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'))
1448 {
1449 $this->sanitize->set_url_replacements($element_attribute);
1450 }
1451
1452 /**
1453 * Set the handler to enable the display of cached favicons.
1454 *
1455 * @access public
1456 * @param str $page Web-accessible path to the handler_favicon.php file.
1457 * @param str $qs The query string that the value should be passed to.
1458 */
1459 function set_favicon_handler($page = false, $qs = 'i')
1460 {
1461 if ($page !== false)
1462 {
1463 $this->favicon_handler = $page . '?' . $qs . '=';
1464 }
1465 else
1466 {
1467 $this->favicon_handler = '';
1468 }
1469 }
1470
1471 /**
1472 * Set the handler to enable the display of cached images.
1473 *
1474 * @access public
1475 * @param str $page Web-accessible path to the handler_image.php file.
1476 * @param str $qs The query string that the value should be passed to.
1477 */
1478 function set_image_handler($page = false, $qs = 'i')
1479 {
1480 if ($page !== false)
1481 {
1482 $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1483 }
1484 else
1485 {
1486 $this->image_handler = '';
1487 }
1488 }
1489
1490 /**
1491 * Set the limit for items returned per-feed with multifeeds.
1492 *
1493 * @access public
1494 * @param integer $limit The maximum number of items to return.
1495 */
1496 function set_item_limit($limit = 0)
1497 {
1498 $this->item_limit = (int) $limit;
1499 }
1500
1501 function init()
1502 {
1503 // Check absolute bare minimum requirements.
1504 if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
1505 {
1506 return false;
1507 }
1508 // 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.
1509 elseif (!extension_loaded('xmlreader'))
1510 {
1511 static $xml_is_sane = null;
1512 if ($xml_is_sane === null)
1513 {
1514 $parser_check = xml_parser_create();
1515 xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
1516 xml_parser_free($parser_check);
1517 $xml_is_sane = isset($values[0]['value']);
1518 }
1519 if (!$xml_is_sane)
1520 {
1521 return false;
1522 }
1523 }
1524
1525 if (isset($_GET[$this->javascript]))
1526 {
1527 SimplePie_Misc::output_javascript();
1528 exit;
1529 }
1530
1531 // Pass whatever was set with config options over to the sanitizer.
1532 $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
1533 $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
1534
1535 if ($this->feed_url !== null || $this->raw_data !== null)
1536 {
1537 $this->data = array();
1538 $this->multifeed_objects = array();
1539 $cache = false;
1540
1541 if ($this->feed_url !== null)
1542 {
1543 $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
1544 // Decide whether to enable caching
1545 if ($this->cache && $parsed_feed_url['scheme'] !== '')
1546 {
1547 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
1548 }
1549 // If it's enabled and we don't want an XML dump, use the cache
1550 if ($cache && !$this->xml_dump)
1551 {
1552 // Load the Cache
1553 $this->data = $cache->load();
1554 if (!empty($this->data))
1555 {
1556 // If the cache is for an outdated build of SimplePie
1557 if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
1558 {
1559 $cache->unlink();
1560 $this->data = array();
1561 }
1562 // If we've hit a collision just rerun it with caching disabled
1563 elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
1564 {
1565 $cache = false;
1566 $this->data = array();
1567 }
1568 // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1569 elseif (isset($this->data['feed_url']))
1570 {
1571 // If the autodiscovery cache is still valid use it.
1572 if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1573 {
1574 // Do not need to do feed autodiscovery yet.
1575 if ($this->data['feed_url'] === $this->data['url'])
1576 {
1577 $cache->unlink();
1578 $this->data = array();
1579 }
1580 else
1581 {
1582 $this->set_feed_url($this->data['feed_url']);
1583 return $this->init();
1584 }
1585 }
1586 }
1587 // Check if the cache has been updated
1588 elseif ($cache->mtime() + $this->cache_duration < time())
1589 {
1590 // If we have last-modified and/or etag set
1591 if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1592 {
1593 $headers = array();
1594 if (isset($this->data['headers']['last-modified']))
1595 {
1596 $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1597 }
1598 if (isset($this->data['headers']['etag']))
1599 {
1600 $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
1601 }
1602 $file =& new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
1603 if ($file->success)
1604 {
1605 if ($file->status_code === 304)
1606 {
1607 $cache->touch();
1608 return true;
1609 }
1610 else
1611 {
1612 $headers = $file->headers;
1613 }
1614 }
1615 else
1616 {
1617 unset($file);
1618 }
1619 }
1620 }
1621 // If the cache is still valid, just return true
1622 else
1623 {
1624 return true;
1625 }
1626 }
1627 // If the cache is empty, delete it
1628 else
1629 {
1630 $cache->unlink();
1631 $this->data = array();
1632 }
1633 }
1634 // 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.
1635 if (!isset($file))
1636 {
1637 if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
1638 {
1639 $file =& $this->file;
1640 }
1641 else
1642 {
1643 $file =& new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
1644 }
1645 }
1646 // If the file connection has an error, set SimplePie::error to that and quit
1647 if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
1648 {
1649 $this->error = $file->error;
1650 if (!empty($this->data))
1651 {
1652 return true;
1653 }
1654 else
1655 {
1656 return false;
1657 }
1658 }
1659
1660 if (!$this->force_feed)
1661 {
1662 // Check if the supplied URL is a feed, if it isn't, look for it.
1663 $locate =& new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
1664 if (!$locate->is_feed($file))
1665 {
1666 // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1667 unset($file);
1668 if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
1669 {
1670 if ($cache)
1671 {
1672 $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1673 if (!$cache->save($this))
1674 {
1675 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);
1676 }
1677 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
1678 }
1679 $this->feed_url = $file->url;
1680 }
1681 else
1682 {
1683 $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.";
1684 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1685 return false;
1686 }
1687 }
1688 $locate = null;
1689 }
1690
1691 $headers = $file->headers;
1692 $data = $file->body;
1693 $sniffer =& new $this->content_type_sniffer_class($file);
1694 $sniffed = $sniffer->get_type();
1695 }
1696 else
1697 {
1698 $data = $this->raw_data;
1699 }
1700
1701 // Set up array of possible encodings
1702 $encodings = array();
1703
1704 // First check to see if input has been overridden.
1705 if ($this->input_encoding !== false)
1706 {
1707 $encodings[] = $this->input_encoding;
1708 }
1709
1710 $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1711 $text_types = array('text/xml', 'text/xml-external-parsed-entity');
1712
1713 // RFC 3023 (only applies to sniffed content)
1714 if (isset($sniffed))
1715 {
1716 if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1717 {
1718 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1719 {
1720 $encodings[] = strtoupper($charset[1]);
1721 }
1722 $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1723 $encodings[] = 'UTF-8';
1724 }
1725 elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1726 {
1727 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1728 {
1729 $encodings[] = $charset[1];
1730 }
1731 $encodings[] = 'US-ASCII';
1732 }
1733 // Text MIME-type default
1734 elseif (substr($sniffed, 0, 5) === 'text/')
1735 {
1736 $encodings[] = 'US-ASCII';
1737 }
1738 }
1739
1740 // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1741 $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1742 $encodings[] = 'UTF-8';
1743 $encodings[] = 'ISO-8859-1';
1744
1745 // There's no point in trying an encoding twice
1746 $encodings = array_unique($encodings);
1747
1748 // If we want the XML, just output that with the most likely encoding and quit
1749 if ($this->xml_dump)
1750 {
1751 header('Content-type: text/xml; charset=' . $encodings[0]);
1752 echo $data;
1753 exit;
1754 }
1755
1756 // Loop through each possible encoding, till we return something, or run out of possibilities
1757 foreach ($encodings as $encoding)
1758 {
1759 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1760 if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
1761 {
1762 // Create new parser
1763 $parser =& new $this->parser_class();
1764
1765 // If it's parsed fine
1766 if ($parser->parse($utf8_data, 'UTF-8'))
1767 {
1768 $this->data = $parser->get_data();
1769 if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
1770 {
1771 if (isset($headers))
1772 {
1773 $this->data['headers'] = $headers;
1774 }
1775 $this->data['build'] = SIMPLEPIE_BUILD;
1776
1777 // Cache the file if caching is enabled
1778 if ($cache && !$cache->save($this))
1779 {
1780 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);
1781 }
1782 return true;
1783 }
1784 else
1785 {
1786 $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
1787 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1788 return false;
1789 }
1790 }
1791 }
1792 }
1793 if (isset($parser))
1794 {
1795 // We have an error, just set SimplePie_Misc::error to it and quit
1796 $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());
1797 }
1798 else
1799 {
1800 $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.';
1801 }
1802 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1803 return false;
1804 }
1805 elseif (!empty($this->multifeed_url))
1806 {
1807 $i = 0;
1808 $success = 0;
1809 $this->multifeed_objects = array();
1810 foreach ($this->multifeed_url as $url)
1811 {
1812 if (SIMPLEPIE_PHP5)
1813 {
1814 // This keyword needs to defy coding standards for PHP4 compatibility
1815 $this->multifeed_objects[$i] = clone($this);
1816 }
1817 else
1818 {
1819 $this->multifeed_objects[$i] = $this;
1820 }
1821 $this->multifeed_objects[$i]->set_feed_url($url);
1822 $success |= $this->multifeed_objects[$i]->init();
1823 $i++;
1824 }
1825 return (bool) $success;
1826 }
1827 else
1828 {
1829 return false;
1830 }
1831 }
1832
1833 /**
1834 * Return the error message for the occured error
1835 *
1836 * @access public
1837 * @return string Error message
1838 */
1839 function error()
1840 {
1841 return $this->error;
1842 }
1843
1844 function get_encoding()
1845 {
1846 return $this->sanitize->output_encoding;
1847 }
1848
1849 function handle_content_type($mime = 'text/html')
1850 {
1851 if (!headers_sent())
1852 {
1853 $header = "Content-type: $mime;";
1854 if ($this->get_encoding())
1855 {
1856 $header .= ' charset=' . $this->get_encoding();
1857 }
1858 else
1859 {
1860 $header .= ' charset=UTF-8';
1861 }
1862 header($header);
1863 }
1864 }
1865
1866 function get_type()
1867 {
1868 if (!isset($this->data['type']))
1869 {
1870 $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1871 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1872 {
1873 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1874 }
1875 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1876 {
1877 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1878 }
1879 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1880 {
1881 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1882 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1883 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1884 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1885 {
1886 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1887 }
1888 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1889 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1890 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1891 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1892 {
1893 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1894 }
1895 }
1896 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
1897 {
1898 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1899 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1900 {
1901 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1902 {
1903 case '0.91':
1904 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1905 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1906 {
1907 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1908 {
1909 case '0':
1910 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1911 break;
1912
1913 case '24':
1914 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1915 break;
1916 }
1917 }
1918 break;
1919
1920 case '0.92':
1921 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1922 break;
1923
1924 case '0.93':
1925 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1926 break;
1927
1928 case '0.94':
1929 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1930 break;
1931
1932 case '2.0':
1933 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1934 break;
1935 }
1936 }
1937 }
1938 else
1939 {
1940 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1941 }
1942 }
1943 return $this->data['type'];
1944 }
1945
1946 /**
1947 * Returns the URL for the favicon of the feed's website.
1948 *
1949 * @todo Cache atom:icon
1950 * @access public
1951 * @since 1.0
1952 */
1953 function get_favicon()
1954 {
1955 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
1956 {
1957 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
1958 }
1959 elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
1960 {
1961 $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
1962
1963 if ($this->cache && $this->favicon_handler)
1964 {
1965 $favicon_filename = call_user_func($this->cache_name_function, $favicon);
1966 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
1967
1968 if ($cache->load())
1969 {
1970 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1971 }
1972 else
1973 {
1974 $file =& new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
1975
1976 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)
1977 {
1978 $sniffer =& new $this->content_type_sniffer_class($file);
1979 if (substr($sniffer->get_type(), 0, 6) === 'image/')
1980 {
1981 if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
1982 {
1983 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1984 }
1985 else
1986 {
1987 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);
1988 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
1989 }
1990 }
1991 // not an image
1992 else
1993 {
1994 return false;
1995 }
1996 }
1997 }
1998 }
1999 else
2000 {
2001 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
2002 }
2003 }
2004 return false;
2005 }
2006
2007 /**
2008 * @todo If we have a perm redirect we should return the new URL
2009 * @todo When we make the above change, let's support <itunes:new-feed-url> as well
2010 * @todo Also, |atom:link|@rel=self
2011 */
2012 function subscribe_url()
2013 {
2014 if ($this->feed_url !== null)
2015 {
2016 return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
2017 }
2018 else
2019 {
2020 return null;
2021 }
2022 }
2023
2024 function subscribe_feed()
2025 {
2026 if ($this->feed_url !== null)
2027 {
2028 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2029 }
2030 else
2031 {
2032 return null;
2033 }
2034 }
2035
2036 function subscribe_outlook()
2037 {
2038 if ($this->feed_url !== null)
2039 {
2040 return $this->sanitize('outlook' . SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2041 }
2042 else
2043 {
2044 return null;
2045 }
2046 }
2047
2048 function subscribe_podcast()
2049 {
2050 if ($this->feed_url !== null)
2051 {
2052 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
2053 }
2054 else
2055 {
2056 return null;
2057 }
2058 }
2059
2060 function subscribe_itunes()
2061 {
2062 if ($this->feed_url !== null)
2063 {
2064 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
2065 }
2066 else
2067 {
2068 return null;
2069 }
2070 }
2071
2072 /**
2073 * Creates the subscribe_* methods' return data
2074 *
2075 * @access private
2076 * @param string $feed_url String to prefix to the feed URL
2077 * @param string $site_url String to prefix to the site URL (and
2078 * suffix to the feed URL)
2079 * @return mixed URL if feed exists, false otherwise
2080 */
2081 function subscribe_service($feed_url, $site_url = null)
2082 {
2083 if ($this->subscribe_url())
2084 {
2085 $return = $feed_url . rawurlencode($this->feed_url);
2086 if ($site_url !== null && $this->get_link() !== null)
2087 {
2088 $return .= $site_url . rawurlencode($this->get_link());
2089 }
2090 return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
2091 }
2092 else
2093 {
2094 return null;
2095 }
2096 }
2097
2098 function subscribe_aol()
2099 {
2100 return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
2101 }
2102
2103 function subscribe_bloglines()
2104 {
2105 return $this->subscribe_service('http://www.bloglines.com/sub/');
2106 }
2107
2108 function subscribe_eskobo()
2109 {
2110 return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
2111 }
2112
2113 function subscribe_feedfeeds()
2114 {
2115 return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
2116 }
2117
2118 function subscribe_feedster()
2119 {
2120 return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
2121 }
2122
2123 function subscribe_google()
2124 {
2125 return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
2126 }
2127
2128 function subscribe_gritwire()
2129 {
2130 return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
2131 }
2132
2133 function subscribe_msn()
2134 {
2135 return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
2136 }
2137
2138 function subscribe_netvibes()
2139 {
2140 return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
2141 }
2142
2143 function subscribe_newsburst()
2144 {
2145 return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
2146 }
2147
2148 function subscribe_newsgator()
2149 {
2150 return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
2151 }
2152
2153 function subscribe_odeo()
2154 {
2155 return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
2156 }
2157
2158 function subscribe_podnova()
2159 {
2160 return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
2161 }
2162
2163 function subscribe_rojo()
2164 {
2165 return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
2166 }
2167
2168 function subscribe_yahoo()
2169 {
2170 return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
2171 }
2172
2173 function get_feed_tags($namespace, $tag)
2174 {
2175 $type = $this->get_type();
2176 if ($type & SIMPLEPIE_TYPE_ATOM_10)
2177 {
2178 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
2179 {
2180 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
2181 }
2182 }
2183 if ($type & SIMPLEPIE_TYPE_ATOM_03)
2184 {
2185 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
2186 {
2187 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
2188 }
2189 }
2190 if ($type & SIMPLEPIE_TYPE_RSS_RDF)
2191 {
2192 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
2193 {
2194 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
2195 }
2196 }
2197 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2198 {
2199 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
2200 {
2201 return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
2202 }
2203 }
2204 return null;
2205 }
2206
2207 function get_channel_tags($namespace, $tag)
2208 {
2209 $type = $this->get_type();
2210 if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
2211 {
2212 if ($return = $this->get_feed_tags($namespace, $tag))
2213 {
2214 return $return;
2215 }
2216 }
2217 if ($type & SIMPLEPIE_TYPE_RSS_10)
2218 {
2219 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
2220 {
2221 if (isset($channel[0]['child'][$namespace][$tag]))
2222 {
2223 return $channel[0]['child'][$namespace][$tag];
2224 }
2225 }
2226 }
2227 if ($type & SIMPLEPIE_TYPE_RSS_090)
2228 {
2229 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
2230 {
2231 if (isset($channel[0]['child'][$namespace][$tag]))
2232 {
2233 return $channel[0]['child'][$namespace][$tag];
2234 }
2235 }
2236 }
2237 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2238 {
2239 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
2240 {
2241 if (isset($channel[0]['child'][$namespace][$tag]))
2242 {
2243 return $channel[0]['child'][$namespace][$tag];
2244 }
2245 }
2246 }
2247 return null;
2248 }
2249
2250 function get_image_tags($namespace, $tag)
2251 {
2252 $type = $this->get_type();
2253 if ($type & SIMPLEPIE_TYPE_RSS_10)
2254 {
2255 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
2256 {
2257 if (isset($image[0]['child'][$namespace][$tag]))
2258 {
2259 return $image[0]['child'][$namespace][$tag];
2260 }
2261 }
2262 }
2263 if ($type & SIMPLEPIE_TYPE_RSS_090)
2264 {
2265 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2266 {
2267 if (isset($image[0]['child'][$namespace][$tag]))
2268 {
2269 return $image[0]['child'][$namespace][$tag];
2270 }
2271 }
2272 }
2273 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2274 {
2275 if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
2276 {
2277 if (isset($image[0]['child'][$namespace][$tag]))
2278 {
2279 return $image[0]['child'][$namespace][$tag];
2280 }
2281 }
2282 }
2283 return null;
2284 }
2285
2286 function get_base($element = array())
2287 {
2288 if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2289 {
2290 return $element['xml_base'];
2291 }
2292 elseif ($this->get_link() !== null)
2293 {
2294 return $this->get_link();
2295 }
2296 else
2297 {
2298 return $this->subscribe_url();
2299 }
2300 }
2301
2302 function sanitize($data, $type, $base = '')
2303 {
2304 return $this->sanitize->sanitize($data, $type, $base);
2305 }
2306
2307 function get_title()
2308 {
2309 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2310 {
2311 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2312 }
2313 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2314 {
2315 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2316 }
2317 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2318 {
2319 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2320 }
2321 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2322 {
2323 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2324 }
2325 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2326 {
2327 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2328 }
2329 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2330 {
2331 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2332 }
2333 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2334 {
2335 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2336 }
2337 else
2338 {
2339 return null;
2340 }
2341 }
2342
2343 function get_category($key = 0)
2344 {
2345 $categories = $this->get_categories();
2346 if (isset($categories[$key]))
2347 {
2348 return $categories[$key];
2349 }
2350 else
2351 {
2352 return null;
2353 }
2354 }
2355
2356 function get_categories()
2357 {
2358 $categories = array();
2359
2360 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2361 {
2362 $term = null;
2363 $scheme = null;
2364 $label = null;
2365 if (isset($category['attribs']['']['term']))
2366 {
2367 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2368 }
2369 if (isset($category['attribs']['']['scheme']))
2370 {
2371 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2372 }
2373 if (isset($category['attribs']['']['label']))
2374 {
2375 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2376 }
2377 $categories[] =& new $this->category_class($term, $scheme, $label);
2378 }
2379 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
2380 {
2381 // This is really the label, but keep this as the term also for BC.
2382 // Label will also work on retrieving because that falls back to term.
2383 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2384 if (isset($category['attribs']['']['domain']))
2385 {
2386 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
2387 }
2388 else
2389 {
2390 $scheme = null;
2391 }
2392 $categories[] =& new $this->category_class($term, $scheme, null);
2393 }
2394 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2395 {
2396 $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2397 }
2398 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2399 {
2400 $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2401 }
2402
2403 if (!empty($categories))
2404 {
2405 return SimplePie_Misc::array_unique($categories);
2406 }
2407 else
2408 {
2409 return null;
2410 }
2411 }
2412
2413 function get_author($key = 0)
2414 {
2415 $authors = $this->get_authors();
2416 if (isset($authors[$key]))
2417 {
2418 return $authors[$key];
2419 }
2420 else
2421 {
2422 return null;
2423 }
2424 }
2425
2426 function get_authors()
2427 {
2428 $authors = array();
2429 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2430 {
2431 $name = null;
2432 $uri = null;
2433 $email = null;
2434 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2435 {
2436 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2437 }
2438 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2439 {
2440 $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]));
2441 }
2442 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2443 {
2444 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2445 }
2446 if ($name !== null || $email !== null || $uri !== null)
2447 {
2448 $authors[] =& new $this->author_class($name, $uri, $email);
2449 }
2450 }
2451 if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2452 {
2453 $name = null;
2454 $url = null;
2455 $email = null;
2456 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2457 {
2458 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2459 }
2460 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2461 {
2462 $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]));
2463 }
2464 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2465 {
2466 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2467 }
2468 if ($name !== null || $email !== null || $url !== null)
2469 {
2470 $authors[] =& new $this->author_class($name, $url, $email);
2471 }
2472 }
2473 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2474 {
2475 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2476 }
2477 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2478 {
2479 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2480 }
2481 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2482 {
2483 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2484 }
2485
2486 if (!empty($authors))
2487 {
2488 return SimplePie_Misc::array_unique($authors);
2489 }
2490 else
2491 {
2492 return null;
2493 }
2494 }
2495
2496 function get_contributor($key = 0)
2497 {
2498 $contributors = $this->get_contributors();
2499 if (isset($contributors[$key]))
2500 {
2501 return $contributors[$key];
2502 }
2503 else
2504 {
2505 return null;
2506 }
2507 }
2508
2509 function get_contributors()
2510 {
2511 $contributors = array();
2512 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2513 {
2514 $name = null;
2515 $uri = null;
2516 $email = null;
2517 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2518 {
2519 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2520 }
2521 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2522 {
2523 $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]));
2524 }
2525 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2526 {
2527 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2528 }
2529 if ($name !== null || $email !== null || $uri !== null)
2530 {
2531 $contributors[] =& new $this->author_class($name, $uri, $email);
2532 }
2533 }
2534 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2535 {
2536 $name = null;
2537 $url = null;
2538 $email = null;
2539 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2540 {
2541 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2542 }
2543 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2544 {
2545 $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]));
2546 }
2547 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2548 {
2549 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2550 }
2551 if ($name !== null || $email !== null || $url !== null)
2552 {
2553 $contributors[] =& new $this->author_class($name, $url, $email);
2554 }
2555 }
2556
2557 if (!empty($contributors))
2558 {
2559 return SimplePie_Misc::array_unique($contributors);
2560 }
2561 else
2562 {
2563 return null;
2564 }
2565 }
2566
2567 function get_link($key = 0, $rel = 'alternate')
2568 {
2569 $links = $this->get_links($rel);
2570 if (isset($links[$key]))
2571 {
2572 return $links[$key];
2573 }
2574 else
2575 {
2576 return null;
2577 }
2578 }
2579
2580 /**
2581 * Added for parity between the parent-level and the item/entry-level.
2582 */
2583 function get_permalink()
2584 {
2585 return $this->get_link(0);
2586 }
2587
2588 function get_links($rel = 'alternate')
2589 {
2590 if (!isset($this->data['links']))
2591 {
2592 $this->data['links'] = array();
2593 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2594 {
2595 foreach ($links as $link)
2596 {
2597 if (isset($link['attribs']['']['href']))
2598 {
2599 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2600 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2601 }
2602 }
2603 }
2604 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2605 {
2606 foreach ($links as $link)
2607 {
2608 if (isset($link['attribs']['']['href']))
2609 {
2610 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2611 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2612
2613 }
2614 }
2615 }
2616 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2617 {
2618 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2619 }
2620 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2621 {
2622 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2623 }
2624 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2625 {
2626 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2627 }
2628
2629 $keys = array_keys($this->data['links']);
2630 foreach ($keys as $key)
2631 {
2632 if (SimplePie_Misc::is_isegment_nz_nc($key))
2633 {
2634 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2635 {
2636 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2637 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2638 }
2639 else
2640 {
2641 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2642 }
2643 }
2644 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2645 {
2646 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2647 }
2648 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2649 }
2650 }
2651
2652 if (isset($this->data['links'][$rel]))
2653 {
2654 return $this->data['links'][$rel];
2655 }
2656 else
2657 {
2658 return null;
2659 }
2660 }
2661
2662 function get_all_discovered_feeds()
2663 {
2664 return $this->all_discovered_feeds;
2665 }
2666
2667 function get_description()
2668 {
2669 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2670 {
2671 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2672 }
2673 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2674 {
2675 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2676 }
2677 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2678 {
2679 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2680 }
2681 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2682 {
2683 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2684 }
2685 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2686 {
2687 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2688 }
2689 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2690 {
2691 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2692 }
2693 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2694 {
2695 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2696 }
2697 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2698 {
2699 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2700 }
2701 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2702 {
2703 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2704 }
2705 else
2706 {
2707 return null;
2708 }
2709 }
2710
2711 function get_copyright()
2712 {
2713 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2714 {
2715 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2716 }
2717 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2718 {
2719 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2720 }
2721 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2722 {
2723 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2724 }
2725 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2726 {
2727 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2728 }
2729 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2730 {
2731 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2732 }
2733 else
2734 {
2735 return null;
2736 }
2737 }
2738
2739 function get_language()
2740 {
2741 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2742 {
2743 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2744 }
2745 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2746 {
2747 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2748 }
2749 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2750 {
2751 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2752 }
2753 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2754 {
2755 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2756 }
2757 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2758 {
2759 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2760 }
2761 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2762 {
2763 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2764 }
2765 elseif (isset($this->data['headers']['content-language']))
2766 {
2767 return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2768 }
2769 else
2770 {
2771 return null;
2772 }
2773 }
2774
2775 function get_latitude()
2776 {
2777
2778 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2779 {
2780 return (float) $return[0]['data'];
2781 }
2782 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))
2783 {
2784 return (float) $match[1];
2785 }
2786 else
2787 {
2788 return null;
2789 }
2790 }
2791
2792 function get_longitude()
2793 {
2794 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2795 {
2796 return (float) $return[0]['data'];
2797 }
2798 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2799 {
2800 return (float) $return[0]['data'];
2801 }
2802 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))
2803 {
2804 return (float) $match[2];
2805 }
2806 else
2807 {
2808 return null;
2809 }
2810 }
2811
2812 function get_image_title()
2813 {
2814 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2815 {
2816 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2817 }
2818 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2819 {
2820 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2821 }
2822 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2823 {
2824 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2825 }
2826 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2827 {
2828 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2829 }
2830 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2831 {
2832 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2833 }
2834 else
2835 {
2836 return null;
2837 }
2838 }
2839
2840 function get_image_url()
2841 {
2842 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2843 {
2844 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2845 }
2846 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2847 {
2848 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2849 }
2850 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2851 {
2852 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2853 }
2854 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2855 {
2856 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2857 }
2858 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2859 {
2860 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2861 }
2862 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2863 {
2864 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2865 }
2866 else
2867 {
2868 return null;
2869 }
2870 }
2871
2872 function get_image_link()
2873 {
2874 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2875 {
2876 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2877 }
2878 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2879 {
2880 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2881 }
2882 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2883 {
2884 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2885 }
2886 else
2887 {
2888 return null;
2889 }
2890 }
2891
2892 function get_image_width()
2893 {
2894 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2895 {
2896 return round($return[0]['data']);
2897 }
2898 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2899 {
2900 return 88.0;
2901 }
2902 else
2903 {
2904 return null;
2905 }
2906 }
2907
2908 function get_image_height()
2909 {
2910 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2911 {
2912 return round($return[0]['data']);
2913 }
2914 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2915 {
2916 return 31.0;
2917 }
2918 else
2919 {
2920 return null;
2921 }
2922 }
2923
2924 function get_item_quantity($max = 0)
2925 {
2926 $max = (int) $max;
2927 $qty = count($this->get_items());
2928 if ($max === 0)
2929 {
2930 return $qty;
2931 }
2932 else
2933 {
2934 return ($qty > $max) ? $max : $qty;
2935 }
2936 }
2937
2938 function get_item($key = 0)
2939 {
2940 $items = $this->get_items();
2941 if (isset($items[$key]))
2942 {
2943 return $items[$key];
2944 }
2945 else
2946 {
2947 return null;
2948 }
2949 }
2950
2951 function get_items($start = 0, $end = 0)
2952 {
2953 if (!isset($this->data['items']))
2954 {
2955 if (!empty($this->multifeed_objects))
2956 {
2957 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2958 }
2959 else
2960 {
2961 $this->data['items'] = array();
2962 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2963 {
2964 $keys = array_keys($items);
2965 foreach ($keys as $key)
2966 {
2967 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2968 }
2969 }
2970 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2971 {
2972 $keys = array_keys($items);
2973 foreach ($keys as $key)
2974 {
2975 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2976 }
2977 }
2978 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
2979 {
2980 $keys = array_keys($items);
2981 foreach ($keys as $key)
2982 {
2983 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2984 }
2985 }
2986 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2987 {
2988 $keys = array_keys($items);
2989 foreach ($keys as $key)
2990 {
2991 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2992 }
2993 }
2994 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
2995 {
2996 $keys = array_keys($items);
2997 foreach ($keys as $key)
2998 {
2999 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
3000 }
3001 }
3002 }
3003 }
3004
3005 if (!empty($this->data['items']))
3006 {
3007 // If we want to order it by date, check if all items have a date, and then sort it
3008 if ($this->order_by_date && empty($this->multifeed_objects))
3009 {
3010 if (!isset($this->data['ordered_items']))
3011 {
3012 $do_sort = true;
3013 foreach ($this->data['items'] as $item)
3014 {
3015 if (!$item->get_date('U'))
3016 {
3017 $do_sort = false;
3018 break;
3019 }
3020 }
3021 $item = null;
3022 $this->data['ordered_items'] = $this->data['items'];
3023 if ($do_sort)
3024 {
3025 usort($this->data['ordered_items'], array(&$this, 'sort_items'));
3026 }
3027 }
3028 $items = $this->data['ordered_items'];
3029 }
3030 else
3031 {
3032 $items = $this->data['items'];
3033 }
3034
3035 // Slice the data as desired
3036 if ($end === 0)
3037 {
3038 return array_slice($items, $start);
3039 }
3040 else
3041 {
3042 return array_slice($items, $start, $end);
3043 }
3044 }
3045 else
3046 {
3047 return array();
3048 }
3049 }
3050
3051 /**
3052 * @static
3053 */
3054 function sort_items($a, $b)
3055 {
3056 return $a->get_date('U') <= $b->get_date('U');
3057 }
3058
3059 /**
3060 * @static
3061 */
3062 function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3063 {
3064 if (is_array($urls) && sizeof($urls) > 0)
3065 {
3066 $items = array();
3067 foreach ($urls as $arg)
3068 {
3069 if (is_a($arg, 'SimplePie'))
3070 {
3071 $items = array_merge($items, $arg->get_items(0, $limit));
3072 }
3073 else
3074 {
3075 trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3076 }
3077 }
3078
3079 $do_sort = true;
3080 foreach ($items as $item)
3081 {
3082 if (!$item->get_date('U'))
3083 {
3084 $do_sort = false;
3085 break;
3086 }
3087 }
3088 $item = null;
3089 if ($do_sort)
3090 {
3091 usort($items, array('SimplePie', 'sort_items'));
3092 }
3093
3094 if ($end === 0)
3095 {
3096 return array_slice($items, $start);
3097 }
3098 else
3099 {
3100 return array_slice($items, $start, $end);
3101 }
3102 }
3103 else
3104 {
3105 trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3106 return array();
3107 }
3108 }
3109 }
3110
3111 class SimplePie_Item
3112 {
3113 var $feed;
3114 var $data = array();
3115
3116 function SimplePie_Item($feed, $data)
3117 {
3118 $this->feed = $feed;
3119 $this->data = $data;
3120 }
3121
3122 function __toString()
3123 {
3124 return md5(serialize($this->data));
3125 }
3126
3127 /**
3128 * Remove items that link back to this before destroying this object
3129 */
3130 function __destruct()
3131 {
3132 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
3133 {
3134 unset($this->feed);
3135 }
3136 }
3137
3138 function get_item_tags($namespace, $tag)
3139 {
3140 if (isset($this->data['child'][$namespace][$tag]))
3141 {
3142 return $this->data['child'][$namespace][$tag];
3143 }
3144 else
3145 {
3146 return null;
3147 }
3148 }
3149
3150 function get_base($element = array())
3151 {
3152 return $this->feed->get_base($element);
3153 }
3154
3155 function sanitize($data, $type, $base = '')
3156 {
3157 return $this->feed->sanitize($data, $type, $base);
3158 }
3159
3160 function get_feed()
3161 {
3162 return $this->feed;
3163 }
3164
3165 function get_id($hash = false)
3166 {
3167 if (!$hash)
3168 {
3169 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
3170 {
3171 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3172 }
3173 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
3174 {
3175 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3176 }
3177 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3178 {
3179 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3180 }
3181 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
3182 {
3183 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3184 }
3185 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
3186 {
3187 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3188 }
3189 elseif (($return = $this->get_permalink()) !== null)
3190 {
3191 return $return;
3192 }
3193 elseif (($return = $this->get_title()) !== null)
3194 {
3195 return $return;
3196 }
3197 }
3198 if ($this->get_permalink() !== null || $this->get_title() !== null)
3199 {
3200 return md5($this->get_permalink() . $this->get_title());
3201 }
3202 else
3203 {
3204 return md5(serialize($this->data));
3205 }
3206 }
3207
3208 function get_title()
3209 {
3210 if (!isset($this->data['title']))
3211 {
3212 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
3213 {
3214 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3215 }
3216 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
3217 {
3218 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3219 }
3220 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
3221 {
3222 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3223 }
3224 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
3225 {
3226 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3227 }
3228 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
3229 {
3230 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3231 }
3232 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
3233 {
3234 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3235 }
3236 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
3237 {
3238 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3239 }
3240 else
3241 {
3242 $this->data['title'] = null;
3243 }
3244 }
3245 return $this->data['title'];
3246 }
3247
3248 function get_description($description_only = false)
3249 {
3250 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
3251 {
3252 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3253 }
3254 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
3255 {
3256 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3257 }
3258 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
3259 {
3260 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3261 }
3262 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
3263 {
3264 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3265 }
3266 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3267 {
3268 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3269 }
3270 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3271 {
3272 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3273 }
3274 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3275 {
3276 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3277 }
3278 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3279 {
3280 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3281 }
3282 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
3283 {
3284 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML);
3285 }
3286
3287 elseif (!$description_only)
3288 {
3289 return $this->get_content(true);
3290 }
3291 else
3292 {
3293 return null;
3294 }
3295 }
3296
3297 function get_content($content_only = false)
3298 {
3299 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3300 {
3301 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3302 }
3303 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3304 {
3305 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3306 }
3307 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3308 {
3309 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3310 }
3311 elseif (!$content_only)
3312 {
3313 return $this->get_description(true);
3314 }
3315 else
3316 {
3317 return null;
3318 }
3319 }
3320
3321 function get_category($key = 0)
3322 {
3323 $categories = $this->get_categories();
3324 if (isset($categories[$key]))
3325 {
3326 return $categories[$key];
3327 }
3328 else
3329 {
3330 return null;
3331 }
3332 }
3333
3334 function get_categories()
3335 {
3336 $categories = array();
3337
3338 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3339 {
3340 $term = null;
3341 $scheme = null;
3342 $label = null;
3343 if (isset($category['attribs']['']['term']))
3344 {
3345 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3346 }
3347 if (isset($category['attribs']['']['scheme']))
3348 {
3349 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3350 }
3351 if (isset($category['attribs']['']['label']))
3352 {
3353 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3354 }
3355 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
3356 }
3357 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
3358 {
3359 // This is really the label, but keep this as the term also for BC.
3360 // Label will also work on retrieving because that falls back to term.
3361 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3362 if (isset($category['attribs']['']['domain']))
3363 {
3364 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
3365 }
3366 else
3367 {
3368 $scheme = null;
3369 }
3370 $categories[] =& new $this->feed->category_class($term, $scheme, null);
3371 }
3372 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3373 {
3374 $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3375 }
3376 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3377 {
3378 $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3379 }
3380
3381 if (!empty($categories))
3382 {
3383 return SimplePie_Misc::array_unique($categories);
3384 }
3385 else
3386 {
3387 return null;
3388 }
3389 }
3390
3391 function get_author($key = 0)
3392 {
3393 $authors = $this->get_authors();
3394 if (isset($authors[$key]))
3395 {
3396 return $authors[$key];
3397 }
3398 else
3399 {
3400 return null;
3401 }
3402 }
3403
3404 function get_contributor($key = 0)
3405 {
3406 $contributors = $this->get_contributors();
3407 if (isset($contributors[$key]))
3408 {
3409 return $contributors[$key];
3410 }
3411 else
3412 {
3413 return null;
3414 }
3415 }
3416
3417 function get_contributors()
3418 {
3419 $contributors = array();
3420 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3421 {
3422 $name = null;
3423 $uri = null;
3424 $email = null;
3425 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3426 {
3427 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3428 }
3429 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3430 {
3431 $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]));
3432 }
3433 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3434 {
3435 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3436 }
3437 if ($name !== null || $email !== null || $uri !== null)
3438 {
3439 $contributors[] =& new $this->feed->author_class($name, $uri, $email);
3440 }
3441 }
3442 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3443 {
3444 $name = null;
3445 $url = null;
3446 $email = null;
3447 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3448 {
3449 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3450 }
3451 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3452 {
3453 $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]));
3454 }
3455 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3456 {
3457 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3458 }
3459 if ($name !== null || $email !== null || $url !== null)
3460 {
3461 $contributors[] =& new $this->feed->author_class($name, $url, $email);
3462 }
3463 }
3464
3465 if (!empty($contributors))
3466 {
3467 return SimplePie_Misc::array_unique($contributors);
3468 }
3469 else
3470 {
3471 return null;
3472 }
3473 }
3474
3475 function get_authors()
3476 {
3477 $authors = array();
3478 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3479 {
3480 $name = null;
3481 $uri = null;
3482 $email = null;
3483 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3484 {
3485 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3486 }
3487 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3488 {
3489 $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]));
3490 }
3491 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3492 {
3493 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3494 }
3495 if ($name !== null || $email !== null || $uri !== null)
3496 {
3497 $authors[] =& new $this->feed->author_class($name, $uri, $email);
3498 }
3499 }
3500 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3501 {
3502 $name = null;
3503 $url = null;
3504 $email = null;
3505 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3506 {
3507 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3508 }
3509 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3510 {
3511 $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]));
3512 }
3513 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3514 {
3515 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3516 }
3517 if ($name !== null || $email !== null || $url !== null)
3518 {
3519 $authors[] =& new $this->feed->author_class($name, $url, $email);
3520 }
3521 }
3522 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
3523 {
3524 $authors[] =& new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3525 }
3526 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3527 {
3528 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3529 }
3530 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3531 {
3532 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3533 }
3534 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3535 {
3536 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3537 }
3538
3539 if (!empty($authors))
3540 {
3541 return SimplePie_Misc::array_unique($authors);
3542 }
3543 elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3544 {
3545 return $authors;
3546 }
3547 elseif ($authors = $this->feed->get_authors())
3548 {
3549 return $authors;
3550 }
3551 else
3552 {
3553 return null;
3554 }
3555 }
3556
3557 function get_copyright()
3558 {
3559 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3560 {
3561 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3562 }
3563 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3564 {
3565 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3566 }
3567 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3568 {
3569 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3570 }
3571 else
3572 {
3573 return null;
3574 }
3575 }
3576
3577 function get_date($date_format = 'j F Y, g:i a')
3578 {
3579 if (!isset($this->data['date']))
3580 {
3581 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3582 {
3583 $this->data['date']['raw'] = $return[0]['data'];
3584 }
3585 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3586 {
3587 $this->data['date']['raw'] = $return[0]['data'];
3588 }
3589 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3590 {
3591 $this->data['date']['raw'] = $return[0]['data'];
3592 }
3593 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3594 {
3595 $this->data['date']['raw'] = $return[0]['data'];
3596 }
3597 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3598 {
3599 $this->data['date']['raw'] = $return[0]['data'];
3600 }
3601 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
3602 {
3603 $this->data['date']['raw'] = $return[0]['data'];
3604 }
3605 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3606 {
3607 $this->data['date']['raw'] = $return[0]['data'];
3608 }
3609 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3610 {
3611 $this->data['date']['raw'] = $return[0]['data'];
3612 }
3613
3614 if (!empty($this->data['date']['raw']))
3615 {
3616 $parser = SimplePie_Parse_Date::get();
3617 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3618 }
3619 else
3620 {
3621 $this->data['date'] = null;
3622 }
3623 }
3624 if ($this->data['date'])
3625 {
3626 $date_format = (string) $date_format;
3627 switch ($date_format)
3628 {
3629 case '':
3630 return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3631
3632 case 'U':
3633 return $this->data['date']['parsed'];
3634
3635 default:
3636 return date($date_format, $this->data['date']['parsed']);
3637 }
3638 }
3639 else
3640 {
3641 return null;
3642 }
3643 }
3644
3645 function get_local_date($date_format = '%c')
3646 {
3647 if (!$date_format)
3648 {
3649 return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3650 }
3651 elseif (($date = $this->get_date('U')) !== null && $date !== false)
3652 {
3653 return strftime($date_format, $date);
3654 }
3655 else
3656 {
3657 return null;
3658 }
3659 }
3660
3661 function get_permalink()
3662 {
3663 $link = $this->get_link();
3664 $enclosure = $this->get_enclosure(0);
3665 if ($link !== null)
3666 {
3667 return $link;
3668 }
3669 elseif ($enclosure !== null)
3670 {
3671 return $enclosure->get_link();
3672 }
3673 else
3674 {
3675 return null;
3676 }
3677 }
3678
3679 function get_link($key = 0, $rel = 'alternate')
3680 {
3681 $links = $this->get_links($rel);
3682 if ($links[$key] !== null)
3683 {
3684 return $links[$key];
3685 }
3686 else
3687 {
3688 return null;
3689 }
3690 }
3691
3692 function get_links($rel = 'alternate')
3693 {
3694 if (!isset($this->data['links']))
3695 {
3696 $this->data['links'] = array();
3697 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3698 {
3699 if (isset($link['attribs']['']['href']))
3700 {
3701 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3702 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3703
3704 }
3705 }
3706 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3707 {
3708 if (isset($link['attribs']['']['href']))
3709 {
3710 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3711 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3712 }
3713 }
3714 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3715 {
3716 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3717 }
3718 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3719 {
3720 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3721 }
3722 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
3723 {
3724 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3725 }
3726 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3727 {
3728 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
3729 {
3730 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3731 }
3732 }
3733
3734 $keys = array_keys($this->data['links']);
3735 foreach ($keys as $key)
3736 {
3737 if (SimplePie_Misc::is_isegment_nz_nc($key))
3738 {
3739 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3740 {
3741 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3742 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3743 }
3744 else
3745 {
3746 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3747 }
3748 }
3749 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
3750 {
3751 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3752 }
3753 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3754 }
3755 }
3756 if (isset($this->data['links'][$rel]))
3757 {
3758 return $this->data['links'][$rel];
3759 }
3760 else
3761 {
3762 return null;
3763 }
3764 }
3765
3766 /**
3767 * @todo Add ability to prefer one type of content over another (in a media group).
3768 */
3769 function get_enclosure($key = 0, $prefer = null)
3770 {
3771 $enclosures = $this->get_enclosures();
3772 if (isset($enclosures[$key]))
3773 {
3774 return $enclosures[$key];
3775 }
3776 else
3777 {
3778 return null;
3779 }
3780 }
3781
3782 /**
3783 * Grabs all available enclosures (podcasts, etc.)
3784 *
3785 * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3786 *
3787 * 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.
3788 *
3789 * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3790 * @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).
3791 */
3792 function get_enclosures()
3793 {
3794 if (!isset($this->data['enclosures']))
3795 {
3796 $this->data['enclosures'] = array();
3797
3798 // Elements
3799 $captions_parent = null;
3800 $categories_parent = null;
3801 $copyrights_parent = null;
3802 $credits_parent = null;
3803 $description_parent = null;
3804 $duration_parent = null;
3805 $hashes_parent = null;
3806 $keywords_parent = null;
3807 $player_parent = null;
3808 $ratings_parent = null;
3809 $restrictions_parent = null;
3810 $thumbnails_parent = null;
3811 $title_parent = null;
3812
3813 // Let's do the channel and item-level ones first, and just re-use them if we need to.
3814 $parent = $this->get_feed();
3815
3816 // CAPTIONS
3817 if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3818 {
3819 foreach ($captions as $caption)
3820 {
3821 $caption_type = null;
3822 $caption_lang = null;
3823 $caption_startTime = null;
3824 $caption_endTime = null;
3825 $caption_text = null;
3826 if (isset($caption['attribs']['']['type']))
3827 {
3828 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3829 }
3830 if (isset($caption['attribs']['']['lang']))
3831 {
3832 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3833 }
3834 if (isset($caption['attribs']['']['start']))
3835 {
3836 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3837 }
3838 if (isset($caption['attribs']['']['end']))
3839 {
3840 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3841 }
3842 if (isset($caption['data']))
3843 {
3844 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3845 }
3846 $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3847 }
3848 }
3849 elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3850 {
3851 foreach ($captions as $caption)
3852 {
3853 $caption_type = null;
3854 $caption_lang = null;
3855 $caption_startTime = null;
3856 $caption_endTime = null;
3857 $caption_text = null;
3858 if (isset($caption['attribs']['']['type']))
3859 {
3860 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3861 }
3862 if (isset($caption['attribs']['']['lang']))
3863 {
3864 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3865 }
3866 if (isset($caption['attribs']['']['start']))
3867 {
3868 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3869 }
3870 if (isset($caption['attribs']['']['end']))
3871 {
3872 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3873 }
3874 if (isset($caption['data']))
3875 {
3876 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3877 }
3878 $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3879 }
3880 }
3881 if (is_array($captions_parent))
3882 {
3883 $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
3884 }
3885
3886 // CATEGORIES
3887 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3888 {
3889 $term = null;
3890 $scheme = null;
3891 $label = null;
3892 if (isset($category['data']))
3893 {
3894 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3895 }
3896 if (isset($category['attribs']['']['scheme']))
3897 {
3898 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3899 }
3900 else
3901 {
3902 $scheme = 'http://search.yahoo.com/mrss/category_schema';
3903 }
3904 if (isset($category['attribs']['']['label']))
3905 {
3906 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3907 }
3908 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3909 }
3910 foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3911 {
3912 $term = null;
3913 $scheme = null;
3914 $label = null;
3915 if (isset($category['data']))
3916 {
3917 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3918 }
3919 if (isset($category['attribs']['']['scheme']))
3920 {
3921 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3922 }
3923 else
3924 {
3925 $scheme = 'http://search.yahoo.com/mrss/category_schema';
3926 }
3927 if (isset($category['attribs']['']['label']))
3928 {
3929 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3930 }
3931 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3932 }
3933 foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
3934 {
3935 $term = null;
3936 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
3937 $label = null;
3938 if (isset($category['attribs']['']['text']))
3939 {
3940 $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3941 }
3942 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3943
3944 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
3945 {
3946 foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
3947 {
3948 if (isset($subcategory['attribs']['']['text']))
3949 {
3950 $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3951 }
3952 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3953 }
3954 }
3955 }
3956 if (is_array($categories_parent))
3957 {
3958 $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
3959 }
3960
3961 // COPYRIGHT
3962 if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3963 {
3964 $copyright_url = null;
3965 $copyright_label = null;
3966 if (isset($copyright[0]['attribs']['']['url']))
3967 {
3968 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3969 }
3970 if (isset($copyright[0]['data']))
3971 {
3972 $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3973 }
3974 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3975 }
3976 elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3977 {
3978 $copyright_url = null;
3979 $copyright_label = null;
3980 if (isset($copyright[0]['attribs']['']['url']))
3981 {
3982 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3983 }
3984 if (isset($copyright[0]['data']))
3985 {
3986 $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3987 }
3988 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3989 }
3990
3991 // CREDITS
3992 if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
3993 {
3994 foreach ($credits as $credit)
3995 {
3996 $credit_role = null;
3997 $credit_scheme = null;
3998 $credit_name = null;
3999 if (isset($credit['attribs']['']['role']))
4000 {
4001 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4002 }
4003 if (isset($credit['attribs']['']['scheme']))
4004 {
4005 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4006 }
4007 else
4008 {
4009 $credit_scheme = 'urn:ebu';
4010 }
4011 if (isset($credit['data']))
4012 {
4013 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4014 }
4015 $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4016 }
4017 }
4018 elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4019 {
4020 foreach ($credits as $credit)
4021 {
4022 $credit_role = null;
4023 $credit_scheme = null;
4024 $credit_name = null;
4025 if (isset($credit['attribs']['']['role']))
4026 {
4027 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4028 }
4029 if (isset($credit['attribs']['']['scheme']))
4030 {
4031 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4032 }
4033 else
4034 {
4035 $credit_scheme = 'urn:ebu';
4036 }
4037 if (isset($credit['data']))
4038 {
4039 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4040 }
4041 $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4042 }
4043 }
4044 if (is_array($credits_parent))
4045 {
4046 $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
4047 }
4048
4049 // DESCRIPTION
4050 if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4051 {
4052 if (isset($description_parent[0]['data']))
4053 {
4054 $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4055 }
4056 }
4057 elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4058 {
4059 if (isset($description_parent[0]['data']))
4060 {
4061 $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4062 }
4063 }
4064
4065 // DURATION
4066 if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
4067 {
4068 $seconds = null;
4069 $minutes = null;
4070 $hours = null;
4071 if (isset($duration_parent[0]['data']))
4072 {
4073 $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4074 if (sizeof($temp) > 0)
4075 {
4076 $seconds = (int) array_pop($temp);
4077 }
4078 if (sizeof($temp) > 0)
4079 {
4080 $minutes = (int) array_pop($temp);
4081 $seconds += $minutes * 60;
4082 }
4083 if (sizeof($temp) > 0)
4084 {
4085 $hours = (int) array_pop($temp);
4086 $seconds += $hours * 3600;
4087 }
4088 unset($temp);
4089 $duration_parent = $seconds;
4090 }
4091 }
4092
4093 // HASHES
4094 if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4095 {
4096 foreach ($hashes_iterator as $hash)
4097 {
4098 $value = null;
4099 $algo = null;
4100 if (isset($hash['data']))
4101 {
4102 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4103 }
4104 if (isset($hash['attribs']['']['algo']))
4105 {
4106 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4107 }
4108 else
4109 {
4110 $algo = 'md5';
4111 }
4112 $hashes_parent[] = $algo.':'.$value;
4113 }
4114 }
4115 elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4116 {
4117 foreach ($hashes_iterator as $hash)
4118 {
4119 $value = null;
4120 $algo = null;
4121 if (isset($hash['data']))
4122 {
4123 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4124 }
4125 if (isset($hash['attribs']['']['algo']))
4126 {
4127 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4128 }
4129 else
4130 {
4131 $algo = 'md5';
4132 }
4133 $hashes_parent[] = $algo.':'.$value;
4134 }
4135 }
4136 if (is_array($hashes_parent))
4137 {
4138 $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
4139 }
4140
4141 // KEYWORDS
4142 if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4143 {
4144 if (isset($keywords[0]['data']))
4145 {
4146 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4147 foreach ($temp as $word)
4148 {
4149 $keywords_parent[] = trim($word);
4150 }
4151 }
4152 unset($temp);
4153 }
4154 elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4155 {
4156 if (isset($keywords[0]['data']))
4157 {
4158 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4159 foreach ($temp as $word)
4160 {
4161 $keywords_parent[] = trim($word);
4162 }
4163 }
4164 unset($temp);
4165 }
4166 elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4167 {
4168 if (isset($keywords[0]['data']))
4169 {
4170 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4171 foreach ($temp as $word)
4172 {
4173 $keywords_parent[] = trim($word);
4174 }
4175 }
4176 unset($temp);
4177 }
4178 elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4179 {
4180 if (isset($keywords[0]['data']))
4181 {
4182 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4183 foreach ($temp as $word)
4184 {
4185 $keywords_parent[] = trim($word);
4186 }
4187 }
4188 unset($temp);
4189 }
4190 if (is_array($keywords_parent))
4191 {
4192 $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
4193 }
4194
4195 // PLAYER
4196 if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4197 {
4198 if (isset($player_parent[0]['attribs']['']['url']))
4199 {
4200 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4201 }
4202 }
4203 elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4204 {
4205 if (isset($player_parent[0]['attribs']['']['url']))
4206 {
4207 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4208 }
4209 }
4210
4211 // RATINGS
4212 if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4213 {
4214 foreach ($ratings as $rating)
4215 {
4216 $rating_scheme = null;
4217 $rating_value = null;
4218 if (isset($rating['attribs']['']['scheme']))
4219 {
4220 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4221 }
4222 else
4223 {
4224 $rating_scheme = 'urn:simple';
4225 }
4226 if (isset($rating['data']))
4227 {
4228 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4229 }
4230 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4231 }
4232 }
4233 elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4234 {
4235 foreach ($ratings as $rating)
4236 {
4237 $rating_scheme = 'urn:itunes';
4238 $rating_value = null;
4239 if (isset($rating['data']))
4240 {
4241 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4242 }
4243 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4244 }
4245 }
4246 elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4247 {
4248 foreach ($ratings as $rating)
4249 {
4250 $rating_scheme = null;
4251 $rating_value = null;
4252 if (isset($rating['attribs']['']['scheme']))
4253 {
4254 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4255 }
4256 else
4257 {
4258 $rating_scheme = 'urn:simple';
4259 }
4260 if (isset($rating['data']))
4261 {
4262 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4263 }
4264 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4265 }
4266 }
4267 elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4268 {
4269 foreach ($ratings as $rating)
4270 {
4271 $rating_scheme = 'urn:itunes';
4272 $rating_value = null;
4273 if (isset($rating['data']))
4274 {
4275 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4276 }
4277 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4278 }
4279 }
4280 if (is_array($ratings_parent))
4281 {
4282 $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
4283 }
4284
4285 // RESTRICTIONS
4286 if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4287 {
4288 foreach ($restrictions as $restriction)
4289 {
4290 $restriction_relationship = null;
4291 $restriction_type = null;
4292 $restriction_value = null;
4293 if (isset($restriction['attribs']['']['relationship']))
4294 {
4295 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4296 }
4297 if (isset($restriction['attribs']['']['type']))
4298 {
4299 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4300 }
4301 if (isset($restriction['data']))
4302 {
4303 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4304 }
4305 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4306 }
4307 }
4308 elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4309 {
4310 foreach ($restrictions as $restriction)
4311 {
4312 $restriction_relationship = 'allow';
4313 $restriction_type = null;
4314 $restriction_value = 'itunes';
4315 if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4316 {
4317 $restriction_relationship = 'deny';
4318 }
4319 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4320 }
4321 }
4322 elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4323 {
4324 foreach ($restrictions as $restriction)
4325 {
4326 $restriction_relationship = null;
4327 $restriction_type = null;
4328 $restriction_value = null;
4329 if (isset($restriction['attribs']['']['relationship']))
4330 {
4331 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4332 }
4333 if (isset($restriction['attribs']['']['type']))
4334 {
4335 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4336 }
4337 if (isset($restriction['data']))
4338 {
4339 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4340 }
4341 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4342 }
4343 }
4344 elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4345 {
4346 foreach ($restrictions as $restriction)
4347 {
4348 $restriction_relationship = 'allow';
4349 $restriction_type = null;
4350 $restriction_value = 'itunes';
4351 if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4352 {
4353 $restriction_relationship = 'deny';
4354 }
4355 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4356 }
4357 }
4358 if (is_array($restrictions_parent))
4359 {
4360 $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
4361 }
4362
4363 // THUMBNAILS
4364 if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4365 {
4366 foreach ($thumbnails as $thumbnail)
4367 {
4368 if (isset($thumbnail['attribs']['']['url']))
4369 {
4370 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4371 }
4372 }
4373 }
4374 elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4375 {
4376 foreach ($thumbnails as $thumbnail)
4377 {
4378 if (isset($thumbnail['attribs']['']['url']))
4379 {
4380 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4381 }
4382 }
4383 }
4384
4385 // TITLES
4386 if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4387 {
4388 if (isset($title_parent[0]['data']))
4389 {
4390 $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4391 }
4392 }
4393 elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4394 {
4395 if (isset($title_parent[0]['data']))
4396 {
4397 $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4398 }
4399 }
4400
4401 // Clear the memory
4402 unset($parent);
4403
4404 // Attributes
4405 $bitrate = null;
4406 $channels = null;
4407 $duration = null;
4408 $expression = null;
4409 $framerate = null;
4410 $height = null;
4411 $javascript = null;
4412 $lang = null;
4413 $length = null;
4414 $medium = null;
4415 $samplingrate = null;
4416 $type = null;
4417 $url = null;
4418 $width = null;
4419
4420 // Elements
4421 $captions = null;
4422 $categories = null;
4423 $copyrights = null;
4424 $credits = null;
4425 $description = null;
4426 $hashes = null;
4427 $keywords = null;
4428 $player = null;
4429 $ratings = null;
4430 $restrictions = null;
4431 $thumbnails = null;
4432 $title = null;
4433
4434 // If we have media:group tags, loop through them.
4435 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
4436 {
4437 if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
4438 {
4439 // If we have media:content tags, loop through them.
4440 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4441 {
4442 if (isset($content['attribs']['']['url']))
4443 {
4444 // Attributes
4445 $bitrate = null;
4446 $channels = null;
4447 $duration = null;
4448 $expression = null;
4449 $framerate = null;
4450 $height = null;
4451 $javascript = null;
4452 $lang = null;
4453 $length = null;
4454 $medium = null;
4455 $samplingrate = null;
4456 $type = null;
4457 $url = null;
4458 $width = null;
4459
4460 // Elements
4461 $captions = null;
4462 $categories = null;
4463 $copyrights = null;
4464 $credits = null;
4465 $description = null;
4466 $hashes = null;
4467 $keywords = null;
4468 $player = null;
4469 $ratings = null;
4470 $restrictions = null;
4471 $thumbnails = null;
4472 $title = null;
4473
4474 // Start checking the attributes of media:content
4475 if (isset($content['attribs']['']['bitrate']))
4476 {
4477 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4478 }
4479 if (isset($content['attribs']['']['channels']))
4480 {
4481 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4482 }
4483 if (isset($content['attribs']['']['duration']))
4484 {
4485 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4486 }
4487 else
4488 {
4489 $duration = $duration_parent;
4490 }
4491 if (isset($content['attribs']['']['expression']))
4492 {
4493 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4494 }
4495 if (isset($content['attribs']['']['framerate']))
4496 {
4497 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4498 }
4499 if (isset($content['attribs']['']['height']))
4500 {
4501 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4502 }
4503 if (isset($content['attribs']['']['lang']))
4504 {
4505 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4506 }
4507 if (isset($content['attribs']['']['fileSize']))
4508 {
4509 $length = ceil($content['attribs']['']['fileSize']);
4510 }
4511 if (isset($content['attribs']['']['medium']))
4512 {
4513 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4514 }
4515 if (isset($content['attribs']['']['samplingrate']))
4516 {
4517 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4518 }
4519 if (isset($content['attribs']['']['type']))
4520 {
4521 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4522 }
4523 if (isset($content['attribs']['']['width']))
4524 {
4525 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4526 }
4527 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4528
4529 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4530
4531 // CAPTIONS
4532 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4533 {
4534 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4535 {
4536 $caption_type = null;
4537 $caption_lang = null;
4538 $caption_startTime = null;
4539 $caption_endTime = null;
4540 $caption_text = null;
4541 if (isset($caption['attribs']['']['type']))
4542 {
4543 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4544 }
4545 if (isset($caption['attribs']['']['lang']))
4546 {
4547 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4548 }
4549 if (isset($caption['attribs']['']['start']))
4550 {
4551 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4552 }
4553 if (isset($caption['attribs']['']['end']))
4554 {
4555 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4556 }
4557 if (isset($caption['data']))
4558 {
4559 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4560 }
4561 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4562 }
4563 if (is_array($captions))
4564 {
4565 $captions = array_values(SimplePie_Misc::array_unique($captions));
4566 }
4567 }
4568 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4569 {
4570 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4571 {
4572 $caption_type = null;
4573 $caption_lang = null;
4574 $caption_startTime = null;
4575 $caption_endTime = null;
4576 $caption_text = null;
4577 if (isset($caption['attribs']['']['type']))
4578 {
4579 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4580 }
4581 if (isset($caption['attribs']['']['lang']))
4582 {
4583 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4584 }
4585 if (isset($caption['attribs']['']['start']))
4586 {
4587 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4588 }
4589 if (isset($caption['attribs']['']['end']))
4590 {
4591 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4592 }
4593 if (isset($caption['data']))
4594 {
4595 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4596 }
4597 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4598 }
4599 if (is_array($captions))
4600 {
4601 $captions = array_values(SimplePie_Misc::array_unique($captions));
4602 }
4603 }
4604 else
4605 {
4606 $captions = $captions_parent;
4607 }
4608
4609 // CATEGORIES
4610 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4611 {
4612 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4613 {
4614 $term = null;
4615 $scheme = null;
4616 $label = null;
4617 if (isset($category['data']))
4618 {
4619 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4620 }
4621 if (isset($category['attribs']['']['scheme']))
4622 {
4623 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4624 }
4625 else
4626 {
4627 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4628 }
4629 if (isset($category['attribs']['']['label']))
4630 {
4631 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4632 }
4633 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4634 }
4635 }
4636 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4637 {
4638 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4639 {
4640 $term = null;
4641 $scheme = null;
4642 $label = null;
4643 if (isset($category['data']))
4644 {
4645 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4646 }
4647 if (isset($category['attribs']['']['scheme']))
4648 {
4649 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4650 }
4651 else
4652 {
4653 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4654 }
4655 if (isset($category['attribs']['']['label']))
4656 {
4657 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4658 }
4659 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4660 }
4661 }
4662 if (is_array($categories) && is_array($categories_parent))
4663 {
4664 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4665 }
4666 elseif (is_array($categories))
4667 {
4668 $categories = array_values(SimplePie_Misc::array_unique($categories));
4669 }
4670 elseif (is_array($categories_parent))
4671 {
4672 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4673 }
4674
4675 // COPYRIGHTS
4676 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4677 {
4678 $copyright_url = null;
4679 $copyright_label = null;
4680 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4681 {
4682 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4683 }
4684 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4685 {
4686 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4687 }
4688 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4689 }
4690 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4691 {
4692 $copyright_url = null;
4693 $copyright_label = null;
4694 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4695 {
4696 $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4697 }
4698 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4699 {
4700 $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4701 }
4702 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4703 }
4704 else
4705 {
4706 $copyrights = $copyrights_parent;
4707 }
4708
4709 // CREDITS
4710 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4711 {
4712 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4713 {
4714 $credit_role = null;
4715 $credit_scheme = null;
4716 $credit_name = null;
4717 if (isset($credit['attribs']['']['role']))
4718 {
4719 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4720 }
4721 if (isset($credit['attribs']['']['scheme']))
4722 {
4723 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4724 }
4725 else
4726 {
4727 $credit_scheme = 'urn:ebu';
4728 }
4729 if (isset($credit['data']))
4730 {
4731 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4732 }
4733 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4734 }
4735 if (is_array($credits))
4736 {
4737 $credits = array_values(SimplePie_Misc::array_unique($credits));
4738 }
4739 }
4740 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4741 {
4742 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4743 {
4744 $credit_role = null;
4745 $credit_scheme = null;
4746 $credit_name = null;
4747 if (isset($credit['attribs']['']['role']))
4748 {
4749 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4750 }
4751 if (isset($credit['attribs']['']['scheme']))
4752 {
4753 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4754 }
4755 else
4756 {
4757 $credit_scheme = 'urn:ebu';
4758 }
4759 if (isset($credit['data']))
4760 {
4761 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4762 }
4763 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4764 }
4765 if (is_array($credits))
4766 {
4767 $credits = array_values(SimplePie_Misc::array_unique($credits));
4768 }
4769 }
4770 else
4771 {
4772 $credits = $credits_parent;
4773 }
4774
4775 // DESCRIPTION
4776 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4777 {
4778 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4779 }
4780 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4781 {
4782 $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4783 }
4784 else
4785 {
4786 $description = $description_parent;
4787 }
4788
4789 // HASHES
4790 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4791 {
4792 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4793 {
4794 $value = null;
4795 $algo = null;
4796 if (isset($hash['data']))
4797 {
4798 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4799 }
4800 if (isset($hash['attribs']['']['algo']))
4801 {
4802 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4803 }
4804 else
4805 {
4806 $algo = 'md5';
4807 }
4808 $hashes[] = $algo.':'.$value;
4809 }
4810 if (is_array($hashes))
4811 {
4812 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4813 }
4814 }
4815 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4816 {
4817 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4818 {
4819 $value = null;
4820 $algo = null;
4821 if (isset($hash['data']))
4822 {
4823 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4824 }
4825 if (isset($hash['attribs']['']['algo']))
4826 {
4827 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4828 }
4829 else
4830 {
4831 $algo = 'md5';
4832 }
4833 $hashes[] = $algo.':'.$value;
4834 }
4835 if (is_array($hashes))
4836 {
4837 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4838 }
4839 }
4840 else
4841 {
4842 $hashes = $hashes_parent;
4843 }
4844
4845 // KEYWORDS
4846 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4847 {
4848 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4849 {
4850 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4851 foreach ($temp as $word)
4852 {
4853 $keywords[] = trim($word);
4854 }
4855 unset($temp);
4856 }
4857 if (is_array($keywords))
4858 {
4859 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4860 }
4861 }
4862 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4863 {
4864 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4865 {
4866 $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4867 foreach ($temp as $word)
4868 {
4869 $keywords[] = trim($word);
4870 }
4871 unset($temp);
4872 }
4873 if (is_array($keywords))
4874 {
4875 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4876 }
4877 }
4878 else
4879 {
4880 $keywords = $keywords_parent;
4881 }
4882
4883 // PLAYER
4884 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4885 {
4886 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4887 }
4888 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4889 {
4890 $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4891 }
4892 else
4893 {
4894 $player = $player_parent;
4895 }
4896
4897 // RATINGS
4898 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4899 {
4900 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4901 {
4902 $rating_scheme = null;
4903 $rating_value = null;
4904 if (isset($rating['attribs']['']['scheme']))
4905 {
4906 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4907 }
4908 else
4909 {
4910 $rating_scheme = 'urn:simple';
4911 }
4912 if (isset($rating['data']))
4913 {
4914 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4915 }
4916 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4917 }
4918 if (is_array($ratings))
4919 {
4920 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4921 }
4922 }
4923 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4924 {
4925 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4926 {
4927 $rating_scheme = null;
4928 $rating_value = null;
4929 if (isset($rating['attribs']['']['scheme']))
4930 {
4931 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4932 }
4933 else
4934 {
4935 $rating_scheme = 'urn:simple';
4936 }
4937 if (isset($rating['data']))
4938 {
4939 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4940 }
4941 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4942 }
4943 if (is_array($ratings))
4944 {
4945 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4946 }
4947 }
4948 else
4949 {
4950 $ratings = $ratings_parent;
4951 }
4952
4953 // RESTRICTIONS
4954 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4955 {
4956 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4957 {
4958 $restriction_relationship = null;
4959 $restriction_type = null;
4960 $restriction_value = null;
4961 if (isset($restriction['attribs']['']['relationship']))
4962 {
4963 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4964 }
4965 if (isset($restriction['attribs']['']['type']))
4966 {
4967 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4968 }
4969 if (isset($restriction['data']))
4970 {
4971 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4972 }
4973 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4974 }
4975 if (is_array($restrictions))
4976 {
4977 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4978 }
4979 }
4980 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4981 {
4982 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4983 {
4984 $restriction_relationship = null;
4985 $restriction_type = null;
4986 $restriction_value = null;
4987 if (isset($restriction['attribs']['']['relationship']))
4988 {
4989 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4990 }
4991 if (isset($restriction['attribs']['']['type']))
4992 {
4993 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4994 }
4995 if (isset($restriction['data']))
4996 {
4997 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4998 }
4999 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5000 }
5001 if (is_array($restrictions))
5002 {
5003 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5004 }
5005 }
5006 else
5007 {
5008 $restrictions = $restrictions_parent;
5009 }
5010
5011 // THUMBNAILS
5012 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5013 {
5014 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5015 {
5016 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5017 }
5018 if (is_array($thumbnails))
5019 {
5020 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5021 }
5022 }
5023 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5024 {
5025 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5026 {
5027 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5028 }
5029 if (is_array($thumbnails))
5030 {
5031 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5032 }
5033 }
5034 else
5035 {
5036 $thumbnails = $thumbnails_parent;
5037 }
5038
5039 // TITLES
5040 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5041 {
5042 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5043 }
5044 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5045 {
5046 $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5047 }
5048 else
5049 {
5050 $title = $title_parent;
5051 }
5052
5053 $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);
5054 }
5055 }
5056 }
5057 }
5058
5059 // If we have standalone media:content tags, loop through them.
5060 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
5061 {
5062 foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
5063 {
5064 if (isset($content['attribs']['']['url']) || isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5065 {
5066 // Attributes
5067 $bitrate = null;
5068 $channels = null;
5069 $duration = null;
5070 $expression = null;
5071 $framerate = null;
5072 $height = null;
5073 $javascript = null;
5074 $lang = null;
5075 $length = null;
5076 $medium = null;
5077 $samplingrate = null;
5078 $type = null;
5079 $url = null;
5080 $width = null;
5081
5082 // Elements
5083 $captions = null;
5084 $categories = null;
5085 $copyrights = null;
5086 $credits = null;
5087 $description = null;
5088 $hashes = null;
5089 $keywords = null;
5090 $player = null;
5091 $ratings = null;
5092 $restrictions = null;
5093 $thumbnails = null;
5094 $title = null;
5095
5096 // Start checking the attributes of media:content
5097 if (isset($content['attribs']['']['bitrate']))
5098 {
5099 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5100 }
5101 if (isset($content['attribs']['']['channels']))
5102 {
5103 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
5104 }
5105 if (isset($content['attribs']['']['duration']))
5106 {
5107 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
5108 }
5109 else
5110 {
5111 $duration = $duration_parent;
5112 }
5113 if (isset($content['attribs']['']['expression']))
5114 {
5115 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
5116 }
5117 if (isset($content['attribs']['']['framerate']))
5118 {
5119 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
5120 }
5121 if (isset($content['attribs']['']['height']))
5122 {
5123 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
5124 }
5125 if (isset($content['attribs']['']['lang']))
5126 {
5127 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5128 }
5129 if (isset($content['attribs']['']['fileSize']))
5130 {
5131 $length = ceil($content['attribs']['']['fileSize']);
5132 }
5133 if (isset($content['attribs']['']['medium']))
5134 {
5135 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
5136 }
5137 if (isset($content['attribs']['']['samplingrate']))
5138 {
5139 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5140 }
5141 if (isset($content['attribs']['']['type']))
5142 {
5143 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5144 }
5145 if (isset($content['attribs']['']['width']))
5146 {
5147 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
5148 }
5149 if (isset($content['attribs']['']['url']))
5150 {
5151 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5152 }
5153 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
5154
5155 // CAPTIONS
5156 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
5157 {
5158 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
5159 {
5160 $caption_type = null;
5161 $caption_lang = null;
5162 $caption_startTime = null;
5163 $caption_endTime = null;
5164 $caption_text = null;
5165 if (isset($caption['attribs']['']['type']))
5166 {
5167 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5168 }
5169 if (isset($caption['attribs']['']['lang']))
5170 {
5171 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5172 }
5173 if (isset($caption['attribs']['']['start']))
5174 {
5175 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
5176 }
5177 if (isset($caption['attribs']['']['end']))
5178 {
5179 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
5180 }
5181 if (isset($caption['data']))
5182 {
5183 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5184 }
5185 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
5186 }
5187 if (is_array($captions))
5188 {
5189 $captions = array_values(SimplePie_Misc::array_unique($captions));
5190 }
5191 }
5192 else
5193 {
5194 $captions = $captions_parent;
5195 }
5196
5197 // CATEGORIES
5198 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
5199 {
5200 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
5201 {
5202 $term = null;
5203 $scheme = null;
5204 $label = null;
5205 if (isset($category['data']))
5206 {
5207 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5208 }
5209 if (isset($category['attribs']['']['scheme']))
5210 {
5211 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5212 }
5213 else
5214 {
5215 $scheme = 'http://search.yahoo.com/mrss/category_schema';
5216 }
5217 if (isset($category['attribs']['']['label']))
5218 {
5219 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5220 }
5221 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
5222 }
5223 }
5224 if (is_array($categories) && is_array($categories_parent))
5225 {
5226 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
5227 }
5228 elseif (is_array($categories))
5229 {
5230 $categories = array_values(SimplePie_Misc::array_unique($categories));
5231 }
5232 elseif (is_array($categories_parent))
5233 {
5234 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
5235 }
5236 else
5237 {
5238 $categories = null;
5239 }
5240
5241 // COPYRIGHTS
5242 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
5243 {
5244 $copyright_url = null;
5245 $copyright_label = null;
5246 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
5247 {
5248 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
5249 }
5250 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
5251 {
5252 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5253 }
5254 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
5255 }
5256 else
5257 {
5258 $copyrights = $copyrights_parent;
5259 }
5260
5261 // CREDITS
5262 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
5263 {
5264 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
5265 {
5266 $credit_role = null;
5267 $credit_scheme = null;
5268 $credit_name = null;
5269 if (isset($credit['attribs']['']['role']))
5270 {
5271 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
5272 }
5273 if (isset($credit['attribs']['']['scheme']))
5274 {
5275 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5276 }
5277 else
5278 {
5279 $credit_scheme = 'urn:ebu';
5280 }
5281 if (isset($credit['data']))
5282 {
5283 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5284 }
5285 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
5286 }
5287 if (is_array($credits))
5288 {
5289 $credits = array_values(SimplePie_Misc::array_unique($credits));
5290 }
5291 }
5292 else
5293 {
5294 $credits = $credits_parent;
5295 }
5296
5297 // DESCRIPTION
5298 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
5299 {
5300 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5301 }
5302 else
5303 {
5304 $description = $description_parent;
5305 }
5306
5307 // HASHES
5308 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
5309 {
5310 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
5311 {
5312 $value = null;
5313 $algo = null;
5314 if (isset($hash['data']))
5315 {
5316 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5317 }
5318 if (isset($hash['attribs']['']['algo']))
5319 {
5320 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
5321 }
5322 else
5323 {
5324 $algo = 'md5';
5325 }
5326 $hashes[] = $algo.':'.$value;
5327 }
5328 if (is_array($hashes))
5329 {
5330 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
5331 }
5332 }
5333 else
5334 {
5335 $hashes = $hashes_parent;
5336 }
5337
5338 // KEYWORDS
5339 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
5340 {
5341 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
5342 {
5343 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
5344 foreach ($temp as $word)
5345 {
5346 $keywords[] = trim($word);
5347 }
5348 unset($temp);
5349 }
5350 if (is_array($keywords))
5351 {
5352 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
5353 }
5354 }
5355 else
5356 {
5357 $keywords = $keywords_parent;
5358 }
5359
5360 // PLAYER
5361 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5362 {
5363 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5364 }
5365 else
5366 {
5367 $player = $player_parent;
5368 }
5369
5370 // RATINGS
5371 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
5372 {
5373 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
5374 {
5375 $rating_scheme = null;
5376 $rating_value = null;
5377 if (isset($rating['attribs']['']['scheme']))
5378 {
5379 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5380 }
5381 else
5382 {
5383 $rating_scheme = 'urn:simple';
5384 }
5385 if (isset($rating['data']))
5386 {
5387 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5388 }
5389 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
5390 }
5391 if (is_array($ratings))
5392 {
5393 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
5394 }
5395 }
5396 else
5397 {
5398 $ratings = $ratings_parent;
5399 }
5400
5401 // RESTRICTIONS
5402 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5403 {
5404 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5405 {
5406 $restriction_relationship = null;
5407 $restriction_type = null;
5408 $restriction_value = null;
5409 if (isset($restriction['attribs']['']['relationship']))
5410 {
5411 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5412 }
5413 if (isset($restriction['attribs']['']['type']))
5414 {
5415 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5416 }
5417 if (isset($restriction['data']))
5418 {
5419 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5420 }
5421 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5422 }
5423 if (is_array($restrictions))
5424 {
5425 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5426 }
5427 }
5428 else
5429 {
5430 $restrictions = $restrictions_parent;
5431 }
5432
5433 // THUMBNAILS
5434 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5435 {
5436 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5437 {
5438 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5439 }
5440 if (is_array($thumbnails))
5441 {
5442 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5443 }
5444 }
5445 else
5446 {
5447 $thumbnails = $thumbnails_parent;
5448 }
5449
5450 // TITLES
5451 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5452 {
5453 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5454 }
5455 else
5456 {
5457 $title = $title_parent;
5458 }
5459
5460 $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);
5461 }
5462 }
5463 }
5464
5465 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
5466 {
5467 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5468 {
5469 // Attributes
5470 $bitrate = null;
5471 $channels = null;
5472 $duration = null;
5473 $expression = null;
5474 $framerate = null;
5475 $height = null;
5476 $javascript = null;
5477 $lang = null;
5478 $length = null;
5479 $medium = null;
5480 $samplingrate = null;
5481 $type = null;
5482 $url = null;
5483 $width = null;
5484
5485 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5486 if (isset($link['attribs']['']['type']))
5487 {
5488 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5489 }
5490 if (isset($link['attribs']['']['length']))
5491 {
5492 $length = ceil($link['attribs']['']['length']);
5493 }
5494
5495 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5496 $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);
5497 }
5498 }
5499
5500 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5501 {
5502 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5503 {
5504 // Attributes
5505 $bitrate = null;
5506 $channels = null;
5507 $duration = null;
5508 $expression = null;
5509 $framerate = null;
5510 $height = null;
5511 $javascript = null;
5512 $lang = null;
5513 $length = null;
5514 $medium = null;
5515 $samplingrate = null;
5516 $type = null;
5517 $url = null;
5518 $width = null;
5519
5520 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5521 if (isset($link['attribs']['']['type']))
5522 {
5523 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5524 }
5525 if (isset($link['attribs']['']['length']))
5526 {
5527 $length = ceil($link['attribs']['']['length']);
5528 }
5529
5530 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5531 $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);
5532 }
5533 }
5534
5535 if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
5536 {
5537 if (isset($enclosure[0]['attribs']['']['url']))
5538 {
5539 // Attributes
5540 $bitrate = null;
5541 $channels = null;
5542 $duration = null;
5543 $expression = null;
5544 $framerate = null;
5545 $height = null;
5546 $javascript = null;
5547 $lang = null;
5548 $length = null;
5549 $medium = null;
5550 $samplingrate = null;
5551 $type = null;
5552 $url = null;
5553 $width = null;
5554
5555 $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5556 if (isset($enclosure[0]['attribs']['']['type']))
5557 {
5558 $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5559 }
5560 if (isset($enclosure[0]['attribs']['']['length']))
5561 {
5562 $length = ceil($enclosure[0]['attribs']['']['length']);
5563 }
5564
5565 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5566 $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);
5567 }
5568 }
5569
5570 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))
5571 {
5572 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5573 $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);
5574 }
5575
5576 $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5577 }
5578 if (!empty($this->data['enclosures']))
5579 {
5580 return $this->data['enclosures'];
5581 }
5582 else
5583 {
5584 return null;
5585 }
5586 }
5587
5588 function get_latitude()
5589 {
5590 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5591 {
5592 return (float) $return[0]['data'];
5593 }
5594 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))
5595 {
5596 return (float) $match[1];
5597 }
5598 else
5599 {
5600 return null;
5601 }
5602 }
5603
5604 function get_longitude()
5605 {
5606 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5607 {
5608 return (float) $return[0]['data'];
5609 }
5610 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5611 {
5612 return (float) $return[0]['data'];
5613 }
5614 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))
5615 {
5616 return (float) $match[2];
5617 }
5618 else
5619 {
5620 return null;
5621 }
5622 }
5623
5624 function get_source()
5625 {
5626 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5627 {
5628 return new $this->feed->source_class($this, $return[0]);
5629 }
5630 else
5631 {
5632 return null;
5633 }
5634 }
5635
5636 /**
5637 * Creates the add_to_* methods' return data
5638 *
5639 * @access private
5640 * @param string $item_url String to prefix to the item permalink
5641 * @param string $title_url String to prefix to the item title
5642 * (and suffix to the item permalink)
5643 * @return mixed URL if feed exists, false otherwise
5644 */
5645 function add_to_service($item_url, $title_url = null, $summary_url = null)
5646 {
5647 if ($this->get_permalink() !== null)
5648 {
5649 $return = $item_url . rawurlencode($this->get_permalink());
5650 if ($title_url !== null && $this->get_title() !== null)
5651 {
5652 $return .= $title_url . rawurlencode($this->get_title());
5653 }
5654 if ($summary_url !== null && $this->get_description() !== null)
5655 {
5656 $return .= $summary_url . rawurlencode($this->get_description());
5657 }
5658 return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
5659 }
5660 else
5661 {
5662 return null;
5663 }
5664 }
5665
5666 function add_to_blinklist()
5667 {
5668 return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5669 }
5670
5671 function add_to_blogmarks()
5672 {
5673 return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5674 }
5675
5676 function add_to_delicious()
5677 {
5678 return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
5679 }
5680
5681 function add_to_digg()
5682 {
5683 return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
5684 }
5685
5686 function add_to_furl()
5687 {
5688 return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5689 }
5690
5691 function add_to_magnolia()
5692 {
5693 return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5694 }
5695
5696 function add_to_myweb20()
5697 {
5698 return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5699 }
5700
5701 function add_to_newsvine()
5702 {
5703 return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5704 }
5705
5706 function add_to_reddit()
5707 {
5708 return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5709 }
5710
5711 function add_to_segnalo()
5712 {
5713 return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5714 }
5715
5716 function add_to_simpy()
5717 {
5718 return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5719 }
5720
5721 function add_to_spurl()
5722 {
5723 return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5724 }
5725
5726 function add_to_wists()
5727 {
5728 return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5729 }
5730
5731 function search_technorati()
5732 {
5733 return $this->add_to_service('http://www.technorati.com/search/');
5734 }
5735 }
5736
5737 class SimplePie_Source
5738 {
5739 var $item;
5740 var $data = array();
5741
5742 function SimplePie_Source($item, $data)
5743 {
5744 $this->item = $item;
5745 $this->data = $data;
5746 }
5747
5748 function __toString()
5749 {
5750 return md5(serialize($this->data));
5751 }
5752
5753 function get_source_tags($namespace, $tag)
5754 {
5755 if (isset($this->data['child'][$namespace][$tag]))
5756 {
5757 return $this->data['child'][$namespace][$tag];
5758 }
5759 else
5760 {
5761 return null;
5762 }
5763 }
5764
5765 function get_base($element = array())
5766 {
5767 return $this->item->get_base($element);
5768 }
5769
5770 function sanitize($data, $type, $base = '')
5771 {
5772 return $this->item->sanitize($data, $type, $base);
5773 }
5774
5775 function get_item()
5776 {
5777 return $this->item;
5778 }
5779
5780 function get_title()
5781 {
5782 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5783 {
5784 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5785 }
5786 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5787 {
5788 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5789 }
5790 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5791 {
5792 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5793 }
5794 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5795 {
5796 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5797 }
5798 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
5799 {
5800 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5801 }
5802 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5803 {
5804 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5805 }
5806 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5807 {
5808 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5809 }
5810 else
5811 {
5812 return null;
5813 }
5814 }
5815
5816 function get_category($key = 0)
5817 {
5818 $categories = $this->get_categories();
5819 if (isset($categories[$key]))
5820 {
5821 return $categories[$key];
5822 }
5823 else
5824 {
5825 return null;
5826 }
5827 }
5828
5829 function get_categories()
5830 {
5831 $categories = array();
5832
5833 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5834 {
5835 $term = null;
5836 $scheme = null;
5837 $label = null;
5838 if (isset($category['attribs']['']['term']))
5839 {
5840 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5841 }
5842 if (isset($category['attribs']['']['scheme']))
5843 {
5844 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5845 }
5846 if (isset($category['attribs']['']['label']))
5847 {
5848 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5849 }
5850 $categories[] =& new $this->item->feed->category_class($term, $scheme, $label);
5851 }
5852 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
5853 {
5854 // This is really the label, but keep this as the term also for BC.
5855 // Label will also work on retrieving because that falls back to term.
5856 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5857 if (isset($category['attribs']['']['domain']))
5858 {
5859 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
5860 }
5861 else
5862 {
5863 $scheme = null;
5864 }
5865 $categories[] =& new $this->item->feed->category_class($term, $scheme, null);
5866 }
5867 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5868 {
5869 $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5870 }
5871 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5872 {
5873 $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5874 }
5875
5876 if (!empty($categories))
5877 {
5878 return SimplePie_Misc::array_unique($categories);
5879 }
5880 else
5881 {
5882 return null;
5883 }
5884 }
5885
5886 function get_author($key = 0)
5887 {
5888 $authors = $this->get_authors();
5889 if (isset($authors[$key]))
5890 {
5891 return $authors[$key];
5892 }
5893 else
5894 {
5895 return null;
5896 }
5897 }
5898
5899 function get_authors()
5900 {
5901 $authors = array();
5902 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5903 {
5904 $name = null;
5905 $uri = null;
5906 $email = null;
5907 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5908 {
5909 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5910 }
5911 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5912 {
5913 $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]));
5914 }
5915 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5916 {
5917 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5918 }
5919 if ($name !== null || $email !== null || $uri !== null)
5920 {
5921 $authors[] =& new $this->item->feed->author_class($name, $uri, $email);
5922 }
5923 }
5924 if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5925 {
5926 $name = null;
5927 $url = null;
5928 $email = null;
5929 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5930 {
5931 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5932 }
5933 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5934 {
5935 $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]));
5936 }
5937 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5938 {
5939 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5940 }
5941 if ($name !== null || $email !== null || $url !== null)
5942 {
5943 $authors[] =& new $this->item->feed->author_class($name, $url, $email);
5944 }
5945 }
5946 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
5947 {
5948 $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5949 }
5950 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
5951 {
5952 $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5953 }
5954 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
5955 {
5956 $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5957 }
5958
5959 if (!empty($authors))
5960 {
5961 return SimplePie_Misc::array_unique($authors);
5962 }
5963 else
5964 {
5965 return null;
5966 }
5967 }
5968
5969 function get_contributor($key = 0)
5970 {
5971 $contributors = $this->get_contributors();
5972 if (isset($contributors[$key]))
5973 {
5974 return $contributors[$key];
5975 }
5976 else
5977 {
5978 return null;
5979 }
5980 }
5981
5982 function get_contributors()
5983 {
5984 $contributors = array();
5985 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
5986 {
5987 $name = null;
5988 $uri = null;
5989 $email = null;
5990 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5991 {
5992 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5993 }
5994 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5995 {
5996 $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]));
5997 }
5998 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5999 {
6000 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6001 }
6002 if ($name !== null || $email !== null || $uri !== null)
6003 {
6004 $contributors[] =& new $this->item->feed->author_class($name, $uri, $email);
6005 }
6006 }
6007 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
6008 {
6009 $name = null;
6010 $url = null;
6011 $email = null;
6012 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
6013 {
6014 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6015 }
6016 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
6017 {
6018 $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]));
6019 }
6020 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6021 {
6022 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6023 }
6024 if ($name !== null || $email !== null || $url !== null)
6025 {
6026 $contributors[] =& new $this->item->feed->author_class($name, $url, $email);
6027 }
6028 }
6029
6030 if (!empty($contributors))
6031 {
6032 return SimplePie_Misc::array_unique($contributors);
6033 }
6034 else
6035 {
6036 return null;
6037 }
6038 }
6039
6040 function get_link($key = 0, $rel = 'alternate')
6041 {
6042 $links = $this->get_links($rel);
6043 if (isset($links[$key]))
6044 {
6045 return $links[$key];
6046 }
6047 else
6048 {
6049 return null;
6050 }
6051 }
6052
6053 /**
6054 * Added for parity between the parent-level and the item/entry-level.
6055 */
6056 function get_permalink()
6057 {
6058 return $this->get_link(0);
6059 }
6060
6061 function get_links($rel = 'alternate')
6062 {
6063 if (!isset($this->data['links']))
6064 {
6065 $this->data['links'] = array();
6066 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
6067 {
6068 foreach ($links as $link)
6069 {
6070 if (isset($link['attribs']['']['href']))
6071 {
6072 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6073 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6074 }
6075 }
6076 }
6077 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
6078 {
6079 foreach ($links as $link)
6080 {
6081 if (isset($link['attribs']['']['href']))
6082 {
6083 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6084 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6085
6086 }
6087 }
6088 }
6089 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
6090 {
6091 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6092 }
6093 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
6094 {
6095 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6096 }
6097 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
6098 {
6099 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6100 }
6101
6102 $keys = array_keys($this->data['links']);
6103 foreach ($keys as $key)
6104 {
6105 if (SimplePie_Misc::is_isegment_nz_nc($key))
6106 {
6107 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
6108 {
6109 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
6110 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
6111 }
6112 else
6113 {
6114 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
6115 }
6116 }
6117 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
6118 {
6119 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
6120 }
6121 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
6122 }
6123 }
6124
6125 if (isset($this->data['links'][$rel]))
6126 {
6127 return $this->data['links'][$rel];
6128 }
6129 else
6130 {
6131 return null;
6132 }
6133 }
6134
6135 function get_description()
6136 {
6137 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
6138 {
6139 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6140 }
6141 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
6142 {
6143 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6144 }
6145 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
6146 {
6147 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6148 }
6149 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
6150 {
6151 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6152 }
6153 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
6154 {
6155 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6156 }
6157 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
6158 {
6159 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6160 }
6161 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
6162 {
6163 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6164 }
6165 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
6166 {
6167 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6168 }
6169 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
6170 {
6171 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6172 }
6173 else
6174 {
6175 return null;
6176 }
6177 }
6178
6179 function get_copyright()
6180 {
6181 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
6182 {
6183 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6184 }
6185 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
6186 {
6187 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6188 }
6189 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
6190 {
6191 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6192 }
6193 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
6194 {
6195 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6196 }
6197 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
6198 {
6199 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6200 }
6201 else
6202 {
6203 return null;
6204 }
6205 }
6206
6207 function get_language()
6208 {
6209 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
6210 {
6211 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6212 }
6213 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
6214 {
6215 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6216 }
6217 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
6218 {
6219 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6220 }
6221 elseif (isset($this->data['xml_lang']))
6222 {
6223 return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
6224 }
6225 else
6226 {
6227 return null;
6228 }
6229 }
6230
6231 function get_latitude()
6232 {
6233 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
6234 {
6235 return (float) $return[0]['data'];
6236 }
6237 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))
6238 {
6239 return (float) $match[1];
6240 }
6241 else
6242 {
6243 return null;
6244 }
6245 }
6246
6247 function get_longitude()
6248 {
6249 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
6250 {
6251 return (float) $return[0]['data'];
6252 }
6253 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
6254 {
6255 return (float) $return[0]['data'];
6256 }
6257 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))
6258 {
6259 return (float) $match[2];
6260 }
6261 else
6262 {
6263 return null;
6264 }
6265 }
6266
6267 function get_image_url()
6268 {
6269 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
6270 {
6271 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
6272 }
6273 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
6274 {
6275 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6276 }
6277 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
6278 {
6279 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6280 }
6281 else
6282 {
6283 return null;
6284 }
6285 }
6286 }
6287
6288 class SimplePie_Author
6289 {
6290 var $name;
6291 var $link;
6292 var $email;
6293
6294 // Constructor, used to input the data
6295 function SimplePie_Author($name = null, $link = null, $email = null)
6296 {
6297 $this->name = $name;
6298 $this->link = $link;
6299 $this->email = $email;
6300 }
6301
6302 function __toString()
6303 {
6304 // There is no $this->data here
6305 return md5(serialize($this));
6306 }
6307
6308 function get_name()
6309 {
6310 if ($this->name !== null)
6311 {
6312 return $this->name;
6313 }
6314 else
6315 {
6316 return null;
6317 }
6318 }
6319
6320 function get_link()
6321 {
6322 if ($this->link !== null)
6323 {
6324 return $this->link;
6325 }
6326 else
6327 {
6328 return null;
6329 }
6330 }
6331
6332 function get_email()
6333 {
6334 if ($this->email !== null)
6335 {
6336 return $this->email;
6337 }
6338 else
6339 {
6340 return null;
6341 }
6342 }
6343 }
6344
6345 class SimplePie_Category
6346 {
6347 var $term;
6348 var $scheme;
6349 var $label;
6350
6351 // Constructor, used to input the data
6352 function SimplePie_Category($term = null, $scheme = null, $label = null)
6353 {
6354 $this->term = $term;
6355 $this->scheme = $scheme;
6356 $this->label = $label;
6357 }
6358
6359 function __toString()
6360 {
6361 // There is no $this->data here
6362 return md5(serialize($this));
6363 }
6364
6365 function get_term()
6366 {
6367 if ($this->term !== null)
6368 {
6369 return $this->term;
6370 }
6371 else
6372 {
6373 return null;
6374 }
6375 }
6376
6377 function get_scheme()
6378 {
6379 if ($this->scheme !== null)
6380 {
6381 return $this->scheme;
6382 }
6383 else
6384 {
6385 return null;
6386 }
6387 }
6388
6389 function get_label()
6390 {
6391 if ($this->label !== null)
6392 {
6393 return $this->label;
6394 }
6395 else
6396 {
6397 return $this->get_term();
6398 }
6399 }
6400 }
6401
6402 class SimplePie_Enclosure
6403 {
6404 var $bitrate;
6405 var $captions;
6406 var $categories;
6407 var $channels;
6408 var $copyright;
6409 var $credits;
6410 var $description;
6411 var $duration;
6412 var $expression;
6413 var $framerate;
6414 var $handler;
6415 var $hashes;
6416 var $height;
6417 var $javascript;
6418 var $keywords;
6419 var $lang;
6420 var $length;
6421 var $link;
6422 var $medium;
6423 var $player;
6424 var $ratings;
6425 var $restrictions;
6426 var $samplingrate;
6427 var $thumbnails;
6428 var $title;
6429 var $type;
6430 var $width;
6431
6432 // Constructor, used to input the data
6433 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)
6434 {
6435 $this->bitrate = $bitrate;
6436 $this->captions = $captions;
6437 $this->categories = $categories;
6438 $this->channels = $channels;
6439 $this->copyright = $copyright;
6440 $this->credits = $credits;
6441 $this->description = $description;
6442 $this->duration = $duration;
6443 $this->expression = $expression;
6444 $this->framerate = $framerate;
6445 $this->hashes = $hashes;
6446 $this->height = $height;
6447 $this->javascript = $javascript;
6448 $this->keywords = $keywords;
6449 $this->lang = $lang;
6450 $this->length = $length;
6451 $this->link = $link;
6452 $this->medium = $medium;
6453 $this->player = $player;
6454 $this->ratings = $ratings;
6455 $this->restrictions = $restrictions;
6456 $this->samplingrate = $samplingrate;
6457 $this->thumbnails = $thumbnails;
6458 $this->title = $title;
6459 $this->type = $type;
6460 $this->width = $width;
6461 if (class_exists('idna_convert'))
6462 {
6463 $idn =& new idna_convert;
6464 $parsed = SimplePie_Misc::parse_url($link);
6465 $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6466 }
6467 $this->handler = $this->get_handler(); // Needs to load last
6468 }
6469
6470 function __toString()
6471 {
6472 // There is no $this->data here
6473 return md5(serialize($this));
6474 }
6475
6476 function get_bitrate()
6477 {
6478 if ($this->bitrate !== null)
6479 {
6480 return $this->bitrate;
6481 }
6482 else
6483 {
6484 return null;
6485 }
6486 }
6487
6488 function get_caption($key = 0)
6489 {
6490 $captions = $this->get_captions();
6491 if (isset($captions[$key]))
6492 {
6493 return $captions[$key];
6494 }
6495 else
6496 {
6497 return null;
6498 }
6499 }
6500
6501 function get_captions()
6502 {
6503 if ($this->captions !== null)
6504 {
6505 return $this->captions;
6506 }
6507 else
6508 {
6509 return null;
6510 }
6511 }
6512
6513 function get_category($key = 0)
6514 {
6515 $categories = $this->get_categories();
6516 if (isset($categories[$key]))
6517 {
6518 return $categories[$key];
6519 }
6520 else
6521 {
6522 return null;
6523 }
6524 }
6525
6526 function get_categories()
6527 {
6528 if ($this->categories !== null)
6529 {
6530 return $this->categories;
6531 }
6532 else
6533 {
6534 return null;
6535 }
6536 }
6537
6538 function get_channels()
6539 {
6540 if ($this->channels !== null)
6541 {
6542 return $this->channels;
6543 }
6544 else
6545 {
6546 return null;
6547 }
6548 }
6549
6550 function get_copyright()
6551 {
6552 if ($this->copyright !== null)
6553 {
6554 return $this->copyright;
6555 }
6556 else
6557 {
6558 return null;
6559 }
6560 }
6561
6562 function get_credit($key = 0)
6563 {
6564 $credits = $this->get_credits();
6565 if (isset($credits[$key]))
6566 {
6567 return $credits[$key];
6568 }
6569 else
6570 {
6571 return null;
6572 }
6573 }
6574
6575 function get_credits()
6576 {
6577 if ($this->credits !== null)
6578 {
6579 return $this->credits;
6580 }
6581 else
6582 {
6583 return null;
6584 }
6585 }
6586
6587 function get_description()
6588 {
6589 if ($this->description !== null)
6590 {
6591 return $this->description;
6592 }
6593 else
6594 {
6595 return null;
6596 }
6597 }
6598
6599 function get_duration($convert = false)
6600 {
6601 if ($this->duration !== null)
6602 {
6603 if ($convert)
6604 {
6605 $time = SimplePie_Misc::time_hms($this->duration);
6606 return $time;
6607 }
6608 else
6609 {
6610 return $this->duration;
6611 }
6612 }
6613 else
6614 {
6615 return null;
6616 }
6617 }
6618
6619 function get_expression()
6620 {
6621 if ($this->expression !== null)
6622 {
6623 return $this->expression;
6624 }
6625 else
6626 {
6627 return 'full';
6628 }
6629 }
6630
6631 function get_extension()
6632 {
6633 if ($this->link !== null)
6634 {
6635 $url = SimplePie_Misc::parse_url($this->link);
6636 if ($url['path'] !== '')
6637 {
6638 return pathinfo($url['path'], PATHINFO_EXTENSION);
6639 }
6640 }
6641 return null;
6642 }
6643
6644 function get_framerate()
6645 {
6646 if ($this->framerate !== null)
6647 {
6648 return $this->framerate;
6649 }
6650 else
6651 {
6652 return null;
6653 }
6654 }
6655
6656 function get_handler()
6657 {
6658 return $this->get_real_type(true);
6659 }
6660
6661 function get_hash($key = 0)
6662 {
6663 $hashes = $this->get_hashes();
6664 if (isset($hashes[$key]))
6665 {
6666 return $hashes[$key];
6667 }
6668 else
6669 {
6670 return null;
6671 }
6672 }
6673
6674 function get_hashes()
6675 {
6676 if ($this->hashes !== null)
6677 {
6678 return $this->hashes;
6679 }
6680 else
6681 {
6682 return null;
6683 }
6684 }
6685
6686 function get_height()
6687 {
6688 if ($this->height !== null)
6689 {
6690 return $this->height;
6691 }
6692 else
6693 {
6694 return null;
6695 }
6696 }
6697
6698 function get_language()
6699 {
6700 if ($this->lang !== null)
6701 {
6702 return $this->lang;
6703 }
6704 else
6705 {
6706 return null;
6707 }
6708 }
6709
6710 function get_keyword($key = 0)
6711 {
6712 $keywords = $this->get_keywords();
6713 if (isset($keywords[$key]))
6714 {
6715 return $keywords[$key];
6716 }
6717 else
6718 {
6719 return null;
6720 }
6721 }
6722
6723 function get_keywords()
6724 {
6725 if ($this->keywords !== null)
6726 {
6727 return $this->keywords;
6728 }
6729 else
6730 {
6731 return null;
6732 }
6733 }
6734
6735 function get_length()
6736 {
6737 if ($this->length !== null)
6738 {
6739 return $this->length;
6740 }
6741 else
6742 {
6743 return null;
6744 }
6745 }
6746
6747 function get_link()
6748 {
6749 if ($this->link !== null)
6750 {
6751 return urldecode($this->link);
6752 }
6753 else
6754 {
6755 return null;
6756 }
6757 }
6758
6759 function get_medium()
6760 {
6761 if ($this->medium !== null)
6762 {
6763 return $this->medium;
6764 }
6765 else
6766 {
6767 return null;
6768 }
6769 }
6770
6771 function get_player()
6772 {
6773 if ($this->player !== null)
6774 {
6775 return $this->player;
6776 }
6777 else
6778 {
6779 return null;
6780 }
6781 }
6782
6783 function get_rating($key = 0)
6784 {
6785 $ratings = $this->get_ratings();
6786 if (isset($ratings[$key]))
6787 {
6788 return $ratings[$key];
6789 }
6790 else
6791 {
6792 return null;
6793 }
6794 }
6795
6796 function get_ratings()
6797 {
6798 if ($this->ratings !== null)
6799 {
6800 return $this->ratings;
6801 }
6802 else
6803 {
6804 return null;
6805 }
6806 }
6807
6808 function get_restriction($key = 0)
6809 {
6810 $restrictions = $this->get_restrictions();
6811 if (isset($restrictions[$key]))
6812 {
6813 return $restrictions[$key];
6814 }
6815 else
6816 {
6817 return null;
6818 }
6819 }
6820
6821 function get_restrictions()
6822 {
6823 if ($this->restrictions !== null)
6824 {
6825 return $this->restrictions;
6826 }
6827 else
6828 {
6829 return null;
6830 }
6831 }
6832
6833 function get_sampling_rate()
6834 {
6835 if ($this->samplingrate !== null)
6836 {
6837 return $this->samplingrate;
6838 }
6839 else
6840 {
6841 return null;
6842 }
6843 }
6844
6845 function get_size()
6846 {
6847 $length = $this->get_length();
6848 if ($length !== null)
6849 {
6850 return round($length/1048576, 2);
6851 }
6852 else
6853 {
6854 return null;
6855 }
6856 }
6857
6858 function get_thumbnail($key = 0)
6859 {
6860 $thumbnails = $this->get_thumbnails();
6861 if (isset($thumbnails[$key]))
6862 {
6863 return $thumbnails[$key];
6864 }
6865 else
6866 {
6867 return null;
6868 }
6869 }
6870
6871 function get_thumbnails()
6872 {
6873 if ($this->thumbnails !== null)
6874 {
6875 return $this->thumbnails;
6876 }
6877 else
6878 {
6879 return null;
6880 }
6881 }
6882
6883 function get_title()
6884 {
6885 if ($this->title !== null)
6886 {
6887 return $this->title;
6888 }
6889 else
6890 {
6891 return null;
6892 }
6893 }
6894
6895 function get_type()
6896 {
6897 if ($this->type !== null)
6898 {
6899 return $this->type;
6900 }
6901 else
6902 {
6903 return null;
6904 }
6905 }
6906
6907 function get_width()
6908 {
6909 if ($this->width !== null)
6910 {
6911 return $this->width;
6912 }
6913 else
6914 {
6915 return null;
6916 }
6917 }
6918
6919 function native_embed($options='')
6920 {
6921 return $this->embed($options, true);
6922 }
6923
6924 /**
6925 * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
6926 */
6927 function embed($options = '', $native = false)
6928 {
6929 // Set up defaults
6930 $audio = '';
6931 $video = '';
6932 $alt = '';
6933 $altclass = '';
6934 $loop = 'false';
6935 $width = 'auto';
6936 $height = 'auto';
6937 $bgcolor = '#ffffff';
6938 $mediaplayer = '';
6939 $widescreen = false;
6940 $handler = $this->get_handler();
6941 $type = $this->get_real_type();
6942
6943 // Process options and reassign values as necessary
6944 if (is_array($options))
6945 {
6946 extract($options);
6947 }
6948 else
6949 {
6950 $options = explode(',', $options);
6951 foreach($options as $option)
6952 {
6953 $opt = explode(':', $option, 2);
6954 if (isset($opt[0], $opt[1]))
6955 {
6956 $opt[0] = trim($opt[0]);
6957 $opt[1] = trim($opt[1]);
6958 switch ($opt[0])
6959 {
6960 case 'audio':
6961 $audio = $opt[1];
6962 break;
6963
6964 case 'video':
6965 $video = $opt[1];
6966 break;
6967
6968 case 'alt':
6969 $alt = $opt[1];
6970 break;
6971
6972 case 'altclass':
6973 $altclass = $opt[1];
6974 break;
6975
6976 case 'loop':
6977 $loop = $opt[1];
6978 break;
6979
6980 case 'width':
6981 $width = $opt[1];
6982 break;
6983
6984 case 'height':
6985 $height = $opt[1];
6986 break;
6987
6988 case 'bgcolor':
6989 $bgcolor = $opt[1];
6990 break;
6991
6992 case 'mediaplayer':
6993 $mediaplayer = $opt[1];
6994 break;
6995
6996 case 'widescreen':
6997 $widescreen = $opt[1];
6998 break;
6999 }
7000 }
7001 }
7002 }
7003
7004 $mime = explode('/', $type, 2);
7005 $mime = $mime[0];
7006
7007 // Process values for 'auto'
7008 if ($width === 'auto')
7009 {
7010 if ($mime === 'video')
7011 {
7012 if ($height === 'auto')
7013 {
7014 $width = 480;
7015 }
7016 elseif ($widescreen)
7017 {
7018 $width = round((intval($height)/9)*16);
7019 }
7020 else
7021 {
7022 $width = round((intval($height)/3)*4);
7023 }
7024 }
7025 else
7026 {
7027 $width = '100%';
7028 }
7029 }
7030
7031 if ($height === 'auto')
7032 {
7033 if ($mime === 'audio')
7034 {
7035 $height = 0;
7036 }
7037 elseif ($mime === 'video')
7038 {
7039 if ($width === 'auto')
7040 {
7041 if ($widescreen)
7042 {
7043 $height = 270;
7044 }
7045 else
7046 {
7047 $height = 360;
7048 }
7049 }
7050 elseif ($widescreen)
7051 {
7052 $height = round((intval($width)/16)*9);
7053 }
7054 else
7055 {
7056 $height = round((intval($width)/4)*3);
7057 }
7058 }
7059 else
7060 {
7061 $height = 376;
7062 }
7063 }
7064 elseif ($mime === 'audio')
7065 {
7066 $height = 0;
7067 }
7068
7069 // Set proper placeholder value
7070 if ($mime === 'audio')
7071 {
7072 $placeholder = $audio;
7073 }
7074 elseif ($mime === 'video')
7075 {
7076 $placeholder = $video;
7077 }
7078
7079 $embed = '';
7080
7081 // Make sure the JS library is included
7082 if (!$native)
7083 {
7084 static $javascript_outputted = null;
7085 if (!$javascript_outputted && $this->javascript)
7086 {
7087 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
7088 $javascript_outputted = true;
7089 }
7090 }
7091
7092 // Odeo Feed MP3's
7093 if ($handler === 'odeo')
7094 {
7095 if ($native)
7096 {
7097 $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>';
7098 }
7099 else
7100 {
7101 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
7102 }
7103 }
7104
7105 // Flash
7106 elseif ($handler === 'flash')
7107 {
7108 if ($native)
7109 {
7110 $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>";
7111 }
7112 else
7113 {
7114 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
7115 }
7116 }
7117
7118 // Flash Media Player file types.
7119 // Preferred handler for MP3 file types.
7120 elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
7121 {
7122 $height += 20;
7123 if ($native)
7124 {
7125 $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>";
7126 }
7127 else
7128 {
7129 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7130 }
7131 }
7132
7133 // QuickTime 7 file types. Need to test with QuickTime 6.
7134 // Only handle MP3's if the Flash Media Player is not present.
7135 elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
7136 {
7137 $height += 16;
7138 if ($native)
7139 {
7140 if ($placeholder !== '')
7141 {
7142 $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>";
7143 }
7144 else
7145 {
7146 $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>";
7147 }
7148 }
7149 else
7150 {
7151 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7152 }
7153 }
7154
7155 // Windows Media
7156 elseif ($handler === 'wmedia')
7157 {
7158 $height += 45;
7159 if ($native)
7160 {
7161 $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>";
7162 }
7163 else
7164 {
7165 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7166 }
7167 }
7168
7169 // Everything else
7170 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7171
7172 return $embed;
7173 }
7174
7175 function get_real_type($find_handler = false)
7176 {
7177 // If it's Odeo, let's get it out of the way.
7178 if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
7179 {
7180 return 'odeo';
7181 }
7182
7183 // Mime-types by handler.
7184 $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
7185 $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
7186 $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
7187 $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
7188 $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7189
7190 if ($this->get_type() !== null)
7191 {
7192 $type = strtolower($this->type);
7193 }
7194 else
7195 {
7196 $type = null;
7197 }
7198
7199 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7200 if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7201 {
7202 switch (strtolower($this->get_extension()))
7203 {
7204 // Audio mime-types
7205 case 'aac':
7206 case 'adts':
7207 $type = 'audio/acc';
7208 break;
7209
7210 case 'aif':
7211 case 'aifc':
7212 case 'aiff':
7213 case 'cdda':
7214 $type = 'audio/aiff';
7215 break;
7216
7217 case 'bwf':
7218 $type = 'audio/wav';
7219 break;
7220
7221 case 'kar':
7222 case 'mid':
7223 case 'midi':
7224 case 'smf':
7225 $type = 'audio/midi';
7226 break;
7227
7228 case 'm4a':
7229 $type = 'audio/x-m4a';
7230 break;
7231
7232 case 'mp3':
7233 case 'swa':
7234 $type = 'audio/mp3';
7235 break;
7236
7237 case 'wav':
7238 $type = 'audio/wav';
7239 break;
7240
7241 case 'wax':
7242 $type = 'audio/x-ms-wax';
7243 break;
7244
7245 case 'wma':
7246 $type = 'audio/x-ms-wma';
7247 break;
7248
7249 // Video mime-types
7250 case '3gp':
7251 case '3gpp':
7252 $type = 'video/3gpp';
7253 break;
7254
7255 case '3g2':
7256 case '3gp2':
7257 $type = 'video/3gpp2';
7258 break;
7259
7260 case 'asf':
7261 $type = 'video/x-ms-asf';
7262 break;
7263
7264 case 'flv':
7265 $type = 'video/x-flv';
7266 break;
7267
7268 case 'm1a':
7269 case 'm1s':
7270 case 'm1v':
7271 case 'm15':
7272 case 'm75':
7273 case 'mp2':
7274 case 'mpa':
7275 case 'mpeg':
7276 case 'mpg':
7277 case 'mpm':
7278 case 'mpv':
7279 $type = 'video/mpeg';
7280 break;
7281
7282 case 'm4v':
7283 $type = 'video/x-m4v';
7284 break;
7285
7286 case 'mov':
7287 case 'qt':
7288 $type = 'video/quicktime';
7289 break;
7290
7291 case 'mp4':
7292 case 'mpg4':
7293 $type = 'video/mp4';
7294 break;
7295
7296 case 'sdv':
7297 $type = 'video/sd-video';
7298 break;
7299
7300 case 'wm':
7301 $type = 'video/x-ms-wm';
7302 break;
7303
7304 case 'wmv':
7305 $type = 'video/x-ms-wmv';
7306 break;
7307
7308 case 'wvx':
7309 $type = 'video/x-ms-wvx';
7310 break;
7311
7312 // Flash mime-types
7313 case 'spl':
7314 $type = 'application/futuresplash';
7315 break;
7316
7317 case 'swf':
7318 $type = 'application/x-shockwave-flash';
7319 break;
7320 }
7321 }
7322
7323 if ($find_handler)
7324 {
7325 if (in_array($type, $types_flash))
7326 {
7327 return 'flash';
7328 }
7329 elseif (in_array($type, $types_fmedia))
7330 {
7331 return 'fmedia';
7332 }
7333 elseif (in_array($type, $types_quicktime))
7334 {
7335 return 'quicktime';
7336 }
7337 elseif (in_array($type, $types_wmedia))
7338 {
7339 return 'wmedia';
7340 }
7341 elseif (in_array($type, $types_mp3))
7342 {
7343 return 'mp3';
7344 }
7345 else
7346 {
7347 return null;
7348 }
7349 }
7350 else
7351 {
7352 return $type;
7353 }
7354 }
7355 }
7356
7357 class SimplePie_Caption
7358 {
7359 var $type;
7360 var $lang;
7361 var $startTime;
7362 var $endTime;
7363 var $text;
7364
7365 // Constructor, used to input the data
7366 function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7367 {
7368 $this->type = $type;
7369 $this->lang = $lang;
7370 $this->startTime = $startTime;
7371 $this->endTime = $endTime;
7372 $this->text = $text;
7373 }
7374
7375 function __toString()
7376 {
7377 // There is no $this->data here
7378 return md5(serialize($this));
7379 }
7380
7381 function get_endtime()
7382 {
7383 if ($this->endTime !== null)
7384 {
7385 return $this->endTime;
7386 }
7387 else
7388 {
7389 return null;
7390 }
7391 }
7392
7393 function get_language()
7394 {
7395 if ($this->lang !== null)
7396 {
7397 return $this->lang;
7398 }
7399 else
7400 {
7401 return null;
7402 }
7403 }
7404
7405 function get_starttime()
7406 {
7407 if ($this->startTime !== null)
7408 {
7409 return $this->startTime;
7410 }
7411 else
7412 {
7413 return null;
7414 }
7415 }
7416
7417 function get_text()
7418 {
7419 if ($this->text !== null)
7420 {
7421 return $this->text;
7422 }
7423 else
7424 {
7425 return null;
7426 }
7427 }
7428
7429 function get_type()
7430 {
7431 if ($this->type !== null)
7432 {
7433 return $this->type;
7434 }
7435 else
7436 {
7437 return null;
7438 }
7439 }
7440 }
7441
7442 class SimplePie_Credit
7443 {
7444 var $role;
7445 var $scheme;
7446 var $name;
7447
7448 // Constructor, used to input the data
7449 function SimplePie_Credit($role = null, $scheme = null, $name = null)
7450 {
7451 $this->role = $role;
7452 $this->scheme = $scheme;
7453 $this->name = $name;
7454 }
7455
7456 function __toString()
7457 {
7458 // There is no $this->data here
7459 return md5(serialize($this));
7460 }
7461
7462 function get_role()
7463 {
7464 if ($this->role !== null)
7465 {
7466 return $this->role;
7467 }
7468 else
7469 {
7470 return null;
7471 }
7472 }
7473
7474 function get_scheme()
7475 {
7476 if ($this->scheme !== null)
7477 {
7478 return $this->scheme;
7479 }
7480 else
7481 {
7482 return null;
7483 }
7484 }
7485
7486 function get_name()
7487 {
7488 if ($this->name !== null)
7489 {
7490 return $this->name;
7491 }
7492 else
7493 {
7494 return null;
7495 }
7496 }
7497 }
7498
7499 class SimplePie_Copyright
7500 {
7501 var $url;
7502 var $label;
7503
7504 // Constructor, used to input the data
7505 function SimplePie_Copyright($url = null, $label = null)
7506 {
7507 $this->url = $url;
7508 $this->label = $label;
7509 }
7510
7511 function __toString()
7512 {
7513 // There is no $this->data here
7514 return md5(serialize($this));
7515 }
7516
7517 function get_url()
7518 {
7519 if ($this->url !== null)
7520 {
7521 return $this->url;
7522 }
7523 else
7524 {
7525 return null;
7526 }
7527 }
7528
7529 function get_attribution()
7530 {
7531 if ($this->label !== null)
7532 {
7533 return $this->label;
7534 }
7535 else
7536 {
7537 return null;
7538 }
7539 }
7540 }
7541
7542 class SimplePie_Rating
7543 {
7544 var $scheme;
7545 var $value;
7546
7547 // Constructor, used to input the data
7548 function SimplePie_Rating($scheme = null, $value = null)
7549 {
7550 $this->scheme = $scheme;
7551 $this->value = $value;
7552 }
7553
7554 function __toString()
7555 {
7556 // There is no $this->data here
7557 return md5(serialize($this));
7558 }
7559
7560 function get_scheme()
7561 {
7562 if ($this->scheme !== null)
7563 {
7564 return $this->scheme;
7565 }
7566 else
7567 {
7568 return null;
7569 }
7570 }
7571
7572 function get_value()
7573 {
7574 if ($this->value !== null)
7575 {
7576 return $this->value;
7577 }
7578 else
7579 {
7580 return null;
7581 }
7582 }
7583 }
7584
7585 class SimplePie_Restriction
7586 {
7587 var $relationship;
7588 var $type;
7589 var $value;
7590
7591 // Constructor, used to input the data
7592 function SimplePie_Restriction($relationship = null, $type = null, $value = null)
7593 {
7594 $this->relationship = $relationship;
7595 $this->type = $type;
7596 $this->value = $value;
7597 }
7598
7599 function __toString()
7600 {
7601 // There is no $this->data here
7602 return md5(serialize($this));
7603 }
7604
7605 function get_relationship()
7606 {
7607 if ($this->relationship !== null)
7608 {
7609 return $this->relationship;
7610 }
7611 else
7612 {
7613 return null;
7614 }
7615 }
7616
7617 function get_type()
7618 {
7619 if ($this->type !== null)
7620 {
7621 return $this->type;
7622 }
7623 else
7624 {
7625 return null;
7626 }
7627 }
7628
7629 function get_value()
7630 {
7631 if ($this->value !== null)
7632 {
7633 return $this->value;
7634 }
7635 else
7636 {
7637 return null;
7638 }
7639 }
7640 }
7641
7642 /**
7643 * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7644 */
7645 class SimplePie_File
7646 {
7647 var $url;
7648 var $useragent;
7649 var $success = true;
7650 var $headers = array();
7651 var $body;
7652 var $status_code;
7653 var $redirects = 0;
7654 var $error;
7655 var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7656
7657 function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7658 {
7659 if (class_exists('idna_convert'))
7660 {
7661 $idn =& new idna_convert;
7662 $parsed = SimplePie_Misc::parse_url($url);
7663 $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7664 }
7665 $this->url = $url;
7666 $this->useragent = $useragent;
7667 if (preg_match('/^http(s)?:\/\//i', $url))
7668 {
7669 if ($useragent === null)
7670 {
7671 $useragent = ini_get('user_agent');
7672 $this->useragent = $useragent;
7673 }
7674 if (!is_array($headers))
7675 {
7676 $headers = array();
7677 }
7678 if (!$force_fsockopen && function_exists('curl_exec'))
7679 {
7680 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7681 $fp = curl_init();
7682 $headers2 = array();
7683 foreach ($headers as $key => $value)
7684 {
7685 $headers2[] = "$key: $value";
7686 }
7687 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7688 {
7689 curl_setopt($fp, CURLOPT_ENCODING, '');
7690 }
7691 curl_setopt($fp, CURLOPT_URL, $url);
7692 curl_setopt($fp, CURLOPT_HEADER, 1);
7693 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7694 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7695 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7696 curl_setopt($fp, CURLOPT_REFERER, $url);
7697 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7698 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7699 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7700 {
7701 curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7702 curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7703 }
7704
7705 /* Enable Digest authentication and SSL -fox */
7706 curl_setopt($fp, CURLOPT_SSL_VERIFYPEER, false);
7707 curl_setopt($fp, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
7708
7709 $this->headers = curl_exec($fp);
7710 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7711 {
7712 curl_setopt($fp, CURLOPT_ENCODING, 'none');
7713 $this->headers = curl_exec($fp);
7714 }
7715 if (curl_errno($fp))
7716 {
7717 $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7718 $this->success = false;
7719 }
7720 else
7721 {
7722 $info = curl_getinfo($fp);
7723 curl_close($fp);
7724 $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7725 $this->headers = array_pop($this->headers);
7726 $parser =& new SimplePie_HTTP_Parser($this->headers);
7727 if ($parser->parse())
7728 {
7729 $this->headers = $parser->headers;
7730 $this->body = $parser->body;
7731 $this->status_code = $parser->status_code;
7732 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)
7733 {
7734 $this->redirects++;
7735 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7736 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7737 }
7738 }
7739 }
7740 }
7741 else
7742 {
7743 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7744 $url_parts = parse_url($url);
7745 $socket_host = $url_parts['host'];
7746 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7747 {
7748 $socket_host = "ssl://$url_parts[host]";
7749 $url_parts['port'] = 443;
7750 }
7751 if (!isset($url_parts['port']))
7752 {
7753 $url_parts['port'] = 80;
7754 }
7755 $fp = @fsockopen($socket_host, $url_parts['port'], $errno, $errstr, $timeout);
7756 if (!$fp)
7757 {
7758 $this->error = 'fsockopen error: ' . $errstr;
7759 $this->success = false;
7760 }
7761 else
7762 {
7763 stream_set_timeout($fp, $timeout);
7764 if (isset($url_parts['path']))
7765 {
7766 if (isset($url_parts['query']))
7767 {
7768 $get = "$url_parts[path]?$url_parts[query]";
7769 }
7770 else
7771 {
7772 $get = $url_parts['path'];
7773 }
7774 }
7775 else
7776 {
7777 $get = '/';
7778 }
7779 $out = "GET $get HTTP/1.0\r\n";
7780 $out .= "Host: $url_parts[host]\r\n";
7781 $out .= "User-Agent: $useragent\r\n";
7782 if (extension_loaded('zlib'))
7783 {
7784 $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7785 }
7786
7787 if (isset($url_parts['user']) && isset($url_parts['pass']))
7788 {
7789 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7790 }
7791 foreach ($headers as $key => $value)
7792 {
7793 $out .= "$key: $value\r\n";
7794 }
7795 $out .= "Connection: Close\r\n\r\n";
7796 fwrite($fp, $out);
7797
7798 $info = stream_get_meta_data($fp);
7799
7800 $this->headers = '';
7801 while (!$info['eof'] && !$info['timed_out'])
7802 {
7803 $this->headers .= fread($fp, 1160);
7804 $info = stream_get_meta_data($fp);
7805 }
7806 if (!$info['timed_out'])
7807 {
7808 $parser =& new SimplePie_HTTP_Parser($this->headers);
7809 if ($parser->parse())
7810 {
7811 $this->headers = $parser->headers;
7812 $this->body = $parser->body;
7813 $this->status_code = $parser->status_code;
7814 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)
7815 {
7816 $this->redirects++;
7817 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7818 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7819 }
7820 if (isset($this->headers['content-encoding']))
7821 {
7822 // Hey, we act dumb elsewhere, so let's do that here too
7823 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7824 {
7825 case 'gzip':
7826 case 'x-gzip':
7827 $decoder =& new SimplePie_gzdecode($this->body);
7828 if (!$decoder->parse())
7829 {
7830 $this->error = 'Unable to decode HTTP "gzip" stream';
7831 $this->success = false;
7832 }
7833 else
7834 {
7835 $this->body = $decoder->data;
7836 }
7837 break;
7838
7839 case 'deflate':
7840 if (($body = gzuncompress($this->body)) === false)
7841 {
7842 if (($body = gzinflate($this->body)) === false)
7843 {
7844 $this->error = 'Unable to decode HTTP "deflate" stream';
7845 $this->success = false;
7846 }
7847 }
7848 $this->body = $body;
7849 break;
7850
7851 default:
7852 $this->error = 'Unknown content coding';
7853 $this->success = false;
7854 }
7855 }
7856 }
7857 }
7858 else
7859 {
7860 $this->error = 'fsocket timed out';
7861 $this->success = false;
7862 }
7863 fclose($fp);
7864 }
7865 }
7866 }
7867 else
7868 {
7869 $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7870 if (!$this->body = file_get_contents($url))
7871 {
7872 $this->error = 'file_get_contents could not read the file';
7873 $this->success = false;
7874 }
7875 }
7876 }
7877 }
7878
7879 /**
7880 * HTTP Response Parser
7881 *
7882 * @package SimplePie
7883 */
7884 class SimplePie_HTTP_Parser
7885 {
7886 /**
7887 * HTTP Version
7888 *
7889 * @access public
7890 * @var float
7891 */
7892 var $http_version = 0.0;
7893
7894 /**
7895 * Status code
7896 *
7897 * @access public
7898 * @var int
7899 */
7900 var $status_code = 0;
7901
7902 /**
7903 * Reason phrase
7904 *
7905 * @access public
7906 * @var string
7907 */
7908 var $reason = '';
7909
7910 /**
7911 * Key/value pairs of the headers
7912 *
7913 * @access public
7914 * @var array
7915 */
7916 var $headers = array();
7917
7918 /**
7919 * Body of the response
7920 *
7921 * @access public
7922 * @var string
7923 */
7924 var $body = '';
7925
7926 /**
7927 * Current state of the state machine
7928 *
7929 * @access private
7930 * @var string
7931 */
7932 var $state = 'http_version';
7933
7934 /**
7935 * Input data
7936 *
7937 * @access private
7938 * @var string
7939 */
7940 var $data = '';
7941
7942 /**
7943 * Input data length (to avoid calling strlen() everytime this is needed)
7944 *
7945 * @access private
7946 * @var int
7947 */
7948 var $data_length = 0;
7949
7950 /**
7951 * Current position of the pointer
7952 *
7953 * @var int
7954 * @access private
7955 */
7956 var $position = 0;
7957
7958 /**
7959 * Name of the hedaer currently being parsed
7960 *
7961 * @access private
7962 * @var string
7963 */
7964 var $name = '';
7965
7966 /**
7967 * Value of the hedaer currently being parsed
7968 *
7969 * @access private
7970 * @var string
7971 */
7972 var $value = '';
7973
7974 /**
7975 * Create an instance of the class with the input data
7976 *
7977 * @access public
7978 * @param string $data Input data
7979 */
7980 function SimplePie_HTTP_Parser($data)
7981 {
7982 $this->data = $data;
7983 $this->data_length = strlen($this->data);
7984 }
7985
7986 /**
7987 * Parse the input data
7988 *
7989 * @access public
7990 * @return bool true on success, false on failure
7991 */
7992 function parse()
7993 {
7994 while ($this->state && $this->state !== 'emit' && $this->has_data())
7995 {
7996 $state = $this->state;
7997 $this->$state();
7998 }
7999 $this->data = '';
8000 if ($this->state === 'emit' || $this->state === 'body')
8001 {
8002 return true;
8003 }
8004 else
8005 {
8006 $this->http_version = '';
8007 $this->status_code = '';
8008 $this->reason = '';
8009 $this->headers = array();
8010 $this->body = '';
8011 return false;
8012 }
8013 }
8014
8015 /**
8016 * Check whether there is data beyond the pointer
8017 *
8018 * @access private
8019 * @return bool true if there is further data, false if not
8020 */
8021 function has_data()
8022 {
8023 return (bool) ($this->position < $this->data_length);
8024 }
8025
8026 /**
8027 * See if the next character is LWS
8028 *
8029 * @access private
8030 * @return bool true if the next character is LWS, false if not
8031 */
8032 function is_linear_whitespace()
8033 {
8034 return (bool) ($this->data[$this->position] === "\x09"
8035 || $this->data[$this->position] === "\x20"
8036 || ($this->data[$this->position] === "\x0A"
8037 && isset($this->data[$this->position + 1])
8038 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
8039 }
8040
8041 /**
8042 * Parse the HTTP version
8043 *
8044 * @access private
8045 */
8046 function http_version()
8047 {
8048 if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
8049 {
8050 $len = strspn($this->data, '0123456789.', 5);
8051 $this->http_version = substr($this->data, 5, $len);
8052 $this->position += 5 + $len;
8053 if (substr_count($this->http_version, '.') <= 1)
8054 {
8055 $this->http_version = (float) $this->http_version;
8056 $this->position += strspn($this->data, "\x09\x20", $this->position);
8057 $this->state = 'status';
8058 }
8059 else
8060 {
8061 $this->state = false;
8062 }
8063 }
8064 else
8065 {
8066 $this->state = false;
8067 }
8068 }
8069
8070 /**
8071 * Parse the status code
8072 *
8073 * @access private
8074 */
8075 function status()
8076 {
8077 if ($len = strspn($this->data, '0123456789', $this->position))
8078 {
8079 $this->status_code = (int) substr($this->data, $this->position, $len);
8080 $this->position += $len;
8081 $this->state = 'reason';
8082 }
8083 else
8084 {
8085 $this->state = false;
8086 }
8087 }
8088
8089 /**
8090 * Parse the reason phrase
8091 *
8092 * @access private
8093 */
8094 function reason()
8095 {
8096 $len = strcspn($this->data, "\x0A", $this->position);
8097 $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
8098 $this->position += $len + 1;
8099 $this->state = 'new_line';
8100 }
8101
8102 /**
8103 * Deal with a new line, shifting data around as needed
8104 *
8105 * @access private
8106 */
8107 function new_line()
8108 {
8109 $this->value = trim($this->value, "\x0D\x20");
8110 if ($this->name !== '' && $this->value !== '')
8111 {
8112 $this->name = strtolower($this->name);
8113 if (isset($this->headers[$this->name]))
8114 {
8115 $this->headers[$this->name] .= ', ' . $this->value;
8116 }
8117 else
8118 {
8119 $this->headers[$this->name] = $this->value;
8120 }
8121 }
8122 $this->name = '';
8123 $this->value = '';
8124 if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
8125 {
8126 $this->position += 2;
8127 $this->state = 'body';
8128 }
8129 elseif ($this->data[$this->position] === "\x0A")
8130 {
8131 $this->position++;
8132 $this->state = 'body';
8133 }
8134 else
8135 {
8136 $this->state = 'name';
8137 }
8138 }
8139
8140 /**
8141 * Parse a header name
8142 *
8143 * @access private
8144 */
8145 function name()
8146 {
8147 $len = strcspn($this->data, "\x0A:", $this->position);
8148 if (isset($this->data[$this->position + $len]))
8149 {
8150 if ($this->data[$this->position + $len] === "\x0A")
8151 {
8152 $this->position += $len;
8153 $this->state = 'new_line';
8154 }
8155 else
8156 {
8157 $this->name = substr($this->data, $this->position, $len);
8158 $this->position += $len + 1;
8159 $this->state = 'value';
8160 }
8161 }
8162 else
8163 {
8164 $this->state = false;
8165 }
8166 }
8167
8168 /**
8169 * Parse LWS, replacing consecutive LWS characters with a single space
8170 *
8171 * @access private
8172 */
8173 function linear_whitespace()
8174 {
8175 do
8176 {
8177 if (substr($this->data, $this->position, 2) === "\x0D\x0A")
8178 {
8179 $this->position += 2;
8180 }
8181 elseif ($this->data[$this->position] === "\x0A")
8182 {
8183 $this->position++;
8184 }
8185 $this->position += strspn($this->data, "\x09\x20", $this->position);
8186 } while ($this->has_data() && $this->is_linear_whitespace());
8187 $this->value .= "\x20";
8188 }
8189
8190 /**
8191 * See what state to move to while within non-quoted header values
8192 *
8193 * @access private
8194 */
8195 function value()
8196 {
8197 if ($this->is_linear_whitespace())
8198 {
8199 $this->linear_whitespace();
8200 }
8201 else
8202 {
8203 switch ($this->data[$this->position])
8204 {
8205 case '"':
8206 $this->position++;
8207 $this->state = 'quote';
8208 break;
8209
8210 case "\x0A":
8211 $this->position++;
8212 $this->state = 'new_line';
8213 break;
8214
8215 default:
8216 $this->state = 'value_char';
8217 break;
8218 }
8219 }
8220 }
8221
8222 /**
8223 * Parse a header value while outside quotes
8224 *
8225 * @access private
8226 */
8227 function value_char()
8228 {
8229 $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
8230 $this->value .= substr($this->data, $this->position, $len);
8231 $this->position += $len;
8232 $this->state = 'value';
8233 }
8234
8235 /**
8236 * See what state to move to while within quoted header values
8237 *
8238 * @access private
8239 */
8240 function quote()
8241 {
8242 if ($this->is_linear_whitespace())
8243 {
8244 $this->linear_whitespace();
8245 }
8246 else
8247 {
8248 switch ($this->data[$this->position])
8249 {
8250 case '"':
8251 $this->position++;
8252 $this->state = 'value';
8253 break;
8254
8255 case "\x0A":
8256 $this->position++;
8257 $this->state = 'new_line';
8258 break;
8259
8260 case '\\':
8261 $this->position++;
8262 $this->state = 'quote_escaped';
8263 break;
8264
8265 default:
8266 $this->state = 'quote_char';
8267 break;
8268 }
8269 }
8270 }
8271
8272 /**
8273 * Parse a header value while within quotes
8274 *
8275 * @access private
8276 */
8277 function quote_char()
8278 {
8279 $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
8280 $this->value .= substr($this->data, $this->position, $len);
8281 $this->position += $len;
8282 $this->state = 'value';
8283 }
8284
8285 /**
8286 * Parse an escaped character within quotes
8287 *
8288 * @access private
8289 */
8290 function quote_escaped()
8291 {
8292 $this->value .= $this->data[$this->position];
8293 $this->position++;
8294 $this->state = 'quote';
8295 }
8296
8297 /**
8298 * Parse the body
8299 *
8300 * @access private
8301 */
8302 function body()
8303 {
8304 $this->body = substr($this->data, $this->position);
8305 $this->state = 'emit';
8306 }
8307 }
8308
8309 /**
8310 * gzdecode
8311 *
8312 * @package SimplePie
8313 */
8314 class SimplePie_gzdecode
8315 {
8316 /**
8317 * Compressed data
8318 *
8319 * @access private
8320 * @see gzdecode::$data
8321 */
8322 var $compressed_data;
8323
8324 /**
8325 * Size of compressed data
8326 *
8327 * @access private
8328 */
8329 var $compressed_size;
8330
8331 /**
8332 * Minimum size of a valid gzip string
8333 *
8334 * @access private
8335 */
8336 var $min_compressed_size = 18;
8337
8338 /**
8339 * Current position of pointer
8340 *
8341 * @access private
8342 */
8343 var $position = 0;
8344
8345 /**
8346 * Flags (FLG)
8347 *
8348 * @access private
8349 */
8350 var $flags;
8351
8352 /**
8353 * Uncompressed data
8354 *
8355 * @access public
8356 * @see gzdecode::$compressed_data
8357 */
8358 var $data;
8359
8360 /**
8361 * Modified time
8362 *
8363 * @access public
8364 */
8365 var $MTIME;
8366
8367 /**
8368 * Extra Flags
8369 *
8370 * @access public
8371 */
8372 var $XFL;
8373
8374 /**
8375 * Operating System
8376 *
8377 * @access public
8378 */
8379 var $OS;
8380
8381 /**
8382 * Subfield ID 1
8383 *
8384 * @access public
8385 * @see gzdecode::$extra_field
8386 * @see gzdecode::$SI2
8387 */
8388 var $SI1;
8389
8390 /**
8391 * Subfield ID 2
8392 *
8393 * @access public
8394 * @see gzdecode::$extra_field
8395 * @see gzdecode::$SI1
8396 */
8397 var $SI2;
8398
8399 /**
8400 * Extra field content
8401 *
8402 * @access public
8403 * @see gzdecode::$SI1
8404 * @see gzdecode::$SI2
8405 */
8406 var $extra_field;
8407
8408 /**
8409 * Original filename
8410 *
8411 * @access public
8412 */
8413 var $filename;
8414
8415 /**
8416 * Human readable comment
8417 *
8418 * @access public
8419 */
8420 var $comment;
8421
8422 /**
8423 * Don't allow anything to be set
8424 *
8425 * @access public
8426 */
8427 function __set($name, $value)
8428 {
8429 trigger_error("Cannot write property $name", E_USER_ERROR);
8430 }
8431
8432 /**
8433 * Set the compressed string and related properties
8434 *
8435 * @access public
8436 */
8437 function SimplePie_gzdecode($data)
8438 {
8439 $this->compressed_data = $data;
8440 $this->compressed_size = strlen($data);
8441 }
8442
8443 /**
8444 * Decode the GZIP stream
8445 *
8446 * @access public
8447 */
8448 function parse()
8449 {
8450 if ($this->compressed_size >= $this->min_compressed_size)
8451 {
8452 // Check ID1, ID2, and CM
8453 if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
8454 {
8455 return false;
8456 }
8457
8458 // Get the FLG (FLaGs)
8459 $this->flags = ord($this->compressed_data[3]);
8460
8461 // FLG bits above (1 << 4) are reserved
8462 if ($this->flags > 0x1F)
8463 {
8464 return false;
8465 }
8466
8467 // Advance the pointer after the above
8468 $this->position += 4;
8469
8470 // MTIME
8471 $mtime = substr($this->compressed_data, $this->position, 4);
8472 // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
8473 if (current(unpack('S', "\x00\x01")) === 1)
8474 {
8475 $mtime = strrev($mtime);
8476 }
8477 $this->MTIME = current(unpack('l', $mtime));
8478 $this->position += 4;
8479
8480 // Get the XFL (eXtra FLags)
8481 $this->XFL = ord($this->compressed_data[$this->position++]);
8482
8483 // Get the OS (Operating System)
8484 $this->OS = ord($this->compressed_data[$this->position++]);
8485
8486 // Parse the FEXTRA
8487 if ($this->flags & 4)
8488 {
8489 // Read subfield IDs
8490 $this->SI1 = $this->compressed_data[$this->position++];
8491 $this->SI2 = $this->compressed_data[$this->position++];
8492
8493 // SI2 set to zero is reserved for future use
8494 if ($this->SI2 === "\x00")
8495 {
8496 return false;
8497 }
8498
8499 // Get the length of the extra field
8500 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8501 $this->position += 2;
8502
8503 // Check the length of the string is still valid
8504 $this->min_compressed_size += $len + 4;
8505 if ($this->compressed_size >= $this->min_compressed_size)
8506 {
8507 // Set the extra field to the given data
8508 $this->extra_field = substr($this->compressed_data, $this->position, $len);
8509 $this->position += $len;
8510 }
8511 else
8512 {
8513 return false;
8514 }
8515 }
8516
8517 // Parse the FNAME
8518 if ($this->flags & 8)
8519 {
8520 // Get the length of the filename
8521 $len = strcspn($this->compressed_data, "\x00", $this->position);
8522
8523 // Check the length of the string is still valid
8524 $this->min_compressed_size += $len + 1;
8525 if ($this->compressed_size >= $this->min_compressed_size)
8526 {
8527 // Set the original filename to the given string
8528 $this->filename = substr($this->compressed_data, $this->position, $len);
8529 $this->position += $len + 1;
8530 }
8531 else
8532 {
8533 return false;
8534 }
8535 }
8536
8537 // Parse the FCOMMENT
8538 if ($this->flags & 16)
8539 {
8540 // Get the length of the comment
8541 $len = strcspn($this->compressed_data, "\x00", $this->position);
8542
8543 // Check the length of the string is still valid
8544 $this->min_compressed_size += $len + 1;
8545 if ($this->compressed_size >= $this->min_compressed_size)
8546 {
8547 // Set the original comment to the given string
8548 $this->comment = substr($this->compressed_data, $this->position, $len);
8549 $this->position += $len + 1;
8550 }
8551 else
8552 {
8553 return false;
8554 }
8555 }
8556
8557 // Parse the FHCRC
8558 if ($this->flags & 2)
8559 {
8560 // Check the length of the string is still valid
8561 $this->min_compressed_size += $len + 2;
8562 if ($this->compressed_size >= $this->min_compressed_size)
8563 {
8564 // Read the CRC
8565 $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8566
8567 // Check the CRC matches
8568 if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
8569 {
8570 $this->position += 2;
8571 }
8572 else
8573 {
8574 return false;
8575 }
8576 }
8577 else
8578 {
8579 return false;
8580 }
8581 }
8582
8583 // Decompress the actual data
8584 if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
8585 {
8586 return false;
8587 }
8588 else
8589 {
8590 $this->position = $this->compressed_size - 8;
8591 }
8592
8593 // Check CRC of data
8594 $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8595 $this->position += 4;
8596 /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
8597 {
8598 return false;
8599 }*/
8600
8601 // Check ISIZE of data
8602 $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8603 $this->position += 4;
8604 if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
8605 {
8606 return false;
8607 }
8608
8609 // Wow, against all odds, we've actually got a valid gzip string
8610 return true;
8611 }
8612 else
8613 {
8614 return false;
8615 }
8616 }
8617 }
8618
8619 class SimplePie_Cache
8620 {
8621 /**
8622 * Don't call the constructor. Please.
8623 *
8624 * @access private
8625 */
8626 function SimplePie_Cache()
8627 {
8628 trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8629 }
8630
8631 /**
8632 * Create a new SimplePie_Cache object
8633 *
8634 * @static
8635 * @access public
8636 */
8637 function create($location, $filename, $extension)
8638 {
8639 $location_iri =& new SimplePie_IRI($location);
8640 switch ($location_iri->get_scheme())
8641 {
8642 case 'mysql':
8643 if (extension_loaded('mysql'))
8644 {
8645 return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
8646 }
8647 break;
8648
8649 default:
8650 return new SimplePie_Cache_File($location, $filename, $extension);
8651 }
8652 }
8653 }
8654
8655 class SimplePie_Cache_File
8656 {
8657 var $location;
8658 var $filename;
8659 var $extension;
8660 var $name;
8661
8662 function SimplePie_Cache_File($location, $filename, $extension)
8663 {
8664 $this->location = $location;
8665 $this->filename = $filename;
8666 $this->extension = $extension;
8667 $this->name = "$this->location/$this->filename.$this->extension";
8668 }
8669
8670 function save($data)
8671 {
8672 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8673 {
8674 if (is_a($data, 'SimplePie'))
8675 {
8676 $data = $data->data;
8677 }
8678
8679 $data = serialize($data);
8680
8681 if (function_exists('file_put_contents'))
8682 {
8683 return (bool) file_put_contents($this->name, $data);
8684 }
8685 else
8686 {
8687 $fp = fopen($this->name, 'wb');
8688 if ($fp)
8689 {
8690 fwrite($fp, $data);
8691 fclose($fp);
8692 return true;
8693 }
8694 }
8695 }
8696 return false;
8697 }
8698
8699 function load()
8700 {
8701 if (file_exists($this->name) && is_readable($this->name))
8702 {
8703 return unserialize(file_get_contents($this->name));
8704 }
8705 return false;
8706 }
8707
8708 function mtime()
8709 {
8710 if (file_exists($this->name))
8711 {
8712 return filemtime($this->name);
8713 }
8714 return false;
8715 }
8716
8717 function touch()
8718 {
8719 if (file_exists($this->name))
8720 {
8721 return touch($this->name);
8722 }
8723 return false;
8724 }
8725
8726 function unlink()
8727 {
8728 if (file_exists($this->name))
8729 {
8730 return unlink($this->name);
8731 }
8732 return false;
8733 }
8734 }
8735
8736 class SimplePie_Cache_DB
8737 {
8738 function prepare_simplepie_object_for_cache($data)
8739 {
8740 $items = $data->get_items();
8741 $items_by_id = array();
8742
8743 if (!empty($items))
8744 {
8745 foreach ($items as $item)
8746 {
8747 $items_by_id[$item->get_id()] = $item;
8748 }
8749
8750 if (count($items_by_id) !== count($items))
8751 {
8752 $items_by_id = array();
8753 foreach ($items as $item)
8754 {
8755 $items_by_id[$item->get_id(true)] = $item;
8756 }
8757 }
8758
8759 if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8760 {
8761 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8762 }
8763 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8764 {
8765 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8766 }
8767 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8768 {
8769 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8770 }
8771 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
8772 {
8773 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
8774 }
8775 else
8776 {
8777 $channel = null;
8778 }
8779
8780 if ($channel !== null)
8781 {
8782 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
8783 {
8784 unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
8785 }
8786 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
8787 {
8788 unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
8789 }
8790 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
8791 {
8792 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
8793 }
8794 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
8795 {
8796 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
8797 }
8798 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
8799 {
8800 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
8801 }
8802 }
8803 if (isset($data->data['items']))
8804 {
8805 unset($data->data['items']);
8806 }
8807 if (isset($data->data['ordered_items']))
8808 {
8809 unset($data->data['ordered_items']);
8810 }
8811 }
8812 return array(serialize($data->data), $items_by_id);
8813 }
8814 }
8815
8816 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
8817 {
8818 var $mysql;
8819 var $options;
8820 var $id;
8821
8822 function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
8823 {
8824 $host = $mysql_location->get_host();
8825 if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
8826 {
8827 $server = ':' . substr($host, 5, -1);
8828 }
8829 else
8830 {
8831 $server = $host;
8832 if ($mysql_location->get_port() !== null)
8833 {
8834 $server .= ':' . $mysql_location->get_port();
8835 }
8836 }
8837
8838 if (strpos($mysql_location->get_userinfo(), ':') !== false)
8839 {
8840 list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
8841 }
8842 else
8843 {
8844 $username = $mysql_location->get_userinfo();
8845 $password = null;
8846 }
8847
8848 if ($this->mysql = mysql_connect($server, $username, $password))
8849 {
8850 $this->id = $name . $extension;
8851 $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
8852 if (!isset($this->options['prefix'][0]))
8853 {
8854 $this->options['prefix'][0] = '';
8855 }
8856
8857 if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
8858 && mysql_query('SET NAMES utf8')
8859 && ($query = mysql_unbuffered_query('SHOW TABLES')))
8860 {
8861 $db = array();
8862 while ($row = mysql_fetch_row($query))
8863 {
8864 $db[] = $row[0];
8865 }
8866
8867 if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
8868 {
8869 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)))'))
8870 {
8871 $this->mysql = null;
8872 }
8873 }
8874
8875 if (!in_array($this->options['prefix'][0] . 'items', $db))
8876 {
8877 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)))'))
8878 {
8879 $this->mysql = null;
8880 }
8881 }
8882 }
8883 else
8884 {
8885 $this->mysql = null;
8886 }
8887 }
8888 }
8889
8890 function save($data)
8891 {
8892 if ($this->mysql)
8893 {
8894 $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
8895
8896 if (is_a($data, 'SimplePie'))
8897 {
8898 if (SIMPLEPIE_PHP5)
8899 {
8900 // This keyword needs to defy coding standards for PHP4 compatibility
8901 $data = clone($data);
8902 }
8903
8904 $prepared = $this->prepare_simplepie_object_for_cache($data);
8905
8906 if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8907 {
8908 if (mysql_num_rows($query))
8909 {
8910 $items = count($prepared[1]);
8911 if ($items)
8912 {
8913 $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8914 }
8915 else
8916 {
8917 $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8918 }
8919
8920 if (!mysql_query($sql, $this->mysql))
8921 {
8922 return false;
8923 }
8924 }
8925 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))
8926 {
8927 return false;
8928 }
8929
8930 $ids = array_keys($prepared[1]);
8931 if (!empty($ids))
8932 {
8933 foreach ($ids as $id)
8934 {
8935 $database_ids[] = mysql_real_escape_string($id);
8936 }
8937
8938 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))
8939 {
8940 $existing_ids = array();
8941 while ($row = mysql_fetch_row($query))
8942 {
8943 $existing_ids[] = $row[0];
8944 }
8945
8946 $new_ids = array_diff($ids, $existing_ids);
8947
8948 foreach ($new_ids as $new_id)
8949 {
8950 if (!($date = $prepared[1][$new_id]->get_date('U')))
8951 {
8952 $date = time();
8953 }
8954
8955 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))
8956 {
8957 return false;
8958 }
8959 }
8960 return true;
8961 }
8962 }
8963 else
8964 {
8965 return true;
8966 }
8967 }
8968 }
8969 elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8970 {
8971 if (mysql_num_rows($query))
8972 {
8973 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))
8974 {
8975 return true;
8976 }
8977 }
8978 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))
8979 {
8980 return true;
8981 }
8982 }
8983 }
8984 return false;
8985 }
8986
8987 function load()
8988 {
8989 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)))
8990 {
8991 $data = unserialize($row[1]);
8992
8993 if (isset($this->options['items'][0]))
8994 {
8995 $items = (int) $this->options['items'][0];
8996 }
8997 else
8998 {
8999 $items = (int) $row[0];
9000 }
9001
9002 if ($items !== 0)
9003 {
9004 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
9005 {
9006 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
9007 }
9008 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
9009 {
9010 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
9011 }
9012 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
9013 {
9014 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
9015 }
9016 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
9017 {
9018 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
9019 }
9020 else
9021 {
9022 $feed = null;
9023 }
9024
9025 if ($feed !== null)
9026 {
9027 $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
9028 if ($items > 0)
9029 {
9030 $sql .= ' LIMIT ' . $items;
9031 }
9032
9033 if ($query = mysql_unbuffered_query($sql, $this->mysql))
9034 {
9035 while ($row = mysql_fetch_row($query))
9036 {
9037 $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
9038 }
9039 }
9040 else
9041 {
9042 return false;
9043 }
9044 }
9045 }
9046 return $data;
9047 }
9048 return false;
9049 }
9050
9051 function mtime()
9052 {
9053 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)))
9054 {
9055 return $row[0];
9056 }
9057 else
9058 {
9059 return false;
9060 }
9061 }
9062
9063 function touch()
9064 {
9065 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))
9066 {
9067 return true;
9068 }
9069 else
9070 {
9071 return false;
9072 }
9073 }
9074
9075 function unlink()
9076 {
9077 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)))
9078 {
9079 return true;
9080 }
9081 else
9082 {
9083 return false;
9084 }
9085 }
9086 }
9087
9088 class SimplePie_Misc
9089 {
9090 function time_hms($seconds)
9091 {
9092 $time = '';
9093
9094 $hours = floor($seconds / 3600);
9095 $remainder = $seconds % 3600;
9096 if ($hours > 0)
9097 {
9098 $time .= $hours.':';
9099 }
9100
9101 $minutes = floor($remainder / 60);
9102 $seconds = $remainder % 60;
9103 if ($minutes < 10 && $hours > 0)
9104 {
9105 $minutes = '0' . $minutes;
9106 }
9107 if ($seconds < 10)
9108 {
9109 $seconds = '0' . $seconds;
9110 }
9111
9112 $time .= $minutes.':';
9113 $time .= $seconds;
9114
9115 return $time;
9116 }
9117
9118 function absolutize_url($relative, $base)
9119 {
9120 $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
9121 return $iri->get_iri();
9122 }
9123
9124 function remove_dot_segments($input)
9125 {
9126 $output = '';
9127 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
9128 {
9129 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
9130 if (strpos($input, '../') === 0)
9131 {
9132 $input = substr($input, 3);
9133 }
9134 elseif (strpos($input, './') === 0)
9135 {
9136 $input = substr($input, 2);
9137 }
9138 // 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,
9139 elseif (strpos($input, '/./') === 0)
9140 {
9141 $input = substr_replace($input, '/', 0, 3);
9142 }
9143 elseif ($input === '/.')
9144 {
9145 $input = '/';
9146 }
9147 // 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,
9148 elseif (strpos($input, '/../') === 0)
9149 {
9150 $input = substr_replace($input, '/', 0, 4);
9151 $output = substr_replace($output, '', strrpos($output, '/'));
9152 }
9153 elseif ($input === '/..')
9154 {
9155 $input = '/';
9156 $output = substr_replace($output, '', strrpos($output, '/'));
9157 }
9158 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
9159 elseif ($input === '.' || $input === '..')
9160 {
9161 $input = '';
9162 }
9163 // 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
9164 elseif (($pos = strpos($input, '/', 1)) !== false)
9165 {
9166 $output .= substr($input, 0, $pos);
9167 $input = substr_replace($input, '', 0, $pos);
9168 }
9169 else
9170 {
9171 $output .= $input;
9172 $input = '';
9173 }
9174 }
9175 return $output . $input;
9176 }
9177
9178 function get_element($realname, $string)
9179 {
9180 $return = array();
9181 $name = preg_quote($realname, '/');
9182 if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
9183 {
9184 for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
9185 {
9186 $return[$i]['tag'] = $realname;
9187 $return[$i]['full'] = $matches[$i][0][0];
9188 $return[$i]['offset'] = $matches[$i][0][1];
9189 if (strlen($matches[$i][3][0]) <= 2)
9190 {
9191 $return[$i]['self_closing'] = true;
9192 }
9193 else
9194 {
9195 $return[$i]['self_closing'] = false;
9196 $return[$i]['content'] = $matches[$i][4][0];
9197 }
9198 $return[$i]['attribs'] = array();
9199 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))
9200 {
9201 for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
9202 {
9203 if (count($attribs[$j]) === 2)
9204 {
9205 $attribs[$j][2] = $attribs[$j][1];
9206 }
9207 $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
9208 }
9209 }
9210 }
9211 }
9212 return $return;
9213 }
9214
9215 function element_implode($element)
9216 {
9217 $full = "<$element[tag]";
9218 foreach ($element['attribs'] as $key => $value)
9219 {
9220 $key = strtolower($key);
9221 $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
9222 }
9223 if ($element['self_closing'])
9224 {
9225 $full .= ' />';
9226 }
9227 else
9228 {
9229 $full .= ">$element[content]</$element[tag]>";
9230 }
9231 return $full;
9232 }
9233
9234 function error($message, $level, $file, $line)
9235 {
9236 if ((ini_get('error_reporting') & $level) > 0)
9237 {
9238 switch ($level)
9239 {
9240 case E_USER_ERROR:
9241 $note = 'PHP Error';
9242 break;
9243 case E_USER_WARNING:
9244 $note = 'PHP Warning';
9245 break;
9246 case E_USER_NOTICE:
9247 $note = 'PHP Notice';
9248 break;
9249 default:
9250 $note = 'Unknown Error';
9251 break;
9252 }
9253
9254 $log_error = true;
9255 if (!function_exists('error_log'))
9256 {
9257 $log_error = false;
9258 }
9259
9260 $log_file = @ini_get('error_log');
9261 if (!empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file))
9262 {
9263 $log_error = false;
9264 }
9265
9266 if ($log_error)
9267 {
9268 @error_log("$note: $message in $file on line $line", 0);
9269 }
9270 }
9271
9272 return $message;
9273 }
9274
9275 /**
9276 * If a file has been cached, retrieve and display it.
9277 *
9278 * This is most useful for caching images (get_favicon(), etc.),
9279 * however it works for all cached files. This WILL NOT display ANY
9280 * file/image/page/whatever, but rather only display what has already
9281 * been cached by SimplePie.
9282 *
9283 * @access public
9284 * @see SimplePie::get_favicon()
9285 * @param str $identifier_url URL that is used to identify the content.
9286 * This may or may not be the actual URL of the live content.
9287 * @param str $cache_location Location of SimplePie's cache. Defaults
9288 * to './cache'.
9289 * @param str $cache_extension The file extension that the file was
9290 * cached with. Defaults to 'spc'.
9291 * @param str $cache_class Name of the cache-handling class being used
9292 * in SimplePie. Defaults to 'SimplePie_Cache', and should be left
9293 * as-is unless you've overloaded the class.
9294 * @param str $cache_name_function Obsolete. Exists for backwards
9295 * compatibility reasons only.
9296 */
9297 function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
9298 {
9299 $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
9300
9301 if ($file = $cache->load())
9302 {
9303 if (isset($file['headers']['content-type']))
9304 {
9305 header('Content-type:' . $file['headers']['content-type']);
9306 }
9307 else
9308 {
9309 header('Content-type: application/octet-stream');
9310 }
9311 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
9312 echo $file['body'];
9313 exit;
9314 }
9315
9316 die('Cached file for ' . $identifier_url . ' cannot be found.');
9317 }
9318
9319 function fix_protocol($url, $http = 1)
9320 {
9321 $url = SimplePie_Misc::normalize_url($url);
9322 $parsed = SimplePie_Misc::parse_url($url);
9323 if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
9324 {
9325 return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
9326 }
9327
9328 if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
9329 {
9330 return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
9331 }
9332
9333 if ($http === 2 && $parsed['scheme'] !== '')
9334 {
9335 return "feed:$url";
9336 }
9337 elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
9338 {
9339 return substr_replace($url, 'podcast', 0, 4);
9340 }
9341 elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
9342 {
9343 return substr_replace($url, 'itpc', 0, 4);
9344 }
9345 else
9346 {
9347 return $url;
9348 }
9349 }
9350
9351 function parse_url($url)
9352 {
9353 $iri =& new SimplePie_IRI($url);
9354 return array(
9355 'scheme' => (string) $iri->get_scheme(),
9356 'authority' => (string) $iri->get_authority(),
9357 'path' => (string) $iri->get_path(),
9358 'query' => (string) $iri->get_query(),
9359 'fragment' => (string) $iri->get_fragment()
9360 );
9361 }
9362
9363 function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
9364 {
9365 $iri =& new SimplePie_IRI('');
9366 $iri->set_scheme($scheme);
9367 $iri->set_authority($authority);
9368 $iri->set_path($path);
9369 $iri->set_query($query);
9370 $iri->set_fragment($fragment);
9371 return $iri->get_iri();
9372 }
9373
9374 function normalize_url($url)
9375 {
9376 $iri =& new SimplePie_IRI($url);
9377 return $iri->get_iri();
9378 }
9379
9380 function percent_encoding_normalization($match)
9381 {
9382 $integer = hexdec($match[1]);
9383 if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
9384 {
9385 return chr($integer);
9386 }
9387 else
9388 {
9389 return strtoupper($match[0]);
9390 }
9391 }
9392
9393 /**
9394 * Remove bad UTF-8 bytes
9395 *
9396 * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
9397 * FAQ: Multilingual Forms (modified to include full ASCII range)
9398 *
9399 * @author Geoffrey Sneddon
9400 * @see http://www.w3.org/International/questions/qa-forms-utf-8
9401 * @param string $str String to remove bad UTF-8 bytes from
9402 * @return string UTF-8 string
9403 */
9404 function utf8_bad_replace($str)
9405 {
9406 if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
9407 {
9408 return $return;
9409 }
9410 elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
9411 {
9412 return $return;
9413 }
9414 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))
9415 {
9416 return implode("\xEF\xBF\xBD", $matches[0]);
9417 }
9418 elseif ($str !== '')
9419 {
9420 return "\xEF\xBF\xBD";
9421 }
9422 else
9423 {
9424 return '';
9425 }
9426 }
9427
9428 /**
9429 * Converts a Windows-1252 encoded string to a UTF-8 encoded string
9430 *
9431 * @static
9432 * @access public
9433 * @param string $string Windows-1252 encoded string
9434 * @return string UTF-8 encoded string
9435 */
9436 function windows_1252_to_utf8($string)
9437 {
9438 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");
9439
9440 return strtr($string, $convert_table);
9441 }
9442
9443 function change_encoding($data, $input, $output)
9444 {
9445 $input = SimplePie_Misc::encoding($input);
9446 $output = SimplePie_Misc::encoding($output);
9447
9448 // We fail to fail on non US-ASCII bytes
9449 if ($input === 'US-ASCII')
9450 {
9451 static $non_ascii_octects = '';
9452 if (!$non_ascii_octects)
9453 {
9454 for ($i = 0x80; $i <= 0xFF; $i++)
9455 {
9456 $non_ascii_octects .= chr($i);
9457 }
9458 }
9459 $data = substr($data, 0, strcspn($data, $non_ascii_octects));
9460 }
9461
9462 // This is first, as behaviour of this is completely predictable
9463 if ($input === 'windows-1252' && $output === 'UTF-8')
9464 {
9465 return SimplePie_Misc::windows_1252_to_utf8($data);
9466 }
9467 // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
9468 elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && in_array($input, mb_list_encodings()) && ($return = @mb_convert_encoding($data, $output, $input)))
9469 {
9470 return $return;
9471 }
9472 // This is last, as behaviour of this varies with OS userland and PHP version
9473 elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
9474 {
9475 return $return;
9476 }
9477 // If we can't do anything, just fail
9478 else
9479 {
9480 return false;
9481 }
9482 }
9483
9484 /**
9485 * Normalize an encoding name
9486 *
9487 * This is automatically generated by create.php
9488 *
9489 * To generate it, run `php create.php` on the command line, and copy the
9490 * output to replace this function.
9491 *
9492 * @param string $charset Character set to standardise
9493 * @return string Standardised name
9494 */
9495 function encoding($charset)
9496 {
9497 // Normalization from UTS #22
9498 switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
9499 {
9500 case 'adobestandardencoding':
9501 case 'csadobestandardencoding':
9502 return 'Adobe-Standard-Encoding';
9503
9504 case 'adobesymbolencoding':
9505 case 'cshppsmath':
9506 return 'Adobe-Symbol-Encoding';
9507
9508 case 'ami1251':
9509 case 'amiga1251':
9510 return 'Amiga-1251';
9511
9512 case 'ansix31101983':
9513 case 'csat5001983':
9514 case 'csiso99naplps':
9515 case 'isoir99':
9516 case 'naplps':
9517 return 'ANSI_X3.110-1983';
9518
9519 case 'arabic7':
9520 case 'asmo449':
9521 case 'csiso89asmo449':
9522 case 'iso9036':
9523 case 'isoir89':
9524 return 'ASMO_449';
9525
9526 case 'big5':
9527 case 'csbig5':
9528 return 'Big5';
9529
9530 case 'big5hkscs':
9531 return 'Big5-HKSCS';
9532
9533 case 'bocu1':
9534 case 'csbocu1':
9535 return 'BOCU-1';
9536
9537 case 'brf':
9538 case 'csbrf':
9539 return 'BRF';
9540
9541 case 'bs4730':
9542 case 'csiso4unitedkingdom':
9543 case 'gb':
9544 case 'iso646gb':
9545 case 'isoir4':
9546 case 'uk':
9547 return 'BS_4730';
9548
9549 case 'bsviewdata':
9550 case 'csiso47bsviewdata':
9551 case 'isoir47':
9552 return 'BS_viewdata';
9553
9554 case 'cesu8':
9555 case 'cscesu8':
9556 return 'CESU-8';
9557
9558 case 'ca':
9559 case 'csa71':
9560 case 'csaz243419851':
9561 case 'csiso121canadian1':
9562 case 'iso646ca':
9563 case 'isoir121':
9564 return 'CSA_Z243.4-1985-1';
9565
9566 case 'csa72':
9567 case 'csaz243419852':
9568 case 'csiso122canadian2':
9569 case 'iso646ca2':
9570 case 'isoir122':
9571 return 'CSA_Z243.4-1985-2';
9572
9573 case 'csaz24341985gr':
9574 case 'csiso123csaz24341985gr':
9575 case 'isoir123':
9576 return 'CSA_Z243.4-1985-gr';
9577
9578 case 'csiso139csn369103':
9579 case 'csn369103':
9580 case 'isoir139':
9581 return 'CSN_369103';
9582
9583 case 'csdecmcs':
9584 case 'dec':
9585 case 'decmcs':
9586 return 'DEC-MCS';
9587
9588 case 'csiso21german':
9589 case 'de':
9590 case 'din66003':
9591 case 'iso646de':
9592 case 'isoir21':
9593 return 'DIN_66003';
9594
9595 case 'csdkus':
9596 case 'dkus':
9597 return 'dk-us';
9598
9599 case 'csiso646danish':
9600 case 'dk':
9601 case 'ds2089':
9602 case 'iso646dk':
9603 return 'DS_2089';
9604
9605 case 'csibmebcdicatde':
9606 case 'ebcdicatde':
9607 return 'EBCDIC-AT-DE';
9608
9609 case 'csebcdicatdea':
9610 case 'ebcdicatdea':
9611 return 'EBCDIC-AT-DE-A';
9612
9613 case 'csebcdiccafr':
9614 case 'ebcdiccafr':
9615 return 'EBCDIC-CA-FR';
9616
9617 case 'csebcdicdkno':
9618 case 'ebcdicdkno':
9619 return 'EBCDIC-DK-NO';
9620
9621 case 'csebcdicdknoa':
9622 case 'ebcdicdknoa':
9623 return 'EBCDIC-DK-NO-A';
9624
9625 case 'csebcdices':
9626 case 'ebcdices':
9627 return 'EBCDIC-ES';
9628
9629 case 'csebcdicesa':
9630 case 'ebcdicesa':
9631 return 'EBCDIC-ES-A';
9632
9633 case 'csebcdicess':
9634 case 'ebcdicess':
9635 return 'EBCDIC-ES-S';
9636
9637 case 'csebcdicfise':
9638 case 'ebcdicfise':
9639 return 'EBCDIC-FI-SE';
9640
9641 case 'csebcdicfisea':
9642 case 'ebcdicfisea':
9643 return 'EBCDIC-FI-SE-A';
9644
9645 case 'csebcdicfr':
9646 case 'ebcdicfr':
9647 return 'EBCDIC-FR';
9648
9649 case 'csebcdicit':
9650 case 'ebcdicit':
9651 return 'EBCDIC-IT';
9652
9653 case 'csebcdicpt':
9654 case 'ebcdicpt':
9655 return 'EBCDIC-PT';
9656
9657 case 'csebcdicuk':
9658 case 'ebcdicuk':
9659 return 'EBCDIC-UK';
9660
9661 case 'csebcdicus':
9662 case 'ebcdicus':
9663 return 'EBCDIC-US';
9664
9665 case 'csiso111ecmacyrillic':
9666 case 'ecmacyrillic':
9667 case 'isoir111':
9668 case 'koi8e':
9669 return 'ECMA-cyrillic';
9670
9671 case 'csiso17spanish':
9672 case 'es':
9673 case 'iso646es':
9674 case 'isoir17':
9675 return 'ES';
9676
9677 case 'csiso85spanish2':
9678 case 'es2':
9679 case 'iso646es2':
9680 case 'isoir85':
9681 return 'ES2';
9682
9683 case 'cseucpkdfmtjapanese':
9684 case 'eucjp':
9685 case 'extendedunixcodepackedformatforjapanese':
9686 return 'EUC-JP';
9687
9688 case 'cseucfixwidjapanese':
9689 case 'extendedunixcodefixedwidthforjapanese':
9690 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
9691
9692 case 'gb18030':
9693 return 'GB18030';
9694
9695 case 'chinese':
9696 case 'cp936':
9697 case 'csgb2312':
9698 case 'csiso58gb231280':
9699 case 'gb2312':
9700 case 'gb231280':
9701 case 'gbk':
9702 case 'isoir58':
9703 case 'ms936':
9704 case 'windows936':
9705 return 'GBK';
9706
9707 case 'cn':
9708 case 'csiso57gb1988':
9709 case 'gb198880':
9710 case 'iso646cn':
9711 case 'isoir57':
9712 return 'GB_1988-80';
9713
9714 case 'csiso153gost1976874':
9715 case 'gost1976874':
9716 case 'isoir153':
9717 case 'stsev35888':
9718 return 'GOST_19768-74';
9719
9720 case 'csiso150':
9721 case 'csiso150greekccitt':
9722 case 'greekccitt':
9723 case 'isoir150':
9724 return 'greek-ccitt';
9725
9726 case 'csiso88greek7':
9727 case 'greek7':
9728 case 'isoir88':
9729 return 'greek7';
9730
9731 case 'csiso18greek7old':
9732 case 'greek7old':
9733 case 'isoir18':
9734 return 'greek7-old';
9735
9736 case 'cshpdesktop':
9737 case 'hpdesktop':
9738 return 'HP-DeskTop';
9739
9740 case 'cshplegal':
9741 case 'hplegal':
9742 return 'HP-Legal';
9743
9744 case 'cshpmath8':
9745 case 'hpmath8':
9746 return 'HP-Math8';
9747
9748 case 'cshppifont':
9749 case 'hppifont':
9750 return 'HP-Pi-font';
9751
9752 case 'cshproman8':
9753 case 'hproman8':
9754 case 'r8':
9755 case 'roman8':
9756 return 'hp-roman8';
9757
9758 case 'hzgb2312':
9759 return 'HZ-GB-2312';
9760
9761 case 'csibmsymbols':
9762 case 'ibmsymbols':
9763 return 'IBM-Symbols';
9764
9765 case 'csibmthai':
9766 case 'ibmthai':
9767 return 'IBM-Thai';
9768
9769 case 'cp37':
9770 case 'csibm37':
9771 case 'ebcdiccpca':
9772 case 'ebcdiccpnl':
9773 case 'ebcdiccpus':
9774 case 'ebcdiccpwt':
9775 case 'ibm37':
9776 return 'IBM037';
9777
9778 case 'cp38':
9779 case 'csibm38':
9780 case 'ebcdicint':
9781 case 'ibm38':
9782 return 'IBM038';
9783
9784 case 'cp273':
9785 case 'csibm273':
9786 case 'ibm273':
9787 return 'IBM273';
9788
9789 case 'cp274':
9790 case 'csibm274':
9791 case 'ebcdicbe':
9792 case 'ibm274':
9793 return 'IBM274';
9794
9795 case 'cp275':
9796 case 'csibm275':
9797 case 'ebcdicbr':
9798 case 'ibm275':
9799 return 'IBM275';
9800
9801 case 'csibm277':
9802 case 'ebcdiccpdk':
9803 case 'ebcdiccpno':
9804 case 'ibm277':
9805 return 'IBM277';
9806
9807 case 'cp278':
9808 case 'csibm278':
9809 case 'ebcdiccpfi':
9810 case 'ebcdiccpse':
9811 case 'ibm278':
9812 return 'IBM278';
9813
9814 case 'cp280':
9815 case 'csibm280':
9816 case 'ebcdiccpit':
9817 case 'ibm280':
9818 return 'IBM280';
9819
9820 case 'cp281':
9821 case 'csibm281':
9822 case 'ebcdicjpe':
9823 case 'ibm281':
9824 return 'IBM281';
9825
9826 case 'cp284':
9827 case 'csibm284':
9828 case 'ebcdiccpes':
9829 case 'ibm284':
9830 return 'IBM284';
9831
9832 case 'cp285':
9833 case 'csibm285':
9834 case 'ebcdiccpgb':
9835 case 'ibm285':
9836 return 'IBM285';
9837
9838 case 'cp290':
9839 case 'csibm290':
9840 case 'ebcdicjpkana':
9841 case 'ibm290':
9842 return 'IBM290';
9843
9844 case 'cp297':
9845 case 'csibm297':
9846 case 'ebcdiccpfr':
9847 case 'ibm297':
9848 return 'IBM297';
9849
9850 case 'cp420':
9851 case 'csibm420':
9852 case 'ebcdiccpar1':
9853 case 'ibm420':
9854 return 'IBM420';
9855
9856 case 'cp423':
9857 case 'csibm423':
9858 case 'ebcdiccpgr':
9859 case 'ibm423':
9860 return 'IBM423';
9861
9862 case 'cp424':
9863 case 'csibm424':
9864 case 'ebcdiccphe':
9865 case 'ibm424':
9866 return 'IBM424';
9867
9868 case '437':
9869 case 'cp437':
9870 case 'cspc8codepage437':
9871 case 'ibm437':
9872 return 'IBM437';
9873
9874 case 'cp500':
9875 case 'csibm500':
9876 case 'ebcdiccpbe':
9877 case 'ebcdiccpch':
9878 case 'ibm500':
9879 return 'IBM500';
9880
9881 case 'cp775':
9882 case 'cspc775baltic':
9883 case 'ibm775':
9884 return 'IBM775';
9885
9886 case '850':
9887 case 'cp850':
9888 case 'cspc850multilingual':
9889 case 'ibm850':
9890 return 'IBM850';
9891
9892 case '851':
9893 case 'cp851':
9894 case 'csibm851':
9895 case 'ibm851':
9896 return 'IBM851';
9897
9898 case '852':
9899 case 'cp852':
9900 case 'cspcp852':
9901 case 'ibm852':
9902 return 'IBM852';
9903
9904 case '855':
9905 case 'cp855':
9906 case 'csibm855':
9907 case 'ibm855':
9908 return 'IBM855';
9909
9910 case '857':
9911 case 'cp857':
9912 case 'csibm857':
9913 case 'ibm857':
9914 return 'IBM857';
9915
9916 case 'ccsid858':
9917 case 'cp858':
9918 case 'ibm858':
9919 case 'pcmultilingual850euro':
9920 return 'IBM00858';
9921
9922 case '860':
9923 case 'cp860':
9924 case 'csibm860':
9925 case 'ibm860':
9926 return 'IBM860';
9927
9928 case '861':
9929 case 'cp861':
9930 case 'cpis':
9931 case 'csibm861':
9932 case 'ibm861':
9933 return 'IBM861';
9934
9935 case '862':
9936 case 'cp862':
9937 case 'cspc862latinhebrew':
9938 case 'ibm862':
9939 return 'IBM862';
9940
9941 case '863':
9942 case 'cp863':
9943 case 'csibm863':
9944 case 'ibm863':
9945 return 'IBM863';
9946
9947 case 'cp864':
9948 case 'csibm864':
9949 case 'ibm864':
9950 return 'IBM864';
9951
9952 case '865':
9953 case 'cp865':
9954 case 'csibm865':
9955 case 'ibm865':
9956 return 'IBM865';
9957
9958 case '866':
9959 case 'cp866':
9960 case 'csibm866':
9961 case 'ibm866':
9962 return 'IBM866';
9963
9964 case 'cp868':
9965 case 'cpar':
9966 case 'csibm868':
9967 case 'ibm868':
9968 return 'IBM868';
9969
9970 case '869':
9971 case 'cp869':
9972 case 'cpgr':
9973 case 'csibm869':
9974 case 'ibm869':
9975 return 'IBM869';
9976
9977 case 'cp870':
9978 case 'csibm870':
9979 case 'ebcdiccproece':
9980 case 'ebcdiccpyu':
9981 case 'ibm870':
9982 return 'IBM870';
9983
9984 case 'cp871':
9985 case 'csibm871':
9986 case 'ebcdiccpis':
9987 case 'ibm871':
9988 return 'IBM871';
9989
9990 case 'cp880':
9991 case 'csibm880':
9992 case 'ebcdiccyrillic':
9993 case 'ibm880':
9994 return 'IBM880';
9995
9996 case 'cp891':
9997 case 'csibm891':
9998 case 'ibm891':
9999 return 'IBM891';
10000
10001 case 'cp903':
10002 case 'csibm903':
10003 case 'ibm903':
10004 return 'IBM903';
10005
10006 case '904':
10007 case 'cp904':
10008 case 'csibbm904':
10009 case 'ibm904':
10010 return 'IBM904';
10011
10012 case 'cp905':
10013 case 'csibm905':
10014 case 'ebcdiccptr':
10015 case 'ibm905':
10016 return 'IBM905';
10017
10018 case 'cp918':
10019 case 'csibm918':
10020 case 'ebcdiccpar2':
10021 case 'ibm918':
10022 return 'IBM918';
10023
10024 case 'ccsid924':
10025 case 'cp924':
10026 case 'ebcdiclatin9euro':
10027 case 'ibm924':
10028 return 'IBM00924';
10029
10030 case 'cp1026':
10031 case 'csibm1026':
10032 case 'ibm1026':
10033 return 'IBM1026';
10034
10035 case 'ibm1047':
10036 return 'IBM1047';
10037
10038 case 'ccsid1140':
10039 case 'cp1140':
10040 case 'ebcdicus37euro':
10041 case 'ibm1140':
10042 return 'IBM01140';
10043
10044 case 'ccsid1141':
10045 case 'cp1141':
10046 case 'ebcdicde273euro':
10047 case 'ibm1141':
10048 return 'IBM01141';
10049
10050 case 'ccsid1142':
10051 case 'cp1142':
10052 case 'ebcdicdk277euro':
10053 case 'ebcdicno277euro':
10054 case 'ibm1142':
10055 return 'IBM01142';
10056
10057 case 'ccsid1143':
10058 case 'cp1143':
10059 case 'ebcdicfi278euro':
10060 case 'ebcdicse278euro':
10061 case 'ibm1143':
10062 return 'IBM01143';
10063
10064 case 'ccsid1144':
10065 case 'cp1144':
10066 case 'ebcdicit280euro':
10067 case 'ibm1144':
10068 return 'IBM01144';
10069
10070 case 'ccsid1145':
10071 case 'cp1145':
10072 case 'ebcdices284euro':
10073 case 'ibm1145':
10074 return 'IBM01145';
10075
10076 case 'ccsid1146':
10077 case 'cp1146':
10078 case 'ebcdicgb285euro':
10079 case 'ibm1146':
10080 return 'IBM01146';
10081
10082 case 'ccsid1147':
10083 case 'cp1147':
10084 case 'ebcdicfr297euro':
10085 case 'ibm1147':
10086 return 'IBM01147';
10087
10088 case 'ccsid1148':
10089 case 'cp1148':
10090 case 'ebcdicinternational500euro':
10091 case 'ibm1148':
10092 return 'IBM01148';
10093
10094 case 'ccsid1149':
10095 case 'cp1149':
10096 case 'ebcdicis871euro':
10097 case 'ibm1149':
10098 return 'IBM01149';
10099
10100 case 'csiso143iecp271':
10101 case 'iecp271':
10102 case 'isoir143':
10103 return 'IEC_P27-1';
10104
10105 case 'csiso49inis':
10106 case 'inis':
10107 case 'isoir49':
10108 return 'INIS';
10109
10110 case 'csiso50inis8':
10111 case 'inis8':
10112 case 'isoir50':
10113 return 'INIS-8';
10114
10115 case 'csiso51iniscyrillic':
10116 case 'iniscyrillic':
10117 case 'isoir51':
10118 return 'INIS-cyrillic';
10119
10120 case 'csinvariant':
10121 case 'invariant':
10122 return 'INVARIANT';
10123
10124 case 'iso2022cn':
10125 return 'ISO-2022-CN';
10126
10127 case 'iso2022cnext':
10128 return 'ISO-2022-CN-EXT';
10129
10130 case 'csiso2022jp':
10131 case 'iso2022jp':
10132 return 'ISO-2022-JP';
10133
10134 case 'csiso2022jp2':
10135 case 'iso2022jp2':
10136 return 'ISO-2022-JP-2';
10137
10138 case 'csiso2022kr':
10139 case 'iso2022kr':
10140 return 'ISO-2022-KR';
10141
10142 case 'cswindows30latin1':
10143 case 'iso88591windows30latin1':
10144 return 'ISO-8859-1-Windows-3.0-Latin-1';
10145
10146 case 'cswindows31latin1':
10147 case 'iso88591windows31latin1':
10148 return 'ISO-8859-1-Windows-3.1-Latin-1';
10149
10150 case 'csisolatin2':
10151 case 'iso88592':
10152 case 'iso885921987':
10153 case 'isoir101':
10154 case 'l2':
10155 case 'latin2':
10156 return 'ISO-8859-2';
10157
10158 case 'cswindows31latin2':
10159 case 'iso88592windowslatin2':
10160 return 'ISO-8859-2-Windows-Latin-2';
10161
10162 case 'csisolatin3':
10163 case 'iso88593':
10164 case 'iso885931988':
10165 case 'isoir109':
10166 case 'l3':
10167 case 'latin3':
10168 return 'ISO-8859-3';
10169
10170 case 'csisolatin4':
10171 case 'iso88594':
10172 case 'iso885941988':
10173 case 'isoir110':
10174 case 'l4':
10175 case 'latin4':
10176 return 'ISO-8859-4';
10177
10178 case 'csisolatincyrillic':
10179 case 'cyrillic':
10180 case 'iso88595':
10181 case 'iso885951988':
10182 case 'isoir144':
10183 return 'ISO-8859-5';
10184
10185 case 'arabic':
10186 case 'asmo708':
10187 case 'csisolatinarabic':
10188 case 'ecma114':
10189 case 'iso88596':
10190 case 'iso885961987':
10191 case 'isoir127':
10192 return 'ISO-8859-6';
10193
10194 case 'csiso88596e':
10195 case 'iso88596e':
10196 return 'ISO-8859-6-E';
10197
10198 case 'csiso88596i':
10199 case 'iso88596i':
10200 return 'ISO-8859-6-I';
10201
10202 case 'csisolatingreek':
10203 case 'ecma118':
10204 case 'elot928':
10205 case 'greek':
10206 case 'greek8':
10207 case 'iso88597':
10208 case 'iso885971987':
10209 case 'isoir126':
10210 return 'ISO-8859-7';
10211
10212 case 'csisolatinhebrew':
10213 case 'hebrew':
10214 case 'iso88598':
10215 case 'iso885981988':
10216 case 'isoir138':
10217 return 'ISO-8859-8';
10218
10219 case 'csiso88598e':
10220 case 'iso88598e':
10221 return 'ISO-8859-8-E';
10222
10223 case 'csiso88598i':
10224 case 'iso88598i':
10225 return 'ISO-8859-8-I';
10226
10227 case 'cswindows31latin5':
10228 case 'iso88599windowslatin5':
10229 return 'ISO-8859-9-Windows-Latin-5';
10230
10231 case 'csisolatin6':
10232 case 'iso885910':
10233 case 'iso8859101992':
10234 case 'isoir157':
10235 case 'l6':
10236 case 'latin6':
10237 return 'ISO-8859-10';
10238
10239 case 'iso885913':
10240 return 'ISO-8859-13';
10241
10242 case 'iso885914':
10243 case 'iso8859141998':
10244 case 'isoceltic':
10245 case 'isoir199':
10246 case 'l8':
10247 case 'latin8':
10248 return 'ISO-8859-14';
10249
10250 case 'iso885915':
10251 case 'latin9':
10252 return 'ISO-8859-15';
10253
10254 case 'iso885916':
10255 case 'iso8859162001':
10256 case 'isoir226':
10257 case 'l10':
10258 case 'latin10':
10259 return 'ISO-8859-16';
10260
10261 case 'iso10646j1':
10262 return 'ISO-10646-J-1';
10263
10264 case 'csunicode':
10265 case 'iso10646ucs2':
10266 return 'ISO-10646-UCS-2';
10267
10268 case 'csucs4':
10269 case 'iso10646ucs4':
10270 return 'ISO-10646-UCS-4';
10271
10272 case 'csunicodeascii':
10273 case 'iso10646ucsbasic':
10274 return 'ISO-10646-UCS-Basic';
10275
10276 case 'csunicodelatin1':
10277 case 'iso10646':
10278 case 'iso10646unicodelatin1':
10279 return 'ISO-10646-Unicode-Latin1';
10280
10281 case 'csiso10646utf1':
10282 case 'iso10646utf1':
10283 return 'ISO-10646-UTF-1';
10284
10285 case 'csiso115481':
10286 case 'iso115481':
10287 case 'isotr115481':
10288 return 'ISO-11548-1';
10289
10290 case 'csiso90':
10291 case 'isoir90':
10292 return 'iso-ir-90';
10293
10294 case 'csunicodeibm1261':
10295 case 'isounicodeibm1261':
10296 return 'ISO-Unicode-IBM-1261';
10297
10298 case 'csunicodeibm1264':
10299 case 'isounicodeibm1264':
10300 return 'ISO-Unicode-IBM-1264';
10301
10302 case 'csunicodeibm1265':
10303 case 'isounicodeibm1265':
10304 return 'ISO-Unicode-IBM-1265';
10305
10306 case 'csunicodeibm1268':
10307 case 'isounicodeibm1268':
10308 return 'ISO-Unicode-IBM-1268';
10309
10310 case 'csunicodeibm1276':
10311 case 'isounicodeibm1276':
10312 return 'ISO-Unicode-IBM-1276';
10313
10314 case 'csiso646basic1983':
10315 case 'iso646basic1983':
10316 case 'ref':
10317 return 'ISO_646.basic:1983';
10318
10319 case 'csiso2intlrefversion':
10320 case 'irv':
10321 case 'iso646irv1983':
10322 case 'isoir2':
10323 return 'ISO_646.irv:1983';
10324
10325 case 'csiso2033':
10326 case 'e13b':
10327 case 'iso20331983':
10328 case 'isoir98':
10329 return 'ISO_2033-1983';
10330
10331 case 'csiso5427cyrillic':
10332 case 'iso5427':
10333 case 'isoir37':
10334 return 'ISO_5427';
10335
10336 case 'iso5427cyrillic1981':
10337 case 'iso54271981':
10338 case 'isoir54':
10339 return 'ISO_5427:1981';
10340
10341 case 'csiso5428greek':
10342 case 'iso54281980':
10343 case 'isoir55':
10344 return 'ISO_5428:1980';
10345
10346 case 'csiso6937add':
10347 case 'iso6937225':
10348 case 'isoir152':
10349 return 'ISO_6937-2-25';
10350
10351 case 'csisotextcomm':
10352 case 'iso69372add':
10353 case 'isoir142':
10354 return 'ISO_6937-2-add';
10355
10356 case 'csiso8859supp':
10357 case 'iso8859supp':
10358 case 'isoir154':
10359 case 'latin125':
10360 return 'ISO_8859-supp';
10361
10362 case 'csiso10367box':
10363 case 'iso10367box':
10364 case 'isoir155':
10365 return 'ISO_10367-box';
10366
10367 case 'csiso15italian':
10368 case 'iso646it':
10369 case 'isoir15':
10370 case 'it':
10371 return 'IT';
10372
10373 case 'csiso13jisc6220jp':
10374 case 'isoir13':
10375 case 'jisc62201969':
10376 case 'jisc62201969jp':
10377 case 'katakana':
10378 case 'x2017':
10379 return 'JIS_C6220-1969-jp';
10380
10381 case 'csiso14jisc6220ro':
10382 case 'iso646jp':
10383 case 'isoir14':
10384 case 'jisc62201969ro':
10385 case 'jp':
10386 return 'JIS_C6220-1969-ro';
10387
10388 case 'csiso42jisc62261978':
10389 case 'isoir42':
10390 case 'jisc62261978':
10391 return 'JIS_C6226-1978';
10392
10393 case 'csiso87jisx208':
10394 case 'isoir87':
10395 case 'jisc62261983':
10396 case 'jisx2081983':
10397 case 'x208':
10398 return 'JIS_C6226-1983';
10399
10400 case 'csiso91jisc62291984a':
10401 case 'isoir91':
10402 case 'jisc62291984a':
10403 case 'jpocra':
10404 return 'JIS_C6229-1984-a';
10405
10406 case 'csiso92jisc62991984b':
10407 case 'iso646jpocrb':
10408 case 'isoir92':
10409 case 'jisc62291984b':
10410 case 'jpocrb':
10411 return 'JIS_C6229-1984-b';
10412
10413 case 'csiso93jis62291984badd':
10414 case 'isoir93':
10415 case 'jisc62291984badd':
10416 case 'jpocrbadd':
10417 return 'JIS_C6229-1984-b-add';
10418
10419 case 'csiso94jis62291984hand':
10420 case 'isoir94':
10421 case 'jisc62291984hand':
10422 case 'jpocrhand':
10423 return 'JIS_C6229-1984-hand';
10424
10425 case 'csiso95jis62291984handadd':
10426 case 'isoir95':
10427 case 'jisc62291984handadd':
10428 case 'jpocrhandadd':
10429 return 'JIS_C6229-1984-hand-add';
10430
10431 case 'csiso96jisc62291984kana':
10432 case 'isoir96':
10433 case 'jisc62291984kana':
10434 return 'JIS_C6229-1984-kana';
10435
10436 case 'csjisencoding':
10437 case 'jisencoding':
10438 return 'JIS_Encoding';
10439
10440 case 'cshalfwidthkatakana':
10441 case 'jisx201':
10442 case 'x201':
10443 return 'JIS_X0201';
10444
10445 case 'csiso159jisx2121990':
10446 case 'isoir159':
10447 case 'jisx2121990':
10448 case 'x212':
10449 return 'JIS_X0212-1990';
10450
10451 case 'csiso141jusib1002':
10452 case 'iso646yu':
10453 case 'isoir141':
10454 case 'js':
10455 case 'jusib1002':
10456 case 'yu':
10457 return 'JUS_I.B1.002';
10458
10459 case 'csiso147macedonian':
10460 case 'isoir147':
10461 case 'jusib1003mac':
10462 case 'macedonian':
10463 return 'JUS_I.B1.003-mac';
10464
10465 case 'csiso146serbian':
10466 case 'isoir146':
10467 case 'jusib1003serb':
10468 case 'serbian':
10469 return 'JUS_I.B1.003-serb';
10470
10471 case 'koi7switched':
10472 return 'KOI7-switched';
10473
10474 case 'cskoi8r':
10475 case 'koi8r':
10476 return 'KOI8-R';
10477
10478 case 'koi8u':
10479 return 'KOI8-U';
10480
10481 case 'csksc5636':
10482 case 'iso646kr':
10483 case 'ksc5636':
10484 return 'KSC5636';
10485
10486 case 'cskz1048':
10487 case 'kz1048':
10488 case 'rk1048':
10489 case 'strk10482002':
10490 return 'KZ-1048';
10491
10492 case 'csiso19latingreek':
10493 case 'isoir19':
10494 case 'latingreek':
10495 return 'latin-greek';
10496
10497 case 'csiso27latingreek1':
10498 case 'isoir27':
10499 case 'latingreek1':
10500 return 'Latin-greek-1';
10501
10502 case 'csiso158lap':
10503 case 'isoir158':
10504 case 'lap':
10505 case 'latinlap':
10506 return 'latin-lap';
10507
10508 case 'csmacintosh':
10509 case 'mac':
10510 case 'macintosh':
10511 return 'macintosh';
10512
10513 case 'csmicrosoftpublishing':
10514 case 'microsoftpublishing':
10515 return 'Microsoft-Publishing';
10516
10517 case 'csmnem':
10518 case 'mnem':
10519 return 'MNEM';
10520
10521 case 'csmnemonic':
10522 case 'mnemonic':
10523 return 'MNEMONIC';
10524
10525 case 'csiso86hungarian':
10526 case 'hu':
10527 case 'iso646hu':
10528 case 'isoir86':
10529 case 'msz77953':
10530 return 'MSZ_7795.3';
10531
10532 case 'csnatsdano':
10533 case 'isoir91':
10534 case 'natsdano':
10535 return 'NATS-DANO';
10536
10537 case 'csnatsdanoadd':
10538 case 'isoir92':
10539 case 'natsdanoadd':
10540 return 'NATS-DANO-ADD';
10541
10542 case 'csnatssefi':
10543 case 'isoir81':
10544 case 'natssefi':
10545 return 'NATS-SEFI';
10546
10547 case 'csnatssefiadd':
10548 case 'isoir82':
10549 case 'natssefiadd':
10550 return 'NATS-SEFI-ADD';
10551
10552 case 'csiso151cuba':
10553 case 'cuba':
10554 case 'iso646cu':
10555 case 'isoir151':
10556 case 'ncnc1081':
10557 return 'NC_NC00-10:81';
10558
10559 case 'csiso69french':
10560 case 'fr':
10561 case 'iso646fr':
10562 case 'isoir69':
10563 case 'nfz62010':
10564 return 'NF_Z_62-010';
10565
10566 case 'csiso25french':
10567 case 'iso646fr1':
10568 case 'isoir25':
10569 case 'nfz620101973':
10570 return 'NF_Z_62-010_(1973)';
10571
10572 case 'csiso60danishnorwegian':
10573 case 'csiso60norwegian1':
10574 case 'iso646no':
10575 case 'isoir60':
10576 case 'no':
10577 case 'ns45511':
10578 return 'NS_4551-1';
10579
10580 case 'csiso61norwegian2':
10581 case 'iso646no2':
10582 case 'isoir61':
10583 case 'no2':
10584 case 'ns45512':
10585 return 'NS_4551-2';
10586
10587 case 'osdebcdicdf3irv':
10588 return 'OSD_EBCDIC_DF03_IRV';
10589
10590 case 'osdebcdicdf41':
10591 return 'OSD_EBCDIC_DF04_1';
10592
10593 case 'osdebcdicdf415':
10594 return 'OSD_EBCDIC_DF04_15';
10595
10596 case 'cspc8danishnorwegian':
10597 case 'pc8danishnorwegian':
10598 return 'PC8-Danish-Norwegian';
10599
10600 case 'cspc8turkish':
10601 case 'pc8turkish':
10602 return 'PC8-Turkish';
10603
10604 case 'csiso16portuguese':
10605 case 'iso646pt':
10606 case 'isoir16':
10607 case 'pt':
10608 return 'PT';
10609
10610 case 'csiso84portuguese2':
10611 case 'iso646pt2':
10612 case 'isoir84':
10613 case 'pt2':
10614 return 'PT2';
10615
10616 case 'cp154':
10617 case 'csptcp154':
10618 case 'cyrillicasian':
10619 case 'pt154':
10620 case 'ptcp154':
10621 return 'PTCP154';
10622
10623 case 'scsu':
10624 return 'SCSU';
10625
10626 case 'csiso10swedish':
10627 case 'fi':
10628 case 'iso646fi':
10629 case 'iso646se':
10630 case 'isoir10':
10631 case 'se':
10632 case 'sen850200b':
10633 return 'SEN_850200_B';
10634
10635 case 'csiso11swedishfornames':
10636 case 'iso646se2':
10637 case 'isoir11':
10638 case 'se2':
10639 case 'sen850200c':
10640 return 'SEN_850200_C';
10641
10642 case 'csiso102t617bit':
10643 case 'isoir102':
10644 case 't617bit':
10645 return 'T.61-7bit';
10646
10647 case 'csiso103t618bit':
10648 case 'isoir103':
10649 case 't61':
10650 case 't618bit':
10651 return 'T.61-8bit';
10652
10653 case 'csiso128t101g2':
10654 case 'isoir128':
10655 case 't101g2':
10656 return 'T.101-G2';
10657
10658 case 'cstscii':
10659 case 'tscii':
10660 return 'TSCII';
10661
10662 case 'csunicode11':
10663 case 'unicode11':
10664 return 'UNICODE-1-1';
10665
10666 case 'csunicode11utf7':
10667 case 'unicode11utf7':
10668 return 'UNICODE-1-1-UTF-7';
10669
10670 case 'csunknown8bit':
10671 case 'unknown8bit':
10672 return 'UNKNOWN-8BIT';
10673
10674 case 'ansix341968':
10675 case 'ansix341986':
10676 case 'ascii':
10677 case 'cp367':
10678 case 'csascii':
10679 case 'ibm367':
10680 case 'iso646irv1991':
10681 case 'iso646us':
10682 case 'isoir6':
10683 case 'us':
10684 case 'usascii':
10685 return 'US-ASCII';
10686
10687 case 'csusdk':
10688 case 'usdk':
10689 return 'us-dk';
10690
10691 case 'utf7':
10692 return 'UTF-7';
10693
10694 case 'utf8':
10695 return 'UTF-8';
10696
10697 case 'utf16':
10698 return 'UTF-16';
10699
10700 case 'utf16be':
10701 return 'UTF-16BE';
10702
10703 case 'utf16le':
10704 return 'UTF-16LE';
10705
10706 case 'utf32':
10707 return 'UTF-32';
10708
10709 case 'utf32be':
10710 return 'UTF-32BE';
10711
10712 case 'utf32le':
10713 return 'UTF-32LE';
10714
10715 case 'csventurainternational':
10716 case 'venturainternational':
10717 return 'Ventura-International';
10718
10719 case 'csventuramath':
10720 case 'venturamath':
10721 return 'Ventura-Math';
10722
10723 case 'csventuraus':
10724 case 'venturaus':
10725 return 'Ventura-US';
10726
10727 case 'csiso70videotexsupp1':
10728 case 'isoir70':
10729 case 'videotexsuppl':
10730 return 'videotex-suppl';
10731
10732 case 'csviqr':
10733 case 'viqr':
10734 return 'VIQR';
10735
10736 case 'csviscii':
10737 case 'viscii':
10738 return 'VISCII';
10739
10740 case 'csshiftjis':
10741 case 'cswindows31j':
10742 case 'mskanji':
10743 case 'shiftjis':
10744 case 'windows31j':
10745 return 'Windows-31J';
10746
10747 case 'iso885911':
10748 case 'tis620':
10749 return 'windows-874';
10750
10751 case 'cseuckr':
10752 case 'csksc56011987':
10753 case 'euckr':
10754 case 'isoir149':
10755 case 'korean':
10756 case 'ksc5601':
10757 case 'ksc56011987':
10758 case 'ksc56011989':
10759 case 'windows949':
10760 return 'windows-949';
10761
10762 case 'windows1250':
10763 return 'windows-1250';
10764
10765 case 'windows1251':
10766 return 'windows-1251';
10767
10768 case 'cp819':
10769 case 'csisolatin1':
10770 case 'ibm819':
10771 case 'iso88591':
10772 case 'iso885911987':
10773 case 'isoir100':
10774 case 'l1':
10775 case 'latin1':
10776 case 'windows1252':
10777 return 'windows-1252';
10778
10779 case 'windows1253':
10780 return 'windows-1253';
10781
10782 case 'csisolatin5':
10783 case 'iso88599':
10784 case 'iso885991989':
10785 case 'isoir148':
10786 case 'l5':
10787 case 'latin5':
10788 case 'windows1254':
10789 return 'windows-1254';
10790
10791 case 'windows1255':
10792 return 'windows-1255';
10793
10794 case 'windows1256':
10795 return 'windows-1256';
10796
10797 case 'windows1257':
10798 return 'windows-1257';
10799
10800 case 'windows1258':
10801 return 'windows-1258';
10802
10803 default:
10804 return $charset;
10805 }
10806 }
10807
10808 function get_curl_version()
10809 {
10810 if (is_array($curl = curl_version()))
10811 {
10812 $curl = $curl['version'];
10813 }
10814 elseif (substr($curl, 0, 5) === 'curl/')
10815 {
10816 $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10817 }
10818 elseif (substr($curl, 0, 8) === 'libcurl/')
10819 {
10820 $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10821 }
10822 else
10823 {
10824 $curl = 0;
10825 }
10826 return $curl;
10827 }
10828
10829 function is_subclass_of($class1, $class2)
10830 {
10831 if (func_num_args() !== 2)
10832 {
10833 trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10834 }
10835 elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10836 {
10837 return is_subclass_of($class1, $class2);
10838 }
10839 elseif (is_string($class1) && is_string($class2))
10840 {
10841 if (class_exists($class1))
10842 {
10843 if (class_exists($class2))
10844 {
10845 $class2 = strtolower($class2);
10846 while ($class1 = strtolower(get_parent_class($class1)))
10847 {
10848 if ($class1 === $class2)
10849 {
10850 return true;
10851 }
10852 }
10853 }
10854 }
10855 else
10856 {
10857 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10858 }
10859 }
10860 return false;
10861 }
10862
10863 /**
10864 * Strip HTML comments
10865 *
10866 * @access public
10867 * @param string $data Data to strip comments from
10868 * @return string Comment stripped string
10869 */
10870 function strip_comments($data)
10871 {
10872 $output = '';
10873 while (($start = strpos($data, '<!--')) !== false)
10874 {
10875 $output .= substr($data, 0, $start);
10876 if (($end = strpos($data, '-->', $start)) !== false)
10877 {
10878 $data = substr_replace($data, '', 0, $end + 3);
10879 }
10880 else
10881 {
10882 $data = '';
10883 }
10884 }
10885 return $output . $data;
10886 }
10887
10888 function parse_date($dt)
10889 {
10890 $parser = SimplePie_Parse_Date::get();
10891 return $parser->parse($dt);
10892 }
10893
10894 /**
10895 * Decode HTML entities
10896 *
10897 * @static
10898 * @access public
10899 * @param string $data Input data
10900 * @return string Output data
10901 */
10902 function entities_decode($data)
10903 {
10904 $decoder =& new SimplePie_Decode_HTML_Entities($data);
10905 return $decoder->parse();
10906 }
10907
10908 /**
10909 * Remove RFC822 comments
10910 *
10911 * @access public
10912 * @param string $data Data to strip comments from
10913 * @return string Comment stripped string
10914 */
10915 function uncomment_rfc822($string)
10916 {
10917 $string = (string) $string;
10918 $position = 0;
10919 $length = strlen($string);
10920 $depth = 0;
10921
10922 $output = '';
10923
10924 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
10925 {
10926 $output .= substr($string, $position, $pos - $position);
10927 $position = $pos + 1;
10928 if ($string[$pos - 1] !== '\\')
10929 {
10930 $depth++;
10931 while ($depth && $position < $length)
10932 {
10933 $position += strcspn($string, '()', $position);
10934 if ($string[$position - 1] === '\\')
10935 {
10936 $position++;
10937 continue;
10938 }
10939 elseif (isset($string[$position]))
10940 {
10941 switch ($string[$position])
10942 {
10943 case '(':
10944 $depth++;
10945 break;
10946
10947 case ')':
10948 $depth--;
10949 break;
10950 }
10951 $position++;
10952 }
10953 else
10954 {
10955 break;
10956 }
10957 }
10958 }
10959 else
10960 {
10961 $output .= '(';
10962 }
10963 }
10964 $output .= substr($string, $position);
10965
10966 return $output;
10967 }
10968
10969 function parse_mime($mime)
10970 {
10971 if (($pos = strpos($mime, ';')) === false)
10972 {
10973 return trim($mime);
10974 }
10975 else
10976 {
10977 return trim(substr($mime, 0, $pos));
10978 }
10979 }
10980
10981 function htmlspecialchars_decode($string, $quote_style)
10982 {
10983 if (function_exists('htmlspecialchars_decode'))
10984 {
10985 return htmlspecialchars_decode($string, $quote_style);
10986 }
10987 else
10988 {
10989 return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
10990 }
10991 }
10992
10993 function atom_03_construct_type($attribs)
10994 {
10995 if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
10996 {
10997 $mode = SIMPLEPIE_CONSTRUCT_BASE64;
10998 }
10999 else
11000 {
11001 $mode = SIMPLEPIE_CONSTRUCT_NONE;
11002 }
11003 if (isset($attribs['']['type']))
11004 {
11005 switch (strtolower(trim($attribs['']['type'])))
11006 {
11007 case 'text':
11008 case 'text/plain':
11009 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11010
11011 case 'html':
11012 case 'text/html':
11013 return SIMPLEPIE_CONSTRUCT_HTML | $mode;
11014
11015 case 'xhtml':
11016 case 'application/xhtml+xml':
11017 return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
11018
11019 default:
11020 return SIMPLEPIE_CONSTRUCT_NONE | $mode;
11021 }
11022 }
11023 else
11024 {
11025 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11026 }
11027 }
11028
11029 function atom_10_construct_type($attribs)
11030 {
11031 if (isset($attribs['']['type']))
11032 {
11033 switch (strtolower(trim($attribs['']['type'])))
11034 {
11035 case 'text':
11036 return SIMPLEPIE_CONSTRUCT_TEXT;
11037
11038 case 'html':
11039 return SIMPLEPIE_CONSTRUCT_HTML;
11040
11041 case 'xhtml':
11042 return SIMPLEPIE_CONSTRUCT_XHTML;
11043
11044 default:
11045 return SIMPLEPIE_CONSTRUCT_NONE;
11046 }
11047 }
11048 return SIMPLEPIE_CONSTRUCT_TEXT;
11049 }
11050
11051 function atom_10_content_construct_type($attribs)
11052 {
11053 if (isset($attribs['']['type']))
11054 {
11055 $type = strtolower(trim($attribs['']['type']));
11056 switch ($type)
11057 {
11058 case 'text':
11059 return SIMPLEPIE_CONSTRUCT_TEXT;
11060
11061 case 'html':
11062 return SIMPLEPIE_CONSTRUCT_HTML;
11063
11064 case 'xhtml':
11065 return SIMPLEPIE_CONSTRUCT_XHTML;
11066 }
11067 if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
11068 {
11069 return SIMPLEPIE_CONSTRUCT_NONE;
11070 }
11071 else
11072 {
11073 return SIMPLEPIE_CONSTRUCT_BASE64;
11074 }
11075 }
11076 else
11077 {
11078 return SIMPLEPIE_CONSTRUCT_TEXT;
11079 }
11080 }
11081
11082 function is_isegment_nz_nc($string)
11083 {
11084 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);
11085 }
11086
11087 function space_seperated_tokens($string)
11088 {
11089 $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
11090 $string_length = strlen($string);
11091
11092 $position = strspn($string, $space_characters);
11093 $tokens = array();
11094
11095 while ($position < $string_length)
11096 {
11097 $len = strcspn($string, $space_characters, $position);
11098 $tokens[] = substr($string, $position, $len);
11099 $position += $len;
11100 $position += strspn($string, $space_characters, $position);
11101 }
11102
11103 return $tokens;
11104 }
11105
11106 function array_unique($array)
11107 {
11108 if (version_compare(PHP_VERSION, '5.2', '>='))
11109 {
11110 return array_unique($array);
11111 }
11112 else
11113 {
11114 $array = (array) $array;
11115 $new_array = array();
11116 $new_array_strings = array();
11117 foreach ($array as $key => $value)
11118 {
11119 if (is_object($value))
11120 {
11121 if (method_exists($value, '__toString'))
11122 {
11123 $cmp = $value->__toString();
11124 }
11125 else
11126 {
11127 trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
11128 }
11129 }
11130 elseif (is_array($value))
11131 {
11132 $cmp = (string) reset($value);
11133 }
11134 else
11135 {
11136 $cmp = (string) $value;
11137 }
11138 if (!in_array($cmp, $new_array_strings))
11139 {
11140 $new_array[$key] = $value;
11141 $new_array_strings[] = $cmp;
11142 }
11143 }
11144 return $new_array;
11145 }
11146 }
11147
11148 /**
11149 * Converts a unicode codepoint to a UTF-8 character
11150 *
11151 * @static
11152 * @access public
11153 * @param int $codepoint Unicode codepoint
11154 * @return string UTF-8 character
11155 */
11156 function codepoint_to_utf8($codepoint)
11157 {
11158 $codepoint = (int) $codepoint;
11159 if ($codepoint < 0)
11160 {
11161 return false;
11162 }
11163 else if ($codepoint <= 0x7f)
11164 {
11165 return chr($codepoint);
11166 }
11167 else if ($codepoint <= 0x7ff)
11168 {
11169 return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
11170 }
11171 else if ($codepoint <= 0xffff)
11172 {
11173 return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11174 }
11175 else if ($codepoint <= 0x10ffff)
11176 {
11177 return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11178 }
11179 else
11180 {
11181 // U+FFFD REPLACEMENT CHARACTER
11182 return "\xEF\xBF\xBD";
11183 }
11184 }
11185
11186 /**
11187 * Re-implementation of PHP 5's stripos()
11188 *
11189 * Returns the numeric position of the first occurrence of needle in the
11190 * haystack string.
11191 *
11192 * @static
11193 * @access string
11194 * @param object $haystack
11195 * @param string $needle Note that the needle may be a string of one or more
11196 * characters. If needle is not a string, it is converted to an integer
11197 * and applied as the ordinal value of a character.
11198 * @param int $offset The optional offset parameter allows you to specify which
11199 * character in haystack to start searching. The position returned is still
11200 * relative to the beginning of haystack.
11201 * @return bool If needle is not found, stripos() will return boolean false.
11202 */
11203 function stripos($haystack, $needle, $offset = 0)
11204 {
11205 if (function_exists('stripos'))
11206 {
11207 return stripos($haystack, $needle, $offset);
11208 }
11209 else
11210 {
11211 if (is_string($needle))
11212 {
11213 $needle = strtolower($needle);
11214 }
11215 elseif (is_int($needle) || is_bool($needle) || is_double($needle))
11216 {
11217 $needle = strtolower(chr($needle));
11218 }
11219 else
11220 {
11221 trigger_error('needle is not a string or an integer', E_USER_WARNING);
11222 return false;
11223 }
11224
11225 return strpos(strtolower($haystack), $needle, $offset);
11226 }
11227 }
11228
11229 /**
11230 * Similar to parse_str()
11231 *
11232 * Returns an associative array of name/value pairs, where the value is an
11233 * array of values that have used the same name
11234 *
11235 * @static
11236 * @access string
11237 * @param string $str The input string.
11238 * @return array
11239 */
11240 function parse_str($str)
11241 {
11242 $return = array();
11243 $str = explode('&', $str);
11244
11245 foreach ($str as $section)
11246 {
11247 if (strpos($section, '=') !== false)
11248 {
11249 list($name, $value) = explode('=', $section, 2);
11250 $return[urldecode($name)][] = urldecode($value);
11251 }
11252 else
11253 {
11254 $return[urldecode($section)][] = null;
11255 }
11256 }
11257
11258 return $return;
11259 }
11260
11261 /**
11262 * Detect XML encoding, as per XML 1.0 Appendix F.1
11263 *
11264 * @todo Add support for EBCDIC
11265 * @param string $data XML data
11266 * @return array Possible encodings
11267 */
11268 function xml_encoding($data)
11269 {
11270 // UTF-32 Big Endian BOM
11271 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
11272 {
11273 $encoding[] = 'UTF-32BE';
11274 }
11275 // UTF-32 Little Endian BOM
11276 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
11277 {
11278 $encoding[] = 'UTF-32LE';
11279 }
11280 // UTF-16 Big Endian BOM
11281 elseif (substr($data, 0, 2) === "\xFE\xFF")
11282 {
11283 $encoding[] = 'UTF-16BE';
11284 }
11285 // UTF-16 Little Endian BOM
11286 elseif (substr($data, 0, 2) === "\xFF\xFE")
11287 {
11288 $encoding[] = 'UTF-16LE';
11289 }
11290 // UTF-8 BOM
11291 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
11292 {
11293 $encoding[] = 'UTF-8';
11294 }
11295 // UTF-32 Big Endian Without BOM
11296 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")
11297 {
11298 if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
11299 {
11300 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
11301 if ($parser->parse())
11302 {
11303 $encoding[] = $parser->encoding;
11304 }
11305 }
11306 $encoding[] = 'UTF-32BE';
11307 }
11308 // UTF-32 Little Endian Without BOM
11309 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")
11310 {
11311 if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
11312 {
11313 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
11314 if ($parser->parse())
11315 {
11316 $encoding[] = $parser->encoding;
11317 }
11318 }
11319 $encoding[] = 'UTF-32LE';
11320 }
11321 // UTF-16 Big Endian Without BOM
11322 elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
11323 {
11324 if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
11325 {
11326 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
11327 if ($parser->parse())
11328 {
11329 $encoding[] = $parser->encoding;
11330 }
11331 }
11332 $encoding[] = 'UTF-16BE';
11333 }
11334 // UTF-16 Little Endian Without BOM
11335 elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
11336 {
11337 if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
11338 {
11339 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
11340 if ($parser->parse())
11341 {
11342 $encoding[] = $parser->encoding;
11343 }
11344 }
11345 $encoding[] = 'UTF-16LE';
11346 }
11347 // US-ASCII (or superset)
11348 elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
11349 {
11350 if ($pos = strpos($data, "\x3F\x3E"))
11351 {
11352 $parser =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
11353 if ($parser->parse())
11354 {
11355 $encoding[] = $parser->encoding;
11356 }
11357 }
11358 $encoding[] = 'UTF-8';
11359 }
11360 // Fallback to UTF-8
11361 else
11362 {
11363 $encoding[] = 'UTF-8';
11364 }
11365 return $encoding;
11366 }
11367
11368 function output_javascript()
11369 {
11370 if (function_exists('ob_gzhandler'))
11371 {
11372 ob_start('ob_gzhandler');
11373 }
11374 header('Content-type: text/javascript; charset: UTF-8');
11375 header('Cache-Control: must-revalidate');
11376 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
11377 ?>
11378 function embed_odeo(link) {
11379 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>');
11380 }
11381
11382 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
11383 if (placeholder != '') {
11384 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>');
11385 }
11386 else {
11387 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>');
11388 }
11389 }
11390
11391 function embed_flash(bgcolor, width, height, link, loop, type) {
11392 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>');
11393 }
11394
11395 function embed_flv(width, height, link, placeholder, loop, player) {
11396 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>');
11397 }
11398
11399 function embed_wmedia(width, height, link) {
11400 document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
11401 }
11402 <?php
11403 }
11404
11405
11406
11407 /**
11408 * Format debugging information
11409 */
11410 function debug($sp)
11411 {
11412 $info = 'SimplePie ' . SIMPLEPIE_VERSION . ' Build ' . SIMPLEPIE_BUILD . "\n";
11413 $info .= 'PHP ' . PHP_VERSION . "\n";
11414 if ($sp->error() !== null)
11415 {
11416 $info .= 'Error occurred: ' . $sp->error() . "\n";
11417 }
11418 else
11419 {
11420 $info .= "No error found.\n";
11421 }
11422 $info .= "Extensions:\n";
11423 $extensions = array('pcre', 'curl', 'zlib', 'mbstring', 'iconv', 'xmlreader', 'xml');
11424 foreach ($extensions as $ext)
11425 {
11426 if (extension_loaded($ext))
11427 {
11428 $info .= " $ext loaded\n";
11429 switch ($ext)
11430 {
11431 case 'pcre':
11432 $info .= ' Version ' . PCRE_VERSION . "\n";
11433 break;
11434 case 'curl':
11435 $version = curl_version();
11436 $info .= ' Version ' . $version['version'] . "\n";
11437 break;
11438 case 'mbstring':
11439 $info .= ' Overloading: ' . mb_get_info('func_overload') . "\n";
11440 break;
11441 case 'iconv':
11442 $info .= ' Version ' . ICONV_VERSION . "\n";
11443 break;
11444 case 'xml':
11445 $info .= ' Version ' . LIBXML_DOTTED_VERSION . "\n";
11446 break;
11447 }
11448 }
11449 else
11450 {
11451 $info .= " $ext not loaded\n";
11452 }
11453 }
11454 return $info;
11455 }
11456 }
11457
11458 /**
11459 * Decode HTML Entities
11460 *
11461 * This implements HTML5 as of revision 967 (2007-06-28)
11462 *
11463 * @package SimplePie
11464 */
11465 class SimplePie_Decode_HTML_Entities
11466 {
11467 /**
11468 * Data to be parsed
11469 *
11470 * @access private
11471 * @var string
11472 */
11473 var $data = '';
11474
11475 /**
11476 * Currently consumed bytes
11477 *
11478 * @access private
11479 * @var string
11480 */
11481 var $consumed = '';
11482
11483 /**
11484 * Position of the current byte being parsed
11485 *
11486 * @access private
11487 * @var int
11488 */
11489 var $position = 0;
11490
11491 /**
11492 * Create an instance of the class with the input data
11493 *
11494 * @access public
11495 * @param string $data Input data
11496 */
11497 function SimplePie_Decode_HTML_Entities($data)
11498 {
11499 $this->data = $data;
11500 }
11501
11502 /**
11503 * Parse the input data
11504 *
11505 * @access public
11506 * @return string Output data
11507 */
11508 function parse()
11509 {
11510 while (($this->position = strpos($this->data, '&', $this->position)) !== false)
11511 {
11512 $this->consume();
11513 $this->entity();
11514 $this->consumed = '';
11515 }
11516 return $this->data;
11517 }
11518
11519 /**
11520 * Consume the next byte
11521 *
11522 * @access private
11523 * @return mixed The next byte, or false, if there is no more data
11524 */
11525 function consume()
11526 {
11527 if (isset($this->data[$this->position]))
11528 {
11529 $this->consumed .= $this->data[$this->position];
11530 return $this->data[$this->position++];
11531 }
11532 else
11533 {
11534 return false;
11535 }
11536 }
11537
11538 /**
11539 * Consume a range of characters
11540 *
11541 * @access private
11542 * @param string $chars Characters to consume
11543 * @return mixed A series of characters that match the range, or false
11544 */
11545 function consume_range($chars)
11546 {
11547 if ($len = strspn($this->data, $chars, $this->position))
11548 {
11549 $data = substr($this->data, $this->position, $len);
11550 $this->consumed .= $data;
11551 $this->position += $len;
11552 return $data;
11553 }
11554 else
11555 {
11556 return false;
11557 }
11558 }
11559
11560 /**
11561 * Unconsume one byte
11562 *
11563 * @access private
11564 */
11565 function unconsume()
11566 {
11567 $this->consumed = substr($this->consumed, 0, -1);
11568 $this->position--;
11569 }
11570
11571 /**
11572 * Decode an entity
11573 *
11574 * @access private
11575 */
11576 function entity()
11577 {
11578 switch ($this->consume())
11579 {
11580 case "\x09":
11581 case "\x0A":
11582 case "\x0B":
11583 case "\x0B":
11584 case "\x0C":
11585 case "\x20":
11586 case "\x3C":
11587 case "\x26":
11588 case false:
11589 break;
11590
11591 case "\x23":
11592 switch ($this->consume())
11593 {
11594 case "\x78":
11595 case "\x58":
11596 $range = '0123456789ABCDEFabcdef';
11597 $hex = true;
11598 break;
11599
11600 default:
11601 $range = '0123456789';
11602 $hex = false;
11603 $this->unconsume();
11604 break;
11605 }
11606
11607 if ($codepoint = $this->consume_range($range))
11608 {
11609 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");
11610
11611 if ($hex)
11612 {
11613 $codepoint = hexdec($codepoint);
11614 }
11615 else
11616 {
11617 $codepoint = intval($codepoint);
11618 }
11619
11620 if (isset($windows_1252_specials[$codepoint]))
11621 {
11622 $replacement = $windows_1252_specials[$codepoint];
11623 }
11624 else
11625 {
11626 $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
11627 }
11628
11629 if (!in_array($this->consume(), array(';', false), true))
11630 {
11631 $this->unconsume();
11632 }
11633
11634 $consumed_length = strlen($this->consumed);
11635 $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
11636 $this->position += strlen($replacement) - $consumed_length;
11637 }
11638 break;
11639
11640 default:
11641 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");
11642
11643 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
11644 {
11645 $consumed = substr($this->consumed, 1);
11646 if (isset($entities[$consumed]))
11647 {
11648 $match = $consumed;
11649 }
11650 }
11651
11652 if ($match !== null)
11653 {
11654 $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
11655 $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
11656 }
11657 break;
11658 }
11659 }
11660 }
11661
11662 /**
11663 * IRI parser/serialiser
11664 *
11665 * @package SimplePie
11666 */
11667 class SimplePie_IRI
11668 {
11669 /**
11670 * Scheme
11671 *
11672 * @access private
11673 * @var string
11674 */
11675 var $scheme;
11676
11677 /**
11678 * User Information
11679 *
11680 * @access private
11681 * @var string
11682 */
11683 var $userinfo;
11684
11685 /**
11686 * Host
11687 *
11688 * @access private
11689 * @var string
11690 */
11691 var $host;
11692
11693 /**
11694 * Port
11695 *
11696 * @access private
11697 * @var string
11698 */
11699 var $port;
11700
11701 /**
11702 * Path
11703 *
11704 * @access private
11705 * @var string
11706 */
11707 var $path;
11708
11709 /**
11710 * Query
11711 *
11712 * @access private
11713 * @var string
11714 */
11715 var $query;
11716
11717 /**
11718 * Fragment
11719 *
11720 * @access private
11721 * @var string
11722 */
11723 var $fragment;
11724
11725 /**
11726 * Whether the object represents a valid IRI
11727 *
11728 * @access private
11729 * @var array
11730 */
11731 var $valid = array();
11732
11733 /**
11734 * Return the entire IRI when you try and read the object as a string
11735 *
11736 * @access public
11737 * @return string
11738 */
11739 function __toString()
11740 {
11741 return $this->get_iri();
11742 }
11743
11744 /**
11745 * Create a new IRI object, from a specified string
11746 *
11747 * @access public
11748 * @param string $iri
11749 * @return SimplePie_IRI
11750 */
11751 function SimplePie_IRI($iri)
11752 {
11753 $iri = (string) $iri;
11754 if ($iri !== '')
11755 {
11756 $parsed = $this->parse_iri($iri);
11757 $this->set_scheme($parsed['scheme']);
11758 $this->set_authority($parsed['authority']);
11759 $this->set_path($parsed['path']);
11760 $this->set_query($parsed['query']);
11761 $this->set_fragment($parsed['fragment']);
11762 }
11763 }
11764
11765 /**
11766 * Create a new IRI object by resolving a relative IRI
11767 *
11768 * @static
11769 * @access public
11770 * @param SimplePie_IRI $base Base IRI
11771 * @param string $relative Relative IRI
11772 * @return SimplePie_IRI
11773 */
11774 function absolutize($base, $relative)
11775 {
11776 $relative = (string) $relative;
11777 if ($relative !== '')
11778 {
11779 $relative =& new SimplePie_IRI($relative);
11780 if ($relative->get_scheme() !== null)
11781 {
11782 $target = $relative;
11783 }
11784 elseif ($base->get_iri() !== null)
11785 {
11786 if ($relative->get_authority() !== null)
11787 {
11788 $target = $relative;
11789 $target->set_scheme($base->get_scheme());
11790 }
11791 else
11792 {
11793 $target =& new SimplePie_IRI('');
11794 $target->set_scheme($base->get_scheme());
11795 $target->set_userinfo($base->get_userinfo());
11796 $target->set_host($base->get_host());
11797 $target->set_port($base->get_port());
11798 if ($relative->get_path() !== null)
11799 {
11800 if (strpos($relative->get_path(), '/') === 0)
11801 {
11802 $target->set_path($relative->get_path());
11803 }
11804 elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
11805 {
11806 $target->set_path('/' . $relative->get_path());
11807 }
11808 elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
11809 {
11810 $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
11811 }
11812 else
11813 {
11814 $target->set_path($relative->get_path());
11815 }
11816 $target->set_query($relative->get_query());
11817 }
11818 else
11819 {
11820 $target->set_path($base->get_path());
11821 if ($relative->get_query() !== null)
11822 {
11823 $target->set_query($relative->get_query());
11824 }
11825 elseif ($base->get_query() !== null)
11826 {
11827 $target->set_query($base->get_query());
11828 }
11829 }
11830 }
11831 $target->set_fragment($relative->get_fragment());
11832 }
11833 else
11834 {
11835 // No base URL, just return the relative URL
11836 $target = $relative;
11837 }
11838 }
11839 else
11840 {
11841 $target = $base;
11842 }
11843 return $target;
11844 }
11845
11846 /**
11847 * Parse an IRI into scheme/authority/path/query/fragment segments
11848 *
11849 * @access private
11850 * @param string $iri
11851 * @return array
11852 */
11853 function parse_iri($iri)
11854 {
11855 preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
11856 for ($i = count($match); $i <= 9; $i++)
11857 {
11858 $match[$i] = '';
11859 }
11860 return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
11861 }
11862
11863 /**
11864 * Remove dot segments from a path
11865 *
11866 * @access private
11867 * @param string $input
11868 * @return string
11869 */
11870 function remove_dot_segments($input)
11871 {
11872 $output = '';
11873 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
11874 {
11875 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
11876 if (strpos($input, '../') === 0)
11877 {
11878 $input = substr($input, 3);
11879 }
11880 elseif (strpos($input, './') === 0)
11881 {
11882 $input = substr($input, 2);
11883 }
11884 // 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,
11885 elseif (strpos($input, '/./') === 0)
11886 {
11887 $input = substr_replace($input, '/', 0, 3);
11888 }
11889 elseif ($input === '/.')
11890 {
11891 $input = '/';
11892 }
11893 // 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,
11894 elseif (strpos($input, '/../') === 0)
11895 {
11896 $input = substr_replace($input, '/', 0, 4);
11897 $output = substr_replace($output, '', strrpos($output, '/'));
11898 }
11899 elseif ($input === '/..')
11900 {
11901 $input = '/';
11902 $output = substr_replace($output, '', strrpos($output, '/'));
11903 }
11904 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
11905 elseif ($input === '.' || $input === '..')
11906 {
11907 $input = '';
11908 }
11909 // 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
11910 elseif (($pos = strpos($input, '/', 1)) !== false)
11911 {
11912 $output .= substr($input, 0, $pos);
11913 $input = substr_replace($input, '', 0, $pos);
11914 }
11915 else
11916 {
11917 $output .= $input;
11918 $input = '';
11919 }
11920 }
11921 return $output . $input;
11922 }
11923
11924 /**
11925 * Replace invalid character with percent encoding
11926 *
11927 * @param string $string Input string
11928 * @param string $valid_chars Valid characters
11929 * @param int $case Normalise case
11930 * @return string
11931 */
11932 function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE, $iprivate = false)
11933 {
11934 // Normalize as many pct-encoded sections as possible
11935 $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array(&$this, 'remove_iunreserved_percent_encoded'), $string);
11936
11937 // Replace invalid percent characters
11938 $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string);
11939
11940 // Add unreserved and % to $valid_chars (the latter is safe because all
11941 // pct-encoded sections are now valid).
11942 $valid_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%';
11943
11944 // Now replace any bytes that aren't allowed with their pct-encoded versions
11945 $position = 0;
11946 $strlen = strlen($string);
11947 while (($position += strspn($string, $valid_chars, $position)) < $strlen)
11948 {
11949 $value = ord($string[$position]);
11950
11951 // Start position
11952 $start = $position;
11953
11954 // By default we are valid
11955 $valid = true;
11956
11957 // No one byte sequences are valid due to the while.
11958 // Two byte sequence:
11959 if (($value & 0xE0) === 0xC0)
11960 {
11961 $character = ($value & 0x1F) << 6;
11962 $length = 2;
11963 $remaining = 1;
11964 }
11965 // Three byte sequence:
11966 elseif (($value & 0xF0) === 0xE0)
11967 {
11968 $character = ($value & 0x0F) << 12;
11969 $length = 3;
11970 $remaining = 2;
11971 }
11972 // Four byte sequence:
11973 elseif (($value & 0xF8) === 0xF0)
11974 {
11975 $character = ($value & 0x07) << 18;
11976 $length = 4;
11977 $remaining = 3;
11978 }
11979 // Invalid byte:
11980 else
11981 {
11982 $valid = false;
11983 $length = 1;
11984 $remaining = 0;
11985 }
11986
11987 if ($remaining)
11988 {
11989 if ($position + $length <= $strlen)
11990 {
11991 for ($position++; $remaining; $position++)
11992 {
11993 $value = ord($string[$position]);
11994
11995 // Check that the byte is valid, then add it to the character:
11996 if (($value & 0xC0) === 0x80)
11997 {
11998 $character |= ($value & 0x3F) << (--$remaining * 6);
11999 }
12000 // If it is invalid, count the sequence as invalid and reprocess the current byte:
12001 else
12002 {
12003 $valid = false;
12004 $position--;
12005 break;
12006 }
12007 }
12008 }
12009 else
12010 {
12011 $position = $strlen - 1;
12012 $valid = false;
12013 }
12014 }
12015
12016 // Percent encode anything invalid or not in ucschar
12017 if (
12018 // Invalid sequences
12019 !$valid
12020 // Non-shortest form sequences are invalid
12021 || $length > 1 && $character <= 0x7F
12022 || $length > 2 && $character <= 0x7FF
12023 || $length > 3 && $character <= 0xFFFF
12024 // Outside of range of ucschar codepoints
12025 // Noncharacters
12026 || ($character & 0xFFFE) === 0xFFFE
12027 || $character >= 0xFDD0 && $character <= 0xFDEF
12028 || (
12029 // Everything else not in ucschar
12030 $character > 0xD7FF && $character < 0xF900
12031 || $character < 0xA0
12032 || $character > 0xEFFFD
12033 )
12034 && (
12035 // Everything not in iprivate, if it applies
12036 !$iprivate
12037 || $character < 0xE000
12038 || $character > 0x10FFFD
12039 )
12040 )
12041 {
12042 // If we were a character, pretend we weren't, but rather an error.
12043 if ($valid)
12044 $position--;
12045
12046 for ($j = $start; $j <= $position; $j++)
12047 {
12048 $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1);
12049 $j += 2;
12050 $position += 2;
12051 $strlen += 2;
12052 }
12053 }
12054 }
12055
12056 // Normalise case
12057 if ($case & SIMPLEPIE_LOWERCASE)
12058 {
12059 $string = strtolower($string);
12060 }
12061 elseif ($case & SIMPLEPIE_UPPERCASE)
12062 {
12063 $string = strtoupper($string);
12064 }
12065
12066 return $string;
12067 }
12068
12069 /**
12070 * Callback function for preg_replace_callback.
12071 *
12072 * Removes sequences of percent encoded bytes that represent UTF-8
12073 * encoded characters in iunreserved
12074 *
12075 * @access private
12076 * @param array $match PCRE match
12077 * @return string Replacement
12078 */
12079 function remove_iunreserved_percent_encoded($match)
12080 {
12081 // As we just have valid percent encoded sequences we can just explode
12082 // and ignore the first member of the returned array (an empty string).
12083 $bytes = explode('%', $match[0]);
12084
12085 // Initialize the new string (this is what will be returned) and that
12086 // there are no bytes remaining in the current sequence (unsurprising
12087 // at the first byte!).
12088 $string = '';
12089 $remaining = 0;
12090
12091 // Loop over each and every byte, and set $value to its value
12092 for ($i = 1, $len = count($bytes); $i < $len; $i++)
12093 {
12094 $value = hexdec($bytes[$i]);
12095
12096 // If we're the first byte of sequence:
12097 if (!$remaining)
12098 {
12099 // Start position
12100 $start = $i;
12101
12102 // By default we are valid
12103 $valid = true;
12104
12105 // One byte sequence:
12106 if ($value <= 0x7F)
12107 {
12108 $character = $value;
12109 $length = 1;
12110 }
12111 // Two byte sequence:
12112 elseif (($value & 0xE0) === 0xC0)
12113 {
12114 $character = ($value & 0x1F) << 6;
12115 $length = 2;
12116 $remaining = 1;
12117 }
12118 // Three byte sequence:
12119 elseif (($value & 0xF0) === 0xE0)
12120 {
12121 $character = ($value & 0x0F) << 12;
12122 $length = 3;
12123 $remaining = 2;
12124 }
12125 // Four byte sequence:
12126 elseif (($value & 0xF8) === 0xF0)
12127 {
12128 $character = ($value & 0x07) << 18;
12129 $length = 4;
12130 $remaining = 3;
12131 }
12132 // Invalid byte:
12133 else
12134 {
12135 $valid = false;
12136 $remaining = 0;
12137 }
12138 }
12139 // Continuation byte:
12140 else
12141 {
12142 // Check that the byte is valid, then add it to the character:
12143 if (($value & 0xC0) === 0x80)
12144 {
12145 $remaining--;
12146 $character |= ($value & 0x3F) << ($remaining * 6);
12147 }
12148 // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence:
12149 else
12150 {
12151 $valid = false;
12152 $remaining = 0;
12153 $i--;
12154 }
12155 }
12156
12157 // If we've reached the end of the current byte sequence, append it to Unicode::$data
12158 if (!$remaining)
12159 {
12160 // Percent encode anything invalid or not in iunreserved
12161 if (
12162 // Invalid sequences
12163 !$valid
12164 // Non-shortest form sequences are invalid
12165 || $length > 1 && $character <= 0x7F
12166 || $length > 2 && $character <= 0x7FF
12167 || $length > 3 && $character <= 0xFFFF
12168 // Outside of range of iunreserved codepoints
12169 || $character < 0x2D
12170 || $character > 0xEFFFD
12171 // Noncharacters
12172 || ($character & 0xFFFE) === 0xFFFE
12173 || $character >= 0xFDD0 && $character <= 0xFDEF
12174 // Everything else not in iunreserved (this is all BMP)
12175 || $character === 0x2F
12176 || $character > 0x39 && $character < 0x41
12177 || $character > 0x5A && $character < 0x61
12178 || $character > 0x7A && $character < 0x7E
12179 || $character > 0x7E && $character < 0xA0
12180 || $character > 0xD7FF && $character < 0xF900
12181 )
12182 {
12183 for ($j = $start; $j <= $i; $j++)
12184 {
12185 $string .= '%' . strtoupper($bytes[$j]);
12186 }
12187 }
12188 else
12189 {
12190 for ($j = $start; $j <= $i; $j++)
12191 {
12192 $string .= chr(hexdec($bytes[$j]));
12193 }
12194 }
12195 }
12196 }
12197
12198 // If we have any bytes left over they are invalid (i.e., we are
12199 // mid-way through a multi-byte sequence)
12200 if ($remaining)
12201 {
12202 for ($j = $start; $j < $len; $j++)
12203 {
12204 $string .= '%' . strtoupper($bytes[$j]);
12205 }
12206 }
12207
12208 return $string;
12209 }
12210
12211 /**
12212 * Check if the object represents a valid IRI
12213 *
12214 * @access public
12215 * @return bool
12216 */
12217 function is_valid()
12218 {
12219 return array_sum($this->valid) === count($this->valid);
12220 }
12221
12222 /**
12223 * Set the scheme. Returns true on success, false on failure (if there are
12224 * any invalid characters).
12225 *
12226 * @access public
12227 * @param string $scheme
12228 * @return bool
12229 */
12230 function set_scheme($scheme)
12231 {
12232 if ($scheme === null || $scheme === '')
12233 {
12234 $this->scheme = null;
12235 }
12236 else
12237 {
12238 $len = strlen($scheme);
12239 switch (true)
12240 {
12241 case $len > 1:
12242 if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
12243 {
12244 $this->scheme = null;
12245 $this->valid[__FUNCTION__] = false;
12246 return false;
12247 }
12248
12249 case $len > 0:
12250 if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
12251 {
12252 $this->scheme = null;
12253 $this->valid[__FUNCTION__] = false;
12254 return false;
12255 }
12256 }
12257 $this->scheme = strtolower($scheme);
12258 }
12259 $this->valid[__FUNCTION__] = true;
12260 return true;
12261 }
12262
12263 /**
12264 * Set the authority. Returns true on success, false on failure (if there are
12265 * any invalid characters).
12266 *
12267 * @access public
12268 * @param string $authority
12269 * @return bool
12270 */
12271 function set_authority($authority)
12272 {
12273 if (($userinfo_end = strrpos($authority, '@')) !== false)
12274 {
12275 $userinfo = substr($authority, 0, $userinfo_end);
12276 $authority = substr($authority, $userinfo_end + 1);
12277 }
12278 else
12279 {
12280 $userinfo = null;
12281 }
12282
12283 if (($port_start = strpos($authority, ':')) !== false)
12284 {
12285 $port = substr($authority, $port_start + 1);
12286 $authority = substr($authority, 0, $port_start);
12287 }
12288 else
12289 {
12290 $port = null;
12291 }
12292
12293 return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
12294 }
12295
12296 /**
12297 * Set the userinfo.
12298 *
12299 * @access public
12300 * @param string $userinfo
12301 * @return bool
12302 */
12303 function set_userinfo($userinfo)
12304 {
12305 if ($userinfo === null || $userinfo === '')
12306 {
12307 $this->userinfo = null;
12308 }
12309 else
12310 {
12311 $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
12312 }
12313 $this->valid[__FUNCTION__] = true;
12314 return true;
12315 }
12316
12317 /**
12318 * Set the host. Returns true on success, false on failure (if there are
12319 * any invalid characters).
12320 *
12321 * @access public
12322 * @param string $host
12323 * @return bool
12324 */
12325 function set_host($host)
12326 {
12327 if ($host === null || $host === '')
12328 {
12329 $this->host = null;
12330 $this->valid[__FUNCTION__] = true;
12331 return true;
12332 }
12333 elseif ($host[0] === '[' && substr($host, -1) === ']')
12334 {
12335 if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
12336 {
12337 $this->host = $host;
12338 $this->valid[__FUNCTION__] = true;
12339 return true;
12340 }
12341 else
12342 {
12343 $this->host = null;
12344 $this->valid[__FUNCTION__] = false;
12345 return false;
12346 }
12347 }
12348 else
12349 {
12350 $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
12351 $this->valid[__FUNCTION__] = true;
12352 return true;
12353 }
12354 }
12355
12356 /**
12357 * Set the port. Returns true on success, false on failure (if there are
12358 * any invalid characters).
12359 *
12360 * @access public
12361 * @param string $port
12362 * @return bool
12363 */
12364 function set_port($port)
12365 {
12366 if ($port === null || $port === '')
12367 {
12368 $this->port = null;
12369 $this->valid[__FUNCTION__] = true;
12370 return true;
12371 }
12372 elseif (strspn($port, '0123456789') === strlen($port))
12373 {
12374 $this->port = (int) $port;
12375 $this->valid[__FUNCTION__] = true;
12376 return true;
12377 }
12378 else
12379 {
12380 $this->port = null;
12381 $this->valid[__FUNCTION__] = false;
12382 return false;
12383 }
12384 }
12385
12386 /**
12387 * Set the path.
12388 *
12389 * @access public
12390 * @param string $path
12391 * @return bool
12392 */
12393 function set_path($path)
12394 {
12395 if ($path === null || $path === '')
12396 {
12397 $this->path = null;
12398 $this->valid[__FUNCTION__] = true;
12399 return true;
12400 }
12401 elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
12402 {
12403 $this->path = null;
12404 $this->valid[__FUNCTION__] = false;
12405 return false;
12406 }
12407 else
12408 {
12409 $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
12410 if ($this->scheme !== null)
12411 {
12412 $this->path = $this->remove_dot_segments($this->path);
12413 }
12414 $this->valid[__FUNCTION__] = true;
12415 return true;
12416 }
12417 }
12418
12419 /**
12420 * Set the query.
12421 *
12422 * @access public
12423 * @param string $query
12424 * @return bool
12425 */
12426 function set_query($query)
12427 {
12428 if ($query === null || $query === '')
12429 {
12430 $this->query = null;
12431 }
12432 else
12433 {
12434 $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?&=');
12435 }
12436 $this->valid[__FUNCTION__] = true;
12437 return true;
12438 }
12439
12440 /**
12441 * Set the fragment.
12442 *
12443 * @access public
12444 * @param string $fragment
12445 * @return bool
12446 */
12447 function set_fragment($fragment)
12448 {
12449 if ($fragment === null || $fragment === '')
12450 {
12451 $this->fragment = null;
12452 }
12453 else
12454 {
12455 $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12456 }
12457 $this->valid[__FUNCTION__] = true;
12458 return true;
12459 }
12460
12461 /**
12462 * Get the complete IRI
12463 *
12464 * @access public
12465 * @return string
12466 */
12467 function get_iri()
12468 {
12469 $iri = '';
12470 if ($this->scheme !== null)
12471 {
12472 $iri .= $this->scheme . ':';
12473 }
12474 if (($authority = $this->get_authority()) !== null)
12475 {
12476 $iri .= '//' . $authority;
12477 }
12478 if ($this->path !== null)
12479 {
12480 $iri .= $this->path;
12481 }
12482 if ($this->query !== null)
12483 {
12484 $iri .= '?' . $this->query;
12485 }
12486 if ($this->fragment !== null)
12487 {
12488 $iri .= '#' . $this->fragment;
12489 }
12490
12491 if ($iri !== '')
12492 {
12493 return $iri;
12494 }
12495 else
12496 {
12497 return null;
12498 }
12499 }
12500
12501 /**
12502 * Get the scheme
12503 *
12504 * @access public
12505 * @return string
12506 */
12507 function get_scheme()
12508 {
12509 return $this->scheme;
12510 }
12511
12512 /**
12513 * Get the complete authority
12514 *
12515 * @access public
12516 * @return string
12517 */
12518 function get_authority()
12519 {
12520 $authority = '';
12521 if ($this->userinfo !== null)
12522 {
12523 $authority .= $this->userinfo . '@';
12524 }
12525 if ($this->host !== null)
12526 {
12527 $authority .= $this->host;
12528 }
12529 if ($this->port !== null)
12530 {
12531 $authority .= ':' . $this->port;
12532 }
12533
12534 if ($authority !== '')
12535 {
12536 return $authority;
12537 }
12538 else
12539 {
12540 return null;
12541 }
12542 }
12543
12544 /**
12545 * Get the user information
12546 *
12547 * @access public
12548 * @return string
12549 */
12550 function get_userinfo()
12551 {
12552 return $this->userinfo;
12553 }
12554
12555 /**
12556 * Get the host
12557 *
12558 * @access public
12559 * @return string
12560 */
12561 function get_host()
12562 {
12563 return $this->host;
12564 }
12565
12566 /**
12567 * Get the port
12568 *
12569 * @access public
12570 * @return string
12571 */
12572 function get_port()
12573 {
12574 return $this->port;
12575 }
12576
12577 /**
12578 * Get the path
12579 *
12580 * @access public
12581 * @return string
12582 */
12583 function get_path()
12584 {
12585 return $this->path;
12586 }
12587
12588 /**
12589 * Get the query
12590 *
12591 * @access public
12592 * @return string
12593 */
12594 function get_query()
12595 {
12596 return $this->query;
12597 }
12598
12599 /**
12600 * Get the fragment
12601 *
12602 * @access public
12603 * @return string
12604 */
12605 function get_fragment()
12606 {
12607 return $this->fragment;
12608 }
12609 }
12610
12611 /**
12612 * Class to validate and to work with IPv6 addresses.
12613 *
12614 * @package SimplePie
12615 * @copyright 2003-2005 The PHP Group
12616 * @license http://www.opensource.org/licenses/bsd-license.php
12617 * @link http://pear.php.net/package/Net_IPv6
12618 * @author Alexander Merz <alexander.merz@web.de>
12619 * @author elfrink at introweb dot nl
12620 * @author Josh Peck <jmp at joshpeck dot org>
12621 * @author Geoffrey Sneddon <geoffers@gmail.com>
12622 */
12623 class SimplePie_Net_IPv6
12624 {
12625 /**
12626 * Removes a possible existing netmask specification of an IP address.
12627 *
12628 * @param string $ip the (compressed) IP as Hex representation
12629 * @return string the IP the without netmask
12630 * @since 1.1.0
12631 * @access public
12632 * @static
12633 */
12634 function removeNetmaskSpec($ip)
12635 {
12636 if (strpos($ip, '/') !== false)
12637 {
12638 list($addr, $nm) = explode('/', $ip);
12639 }
12640 else
12641 {
12642 $addr = $ip;
12643 }
12644 return $addr;
12645 }
12646
12647 /**
12648 * Uncompresses an IPv6 address
12649 *
12650 * RFC 2373 allows you to compress zeros in an address to '::'. This
12651 * function expects an valid IPv6 address and expands the '::' to
12652 * the required zeros.
12653 *
12654 * Example: FF01::101 -> FF01:0:0:0:0:0:0:101
12655 * ::1 -> 0:0:0:0:0:0:0:1
12656 *
12657 * @access public
12658 * @static
12659 * @param string $ip a valid IPv6-address (hex format)
12660 * @return string the uncompressed IPv6-address (hex format)
12661 */
12662 function Uncompress($ip)
12663 {
12664 $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
12665 $c1 = -1;
12666 $c2 = -1;
12667 if (strpos($ip, '::') !== false)
12668 {
12669 list($ip1, $ip2) = explode('::', $ip);
12670 if ($ip1 === '')
12671 {
12672 $c1 = -1;
12673 }
12674 else
12675 {
12676 $pos = 0;
12677 if (($pos = substr_count($ip1, ':')) > 0)
12678 {
12679 $c1 = $pos;
12680 }
12681 else
12682 {
12683 $c1 = 0;
12684 }
12685 }
12686 if ($ip2 === '')
12687 {
12688 $c2 = -1;
12689 }
12690 else
12691 {
12692 $pos = 0;
12693 if (($pos = substr_count($ip2, ':')) > 0)
12694 {
12695 $c2 = $pos;
12696 }
12697 else
12698 {
12699 $c2 = 0;
12700 }
12701 }
12702 if (strstr($ip2, '.'))
12703 {
12704 $c2++;
12705 }
12706 // ::
12707 if ($c1 === -1 && $c2 === -1)
12708 {
12709 $uip = '0:0:0:0:0:0:0:0';
12710 }
12711 // ::xxx
12712 else if ($c1 === -1)
12713 {
12714 $fill = str_repeat('0:', 7 - $c2);
12715 $uip = str_replace('::', $fill, $uip);
12716 }
12717 // xxx::
12718 else if ($c2 === -1)
12719 {
12720 $fill = str_repeat(':0', 7 - $c1);
12721 $uip = str_replace('::', $fill, $uip);
12722 }
12723 // xxx::xxx
12724 else
12725 {
12726 $fill = str_repeat(':0:', 6 - $c2 - $c1);
12727 $uip = str_replace('::', $fill, $uip);
12728 $uip = str_replace('::', ':', $uip);
12729 }
12730 }
12731 return $uip;
12732 }
12733
12734 /**
12735 * Splits an IPv6 address into the IPv6 and a possible IPv4 part
12736 *
12737 * RFC 2373 allows you to note the last two parts of an IPv6 address as
12738 * an IPv4 compatible address
12739 *
12740 * Example: 0:0:0:0:0:0:13.1.68.3
12741 * 0:0:0:0:0:FFFF:129.144.52.38
12742 *
12743 * @access public
12744 * @static
12745 * @param string $ip a valid IPv6-address (hex format)
12746 * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
12747 */
12748 function SplitV64($ip)
12749 {
12750 $ip = SimplePie_Net_IPv6::Uncompress($ip);
12751 if (strstr($ip, '.'))
12752 {
12753 $pos = strrpos($ip, ':');
12754 $ip[$pos] = '_';
12755 $ipPart = explode('_', $ip);
12756 return $ipPart;
12757 }
12758 else
12759 {
12760 return array($ip, '');
12761 }
12762 }
12763
12764 /**
12765 * Checks an IPv6 address
12766 *
12767 * Checks if the given IP is IPv6-compatible
12768 *
12769 * @access public
12770 * @static
12771 * @param string $ip a valid IPv6-address
12772 * @return bool true if $ip is an IPv6 address
12773 */
12774 function checkIPv6($ip)
12775 {
12776 $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
12777 $count = 0;
12778 if (!empty($ipPart[0]))
12779 {
12780 $ipv6 = explode(':', $ipPart[0]);
12781 for ($i = 0; $i < count($ipv6); $i++)
12782 {
12783 $dec = hexdec($ipv6[$i]);
12784 $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
12785 if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
12786 {
12787 $count++;
12788 }
12789 }
12790 if ($count === 8)
12791 {
12792 return true;
12793 }
12794 elseif ($count === 6 && !empty($ipPart[1]))
12795 {
12796 $ipv4 = explode('.', $ipPart[1]);
12797 $count = 0;
12798 foreach ($ipv4 as $ipv4_part)
12799 {
12800 if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
12801 {
12802 $count++;
12803 }
12804 }
12805 if ($count === 4)
12806 {
12807 return true;
12808 }
12809 }
12810 else
12811 {
12812 return false;
12813 }
12814
12815 }
12816 else
12817 {
12818 return false;
12819 }
12820 }
12821 }
12822
12823 /**
12824 * Date Parser
12825 *
12826 * @package SimplePie
12827 */
12828 class SimplePie_Parse_Date
12829 {
12830 /**
12831 * Input data
12832 *
12833 * @access protected
12834 * @var string
12835 */
12836 var $date;
12837
12838 /**
12839 * List of days, calendar day name => ordinal day number in the week
12840 *
12841 * @access protected
12842 * @var array
12843 */
12844 var $day = array(
12845 // English
12846 'mon' => 1,
12847 'monday' => 1,
12848 'tue' => 2,
12849 'tuesday' => 2,
12850 'wed' => 3,
12851 'wednesday' => 3,
12852 'thu' => 4,
12853 'thursday' => 4,
12854 'fri' => 5,
12855 'friday' => 5,
12856 'sat' => 6,
12857 'saturday' => 6,
12858 'sun' => 7,
12859 'sunday' => 7,
12860 // Dutch
12861 'maandag' => 1,
12862 'dinsdag' => 2,
12863 'woensdag' => 3,
12864 'donderdag' => 4,
12865 'vrijdag' => 5,
12866 'zaterdag' => 6,
12867 'zondag' => 7,
12868 // French
12869 'lundi' => 1,
12870 'mardi' => 2,
12871 'mercredi' => 3,
12872 'jeudi' => 4,
12873 'vendredi' => 5,
12874 'samedi' => 6,
12875 'dimanche' => 7,
12876 // German
12877 'montag' => 1,
12878 'dienstag' => 2,
12879 'mittwoch' => 3,
12880 'donnerstag' => 4,
12881 'freitag' => 5,
12882 'samstag' => 6,
12883 'sonnabend' => 6,
12884 'sonntag' => 7,
12885 // Italian
12886 'lunedì' => 1,
12887 'martedì' => 2,
12888 'mercoledì' => 3,
12889 'giovedì' => 4,
12890 'venerdì' => 5,
12891 'sabato' => 6,
12892 'domenica' => 7,
12893 // Spanish
12894 'lunes' => 1,
12895 'martes' => 2,
12896 'miércoles' => 3,
12897 'jueves' => 4,
12898 'viernes' => 5,
12899 'sábado' => 6,
12900 'domingo' => 7,
12901 // Finnish
12902 'maanantai' => 1,
12903 'tiistai' => 2,
12904 'keskiviikko' => 3,
12905 'torstai' => 4,
12906 'perjantai' => 5,
12907 'lauantai' => 6,
12908 'sunnuntai' => 7,
12909 // Hungarian
12910 'hétfő' => 1,
12911 'kedd' => 2,
12912 'szerda' => 3,
12913 'csütörtok' => 4,
12914 'péntek' => 5,
12915 'szombat' => 6,
12916 'vasárnap' => 7,
12917 // Greek
12918 'Δευ' => 1,
12919 'Τρι' => 2,
12920 'Τετ' => 3,
12921 'Πεμ' => 4,
12922 'Παρ' => 5,
12923 'Σαβ' => 6,
12924 'Κυρ' => 7,
12925 );
12926
12927 /**
12928 * List of months, calendar month name => calendar month number
12929 *
12930 * @access protected
12931 * @var array
12932 */
12933 var $month = array(
12934 // English
12935 'jan' => 1,
12936 'january' => 1,
12937 'feb' => 2,
12938 'february' => 2,
12939 'mar' => 3,
12940 'march' => 3,
12941 'apr' => 4,
12942 'april' => 4,
12943 'may' => 5,
12944 // No long form of May
12945 'jun' => 6,
12946 'june' => 6,
12947 'jul' => 7,
12948 'july' => 7,
12949 'aug' => 8,
12950 'august' => 8,
12951 'sep' => 9,
12952 'september' => 8,
12953 'oct' => 10,
12954 'october' => 10,
12955 'nov' => 11,
12956 'november' => 11,
12957 'dec' => 12,
12958 'december' => 12,
12959 // Dutch
12960 'januari' => 1,
12961 'februari' => 2,
12962 'maart' => 3,
12963 'april' => 4,
12964 'mei' => 5,
12965 'juni' => 6,
12966 'juli' => 7,
12967 'augustus' => 8,
12968 'september' => 9,
12969 'oktober' => 10,
12970 'november' => 11,
12971 'december' => 12,
12972 // French
12973 'janvier' => 1,
12974 'février' => 2,
12975 'mars' => 3,
12976 'avril' => 4,
12977 'mai' => 5,
12978 'juin' => 6,
12979 'juillet' => 7,
12980 'août' => 8,
12981 'septembre' => 9,
12982 'octobre' => 10,
12983 'novembre' => 11,
12984 'décembre' => 12,
12985 // German
12986 'januar' => 1,
12987 'februar' => 2,
12988 'märz' => 3,
12989 'april' => 4,
12990 'mai' => 5,
12991 'juni' => 6,
12992 'juli' => 7,
12993 'august' => 8,
12994 'september' => 9,
12995 'oktober' => 10,
12996 'november' => 11,
12997 'dezember' => 12,
12998 // Italian
12999 'gennaio' => 1,
13000 'febbraio' => 2,
13001 'marzo' => 3,
13002 'aprile' => 4,
13003 'maggio' => 5,
13004 'giugno' => 6,
13005 'luglio' => 7,
13006 'agosto' => 8,
13007 'settembre' => 9,
13008 'ottobre' => 10,
13009 'novembre' => 11,
13010 'dicembre' => 12,
13011 // Spanish
13012 'enero' => 1,
13013 'febrero' => 2,
13014 'marzo' => 3,
13015 'abril' => 4,
13016 'mayo' => 5,
13017 'junio' => 6,
13018 'julio' => 7,
13019 'agosto' => 8,
13020 'septiembre' => 9,
13021 'setiembre' => 9,
13022 'octubre' => 10,
13023 'noviembre' => 11,
13024 'diciembre' => 12,
13025 // Finnish
13026 'tammikuu' => 1,
13027 'helmikuu' => 2,
13028 'maaliskuu' => 3,
13029 'huhtikuu' => 4,
13030 'toukokuu' => 5,
13031 'kesäkuu' => 6,
13032 'heinäkuu' => 7,
13033 'elokuu' => 8,
13034 'suuskuu' => 9,
13035 'lokakuu' => 10,
13036 'marras' => 11,
13037 'joulukuu' => 12,
13038 // Hungarian
13039 'január' => 1,
13040 'február' => 2,
13041 'március' => 3,
13042 'április' => 4,
13043 'május' => 5,
13044 'június' => 6,
13045 'július' => 7,
13046 'augusztus' => 8,
13047 'szeptember' => 9,
13048 'október' => 10,
13049 'november' => 11,
13050 'december' => 12,
13051 // Greek
13052 'Ιαν' => 1,
13053 'Φεβ' => 2,
13054 'Μάώ' => 3,
13055 'Μαώ' => 3,
13056 'Απρ' => 4,
13057 'Μάι' => 5,
13058 'Μαϊ' => 5,
13059 'Μαι' => 5,
13060 'Ιούν' => 6,
13061 'Ιον' => 6,
13062 'Ιούλ' => 7,
13063 'Ιολ' => 7,
13064 'Αύγ' => 8,
13065 'Αυγ' => 8,
13066 'Σεπ' => 9,
13067 'Οκτ' => 10,
13068 'Νοέ' => 11,
13069 'Δεκ' => 12,
13070 );
13071
13072 /**
13073 * List of timezones, abbreviation => offset from UTC
13074 *
13075 * @access protected
13076 * @var array
13077 */
13078 var $timezone = array(
13079 'ACDT' => 37800,
13080 'ACIT' => 28800,
13081 'ACST' => 34200,
13082 'ACT' => -18000,
13083 'ACWDT' => 35100,
13084 'ACWST' => 31500,
13085 'AEDT' => 39600,
13086 'AEST' => 36000,
13087 'AFT' => 16200,
13088 'AKDT' => -28800,
13089 'AKST' => -32400,
13090 'AMDT' => 18000,
13091 'AMT' => -14400,
13092 'ANAST' => 46800,
13093 'ANAT' => 43200,
13094 'ART' => -10800,
13095 'AZOST' => -3600,
13096 'AZST' => 18000,
13097 'AZT' => 14400,
13098 'BIOT' => 21600,
13099 'BIT' => -43200,
13100 'BOT' => -14400,
13101 'BRST' => -7200,
13102 'BRT' => -10800,
13103 'BST' => 3600,
13104 'BTT' => 21600,
13105 'CAST' => 18000,
13106 'CAT' => 7200,
13107 'CCT' => 23400,
13108 'CDT' => -18000,
13109 'CEDT' => 7200,
13110 'CET' => 3600,
13111 'CGST' => -7200,
13112 'CGT' => -10800,
13113 'CHADT' => 49500,
13114 'CHAST' => 45900,
13115 'CIST' => -28800,
13116 'CKT' => -36000,
13117 'CLDT' => -10800,
13118 'CLST' => -14400,
13119 'COT' => -18000,
13120 'CST' => -21600,
13121 'CVT' => -3600,
13122 'CXT' => 25200,
13123 'DAVT' => 25200,
13124 'DTAT' => 36000,
13125 'EADT' => -18000,
13126 'EAST' => -21600,
13127 'EAT' => 10800,
13128 'ECT' => -18000,
13129 'EDT' => -14400,
13130 'EEST' => 10800,
13131 'EET' => 7200,
13132 'EGT' => -3600,
13133 'EKST' => 21600,
13134 'EST' => -18000,
13135 'FJT' => 43200,
13136 'FKDT' => -10800,
13137 'FKST' => -14400,
13138 'FNT' => -7200,
13139 'GALT' => -21600,
13140 'GEDT' => 14400,
13141 'GEST' => 10800,
13142 'GFT' => -10800,
13143 'GILT' => 43200,
13144 'GIT' => -32400,
13145 'GST' => 14400,
13146 'GST' => -7200,
13147 'GYT' => -14400,
13148 'HAA' => -10800,
13149 'HAC' => -18000,
13150 'HADT' => -32400,
13151 'HAE' => -14400,
13152 'HAP' => -25200,
13153 'HAR' => -21600,
13154 'HAST' => -36000,
13155 'HAT' => -9000,
13156 'HAY' => -28800,
13157 'HKST' => 28800,
13158 'HMT' => 18000,
13159 'HNA' => -14400,
13160 'HNC' => -21600,
13161 'HNE' => -18000,
13162 'HNP' => -28800,
13163 'HNR' => -25200,
13164 'HNT' => -12600,
13165 'HNY' => -32400,
13166 'IRDT' => 16200,
13167 'IRKST' => 32400,
13168 'IRKT' => 28800,
13169 'IRST' => 12600,
13170 'JFDT' => -10800,
13171 'JFST' => -14400,
13172 'JST' => 32400,
13173 'KGST' => 21600,
13174 'KGT' => 18000,
13175 'KOST' => 39600,
13176 'KOVST' => 28800,
13177 'KOVT' => 25200,
13178 'KRAST' => 28800,
13179 'KRAT' => 25200,
13180 'KST' => 32400,
13181 'LHDT' => 39600,
13182 'LHST' => 37800,
13183 'LINT' => 50400,
13184 'LKT' => 21600,
13185 'MAGST' => 43200,
13186 'MAGT' => 39600,
13187 'MAWT' => 21600,
13188 'MDT' => -21600,
13189 'MESZ' => 7200,
13190 'MEZ' => 3600,
13191 'MHT' => 43200,
13192 'MIT' => -34200,
13193 'MNST' => 32400,
13194 'MSDT' => 14400,
13195 'MSST' => 10800,
13196 'MST' => -25200,
13197 'MUT' => 14400,
13198 'MVT' => 18000,
13199 'MYT' => 28800,
13200 'NCT' => 39600,
13201 'NDT' => -9000,
13202 'NFT' => 41400,
13203 'NMIT' => 36000,
13204 'NOVST' => 25200,
13205 'NOVT' => 21600,
13206 'NPT' => 20700,
13207 'NRT' => 43200,
13208 'NST' => -12600,
13209 'NUT' => -39600,
13210 'NZDT' => 46800,
13211 'NZST' => 43200,
13212 'OMSST' => 25200,
13213 'OMST' => 21600,
13214 'PDT' => -25200,
13215 'PET' => -18000,
13216 'PETST' => 46800,
13217 'PETT' => 43200,
13218 'PGT' => 36000,
13219 'PHOT' => 46800,
13220 'PHT' => 28800,
13221 'PKT' => 18000,
13222 'PMDT' => -7200,
13223 'PMST' => -10800,
13224 'PONT' => 39600,
13225 'PST' => -28800,
13226 'PWT' => 32400,
13227 'PYST' => -10800,
13228 'PYT' => -14400,
13229 'RET' => 14400,
13230 'ROTT' => -10800,
13231 'SAMST' => 18000,
13232 'SAMT' => 14400,
13233 'SAST' => 7200,
13234 'SBT' => 39600,
13235 'SCDT' => 46800,
13236 'SCST' => 43200,
13237 'SCT' => 14400,
13238 'SEST' => 3600,
13239 'SGT' => 28800,
13240 'SIT' => 28800,
13241 'SRT' => -10800,
13242 'SST' => -39600,
13243 'SYST' => 10800,
13244 'SYT' => 7200,
13245 'TFT' => 18000,
13246 'THAT' => -36000,
13247 'TJT' => 18000,
13248 'TKT' => -36000,
13249 'TMT' => 18000,
13250 'TOT' => 46800,
13251 'TPT' => 32400,
13252 'TRUT' => 36000,
13253 'TVT' => 43200,
13254 'TWT' => 28800,
13255 'UYST' => -7200,
13256 'UYT' => -10800,
13257 'UZT' => 18000,
13258 'VET' => -14400,
13259 'VLAST' => 39600,
13260 'VLAT' => 36000,
13261 'VOST' => 21600,
13262 'VUT' => 39600,
13263 'WAST' => 7200,
13264 'WAT' => 3600,
13265 'WDT' => 32400,
13266 'WEST' => 3600,
13267 'WFT' => 43200,
13268 'WIB' => 25200,
13269 'WIT' => 32400,
13270 'WITA' => 28800,
13271 'WKST' => 18000,
13272 'WST' => 28800,
13273 'YAKST' => 36000,
13274 'YAKT' => 32400,
13275 'YAPT' => 36000,
13276 'YEKST' => 21600,
13277 'YEKT' => 18000,
13278 );
13279
13280 /**
13281 * Cached PCRE for SimplePie_Parse_Date::$day
13282 *
13283 * @access protected
13284 * @var string
13285 */
13286 var $day_pcre;
13287
13288 /**
13289 * Cached PCRE for SimplePie_Parse_Date::$month
13290 *
13291 * @access protected
13292 * @var string
13293 */
13294 var $month_pcre;
13295
13296 /**
13297 * Array of user-added callback methods
13298 *
13299 * @access private
13300 * @var array
13301 */
13302 var $built_in = array();
13303
13304 /**
13305 * Array of user-added callback methods
13306 *
13307 * @access private
13308 * @var array
13309 */
13310 var $user = array();
13311
13312 /**
13313 * Create new SimplePie_Parse_Date object, and set self::day_pcre,
13314 * self::month_pcre, and self::built_in
13315 *
13316 * @access private
13317 */
13318 function SimplePie_Parse_Date()
13319 {
13320 $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
13321 $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
13322
13323 static $cache;
13324 if (!isset($cache[get_class($this)]))
13325 {
13326 $all_methods = get_class_methods($this);
13327
13328 foreach ($all_methods as $method)
13329 {
13330 if (strtolower(substr($method, 0, 5)) === 'date_')
13331 {
13332 $cache[get_class($this)][] = $method;
13333 }
13334 }
13335 }
13336
13337 foreach ($cache[get_class($this)] as $method)
13338 {
13339 $this->built_in[] = $method;
13340 }
13341 }
13342
13343 /**
13344 * Get the object
13345 *
13346 * @access public
13347 */
13348 function get()
13349 {
13350 static $object;
13351 if (!$object)
13352 {
13353 $object =& new SimplePie_Parse_Date;
13354 }
13355 return $object;
13356 }
13357
13358 /**
13359 * Parse a date
13360 *
13361 * @final
13362 * @access public
13363 * @param string $date Date to parse
13364 * @return int Timestamp corresponding to date string, or false on failure
13365 */
13366 function parse($date)
13367 {
13368 foreach ($this->user as $method)
13369 {
13370 if (($returned = call_user_func($method, $date)) !== false)
13371 {
13372 return $returned;
13373 }
13374 }
13375
13376 foreach ($this->built_in as $method)
13377 {
13378 if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
13379 {
13380 return $returned;
13381 }
13382 }
13383
13384 return false;
13385 }
13386
13387 /**
13388 * Add a callback method to parse a date
13389 *
13390 * @final
13391 * @access public
13392 * @param callback $callback
13393 */
13394 function add_callback($callback)
13395 {
13396 if (is_callable($callback))
13397 {
13398 $this->user[] = $callback;
13399 }
13400 else
13401 {
13402 trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
13403 }
13404 }
13405
13406 /**
13407 * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
13408 * well as allowing any of upper or lower case "T", horizontal tabs, or
13409 * spaces to be used as the time seperator (including more than one))
13410 *
13411 * @access protected
13412 * @return int Timestamp
13413 */
13414 function date_w3cdtf($date)
13415 {
13416 static $pcre;
13417 if (!$pcre)
13418 {
13419 $year = '([0-9]{4})';
13420 $month = $day = $hour = $minute = $second = '([0-9]{2})';
13421 $decimal = '([0-9]*)';
13422 $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
13423 $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
13424 }
13425 if (preg_match($pcre, $date, $match))
13426 {
13427 /*
13428 Capturing subpatterns:
13429 1: Year
13430 2: Month
13431 3: Day
13432 4: Hour
13433 5: Minute
13434 6: Second
13435 7: Decimal fraction of a second
13436 8: Zulu
13437 9: Timezone ±
13438 10: Timezone hours
13439 11: Timezone minutes
13440 */
13441
13442 // Fill in empty matches
13443 for ($i = count($match); $i <= 3; $i++)
13444 {
13445 $match[$i] = '1';
13446 }
13447
13448 for ($i = count($match); $i <= 7; $i++)
13449 {
13450 $match[$i] = '0';
13451 }
13452
13453 // Numeric timezone
13454 if (isset($match[9]) && $match[9] !== '')
13455 {
13456 $timezone = $match[10] * 3600;
13457 $timezone += $match[11] * 60;
13458 if ($match[9] === '-')
13459 {
13460 $timezone = 0 - $timezone;
13461 }
13462 }
13463 else
13464 {
13465 $timezone = 0;
13466 }
13467
13468 // Convert the number of seconds to an integer, taking decimals into account
13469 $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
13470
13471 return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
13472 }
13473 else
13474 {
13475 return false;
13476 }
13477 }
13478
13479 /**
13480 * Remove RFC822 comments
13481 *
13482 * @access protected
13483 * @param string $data Data to strip comments from
13484 * @return string Comment stripped string
13485 */
13486 function remove_rfc2822_comments($string)
13487 {
13488 $string = (string) $string;
13489 $position = 0;
13490 $length = strlen($string);
13491 $depth = 0;
13492
13493 $output = '';
13494
13495 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
13496 {
13497 $output .= substr($string, $position, $pos - $position);
13498 $position = $pos + 1;
13499 if ($string[$pos - 1] !== '\\')
13500 {
13501 $depth++;
13502 while ($depth && $position < $length)
13503 {
13504 $position += strcspn($string, '()', $position);
13505 if ($string[$position - 1] === '\\')
13506 {
13507 $position++;
13508 continue;
13509 }
13510 elseif (isset($string[$position]))
13511 {
13512 switch ($string[$position])
13513 {
13514 case '(':
13515 $depth++;
13516 break;
13517
13518 case ')':
13519 $depth--;
13520 break;
13521 }
13522 $position++;
13523 }
13524 else
13525 {
13526 break;
13527 }
13528 }
13529 }
13530 else
13531 {
13532 $output .= '(';
13533 }
13534 }
13535 $output .= substr($string, $position);
13536
13537 return $output;
13538 }
13539
13540 /**
13541 * Parse RFC2822's date format
13542 *
13543 * @access protected
13544 * @return int Timestamp
13545 */
13546 function date_rfc2822($date)
13547 {
13548 static $pcre;
13549 if (!$pcre)
13550 {
13551 $wsp = '[\x09\x20]';
13552 $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
13553 $optional_fws = $fws . '?';
13554 $day_name = $this->day_pcre;
13555 $month = $this->month_pcre;
13556 $day = '([0-9]{1,2})';
13557 $hour = $minute = $second = '([0-9]{2})';
13558 $year = '([0-9]{2,4})';
13559 $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
13560 $character_zone = '([A-Z]{1,5})';
13561 $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
13562 $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';
13563 }
13564 if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
13565 {
13566 /*
13567 Capturing subpatterns:
13568 1: Day name
13569 2: Day
13570 3: Month
13571 4: Year
13572 5: Hour
13573 6: Minute
13574 7: Second
13575 8: Timezone ±
13576 9: Timezone hours
13577 10: Timezone minutes
13578 11: Alphabetic timezone
13579 */
13580
13581 // Find the month number
13582 $month = $this->month[strtolower($match[3])];
13583
13584 // Numeric timezone
13585 if ($match[8] !== '')
13586 {
13587 $timezone = $match[9] * 3600;
13588 $timezone += $match[10] * 60;
13589 if ($match[8] === '-')
13590 {
13591 $timezone = 0 - $timezone;
13592 }
13593 }
13594 // Character timezone
13595 elseif (isset($this->timezone[strtoupper($match[11])]))
13596 {
13597 $timezone = $this->timezone[strtoupper($match[11])];
13598 }
13599 // Assume everything else to be -0000
13600 else
13601 {
13602 $timezone = 0;
13603 }
13604
13605 // Deal with 2/3 digit years
13606 if ($match[4] < 50)
13607 {
13608 $match[4] += 2000;
13609 }
13610 elseif ($match[4] < 1000)
13611 {
13612 $match[4] += 1900;
13613 }
13614
13615 // Second is optional, if it is empty set it to zero
13616 if ($match[7] !== '')
13617 {
13618 $second = $match[7];
13619 }
13620 else
13621 {
13622 $second = 0;
13623 }
13624
13625 return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
13626 }
13627 else
13628 {
13629 return false;
13630 }
13631 }
13632
13633 /**
13634 * Parse RFC850's date format
13635 *
13636 * @access protected
13637 * @return int Timestamp
13638 */
13639 function date_rfc850($date)
13640 {
13641 static $pcre;
13642 if (!$pcre)
13643 {
13644 $space = '[\x09\x20]+';
13645 $day_name = $this->day_pcre;
13646 $month = $this->month_pcre;
13647 $day = '([0-9]{1,2})';
13648 $year = $hour = $minute = $second = '([0-9]{2})';
13649 $zone = '([A-Z]{1,5})';
13650 $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
13651 }
13652 if (preg_match($pcre, $date, $match))
13653 {
13654 /*
13655 Capturing subpatterns:
13656 1: Day name
13657 2: Day
13658 3: Month
13659 4: Year
13660 5: Hour
13661 6: Minute
13662 7: Second
13663 8: Timezone
13664 */
13665
13666 // Month
13667 $month = $this->month[strtolower($match[3])];
13668
13669 // Character timezone
13670 if (isset($this->timezone[strtoupper($match[8])]))
13671 {
13672 $timezone = $this->timezone[strtoupper($match[8])];
13673 }
13674 // Assume everything else to be -0000
13675 else
13676 {
13677 $timezone = 0;
13678 }
13679
13680 // Deal with 2 digit year
13681 if ($match[4] < 50)
13682 {
13683 $match[4] += 2000;
13684 }
13685 else
13686 {
13687 $match[4] += 1900;
13688 }
13689
13690 return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
13691 }
13692 else
13693 {
13694 return false;
13695 }
13696 }
13697
13698 /**
13699 * Parse C99's asctime()'s date format
13700 *
13701 * @access protected
13702 * @return int Timestamp
13703 */
13704 function date_asctime($date)
13705 {
13706 static $pcre;
13707 if (!$pcre)
13708 {
13709 $space = '[\x09\x20]+';
13710 $wday_name = $this->day_pcre;
13711 $mon_name = $this->month_pcre;
13712 $day = '([0-9]{1,2})';
13713 $hour = $sec = $min = '([0-9]{2})';
13714 $year = '([0-9]{4})';
13715 $terminator = '\x0A?\x00?';
13716 $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
13717 }
13718 if (preg_match($pcre, $date, $match))
13719 {
13720 /*
13721 Capturing subpatterns:
13722 1: Day name
13723 2: Month
13724 3: Day
13725 4: Hour
13726 5: Minute
13727 6: Second
13728 7: Year
13729 */
13730
13731 $month = $this->month[strtolower($match[2])];
13732 return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
13733 }
13734 else
13735 {
13736 return false;
13737 }
13738 }
13739
13740 /**
13741 * Parse dates using strtotime()
13742 *
13743 * @access protected
13744 * @return int Timestamp
13745 */
13746 function date_strtotime($date)
13747 {
13748 $strtotime = strtotime($date);
13749 if ($strtotime === -1 || $strtotime === false)
13750 {
13751 return false;
13752 }
13753 else
13754 {
13755 return $strtotime;
13756 }
13757 }
13758 }
13759
13760 /**
13761 * Content-type sniffing
13762 *
13763 * @package SimplePie
13764 */
13765 class SimplePie_Content_Type_Sniffer
13766 {
13767 /**
13768 * File object
13769 *
13770 * @var SimplePie_File
13771 * @access private
13772 */
13773 var $file;
13774
13775 /**
13776 * Create an instance of the class with the input file
13777 *
13778 * @access public
13779 * @param SimplePie_Content_Type_Sniffer $file Input file
13780 */
13781 function SimplePie_Content_Type_Sniffer($file)
13782 {
13783 $this->file = $file;
13784 }
13785
13786 /**
13787 * Get the Content-Type of the specified file
13788 *
13789 * @access public
13790 * @return string Actual Content-Type
13791 */
13792 function get_type()
13793 {
13794 if (isset($this->file->headers['content-type']))
13795 {
13796 if (!isset($this->file->headers['content-encoding'])
13797 && ($this->file->headers['content-type'] === 'text/plain'
13798 || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
13799 || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
13800 {
13801 return $this->text_or_binary();
13802 }
13803
13804 if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
13805 {
13806 $official = substr($this->file->headers['content-type'], 0, $pos);
13807 }
13808 else
13809 {
13810 $official = $this->file->headers['content-type'];
13811 }
13812 $official = strtolower($official);
13813
13814 if ($official === 'unknown/unknown'
13815 || $official === 'application/unknown')
13816 {
13817 return $this->unknown();
13818 }
13819 elseif (substr($official, -4) === '+xml'
13820 || $official === 'text/xml'
13821 || $official === 'application/xml')
13822 {
13823 return $official;
13824 }
13825 elseif (substr($official, 0, 6) === 'image/')
13826 {
13827 if ($return = $this->image())
13828 {
13829 return $return;
13830 }
13831 else
13832 {
13833 return $official;
13834 }
13835 }
13836 elseif ($official === 'text/html')
13837 {
13838 return $this->feed_or_html();
13839 }
13840 else
13841 {
13842 return $official;
13843 }
13844 }
13845 else
13846 {
13847 return $this->unknown();
13848 }
13849 }
13850
13851 /**
13852 * Sniff text or binary
13853 *
13854 * @access private
13855 * @return string Actual Content-Type
13856 */
13857 function text_or_binary()
13858 {
13859 if (substr($this->file->body, 0, 2) === "\xFE\xFF"
13860 || substr($this->file->body, 0, 2) === "\xFF\xFE"
13861 || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
13862 || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
13863 {
13864 return 'text/plain';
13865 }
13866 elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
13867 {
13868 return 'application/octect-stream';
13869 }
13870 else
13871 {
13872 return 'text/plain';
13873 }
13874 }
13875
13876 /**
13877 * Sniff unknown
13878 *
13879 * @access private
13880 * @return string Actual Content-Type
13881 */
13882 function unknown()
13883 {
13884 $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
13885 if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
13886 || strtolower(substr($this->file->body, $ws, 5)) === '<html'
13887 || strtolower(substr($this->file->body, $ws, 7)) === '<script')
13888 {
13889 return 'text/html';
13890 }
13891 elseif (substr($this->file->body, 0, 5) === '%PDF-')
13892 {
13893 return 'application/pdf';
13894 }
13895 elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
13896 {
13897 return 'application/postscript';
13898 }
13899 elseif (substr($this->file->body, 0, 6) === 'GIF87a'
13900 || substr($this->file->body, 0, 6) === 'GIF89a')
13901 {
13902 return 'image/gif';
13903 }
13904 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13905 {
13906 return 'image/png';
13907 }
13908 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13909 {
13910 return 'image/jpeg';
13911 }
13912 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13913 {
13914 return 'image/bmp';
13915 }
13916 else
13917 {
13918 return $this->text_or_binary();
13919 }
13920 }
13921
13922 /**
13923 * Sniff images
13924 *
13925 * @access private
13926 * @return string Actual Content-Type
13927 */
13928 function image()
13929 {
13930 if (substr($this->file->body, 0, 6) === 'GIF87a'
13931 || substr($this->file->body, 0, 6) === 'GIF89a')
13932 {
13933 return 'image/gif';
13934 }
13935 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13936 {
13937 return 'image/png';
13938 }
13939 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13940 {
13941 return 'image/jpeg';
13942 }
13943 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13944 {
13945 return 'image/bmp';
13946 }
13947 else
13948 {
13949 return false;
13950 }
13951 }
13952
13953 /**
13954 * Sniff HTML
13955 *
13956 * @access private
13957 * @return string Actual Content-Type
13958 */
13959 function feed_or_html()
13960 {
13961 $len = strlen($this->file->body);
13962 $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
13963
13964 while ($pos < $len)
13965 {
13966 switch ($this->file->body[$pos])
13967 {
13968 case "\x09":
13969 case "\x0A":
13970 case "\x0D":
13971 case "\x20":
13972 $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
13973 continue 2;
13974
13975 case '<':
13976 $pos++;
13977 break;
13978
13979 default:
13980 return 'text/html';
13981 }
13982
13983 if (substr($this->file->body, $pos, 3) === '!--')
13984 {
13985 $pos += 3;
13986 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
13987 {
13988 $pos += 3;
13989 }
13990 else
13991 {
13992 return 'text/html';
13993 }
13994 }
13995 elseif (substr($this->file->body, $pos, 1) === '!')
13996 {
13997 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
13998 {
13999 $pos++;
14000 }
14001 else
14002 {
14003 return 'text/html';
14004 }
14005 }
14006 elseif (substr($this->file->body, $pos, 1) === '?')
14007 {
14008 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
14009 {
14010 $pos += 2;
14011 }
14012 else
14013 {
14014 return 'text/html';
14015 }
14016 }
14017 elseif (substr($this->file->body, $pos, 3) === 'rss'
14018 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
14019 {
14020 return 'application/rss+xml';
14021 }
14022 elseif (substr($this->file->body, $pos, 4) === 'feed')
14023 {
14024 return 'application/atom+xml';
14025 }
14026 else
14027 {
14028 return 'text/html';
14029 }
14030 }
14031
14032 return 'text/html';
14033 }
14034 }
14035
14036 /**
14037 * Parses the XML Declaration
14038 *
14039 * @package SimplePie
14040 */
14041 class SimplePie_XML_Declaration_Parser
14042 {
14043 /**
14044 * XML Version
14045 *
14046 * @access public
14047 * @var string
14048 */
14049 var $version = '1.0';
14050
14051 /**
14052 * Encoding
14053 *
14054 * @access public
14055 * @var string
14056 */
14057 var $encoding = 'UTF-8';
14058
14059 /**
14060 * Standalone
14061 *
14062 * @access public
14063 * @var bool
14064 */
14065 var $standalone = false;
14066
14067 /**
14068 * Current state of the state machine
14069 *
14070 * @access private
14071 * @var string
14072 */
14073 var $state = 'before_version_name';
14074
14075 /**
14076 * Input data
14077 *
14078 * @access private
14079 * @var string
14080 */
14081 var $data = '';
14082
14083 /**
14084 * Input data length (to avoid calling strlen() everytime this is needed)
14085 *
14086 * @access private
14087 * @var int
14088 */
14089 var $data_length = 0;
14090
14091 /**
14092 * Current position of the pointer
14093 *
14094 * @var int
14095 * @access private
14096 */
14097 var $position = 0;
14098
14099 /**
14100 * Create an instance of the class with the input data
14101 *
14102 * @access public
14103 * @param string $data Input data
14104 */
14105 function SimplePie_XML_Declaration_Parser($data)
14106 {
14107 $this->data = $data;
14108 $this->data_length = strlen($this->data);
14109 }
14110
14111 /**
14112 * Parse the input data
14113 *
14114 * @access public
14115 * @return bool true on success, false on failure
14116 */
14117 function parse()
14118 {
14119 while ($this->state && $this->state !== 'emit' && $this->has_data())
14120 {
14121 $state = $this->state;
14122 $this->$state();
14123 }
14124 $this->data = '';
14125 if ($this->state === 'emit')
14126 {
14127 return true;
14128 }
14129 else
14130 {
14131 $this->version = '';
14132 $this->encoding = '';
14133 $this->standalone = '';
14134 return false;
14135 }
14136 }
14137
14138 /**
14139 * Check whether there is data beyond the pointer
14140 *
14141 * @access private
14142 * @return bool true if there is further data, false if not
14143 */
14144 function has_data()
14145 {
14146 return (bool) ($this->position < $this->data_length);
14147 }
14148
14149 /**
14150 * Advance past any whitespace
14151 *
14152 * @return int Number of whitespace characters passed
14153 */
14154 function skip_whitespace()
14155 {
14156 $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
14157 $this->position += $whitespace;
14158 return $whitespace;
14159 }
14160
14161 /**
14162 * Read value
14163 */
14164 function get_value()
14165 {
14166 $quote = substr($this->data, $this->position, 1);
14167 if ($quote === '"' || $quote === "'")
14168 {
14169 $this->position++;
14170 $len = strcspn($this->data, $quote, $this->position);
14171 if ($this->has_data())
14172 {
14173 $value = substr($this->data, $this->position, $len);
14174 $this->position += $len + 1;
14175 return $value;
14176 }
14177 }
14178 return false;
14179 }
14180
14181 function before_version_name()
14182 {
14183 if ($this->skip_whitespace())
14184 {
14185 $this->state = 'version_name';
14186 }
14187 else
14188 {
14189 $this->state = false;
14190 }
14191 }
14192
14193 function version_name()
14194 {
14195 if (substr($this->data, $this->position, 7) === 'version')
14196 {
14197 $this->position += 7;
14198 $this->skip_whitespace();
14199 $this->state = 'version_equals';
14200 }
14201 else
14202 {
14203 $this->state = false;
14204 }
14205 }
14206
14207 function version_equals()
14208 {
14209 if (substr($this->data, $this->position, 1) === '=')
14210 {
14211 $this->position++;
14212 $this->skip_whitespace();
14213 $this->state = 'version_value';
14214 }
14215 else
14216 {
14217 $this->state = false;
14218 }
14219 }
14220
14221 function version_value()
14222 {
14223 if ($this->version = $this->get_value())
14224 {
14225 $this->skip_whitespace();
14226 if ($this->has_data())
14227 {
14228 $this->state = 'encoding_name';
14229 }
14230 else
14231 {
14232 $this->state = 'emit';
14233 }
14234 }
14235 else
14236 {
14237 $this->state = false;
14238 }
14239 }
14240
14241 function encoding_name()
14242 {
14243 if (substr($this->data, $this->position, 8) === 'encoding')
14244 {
14245 $this->position += 8;
14246 $this->skip_whitespace();
14247 $this->state = 'encoding_equals';
14248 }
14249 else
14250 {
14251 $this->state = 'standalone_name';
14252 }
14253 }
14254
14255 function encoding_equals()
14256 {
14257 if (substr($this->data, $this->position, 1) === '=')
14258 {
14259 $this->position++;
14260 $this->skip_whitespace();
14261 $this->state = 'encoding_value';
14262 }
14263 else
14264 {
14265 $this->state = false;
14266 }
14267 }
14268
14269 function encoding_value()
14270 {
14271 if ($this->encoding = $this->get_value())
14272 {
14273 $this->skip_whitespace();
14274 if ($this->has_data())
14275 {
14276 $this->state = 'standalone_name';
14277 }
14278 else
14279 {
14280 $this->state = 'emit';
14281 }
14282 }
14283 else
14284 {
14285 $this->state = false;
14286 }
14287 }
14288
14289 function standalone_name()
14290 {
14291 if (substr($this->data, $this->position, 10) === 'standalone')
14292 {
14293 $this->position += 10;
14294 $this->skip_whitespace();
14295 $this->state = 'standalone_equals';
14296 }
14297 else
14298 {
14299 $this->state = false;
14300 }
14301 }
14302
14303 function standalone_equals()
14304 {
14305 if (substr($this->data, $this->position, 1) === '=')
14306 {
14307 $this->position++;
14308 $this->skip_whitespace();
14309 $this->state = 'standalone_value';
14310 }
14311 else
14312 {
14313 $this->state = false;
14314 }
14315 }
14316
14317 function standalone_value()
14318 {
14319 if ($standalone = $this->get_value())
14320 {
14321 switch ($standalone)
14322 {
14323 case 'yes':
14324 $this->standalone = true;
14325 break;
14326
14327 case 'no':
14328 $this->standalone = false;
14329 break;
14330
14331 default:
14332 $this->state = false;
14333 return;
14334 }
14335
14336 $this->skip_whitespace();
14337 if ($this->has_data())
14338 {
14339 $this->state = false;
14340 }
14341 else
14342 {
14343 $this->state = 'emit';
14344 }
14345 }
14346 else
14347 {
14348 $this->state = false;
14349 }
14350 }
14351 }
14352
14353 class SimplePie_Locator
14354 {
14355 var $useragent;
14356 var $timeout;
14357 var $file;
14358 var $local = array();
14359 var $elsewhere = array();
14360 var $file_class = 'SimplePie_File';
14361 var $cached_entities = array();
14362 var $http_base;
14363 var $base;
14364 var $base_location = 0;
14365 var $checked_feeds = 0;
14366 var $max_checked_feeds = 10;
14367 var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
14368
14369 function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
14370 {
14371 $this->file =& $file;
14372 $this->file_class = $file_class;
14373 $this->useragent = $useragent;
14374 $this->timeout = $timeout;
14375 $this->max_checked_feeds = $max_checked_feeds;
14376 $this->content_type_sniffer_class = $content_type_sniffer_class;
14377 }
14378
14379 function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
14380 {
14381 if ($this->is_feed($this->file))
14382 {
14383 return $this->file;
14384 }
14385
14386 if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14387 {
14388 $sniffer =& new $this->content_type_sniffer_class($this->file);
14389 if ($sniffer->get_type() !== 'text/html')
14390 {
14391 return null;
14392 }
14393 }
14394
14395 if ($type & ~SIMPLEPIE_LOCATOR_NONE)
14396 {
14397 $this->get_base();
14398 }
14399
14400 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
14401 {
14402 return $working[0];
14403 }
14404
14405 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
14406 {
14407 if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
14408 {
14409 return $working;
14410 }
14411
14412 if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
14413 {
14414 return $working;
14415 }
14416
14417 if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
14418 {
14419 return $working;
14420 }
14421
14422 if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
14423 {
14424 return $working;
14425 }
14426 }
14427 return null;
14428 }
14429
14430 function is_feed(&$file)
14431 {
14432 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14433 {
14434 $sniffer =& new $this->content_type_sniffer_class($file);
14435 $sniffed = $sniffer->get_type();
14436 if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
14437 {
14438 return true;
14439 }
14440 else
14441 {
14442 return false;
14443 }
14444 }
14445 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
14446 {
14447 return true;
14448 }
14449 else
14450 {
14451 return false;
14452 }
14453 }
14454
14455 function get_base()
14456 {
14457 $this->http_base = $this->file->url;
14458 $this->base = $this->http_base;
14459 $elements = SimplePie_Misc::get_element('base', $this->file->body);
14460 foreach ($elements as $element)
14461 {
14462 if ($element['attribs']['href']['data'] !== '')
14463 {
14464 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
14465 $this->base_location = $element['offset'];
14466 break;
14467 }
14468 }
14469 }
14470
14471 function autodiscovery()
14472 {
14473 $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));
14474 $done = array();
14475 $feeds = array();
14476 foreach ($links as $link)
14477 {
14478 if ($this->checked_feeds === $this->max_checked_feeds)
14479 {
14480 break;
14481 }
14482 if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
14483 {
14484 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
14485
14486 if ($this->base_location < $link['offset'])
14487 {
14488 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14489 }
14490 else
14491 {
14492 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14493 }
14494
14495 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]))
14496 {
14497 $this->checked_feeds++;
14498 $feed =& new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
14499 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))
14500 {
14501 $feeds[$href] = $feed;
14502 }
14503 }
14504 $done[] = $href;
14505 }
14506 }
14507
14508 if (!empty($feeds))
14509 {
14510 return array_values($feeds);
14511 }
14512 else {
14513 return null;
14514 }
14515 }
14516
14517 function get_links()
14518 {
14519 $links = SimplePie_Misc::get_element('a', $this->file->body);
14520 foreach ($links as $link)
14521 {
14522 if (isset($link['attribs']['href']['data']))
14523 {
14524 $href = trim($link['attribs']['href']['data']);
14525 $parsed = SimplePie_Misc::parse_url($href);
14526 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
14527 {
14528 if ($this->base_location < $link['offset'])
14529 {
14530 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14531 }
14532 else
14533 {
14534 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14535 }
14536
14537 $current = SimplePie_Misc::parse_url($this->file->url);
14538
14539 if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
14540 {
14541 $this->local[] = $href;
14542 }
14543 else
14544 {
14545 $this->elsewhere[] = $href;
14546 }
14547 }
14548 }
14549 }
14550 $this->local = array_unique($this->local);
14551 $this->elsewhere = array_unique($this->elsewhere);
14552 if (!empty($this->local) || !empty($this->elsewhere))
14553 {
14554 return true;
14555 }
14556 return null;
14557 }
14558
14559 function extension(&$array)
14560 {
14561 foreach ($array as $key => $value)
14562 {
14563 if ($this->checked_feeds === $this->max_checked_feeds)
14564 {
14565 break;
14566 }
14567 if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
14568 {
14569 $this->checked_feeds++;
14570 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14571 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))
14572 {
14573 return $feed;
14574 }
14575 else
14576 {
14577 unset($array[$key]);
14578 }
14579 }
14580 }
14581 return null;
14582 }
14583
14584 function body(&$array)
14585 {
14586 foreach ($array as $key => $value)
14587 {
14588 if ($this->checked_feeds === $this->max_checked_feeds)
14589 {
14590 break;
14591 }
14592 if (preg_match('/(rss|rdf|atom|xml)/i', $value))
14593 {
14594 $this->checked_feeds++;
14595 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14596 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))
14597 {
14598 return $feed;
14599 }
14600 else
14601 {
14602 unset($array[$key]);
14603 }
14604 }
14605 }
14606 return null;
14607 }
14608 }
14609
14610 class SimplePie_Parser
14611 {
14612 var $error_code;
14613 var $error_string;
14614 var $current_line;
14615 var $current_column;
14616 var $current_byte;
14617 var $separator = ' ';
14618 var $namespace = array('');
14619 var $element = array('');
14620 var $xml_base = array('');
14621 var $xml_base_explicit = array(false);
14622 var $xml_lang = array('');
14623 var $data = array();
14624 var $datas = array(array());
14625 var $current_xhtml_construct = -1;
14626 var $encoding;
14627
14628 function parse(&$data, $encoding)
14629 {
14630 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
14631 if (strtoupper($encoding) === 'US-ASCII')
14632 {
14633 $this->encoding = 'UTF-8';
14634 }
14635 else
14636 {
14637 $this->encoding = $encoding;
14638 }
14639
14640 // Strip BOM:
14641 // UTF-32 Big Endian BOM
14642 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14643 {
14644 $data = substr($data, 4);
14645 }
14646 // UTF-32 Little Endian BOM
14647 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14648 {
14649 $data = substr($data, 4);
14650 }
14651 // UTF-16 Big Endian BOM
14652 elseif (substr($data, 0, 2) === "\xFE\xFF")
14653 {
14654 $data = substr($data, 2);
14655 }
14656 // UTF-16 Little Endian BOM
14657 elseif (substr($data, 0, 2) === "\xFF\xFE")
14658 {
14659 $data = substr($data, 2);
14660 }
14661 // UTF-8 BOM
14662 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14663 {
14664 $data = substr($data, 3);
14665 }
14666
14667 if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
14668 {
14669 $declaration =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
14670 if ($declaration->parse())
14671 {
14672 $data = substr($data, $pos + 2);
14673 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
14674 }
14675 else
14676 {
14677 $this->error_string = 'SimplePie bug! Please report this!';
14678 return false;
14679 }
14680 }
14681
14682 $return = true;
14683
14684 static $xml_is_sane = null;
14685 if ($xml_is_sane === null)
14686 {
14687 $parser_check = xml_parser_create();
14688 xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
14689 xml_parser_free($parser_check);
14690 $xml_is_sane = isset($values[0]['value']);
14691 }
14692
14693 // Create the parser
14694 if ($xml_is_sane)
14695 {
14696 $xml = xml_parser_create_ns($this->encoding, $this->separator);
14697 xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
14698 xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
14699 xml_set_object($xml, $this);
14700 xml_set_character_data_handler($xml, 'cdata');
14701 xml_set_element_handler($xml, 'tag_open', 'tag_close');
14702
14703 // Parse!
14704 if (!xml_parse($xml, $data, true))
14705 {
14706 $this->error_code = xml_get_error_code($xml);
14707 $this->error_string = xml_error_string($this->error_code);
14708 $return = false;
14709 }
14710 $this->current_line = xml_get_current_line_number($xml);
14711 $this->current_column = xml_get_current_column_number($xml);
14712 $this->current_byte = xml_get_current_byte_index($xml);
14713 xml_parser_free($xml);
14714 return $return;
14715 }
14716 else
14717 {
14718 libxml_clear_errors();
14719 $xml =& new XMLReader();
14720 $xml->xml($data);
14721 while (@$xml->read())
14722 {
14723 switch ($xml->nodeType)
14724 {
14725
14726 case constant('XMLReader::END_ELEMENT'):
14727 if ($xml->namespaceURI !== '')
14728 {
14729 $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
14730 }
14731 else
14732 {
14733 $tagName = $xml->localName;
14734 }
14735 $this->tag_close(null, $tagName);
14736 break;
14737 case constant('XMLReader::ELEMENT'):
14738 $empty = $xml->isEmptyElement;
14739 if ($xml->namespaceURI !== '')
14740 {
14741 $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
14742 }
14743 else
14744 {
14745 $tagName = $xml->localName;
14746 }
14747 $attributes = array();
14748 while ($xml->moveToNextAttribute())
14749 {
14750 if ($xml->namespaceURI !== '')
14751 {
14752 $attrName = $xml->namespaceURI . $this->separator . $xml->localName;
14753 }
14754 else
14755 {
14756 $attrName = $xml->localName;
14757 }
14758 $attributes[$attrName] = $xml->value;
14759 }
14760 $this->tag_open(null, $tagName, $attributes);
14761 if ($empty)
14762 {
14763 $this->tag_close(null, $tagName);
14764 }
14765 break;
14766 case constant('XMLReader::TEXT'):
14767
14768 case constant('XMLReader::CDATA'):
14769 $this->cdata(null, $xml->value);
14770 break;
14771 }
14772 }
14773 if ($error = libxml_get_last_error())
14774 {
14775 $this->error_code = $error->code;
14776 $this->error_string = $error->message;
14777 $this->current_line = $error->line;
14778 $this->current_column = $error->column;
14779 return false;
14780 }
14781 else
14782 {
14783 return true;
14784 }
14785 }
14786 }
14787
14788 function get_error_code()
14789 {
14790 return $this->error_code;
14791 }
14792
14793 function get_error_string()
14794 {
14795 return $this->error_string;
14796 }
14797
14798 function get_current_line()
14799 {
14800 return $this->current_line;
14801 }
14802
14803 function get_current_column()
14804 {
14805 return $this->current_column;
14806 }
14807
14808 function get_current_byte()
14809 {
14810 return $this->current_byte;
14811 }
14812
14813 function get_data()
14814 {
14815 return $this->data;
14816 }
14817
14818 function tag_open($parser, $tag, $attributes)
14819 {
14820 list($this->namespace[], $this->element[]) = $this->split_ns($tag);
14821
14822 $attribs = array();
14823 foreach ($attributes as $name => $value)
14824 {
14825 list($attrib_namespace, $attribute) = $this->split_ns($name);
14826 $attribs[$attrib_namespace][$attribute] = $value;
14827 }
14828
14829 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
14830 {
14831 $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
14832 $this->xml_base_explicit[] = true;
14833 }
14834 else
14835 {
14836 $this->xml_base[] = end($this->xml_base);
14837 $this->xml_base_explicit[] = end($this->xml_base_explicit);
14838 }
14839
14840 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
14841 {
14842 $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
14843 }
14844 else
14845 {
14846 $this->xml_lang[] = end($this->xml_lang);
14847 }
14848
14849 if ($this->current_xhtml_construct >= 0)
14850 {
14851 $this->current_xhtml_construct++;
14852 if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
14853 {
14854 $this->data['data'] .= '<' . end($this->element);
14855 if (isset($attribs['']))
14856 {
14857 foreach ($attribs[''] as $name => $value)
14858 {
14859 $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
14860 }
14861 }
14862 $this->data['data'] .= '>';
14863 }
14864 }
14865 else
14866 {
14867 $this->datas[] =& $this->data;
14868 $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
14869 $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));
14870 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')
14871 || (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'))
14872 {
14873 $this->current_xhtml_construct = 0;
14874 }
14875 }
14876 }
14877
14878 function cdata($parser, $cdata)
14879 {
14880 if ($this->current_xhtml_construct >= 0)
14881 {
14882 $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
14883 }
14884 else
14885 {
14886 $this->data['data'] .= $cdata;
14887 }
14888 }
14889
14890 function tag_close($parser, $tag)
14891 {
14892 if ($this->current_xhtml_construct >= 0)
14893 {
14894 $this->current_xhtml_construct--;
14895 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')))
14896 {
14897 $this->data['data'] .= '</' . end($this->element) . '>';
14898 }
14899 }
14900 if ($this->current_xhtml_construct === -1)
14901 {
14902 $this->data =& $this->datas[count($this->datas) - 1];
14903 array_pop($this->datas);
14904 }
14905
14906 array_pop($this->element);
14907 array_pop($this->namespace);
14908 array_pop($this->xml_base);
14909 array_pop($this->xml_base_explicit);
14910 array_pop($this->xml_lang);
14911 }
14912
14913 function split_ns($string)
14914 {
14915 static $cache = array();
14916 if (!isset($cache[$string]))
14917 {
14918 if ($pos = strpos($string, $this->separator))
14919 {
14920 static $separator_length;
14921 if (!$separator_length)
14922 {
14923 $separator_length = strlen($this->separator);
14924 }
14925 $namespace = substr($string, 0, $pos);
14926 $local_name = substr($string, $pos + $separator_length);
14927 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
14928 {
14929 $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
14930 }
14931
14932 // Normalize the Media RSS namespaces
14933 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
14934 {
14935 $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
14936 }
14937 $cache[$string] = array($namespace, $local_name);
14938 }
14939 else
14940 {
14941 $cache[$string] = array('', $string);
14942 }
14943 }
14944 return $cache[$string];
14945 }
14946 }
14947
14948 /**
14949 * @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
14950 */
14951 class SimplePie_Sanitize
14952 {
14953 // Private vars
14954 var $base;
14955
14956 // Options
14957 var $remove_div = true;
14958 var $image_handler = '';
14959 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
14960 var $encode_instead_of_strip = false;
14961 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
14962 var $strip_comments = false;
14963 var $output_encoding = 'UTF-8';
14964 var $enable_cache = true;
14965 var $cache_location = './cache';
14966 var $cache_name_function = 'md5';
14967 var $cache_class = 'SimplePie_Cache';
14968 var $file_class = 'SimplePie_File';
14969 var $timeout = 10;
14970 var $useragent = '';
14971 var $force_fsockopen = false;
14972
14973 var $replace_url_attributes = array(
14974 'a' => 'href',
14975 'area' => 'href',
14976 'blockquote' => 'cite',
14977 'del' => 'cite',
14978 'form' => 'action',
14979 'img' => array('longdesc', 'src'),
14980 'input' => 'src',
14981 'ins' => 'cite',
14982 'q' => 'cite'
14983 );
14984
14985 function remove_div($enable = true)
14986 {
14987 $this->remove_div = (bool) $enable;
14988 }
14989
14990 function set_image_handler($page = false)
14991 {
14992 if ($page)
14993 {
14994 $this->image_handler = (string) $page;
14995 }
14996 else
14997 {
14998 $this->image_handler = false;
14999 }
15000 }
15001
15002 function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
15003 {
15004 if (isset($enable_cache))
15005 {
15006 $this->enable_cache = (bool) $enable_cache;
15007 }
15008
15009 if ($cache_location)
15010 {
15011 $this->cache_location = (string) $cache_location;
15012 }
15013
15014 if ($cache_name_function)
15015 {
15016 $this->cache_name_function = (string) $cache_name_function;
15017 }
15018
15019 if ($cache_class)
15020 {
15021 $this->cache_class = (string) $cache_class;
15022 }
15023 }
15024
15025 function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
15026 {
15027 if ($file_class)
15028 {
15029 $this->file_class = (string) $file_class;
15030 }
15031
15032 if ($timeout)
15033 {
15034 $this->timeout = (string) $timeout;
15035 }
15036
15037 if ($useragent)
15038 {
15039 $this->useragent = (string) $useragent;
15040 }
15041
15042 if ($force_fsockopen)
15043 {
15044 $this->force_fsockopen = (string) $force_fsockopen;
15045 }
15046 }
15047
15048 function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
15049 {
15050 if ($tags)
15051 {
15052 if (is_array($tags))
15053 {
15054 $this->strip_htmltags = $tags;
15055 }
15056 else
15057 {
15058 $this->strip_htmltags = explode(',', $tags);
15059 }
15060 }
15061 else
15062 {
15063 $this->strip_htmltags = false;
15064 }
15065 }
15066
15067 function encode_instead_of_strip($encode = false)
15068 {
15069 $this->encode_instead_of_strip = (bool) $encode;
15070 }
15071
15072 function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
15073 {
15074 if ($attribs)
15075 {
15076 if (is_array($attribs))
15077 {
15078 $this->strip_attributes = $attribs;
15079 }
15080 else
15081 {
15082 $this->strip_attributes = explode(',', $attribs);
15083 }
15084 }
15085 else
15086 {
15087 $this->strip_attributes = false;
15088 }
15089 }
15090
15091 function strip_comments($strip = false)
15092 {
15093 $this->strip_comments = (bool) $strip;
15094 }
15095
15096 function set_output_encoding($encoding = 'UTF-8')
15097 {
15098 $this->output_encoding = (string) $encoding;
15099 }
15100
15101 /**
15102 * Set element/attribute key/value pairs of HTML attributes
15103 * containing URLs that need to be resolved relative to the feed
15104 *
15105 * @access public
15106 * @since 1.0
15107 * @param array $element_attribute Element/attribute key/value pairs
15108 */
15109 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'))
15110 {
15111 $this->replace_url_attributes = (array) $element_attribute;
15112 }
15113
15114 function sanitize($data, $type, $base = '')
15115 {
15116 $data = trim($data);
15117 if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
15118 {
15119 if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
15120 {
15121 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))
15122 {
15123 $type |= SIMPLEPIE_CONSTRUCT_HTML;
15124 }
15125 else
15126 {
15127 $type |= SIMPLEPIE_CONSTRUCT_TEXT;
15128 }
15129 }
15130
15131 if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
15132 {
15133 $data = base64_decode($data);
15134 }
15135
15136 if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
15137 {
15138 if ($this->remove_div)
15139 {
15140 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
15141 $data = preg_replace('/<\/div>$/', '', $data);
15142 }
15143 else
15144 {
15145 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
15146 }
15147 }
15148
15149 if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
15150 {
15151 // Strip comments
15152 if ($this->strip_comments)
15153 {
15154 $data = SimplePie_Misc::strip_comments($data);
15155 }
15156
15157 // Strip out HTML tags and attributes that might cause various security problems.
15158 // Based on recommendations by Mark Pilgrim at:
15159 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
15160 if ($this->strip_htmltags)
15161 {
15162 foreach ($this->strip_htmltags as $tag)
15163 {
15164 $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
15165 while (preg_match($pcre, $data))
15166 {
15167 $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
15168 }
15169 }
15170 }
15171
15172 if ($this->strip_attributes)
15173 {
15174 foreach ($this->strip_attributes as $attrib)
15175 {
15176 $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);
15177 }
15178 }
15179
15180 // Replace relative URLs
15181 $this->base = $base;
15182 foreach ($this->replace_url_attributes as $element => $attributes)
15183 {
15184 $data = $this->replace_urls($data, $element, $attributes);
15185 }
15186
15187 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
15188 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
15189 {
15190 $images = SimplePie_Misc::get_element('img', $data);
15191 foreach ($images as $img)
15192 {
15193 if (isset($img['attribs']['src']['data']))
15194 {
15195 $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
15196 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
15197
15198 if ($cache->load())
15199 {
15200 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15201 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15202 }
15203 else
15204 {
15205 $file =& new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
15206 $headers = $file->headers;
15207
15208 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
15209 {
15210 if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
15211 {
15212 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15213 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15214 }
15215 else
15216 {
15217 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);
15218 }
15219 }
15220 }
15221 }
15222 }
15223 }
15224
15225 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
15226 $data = trim($data);
15227 }
15228
15229 if ($type & SIMPLEPIE_CONSTRUCT_IRI)
15230 {
15231 $data = SimplePie_Misc::absolutize_url($data, $base);
15232 }
15233
15234 if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
15235 {
15236 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
15237 }
15238
15239 if ($this->output_encoding !== 'UTF-8')
15240 {
15241 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
15242 }
15243 }
15244 return $data;
15245 }
15246
15247 function replace_urls($data, $tag, $attributes)
15248 {
15249 if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
15250 {
15251 $elements = SimplePie_Misc::get_element($tag, $data);
15252 foreach ($elements as $element)
15253 {
15254 if (is_array($attributes))
15255 {
15256 foreach ($attributes as $attribute)
15257 {
15258 if (isset($element['attribs'][$attribute]['data']))
15259 {
15260 $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
15261 $new_element = SimplePie_Misc::element_implode($element);
15262 $data = str_replace($element['full'], $new_element, $data);
15263 $element['full'] = $new_element;
15264 }
15265 }
15266 }
15267 elseif (isset($element['attribs'][$attributes]['data']))
15268 {
15269 $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
15270 $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
15271 }
15272 }
15273 }
15274 return $data;
15275 }
15276
15277 function do_strip_htmltags($match)
15278 {
15279 if ($this->encode_instead_of_strip)
15280 {
15281 if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15282 {
15283 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
15284 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
15285 return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
15286 }
15287 else
15288 {
15289 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
15290 }
15291 }
15292 elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15293 {
15294 return $match[4];
15295 }
15296 else
15297 {
15298 return '';
15299 }
15300 }
15301 }
15302
15303 ?>