]> git.wh0rd.org - tt-rss.git/blob - lib/simplepie/simplepie.inc
simplepie: enable digest authentication
[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-2009, Ryan Parman and Geoffrey Sneddon
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without modification, are
12 * permitted provided that the following conditions are met:
13 *
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
37 * @copyright 2004-2009 Ryan Parman, Geoffrey Sneddon
38 * @author Ryan Parman
39 * @author Geoffrey Sneddon
40 * @link http://simplepie.org/ SimplePie
41 * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
42 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
43 * @todo phpDoc comments
44 */
45
46 /**
47 * SimplePie Name
48 */
49 define('SIMPLEPIE_NAME', 'SimplePie');
50
51 /**
52 * SimplePie Version
53 */
54 define('SIMPLEPIE_VERSION', '1.2');
55
56 /**
57 * SimplePie Build
58 */
59 define('SIMPLEPIE_BUILD', '20090627192103');
60
61 /**
62 * SimplePie Website URL
63 */
64 define('SIMPLEPIE_URL', 'http://simplepie.org');
65
66 /**
67 * SimplePie Useragent
68 * @see SimplePie::set_useragent()
69 */
70 define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
71
72 /**
73 * SimplePie Linkback
74 */
75 define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
76
77 /**
78 * No Autodiscovery
79 * @see SimplePie::set_autodiscovery_level()
80 */
81 define('SIMPLEPIE_LOCATOR_NONE', 0);
82
83 /**
84 * Feed Link Element Autodiscovery
85 * @see SimplePie::set_autodiscovery_level()
86 */
87 define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
88
89 /**
90 * Local Feed Extension Autodiscovery
91 * @see SimplePie::set_autodiscovery_level()
92 */
93 define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
94
95 /**
96 * Local Feed Body Autodiscovery
97 * @see SimplePie::set_autodiscovery_level()
98 */
99 define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
100
101 /**
102 * Remote Feed Extension Autodiscovery
103 * @see SimplePie::set_autodiscovery_level()
104 */
105 define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
106
107 /**
108 * Remote Feed Body Autodiscovery
109 * @see SimplePie::set_autodiscovery_level()
110 */
111 define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
112
113 /**
114 * All Feed Autodiscovery
115 * @see SimplePie::set_autodiscovery_level()
116 */
117 define('SIMPLEPIE_LOCATOR_ALL', 31);
118
119 /**
120 * No known feed type
121 */
122 define('SIMPLEPIE_TYPE_NONE', 0);
123
124 /**
125 * RSS 0.90
126 */
127 define('SIMPLEPIE_TYPE_RSS_090', 1);
128
129 /**
130 * RSS 0.91 (Netscape)
131 */
132 define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
133
134 /**
135 * RSS 0.91 (Userland)
136 */
137 define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
138
139 /**
140 * RSS 0.91 (both Netscape and Userland)
141 */
142 define('SIMPLEPIE_TYPE_RSS_091', 6);
143
144 /**
145 * RSS 0.92
146 */
147 define('SIMPLEPIE_TYPE_RSS_092', 8);
148
149 /**
150 * RSS 0.93
151 */
152 define('SIMPLEPIE_TYPE_RSS_093', 16);
153
154 /**
155 * RSS 0.94
156 */
157 define('SIMPLEPIE_TYPE_RSS_094', 32);
158
159 /**
160 * RSS 1.0
161 */
162 define('SIMPLEPIE_TYPE_RSS_10', 64);
163
164 /**
165 * RSS 2.0
166 */
167 define('SIMPLEPIE_TYPE_RSS_20', 128);
168
169 /**
170 * RDF-based RSS
171 */
172 define('SIMPLEPIE_TYPE_RSS_RDF', 65);
173
174 /**
175 * Non-RDF-based RSS (truly intended as syndication format)
176 */
177 define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
178
179 /**
180 * All RSS
181 */
182 define('SIMPLEPIE_TYPE_RSS_ALL', 255);
183
184 /**
185 * Atom 0.3
186 */
187 define('SIMPLEPIE_TYPE_ATOM_03', 256);
188
189 /**
190 * Atom 1.0
191 */
192 define('SIMPLEPIE_TYPE_ATOM_10', 512);
193
194 /**
195 * All Atom
196 */
197 define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
198
199 /**
200 * All feed types
201 */
202 define('SIMPLEPIE_TYPE_ALL', 1023);
203
204 /**
205 * No construct
206 */
207 define('SIMPLEPIE_CONSTRUCT_NONE', 0);
208
209 /**
210 * Text construct
211 */
212 define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
213
214 /**
215 * HTML construct
216 */
217 define('SIMPLEPIE_CONSTRUCT_HTML', 2);
218
219 /**
220 * XHTML construct
221 */
222 define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
223
224 /**
225 * base64-encoded construct
226 */
227 define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
228
229 /**
230 * IRI construct
231 */
232 define('SIMPLEPIE_CONSTRUCT_IRI', 16);
233
234 /**
235 * A construct that might be HTML
236 */
237 define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
238
239 /**
240 * All constructs
241 */
242 define('SIMPLEPIE_CONSTRUCT_ALL', 63);
243
244 /**
245 * Don't change case
246 */
247 define('SIMPLEPIE_SAME_CASE', 1);
248
249 /**
250 * Change to lowercase
251 */
252 define('SIMPLEPIE_LOWERCASE', 2);
253
254 /**
255 * Change to uppercase
256 */
257 define('SIMPLEPIE_UPPERCASE', 4);
258
259 /**
260 * PCRE for HTML attributes
261 */
262 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]*');
263
264 /**
265 * PCRE for XML attributes
266 */
267 define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
268
269 /**
270 * XML Namespace
271 */
272 define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
273
274 /**
275 * Atom 1.0 Namespace
276 */
277 define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
278
279 /**
280 * Atom 0.3 Namespace
281 */
282 define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
283
284 /**
285 * RDF Namespace
286 */
287 define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
288
289 /**
290 * RSS 0.90 Namespace
291 */
292 define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
293
294 /**
295 * RSS 1.0 Namespace
296 */
297 define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
298
299 /**
300 * RSS 1.0 Content Module Namespace
301 */
302 define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
303
304 /**
305 * RSS 2.0 Namespace
306 * (Stupid, I know, but I'm certain it will confuse people less with support.)
307 */
308 define('SIMPLEPIE_NAMESPACE_RSS_20', '');
309
310 /**
311 * DC 1.0 Namespace
312 */
313 define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
314
315 /**
316 * DC 1.1 Namespace
317 */
318 define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
319
320 /**
321 * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
322 */
323 define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
324
325 /**
326 * GeoRSS Namespace
327 */
328 define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
329
330 /**
331 * Media RSS Namespace
332 */
333 define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
334
335 /**
336 * Wrong Media RSS Namespace
337 */
338 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
339
340 /**
341 * iTunes RSS Namespace
342 */
343 define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
344
345 /**
346 * XHTML Namespace
347 */
348 define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
349
350 /**
351 * IANA Link Relations Registry
352 */
353 define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
354
355 /**
356 * Whether we're running on PHP5
357 */
358 define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
359
360 /**
361 * No file source
362 */
363 define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
364
365 /**
366 * Remote file source
367 */
368 define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
369
370 /**
371 * Local file source
372 */
373 define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
374
375 /**
376 * fsockopen() file source
377 */
378 define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
379
380 /**
381 * cURL file source
382 */
383 define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
384
385 /**
386 * file_get_contents() file source
387 */
388 define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
389
390 /**
391 * SimplePie
392 *
393 * @package SimplePie
394 */
395 class SimplePie
396 {
397 /**
398 * @var array Raw data
399 * @access private
400 */
401 var $data = array();
402
403 /**
404 * @var mixed Error string
405 * @access private
406 */
407 var $error;
408
409 /**
410 * @var object Instance of SimplePie_Sanitize (or other class)
411 * @see SimplePie::set_sanitize_class()
412 * @access private
413 */
414 var $sanitize;
415
416 /**
417 * @var string SimplePie Useragent
418 * @see SimplePie::set_useragent()
419 * @access private
420 */
421 var $useragent = SIMPLEPIE_USERAGENT;
422
423 /**
424 * @var string Feed URL
425 * @see SimplePie::set_feed_url()
426 * @access private
427 */
428 var $feed_url;
429
430 /**
431 * @var object Instance of SimplePie_File to use as a feed
432 * @see SimplePie::set_file()
433 * @access private
434 */
435 var $file;
436
437 /**
438 * @var string Raw feed data
439 * @see SimplePie::set_raw_data()
440 * @access private
441 */
442 var $raw_data;
443
444 /**
445 * @var int Timeout for fetching remote files
446 * @see SimplePie::set_timeout()
447 * @access private
448 */
449 var $timeout = 10;
450
451 /**
452 * @var bool Forces fsockopen() to be used for remote files instead
453 * of cURL, even if a new enough version is installed
454 * @see SimplePie::force_fsockopen()
455 * @access private
456 */
457 var $force_fsockopen = false;
458
459 /**
460 * @var bool Force the given data/URL to be treated as a feed no matter what
461 * it appears like
462 * @see SimplePie::force_feed()
463 * @access private
464 */
465 var $force_feed = false;
466
467 /**
468 * @var bool Enable/Disable XML dump
469 * @see SimplePie::enable_xml_dump()
470 * @access private
471 */
472 var $xml_dump = false;
473
474 /**
475 * @var bool Enable/Disable Caching
476 * @see SimplePie::enable_cache()
477 * @access private
478 */
479 var $cache = true;
480
481 /**
482 * @var int Cache duration (in seconds)
483 * @see SimplePie::set_cache_duration()
484 * @access private
485 */
486 var $cache_duration = 3600;
487
488 /**
489 * @var int Auto-discovery cache duration (in seconds)
490 * @see SimplePie::set_autodiscovery_cache_duration()
491 * @access private
492 */
493 var $autodiscovery_cache_duration = 604800; // 7 Days.
494
495 /**
496 * @var string Cache location (relative to executing script)
497 * @see SimplePie::set_cache_location()
498 * @access private
499 */
500 var $cache_location = './cache';
501
502 /**
503 * @var string Function that creates the cache filename
504 * @see SimplePie::set_cache_name_function()
505 * @access private
506 */
507 var $cache_name_function = 'md5';
508
509 /**
510 * @var bool Reorder feed by date descending
511 * @see SimplePie::enable_order_by_date()
512 * @access private
513 */
514 var $order_by_date = true;
515
516 /**
517 * @var mixed Force input encoding to be set to the follow value
518 * (false, or anything type-cast to false, disables this feature)
519 * @see SimplePie::set_input_encoding()
520 * @access private
521 */
522 var $input_encoding = false;
523
524 /**
525 * @var int Feed Autodiscovery Level
526 * @see SimplePie::set_autodiscovery_level()
527 * @access private
528 */
529 var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
530
531 /**
532 * @var string Class used for caching feeds
533 * @see SimplePie::set_cache_class()
534 * @access private
535 */
536 var $cache_class = 'SimplePie_Cache';
537
538 /**
539 * @var string Class used for locating feeds
540 * @see SimplePie::set_locator_class()
541 * @access private
542 */
543 var $locator_class = 'SimplePie_Locator';
544
545 /**
546 * @var string Class used for parsing feeds
547 * @see SimplePie::set_parser_class()
548 * @access private
549 */
550 var $parser_class = 'SimplePie_Parser';
551
552 /**
553 * @var string Class used for fetching feeds
554 * @see SimplePie::set_file_class()
555 * @access private
556 */
557 var $file_class = 'SimplePie_File';
558
559 /**
560 * @var string Class used for items
561 * @see SimplePie::set_item_class()
562 * @access private
563 */
564 var $item_class = 'SimplePie_Item';
565
566 /**
567 * @var string Class used for authors
568 * @see SimplePie::set_author_class()
569 * @access private
570 */
571 var $author_class = 'SimplePie_Author';
572
573 /**
574 * @var string Class used for categories
575 * @see SimplePie::set_category_class()
576 * @access private
577 */
578 var $category_class = 'SimplePie_Category';
579
580 /**
581 * @var string Class used for enclosures
582 * @see SimplePie::set_enclosures_class()
583 * @access private
584 */
585 var $enclosure_class = 'SimplePie_Enclosure';
586
587 /**
588 * @var string Class used for Media RSS <media:text> captions
589 * @see SimplePie::set_caption_class()
590 * @access private
591 */
592 var $caption_class = 'SimplePie_Caption';
593
594 /**
595 * @var string Class used for Media RSS <media:copyright>
596 * @see SimplePie::set_copyright_class()
597 * @access private
598 */
599 var $copyright_class = 'SimplePie_Copyright';
600
601 /**
602 * @var string Class used for Media RSS <media:credit>
603 * @see SimplePie::set_credit_class()
604 * @access private
605 */
606 var $credit_class = 'SimplePie_Credit';
607
608 /**
609 * @var string Class used for Media RSS <media:rating>
610 * @see SimplePie::set_rating_class()
611 * @access private
612 */
613 var $rating_class = 'SimplePie_Rating';
614
615 /**
616 * @var string Class used for Media RSS <media:restriction>
617 * @see SimplePie::set_restriction_class()
618 * @access private
619 */
620 var $restriction_class = 'SimplePie_Restriction';
621
622 /**
623 * @var string Class used for content-type sniffing
624 * @see SimplePie::set_content_type_sniffer_class()
625 * @access private
626 */
627 var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
628
629 /**
630 * @var string Class used for item sources.
631 * @see SimplePie::set_source_class()
632 * @access private
633 */
634 var $source_class = 'SimplePie_Source';
635
636 /**
637 * @var mixed Set javascript query string parameter (false, or
638 * anything type-cast to false, disables this feature)
639 * @see SimplePie::set_javascript()
640 * @access private
641 */
642 var $javascript = 'js';
643
644 /**
645 * @var int Maximum number of feeds to check with autodiscovery
646 * @see SimplePie::set_max_checked_feeds()
647 * @access private
648 */
649 var $max_checked_feeds = 10;
650
651 /**
652 * @var array All the feeds found during the autodiscovery process
653 * @see SimplePie::get_all_discovered_feeds()
654 * @access private
655 */
656 var $all_discovered_feeds = array();
657
658 /**
659 * @var string Web-accessible path to the handler_favicon.php file.
660 * @see SimplePie::set_favicon_handler()
661 * @access private
662 */
663 var $favicon_handler = '';
664
665 /**
666 * @var string Web-accessible path to the handler_image.php file.
667 * @see SimplePie::set_image_handler()
668 * @access private
669 */
670 var $image_handler = '';
671
672 /**
673 * @var array Stores the URLs when multiple feeds are being initialized.
674 * @see SimplePie::set_feed_url()
675 * @access private
676 */
677 var $multifeed_url = array();
678
679 /**
680 * @var array Stores SimplePie objects when multiple feeds initialized.
681 * @access private
682 */
683 var $multifeed_objects = array();
684
685 /**
686 * @var array Stores the get_object_vars() array for use with multifeeds.
687 * @see SimplePie::set_feed_url()
688 * @access private
689 */
690 var $config_settings = null;
691
692 /**
693 * @var integer Stores the number of items to return per-feed with multifeeds.
694 * @see SimplePie::set_item_limit()
695 * @access private
696 */
697 var $item_limit = 0;
698
699 /**
700 * @var array Stores the default attributes to be stripped by strip_attributes().
701 * @see SimplePie::strip_attributes()
702 * @access private
703 */
704 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
705
706 /**
707 * @var array Stores the default tags to be stripped by strip_htmltags().
708 * @see SimplePie::strip_htmltags()
709 * @access private
710 */
711 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
712
713 /**
714 * The SimplePie class contains feed level data and options
715 *
716 * There are two ways that you can create a new SimplePie object. The first
717 * is by passing a feed URL as a parameter to the SimplePie constructor
718 * (as well as optionally setting the cache location and cache expiry). This
719 * will initialise the whole feed with all of the default settings, and you
720 * can begin accessing methods and properties immediately.
721 *
722 * The second way is to create the SimplePie object with no parameters
723 * at all. This will enable you to set configuration options. After setting
724 * them, you must initialise the feed using $feed->init(). At that point the
725 * object's methods and properties will be available to you. This format is
726 * what is used throughout this documentation.
727 *
728 * @access public
729 * @since 1.0 Preview Release
730 * @param string $feed_url This is the URL you want to parse.
731 * @param string $cache_location This is where you want the cache to be stored.
732 * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
733 */
734 function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
735 {
736 // Other objects, instances created here so we can set options on them
737 $this->sanitize =& new SimplePie_Sanitize;
738
739 // Set options if they're passed to the constructor
740 if ($cache_location !== null)
741 {
742 $this->set_cache_location($cache_location);
743 }
744
745 if ($cache_duration !== null)
746 {
747 $this->set_cache_duration($cache_duration);
748 }
749
750 // Only init the script if we're passed a feed URL
751 if ($feed_url !== null)
752 {
753 $this->set_feed_url($feed_url);
754 $this->init();
755 }
756 }
757
758 /**
759 * Used for converting object to a string
760 */
761 function __toString()
762 {
763 return md5(serialize($this->data));
764 }
765
766 /**
767 * Remove items that link back to this before destroying this object
768 */
769 function __destruct()
770 {
771 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
772 {
773 if (!empty($this->data['items']))
774 {
775 foreach ($this->data['items'] as $item)
776 {
777 $item->__destruct();
778 }
779 unset($item, $this->data['items']);
780 }
781 if (!empty($this->data['ordered_items']))
782 {
783 foreach ($this->data['ordered_items'] as $item)
784 {
785 $item->__destruct();
786 }
787 unset($item, $this->data['ordered_items']);
788 }
789 }
790 }
791
792 /**
793 * Force the given data/URL to be treated as a feed no matter what it
794 * appears like
795 *
796 * @access public
797 * @since 1.1
798 * @param bool $enable Force the given data/URL to be treated as a feed
799 */
800 function force_feed($enable = false)
801 {
802 $this->force_feed = (bool) $enable;
803 }
804
805 /**
806 * This is the URL of the feed you want to parse.
807 *
808 * This allows you to enter the URL of the feed you want to parse, or the
809 * website you want to try to use auto-discovery on. This takes priority
810 * over any set raw data.
811 *
812 * You can set multiple feeds to mash together by passing an array instead
813 * of a string for the $url. Remember that with each additional feed comes
814 * additional processing and resources.
815 *
816 * @access public
817 * @since 1.0 Preview Release
818 * @param mixed $url This is the URL (or array of URLs) that you want to parse.
819 * @see SimplePie::set_raw_data()
820 */
821 function set_feed_url($url)
822 {
823 if (is_array($url))
824 {
825 $this->multifeed_url = array();
826 foreach ($url as $value)
827 {
828 $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
829 }
830 }
831 else
832 {
833 $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
834 }
835 }
836
837 /**
838 * Provides an instance of SimplePie_File to use as a feed
839 *
840 * @access public
841 * @param object &$file Instance of SimplePie_File (or subclass)
842 * @return bool True on success, false on failure
843 */
844 function set_file(&$file)
845 {
846 if (is_a($file, 'SimplePie_File'))
847 {
848 $this->feed_url = $file->url;
849 $this->file =& $file;
850 return true;
851 }
852 return false;
853 }
854
855 /**
856 * Allows you to use a string of RSS/Atom data instead of a remote feed.
857 *
858 * If you have a feed available as a string in PHP, you can tell SimplePie
859 * to parse that data string instead of a remote feed. Any set feed URL
860 * takes precedence.
861 *
862 * @access public
863 * @since 1.0 Beta 3
864 * @param string $data RSS or Atom data as a string.
865 * @see SimplePie::set_feed_url()
866 */
867 function set_raw_data($data)
868 {
869 $this->raw_data = $data;
870 }
871
872 /**
873 * Allows you to override the default timeout for fetching remote feeds.
874 *
875 * This allows you to change the maximum time the feed's server to respond
876 * and send the feed back.
877 *
878 * @access public
879 * @since 1.0 Beta 3
880 * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
881 */
882 function set_timeout($timeout = 10)
883 {
884 $this->timeout = (int) $timeout;
885 }
886
887 /**
888 * Forces SimplePie to use fsockopen() instead of the preferred cURL
889 * functions.
890 *
891 * @access public
892 * @since 1.0 Beta 3
893 * @param bool $enable Force fsockopen() to be used
894 */
895 function force_fsockopen($enable = false)
896 {
897 $this->force_fsockopen = (bool) $enable;
898 }
899
900 /**
901 * Outputs the raw XML content of the feed, after it has gone through
902 * SimplePie's filters.
903 *
904 * Used only for debugging, this function will output the XML content as
905 * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
906 * before trying to parse it. Many parts of the feed are re-written in
907 * memory, and in the end, you have a parsable feed. XML dump shows you the
908 * actual XML that SimplePie tries to parse, which may or may not be very
909 * different from the original feed.
910 *
911 * @access public
912 * @since 1.0 Preview Release
913 * @param bool $enable Enable XML dump
914 */
915 function enable_xml_dump($enable = false)
916 {
917 $this->xml_dump = (bool) $enable;
918 }
919
920 /**
921 * Enables/disables caching in SimplePie.
922 *
923 * This option allows you to disable caching all-together in SimplePie.
924 * However, disabling the cache can lead to longer load times.
925 *
926 * @access public
927 * @since 1.0 Preview Release
928 * @param bool $enable Enable caching
929 */
930 function enable_cache($enable = true)
931 {
932 $this->cache = (bool) $enable;
933 }
934
935 /**
936 * Set the length of time (in seconds) that the contents of a feed
937 * will be cached.
938 *
939 * @access public
940 * @param int $seconds The feed content cache duration.
941 */
942 function set_cache_duration($seconds = 3600)
943 {
944 $this->cache_duration = (int) $seconds;
945 }
946
947 /**
948 * Set the length of time (in seconds) that the autodiscovered feed
949 * URL will be cached.
950 *
951 * @access public
952 * @param int $seconds The autodiscovered feed URL cache duration.
953 */
954 function set_autodiscovery_cache_duration($seconds = 604800)
955 {
956 $this->autodiscovery_cache_duration = (int) $seconds;
957 }
958
959 /**
960 * Set the file system location where the cached files should be stored.
961 *
962 * @access public
963 * @param string $location The file system location.
964 */
965 function set_cache_location($location = './cache')
966 {
967 $this->cache_location = (string) $location;
968 }
969
970 /**
971 * Determines whether feed items should be sorted into reverse chronological order.
972 *
973 * @access public
974 * @param bool $enable Sort as reverse chronological order.
975 */
976 function enable_order_by_date($enable = true)
977 {
978 $this->order_by_date = (bool) $enable;
979 }
980
981 /**
982 * Allows you to override the character encoding reported by the feed.
983 *
984 * @access public
985 * @param string $encoding Character encoding.
986 */
987 function set_input_encoding($encoding = false)
988 {
989 if ($encoding)
990 {
991 $this->input_encoding = (string) $encoding;
992 }
993 else
994 {
995 $this->input_encoding = false;
996 }
997 }
998
999 /**
1000 * Set how much feed autodiscovery to do
1001 *
1002 * @access public
1003 * @see SIMPLEPIE_LOCATOR_NONE
1004 * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
1005 * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
1006 * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
1007 * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
1008 * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
1009 * @see SIMPLEPIE_LOCATOR_ALL
1010 * @param int $level Feed Autodiscovery Level (level can be a
1011 * combination of the above constants, see bitwise OR operator)
1012 */
1013 function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
1014 {
1015 $this->autodiscovery = (int) $level;
1016 }
1017
1018 /**
1019 * Allows you to change which class SimplePie uses for caching.
1020 * Useful when you are overloading or extending SimplePie's default classes.
1021 *
1022 * @access public
1023 * @param string $class Name of custom class.
1024 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1025 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1026 */
1027 function set_cache_class($class = 'SimplePie_Cache')
1028 {
1029 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
1030 {
1031 $this->cache_class = $class;
1032 return true;
1033 }
1034 return false;
1035 }
1036
1037 /**
1038 * Allows you to change which class SimplePie uses for auto-discovery.
1039 * Useful when you are overloading or extending SimplePie's default classes.
1040 *
1041 * @access public
1042 * @param string $class Name of custom class.
1043 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1044 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1045 */
1046 function set_locator_class($class = 'SimplePie_Locator')
1047 {
1048 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
1049 {
1050 $this->locator_class = $class;
1051 return true;
1052 }
1053 return false;
1054 }
1055
1056 /**
1057 * Allows you to change which class SimplePie uses for XML parsing.
1058 * Useful when you are overloading or extending SimplePie's default classes.
1059 *
1060 * @access public
1061 * @param string $class Name of custom class.
1062 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1063 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1064 */
1065 function set_parser_class($class = 'SimplePie_Parser')
1066 {
1067 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
1068 {
1069 $this->parser_class = $class;
1070 return true;
1071 }
1072 return false;
1073 }
1074
1075 /**
1076 * Allows you to change which class SimplePie uses for remote file fetching.
1077 * Useful when you are overloading or extending SimplePie's default classes.
1078 *
1079 * @access public
1080 * @param string $class Name of custom class.
1081 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1082 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1083 */
1084 function set_file_class($class = 'SimplePie_File')
1085 {
1086 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
1087 {
1088 $this->file_class = $class;
1089 return true;
1090 }
1091 return false;
1092 }
1093
1094 /**
1095 * Allows you to change which class SimplePie uses for data sanitization.
1096 * Useful when you are overloading or extending SimplePie's default classes.
1097 *
1098 * @access public
1099 * @param string $class Name of custom class.
1100 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1101 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1102 */
1103 function set_sanitize_class($class = 'SimplePie_Sanitize')
1104 {
1105 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
1106 {
1107 $this->sanitize =& new $class;
1108 return true;
1109 }
1110 return false;
1111 }
1112
1113 /**
1114 * Allows you to change which class SimplePie uses for handling feed items.
1115 * Useful when you are overloading or extending SimplePie's default classes.
1116 *
1117 * @access public
1118 * @param string $class Name of custom class.
1119 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1120 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1121 */
1122 function set_item_class($class = 'SimplePie_Item')
1123 {
1124 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
1125 {
1126 $this->item_class = $class;
1127 return true;
1128 }
1129 return false;
1130 }
1131
1132 /**
1133 * Allows you to change which class SimplePie uses for handling author data.
1134 * Useful when you are overloading or extending SimplePie's default classes.
1135 *
1136 * @access public
1137 * @param string $class Name of custom class.
1138 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1139 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1140 */
1141 function set_author_class($class = 'SimplePie_Author')
1142 {
1143 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
1144 {
1145 $this->author_class = $class;
1146 return true;
1147 }
1148 return false;
1149 }
1150
1151 /**
1152 * Allows you to change which class SimplePie uses for handling category data.
1153 * Useful when you are overloading or extending SimplePie's default classes.
1154 *
1155 * @access public
1156 * @param string $class Name of custom class.
1157 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1158 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1159 */
1160 function set_category_class($class = 'SimplePie_Category')
1161 {
1162 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
1163 {
1164 $this->category_class = $class;
1165 return true;
1166 }
1167 return false;
1168 }
1169
1170 /**
1171 * Allows you to change which class SimplePie uses for feed enclosures.
1172 * Useful when you are overloading or extending SimplePie's default classes.
1173 *
1174 * @access public
1175 * @param string $class Name of custom class.
1176 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1177 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1178 */
1179 function set_enclosure_class($class = 'SimplePie_Enclosure')
1180 {
1181 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
1182 {
1183 $this->enclosure_class = $class;
1184 return true;
1185 }
1186 return false;
1187 }
1188
1189 /**
1190 * Allows you to change which class SimplePie uses for <media:text> captions
1191 * Useful when you are overloading or extending SimplePie's default classes.
1192 *
1193 * @access public
1194 * @param string $class Name of custom class.
1195 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1196 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1197 */
1198 function set_caption_class($class = 'SimplePie_Caption')
1199 {
1200 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
1201 {
1202 $this->caption_class = $class;
1203 return true;
1204 }
1205 return false;
1206 }
1207
1208 /**
1209 * Allows you to change which class SimplePie uses for <media:copyright>
1210 * Useful when you are overloading or extending SimplePie's default classes.
1211 *
1212 * @access public
1213 * @param string $class Name of custom class.
1214 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1215 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1216 */
1217 function set_copyright_class($class = 'SimplePie_Copyright')
1218 {
1219 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
1220 {
1221 $this->copyright_class = $class;
1222 return true;
1223 }
1224 return false;
1225 }
1226
1227 /**
1228 * Allows you to change which class SimplePie uses for <media:credit>
1229 * Useful when you are overloading or extending SimplePie's default classes.
1230 *
1231 * @access public
1232 * @param string $class Name of custom class.
1233 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1234 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1235 */
1236 function set_credit_class($class = 'SimplePie_Credit')
1237 {
1238 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
1239 {
1240 $this->credit_class = $class;
1241 return true;
1242 }
1243 return false;
1244 }
1245
1246 /**
1247 * Allows you to change which class SimplePie uses for <media:rating>
1248 * Useful when you are overloading or extending SimplePie's default classes.
1249 *
1250 * @access public
1251 * @param string $class Name of custom class.
1252 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1253 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1254 */
1255 function set_rating_class($class = 'SimplePie_Rating')
1256 {
1257 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
1258 {
1259 $this->rating_class = $class;
1260 return true;
1261 }
1262 return false;
1263 }
1264
1265 /**
1266 * Allows you to change which class SimplePie uses for <media:restriction>
1267 * Useful when you are overloading or extending SimplePie's default classes.
1268 *
1269 * @access public
1270 * @param string $class Name of custom class.
1271 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1272 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1273 */
1274 function set_restriction_class($class = 'SimplePie_Restriction')
1275 {
1276 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
1277 {
1278 $this->restriction_class = $class;
1279 return true;
1280 }
1281 return false;
1282 }
1283
1284 /**
1285 * Allows you to change which class SimplePie uses for content-type sniffing.
1286 * Useful when you are overloading or extending SimplePie's default classes.
1287 *
1288 * @access public
1289 * @param string $class Name of custom class.
1290 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1291 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1292 */
1293 function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1294 {
1295 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
1296 {
1297 $this->content_type_sniffer_class = $class;
1298 return true;
1299 }
1300 return false;
1301 }
1302
1303 /**
1304 * Allows you to change which class SimplePie uses item sources.
1305 * Useful when you are overloading or extending SimplePie's default classes.
1306 *
1307 * @access public
1308 * @param string $class Name of custom class.
1309 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1310 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1311 */
1312 function set_source_class($class = 'SimplePie_Source')
1313 {
1314 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
1315 {
1316 $this->source_class = $class;
1317 return true;
1318 }
1319 return false;
1320 }
1321
1322 /**
1323 * Allows you to override the default user agent string.
1324 *
1325 * @access public
1326 * @param string $ua New user agent string.
1327 */
1328 function set_useragent($ua = SIMPLEPIE_USERAGENT)
1329 {
1330 $this->useragent = (string) $ua;
1331 }
1332
1333 /**
1334 * Set callback function to create cache filename with
1335 *
1336 * @access public
1337 * @param mixed $function Callback function
1338 */
1339 function set_cache_name_function($function = 'md5')
1340 {
1341 if (is_callable($function))
1342 {
1343 $this->cache_name_function = $function;
1344 }
1345 }
1346
1347 /**
1348 * Set javascript query string parameter
1349 *
1350 * @access public
1351 * @param mixed $get Javascript query string parameter
1352 */
1353 function set_javascript($get = 'js')
1354 {
1355 if ($get)
1356 {
1357 $this->javascript = (string) $get;
1358 }
1359 else
1360 {
1361 $this->javascript = false;
1362 }
1363 }
1364
1365 /**
1366 * Set options to make SP as fast as possible. Forgoes a
1367 * substantial amount of data sanitization in favor of speed.
1368 *
1369 * @access public
1370 * @param bool $set Whether to set them or not
1371 */
1372 function set_stupidly_fast($set = false)
1373 {
1374 if ($set)
1375 {
1376 $this->enable_order_by_date(false);
1377 $this->remove_div(false);
1378 $this->strip_comments(false);
1379 $this->strip_htmltags(false);
1380 $this->strip_attributes(false);
1381 $this->set_image_handler(false);
1382 }
1383 }
1384
1385 /**
1386 * Set maximum number of feeds to check with autodiscovery
1387 *
1388 * @access public
1389 * @param int $max Maximum number of feeds to check
1390 */
1391 function set_max_checked_feeds($max = 10)
1392 {
1393 $this->max_checked_feeds = (int) $max;
1394 }
1395
1396 function remove_div($enable = true)
1397 {
1398 $this->sanitize->remove_div($enable);
1399 }
1400
1401 function strip_htmltags($tags = '', $encode = null)
1402 {
1403 if ($tags === '')
1404 {
1405 $tags = $this->strip_htmltags;
1406 }
1407 $this->sanitize->strip_htmltags($tags);
1408 if ($encode !== null)
1409 {
1410 $this->sanitize->encode_instead_of_strip($tags);
1411 }
1412 }
1413
1414 function encode_instead_of_strip($enable = true)
1415 {
1416 $this->sanitize->encode_instead_of_strip($enable);
1417 }
1418
1419 function strip_attributes($attribs = '')
1420 {
1421 if ($attribs === '')
1422 {
1423 $attribs = $this->strip_attributes;
1424 }
1425 $this->sanitize->strip_attributes($attribs);
1426 }
1427
1428 function set_output_encoding($encoding = 'UTF-8')
1429 {
1430 $this->sanitize->set_output_encoding($encoding);
1431 }
1432
1433 function strip_comments($strip = false)
1434 {
1435 $this->sanitize->strip_comments($strip);
1436 }
1437
1438 /**
1439 * Set element/attribute key/value pairs of HTML attributes
1440 * containing URLs that need to be resolved relative to the feed
1441 *
1442 * @access public
1443 * @since 1.0
1444 * @param array $element_attribute Element/attribute key/value pairs
1445 */
1446 function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
1447 {
1448 $this->sanitize->set_url_replacements($element_attribute);
1449 }
1450
1451 /**
1452 * Set the handler to enable the display of cached favicons.
1453 *
1454 * @access public
1455 * @param str $page Web-accessible path to the handler_favicon.php file.
1456 * @param str $qs The query string that the value should be passed to.
1457 */
1458 function set_favicon_handler($page = false, $qs = 'i')
1459 {
1460 if ($page !== false)
1461 {
1462 $this->favicon_handler = $page . '?' . $qs . '=';
1463 }
1464 else
1465 {
1466 $this->favicon_handler = '';
1467 }
1468 }
1469
1470 /**
1471 * Set the handler to enable the display of cached images.
1472 *
1473 * @access public
1474 * @param str $page Web-accessible path to the handler_image.php file.
1475 * @param str $qs The query string that the value should be passed to.
1476 */
1477 function set_image_handler($page = false, $qs = 'i')
1478 {
1479 if ($page !== false)
1480 {
1481 $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1482 }
1483 else
1484 {
1485 $this->image_handler = '';
1486 }
1487 }
1488
1489 /**
1490 * Set the limit for items returned per-feed with multifeeds.
1491 *
1492 * @access public
1493 * @param integer $limit The maximum number of items to return.
1494 */
1495 function set_item_limit($limit = 0)
1496 {
1497 $this->item_limit = (int) $limit;
1498 }
1499
1500 function init()
1501 {
1502 // Check absolute bare minimum requirements.
1503 if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
1504 {
1505 return false;
1506 }
1507 // Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader.
1508 elseif (!extension_loaded('xmlreader'))
1509 {
1510 static $xml_is_sane = null;
1511 if ($xml_is_sane === null)
1512 {
1513 $parser_check = xml_parser_create();
1514 xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
1515 xml_parser_free($parser_check);
1516 $xml_is_sane = isset($values[0]['value']);
1517 }
1518 if (!$xml_is_sane)
1519 {
1520 return false;
1521 }
1522 }
1523
1524 if (isset($_GET[$this->javascript]))
1525 {
1526 SimplePie_Misc::output_javascript();
1527 exit;
1528 }
1529
1530 // Pass whatever was set with config options over to the sanitizer.
1531 $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
1532 $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
1533
1534 if ($this->feed_url !== null || $this->raw_data !== null)
1535 {
1536 $this->data = array();
1537 $this->multifeed_objects = array();
1538 $cache = false;
1539
1540 if ($this->feed_url !== null)
1541 {
1542 $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
1543 // Decide whether to enable caching
1544 if ($this->cache && $parsed_feed_url['scheme'] !== '')
1545 {
1546 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
1547 }
1548 // If it's enabled and we don't want an XML dump, use the cache
1549 if ($cache && !$this->xml_dump)
1550 {
1551 // Load the Cache
1552 $this->data = $cache->load();
1553 if (!empty($this->data))
1554 {
1555 // If the cache is for an outdated build of SimplePie
1556 if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
1557 {
1558 $cache->unlink();
1559 $this->data = array();
1560 }
1561 // If we've hit a collision just rerun it with caching disabled
1562 elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
1563 {
1564 $cache = false;
1565 $this->data = array();
1566 }
1567 // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1568 elseif (isset($this->data['feed_url']))
1569 {
1570 // If the autodiscovery cache is still valid use it.
1571 if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1572 {
1573 // Do not need to do feed autodiscovery yet.
1574 if ($this->data['feed_url'] === $this->data['url'])
1575 {
1576 $cache->unlink();
1577 $this->data = array();
1578 }
1579 else
1580 {
1581 $this->set_feed_url($this->data['feed_url']);
1582 return $this->init();
1583 }
1584 }
1585 }
1586 // Check if the cache has been updated
1587 elseif ($cache->mtime() + $this->cache_duration < time())
1588 {
1589 // If we have last-modified and/or etag set
1590 if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1591 {
1592 $headers = array();
1593 if (isset($this->data['headers']['last-modified']))
1594 {
1595 $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1596 }
1597 if (isset($this->data['headers']['etag']))
1598 {
1599 $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
1600 }
1601 $file =& new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
1602 if ($file->success)
1603 {
1604 if ($file->status_code === 304)
1605 {
1606 $cache->touch();
1607 return true;
1608 }
1609 else
1610 {
1611 $headers = $file->headers;
1612 }
1613 }
1614 else
1615 {
1616 unset($file);
1617 }
1618 }
1619 }
1620 // If the cache is still valid, just return true
1621 else
1622 {
1623 return true;
1624 }
1625 }
1626 // If the cache is empty, delete it
1627 else
1628 {
1629 $cache->unlink();
1630 $this->data = array();
1631 }
1632 }
1633 // If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it.
1634 if (!isset($file))
1635 {
1636 if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
1637 {
1638 $file =& $this->file;
1639 }
1640 else
1641 {
1642 $file =& new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
1643 }
1644 }
1645 // If the file connection has an error, set SimplePie::error to that and quit
1646 if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
1647 {
1648 $this->error = $file->error;
1649 if (!empty($this->data))
1650 {
1651 return true;
1652 }
1653 else
1654 {
1655 return false;
1656 }
1657 }
1658
1659 if (!$this->force_feed)
1660 {
1661 // Check if the supplied URL is a feed, if it isn't, look for it.
1662 $locate =& new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
1663 if (!$locate->is_feed($file))
1664 {
1665 // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1666 unset($file);
1667 if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
1668 {
1669 if ($cache)
1670 {
1671 $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1672 if (!$cache->save($this))
1673 {
1674 trigger_error("$this->cache_location is not writeable", E_USER_WARNING);
1675 }
1676 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
1677 }
1678 $this->feed_url = $file->url;
1679 }
1680 else
1681 {
1682 $this->error = "A feed could not be found at $this->feed_url";
1683 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1684 return false;
1685 }
1686 }
1687 $locate = null;
1688 }
1689
1690 $headers = $file->headers;
1691 $data = $file->body;
1692 $sniffer =& new $this->content_type_sniffer_class($file);
1693 $sniffed = $sniffer->get_type();
1694 }
1695 else
1696 {
1697 $data = $this->raw_data;
1698 }
1699
1700 // Set up array of possible encodings
1701 $encodings = array();
1702
1703 // First check to see if input has been overridden.
1704 if ($this->input_encoding !== false)
1705 {
1706 $encodings[] = $this->input_encoding;
1707 }
1708
1709 $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1710 $text_types = array('text/xml', 'text/xml-external-parsed-entity');
1711
1712 // RFC 3023 (only applies to sniffed content)
1713 if (isset($sniffed))
1714 {
1715 if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1716 {
1717 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1718 {
1719 $encodings[] = strtoupper($charset[1]);
1720 }
1721 $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1722 $encodings[] = 'UTF-8';
1723 }
1724 elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1725 {
1726 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1727 {
1728 $encodings[] = $charset[1];
1729 }
1730 $encodings[] = 'US-ASCII';
1731 }
1732 // Text MIME-type default
1733 elseif (substr($sniffed, 0, 5) === 'text/')
1734 {
1735 $encodings[] = 'US-ASCII';
1736 }
1737 }
1738
1739 // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1740 $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1741 $encodings[] = 'UTF-8';
1742 $encodings[] = 'ISO-8859-1';
1743
1744 // There's no point in trying an encoding twice
1745 $encodings = array_unique($encodings);
1746
1747 // If we want the XML, just output that with the most likely encoding and quit
1748 if ($this->xml_dump)
1749 {
1750 header('Content-type: text/xml; charset=' . $encodings[0]);
1751 echo $data;
1752 exit;
1753 }
1754
1755 // Loop through each possible encoding, till we return something, or run out of possibilities
1756 foreach ($encodings as $encoding)
1757 {
1758 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1759 if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
1760 {
1761 // Create new parser
1762 $parser =& new $this->parser_class();
1763
1764 // If it's parsed fine
1765 if ($parser->parse($utf8_data, 'UTF-8'))
1766 {
1767 $this->data = $parser->get_data();
1768 if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
1769 {
1770 if (isset($headers))
1771 {
1772 $this->data['headers'] = $headers;
1773 }
1774 $this->data['build'] = SIMPLEPIE_BUILD;
1775
1776 // Cache the file if caching is enabled
1777 if ($cache && !$cache->save($this))
1778 {
1779 trigger_error("$cache->name is not writeable", E_USER_WARNING);
1780 }
1781 return true;
1782 }
1783 else
1784 {
1785 $this->error = "A feed could not be found at $this->feed_url";
1786 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1787 return false;
1788 }
1789 }
1790 }
1791 }
1792 if(isset($parser))
1793 {
1794 // We have an error, just set SimplePie_Misc::error to it and quit
1795 $this->error = sprintf('XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
1796 }
1797 else
1798 {
1799 $this->error = 'The data could not be converted to UTF-8';
1800 }
1801 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1802 return false;
1803 }
1804 elseif (!empty($this->multifeed_url))
1805 {
1806 $i = 0;
1807 $success = 0;
1808 $this->multifeed_objects = array();
1809 foreach ($this->multifeed_url as $url)
1810 {
1811 if (SIMPLEPIE_PHP5)
1812 {
1813 // This keyword needs to defy coding standards for PHP4 compatibility
1814 $this->multifeed_objects[$i] = clone($this);
1815 }
1816 else
1817 {
1818 $this->multifeed_objects[$i] = $this;
1819 }
1820 $this->multifeed_objects[$i]->set_feed_url($url);
1821 $success |= $this->multifeed_objects[$i]->init();
1822 $i++;
1823 }
1824 return (bool) $success;
1825 }
1826 else
1827 {
1828 return false;
1829 }
1830 }
1831
1832 /**
1833 * Return the error message for the occured error
1834 *
1835 * @access public
1836 * @return string Error message
1837 */
1838 function error()
1839 {
1840 return $this->error;
1841 }
1842
1843 function get_encoding()
1844 {
1845 return $this->sanitize->output_encoding;
1846 }
1847
1848 function handle_content_type($mime = 'text/html')
1849 {
1850 if (!headers_sent())
1851 {
1852 $header = "Content-type: $mime;";
1853 if ($this->get_encoding())
1854 {
1855 $header .= ' charset=' . $this->get_encoding();
1856 }
1857 else
1858 {
1859 $header .= ' charset=UTF-8';
1860 }
1861 header($header);
1862 }
1863 }
1864
1865 function get_type()
1866 {
1867 if (!isset($this->data['type']))
1868 {
1869 $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1870 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1871 {
1872 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1873 }
1874 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1875 {
1876 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1877 }
1878 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1879 {
1880 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1881 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1882 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1883 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1884 {
1885 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1886 }
1887 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1888 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1889 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1890 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1891 {
1892 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1893 }
1894 }
1895 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
1896 {
1897 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1898 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1899 {
1900 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1901 {
1902 case '0.91':
1903 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1904 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1905 {
1906 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1907 {
1908 case '0':
1909 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1910 break;
1911
1912 case '24':
1913 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1914 break;
1915 }
1916 }
1917 break;
1918
1919 case '0.92':
1920 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1921 break;
1922
1923 case '0.93':
1924 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1925 break;
1926
1927 case '0.94':
1928 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1929 break;
1930
1931 case '2.0':
1932 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1933 break;
1934 }
1935 }
1936 }
1937 else
1938 {
1939 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1940 }
1941 }
1942 return $this->data['type'];
1943 }
1944
1945 /**
1946 * Returns the URL for the favicon of the feed's website.
1947 *
1948 * @todo Cache atom:icon
1949 * @access public
1950 * @since 1.0
1951 */
1952 function get_favicon()
1953 {
1954 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
1955 {
1956 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
1957 }
1958 elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
1959 {
1960 $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
1961
1962 if ($this->cache && $this->favicon_handler)
1963 {
1964 $favicon_filename = call_user_func($this->cache_name_function, $favicon);
1965 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
1966
1967 if ($cache->load())
1968 {
1969 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1970 }
1971 else
1972 {
1973 $file =& new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
1974
1975 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)) && strlen($file->body) > 0)
1976 {
1977 $sniffer =& new $this->content_type_sniffer_class($file);
1978 if (substr($sniffer->get_type(), 0, 6) === 'image/')
1979 {
1980 if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
1981 {
1982 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1983 }
1984 else
1985 {
1986 trigger_error("$cache->name is not writeable", E_USER_WARNING);
1987 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
1988 }
1989 }
1990 // not an image
1991 else
1992 {
1993 return false;
1994 }
1995 }
1996 }
1997 }
1998 else
1999 {
2000 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
2001 }
2002 }
2003 return false;
2004 }
2005
2006 /**
2007 * @todo If we have a perm redirect we should return the new URL
2008 * @todo When we make the above change, let's support <itunes:new-feed-url> as well
2009 * @todo Also, |atom:link|@rel=self
2010 */
2011 function subscribe_url()
2012 {
2013 if ($this->feed_url !== null)
2014 {
2015 return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
2016 }
2017 else
2018 {
2019 return null;
2020 }
2021 }
2022
2023 function subscribe_feed()
2024 {
2025 if ($this->feed_url !== null)
2026 {
2027 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2028 }
2029 else
2030 {
2031 return null;
2032 }
2033 }
2034
2035 function subscribe_outlook()
2036 {
2037 if ($this->feed_url !== null)
2038 {
2039 return $this->sanitize('outlook' . SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2040 }
2041 else
2042 {
2043 return null;
2044 }
2045 }
2046
2047 function subscribe_podcast()
2048 {
2049 if ($this->feed_url !== null)
2050 {
2051 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
2052 }
2053 else
2054 {
2055 return null;
2056 }
2057 }
2058
2059 function subscribe_itunes()
2060 {
2061 if ($this->feed_url !== null)
2062 {
2063 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
2064 }
2065 else
2066 {
2067 return null;
2068 }
2069 }
2070
2071 /**
2072 * Creates the subscribe_* methods' return data
2073 *
2074 * @access private
2075 * @param string $feed_url String to prefix to the feed URL
2076 * @param string $site_url String to prefix to the site URL (and
2077 * suffix to the feed URL)
2078 * @return mixed URL if feed exists, false otherwise
2079 */
2080 function subscribe_service($feed_url, $site_url = null)
2081 {
2082 if ($this->subscribe_url())
2083 {
2084 $return = $feed_url . rawurlencode($this->feed_url);
2085 if ($site_url !== null && $this->get_link() !== null)
2086 {
2087 $return .= $site_url . rawurlencode($this->get_link());
2088 }
2089 return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
2090 }
2091 else
2092 {
2093 return null;
2094 }
2095 }
2096
2097 function subscribe_aol()
2098 {
2099 return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
2100 }
2101
2102 function subscribe_bloglines()
2103 {
2104 return $this->subscribe_service('http://www.bloglines.com/sub/');
2105 }
2106
2107 function subscribe_eskobo()
2108 {
2109 return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
2110 }
2111
2112 function subscribe_feedfeeds()
2113 {
2114 return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
2115 }
2116
2117 function subscribe_feedster()
2118 {
2119 return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
2120 }
2121
2122 function subscribe_google()
2123 {
2124 return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
2125 }
2126
2127 function subscribe_gritwire()
2128 {
2129 return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
2130 }
2131
2132 function subscribe_msn()
2133 {
2134 return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
2135 }
2136
2137 function subscribe_netvibes()
2138 {
2139 return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
2140 }
2141
2142 function subscribe_newsburst()
2143 {
2144 return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
2145 }
2146
2147 function subscribe_newsgator()
2148 {
2149 return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
2150 }
2151
2152 function subscribe_odeo()
2153 {
2154 return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
2155 }
2156
2157 function subscribe_podnova()
2158 {
2159 return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
2160 }
2161
2162 function subscribe_rojo()
2163 {
2164 return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
2165 }
2166
2167 function subscribe_yahoo()
2168 {
2169 return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
2170 }
2171
2172 function get_feed_tags($namespace, $tag)
2173 {
2174 $type = $this->get_type();
2175 if ($type & SIMPLEPIE_TYPE_ATOM_10)
2176 {
2177 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
2178 {
2179 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
2180 }
2181 }
2182 if ($type & SIMPLEPIE_TYPE_ATOM_03)
2183 {
2184 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
2185 {
2186 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
2187 }
2188 }
2189 if ($type & SIMPLEPIE_TYPE_RSS_RDF)
2190 {
2191 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
2192 {
2193 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
2194 }
2195 }
2196 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2197 {
2198 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
2199 {
2200 return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
2201 }
2202 }
2203 return null;
2204 }
2205
2206 function get_channel_tags($namespace, $tag)
2207 {
2208 $type = $this->get_type();
2209 if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
2210 {
2211 if ($return = $this->get_feed_tags($namespace, $tag))
2212 {
2213 return $return;
2214 }
2215 }
2216 if ($type & SIMPLEPIE_TYPE_RSS_10)
2217 {
2218 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
2219 {
2220 if (isset($channel[0]['child'][$namespace][$tag]))
2221 {
2222 return $channel[0]['child'][$namespace][$tag];
2223 }
2224 }
2225 }
2226 if ($type & SIMPLEPIE_TYPE_RSS_090)
2227 {
2228 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
2229 {
2230 if (isset($channel[0]['child'][$namespace][$tag]))
2231 {
2232 return $channel[0]['child'][$namespace][$tag];
2233 }
2234 }
2235 }
2236 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2237 {
2238 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
2239 {
2240 if (isset($channel[0]['child'][$namespace][$tag]))
2241 {
2242 return $channel[0]['child'][$namespace][$tag];
2243 }
2244 }
2245 }
2246 return null;
2247 }
2248
2249 function get_image_tags($namespace, $tag)
2250 {
2251 $type = $this->get_type();
2252 if ($type & SIMPLEPIE_TYPE_RSS_10)
2253 {
2254 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
2255 {
2256 if (isset($image[0]['child'][$namespace][$tag]))
2257 {
2258 return $image[0]['child'][$namespace][$tag];
2259 }
2260 }
2261 }
2262 if ($type & SIMPLEPIE_TYPE_RSS_090)
2263 {
2264 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2265 {
2266 if (isset($image[0]['child'][$namespace][$tag]))
2267 {
2268 return $image[0]['child'][$namespace][$tag];
2269 }
2270 }
2271 }
2272 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2273 {
2274 if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
2275 {
2276 if (isset($image[0]['child'][$namespace][$tag]))
2277 {
2278 return $image[0]['child'][$namespace][$tag];
2279 }
2280 }
2281 }
2282 return null;
2283 }
2284
2285 function get_base($element = array())
2286 {
2287 if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2288 {
2289 return $element['xml_base'];
2290 }
2291 elseif ($this->get_link() !== null)
2292 {
2293 return $this->get_link();
2294 }
2295 else
2296 {
2297 return $this->subscribe_url();
2298 }
2299 }
2300
2301 function sanitize($data, $type, $base = '')
2302 {
2303 return $this->sanitize->sanitize($data, $type, $base);
2304 }
2305
2306 function get_title()
2307 {
2308 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2309 {
2310 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2311 }
2312 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2313 {
2314 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2315 }
2316 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2317 {
2318 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2319 }
2320 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2321 {
2322 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2323 }
2324 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2325 {
2326 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2327 }
2328 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2329 {
2330 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2331 }
2332 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2333 {
2334 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2335 }
2336 else
2337 {
2338 return null;
2339 }
2340 }
2341
2342 function get_category($key = 0)
2343 {
2344 $categories = $this->get_categories();
2345 if (isset($categories[$key]))
2346 {
2347 return $categories[$key];
2348 }
2349 else
2350 {
2351 return null;
2352 }
2353 }
2354
2355 function get_categories()
2356 {
2357 $categories = array();
2358
2359 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2360 {
2361 $term = null;
2362 $scheme = null;
2363 $label = null;
2364 if (isset($category['attribs']['']['term']))
2365 {
2366 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2367 }
2368 if (isset($category['attribs']['']['scheme']))
2369 {
2370 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2371 }
2372 if (isset($category['attribs']['']['label']))
2373 {
2374 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2375 }
2376 $categories[] =& new $this->category_class($term, $scheme, $label);
2377 }
2378 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
2379 {
2380 // This is really the label, but keep this as the term also for BC.
2381 // Label will also work on retrieving because that falls back to term.
2382 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2383 if (isset($category['attribs']['']['domain']))
2384 {
2385 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
2386 }
2387 else
2388 {
2389 $scheme = null;
2390 }
2391 $categories[] =& new $this->category_class($term, $scheme, null);
2392 }
2393 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2394 {
2395 $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2396 }
2397 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2398 {
2399 $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2400 }
2401
2402 if (!empty($categories))
2403 {
2404 return SimplePie_Misc::array_unique($categories);
2405 }
2406 else
2407 {
2408 return null;
2409 }
2410 }
2411
2412 function get_author($key = 0)
2413 {
2414 $authors = $this->get_authors();
2415 if (isset($authors[$key]))
2416 {
2417 return $authors[$key];
2418 }
2419 else
2420 {
2421 return null;
2422 }
2423 }
2424
2425 function get_authors()
2426 {
2427 $authors = array();
2428 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2429 {
2430 $name = null;
2431 $uri = null;
2432 $email = null;
2433 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2434 {
2435 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2436 }
2437 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2438 {
2439 $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
2440 }
2441 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2442 {
2443 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2444 }
2445 if ($name !== null || $email !== null || $uri !== null)
2446 {
2447 $authors[] =& new $this->author_class($name, $uri, $email);
2448 }
2449 }
2450 if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2451 {
2452 $name = null;
2453 $url = null;
2454 $email = null;
2455 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2456 {
2457 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2458 }
2459 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2460 {
2461 $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
2462 }
2463 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2464 {
2465 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2466 }
2467 if ($name !== null || $email !== null || $url !== null)
2468 {
2469 $authors[] =& new $this->author_class($name, $url, $email);
2470 }
2471 }
2472 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2473 {
2474 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2475 }
2476 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2477 {
2478 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2479 }
2480 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2481 {
2482 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2483 }
2484
2485 if (!empty($authors))
2486 {
2487 return SimplePie_Misc::array_unique($authors);
2488 }
2489 else
2490 {
2491 return null;
2492 }
2493 }
2494
2495 function get_contributor($key = 0)
2496 {
2497 $contributors = $this->get_contributors();
2498 if (isset($contributors[$key]))
2499 {
2500 return $contributors[$key];
2501 }
2502 else
2503 {
2504 return null;
2505 }
2506 }
2507
2508 function get_contributors()
2509 {
2510 $contributors = array();
2511 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2512 {
2513 $name = null;
2514 $uri = null;
2515 $email = null;
2516 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2517 {
2518 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2519 }
2520 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2521 {
2522 $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
2523 }
2524 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2525 {
2526 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2527 }
2528 if ($name !== null || $email !== null || $uri !== null)
2529 {
2530 $contributors[] =& new $this->author_class($name, $uri, $email);
2531 }
2532 }
2533 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2534 {
2535 $name = null;
2536 $url = null;
2537 $email = null;
2538 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2539 {
2540 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2541 }
2542 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2543 {
2544 $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
2545 }
2546 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2547 {
2548 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2549 }
2550 if ($name !== null || $email !== null || $url !== null)
2551 {
2552 $contributors[] =& new $this->author_class($name, $url, $email);
2553 }
2554 }
2555
2556 if (!empty($contributors))
2557 {
2558 return SimplePie_Misc::array_unique($contributors);
2559 }
2560 else
2561 {
2562 return null;
2563 }
2564 }
2565
2566 function get_link($key = 0, $rel = 'alternate')
2567 {
2568 $links = $this->get_links($rel);
2569 if (isset($links[$key]))
2570 {
2571 return $links[$key];
2572 }
2573 else
2574 {
2575 return null;
2576 }
2577 }
2578
2579 /**
2580 * Added for parity between the parent-level and the item/entry-level.
2581 */
2582 function get_permalink()
2583 {
2584 return $this->get_link(0);
2585 }
2586
2587 function get_links($rel = 'alternate')
2588 {
2589 if (!isset($this->data['links']))
2590 {
2591 $this->data['links'] = array();
2592 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2593 {
2594 foreach ($links as $link)
2595 {
2596 if (isset($link['attribs']['']['href']))
2597 {
2598 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2599 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2600 }
2601 }
2602 }
2603 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2604 {
2605 foreach ($links as $link)
2606 {
2607 if (isset($link['attribs']['']['href']))
2608 {
2609 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2610 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2611
2612 }
2613 }
2614 }
2615 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2616 {
2617 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2618 }
2619 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2620 {
2621 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2622 }
2623 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2624 {
2625 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2626 }
2627
2628 $keys = array_keys($this->data['links']);
2629 foreach ($keys as $key)
2630 {
2631 if (SimplePie_Misc::is_isegment_nz_nc($key))
2632 {
2633 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2634 {
2635 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2636 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2637 }
2638 else
2639 {
2640 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2641 }
2642 }
2643 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2644 {
2645 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2646 }
2647 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2648 }
2649 }
2650
2651 if (isset($this->data['links'][$rel]))
2652 {
2653 return $this->data['links'][$rel];
2654 }
2655 else
2656 {
2657 return null;
2658 }
2659 }
2660
2661 function get_all_discovered_feeds()
2662 {
2663 return $this->all_discovered_feeds;
2664 }
2665
2666 function get_description()
2667 {
2668 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2669 {
2670 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2671 }
2672 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2673 {
2674 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2675 }
2676 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2677 {
2678 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2679 }
2680 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2681 {
2682 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2683 }
2684 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2685 {
2686 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2687 }
2688 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2689 {
2690 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2691 }
2692 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2693 {
2694 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2695 }
2696 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2697 {
2698 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2699 }
2700 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2701 {
2702 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2703 }
2704 else
2705 {
2706 return null;
2707 }
2708 }
2709
2710 function get_copyright()
2711 {
2712 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2713 {
2714 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2715 }
2716 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2717 {
2718 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2719 }
2720 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2721 {
2722 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2723 }
2724 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2725 {
2726 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2727 }
2728 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2729 {
2730 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2731 }
2732 else
2733 {
2734 return null;
2735 }
2736 }
2737
2738 function get_language()
2739 {
2740 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2741 {
2742 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2743 }
2744 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2745 {
2746 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2747 }
2748 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2749 {
2750 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2751 }
2752 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2753 {
2754 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2755 }
2756 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2757 {
2758 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2759 }
2760 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2761 {
2762 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2763 }
2764 elseif (isset($this->data['headers']['content-language']))
2765 {
2766 return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2767 }
2768 else
2769 {
2770 return null;
2771 }
2772 }
2773
2774 function get_latitude()
2775 {
2776 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2777 {
2778 return (float) $return[0]['data'];
2779 }
2780 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
2781 {
2782 return (float) $match[1];
2783 }
2784 else
2785 {
2786 return null;
2787 }
2788 }
2789
2790 function get_longitude()
2791 {
2792 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2793 {
2794 return (float) $return[0]['data'];
2795 }
2796 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2797 {
2798 return (float) $return[0]['data'];
2799 }
2800 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
2801 {
2802 return (float) $match[2];
2803 }
2804 else
2805 {
2806 return null;
2807 }
2808 }
2809
2810 function get_image_title()
2811 {
2812 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2813 {
2814 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2815 }
2816 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2817 {
2818 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2819 }
2820 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2821 {
2822 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2823 }
2824 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2825 {
2826 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2827 }
2828 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2829 {
2830 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2831 }
2832 else
2833 {
2834 return null;
2835 }
2836 }
2837
2838 function get_image_url()
2839 {
2840 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2841 {
2842 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2843 }
2844 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2845 {
2846 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2847 }
2848 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2849 {
2850 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2851 }
2852 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2853 {
2854 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2855 }
2856 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2857 {
2858 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2859 }
2860 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2861 {
2862 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2863 }
2864 else
2865 {
2866 return null;
2867 }
2868 }
2869
2870 function get_image_link()
2871 {
2872 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2873 {
2874 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2875 }
2876 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2877 {
2878 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2879 }
2880 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2881 {
2882 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2883 }
2884 else
2885 {
2886 return null;
2887 }
2888 }
2889
2890 function get_image_width()
2891 {
2892 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2893 {
2894 return round($return[0]['data']);
2895 }
2896 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2897 {
2898 return 88.0;
2899 }
2900 else
2901 {
2902 return null;
2903 }
2904 }
2905
2906 function get_image_height()
2907 {
2908 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2909 {
2910 return round($return[0]['data']);
2911 }
2912 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2913 {
2914 return 31.0;
2915 }
2916 else
2917 {
2918 return null;
2919 }
2920 }
2921
2922 function get_item_quantity($max = 0)
2923 {
2924 $max = (int) $max;
2925 $qty = count($this->get_items());
2926 if ($max === 0)
2927 {
2928 return $qty;
2929 }
2930 else
2931 {
2932 return ($qty > $max) ? $max : $qty;
2933 }
2934 }
2935
2936 function get_item($key = 0)
2937 {
2938 $items = $this->get_items();
2939 if (isset($items[$key]))
2940 {
2941 return $items[$key];
2942 }
2943 else
2944 {
2945 return null;
2946 }
2947 }
2948
2949 function get_items($start = 0, $end = 0)
2950 {
2951 if (!isset($this->data['items']))
2952 {
2953 if (!empty($this->multifeed_objects))
2954 {
2955 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2956 }
2957 else
2958 {
2959 $this->data['items'] = array();
2960 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2961 {
2962 $keys = array_keys($items);
2963 foreach ($keys as $key)
2964 {
2965 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2966 }
2967 }
2968 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2969 {
2970 $keys = array_keys($items);
2971 foreach ($keys as $key)
2972 {
2973 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2974 }
2975 }
2976 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
2977 {
2978 $keys = array_keys($items);
2979 foreach ($keys as $key)
2980 {
2981 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2982 }
2983 }
2984 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2985 {
2986 $keys = array_keys($items);
2987 foreach ($keys as $key)
2988 {
2989 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2990 }
2991 }
2992 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
2993 {
2994 $keys = array_keys($items);
2995 foreach ($keys as $key)
2996 {
2997 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2998 }
2999 }
3000 }
3001 }
3002
3003 if (!empty($this->data['items']))
3004 {
3005 // If we want to order it by date, check if all items have a date, and then sort it
3006 if ($this->order_by_date && empty($this->multifeed_objects))
3007 {
3008 if (!isset($this->data['ordered_items']))
3009 {
3010 $do_sort = true;
3011 foreach ($this->data['items'] as $item)
3012 {
3013 if (!$item->get_date('U'))
3014 {
3015 $do_sort = false;
3016 break;
3017 }
3018 }
3019 $item = null;
3020 $this->data['ordered_items'] = $this->data['items'];
3021 if ($do_sort)
3022 {
3023 usort($this->data['ordered_items'], array(&$this, 'sort_items'));
3024 }
3025 }
3026 $items = $this->data['ordered_items'];
3027 }
3028 else
3029 {
3030 $items = $this->data['items'];
3031 }
3032
3033 // Slice the data as desired
3034 if ($end === 0)
3035 {
3036 return array_slice($items, $start);
3037 }
3038 else
3039 {
3040 return array_slice($items, $start, $end);
3041 }
3042 }
3043 else
3044 {
3045 return array();
3046 }
3047 }
3048
3049 /**
3050 * @static
3051 */
3052 function sort_items($a, $b)
3053 {
3054 return $a->get_date('U') <= $b->get_date('U');
3055 }
3056
3057 /**
3058 * @static
3059 */
3060 function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3061 {
3062 if (is_array($urls) && sizeof($urls) > 0)
3063 {
3064 $items = array();
3065 foreach ($urls as $arg)
3066 {
3067 if (is_a($arg, 'SimplePie'))
3068 {
3069 $items = array_merge($items, $arg->get_items(0, $limit));
3070 }
3071 else
3072 {
3073 trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3074 }
3075 }
3076
3077 $do_sort = true;
3078 foreach ($items as $item)
3079 {
3080 if (!$item->get_date('U'))
3081 {
3082 $do_sort = false;
3083 break;
3084 }
3085 }
3086 $item = null;
3087 if ($do_sort)
3088 {
3089 usort($items, array('SimplePie', 'sort_items'));
3090 }
3091
3092 if ($end === 0)
3093 {
3094 return array_slice($items, $start);
3095 }
3096 else
3097 {
3098 return array_slice($items, $start, $end);
3099 }
3100 }
3101 else
3102 {
3103 trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3104 return array();
3105 }
3106 }
3107 }
3108
3109 class SimplePie_Item
3110 {
3111 var $feed;
3112 var $data = array();
3113
3114 function SimplePie_Item($feed, $data)
3115 {
3116 $this->feed = $feed;
3117 $this->data = $data;
3118 }
3119
3120 function __toString()
3121 {
3122 return md5(serialize($this->data));
3123 }
3124
3125 /**
3126 * Remove items that link back to this before destroying this object
3127 */
3128 function __destruct()
3129 {
3130 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
3131 {
3132 unset($this->feed);
3133 }
3134 }
3135
3136 function get_item_tags($namespace, $tag)
3137 {
3138 if (isset($this->data['child'][$namespace][$tag]))
3139 {
3140 return $this->data['child'][$namespace][$tag];
3141 }
3142 else
3143 {
3144 return null;
3145 }
3146 }
3147
3148 function get_base($element = array())
3149 {
3150 return $this->feed->get_base($element);
3151 }
3152
3153 function sanitize($data, $type, $base = '')
3154 {
3155 return $this->feed->sanitize($data, $type, $base);
3156 }
3157
3158 function get_feed()
3159 {
3160 return $this->feed;
3161 }
3162
3163 function get_id($hash = false)
3164 {
3165 if (!$hash)
3166 {
3167 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
3168 {
3169 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3170 }
3171 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
3172 {
3173 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3174 }
3175 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3176 {
3177 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3178 }
3179 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
3180 {
3181 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3182 }
3183 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
3184 {
3185 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3186 }
3187 elseif (($return = $this->get_permalink()) !== null)
3188 {
3189 return $return;
3190 }
3191 elseif (($return = $this->get_title()) !== null)
3192 {
3193 return $return;
3194 }
3195 }
3196 if ($this->get_permalink() !== null || $this->get_title() !== null)
3197 {
3198 return md5($this->get_permalink() . $this->get_title());
3199 }
3200 else
3201 {
3202 return md5(serialize($this->data));
3203 }
3204 }
3205
3206 function get_title()
3207 {
3208 if (!isset($this->data['title']))
3209 {
3210 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
3211 {
3212 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3213 }
3214 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
3215 {
3216 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3217 }
3218 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
3219 {
3220 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3221 }
3222 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
3223 {
3224 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3225 }
3226 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
3227 {
3228 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3229 }
3230 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
3231 {
3232 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3233 }
3234 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
3235 {
3236 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3237 }
3238 else
3239 {
3240 $this->data['title'] = null;
3241 }
3242 }
3243 return $this->data['title'];
3244 }
3245
3246 function get_description($description_only = false)
3247 {
3248 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
3249 {
3250 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3251 }
3252 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
3253 {
3254 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3255 }
3256 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
3257 {
3258 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3259 }
3260 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
3261 {
3262 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3263 }
3264 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3265 {
3266 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3267 }
3268 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3269 {
3270 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3271 }
3272 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3273 {
3274 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3275 }
3276 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3277 {
3278 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3279 }
3280 elseif (!$description_only)
3281 {
3282 return $this->get_content(true);
3283 }
3284 else
3285 {
3286 return null;
3287 }
3288 }
3289
3290 function get_content($content_only = false)
3291 {
3292 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3293 {
3294 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3295 }
3296 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3297 {
3298 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3299 }
3300 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3301 {
3302 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3303 }
3304 elseif (!$content_only)
3305 {
3306 return $this->get_description(true);
3307 }
3308 else
3309 {
3310 return null;
3311 }
3312 }
3313
3314 function get_category($key = 0)
3315 {
3316 $categories = $this->get_categories();
3317 if (isset($categories[$key]))
3318 {
3319 return $categories[$key];
3320 }
3321 else
3322 {
3323 return null;
3324 }
3325 }
3326
3327 function get_categories()
3328 {
3329 $categories = array();
3330
3331 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3332 {
3333 $term = null;
3334 $scheme = null;
3335 $label = null;
3336 if (isset($category['attribs']['']['term']))
3337 {
3338 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3339 }
3340 if (isset($category['attribs']['']['scheme']))
3341 {
3342 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3343 }
3344 if (isset($category['attribs']['']['label']))
3345 {
3346 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3347 }
3348 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
3349 }
3350 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
3351 {
3352 // This is really the label, but keep this as the term also for BC.
3353 // Label will also work on retrieving because that falls back to term.
3354 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3355 if (isset($category['attribs']['']['domain']))
3356 {
3357 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
3358 }
3359 else
3360 {
3361 $scheme = null;
3362 }
3363 $categories[] =& new $this->feed->category_class($term, $scheme, null);
3364 }
3365 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3366 {
3367 $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3368 }
3369 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3370 {
3371 $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3372 }
3373
3374 if (!empty($categories))
3375 {
3376 return SimplePie_Misc::array_unique($categories);
3377 }
3378 else
3379 {
3380 return null;
3381 }
3382 }
3383
3384 function get_author($key = 0)
3385 {
3386 $authors = $this->get_authors();
3387 if (isset($authors[$key]))
3388 {
3389 return $authors[$key];
3390 }
3391 else
3392 {
3393 return null;
3394 }
3395 }
3396
3397 function get_contributor($key = 0)
3398 {
3399 $contributors = $this->get_contributors();
3400 if (isset($contributors[$key]))
3401 {
3402 return $contributors[$key];
3403 }
3404 else
3405 {
3406 return null;
3407 }
3408 }
3409
3410 function get_contributors()
3411 {
3412 $contributors = array();
3413 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3414 {
3415 $name = null;
3416 $uri = null;
3417 $email = null;
3418 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3419 {
3420 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3421 }
3422 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3423 {
3424 $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
3425 }
3426 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3427 {
3428 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3429 }
3430 if ($name !== null || $email !== null || $uri !== null)
3431 {
3432 $contributors[] =& new $this->feed->author_class($name, $uri, $email);
3433 }
3434 }
3435 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3436 {
3437 $name = null;
3438 $url = null;
3439 $email = null;
3440 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3441 {
3442 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3443 }
3444 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3445 {
3446 $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
3447 }
3448 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3449 {
3450 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3451 }
3452 if ($name !== null || $email !== null || $url !== null)
3453 {
3454 $contributors[] =& new $this->feed->author_class($name, $url, $email);
3455 }
3456 }
3457
3458 if (!empty($contributors))
3459 {
3460 return SimplePie_Misc::array_unique($contributors);
3461 }
3462 else
3463 {
3464 return null;
3465 }
3466 }
3467
3468 function get_authors()
3469 {
3470 $authors = array();
3471 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3472 {
3473 $name = null;
3474 $uri = null;
3475 $email = null;
3476 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3477 {
3478 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3479 }
3480 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3481 {
3482 $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
3483 }
3484 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3485 {
3486 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3487 }
3488 if ($name !== null || $email !== null || $uri !== null)
3489 {
3490 $authors[] =& new $this->feed->author_class($name, $uri, $email);
3491 }
3492 }
3493 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3494 {
3495 $name = null;
3496 $url = null;
3497 $email = null;
3498 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3499 {
3500 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3501 }
3502 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3503 {
3504 $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
3505 }
3506 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3507 {
3508 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3509 }
3510 if ($name !== null || $email !== null || $url !== null)
3511 {
3512 $authors[] =& new $this->feed->author_class($name, $url, $email);
3513 }
3514 }
3515 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
3516 {
3517 $authors[] =& new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3518 }
3519 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3520 {
3521 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3522 }
3523 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3524 {
3525 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3526 }
3527 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3528 {
3529 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3530 }
3531
3532 if (!empty($authors))
3533 {
3534 return SimplePie_Misc::array_unique($authors);
3535 }
3536 elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3537 {
3538 return $authors;
3539 }
3540 elseif ($authors = $this->feed->get_authors())
3541 {
3542 return $authors;
3543 }
3544 else
3545 {
3546 return null;
3547 }
3548 }
3549
3550 function get_copyright()
3551 {
3552 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3553 {
3554 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3555 }
3556 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3557 {
3558 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3559 }
3560 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3561 {
3562 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3563 }
3564 else
3565 {
3566 return null;
3567 }
3568 }
3569
3570 function get_date($date_format = 'j F Y, g:i a')
3571 {
3572 if (!isset($this->data['date']))
3573 {
3574 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3575 {
3576 $this->data['date']['raw'] = $return[0]['data'];
3577 }
3578 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3579 {
3580 $this->data['date']['raw'] = $return[0]['data'];
3581 }
3582 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3583 {
3584 $this->data['date']['raw'] = $return[0]['data'];
3585 }
3586 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3587 {
3588 $this->data['date']['raw'] = $return[0]['data'];
3589 }
3590 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3591 {
3592 $this->data['date']['raw'] = $return[0]['data'];
3593 }
3594 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
3595 {
3596 $this->data['date']['raw'] = $return[0]['data'];
3597 }
3598 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3599 {
3600 $this->data['date']['raw'] = $return[0]['data'];
3601 }
3602 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3603 {
3604 $this->data['date']['raw'] = $return[0]['data'];
3605 }
3606
3607 if (!empty($this->data['date']['raw']))
3608 {
3609 $parser = SimplePie_Parse_Date::get();
3610 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3611 }
3612 else
3613 {
3614 $this->data['date'] = null;
3615 }
3616 }
3617 if ($this->data['date'])
3618 {
3619 $date_format = (string) $date_format;
3620 switch ($date_format)
3621 {
3622 case '':
3623 return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3624
3625 case 'U':
3626 return $this->data['date']['parsed'];
3627
3628 default:
3629 return date($date_format, $this->data['date']['parsed']);
3630 }
3631 }
3632 else
3633 {
3634 return null;
3635 }
3636 }
3637
3638 function get_local_date($date_format = '%c')
3639 {
3640 if (!$date_format)
3641 {
3642 return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3643 }
3644 elseif (($date = $this->get_date('U')) !== null)
3645 {
3646 return strftime($date_format, $date);
3647 }
3648 else
3649 {
3650 return null;
3651 }
3652 }
3653
3654 function get_permalink()
3655 {
3656 $link = $this->get_link();
3657 $enclosure = $this->get_enclosure(0);
3658 if ($link !== null)
3659 {
3660 return $link;
3661 }
3662 elseif ($enclosure !== null)
3663 {
3664 return $enclosure->get_link();
3665 }
3666 else
3667 {
3668 return null;
3669 }
3670 }
3671
3672 function get_link($key = 0, $rel = 'alternate')
3673 {
3674 $links = $this->get_links($rel);
3675 if ($links[$key] !== null)
3676 {
3677 return $links[$key];
3678 }
3679 else
3680 {
3681 return null;
3682 }
3683 }
3684
3685 function get_links($rel = 'alternate')
3686 {
3687 if (!isset($this->data['links']))
3688 {
3689 $this->data['links'] = array();
3690 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3691 {
3692 if (isset($link['attribs']['']['href']))
3693 {
3694 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3695 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3696
3697 }
3698 }
3699 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3700 {
3701 if (isset($link['attribs']['']['href']))
3702 {
3703 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3704 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3705 }
3706 }
3707 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3708 {
3709 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3710 }
3711 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3712 {
3713 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3714 }
3715 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
3716 {
3717 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3718 }
3719 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3720 {
3721 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
3722 {
3723 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3724 }
3725 }
3726
3727 $keys = array_keys($this->data['links']);
3728 foreach ($keys as $key)
3729 {
3730 if (SimplePie_Misc::is_isegment_nz_nc($key))
3731 {
3732 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3733 {
3734 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3735 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3736 }
3737 else
3738 {
3739 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3740 }
3741 }
3742 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
3743 {
3744 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3745 }
3746 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3747 }
3748 }
3749 if (isset($this->data['links'][$rel]))
3750 {
3751 return $this->data['links'][$rel];
3752 }
3753 else
3754 {
3755 return null;
3756 }
3757 }
3758
3759 /**
3760 * @todo Add ability to prefer one type of content over another (in a media group).
3761 */
3762 function get_enclosure($key = 0, $prefer = null)
3763 {
3764 $enclosures = $this->get_enclosures();
3765 if (isset($enclosures[$key]))
3766 {
3767 return $enclosures[$key];
3768 }
3769 else
3770 {
3771 return null;
3772 }
3773 }
3774
3775 /**
3776 * Grabs all available enclosures (podcasts, etc.)
3777 *
3778 * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3779 *
3780 * At this point, we're pretty much assuming that all enclosures for an item are the same content. Anything else is too complicated to properly support.
3781 *
3782 * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3783 * @todo If an element exists at a level, but it's value is empty, we should fall back to the value from the parent (if it exists).
3784 */
3785 function get_enclosures()
3786 {
3787 if (!isset($this->data['enclosures']))
3788 {
3789 $this->data['enclosures'] = array();
3790
3791 // Elements
3792 $captions_parent = null;
3793 $categories_parent = null;
3794 $copyrights_parent = null;
3795 $credits_parent = null;
3796 $description_parent = null;
3797 $duration_parent = null;
3798 $hashes_parent = null;
3799 $keywords_parent = null;
3800 $player_parent = null;
3801 $ratings_parent = null;
3802 $restrictions_parent = null;
3803 $thumbnails_parent = null;
3804 $title_parent = null;
3805
3806 // Let's do the channel and item-level ones first, and just re-use them if we need to.
3807 $parent = $this->get_feed();
3808
3809 // CAPTIONS
3810 if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3811 {
3812 foreach ($captions as $caption)
3813 {
3814 $caption_type = null;
3815 $caption_lang = null;
3816 $caption_startTime = null;
3817 $caption_endTime = null;
3818 $caption_text = null;
3819 if (isset($caption['attribs']['']['type']))
3820 {
3821 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3822 }
3823 if (isset($caption['attribs']['']['lang']))
3824 {
3825 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3826 }
3827 if (isset($caption['attribs']['']['start']))
3828 {
3829 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3830 }
3831 if (isset($caption['attribs']['']['end']))
3832 {
3833 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3834 }
3835 if (isset($caption['data']))
3836 {
3837 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3838 }
3839 $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3840 }
3841 }
3842 elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3843 {
3844 foreach ($captions as $caption)
3845 {
3846 $caption_type = null;
3847 $caption_lang = null;
3848 $caption_startTime = null;
3849 $caption_endTime = null;
3850 $caption_text = null;
3851 if (isset($caption['attribs']['']['type']))
3852 {
3853 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3854 }
3855 if (isset($caption['attribs']['']['lang']))
3856 {
3857 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3858 }
3859 if (isset($caption['attribs']['']['start']))
3860 {
3861 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3862 }
3863 if (isset($caption['attribs']['']['end']))
3864 {
3865 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3866 }
3867 if (isset($caption['data']))
3868 {
3869 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3870 }
3871 $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3872 }
3873 }
3874 if (is_array($captions_parent))
3875 {
3876 $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
3877 }
3878
3879 // CATEGORIES
3880 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3881 {
3882 $term = null;
3883 $scheme = null;
3884 $label = null;
3885 if (isset($category['data']))
3886 {
3887 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3888 }
3889 if (isset($category['attribs']['']['scheme']))
3890 {
3891 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3892 }
3893 else
3894 {
3895 $scheme = 'http://search.yahoo.com/mrss/category_schema';
3896 }
3897 if (isset($category['attribs']['']['label']))
3898 {
3899 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3900 }
3901 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3902 }
3903 foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3904 {
3905 $term = null;
3906 $scheme = null;
3907 $label = null;
3908 if (isset($category['data']))
3909 {
3910 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3911 }
3912 if (isset($category['attribs']['']['scheme']))
3913 {
3914 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3915 }
3916 else
3917 {
3918 $scheme = 'http://search.yahoo.com/mrss/category_schema';
3919 }
3920 if (isset($category['attribs']['']['label']))
3921 {
3922 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3923 }
3924 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3925 }
3926 foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
3927 {
3928 $term = null;
3929 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
3930 $label = null;
3931 if (isset($category['attribs']['']['text']))
3932 {
3933 $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3934 }
3935 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3936
3937 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
3938 {
3939 foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
3940 {
3941 if (isset($subcategory['attribs']['']['text']))
3942 {
3943 $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3944 }
3945 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3946 }
3947 }
3948 }
3949 if (is_array($categories_parent))
3950 {
3951 $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
3952 }
3953
3954 // COPYRIGHT
3955 if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3956 {
3957 $copyright_url = null;
3958 $copyright_label = null;
3959 if (isset($copyright[0]['attribs']['']['url']))
3960 {
3961 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3962 }
3963 if (isset($copyright[0]['data']))
3964 {
3965 $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3966 }
3967 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3968 }
3969 elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3970 {
3971 $copyright_url = null;
3972 $copyright_label = null;
3973 if (isset($copyright[0]['attribs']['']['url']))
3974 {
3975 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3976 }
3977 if (isset($copyright[0]['data']))
3978 {
3979 $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3980 }
3981 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3982 }
3983
3984 // CREDITS
3985 if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
3986 {
3987 foreach ($credits as $credit)
3988 {
3989 $credit_role = null;
3990 $credit_scheme = null;
3991 $credit_name = null;
3992 if (isset($credit['attribs']['']['role']))
3993 {
3994 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
3995 }
3996 if (isset($credit['attribs']['']['scheme']))
3997 {
3998 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3999 }
4000 else
4001 {
4002 $credit_scheme = 'urn:ebu';
4003 }
4004 if (isset($credit['data']))
4005 {
4006 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4007 }
4008 $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4009 }
4010 }
4011 elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4012 {
4013 foreach ($credits as $credit)
4014 {
4015 $credit_role = null;
4016 $credit_scheme = null;
4017 $credit_name = null;
4018 if (isset($credit['attribs']['']['role']))
4019 {
4020 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4021 }
4022 if (isset($credit['attribs']['']['scheme']))
4023 {
4024 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4025 }
4026 else
4027 {
4028 $credit_scheme = 'urn:ebu';
4029 }
4030 if (isset($credit['data']))
4031 {
4032 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4033 }
4034 $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4035 }
4036 }
4037 if (is_array($credits_parent))
4038 {
4039 $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
4040 }
4041
4042 // DESCRIPTION
4043 if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4044 {
4045 if (isset($description_parent[0]['data']))
4046 {
4047 $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4048 }
4049 }
4050 elseif ($description_parent = $parent->get_channel_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
4058 // DURATION
4059 if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
4060 {
4061 $seconds = null;
4062 $minutes = null;
4063 $hours = null;
4064 if (isset($duration_parent[0]['data']))
4065 {
4066 $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4067 if (sizeof($temp) > 0)
4068 {
4069 (int) $seconds = array_pop($temp);
4070 }
4071 if (sizeof($temp) > 0)
4072 {
4073 (int) $minutes = array_pop($temp);
4074 $seconds += $minutes * 60;
4075 }
4076 if (sizeof($temp) > 0)
4077 {
4078 (int) $hours = array_pop($temp);
4079 $seconds += $hours * 3600;
4080 }
4081 unset($temp);
4082 $duration_parent = $seconds;
4083 }
4084 }
4085
4086 // HASHES
4087 if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4088 {
4089 foreach ($hashes_iterator as $hash)
4090 {
4091 $value = null;
4092 $algo = null;
4093 if (isset($hash['data']))
4094 {
4095 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4096 }
4097 if (isset($hash['attribs']['']['algo']))
4098 {
4099 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4100 }
4101 else
4102 {
4103 $algo = 'md5';
4104 }
4105 $hashes_parent[] = $algo.':'.$value;
4106 }
4107 }
4108 elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4109 {
4110 foreach ($hashes_iterator as $hash)
4111 {
4112 $value = null;
4113 $algo = null;
4114 if (isset($hash['data']))
4115 {
4116 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4117 }
4118 if (isset($hash['attribs']['']['algo']))
4119 {
4120 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4121 }
4122 else
4123 {
4124 $algo = 'md5';
4125 }
4126 $hashes_parent[] = $algo.':'.$value;
4127 }
4128 }
4129 if (is_array($hashes_parent))
4130 {
4131 $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
4132 }
4133
4134 // KEYWORDS
4135 if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4136 {
4137 if (isset($keywords[0]['data']))
4138 {
4139 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4140 foreach ($temp as $word)
4141 {
4142 $keywords_parent[] = trim($word);
4143 }
4144 }
4145 unset($temp);
4146 }
4147 elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4148 {
4149 if (isset($keywords[0]['data']))
4150 {
4151 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4152 foreach ($temp as $word)
4153 {
4154 $keywords_parent[] = trim($word);
4155 }
4156 }
4157 unset($temp);
4158 }
4159 elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4160 {
4161 if (isset($keywords[0]['data']))
4162 {
4163 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4164 foreach ($temp as $word)
4165 {
4166 $keywords_parent[] = trim($word);
4167 }
4168 }
4169 unset($temp);
4170 }
4171 elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4172 {
4173 if (isset($keywords[0]['data']))
4174 {
4175 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4176 foreach ($temp as $word)
4177 {
4178 $keywords_parent[] = trim($word);
4179 }
4180 }
4181 unset($temp);
4182 }
4183 if (is_array($keywords_parent))
4184 {
4185 $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
4186 }
4187
4188 // PLAYER
4189 if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4190 {
4191 if (isset($player_parent[0]['attribs']['']['url']))
4192 {
4193 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4194 }
4195 }
4196 elseif ($player_parent = $parent->get_channel_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
4204 // RATINGS
4205 if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4206 {
4207 foreach ($ratings as $rating)
4208 {
4209 $rating_scheme = null;
4210 $rating_value = null;
4211 if (isset($rating['attribs']['']['scheme']))
4212 {
4213 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4214 }
4215 else
4216 {
4217 $rating_scheme = 'urn:simple';
4218 }
4219 if (isset($rating['data']))
4220 {
4221 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4222 }
4223 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4224 }
4225 }
4226 elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4227 {
4228 foreach ($ratings as $rating)
4229 {
4230 $rating_scheme = 'urn:itunes';
4231 $rating_value = null;
4232 if (isset($rating['data']))
4233 {
4234 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4235 }
4236 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4237 }
4238 }
4239 elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4240 {
4241 foreach ($ratings as $rating)
4242 {
4243 $rating_scheme = null;
4244 $rating_value = null;
4245 if (isset($rating['attribs']['']['scheme']))
4246 {
4247 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4248 }
4249 else
4250 {
4251 $rating_scheme = 'urn:simple';
4252 }
4253 if (isset($rating['data']))
4254 {
4255 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4256 }
4257 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4258 }
4259 }
4260 elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4261 {
4262 foreach ($ratings as $rating)
4263 {
4264 $rating_scheme = 'urn:itunes';
4265 $rating_value = null;
4266 if (isset($rating['data']))
4267 {
4268 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4269 }
4270 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4271 }
4272 }
4273 if (is_array($ratings_parent))
4274 {
4275 $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
4276 }
4277
4278 // RESTRICTIONS
4279 if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4280 {
4281 foreach ($restrictions as $restriction)
4282 {
4283 $restriction_relationship = null;
4284 $restriction_type = null;
4285 $restriction_value = null;
4286 if (isset($restriction['attribs']['']['relationship']))
4287 {
4288 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4289 }
4290 if (isset($restriction['attribs']['']['type']))
4291 {
4292 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4293 }
4294 if (isset($restriction['data']))
4295 {
4296 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4297 }
4298 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4299 }
4300 }
4301 elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4302 {
4303 foreach ($restrictions as $restriction)
4304 {
4305 $restriction_relationship = 'allow';
4306 $restriction_type = null;
4307 $restriction_value = 'itunes';
4308 if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4309 {
4310 $restriction_relationship = 'deny';
4311 }
4312 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4313 }
4314 }
4315 elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4316 {
4317 foreach ($restrictions as $restriction)
4318 {
4319 $restriction_relationship = null;
4320 $restriction_type = null;
4321 $restriction_value = null;
4322 if (isset($restriction['attribs']['']['relationship']))
4323 {
4324 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4325 }
4326 if (isset($restriction['attribs']['']['type']))
4327 {
4328 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4329 }
4330 if (isset($restriction['data']))
4331 {
4332 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4333 }
4334 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4335 }
4336 }
4337 elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4338 {
4339 foreach ($restrictions as $restriction)
4340 {
4341 $restriction_relationship = 'allow';
4342 $restriction_type = null;
4343 $restriction_value = 'itunes';
4344 if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4345 {
4346 $restriction_relationship = 'deny';
4347 }
4348 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4349 }
4350 }
4351 if (is_array($restrictions_parent))
4352 {
4353 $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
4354 }
4355
4356 // THUMBNAILS
4357 if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4358 {
4359 foreach ($thumbnails as $thumbnail)
4360 {
4361 if (isset($thumbnail['attribs']['']['url']))
4362 {
4363 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4364 }
4365 }
4366 }
4367 elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4368 {
4369 foreach ($thumbnails as $thumbnail)
4370 {
4371 if (isset($thumbnail['attribs']['']['url']))
4372 {
4373 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4374 }
4375 }
4376 }
4377
4378 // TITLES
4379 if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4380 {
4381 if (isset($title_parent[0]['data']))
4382 {
4383 $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4384 }
4385 }
4386 elseif ($title_parent = $parent->get_channel_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
4394 // Clear the memory
4395 unset($parent);
4396
4397 // Attributes
4398 $bitrate = null;
4399 $channels = null;
4400 $duration = null;
4401 $expression = null;
4402 $framerate = null;
4403 $height = null;
4404 $javascript = null;
4405 $lang = null;
4406 $length = null;
4407 $medium = null;
4408 $samplingrate = null;
4409 $type = null;
4410 $url = null;
4411 $width = null;
4412
4413 // Elements
4414 $captions = null;
4415 $categories = null;
4416 $copyrights = null;
4417 $credits = null;
4418 $description = null;
4419 $hashes = null;
4420 $keywords = null;
4421 $player = null;
4422 $ratings = null;
4423 $restrictions = null;
4424 $thumbnails = null;
4425 $title = null;
4426
4427 // If we have media:group tags, loop through them.
4428 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
4429 {
4430 // If we have media:content tags, loop through them.
4431 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4432 {
4433 if (isset($content['attribs']['']['url']))
4434 {
4435 // Attributes
4436 $bitrate = null;
4437 $channels = null;
4438 $duration = null;
4439 $expression = null;
4440 $framerate = null;
4441 $height = null;
4442 $javascript = null;
4443 $lang = null;
4444 $length = null;
4445 $medium = null;
4446 $samplingrate = null;
4447 $type = null;
4448 $url = null;
4449 $width = null;
4450
4451 // Elements
4452 $captions = null;
4453 $categories = null;
4454 $copyrights = null;
4455 $credits = null;
4456 $description = null;
4457 $hashes = null;
4458 $keywords = null;
4459 $player = null;
4460 $ratings = null;
4461 $restrictions = null;
4462 $thumbnails = null;
4463 $title = null;
4464
4465 // Start checking the attributes of media:content
4466 if (isset($content['attribs']['']['bitrate']))
4467 {
4468 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4469 }
4470 if (isset($content['attribs']['']['channels']))
4471 {
4472 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4473 }
4474 if (isset($content['attribs']['']['duration']))
4475 {
4476 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4477 }
4478 else
4479 {
4480 $duration = $duration_parent;
4481 }
4482 if (isset($content['attribs']['']['expression']))
4483 {
4484 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4485 }
4486 if (isset($content['attribs']['']['framerate']))
4487 {
4488 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4489 }
4490 if (isset($content['attribs']['']['height']))
4491 {
4492 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4493 }
4494 if (isset($content['attribs']['']['lang']))
4495 {
4496 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4497 }
4498 if (isset($content['attribs']['']['fileSize']))
4499 {
4500 $length = ceil($content['attribs']['']['fileSize']);
4501 }
4502 if (isset($content['attribs']['']['medium']))
4503 {
4504 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4505 }
4506 if (isset($content['attribs']['']['samplingrate']))
4507 {
4508 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4509 }
4510 if (isset($content['attribs']['']['type']))
4511 {
4512 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4513 }
4514 if (isset($content['attribs']['']['width']))
4515 {
4516 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4517 }
4518 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4519
4520 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4521
4522 // CAPTIONS
4523 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4524 {
4525 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4526 {
4527 $caption_type = null;
4528 $caption_lang = null;
4529 $caption_startTime = null;
4530 $caption_endTime = null;
4531 $caption_text = null;
4532 if (isset($caption['attribs']['']['type']))
4533 {
4534 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4535 }
4536 if (isset($caption['attribs']['']['lang']))
4537 {
4538 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4539 }
4540 if (isset($caption['attribs']['']['start']))
4541 {
4542 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4543 }
4544 if (isset($caption['attribs']['']['end']))
4545 {
4546 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4547 }
4548 if (isset($caption['data']))
4549 {
4550 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4551 }
4552 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4553 }
4554 if (is_array($captions))
4555 {
4556 $captions = array_values(SimplePie_Misc::array_unique($captions));
4557 }
4558 }
4559 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4560 {
4561 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4562 {
4563 $caption_type = null;
4564 $caption_lang = null;
4565 $caption_startTime = null;
4566 $caption_endTime = null;
4567 $caption_text = null;
4568 if (isset($caption['attribs']['']['type']))
4569 {
4570 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4571 }
4572 if (isset($caption['attribs']['']['lang']))
4573 {
4574 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4575 }
4576 if (isset($caption['attribs']['']['start']))
4577 {
4578 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4579 }
4580 if (isset($caption['attribs']['']['end']))
4581 {
4582 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4583 }
4584 if (isset($caption['data']))
4585 {
4586 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4587 }
4588 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4589 }
4590 if (is_array($captions))
4591 {
4592 $captions = array_values(SimplePie_Misc::array_unique($captions));
4593 }
4594 }
4595 else
4596 {
4597 $captions = $captions_parent;
4598 }
4599
4600 // CATEGORIES
4601 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4602 {
4603 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4604 {
4605 $term = null;
4606 $scheme = null;
4607 $label = null;
4608 if (isset($category['data']))
4609 {
4610 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4611 }
4612 if (isset($category['attribs']['']['scheme']))
4613 {
4614 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4615 }
4616 else
4617 {
4618 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4619 }
4620 if (isset($category['attribs']['']['label']))
4621 {
4622 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4623 }
4624 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4625 }
4626 }
4627 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4628 {
4629 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4630 {
4631 $term = null;
4632 $scheme = null;
4633 $label = null;
4634 if (isset($category['data']))
4635 {
4636 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4637 }
4638 if (isset($category['attribs']['']['scheme']))
4639 {
4640 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4641 }
4642 else
4643 {
4644 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4645 }
4646 if (isset($category['attribs']['']['label']))
4647 {
4648 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4649 }
4650 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4651 }
4652 }
4653 if (is_array($categories) && is_array($categories_parent))
4654 {
4655 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4656 }
4657 elseif (is_array($categories))
4658 {
4659 $categories = array_values(SimplePie_Misc::array_unique($categories));
4660 }
4661 elseif (is_array($categories_parent))
4662 {
4663 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4664 }
4665
4666 // COPYRIGHTS
4667 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4668 {
4669 $copyright_url = null;
4670 $copyright_label = null;
4671 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4672 {
4673 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4674 }
4675 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4676 {
4677 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4678 }
4679 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4680 }
4681 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4682 {
4683 $copyright_url = null;
4684 $copyright_label = null;
4685 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4686 {
4687 $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4688 }
4689 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4690 {
4691 $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4692 }
4693 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4694 }
4695 else
4696 {
4697 $copyrights = $copyrights_parent;
4698 }
4699
4700 // CREDITS
4701 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4702 {
4703 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4704 {
4705 $credit_role = null;
4706 $credit_scheme = null;
4707 $credit_name = null;
4708 if (isset($credit['attribs']['']['role']))
4709 {
4710 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4711 }
4712 if (isset($credit['attribs']['']['scheme']))
4713 {
4714 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4715 }
4716 else
4717 {
4718 $credit_scheme = 'urn:ebu';
4719 }
4720 if (isset($credit['data']))
4721 {
4722 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4723 }
4724 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4725 }
4726 if (is_array($credits))
4727 {
4728 $credits = array_values(SimplePie_Misc::array_unique($credits));
4729 }
4730 }
4731 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4732 {
4733 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4734 {
4735 $credit_role = null;
4736 $credit_scheme = null;
4737 $credit_name = null;
4738 if (isset($credit['attribs']['']['role']))
4739 {
4740 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4741 }
4742 if (isset($credit['attribs']['']['scheme']))
4743 {
4744 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4745 }
4746 else
4747 {
4748 $credit_scheme = 'urn:ebu';
4749 }
4750 if (isset($credit['data']))
4751 {
4752 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4753 }
4754 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4755 }
4756 if (is_array($credits))
4757 {
4758 $credits = array_values(SimplePie_Misc::array_unique($credits));
4759 }
4760 }
4761 else
4762 {
4763 $credits = $credits_parent;
4764 }
4765
4766 // DESCRIPTION
4767 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4768 {
4769 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4770 }
4771 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4772 {
4773 $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4774 }
4775 else
4776 {
4777 $description = $description_parent;
4778 }
4779
4780 // HASHES
4781 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4782 {
4783 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4784 {
4785 $value = null;
4786 $algo = null;
4787 if (isset($hash['data']))
4788 {
4789 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4790 }
4791 if (isset($hash['attribs']['']['algo']))
4792 {
4793 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4794 }
4795 else
4796 {
4797 $algo = 'md5';
4798 }
4799 $hashes[] = $algo.':'.$value;
4800 }
4801 if (is_array($hashes))
4802 {
4803 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4804 }
4805 }
4806 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4807 {
4808 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4809 {
4810 $value = null;
4811 $algo = null;
4812 if (isset($hash['data']))
4813 {
4814 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4815 }
4816 if (isset($hash['attribs']['']['algo']))
4817 {
4818 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4819 }
4820 else
4821 {
4822 $algo = 'md5';
4823 }
4824 $hashes[] = $algo.':'.$value;
4825 }
4826 if (is_array($hashes))
4827 {
4828 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4829 }
4830 }
4831 else
4832 {
4833 $hashes = $hashes_parent;
4834 }
4835
4836 // KEYWORDS
4837 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4838 {
4839 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4840 {
4841 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4842 foreach ($temp as $word)
4843 {
4844 $keywords[] = trim($word);
4845 }
4846 unset($temp);
4847 }
4848 if (is_array($keywords))
4849 {
4850 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4851 }
4852 }
4853 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4854 {
4855 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4856 {
4857 $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4858 foreach ($temp as $word)
4859 {
4860 $keywords[] = trim($word);
4861 }
4862 unset($temp);
4863 }
4864 if (is_array($keywords))
4865 {
4866 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4867 }
4868 }
4869 else
4870 {
4871 $keywords = $keywords_parent;
4872 }
4873
4874 // PLAYER
4875 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4876 {
4877 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4878 }
4879 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4880 {
4881 $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4882 }
4883 else
4884 {
4885 $player = $player_parent;
4886 }
4887
4888 // RATINGS
4889 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4890 {
4891 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4892 {
4893 $rating_scheme = null;
4894 $rating_value = null;
4895 if (isset($rating['attribs']['']['scheme']))
4896 {
4897 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4898 }
4899 else
4900 {
4901 $rating_scheme = 'urn:simple';
4902 }
4903 if (isset($rating['data']))
4904 {
4905 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4906 }
4907 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4908 }
4909 if (is_array($ratings))
4910 {
4911 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4912 }
4913 }
4914 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4915 {
4916 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4917 {
4918 $rating_scheme = null;
4919 $rating_value = null;
4920 if (isset($rating['attribs']['']['scheme']))
4921 {
4922 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4923 }
4924 else
4925 {
4926 $rating_scheme = 'urn:simple';
4927 }
4928 if (isset($rating['data']))
4929 {
4930 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4931 }
4932 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4933 }
4934 if (is_array($ratings))
4935 {
4936 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4937 }
4938 }
4939 else
4940 {
4941 $ratings = $ratings_parent;
4942 }
4943
4944 // RESTRICTIONS
4945 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4946 {
4947 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4948 {
4949 $restriction_relationship = null;
4950 $restriction_type = null;
4951 $restriction_value = null;
4952 if (isset($restriction['attribs']['']['relationship']))
4953 {
4954 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4955 }
4956 if (isset($restriction['attribs']['']['type']))
4957 {
4958 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4959 }
4960 if (isset($restriction['data']))
4961 {
4962 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4963 }
4964 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4965 }
4966 if (is_array($restrictions))
4967 {
4968 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4969 }
4970 }
4971 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4972 {
4973 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4974 {
4975 $restriction_relationship = null;
4976 $restriction_type = null;
4977 $restriction_value = null;
4978 if (isset($restriction['attribs']['']['relationship']))
4979 {
4980 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4981 }
4982 if (isset($restriction['attribs']['']['type']))
4983 {
4984 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4985 }
4986 if (isset($restriction['data']))
4987 {
4988 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4989 }
4990 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4991 }
4992 if (is_array($restrictions))
4993 {
4994 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4995 }
4996 }
4997 else
4998 {
4999 $restrictions = $restrictions_parent;
5000 }
5001
5002 // THUMBNAILS
5003 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5004 {
5005 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5006 {
5007 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5008 }
5009 if (is_array($thumbnails))
5010 {
5011 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5012 }
5013 }
5014 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5015 {
5016 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5017 {
5018 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5019 }
5020 if (is_array($thumbnails))
5021 {
5022 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5023 }
5024 }
5025 else
5026 {
5027 $thumbnails = $thumbnails_parent;
5028 }
5029
5030 // TITLES
5031 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5032 {
5033 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5034 }
5035 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5036 {
5037 $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5038 }
5039 else
5040 {
5041 $title = $title_parent;
5042 }
5043
5044 $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);
5045 }
5046 }
5047 }
5048
5049 // If we have standalone media:content tags, loop through them.
5050 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
5051 {
5052 foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
5053 {
5054 if (isset($content['attribs']['']['url']))
5055 {
5056 // Attributes
5057 $bitrate = null;
5058 $channels = null;
5059 $duration = null;
5060 $expression = null;
5061 $framerate = null;
5062 $height = null;
5063 $javascript = null;
5064 $lang = null;
5065 $length = null;
5066 $medium = null;
5067 $samplingrate = null;
5068 $type = null;
5069 $url = null;
5070 $width = null;
5071
5072 // Elements
5073 $captions = null;
5074 $categories = null;
5075 $copyrights = null;
5076 $credits = null;
5077 $description = null;
5078 $hashes = null;
5079 $keywords = null;
5080 $player = null;
5081 $ratings = null;
5082 $restrictions = null;
5083 $thumbnails = null;
5084 $title = null;
5085
5086 // Start checking the attributes of media:content
5087 if (isset($content['attribs']['']['bitrate']))
5088 {
5089 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5090 }
5091 if (isset($content['attribs']['']['channels']))
5092 {
5093 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
5094 }
5095 if (isset($content['attribs']['']['duration']))
5096 {
5097 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
5098 }
5099 else
5100 {
5101 $duration = $duration_parent;
5102 }
5103 if (isset($content['attribs']['']['expression']))
5104 {
5105 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
5106 }
5107 if (isset($content['attribs']['']['framerate']))
5108 {
5109 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
5110 }
5111 if (isset($content['attribs']['']['height']))
5112 {
5113 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
5114 }
5115 if (isset($content['attribs']['']['lang']))
5116 {
5117 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5118 }
5119 if (isset($content['attribs']['']['fileSize']))
5120 {
5121 $length = ceil($content['attribs']['']['fileSize']);
5122 }
5123 if (isset($content['attribs']['']['medium']))
5124 {
5125 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
5126 }
5127 if (isset($content['attribs']['']['samplingrate']))
5128 {
5129 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5130 }
5131 if (isset($content['attribs']['']['type']))
5132 {
5133 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5134 }
5135 if (isset($content['attribs']['']['width']))
5136 {
5137 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
5138 }
5139 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5140
5141 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
5142
5143 // CAPTIONS
5144 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
5145 {
5146 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
5147 {
5148 $caption_type = null;
5149 $caption_lang = null;
5150 $caption_startTime = null;
5151 $caption_endTime = null;
5152 $caption_text = null;
5153 if (isset($caption['attribs']['']['type']))
5154 {
5155 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5156 }
5157 if (isset($caption['attribs']['']['lang']))
5158 {
5159 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5160 }
5161 if (isset($caption['attribs']['']['start']))
5162 {
5163 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
5164 }
5165 if (isset($caption['attribs']['']['end']))
5166 {
5167 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
5168 }
5169 if (isset($caption['data']))
5170 {
5171 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5172 }
5173 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
5174 }
5175 if (is_array($captions))
5176 {
5177 $captions = array_values(SimplePie_Misc::array_unique($captions));
5178 }
5179 }
5180 else
5181 {
5182 $captions = $captions_parent;
5183 }
5184
5185 // CATEGORIES
5186 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
5187 {
5188 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
5189 {
5190 $term = null;
5191 $scheme = null;
5192 $label = null;
5193 if (isset($category['data']))
5194 {
5195 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5196 }
5197 if (isset($category['attribs']['']['scheme']))
5198 {
5199 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5200 }
5201 else
5202 {
5203 $scheme = 'http://search.yahoo.com/mrss/category_schema';
5204 }
5205 if (isset($category['attribs']['']['label']))
5206 {
5207 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5208 }
5209 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
5210 }
5211 }
5212 if (is_array($categories) && is_array($categories_parent))
5213 {
5214 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
5215 }
5216 elseif (is_array($categories))
5217 {
5218 $categories = array_values(SimplePie_Misc::array_unique($categories));
5219 }
5220 elseif (is_array($categories_parent))
5221 {
5222 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
5223 }
5224 else
5225 {
5226 $categories = null;
5227 }
5228
5229 // COPYRIGHTS
5230 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
5231 {
5232 $copyright_url = null;
5233 $copyright_label = null;
5234 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
5235 {
5236 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
5237 }
5238 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
5239 {
5240 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5241 }
5242 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
5243 }
5244 else
5245 {
5246 $copyrights = $copyrights_parent;
5247 }
5248
5249 // CREDITS
5250 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
5251 {
5252 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
5253 {
5254 $credit_role = null;
5255 $credit_scheme = null;
5256 $credit_name = null;
5257 if (isset($credit['attribs']['']['role']))
5258 {
5259 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
5260 }
5261 if (isset($credit['attribs']['']['scheme']))
5262 {
5263 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5264 }
5265 else
5266 {
5267 $credit_scheme = 'urn:ebu';
5268 }
5269 if (isset($credit['data']))
5270 {
5271 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5272 }
5273 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
5274 }
5275 if (is_array($credits))
5276 {
5277 $credits = array_values(SimplePie_Misc::array_unique($credits));
5278 }
5279 }
5280 else
5281 {
5282 $credits = $credits_parent;
5283 }
5284
5285 // DESCRIPTION
5286 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
5287 {
5288 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5289 }
5290 else
5291 {
5292 $description = $description_parent;
5293 }
5294
5295 // HASHES
5296 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
5297 {
5298 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
5299 {
5300 $value = null;
5301 $algo = null;
5302 if (isset($hash['data']))
5303 {
5304 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5305 }
5306 if (isset($hash['attribs']['']['algo']))
5307 {
5308 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
5309 }
5310 else
5311 {
5312 $algo = 'md5';
5313 }
5314 $hashes[] = $algo.':'.$value;
5315 }
5316 if (is_array($hashes))
5317 {
5318 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
5319 }
5320 }
5321 else
5322 {
5323 $hashes = $hashes_parent;
5324 }
5325
5326 // KEYWORDS
5327 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
5328 {
5329 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
5330 {
5331 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
5332 foreach ($temp as $word)
5333 {
5334 $keywords[] = trim($word);
5335 }
5336 unset($temp);
5337 }
5338 if (is_array($keywords))
5339 {
5340 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
5341 }
5342 }
5343 else
5344 {
5345 $keywords = $keywords_parent;
5346 }
5347
5348 // PLAYER
5349 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5350 {
5351 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5352 }
5353 else
5354 {
5355 $player = $player_parent;
5356 }
5357
5358 // RATINGS
5359 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
5360 {
5361 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
5362 {
5363 $rating_scheme = null;
5364 $rating_value = null;
5365 if (isset($rating['attribs']['']['scheme']))
5366 {
5367 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5368 }
5369 else
5370 {
5371 $rating_scheme = 'urn:simple';
5372 }
5373 if (isset($rating['data']))
5374 {
5375 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5376 }
5377 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
5378 }
5379 if (is_array($ratings))
5380 {
5381 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
5382 }
5383 }
5384 else
5385 {
5386 $ratings = $ratings_parent;
5387 }
5388
5389 // RESTRICTIONS
5390 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5391 {
5392 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5393 {
5394 $restriction_relationship = null;
5395 $restriction_type = null;
5396 $restriction_value = null;
5397 if (isset($restriction['attribs']['']['relationship']))
5398 {
5399 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5400 }
5401 if (isset($restriction['attribs']['']['type']))
5402 {
5403 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5404 }
5405 if (isset($restriction['data']))
5406 {
5407 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5408 }
5409 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5410 }
5411 if (is_array($restrictions))
5412 {
5413 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5414 }
5415 }
5416 else
5417 {
5418 $restrictions = $restrictions_parent;
5419 }
5420
5421 // THUMBNAILS
5422 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5423 {
5424 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5425 {
5426 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5427 }
5428 if (is_array($thumbnails))
5429 {
5430 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5431 }
5432 }
5433 else
5434 {
5435 $thumbnails = $thumbnails_parent;
5436 }
5437
5438 // TITLES
5439 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5440 {
5441 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5442 }
5443 else
5444 {
5445 $title = $title_parent;
5446 }
5447
5448 $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);
5449 }
5450 }
5451 }
5452
5453 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
5454 {
5455 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5456 {
5457 // Attributes
5458 $bitrate = null;
5459 $channels = null;
5460 $duration = null;
5461 $expression = null;
5462 $framerate = null;
5463 $height = null;
5464 $javascript = null;
5465 $lang = null;
5466 $length = null;
5467 $medium = null;
5468 $samplingrate = null;
5469 $type = null;
5470 $url = null;
5471 $width = null;
5472
5473 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5474 if (isset($link['attribs']['']['type']))
5475 {
5476 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5477 }
5478 if (isset($link['attribs']['']['length']))
5479 {
5480 $length = ceil($link['attribs']['']['length']);
5481 }
5482
5483 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5484 $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);
5485 }
5486 }
5487
5488 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5489 {
5490 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5491 {
5492 // Attributes
5493 $bitrate = null;
5494 $channels = null;
5495 $duration = null;
5496 $expression = null;
5497 $framerate = null;
5498 $height = null;
5499 $javascript = null;
5500 $lang = null;
5501 $length = null;
5502 $medium = null;
5503 $samplingrate = null;
5504 $type = null;
5505 $url = null;
5506 $width = null;
5507
5508 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5509 if (isset($link['attribs']['']['type']))
5510 {
5511 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5512 }
5513 if (isset($link['attribs']['']['length']))
5514 {
5515 $length = ceil($link['attribs']['']['length']);
5516 }
5517
5518 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5519 $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);
5520 }
5521 }
5522
5523 if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
5524 {
5525 if (isset($enclosure[0]['attribs']['']['url']))
5526 {
5527 // Attributes
5528 $bitrate = null;
5529 $channels = null;
5530 $duration = null;
5531 $expression = null;
5532 $framerate = null;
5533 $height = null;
5534 $javascript = null;
5535 $lang = null;
5536 $length = null;
5537 $medium = null;
5538 $samplingrate = null;
5539 $type = null;
5540 $url = null;
5541 $width = null;
5542
5543 $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5544 if (isset($enclosure[0]['attribs']['']['type']))
5545 {
5546 $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5547 }
5548 if (isset($enclosure[0]['attribs']['']['length']))
5549 {
5550 $length = ceil($enclosure[0]['attribs']['']['length']);
5551 }
5552
5553 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5554 $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);
5555 }
5556 }
5557
5558 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))
5559 {
5560 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5561 $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);
5562 }
5563
5564 $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5565 }
5566 if (!empty($this->data['enclosures']))
5567 {
5568 return $this->data['enclosures'];
5569 }
5570 else
5571 {
5572 return null;
5573 }
5574 }
5575
5576 function get_latitude()
5577 {
5578 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5579 {
5580 return (float) $return[0]['data'];
5581 }
5582 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
5583 {
5584 return (float) $match[1];
5585 }
5586 else
5587 {
5588 return null;
5589 }
5590 }
5591
5592 function get_longitude()
5593 {
5594 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5595 {
5596 return (float) $return[0]['data'];
5597 }
5598 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5599 {
5600 return (float) $return[0]['data'];
5601 }
5602 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
5603 {
5604 return (float) $match[2];
5605 }
5606 else
5607 {
5608 return null;
5609 }
5610 }
5611
5612 function get_source()
5613 {
5614 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5615 {
5616 return new $this->feed->source_class($this, $return[0]);
5617 }
5618 else
5619 {
5620 return null;
5621 }
5622 }
5623
5624 /**
5625 * Creates the add_to_* methods' return data
5626 *
5627 * @access private
5628 * @param string $item_url String to prefix to the item permalink
5629 * @param string $title_url String to prefix to the item title
5630 * (and suffix to the item permalink)
5631 * @return mixed URL if feed exists, false otherwise
5632 */
5633 function add_to_service($item_url, $title_url = null, $summary_url = null)
5634 {
5635 if ($this->get_permalink() !== null)
5636 {
5637 $return = $item_url . rawurlencode($this->get_permalink());
5638 if ($title_url !== null && $this->get_title() !== null)
5639 {
5640 $return .= $title_url . rawurlencode($this->get_title());
5641 }
5642 if ($summary_url !== null && $this->get_description() !== null)
5643 {
5644 $return .= $summary_url . rawurlencode($this->get_description());
5645 }
5646 return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
5647 }
5648 else
5649 {
5650 return null;
5651 }
5652 }
5653
5654 function add_to_blinklist()
5655 {
5656 return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5657 }
5658
5659 function add_to_blogmarks()
5660 {
5661 return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5662 }
5663
5664 function add_to_delicious()
5665 {
5666 return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
5667 }
5668
5669 function add_to_digg()
5670 {
5671 return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
5672 }
5673
5674 function add_to_furl()
5675 {
5676 return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5677 }
5678
5679 function add_to_magnolia()
5680 {
5681 return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5682 }
5683
5684 function add_to_myweb20()
5685 {
5686 return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5687 }
5688
5689 function add_to_newsvine()
5690 {
5691 return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5692 }
5693
5694 function add_to_reddit()
5695 {
5696 return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5697 }
5698
5699 function add_to_segnalo()
5700 {
5701 return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5702 }
5703
5704 function add_to_simpy()
5705 {
5706 return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5707 }
5708
5709 function add_to_spurl()
5710 {
5711 return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5712 }
5713
5714 function add_to_wists()
5715 {
5716 return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5717 }
5718
5719 function search_technorati()
5720 {
5721 return $this->add_to_service('http://www.technorati.com/search/');
5722 }
5723 }
5724
5725 class SimplePie_Source
5726 {
5727 var $item;
5728 var $data = array();
5729
5730 function SimplePie_Source($item, $data)
5731 {
5732 $this->item = $item;
5733 $this->data = $data;
5734 }
5735
5736 function __toString()
5737 {
5738 return md5(serialize($this->data));
5739 }
5740
5741 function get_source_tags($namespace, $tag)
5742 {
5743 if (isset($this->data['child'][$namespace][$tag]))
5744 {
5745 return $this->data['child'][$namespace][$tag];
5746 }
5747 else
5748 {
5749 return null;
5750 }
5751 }
5752
5753 function get_base($element = array())
5754 {
5755 return $this->item->get_base($element);
5756 }
5757
5758 function sanitize($data, $type, $base = '')
5759 {
5760 return $this->item->sanitize($data, $type, $base);
5761 }
5762
5763 function get_item()
5764 {
5765 return $this->item;
5766 }
5767
5768 function get_title()
5769 {
5770 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5771 {
5772 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5773 }
5774 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5775 {
5776 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5777 }
5778 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5779 {
5780 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5781 }
5782 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5783 {
5784 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5785 }
5786 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
5787 {
5788 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5789 }
5790 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5791 {
5792 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5793 }
5794 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5795 {
5796 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5797 }
5798 else
5799 {
5800 return null;
5801 }
5802 }
5803
5804 function get_category($key = 0)
5805 {
5806 $categories = $this->get_categories();
5807 if (isset($categories[$key]))
5808 {
5809 return $categories[$key];
5810 }
5811 else
5812 {
5813 return null;
5814 }
5815 }
5816
5817 function get_categories()
5818 {
5819 $categories = array();
5820
5821 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5822 {
5823 $term = null;
5824 $scheme = null;
5825 $label = null;
5826 if (isset($category['attribs']['']['term']))
5827 {
5828 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5829 }
5830 if (isset($category['attribs']['']['scheme']))
5831 {
5832 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5833 }
5834 if (isset($category['attribs']['']['label']))
5835 {
5836 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5837 }
5838 $categories[] =& new $this->item->feed->category_class($term, $scheme, $label);
5839 }
5840 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
5841 {
5842 // This is really the label, but keep this as the term also for BC.
5843 // Label will also work on retrieving because that falls back to term.
5844 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5845 if (isset($category['attribs']['']['domain']))
5846 {
5847 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
5848 }
5849 else
5850 {
5851 $scheme = null;
5852 }
5853 $categories[] =& new $this->item->feed->category_class($term, $scheme, null);
5854 }
5855 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5856 {
5857 $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5858 }
5859 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5860 {
5861 $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5862 }
5863
5864 if (!empty($categories))
5865 {
5866 return SimplePie_Misc::array_unique($categories);
5867 }
5868 else
5869 {
5870 return null;
5871 }
5872 }
5873
5874 function get_author($key = 0)
5875 {
5876 $authors = $this->get_authors();
5877 if (isset($authors[$key]))
5878 {
5879 return $authors[$key];
5880 }
5881 else
5882 {
5883 return null;
5884 }
5885 }
5886
5887 function get_authors()
5888 {
5889 $authors = array();
5890 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5891 {
5892 $name = null;
5893 $uri = null;
5894 $email = null;
5895 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5896 {
5897 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5898 }
5899 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5900 {
5901 $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]));
5902 }
5903 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5904 {
5905 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5906 }
5907 if ($name !== null || $email !== null || $uri !== null)
5908 {
5909 $authors[] =& new $this->item->feed->author_class($name, $uri, $email);
5910 }
5911 }
5912 if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5913 {
5914 $name = null;
5915 $url = null;
5916 $email = null;
5917 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5918 {
5919 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5920 }
5921 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5922 {
5923 $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]));
5924 }
5925 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5926 {
5927 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5928 }
5929 if ($name !== null || $email !== null || $url !== null)
5930 {
5931 $authors[] =& new $this->item->feed->author_class($name, $url, $email);
5932 }
5933 }
5934 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
5935 {
5936 $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5937 }
5938 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
5939 {
5940 $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5941 }
5942 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
5943 {
5944 $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5945 }
5946
5947 if (!empty($authors))
5948 {
5949 return SimplePie_Misc::array_unique($authors);
5950 }
5951 else
5952 {
5953 return null;
5954 }
5955 }
5956
5957 function get_contributor($key = 0)
5958 {
5959 $contributors = $this->get_contributors();
5960 if (isset($contributors[$key]))
5961 {
5962 return $contributors[$key];
5963 }
5964 else
5965 {
5966 return null;
5967 }
5968 }
5969
5970 function get_contributors()
5971 {
5972 $contributors = array();
5973 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
5974 {
5975 $name = null;
5976 $uri = null;
5977 $email = null;
5978 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5979 {
5980 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5981 }
5982 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5983 {
5984 $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]));
5985 }
5986 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5987 {
5988 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5989 }
5990 if ($name !== null || $email !== null || $uri !== null)
5991 {
5992 $contributors[] =& new $this->item->feed->author_class($name, $uri, $email);
5993 }
5994 }
5995 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
5996 {
5997 $name = null;
5998 $url = null;
5999 $email = null;
6000 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
6001 {
6002 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6003 }
6004 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
6005 {
6006 $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]));
6007 }
6008 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6009 {
6010 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6011 }
6012 if ($name !== null || $email !== null || $url !== null)
6013 {
6014 $contributors[] =& new $this->item->feed->author_class($name, $url, $email);
6015 }
6016 }
6017
6018 if (!empty($contributors))
6019 {
6020 return SimplePie_Misc::array_unique($contributors);
6021 }
6022 else
6023 {
6024 return null;
6025 }
6026 }
6027
6028 function get_link($key = 0, $rel = 'alternate')
6029 {
6030 $links = $this->get_links($rel);
6031 if (isset($links[$key]))
6032 {
6033 return $links[$key];
6034 }
6035 else
6036 {
6037 return null;
6038 }
6039 }
6040
6041 /**
6042 * Added for parity between the parent-level and the item/entry-level.
6043 */
6044 function get_permalink()
6045 {
6046 return $this->get_link(0);
6047 }
6048
6049 function get_links($rel = 'alternate')
6050 {
6051 if (!isset($this->data['links']))
6052 {
6053 $this->data['links'] = array();
6054 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
6055 {
6056 foreach ($links as $link)
6057 {
6058 if (isset($link['attribs']['']['href']))
6059 {
6060 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6061 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6062 }
6063 }
6064 }
6065 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
6066 {
6067 foreach ($links as $link)
6068 {
6069 if (isset($link['attribs']['']['href']))
6070 {
6071 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6072 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6073
6074 }
6075 }
6076 }
6077 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
6078 {
6079 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6080 }
6081 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
6082 {
6083 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6084 }
6085 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
6086 {
6087 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6088 }
6089
6090 $keys = array_keys($this->data['links']);
6091 foreach ($keys as $key)
6092 {
6093 if (SimplePie_Misc::is_isegment_nz_nc($key))
6094 {
6095 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
6096 {
6097 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
6098 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
6099 }
6100 else
6101 {
6102 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
6103 }
6104 }
6105 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
6106 {
6107 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
6108 }
6109 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
6110 }
6111 }
6112
6113 if (isset($this->data['links'][$rel]))
6114 {
6115 return $this->data['links'][$rel];
6116 }
6117 else
6118 {
6119 return null;
6120 }
6121 }
6122
6123 function get_description()
6124 {
6125 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
6126 {
6127 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6128 }
6129 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
6130 {
6131 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6132 }
6133 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
6134 {
6135 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6136 }
6137 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
6138 {
6139 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6140 }
6141 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
6142 {
6143 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6144 }
6145 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
6146 {
6147 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6148 }
6149 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
6150 {
6151 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6152 }
6153 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
6154 {
6155 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6156 }
6157 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
6158 {
6159 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6160 }
6161 else
6162 {
6163 return null;
6164 }
6165 }
6166
6167 function get_copyright()
6168 {
6169 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
6170 {
6171 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6172 }
6173 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
6174 {
6175 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6176 }
6177 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
6178 {
6179 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6180 }
6181 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
6182 {
6183 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6184 }
6185 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
6186 {
6187 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6188 }
6189 else
6190 {
6191 return null;
6192 }
6193 }
6194
6195 function get_language()
6196 {
6197 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
6198 {
6199 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6200 }
6201 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
6202 {
6203 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6204 }
6205 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
6206 {
6207 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6208 }
6209 elseif (isset($this->data['xml_lang']))
6210 {
6211 return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
6212 }
6213 else
6214 {
6215 return null;
6216 }
6217 }
6218
6219 function get_latitude()
6220 {
6221 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
6222 {
6223 return (float) $return[0]['data'];
6224 }
6225 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
6226 {
6227 return (float) $match[1];
6228 }
6229 else
6230 {
6231 return null;
6232 }
6233 }
6234
6235 function get_longitude()
6236 {
6237 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
6238 {
6239 return (float) $return[0]['data'];
6240 }
6241 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
6242 {
6243 return (float) $return[0]['data'];
6244 }
6245 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
6246 {
6247 return (float) $match[2];
6248 }
6249 else
6250 {
6251 return null;
6252 }
6253 }
6254
6255 function get_image_url()
6256 {
6257 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
6258 {
6259 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
6260 }
6261 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
6262 {
6263 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6264 }
6265 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
6266 {
6267 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6268 }
6269 else
6270 {
6271 return null;
6272 }
6273 }
6274 }
6275
6276 class SimplePie_Author
6277 {
6278 var $name;
6279 var $link;
6280 var $email;
6281
6282 // Constructor, used to input the data
6283 function SimplePie_Author($name = null, $link = null, $email = null)
6284 {
6285 $this->name = $name;
6286 $this->link = $link;
6287 $this->email = $email;
6288 }
6289
6290 function __toString()
6291 {
6292 // There is no $this->data here
6293 return md5(serialize($this));
6294 }
6295
6296 function get_name()
6297 {
6298 if ($this->name !== null)
6299 {
6300 return $this->name;
6301 }
6302 else
6303 {
6304 return null;
6305 }
6306 }
6307
6308 function get_link()
6309 {
6310 if ($this->link !== null)
6311 {
6312 return $this->link;
6313 }
6314 else
6315 {
6316 return null;
6317 }
6318 }
6319
6320 function get_email()
6321 {
6322 if ($this->email !== null)
6323 {
6324 return $this->email;
6325 }
6326 else
6327 {
6328 return null;
6329 }
6330 }
6331 }
6332
6333 class SimplePie_Category
6334 {
6335 var $term;
6336 var $scheme;
6337 var $label;
6338
6339 // Constructor, used to input the data
6340 function SimplePie_Category($term = null, $scheme = null, $label = null)
6341 {
6342 $this->term = $term;
6343 $this->scheme = $scheme;
6344 $this->label = $label;
6345 }
6346
6347 function __toString()
6348 {
6349 // There is no $this->data here
6350 return md5(serialize($this));
6351 }
6352
6353 function get_term()
6354 {
6355 if ($this->term !== null)
6356 {
6357 return $this->term;
6358 }
6359 else
6360 {
6361 return null;
6362 }
6363 }
6364
6365 function get_scheme()
6366 {
6367 if ($this->scheme !== null)
6368 {
6369 return $this->scheme;
6370 }
6371 else
6372 {
6373 return null;
6374 }
6375 }
6376
6377 function get_label()
6378 {
6379 if ($this->label !== null)
6380 {
6381 return $this->label;
6382 }
6383 else
6384 {
6385 return $this->get_term();
6386 }
6387 }
6388 }
6389
6390 class SimplePie_Enclosure
6391 {
6392 var $bitrate;
6393 var $captions;
6394 var $categories;
6395 var $channels;
6396 var $copyright;
6397 var $credits;
6398 var $description;
6399 var $duration;
6400 var $expression;
6401 var $framerate;
6402 var $handler;
6403 var $hashes;
6404 var $height;
6405 var $javascript;
6406 var $keywords;
6407 var $lang;
6408 var $length;
6409 var $link;
6410 var $medium;
6411 var $player;
6412 var $ratings;
6413 var $restrictions;
6414 var $samplingrate;
6415 var $thumbnails;
6416 var $title;
6417 var $type;
6418 var $width;
6419
6420 // Constructor, used to input the data
6421 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)
6422 {
6423 $this->bitrate = $bitrate;
6424 $this->captions = $captions;
6425 $this->categories = $categories;
6426 $this->channels = $channels;
6427 $this->copyright = $copyright;
6428 $this->credits = $credits;
6429 $this->description = $description;
6430 $this->duration = $duration;
6431 $this->expression = $expression;
6432 $this->framerate = $framerate;
6433 $this->hashes = $hashes;
6434 $this->height = $height;
6435 $this->javascript = $javascript;
6436 $this->keywords = $keywords;
6437 $this->lang = $lang;
6438 $this->length = $length;
6439 $this->link = $link;
6440 $this->medium = $medium;
6441 $this->player = $player;
6442 $this->ratings = $ratings;
6443 $this->restrictions = $restrictions;
6444 $this->samplingrate = $samplingrate;
6445 $this->thumbnails = $thumbnails;
6446 $this->title = $title;
6447 $this->type = $type;
6448 $this->width = $width;
6449 if (class_exists('idna_convert'))
6450 {
6451 $idn =& new idna_convert;
6452 $parsed = SimplePie_Misc::parse_url($link);
6453 $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6454 }
6455 $this->handler = $this->get_handler(); // Needs to load last
6456 }
6457
6458 function __toString()
6459 {
6460 // There is no $this->data here
6461 return md5(serialize($this));
6462 }
6463
6464 function get_bitrate()
6465 {
6466 if ($this->bitrate !== null)
6467 {
6468 return $this->bitrate;
6469 }
6470 else
6471 {
6472 return null;
6473 }
6474 }
6475
6476 function get_caption($key = 0)
6477 {
6478 $captions = $this->get_captions();
6479 if (isset($captions[$key]))
6480 {
6481 return $captions[$key];
6482 }
6483 else
6484 {
6485 return null;
6486 }
6487 }
6488
6489 function get_captions()
6490 {
6491 if ($this->captions !== null)
6492 {
6493 return $this->captions;
6494 }
6495 else
6496 {
6497 return null;
6498 }
6499 }
6500
6501 function get_category($key = 0)
6502 {
6503 $categories = $this->get_categories();
6504 if (isset($categories[$key]))
6505 {
6506 return $categories[$key];
6507 }
6508 else
6509 {
6510 return null;
6511 }
6512 }
6513
6514 function get_categories()
6515 {
6516 if ($this->categories !== null)
6517 {
6518 return $this->categories;
6519 }
6520 else
6521 {
6522 return null;
6523 }
6524 }
6525
6526 function get_channels()
6527 {
6528 if ($this->channels !== null)
6529 {
6530 return $this->channels;
6531 }
6532 else
6533 {
6534 return null;
6535 }
6536 }
6537
6538 function get_copyright()
6539 {
6540 if ($this->copyright !== null)
6541 {
6542 return $this->copyright;
6543 }
6544 else
6545 {
6546 return null;
6547 }
6548 }
6549
6550 function get_credit($key = 0)
6551 {
6552 $credits = $this->get_credits();
6553 if (isset($credits[$key]))
6554 {
6555 return $credits[$key];
6556 }
6557 else
6558 {
6559 return null;
6560 }
6561 }
6562
6563 function get_credits()
6564 {
6565 if ($this->credits !== null)
6566 {
6567 return $this->credits;
6568 }
6569 else
6570 {
6571 return null;
6572 }
6573 }
6574
6575 function get_description()
6576 {
6577 if ($this->description !== null)
6578 {
6579 return $this->description;
6580 }
6581 else
6582 {
6583 return null;
6584 }
6585 }
6586
6587 function get_duration($convert = false)
6588 {
6589 if ($this->duration !== null)
6590 {
6591 if ($convert)
6592 {
6593 $time = SimplePie_Misc::time_hms($this->duration);
6594 return $time;
6595 }
6596 else
6597 {
6598 return $this->duration;
6599 }
6600 }
6601 else
6602 {
6603 return null;
6604 }
6605 }
6606
6607 function get_expression()
6608 {
6609 if ($this->expression !== null)
6610 {
6611 return $this->expression;
6612 }
6613 else
6614 {
6615 return 'full';
6616 }
6617 }
6618
6619 function get_extension()
6620 {
6621 if ($this->link !== null)
6622 {
6623 $url = SimplePie_Misc::parse_url($this->link);
6624 if ($url['path'] !== '')
6625 {
6626 return pathinfo($url['path'], PATHINFO_EXTENSION);
6627 }
6628 }
6629 return null;
6630 }
6631
6632 function get_framerate()
6633 {
6634 if ($this->framerate !== null)
6635 {
6636 return $this->framerate;
6637 }
6638 else
6639 {
6640 return null;
6641 }
6642 }
6643
6644 function get_handler()
6645 {
6646 return $this->get_real_type(true);
6647 }
6648
6649 function get_hash($key = 0)
6650 {
6651 $hashes = $this->get_hashes();
6652 if (isset($hashes[$key]))
6653 {
6654 return $hashes[$key];
6655 }
6656 else
6657 {
6658 return null;
6659 }
6660 }
6661
6662 function get_hashes()
6663 {
6664 if ($this->hashes !== null)
6665 {
6666 return $this->hashes;
6667 }
6668 else
6669 {
6670 return null;
6671 }
6672 }
6673
6674 function get_height()
6675 {
6676 if ($this->height !== null)
6677 {
6678 return $this->height;
6679 }
6680 else
6681 {
6682 return null;
6683 }
6684 }
6685
6686 function get_language()
6687 {
6688 if ($this->lang !== null)
6689 {
6690 return $this->lang;
6691 }
6692 else
6693 {
6694 return null;
6695 }
6696 }
6697
6698 function get_keyword($key = 0)
6699 {
6700 $keywords = $this->get_keywords();
6701 if (isset($keywords[$key]))
6702 {
6703 return $keywords[$key];
6704 }
6705 else
6706 {
6707 return null;
6708 }
6709 }
6710
6711 function get_keywords()
6712 {
6713 if ($this->keywords !== null)
6714 {
6715 return $this->keywords;
6716 }
6717 else
6718 {
6719 return null;
6720 }
6721 }
6722
6723 function get_length()
6724 {
6725 if ($this->length !== null)
6726 {
6727 return $this->length;
6728 }
6729 else
6730 {
6731 return null;
6732 }
6733 }
6734
6735 function get_link()
6736 {
6737 if ($this->link !== null)
6738 {
6739 return urldecode($this->link);
6740 }
6741 else
6742 {
6743 return null;
6744 }
6745 }
6746
6747 function get_medium()
6748 {
6749 if ($this->medium !== null)
6750 {
6751 return $this->medium;
6752 }
6753 else
6754 {
6755 return null;
6756 }
6757 }
6758
6759 function get_player()
6760 {
6761 if ($this->player !== null)
6762 {
6763 return $this->player;
6764 }
6765 else
6766 {
6767 return null;
6768 }
6769 }
6770
6771 function get_rating($key = 0)
6772 {
6773 $ratings = $this->get_ratings();
6774 if (isset($ratings[$key]))
6775 {
6776 return $ratings[$key];
6777 }
6778 else
6779 {
6780 return null;
6781 }
6782 }
6783
6784 function get_ratings()
6785 {
6786 if ($this->ratings !== null)
6787 {
6788 return $this->ratings;
6789 }
6790 else
6791 {
6792 return null;
6793 }
6794 }
6795
6796 function get_restriction($key = 0)
6797 {
6798 $restrictions = $this->get_restrictions();
6799 if (isset($restrictions[$key]))
6800 {
6801 return $restrictions[$key];
6802 }
6803 else
6804 {
6805 return null;
6806 }
6807 }
6808
6809 function get_restrictions()
6810 {
6811 if ($this->restrictions !== null)
6812 {
6813 return $this->restrictions;
6814 }
6815 else
6816 {
6817 return null;
6818 }
6819 }
6820
6821 function get_sampling_rate()
6822 {
6823 if ($this->samplingrate !== null)
6824 {
6825 return $this->samplingrate;
6826 }
6827 else
6828 {
6829 return null;
6830 }
6831 }
6832
6833 function get_size()
6834 {
6835 $length = $this->get_length();
6836 if ($length !== null)
6837 {
6838 return round($length/1048576, 2);
6839 }
6840 else
6841 {
6842 return null;
6843 }
6844 }
6845
6846 function get_thumbnail($key = 0)
6847 {
6848 $thumbnails = $this->get_thumbnails();
6849 if (isset($thumbnails[$key]))
6850 {
6851 return $thumbnails[$key];
6852 }
6853 else
6854 {
6855 return null;
6856 }
6857 }
6858
6859 function get_thumbnails()
6860 {
6861 if ($this->thumbnails !== null)
6862 {
6863 return $this->thumbnails;
6864 }
6865 else
6866 {
6867 return null;
6868 }
6869 }
6870
6871 function get_title()
6872 {
6873 if ($this->title !== null)
6874 {
6875 return $this->title;
6876 }
6877 else
6878 {
6879 return null;
6880 }
6881 }
6882
6883 function get_type()
6884 {
6885 if ($this->type !== null)
6886 {
6887 return $this->type;
6888 }
6889 else
6890 {
6891 return null;
6892 }
6893 }
6894
6895 function get_width()
6896 {
6897 if ($this->width !== null)
6898 {
6899 return $this->width;
6900 }
6901 else
6902 {
6903 return null;
6904 }
6905 }
6906
6907 function native_embed($options='')
6908 {
6909 return $this->embed($options, true);
6910 }
6911
6912 /**
6913 * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
6914 */
6915 function embed($options = '', $native = false)
6916 {
6917 // Set up defaults
6918 $audio = '';
6919 $video = '';
6920 $alt = '';
6921 $altclass = '';
6922 $loop = 'false';
6923 $width = 'auto';
6924 $height = 'auto';
6925 $bgcolor = '#ffffff';
6926 $mediaplayer = '';
6927 $widescreen = false;
6928 $handler = $this->get_handler();
6929 $type = $this->get_real_type();
6930
6931 // Process options and reassign values as necessary
6932 if (is_array($options))
6933 {
6934 extract($options);
6935 }
6936 else
6937 {
6938 $options = explode(',', $options);
6939 foreach($options as $option)
6940 {
6941 $opt = explode(':', $option, 2);
6942 if (isset($opt[0], $opt[1]))
6943 {
6944 $opt[0] = trim($opt[0]);
6945 $opt[1] = trim($opt[1]);
6946 switch ($opt[0])
6947 {
6948 case 'audio':
6949 $audio = $opt[1];
6950 break;
6951
6952 case 'video':
6953 $video = $opt[1];
6954 break;
6955
6956 case 'alt':
6957 $alt = $opt[1];
6958 break;
6959
6960 case 'altclass':
6961 $altclass = $opt[1];
6962 break;
6963
6964 case 'loop':
6965 $loop = $opt[1];
6966 break;
6967
6968 case 'width':
6969 $width = $opt[1];
6970 break;
6971
6972 case 'height':
6973 $height = $opt[1];
6974 break;
6975
6976 case 'bgcolor':
6977 $bgcolor = $opt[1];
6978 break;
6979
6980 case 'mediaplayer':
6981 $mediaplayer = $opt[1];
6982 break;
6983
6984 case 'widescreen':
6985 $widescreen = $opt[1];
6986 break;
6987 }
6988 }
6989 }
6990 }
6991
6992 $mime = explode('/', $type, 2);
6993 $mime = $mime[0];
6994
6995 // Process values for 'auto'
6996 if ($width === 'auto')
6997 {
6998 if ($mime === 'video')
6999 {
7000 if ($height === 'auto')
7001 {
7002 $width = 480;
7003 }
7004 elseif ($widescreen)
7005 {
7006 $width = round((intval($height)/9)*16);
7007 }
7008 else
7009 {
7010 $width = round((intval($height)/3)*4);
7011 }
7012 }
7013 else
7014 {
7015 $width = '100%';
7016 }
7017 }
7018
7019 if ($height === 'auto')
7020 {
7021 if ($mime === 'audio')
7022 {
7023 $height = 0;
7024 }
7025 elseif ($mime === 'video')
7026 {
7027 if ($width === 'auto')
7028 {
7029 if ($widescreen)
7030 {
7031 $height = 270;
7032 }
7033 else
7034 {
7035 $height = 360;
7036 }
7037 }
7038 elseif ($widescreen)
7039 {
7040 $height = round((intval($width)/16)*9);
7041 }
7042 else
7043 {
7044 $height = round((intval($width)/4)*3);
7045 }
7046 }
7047 else
7048 {
7049 $height = 376;
7050 }
7051 }
7052 elseif ($mime === 'audio')
7053 {
7054 $height = 0;
7055 }
7056
7057 // Set proper placeholder value
7058 if ($mime === 'audio')
7059 {
7060 $placeholder = $audio;
7061 }
7062 elseif ($mime === 'video')
7063 {
7064 $placeholder = $video;
7065 }
7066
7067 $embed = '';
7068
7069 // Make sure the JS library is included
7070 if (!$native)
7071 {
7072 static $javascript_outputted = null;
7073 if (!$javascript_outputted && $this->javascript)
7074 {
7075 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
7076 $javascript_outputted = true;
7077 }
7078 }
7079
7080 // Odeo Feed MP3's
7081 if ($handler === 'odeo')
7082 {
7083 if ($native)
7084 {
7085 $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>';
7086 }
7087 else
7088 {
7089 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
7090 }
7091 }
7092
7093 // Flash
7094 elseif ($handler === 'flash')
7095 {
7096 if ($native)
7097 {
7098 $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>";
7099 }
7100 else
7101 {
7102 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
7103 }
7104 }
7105
7106 // Flash Media Player file types.
7107 // Preferred handler for MP3 file types.
7108 elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
7109 {
7110 $height += 20;
7111 if ($native)
7112 {
7113 $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>";
7114 }
7115 else
7116 {
7117 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7118 }
7119 }
7120
7121 // QuickTime 7 file types. Need to test with QuickTime 6.
7122 // Only handle MP3's if the Flash Media Player is not present.
7123 elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
7124 {
7125 $height += 16;
7126 if ($native)
7127 {
7128 if ($placeholder !== '')
7129 {
7130 $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>";
7131 }
7132 else
7133 {
7134 $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>";
7135 }
7136 }
7137 else
7138 {
7139 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7140 }
7141 }
7142
7143 // Windows Media
7144 elseif ($handler === 'wmedia')
7145 {
7146 $height += 45;
7147 if ($native)
7148 {
7149 $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>";
7150 }
7151 else
7152 {
7153 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7154 }
7155 }
7156
7157 // Everything else
7158 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7159
7160 return $embed;
7161 }
7162
7163 function get_real_type($find_handler = false)
7164 {
7165 // If it's Odeo, let's get it out of the way.
7166 if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
7167 {
7168 return 'odeo';
7169 }
7170
7171 // Mime-types by handler.
7172 $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
7173 $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
7174 $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
7175 $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
7176 $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7177
7178 if ($this->get_type() !== null)
7179 {
7180 $type = strtolower($this->type);
7181 }
7182 else
7183 {
7184 $type = null;
7185 }
7186
7187 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7188 if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7189 {
7190 switch (strtolower($this->get_extension()))
7191 {
7192 // Audio mime-types
7193 case 'aac':
7194 case 'adts':
7195 $type = 'audio/acc';
7196 break;
7197
7198 case 'aif':
7199 case 'aifc':
7200 case 'aiff':
7201 case 'cdda':
7202 $type = 'audio/aiff';
7203 break;
7204
7205 case 'bwf':
7206 $type = 'audio/wav';
7207 break;
7208
7209 case 'kar':
7210 case 'mid':
7211 case 'midi':
7212 case 'smf':
7213 $type = 'audio/midi';
7214 break;
7215
7216 case 'm4a':
7217 $type = 'audio/x-m4a';
7218 break;
7219
7220 case 'mp3':
7221 case 'swa':
7222 $type = 'audio/mp3';
7223 break;
7224
7225 case 'wav':
7226 $type = 'audio/wav';
7227 break;
7228
7229 case 'wax':
7230 $type = 'audio/x-ms-wax';
7231 break;
7232
7233 case 'wma':
7234 $type = 'audio/x-ms-wma';
7235 break;
7236
7237 // Video mime-types
7238 case '3gp':
7239 case '3gpp':
7240 $type = 'video/3gpp';
7241 break;
7242
7243 case '3g2':
7244 case '3gp2':
7245 $type = 'video/3gpp2';
7246 break;
7247
7248 case 'asf':
7249 $type = 'video/x-ms-asf';
7250 break;
7251
7252 case 'flv':
7253 $type = 'video/x-flv';
7254 break;
7255
7256 case 'm1a':
7257 case 'm1s':
7258 case 'm1v':
7259 case 'm15':
7260 case 'm75':
7261 case 'mp2':
7262 case 'mpa':
7263 case 'mpeg':
7264 case 'mpg':
7265 case 'mpm':
7266 case 'mpv':
7267 $type = 'video/mpeg';
7268 break;
7269
7270 case 'm4v':
7271 $type = 'video/x-m4v';
7272 break;
7273
7274 case 'mov':
7275 case 'qt':
7276 $type = 'video/quicktime';
7277 break;
7278
7279 case 'mp4':
7280 case 'mpg4':
7281 $type = 'video/mp4';
7282 break;
7283
7284 case 'sdv':
7285 $type = 'video/sd-video';
7286 break;
7287
7288 case 'wm':
7289 $type = 'video/x-ms-wm';
7290 break;
7291
7292 case 'wmv':
7293 $type = 'video/x-ms-wmv';
7294 break;
7295
7296 case 'wvx':
7297 $type = 'video/x-ms-wvx';
7298 break;
7299
7300 // Flash mime-types
7301 case 'spl':
7302 $type = 'application/futuresplash';
7303 break;
7304
7305 case 'swf':
7306 $type = 'application/x-shockwave-flash';
7307 break;
7308 }
7309 }
7310
7311 if ($find_handler)
7312 {
7313 if (in_array($type, $types_flash))
7314 {
7315 return 'flash';
7316 }
7317 elseif (in_array($type, $types_fmedia))
7318 {
7319 return 'fmedia';
7320 }
7321 elseif (in_array($type, $types_quicktime))
7322 {
7323 return 'quicktime';
7324 }
7325 elseif (in_array($type, $types_wmedia))
7326 {
7327 return 'wmedia';
7328 }
7329 elseif (in_array($type, $types_mp3))
7330 {
7331 return 'mp3';
7332 }
7333 else
7334 {
7335 return null;
7336 }
7337 }
7338 else
7339 {
7340 return $type;
7341 }
7342 }
7343 }
7344
7345 class SimplePie_Caption
7346 {
7347 var $type;
7348 var $lang;
7349 var $startTime;
7350 var $endTime;
7351 var $text;
7352
7353 // Constructor, used to input the data
7354 function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7355 {
7356 $this->type = $type;
7357 $this->lang = $lang;
7358 $this->startTime = $startTime;
7359 $this->endTime = $endTime;
7360 $this->text = $text;
7361 }
7362
7363 function __toString()
7364 {
7365 // There is no $this->data here
7366 return md5(serialize($this));
7367 }
7368
7369 function get_endtime()
7370 {
7371 if ($this->endTime !== null)
7372 {
7373 return $this->endTime;
7374 }
7375 else
7376 {
7377 return null;
7378 }
7379 }
7380
7381 function get_language()
7382 {
7383 if ($this->lang !== null)
7384 {
7385 return $this->lang;
7386 }
7387 else
7388 {
7389 return null;
7390 }
7391 }
7392
7393 function get_starttime()
7394 {
7395 if ($this->startTime !== null)
7396 {
7397 return $this->startTime;
7398 }
7399 else
7400 {
7401 return null;
7402 }
7403 }
7404
7405 function get_text()
7406 {
7407 if ($this->text !== null)
7408 {
7409 return $this->text;
7410 }
7411 else
7412 {
7413 return null;
7414 }
7415 }
7416
7417 function get_type()
7418 {
7419 if ($this->type !== null)
7420 {
7421 return $this->type;
7422 }
7423 else
7424 {
7425 return null;
7426 }
7427 }
7428 }
7429
7430 class SimplePie_Credit
7431 {
7432 var $role;
7433 var $scheme;
7434 var $name;
7435
7436 // Constructor, used to input the data
7437 function SimplePie_Credit($role = null, $scheme = null, $name = null)
7438 {
7439 $this->role = $role;
7440 $this->scheme = $scheme;
7441 $this->name = $name;
7442 }
7443
7444 function __toString()
7445 {
7446 // There is no $this->data here
7447 return md5(serialize($this));
7448 }
7449
7450 function get_role()
7451 {
7452 if ($this->role !== null)
7453 {
7454 return $this->role;
7455 }
7456 else
7457 {
7458 return null;
7459 }
7460 }
7461
7462 function get_scheme()
7463 {
7464 if ($this->scheme !== null)
7465 {
7466 return $this->scheme;
7467 }
7468 else
7469 {
7470 return null;
7471 }
7472 }
7473
7474 function get_name()
7475 {
7476 if ($this->name !== null)
7477 {
7478 return $this->name;
7479 }
7480 else
7481 {
7482 return null;
7483 }
7484 }
7485 }
7486
7487 class SimplePie_Copyright
7488 {
7489 var $url;
7490 var $label;
7491
7492 // Constructor, used to input the data
7493 function SimplePie_Copyright($url = null, $label = null)
7494 {
7495 $this->url = $url;
7496 $this->label = $label;
7497 }
7498
7499 function __toString()
7500 {
7501 // There is no $this->data here
7502 return md5(serialize($this));
7503 }
7504
7505 function get_url()
7506 {
7507 if ($this->url !== null)
7508 {
7509 return $this->url;
7510 }
7511 else
7512 {
7513 return null;
7514 }
7515 }
7516
7517 function get_attribution()
7518 {
7519 if ($this->label !== null)
7520 {
7521 return $this->label;
7522 }
7523 else
7524 {
7525 return null;
7526 }
7527 }
7528 }
7529
7530 class SimplePie_Rating
7531 {
7532 var $scheme;
7533 var $value;
7534
7535 // Constructor, used to input the data
7536 function SimplePie_Rating($scheme = null, $value = null)
7537 {
7538 $this->scheme = $scheme;
7539 $this->value = $value;
7540 }
7541
7542 function __toString()
7543 {
7544 // There is no $this->data here
7545 return md5(serialize($this));
7546 }
7547
7548 function get_scheme()
7549 {
7550 if ($this->scheme !== null)
7551 {
7552 return $this->scheme;
7553 }
7554 else
7555 {
7556 return null;
7557 }
7558 }
7559
7560 function get_value()
7561 {
7562 if ($this->value !== null)
7563 {
7564 return $this->value;
7565 }
7566 else
7567 {
7568 return null;
7569 }
7570 }
7571 }
7572
7573 class SimplePie_Restriction
7574 {
7575 var $relationship;
7576 var $type;
7577 var $value;
7578
7579 // Constructor, used to input the data
7580 function SimplePie_Restriction($relationship = null, $type = null, $value = null)
7581 {
7582 $this->relationship = $relationship;
7583 $this->type = $type;
7584 $this->value = $value;
7585 }
7586
7587 function __toString()
7588 {
7589 // There is no $this->data here
7590 return md5(serialize($this));
7591 }
7592
7593 function get_relationship()
7594 {
7595 if ($this->relationship !== null)
7596 {
7597 return $this->relationship;
7598 }
7599 else
7600 {
7601 return null;
7602 }
7603 }
7604
7605 function get_type()
7606 {
7607 if ($this->type !== null)
7608 {
7609 return $this->type;
7610 }
7611 else
7612 {
7613 return null;
7614 }
7615 }
7616
7617 function get_value()
7618 {
7619 if ($this->value !== null)
7620 {
7621 return $this->value;
7622 }
7623 else
7624 {
7625 return null;
7626 }
7627 }
7628 }
7629
7630 /**
7631 * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7632 */
7633 class SimplePie_File
7634 {
7635 var $url;
7636 var $useragent;
7637 var $success = true;
7638 var $headers = array();
7639 var $body;
7640 var $status_code;
7641 var $redirects = 0;
7642 var $error;
7643 var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7644
7645 function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7646 {
7647 if (class_exists('idna_convert'))
7648 {
7649 $idn =& new idna_convert;
7650 $parsed = SimplePie_Misc::parse_url($url);
7651 $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7652 }
7653 $this->url = $url;
7654 $this->useragent = $useragent;
7655 if (preg_match('/^http(s)?:\/\//i', $url))
7656 {
7657 if ($useragent === null)
7658 {
7659 $useragent = ini_get('user_agent');
7660 $this->useragent = $useragent;
7661 }
7662 if (!is_array($headers))
7663 {
7664 $headers = array();
7665 }
7666 if (!$force_fsockopen && function_exists('curl_exec'))
7667 {
7668 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7669 $fp = curl_init();
7670 $headers2 = array();
7671 foreach ($headers as $key => $value)
7672 {
7673 $headers2[] = "$key: $value";
7674 }
7675 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7676 {
7677 curl_setopt($fp, CURLOPT_ENCODING, '');
7678 }
7679 curl_setopt($fp, CURLOPT_URL, $url);
7680 curl_setopt($fp, CURLOPT_HEADER, 1);
7681 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7682 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7683 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7684 curl_setopt($fp, CURLOPT_REFERER, $url);
7685 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7686 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7687 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7688 {
7689 curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7690 curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7691 }
7692
7693 /* Enable Digest authentication and SSL -fox */
7694 curl_setopt($fp, CURLOPT_SSL_VERIFYPEER, false);
7695 curl_setopt($fp, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
7696
7697 $this->headers = curl_exec($fp);
7698 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7699 {
7700 curl_setopt($fp, CURLOPT_ENCODING, 'none');
7701 $this->headers = curl_exec($fp);
7702 }
7703 if (curl_errno($fp))
7704 {
7705 $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7706 $this->success = false;
7707 }
7708 else
7709 {
7710 $info = curl_getinfo($fp);
7711 curl_close($fp);
7712 $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7713 $this->headers = array_pop($this->headers);
7714 $parser =& new SimplePie_HTTP_Parser($this->headers);
7715 if ($parser->parse())
7716 {
7717 $this->headers = $parser->headers;
7718 $this->body = $parser->body;
7719 $this->status_code = $parser->status_code;
7720 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)
7721 {
7722 $this->redirects++;
7723 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7724 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7725 }
7726 }
7727 }
7728 }
7729 else
7730 {
7731 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7732 $url_parts = parse_url($url);
7733 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7734 {
7735 $url_parts['host'] = "ssl://$url_parts[host]";
7736 $url_parts['port'] = 443;
7737 }
7738 if (!isset($url_parts['port']))
7739 {
7740 $url_parts['port'] = 80;
7741 }
7742 $fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
7743 if (!$fp)
7744 {
7745 $this->error = 'fsockopen error: ' . $errstr;
7746 $this->success = false;
7747 }
7748 else
7749 {
7750 stream_set_timeout($fp, $timeout);
7751 if (isset($url_parts['path']))
7752 {
7753 if (isset($url_parts['query']))
7754 {
7755 $get = "$url_parts[path]?$url_parts[query]";
7756 }
7757 else
7758 {
7759 $get = $url_parts['path'];
7760 }
7761 }
7762 else
7763 {
7764 $get = '/';
7765 }
7766 $out = "GET $get HTTP/1.0\r\n";
7767 $out .= "Host: $url_parts[host]\r\n";
7768 $out .= "User-Agent: $useragent\r\n";
7769 if (extension_loaded('zlib'))
7770 {
7771 $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7772 }
7773
7774 if (isset($url_parts['user']) && isset($url_parts['pass']))
7775 {
7776 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7777 }
7778 foreach ($headers as $key => $value)
7779 {
7780 $out .= "$key: $value\r\n";
7781 }
7782 $out .= "Connection: Close\r\n\r\n";
7783 fwrite($fp, $out);
7784
7785 $info = stream_get_meta_data($fp);
7786
7787 $this->headers = '';
7788 while (!$info['eof'] && !$info['timed_out'])
7789 {
7790 $this->headers .= fread($fp, 1160);
7791 $info = stream_get_meta_data($fp);
7792 }
7793 if (!$info['timed_out'])
7794 {
7795 $parser =& new SimplePie_HTTP_Parser($this->headers);
7796 if ($parser->parse())
7797 {
7798 $this->headers = $parser->headers;
7799 $this->body = $parser->body;
7800 $this->status_code = $parser->status_code;
7801 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)
7802 {
7803 $this->redirects++;
7804 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7805 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7806 }
7807 if (isset($this->headers['content-encoding']))
7808 {
7809 // Hey, we act dumb elsewhere, so let's do that here too
7810 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7811 {
7812 case 'gzip':
7813 case 'x-gzip':
7814 $decoder =& new SimplePie_gzdecode($this->body);
7815 if (!$decoder->parse())
7816 {
7817 $this->error = 'Unable to decode HTTP "gzip" stream';
7818 $this->success = false;
7819 }
7820 else
7821 {
7822 $this->body = $decoder->data;
7823 }
7824 break;
7825
7826 case 'deflate':
7827 if (($body = gzuncompress($this->body)) === false)
7828 {
7829 if (($body = gzinflate($this->body)) === false)
7830 {
7831 $this->error = 'Unable to decode HTTP "deflate" stream';
7832 $this->success = false;
7833 }
7834 }
7835 $this->body = $body;
7836 break;
7837
7838 default:
7839 $this->error = 'Unknown content coding';
7840 $this->success = false;
7841 }
7842 }
7843 }
7844 }
7845 else
7846 {
7847 $this->error = 'fsocket timed out';
7848 $this->success = false;
7849 }
7850 fclose($fp);
7851 }
7852 }
7853 }
7854 else
7855 {
7856 $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7857 if (!$this->body = file_get_contents($url))
7858 {
7859 $this->error = 'file_get_contents could not read the file';
7860 $this->success = false;
7861 }
7862 }
7863 }
7864 }
7865
7866 /**
7867 * HTTP Response Parser
7868 *
7869 * @package SimplePie
7870 */
7871 class SimplePie_HTTP_Parser
7872 {
7873 /**
7874 * HTTP Version
7875 *
7876 * @access public
7877 * @var float
7878 */
7879 var $http_version = 0.0;
7880
7881 /**
7882 * Status code
7883 *
7884 * @access public
7885 * @var int
7886 */
7887 var $status_code = 0;
7888
7889 /**
7890 * Reason phrase
7891 *
7892 * @access public
7893 * @var string
7894 */
7895 var $reason = '';
7896
7897 /**
7898 * Key/value pairs of the headers
7899 *
7900 * @access public
7901 * @var array
7902 */
7903 var $headers = array();
7904
7905 /**
7906 * Body of the response
7907 *
7908 * @access public
7909 * @var string
7910 */
7911 var $body = '';
7912
7913 /**
7914 * Current state of the state machine
7915 *
7916 * @access private
7917 * @var string
7918 */
7919 var $state = 'http_version';
7920
7921 /**
7922 * Input data
7923 *
7924 * @access private
7925 * @var string
7926 */
7927 var $data = '';
7928
7929 /**
7930 * Input data length (to avoid calling strlen() everytime this is needed)
7931 *
7932 * @access private
7933 * @var int
7934 */
7935 var $data_length = 0;
7936
7937 /**
7938 * Current position of the pointer
7939 *
7940 * @var int
7941 * @access private
7942 */
7943 var $position = 0;
7944
7945 /**
7946 * Name of the hedaer currently being parsed
7947 *
7948 * @access private
7949 * @var string
7950 */
7951 var $name = '';
7952
7953 /**
7954 * Value of the hedaer currently being parsed
7955 *
7956 * @access private
7957 * @var string
7958 */
7959 var $value = '';
7960
7961 /**
7962 * Create an instance of the class with the input data
7963 *
7964 * @access public
7965 * @param string $data Input data
7966 */
7967 function SimplePie_HTTP_Parser($data)
7968 {
7969 $this->data = $data;
7970 $this->data_length = strlen($this->data);
7971 }
7972
7973 /**
7974 * Parse the input data
7975 *
7976 * @access public
7977 * @return bool true on success, false on failure
7978 */
7979 function parse()
7980 {
7981 while ($this->state && $this->state !== 'emit' && $this->has_data())
7982 {
7983 $state = $this->state;
7984 $this->$state();
7985 }
7986 $this->data = '';
7987 if ($this->state === 'emit' || $this->state === 'body')
7988 {
7989 return true;
7990 }
7991 else
7992 {
7993 $this->http_version = '';
7994 $this->status_code = '';
7995 $this->reason = '';
7996 $this->headers = array();
7997 $this->body = '';
7998 return false;
7999 }
8000 }
8001
8002 /**
8003 * Check whether there is data beyond the pointer
8004 *
8005 * @access private
8006 * @return bool true if there is further data, false if not
8007 */
8008 function has_data()
8009 {
8010 return (bool) ($this->position < $this->data_length);
8011 }
8012
8013 /**
8014 * See if the next character is LWS
8015 *
8016 * @access private
8017 * @return bool true if the next character is LWS, false if not
8018 */
8019 function is_linear_whitespace()
8020 {
8021 return (bool) ($this->data[$this->position] === "\x09"
8022 || $this->data[$this->position] === "\x20"
8023 || ($this->data[$this->position] === "\x0A"
8024 && isset($this->data[$this->position + 1])
8025 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
8026 }
8027
8028 /**
8029 * Parse the HTTP version
8030 *
8031 * @access private
8032 */
8033 function http_version()
8034 {
8035 if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
8036 {
8037 $len = strspn($this->data, '0123456789.', 5);
8038 $this->http_version = substr($this->data, 5, $len);
8039 $this->position += 5 + $len;
8040 if (substr_count($this->http_version, '.') <= 1)
8041 {
8042 $this->http_version = (float) $this->http_version;
8043 $this->position += strspn($this->data, "\x09\x20", $this->position);
8044 $this->state = 'status';
8045 }
8046 else
8047 {
8048 $this->state = false;
8049 }
8050 }
8051 else
8052 {
8053 $this->state = false;
8054 }
8055 }
8056
8057 /**
8058 * Parse the status code
8059 *
8060 * @access private
8061 */
8062 function status()
8063 {
8064 if ($len = strspn($this->data, '0123456789', $this->position))
8065 {
8066 $this->status_code = (int) substr($this->data, $this->position, $len);
8067 $this->position += $len;
8068 $this->state = 'reason';
8069 }
8070 else
8071 {
8072 $this->state = false;
8073 }
8074 }
8075
8076 /**
8077 * Parse the reason phrase
8078 *
8079 * @access private
8080 */
8081 function reason()
8082 {
8083 $len = strcspn($this->data, "\x0A", $this->position);
8084 $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
8085 $this->position += $len + 1;
8086 $this->state = 'new_line';
8087 }
8088
8089 /**
8090 * Deal with a new line, shifting data around as needed
8091 *
8092 * @access private
8093 */
8094 function new_line()
8095 {
8096 $this->value = trim($this->value, "\x0D\x20");
8097 if ($this->name !== '' && $this->value !== '')
8098 {
8099 $this->name = strtolower($this->name);
8100 if (isset($this->headers[$this->name]))
8101 {
8102 $this->headers[$this->name] .= ', ' . $this->value;
8103 }
8104 else
8105 {
8106 $this->headers[$this->name] = $this->value;
8107 }
8108 }
8109 $this->name = '';
8110 $this->value = '';
8111 if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
8112 {
8113 $this->position += 2;
8114 $this->state = 'body';
8115 }
8116 elseif ($this->data[$this->position] === "\x0A")
8117 {
8118 $this->position++;
8119 $this->state = 'body';
8120 }
8121 else
8122 {
8123 $this->state = 'name';
8124 }
8125 }
8126
8127 /**
8128 * Parse a header name
8129 *
8130 * @access private
8131 */
8132 function name()
8133 {
8134 $len = strcspn($this->data, "\x0A:", $this->position);
8135 if (isset($this->data[$this->position + $len]))
8136 {
8137 if ($this->data[$this->position + $len] === "\x0A")
8138 {
8139 $this->position += $len;
8140 $this->state = 'new_line';
8141 }
8142 else
8143 {
8144 $this->name = substr($this->data, $this->position, $len);
8145 $this->position += $len + 1;
8146 $this->state = 'value';
8147 }
8148 }
8149 else
8150 {
8151 $this->state = false;
8152 }
8153 }
8154
8155 /**
8156 * Parse LWS, replacing consecutive LWS characters with a single space
8157 *
8158 * @access private
8159 */
8160 function linear_whitespace()
8161 {
8162 do
8163 {
8164 if (substr($this->data, $this->position, 2) === "\x0D\x0A")
8165 {
8166 $this->position += 2;
8167 }
8168 elseif ($this->data[$this->position] === "\x0A")
8169 {
8170 $this->position++;
8171 }
8172 $this->position += strspn($this->data, "\x09\x20", $this->position);
8173 } while ($this->has_data() && $this->is_linear_whitespace());
8174 $this->value .= "\x20";
8175 }
8176
8177 /**
8178 * See what state to move to while within non-quoted header values
8179 *
8180 * @access private
8181 */
8182 function value()
8183 {
8184 if ($this->is_linear_whitespace())
8185 {
8186 $this->linear_whitespace();
8187 }
8188 else
8189 {
8190 switch ($this->data[$this->position])
8191 {
8192 case '"':
8193 $this->position++;
8194 $this->state = 'quote';
8195 break;
8196
8197 case "\x0A":
8198 $this->position++;
8199 $this->state = 'new_line';
8200 break;
8201
8202 default:
8203 $this->state = 'value_char';
8204 break;
8205 }
8206 }
8207 }
8208
8209 /**
8210 * Parse a header value while outside quotes
8211 *
8212 * @access private
8213 */
8214 function value_char()
8215 {
8216 $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
8217 $this->value .= substr($this->data, $this->position, $len);
8218 $this->position += $len;
8219 $this->state = 'value';
8220 }
8221
8222 /**
8223 * See what state to move to while within quoted header values
8224 *
8225 * @access private
8226 */
8227 function quote()
8228 {
8229 if ($this->is_linear_whitespace())
8230 {
8231 $this->linear_whitespace();
8232 }
8233 else
8234 {
8235 switch ($this->data[$this->position])
8236 {
8237 case '"':
8238 $this->position++;
8239 $this->state = 'value';
8240 break;
8241
8242 case "\x0A":
8243 $this->position++;
8244 $this->state = 'new_line';
8245 break;
8246
8247 case '\\':
8248 $this->position++;
8249 $this->state = 'quote_escaped';
8250 break;
8251
8252 default:
8253 $this->state = 'quote_char';
8254 break;
8255 }
8256 }
8257 }
8258
8259 /**
8260 * Parse a header value while within quotes
8261 *
8262 * @access private
8263 */
8264 function quote_char()
8265 {
8266 $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
8267 $this->value .= substr($this->data, $this->position, $len);
8268 $this->position += $len;
8269 $this->state = 'value';
8270 }
8271
8272 /**
8273 * Parse an escaped character within quotes
8274 *
8275 * @access private
8276 */
8277 function quote_escaped()
8278 {
8279 $this->value .= $this->data[$this->position];
8280 $this->position++;
8281 $this->state = 'quote';
8282 }
8283
8284 /**
8285 * Parse the body
8286 *
8287 * @access private
8288 */
8289 function body()
8290 {
8291 $this->body = substr($this->data, $this->position);
8292 $this->state = 'emit';
8293 }
8294 }
8295
8296 /**
8297 * gzdecode
8298 *
8299 * @package SimplePie
8300 */
8301 class SimplePie_gzdecode
8302 {
8303 /**
8304 * Compressed data
8305 *
8306 * @access private
8307 * @see gzdecode::$data
8308 */
8309 var $compressed_data;
8310
8311 /**
8312 * Size of compressed data
8313 *
8314 * @access private
8315 */
8316 var $compressed_size;
8317
8318 /**
8319 * Minimum size of a valid gzip string
8320 *
8321 * @access private
8322 */
8323 var $min_compressed_size = 18;
8324
8325 /**
8326 * Current position of pointer
8327 *
8328 * @access private
8329 */
8330 var $position = 0;
8331
8332 /**
8333 * Flags (FLG)
8334 *
8335 * @access private
8336 */
8337 var $flags;
8338
8339 /**
8340 * Uncompressed data
8341 *
8342 * @access public
8343 * @see gzdecode::$compressed_data
8344 */
8345 var $data;
8346
8347 /**
8348 * Modified time
8349 *
8350 * @access public
8351 */
8352 var $MTIME;
8353
8354 /**
8355 * Extra Flags
8356 *
8357 * @access public
8358 */
8359 var $XFL;
8360
8361 /**
8362 * Operating System
8363 *
8364 * @access public
8365 */
8366 var $OS;
8367
8368 /**
8369 * Subfield ID 1
8370 *
8371 * @access public
8372 * @see gzdecode::$extra_field
8373 * @see gzdecode::$SI2
8374 */
8375 var $SI1;
8376
8377 /**
8378 * Subfield ID 2
8379 *
8380 * @access public
8381 * @see gzdecode::$extra_field
8382 * @see gzdecode::$SI1
8383 */
8384 var $SI2;
8385
8386 /**
8387 * Extra field content
8388 *
8389 * @access public
8390 * @see gzdecode::$SI1
8391 * @see gzdecode::$SI2
8392 */
8393 var $extra_field;
8394
8395 /**
8396 * Original filename
8397 *
8398 * @access public
8399 */
8400 var $filename;
8401
8402 /**
8403 * Human readable comment
8404 *
8405 * @access public
8406 */
8407 var $comment;
8408
8409 /**
8410 * Don't allow anything to be set
8411 *
8412 * @access public
8413 */
8414 function __set($name, $value)
8415 {
8416 trigger_error("Cannot write property $name", E_USER_ERROR);
8417 }
8418
8419 /**
8420 * Set the compressed string and related properties
8421 *
8422 * @access public
8423 */
8424 function SimplePie_gzdecode($data)
8425 {
8426 $this->compressed_data = $data;
8427 $this->compressed_size = strlen($data);
8428 }
8429
8430 /**
8431 * Decode the GZIP stream
8432 *
8433 * @access public
8434 */
8435 function parse()
8436 {
8437 if ($this->compressed_size >= $this->min_compressed_size)
8438 {
8439 // Check ID1, ID2, and CM
8440 if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
8441 {
8442 return false;
8443 }
8444
8445 // Get the FLG (FLaGs)
8446 $this->flags = ord($this->compressed_data[3]);
8447
8448 // FLG bits above (1 << 4) are reserved
8449 if ($this->flags > 0x1F)
8450 {
8451 return false;
8452 }
8453
8454 // Advance the pointer after the above
8455 $this->position += 4;
8456
8457 // MTIME
8458 $mtime = substr($this->compressed_data, $this->position, 4);
8459 // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
8460 if (current(unpack('S', "\x00\x01")) === 1)
8461 {
8462 $mtime = strrev($mtime);
8463 }
8464 $this->MTIME = current(unpack('l', $mtime));
8465 $this->position += 4;
8466
8467 // Get the XFL (eXtra FLags)
8468 $this->XFL = ord($this->compressed_data[$this->position++]);
8469
8470 // Get the OS (Operating System)
8471 $this->OS = ord($this->compressed_data[$this->position++]);
8472
8473 // Parse the FEXTRA
8474 if ($this->flags & 4)
8475 {
8476 // Read subfield IDs
8477 $this->SI1 = $this->compressed_data[$this->position++];
8478 $this->SI2 = $this->compressed_data[$this->position++];
8479
8480 // SI2 set to zero is reserved for future use
8481 if ($this->SI2 === "\x00")
8482 {
8483 return false;
8484 }
8485
8486 // Get the length of the extra field
8487 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8488 $position += 2;
8489
8490 // Check the length of the string is still valid
8491 $this->min_compressed_size += $len + 4;
8492 if ($this->compressed_size >= $this->min_compressed_size)
8493 {
8494 // Set the extra field to the given data
8495 $this->extra_field = substr($this->compressed_data, $this->position, $len);
8496 $this->position += $len;
8497 }
8498 else
8499 {
8500 return false;
8501 }
8502 }
8503
8504 // Parse the FNAME
8505 if ($this->flags & 8)
8506 {
8507 // Get the length of the filename
8508 $len = strcspn($this->compressed_data, "\x00", $this->position);
8509
8510 // Check the length of the string is still valid
8511 $this->min_compressed_size += $len + 1;
8512 if ($this->compressed_size >= $this->min_compressed_size)
8513 {
8514 // Set the original filename to the given string
8515 $this->filename = substr($this->compressed_data, $this->position, $len);
8516 $this->position += $len + 1;
8517 }
8518 else
8519 {
8520 return false;
8521 }
8522 }
8523
8524 // Parse the FCOMMENT
8525 if ($this->flags & 16)
8526 {
8527 // Get the length of the comment
8528 $len = strcspn($this->compressed_data, "\x00", $this->position);
8529
8530 // Check the length of the string is still valid
8531 $this->min_compressed_size += $len + 1;
8532 if ($this->compressed_size >= $this->min_compressed_size)
8533 {
8534 // Set the original comment to the given string
8535 $this->comment = substr($this->compressed_data, $this->position, $len);
8536 $this->position += $len + 1;
8537 }
8538 else
8539 {
8540 return false;
8541 }
8542 }
8543
8544 // Parse the FHCRC
8545 if ($this->flags & 2)
8546 {
8547 // Check the length of the string is still valid
8548 $this->min_compressed_size += $len + 2;
8549 if ($this->compressed_size >= $this->min_compressed_size)
8550 {
8551 // Read the CRC
8552 $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8553
8554 // Check the CRC matches
8555 if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
8556 {
8557 $this->position += 2;
8558 }
8559 else
8560 {
8561 return false;
8562 }
8563 }
8564 else
8565 {
8566 return false;
8567 }
8568 }
8569
8570 // Decompress the actual data
8571 if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
8572 {
8573 return false;
8574 }
8575 else
8576 {
8577 $this->position = $this->compressed_size - 8;
8578 }
8579
8580 // Check CRC of data
8581 $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8582 $this->position += 4;
8583 /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
8584 {
8585 return false;
8586 }*/
8587
8588 // Check ISIZE of data
8589 $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8590 $this->position += 4;
8591 if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
8592 {
8593 return false;
8594 }
8595
8596 // Wow, against all odds, we've actually got a valid gzip string
8597 return true;
8598 }
8599 else
8600 {
8601 return false;
8602 }
8603 }
8604 }
8605
8606 class SimplePie_Cache
8607 {
8608 /**
8609 * Don't call the constructor. Please.
8610 *
8611 * @access private
8612 */
8613 function SimplePie_Cache()
8614 {
8615 trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8616 }
8617
8618 /**
8619 * Create a new SimplePie_Cache object
8620 *
8621 * @static
8622 * @access public
8623 */
8624 function create($location, $filename, $extension)
8625 {
8626 $location_iri =& new SimplePie_IRI($location);
8627 switch ($location_iri->get_scheme())
8628 {
8629 case 'mysql':
8630 if (extension_loaded('mysql'))
8631 {
8632 return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
8633 }
8634 break;
8635
8636 default:
8637 return new SimplePie_Cache_File($location, $filename, $extension);
8638 }
8639 }
8640 }
8641
8642 class SimplePie_Cache_File
8643 {
8644 var $location;
8645 var $filename;
8646 var $extension;
8647 var $name;
8648
8649 function SimplePie_Cache_File($location, $filename, $extension)
8650 {
8651 $this->location = $location;
8652 $this->filename = $filename;
8653 $this->extension = $extension;
8654 $this->name = "$this->location/$this->filename.$this->extension";
8655 }
8656
8657 function save($data)
8658 {
8659 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8660 {
8661 if (is_a($data, 'SimplePie'))
8662 {
8663 $data = $data->data;
8664 }
8665
8666 $data = serialize($data);
8667
8668 if (function_exists('file_put_contents'))
8669 {
8670 return (bool) file_put_contents($this->name, $data);
8671 }
8672 else
8673 {
8674 $fp = fopen($this->name, 'wb');
8675 if ($fp)
8676 {
8677 fwrite($fp, $data);
8678 fclose($fp);
8679 return true;
8680 }
8681 }
8682 }
8683 return false;
8684 }
8685
8686 function load()
8687 {
8688 if (file_exists($this->name) && is_readable($this->name))
8689 {
8690 return unserialize(file_get_contents($this->name));
8691 }
8692 return false;
8693 }
8694
8695 function mtime()
8696 {
8697 if (file_exists($this->name))
8698 {
8699 return filemtime($this->name);
8700 }
8701 return false;
8702 }
8703
8704 function touch()
8705 {
8706 if (file_exists($this->name))
8707 {
8708 return touch($this->name);
8709 }
8710 return false;
8711 }
8712
8713 function unlink()
8714 {
8715 if (file_exists($this->name))
8716 {
8717 return unlink($this->name);
8718 }
8719 return false;
8720 }
8721 }
8722
8723 class SimplePie_Cache_DB
8724 {
8725 function prepare_simplepie_object_for_cache($data)
8726 {
8727 $items = $data->get_items();
8728 $items_by_id = array();
8729
8730 if (!empty($items))
8731 {
8732 foreach ($items as $item)
8733 {
8734 $items_by_id[$item->get_id()] = $item;
8735 }
8736
8737 if (count($items_by_id) !== count($items))
8738 {
8739 $items_by_id = array();
8740 foreach ($items as $item)
8741 {
8742 $items_by_id[$item->get_id(true)] = $item;
8743 }
8744 }
8745
8746 if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8747 {
8748 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8749 }
8750 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8751 {
8752 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8753 }
8754 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8755 {
8756 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8757 }
8758 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
8759 {
8760 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
8761 }
8762 else
8763 {
8764 $channel = null;
8765 }
8766
8767 if ($channel !== null)
8768 {
8769 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
8770 {
8771 unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
8772 }
8773 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
8774 {
8775 unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
8776 }
8777 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
8778 {
8779 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
8780 }
8781 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
8782 {
8783 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
8784 }
8785 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
8786 {
8787 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
8788 }
8789 }
8790 if (isset($data->data['items']))
8791 {
8792 unset($data->data['items']);
8793 }
8794 if (isset($data->data['ordered_items']))
8795 {
8796 unset($data->data['ordered_items']);
8797 }
8798 }
8799 return array(serialize($data->data), $items_by_id);
8800 }
8801 }
8802
8803 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
8804 {
8805 var $mysql;
8806 var $options;
8807 var $id;
8808
8809 function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
8810 {
8811 $host = $mysql_location->get_host();
8812 if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
8813 {
8814 $server = ':' . substr($host, 5, -1);
8815 }
8816 else
8817 {
8818 $server = $host;
8819 if ($mysql_location->get_port() !== null)
8820 {
8821 $server .= ':' . $mysql_location->get_port();
8822 }
8823 }
8824
8825 if (strpos($mysql_location->get_userinfo(), ':') !== false)
8826 {
8827 list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
8828 }
8829 else
8830 {
8831 $username = $mysql_location->get_userinfo();
8832 $password = null;
8833 }
8834
8835 if ($this->mysql = mysql_connect($server, $username, $password))
8836 {
8837 $this->id = $name . $extension;
8838 $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
8839 if (!isset($this->options['prefix'][0]))
8840 {
8841 $this->options['prefix'][0] = '';
8842 }
8843
8844 if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
8845 && mysql_query('SET NAMES utf8')
8846 && ($query = mysql_unbuffered_query('SHOW TABLES')))
8847 {
8848 $db = array();
8849 while ($row = mysql_fetch_row($query))
8850 {
8851 $db[] = $row[0];
8852 }
8853
8854 if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
8855 {
8856 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)))'))
8857 {
8858 $this->mysql = null;
8859 }
8860 }
8861
8862 if (!in_array($this->options['prefix'][0] . 'items', $db))
8863 {
8864 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)))'))
8865 {
8866 $this->mysql = null;
8867 }
8868 }
8869 }
8870 else
8871 {
8872 $this->mysql = null;
8873 }
8874 }
8875 }
8876
8877 function save($data)
8878 {
8879 if ($this->mysql)
8880 {
8881 $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
8882
8883 if (is_a($data, 'SimplePie'))
8884 {
8885 if (SIMPLEPIE_PHP5)
8886 {
8887 // This keyword needs to defy coding standards for PHP4 compatibility
8888 $data = clone($data);
8889 }
8890
8891 $prepared = $this->prepare_simplepie_object_for_cache($data);
8892
8893 if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8894 {
8895 if (mysql_num_rows($query))
8896 {
8897 $items = count($prepared[1]);
8898 if ($items)
8899 {
8900 $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8901 }
8902 else
8903 {
8904 $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8905 }
8906
8907 if (!mysql_query($sql, $this->mysql))
8908 {
8909 return false;
8910 }
8911 }
8912 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))
8913 {
8914 return false;
8915 }
8916
8917 $ids = array_keys($prepared[1]);
8918 if (!empty($ids))
8919 {
8920 foreach ($ids as $id)
8921 {
8922 $database_ids[] = mysql_real_escape_string($id);
8923 }
8924
8925 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))
8926 {
8927 $existing_ids = array();
8928 while ($row = mysql_fetch_row($query))
8929 {
8930 $existing_ids[] = $row[0];
8931 }
8932
8933 $new_ids = array_diff($ids, $existing_ids);
8934
8935 foreach ($new_ids as $new_id)
8936 {
8937 if (!($date = $prepared[1][$new_id]->get_date('U')))
8938 {
8939 $date = time();
8940 }
8941
8942 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))
8943 {
8944 return false;
8945 }
8946 }
8947 return true;
8948 }
8949 }
8950 else
8951 {
8952 return true;
8953 }
8954 }
8955 }
8956 elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8957 {
8958 if (mysql_num_rows($query))
8959 {
8960 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))
8961 {
8962 return true;
8963 }
8964 }
8965 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))
8966 {
8967 return true;
8968 }
8969 }
8970 }
8971 return false;
8972 }
8973
8974 function load()
8975 {
8976 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)))
8977 {
8978 $data = unserialize($row[1]);
8979
8980 if (isset($this->options['items'][0]))
8981 {
8982 $items = (int) $this->options['items'][0];
8983 }
8984 else
8985 {
8986 $items = (int) $row[0];
8987 }
8988
8989 if ($items !== 0)
8990 {
8991 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8992 {
8993 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8994 }
8995 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8996 {
8997 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8998 }
8999 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
9000 {
9001 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
9002 }
9003 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
9004 {
9005 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
9006 }
9007 else
9008 {
9009 $feed = null;
9010 }
9011
9012 if ($feed !== null)
9013 {
9014 $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
9015 if ($items > 0)
9016 {
9017 $sql .= ' LIMIT ' . $items;
9018 }
9019
9020 if ($query = mysql_unbuffered_query($sql, $this->mysql))
9021 {
9022 while ($row = mysql_fetch_row($query))
9023 {
9024 $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
9025 }
9026 }
9027 else
9028 {
9029 return false;
9030 }
9031 }
9032 }
9033 return $data;
9034 }
9035 return false;
9036 }
9037
9038 function mtime()
9039 {
9040 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)))
9041 {
9042 return $row[0];
9043 }
9044 else
9045 {
9046 return false;
9047 }
9048 }
9049
9050 function touch()
9051 {
9052 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))
9053 {
9054 return true;
9055 }
9056 else
9057 {
9058 return false;
9059 }
9060 }
9061
9062 function unlink()
9063 {
9064 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)))
9065 {
9066 return true;
9067 }
9068 else
9069 {
9070 return false;
9071 }
9072 }
9073 }
9074
9075 class SimplePie_Misc
9076 {
9077 function time_hms($seconds)
9078 {
9079 $time = '';
9080
9081 $hours = floor($seconds / 3600);
9082 $remainder = $seconds % 3600;
9083 if ($hours > 0)
9084 {
9085 $time .= $hours.':';
9086 }
9087
9088 $minutes = floor($remainder / 60);
9089 $seconds = $remainder % 60;
9090 if ($minutes < 10 && $hours > 0)
9091 {
9092 $minutes = '0' . $minutes;
9093 }
9094 if ($seconds < 10)
9095 {
9096 $seconds = '0' . $seconds;
9097 }
9098
9099 $time .= $minutes.':';
9100 $time .= $seconds;
9101
9102 return $time;
9103 }
9104
9105 function absolutize_url($relative, $base)
9106 {
9107 $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
9108 return $iri->get_iri();
9109 }
9110
9111 function remove_dot_segments($input)
9112 {
9113 $output = '';
9114 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
9115 {
9116 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
9117 if (strpos($input, '../') === 0)
9118 {
9119 $input = substr($input, 3);
9120 }
9121 elseif (strpos($input, './') === 0)
9122 {
9123 $input = substr($input, 2);
9124 }
9125 // 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,
9126 elseif (strpos($input, '/./') === 0)
9127 {
9128 $input = substr_replace($input, '/', 0, 3);
9129 }
9130 elseif ($input === '/.')
9131 {
9132 $input = '/';
9133 }
9134 // 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,
9135 elseif (strpos($input, '/../') === 0)
9136 {
9137 $input = substr_replace($input, '/', 0, 4);
9138 $output = substr_replace($output, '', strrpos($output, '/'));
9139 }
9140 elseif ($input === '/..')
9141 {
9142 $input = '/';
9143 $output = substr_replace($output, '', strrpos($output, '/'));
9144 }
9145 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
9146 elseif ($input === '.' || $input === '..')
9147 {
9148 $input = '';
9149 }
9150 // 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
9151 elseif (($pos = strpos($input, '/', 1)) !== false)
9152 {
9153 $output .= substr($input, 0, $pos);
9154 $input = substr_replace($input, '', 0, $pos);
9155 }
9156 else
9157 {
9158 $output .= $input;
9159 $input = '';
9160 }
9161 }
9162 return $output . $input;
9163 }
9164
9165 function get_element($realname, $string)
9166 {
9167 $return = array();
9168 $name = preg_quote($realname, '/');
9169 if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
9170 {
9171 for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
9172 {
9173 $return[$i]['tag'] = $realname;
9174 $return[$i]['full'] = $matches[$i][0][0];
9175 $return[$i]['offset'] = $matches[$i][0][1];
9176 if (strlen($matches[$i][3][0]) <= 2)
9177 {
9178 $return[$i]['self_closing'] = true;
9179 }
9180 else
9181 {
9182 $return[$i]['self_closing'] = false;
9183 $return[$i]['content'] = $matches[$i][4][0];
9184 }
9185 $return[$i]['attribs'] = array();
9186 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))
9187 {
9188 for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
9189 {
9190 if (count($attribs[$j]) === 2)
9191 {
9192 $attribs[$j][2] = $attribs[$j][1];
9193 }
9194 $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
9195 }
9196 }
9197 }
9198 }
9199 return $return;
9200 }
9201
9202 function element_implode($element)
9203 {
9204 $full = "<$element[tag]";
9205 foreach ($element['attribs'] as $key => $value)
9206 {
9207 $key = strtolower($key);
9208 $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
9209 }
9210 if ($element['self_closing'])
9211 {
9212 $full .= ' />';
9213 }
9214 else
9215 {
9216 $full .= ">$element[content]</$element[tag]>";
9217 }
9218 return $full;
9219 }
9220
9221 function error($message, $level, $file, $line)
9222 {
9223 if ((ini_get('error_reporting') & $level) > 0)
9224 {
9225 switch ($level)
9226 {
9227 case E_USER_ERROR:
9228 $note = 'PHP Error';
9229 break;
9230 case E_USER_WARNING:
9231 $note = 'PHP Warning';
9232 break;
9233 case E_USER_NOTICE:
9234 $note = 'PHP Notice';
9235 break;
9236 default:
9237 $note = 'Unknown Error';
9238 break;
9239 }
9240 error_log("$note: $message in $file on line $line", 0);
9241 }
9242 return $message;
9243 }
9244
9245 /**
9246 * If a file has been cached, retrieve and display it.
9247 *
9248 * This is most useful for caching images (get_favicon(), etc.),
9249 * however it works for all cached files. This WILL NOT display ANY
9250 * file/image/page/whatever, but rather only display what has already
9251 * been cached by SimplePie.
9252 *
9253 * @access public
9254 * @see SimplePie::get_favicon()
9255 * @param str $identifier_url URL that is used to identify the content.
9256 * This may or may not be the actual URL of the live content.
9257 * @param str $cache_location Location of SimplePie's cache. Defaults
9258 * to './cache'.
9259 * @param str $cache_extension The file extension that the file was
9260 * cached with. Defaults to 'spc'.
9261 * @param str $cache_class Name of the cache-handling class being used
9262 * in SimplePie. Defaults to 'SimplePie_Cache', and should be left
9263 * as-is unless you've overloaded the class.
9264 * @param str $cache_name_function Obsolete. Exists for backwards
9265 * compatibility reasons only.
9266 */
9267 function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
9268 {
9269 $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
9270
9271 if ($file = $cache->load())
9272 {
9273 if (isset($file['headers']['content-type']))
9274 {
9275 header('Content-type:' . $file['headers']['content-type']);
9276 }
9277 else
9278 {
9279 header('Content-type: application/octet-stream');
9280 }
9281 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
9282 echo $file['body'];
9283 exit;
9284 }
9285
9286 die('Cached file for ' . $identifier_url . ' cannot be found.');
9287 }
9288
9289 function fix_protocol($url, $http = 1)
9290 {
9291 $url = SimplePie_Misc::normalize_url($url);
9292 $parsed = SimplePie_Misc::parse_url($url);
9293 if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
9294 {
9295 return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
9296 }
9297
9298 if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
9299 {
9300 return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
9301 }
9302
9303 if ($http === 2 && $parsed['scheme'] !== '')
9304 {
9305 return "feed:$url";
9306 }
9307 elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
9308 {
9309 return substr_replace($url, 'podcast', 0, 4);
9310 }
9311 elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
9312 {
9313 return substr_replace($url, 'itpc', 0, 4);
9314 }
9315 else
9316 {
9317 return $url;
9318 }
9319 }
9320
9321 function parse_url($url)
9322 {
9323 $iri =& new SimplePie_IRI($url);
9324 return array(
9325 'scheme' => (string) $iri->get_scheme(),
9326 'authority' => (string) $iri->get_authority(),
9327 'path' => (string) $iri->get_path(),
9328 'query' => (string) $iri->get_query(),
9329 'fragment' => (string) $iri->get_fragment()
9330 );
9331 }
9332
9333 function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
9334 {
9335 $iri =& new SimplePie_IRI('');
9336 $iri->set_scheme($scheme);
9337 $iri->set_authority($authority);
9338 $iri->set_path($path);
9339 $iri->set_query($query);
9340 $iri->set_fragment($fragment);
9341 return $iri->get_iri();
9342 }
9343
9344 function normalize_url($url)
9345 {
9346 $iri =& new SimplePie_IRI($url);
9347 return $iri->get_iri();
9348 }
9349
9350 function percent_encoding_normalization($match)
9351 {
9352 $integer = hexdec($match[1]);
9353 if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
9354 {
9355 return chr($integer);
9356 }
9357 else
9358 {
9359 return strtoupper($match[0]);
9360 }
9361 }
9362
9363 /**
9364 * Remove bad UTF-8 bytes
9365 *
9366 * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
9367 * FAQ: Multilingual Forms (modified to include full ASCII range)
9368 *
9369 * @author Geoffrey Sneddon
9370 * @see http://www.w3.org/International/questions/qa-forms-utf-8
9371 * @param string $str String to remove bad UTF-8 bytes from
9372 * @return string UTF-8 string
9373 */
9374 function utf8_bad_replace($str)
9375 {
9376 if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
9377 {
9378 return $return;
9379 }
9380 elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
9381 {
9382 return $return;
9383 }
9384 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))
9385 {
9386 return implode("\xEF\xBF\xBD", $matches[0]);
9387 }
9388 elseif ($str !== '')
9389 {
9390 return "\xEF\xBF\xBD";
9391 }
9392 else
9393 {
9394 return '';
9395 }
9396 }
9397
9398 /**
9399 * Converts a Windows-1252 encoded string to a UTF-8 encoded string
9400 *
9401 * @static
9402 * @access public
9403 * @param string $string Windows-1252 encoded string
9404 * @return string UTF-8 encoded string
9405 */
9406 function windows_1252_to_utf8($string)
9407 {
9408 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");
9409
9410 return strtr($string, $convert_table);
9411 }
9412
9413 function change_encoding($data, $input, $output)
9414 {
9415 $input = SimplePie_Misc::encoding($input);
9416 $output = SimplePie_Misc::encoding($output);
9417
9418 // We fail to fail on non US-ASCII bytes
9419 if ($input === 'US-ASCII')
9420 {
9421 static $non_ascii_octects = '';
9422 if (!$non_ascii_octects)
9423 {
9424 for ($i = 0x80; $i <= 0xFF; $i++)
9425 {
9426 $non_ascii_octects .= chr($i);
9427 }
9428 }
9429 $data = substr($data, 0, strcspn($data, $non_ascii_octects));
9430 }
9431
9432 // This is first, as behaviour of this is completely predictable
9433 if ($input === 'Windows-1252' && $output === 'UTF-8')
9434 {
9435 return SimplePie_Misc::windows_1252_to_utf8($data);
9436 }
9437 // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
9438 elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input)))
9439 {
9440 return $return;
9441 }
9442 // This is last, as behaviour of this varies with OS userland and PHP version
9443 elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
9444 {
9445 return $return;
9446 }
9447 // If we can't do anything, just fail
9448 else
9449 {
9450 return false;
9451 }
9452 }
9453
9454 function encoding($charset)
9455 {
9456 // Normalization from UTS #22
9457 switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
9458 {
9459 case 'adobestandardencoding':
9460 case 'csadobestandardencoding':
9461 return 'Adobe-Standard-Encoding';
9462
9463 case 'adobesymbolencoding':
9464 case 'cshppsmath':
9465 return 'Adobe-Symbol-Encoding';
9466
9467 case 'ami1251':
9468 case 'amiga1251':
9469 return 'Amiga-1251';
9470
9471 case 'ansix31101983':
9472 case 'csat5001983':
9473 case 'csiso99naplps':
9474 case 'isoir99':
9475 case 'naplps':
9476 return 'ANSI_X3.110-1983';
9477
9478 case 'arabic7':
9479 case 'asmo449':
9480 case 'csiso89asmo449':
9481 case 'iso9036':
9482 case 'isoir89':
9483 return 'ASMO_449';
9484
9485 case 'big5':
9486 case 'csbig5':
9487 case 'xxbig5':
9488 return 'Big5';
9489
9490 case 'big5hkscs':
9491 return 'Big5-HKSCS';
9492
9493 case 'bocu1':
9494 case 'csbocu1':
9495 return 'BOCU-1';
9496
9497 case 'brf':
9498 case 'csbrf':
9499 return 'BRF';
9500
9501 case 'bs4730':
9502 case 'csiso4unitedkingdom':
9503 case 'gb':
9504 case 'iso646gb':
9505 case 'isoir4':
9506 case 'uk':
9507 return 'BS_4730';
9508
9509 case 'bsviewdata':
9510 case 'csiso47bsviewdata':
9511 case 'isoir47':
9512 return 'BS_viewdata';
9513
9514 case 'cesu8':
9515 case 'cscesu8':
9516 return 'CESU-8';
9517
9518 case 'ca':
9519 case 'csa71':
9520 case 'csaz243419851':
9521 case 'csiso121canadian1':
9522 case 'iso646ca':
9523 case 'isoir121':
9524 return 'CSA_Z243.4-1985-1';
9525
9526 case 'csa72':
9527 case 'csaz243419852':
9528 case 'csiso122canadian2':
9529 case 'iso646ca2':
9530 case 'isoir122':
9531 return 'CSA_Z243.4-1985-2';
9532
9533 case 'csaz24341985gr':
9534 case 'csiso123csaz24341985gr':
9535 case 'isoir123':
9536 return 'CSA_Z243.4-1985-gr';
9537
9538 case 'csiso139csn369103':
9539 case 'csn369103':
9540 case 'isoir139':
9541 return 'CSN_369103';
9542
9543 case 'csdecmcs':
9544 case 'dec':
9545 case 'decmcs':
9546 return 'DEC-MCS';
9547
9548 case 'csiso21german':
9549 case 'de':
9550 case 'din66003':
9551 case 'iso646de':
9552 case 'isoir21':
9553 return 'DIN_66003';
9554
9555 case 'csdkus':
9556 case 'dkus':
9557 return 'dk-us';
9558
9559 case 'csiso646danish':
9560 case 'dk':
9561 case 'ds2089':
9562 case 'iso646dk':
9563 return 'DS_2089';
9564
9565 case 'csibmebcdicatde':
9566 case 'ebcdicatde':
9567 return 'EBCDIC-AT-DE';
9568
9569 case 'csebcdicatdea':
9570 case 'ebcdicatdea':
9571 return 'EBCDIC-AT-DE-A';
9572
9573 case 'csebcdiccafr':
9574 case 'ebcdiccafr':
9575 return 'EBCDIC-CA-FR';
9576
9577 case 'csebcdicdkno':
9578 case 'ebcdicdkno':
9579 return 'EBCDIC-DK-NO';
9580
9581 case 'csebcdicdknoa':
9582 case 'ebcdicdknoa':
9583 return 'EBCDIC-DK-NO-A';
9584
9585 case 'csebcdices':
9586 case 'ebcdices':
9587 return 'EBCDIC-ES';
9588
9589 case 'csebcdicesa':
9590 case 'ebcdicesa':
9591 return 'EBCDIC-ES-A';
9592
9593 case 'csebcdicess':
9594 case 'ebcdicess':
9595 return 'EBCDIC-ES-S';
9596
9597 case 'csebcdicfise':
9598 case 'ebcdicfise':
9599 return 'EBCDIC-FI-SE';
9600
9601 case 'csebcdicfisea':
9602 case 'ebcdicfisea':
9603 return 'EBCDIC-FI-SE-A';
9604
9605 case 'csebcdicfr':
9606 case 'ebcdicfr':
9607 return 'EBCDIC-FR';
9608
9609 case 'csebcdicit':
9610 case 'ebcdicit':
9611 return 'EBCDIC-IT';
9612
9613 case 'csebcdicpt':
9614 case 'ebcdicpt':
9615 return 'EBCDIC-PT';
9616
9617 case 'csebcdicuk':
9618 case 'ebcdicuk':
9619 return 'EBCDIC-UK';
9620
9621 case 'csebcdicus':
9622 case 'ebcdicus':
9623 return 'EBCDIC-US';
9624
9625 case 'csiso111ecmacyrillic':
9626 case 'ecmacyrillic':
9627 case 'isoir111':
9628 case 'koi8e':
9629 return 'ECMA-cyrillic';
9630
9631 case 'csiso17spanish':
9632 case 'es':
9633 case 'iso646es':
9634 case 'isoir17':
9635 return 'ES';
9636
9637 case 'csiso85spanish2':
9638 case 'es2':
9639 case 'iso646es2':
9640 case 'isoir85':
9641 return 'ES2';
9642
9643 case 'cseucfixwidjapanese':
9644 case 'extendedunixcodefixedwidthforjapanese':
9645 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
9646
9647 case 'cseucpkdfmtjapanese':
9648 case 'eucjp':
9649 case 'extendedunixcodepackedformatforjapanese':
9650 return 'Extended_UNIX_Code_Packed_Format_for_Japanese';
9651
9652 case 'gb18030':
9653 return 'GB18030';
9654
9655 case 'chinese':
9656 case 'cp936':
9657 case 'csgb2312':
9658 case 'csiso58gb231280':
9659 case 'gb2312':
9660 case 'gb231280':
9661 case 'gbk':
9662 case 'isoir58':
9663 case 'ms936':
9664 case 'windows936':
9665 return 'GBK';
9666
9667 case 'cn':
9668 case 'csiso57gb1988':
9669 case 'gb198880':
9670 case 'iso646cn':
9671 case 'isoir57':
9672 return 'GB_1988-80';
9673
9674 case 'csiso153gost1976874':
9675 case 'gost1976874':
9676 case 'isoir153':
9677 case 'stsev35888':
9678 return 'GOST_19768-74';
9679
9680 case 'csiso150':
9681 case 'csiso150greekccitt':
9682 case 'greekccitt':
9683 case 'isoir150':
9684 return 'greek-ccitt';
9685
9686 case 'csiso88greek7':
9687 case 'greek7':
9688 case 'isoir88':
9689 return 'greek7';
9690
9691 case 'csiso18greek7old':
9692 case 'greek7old':
9693 case 'isoir18':
9694 return 'greek7-old';
9695
9696 case 'cshpdesktop':
9697 case 'hpdesktop':
9698 return 'HP-DeskTop';
9699
9700 case 'cshplegal':
9701 case 'hplegal':
9702 return 'HP-Legal';
9703
9704 case 'cshpmath8':
9705 case 'hpmath8':
9706 return 'HP-Math8';
9707
9708 case 'cshppifont':
9709 case 'hppifont':
9710 return 'HP-Pi-font';
9711
9712 case 'cshproman8':
9713 case 'hproman8':
9714 case 'r8':
9715 case 'roman8':
9716 return 'hp-roman8';
9717
9718 case 'hzgb2312':
9719 return 'HZ-GB-2312';
9720
9721 case 'csibmsymbols':
9722 case 'ibmsymbols':
9723 return 'IBM-Symbols';
9724
9725 case 'csibmthai':
9726 case 'ibmthai':
9727 return 'IBM-Thai';
9728
9729 case 'ccsid858':
9730 case 'cp858':
9731 case 'ibm858':
9732 case 'pcmultilingual850euro':
9733 return 'IBM00858';
9734
9735 case 'ccsid924':
9736 case 'cp924':
9737 case 'ebcdiclatin9euro':
9738 case 'ibm924':
9739 return 'IBM00924';
9740
9741 case 'ccsid1140':
9742 case 'cp1140':
9743 case 'ebcdicus37euro':
9744 case 'ibm1140':
9745 return 'IBM01140';
9746
9747 case 'ccsid1141':
9748 case 'cp1141':
9749 case 'ebcdicde273euro':
9750 case 'ibm1141':
9751 return 'IBM01141';
9752
9753 case 'ccsid1142':
9754 case 'cp1142':
9755 case 'ebcdicdk277euro':
9756 case 'ebcdicno277euro':
9757 case 'ibm1142':
9758 return 'IBM01142';
9759
9760 case 'ccsid1143':
9761 case 'cp1143':
9762 case 'ebcdicfi278euro':
9763 case 'ebcdicse278euro':
9764 case 'ibm1143':
9765 return 'IBM01143';
9766
9767 case 'ccsid1144':
9768 case 'cp1144':
9769 case 'ebcdicit280euro':
9770 case 'ibm1144':
9771 return 'IBM01144';
9772
9773 case 'ccsid1145':
9774 case 'cp1145':
9775 case 'ebcdices284euro':
9776 case 'ibm1145':
9777 return 'IBM01145';
9778
9779 case 'ccsid1146':
9780 case 'cp1146':
9781 case 'ebcdicgb285euro':
9782 case 'ibm1146':
9783 return 'IBM01146';
9784
9785 case 'ccsid1147':
9786 case 'cp1147':
9787 case 'ebcdicfr297euro':
9788 case 'ibm1147':
9789 return 'IBM01147';
9790
9791 case 'ccsid1148':
9792 case 'cp1148':
9793 case 'ebcdicinternational500euro':
9794 case 'ibm1148':
9795 return 'IBM01148';
9796
9797 case 'ccsid1149':
9798 case 'cp1149':
9799 case 'ebcdicis871euro':
9800 case 'ibm1149':
9801 return 'IBM01149';
9802
9803 case 'cp37':
9804 case 'csibm37':
9805 case 'ebcdiccpca':
9806 case 'ebcdiccpnl':
9807 case 'ebcdiccpus':
9808 case 'ebcdiccpwt':
9809 case 'ibm37':
9810 return 'IBM037';
9811
9812 case 'cp38':
9813 case 'csibm38':
9814 case 'ebcdicint':
9815 case 'ibm38':
9816 return 'IBM038';
9817
9818 case 'cp273':
9819 case 'csibm273':
9820 case 'ibm273':
9821 return 'IBM273';
9822
9823 case 'cp274':
9824 case 'csibm274':
9825 case 'ebcdicbe':
9826 case 'ibm274':
9827 return 'IBM274';
9828
9829 case 'cp275':
9830 case 'csibm275':
9831 case 'ebcdicbr':
9832 case 'ibm275':
9833 return 'IBM275';
9834
9835 case 'csibm277':
9836 case 'ebcdiccpdk':
9837 case 'ebcdiccpno':
9838 case 'ibm277':
9839 return 'IBM277';
9840
9841 case 'cp278':
9842 case 'csibm278':
9843 case 'ebcdiccpfi':
9844 case 'ebcdiccpse':
9845 case 'ibm278':
9846 return 'IBM278';
9847
9848 case 'cp280':
9849 case 'csibm280':
9850 case 'ebcdiccpit':
9851 case 'ibm280':
9852 return 'IBM280';
9853
9854 case 'cp281':
9855 case 'csibm281':
9856 case 'ebcdicjpe':
9857 case 'ibm281':
9858 return 'IBM281';
9859
9860 case 'cp284':
9861 case 'csibm284':
9862 case 'ebcdiccpes':
9863 case 'ibm284':
9864 return 'IBM284';
9865
9866 case 'cp285':
9867 case 'csibm285':
9868 case 'ebcdiccpgb':
9869 case 'ibm285':
9870 return 'IBM285';
9871
9872 case 'cp290':
9873 case 'csibm290':
9874 case 'ebcdicjpkana':
9875 case 'ibm290':
9876 return 'IBM290';
9877
9878 case 'cp297':
9879 case 'csibm297':
9880 case 'ebcdiccpfr':
9881 case 'ibm297':
9882 return 'IBM297';
9883
9884 case 'cp420':
9885 case 'csibm420':
9886 case 'ebcdiccpar1':
9887 case 'ibm420':
9888 return 'IBM420';
9889
9890 case 'cp423':
9891 case 'csibm423':
9892 case 'ebcdiccpgr':
9893 case 'ibm423':
9894 return 'IBM423';
9895
9896 case 'cp424':
9897 case 'csibm424':
9898 case 'ebcdiccphe':
9899 case 'ibm424':
9900 return 'IBM424';
9901
9902 case '437':
9903 case 'cp437':
9904 case 'cspc8codepage437':
9905 case 'ibm437':
9906 return 'IBM437';
9907
9908 case 'cp500':
9909 case 'csibm500':
9910 case 'ebcdiccpbe':
9911 case 'ebcdiccpch':
9912 case 'ibm500':
9913 return 'IBM500';
9914
9915 case 'cp775':
9916 case 'cspc775baltic':
9917 case 'ibm775':
9918 return 'IBM775';
9919
9920 case '850':
9921 case 'cp850':
9922 case 'cspc850multilingual':
9923 case 'ibm850':
9924 return 'IBM850';
9925
9926 case '851':
9927 case 'cp851':
9928 case 'csibm851':
9929 case 'ibm851':
9930 return 'IBM851';
9931
9932 case '852':
9933 case 'cp852':
9934 case 'cspcp852':
9935 case 'ibm852':
9936 return 'IBM852';
9937
9938 case '855':
9939 case 'cp855':
9940 case 'csibm855':
9941 case 'ibm855':
9942 return 'IBM855';
9943
9944 case '857':
9945 case 'cp857':
9946 case 'csibm857':
9947 case 'ibm857':
9948 return 'IBM857';
9949
9950 case '860':
9951 case 'cp860':
9952 case 'csibm860':
9953 case 'ibm860':
9954 return 'IBM860';
9955
9956 case '861':
9957 case 'cp861':
9958 case 'cpis':
9959 case 'csibm861':
9960 case 'ibm861':
9961 return 'IBM861';
9962
9963 case '862':
9964 case 'cp862':
9965 case 'cspc862latinhebrew':
9966 case 'ibm862':
9967 return 'IBM862';
9968
9969 case '863':
9970 case 'cp863':
9971 case 'csibm863':
9972 case 'ibm863':
9973 return 'IBM863';
9974
9975 case 'cp864':
9976 case 'csibm864':
9977 case 'ibm864':
9978 return 'IBM864';
9979
9980 case '865':
9981 case 'cp865':
9982 case 'csibm865':
9983 case 'ibm865':
9984 return 'IBM865';
9985
9986 case '866':
9987 case 'cp866':
9988 case 'csibm866':
9989 case 'ibm866':
9990 return 'IBM866';
9991
9992 case 'cp868':
9993 case 'cpar':
9994 case 'csibm868':
9995 case 'ibm868':
9996 return 'IBM868';
9997
9998 case '869':
9999 case 'cp869':
10000 case 'cpgr':
10001 case 'csibm869':
10002 case 'ibm869':
10003 return 'IBM869';
10004
10005 case 'cp870':
10006 case 'csibm870':
10007 case 'ebcdiccproece':
10008 case 'ebcdiccpyu':
10009 case 'ibm870':
10010 return 'IBM870';
10011
10012 case 'cp871':
10013 case 'csibm871':
10014 case 'ebcdiccpis':
10015 case 'ibm871':
10016 return 'IBM871';
10017
10018 case 'cp880':
10019 case 'csibm880':
10020 case 'ebcdiccyrillic':
10021 case 'ibm880':
10022 return 'IBM880';
10023
10024 case 'cp891':
10025 case 'csibm891':
10026 case 'ibm891':
10027 return 'IBM891';
10028
10029 case 'cp903':
10030 case 'csibm903':
10031 case 'ibm903':
10032 return 'IBM903';
10033
10034 case '904':
10035 case 'cp904':
10036 case 'csibbm904':
10037 case 'ibm904':
10038 return 'IBM904';
10039
10040 case 'cp905':
10041 case 'csibm905':
10042 case 'ebcdiccptr':
10043 case 'ibm905':
10044 return 'IBM905';
10045
10046 case 'cp918':
10047 case 'csibm918':
10048 case 'ebcdiccpar2':
10049 case 'ibm918':
10050 return 'IBM918';
10051
10052 case 'cp1026':
10053 case 'csibm1026':
10054 case 'ibm1026':
10055 return 'IBM1026';
10056
10057 case 'ibm1047':
10058 return 'IBM1047';
10059
10060 case 'csiso143iecp271':
10061 case 'iecp271':
10062 case 'isoir143':
10063 return 'IEC_P27-1';
10064
10065 case 'csiso49inis':
10066 case 'inis':
10067 case 'isoir49':
10068 return 'INIS';
10069
10070 case 'csiso50inis8':
10071 case 'inis8':
10072 case 'isoir50':
10073 return 'INIS-8';
10074
10075 case 'csiso51iniscyrillic':
10076 case 'iniscyrillic':
10077 case 'isoir51':
10078 return 'INIS-cyrillic';
10079
10080 case 'csinvariant':
10081 case 'invariant':
10082 return 'INVARIANT';
10083
10084 case 'iso2022cn':
10085 return 'ISO-2022-CN';
10086
10087 case 'iso2022cnext':
10088 return 'ISO-2022-CN-EXT';
10089
10090 case 'csiso2022jp':
10091 case 'iso2022jp':
10092 return 'ISO-2022-JP';
10093
10094 case 'csiso2022jp2':
10095 case 'iso2022jp2':
10096 return 'ISO-2022-JP-2';
10097
10098 case 'csiso2022kr':
10099 case 'iso2022kr':
10100 return 'ISO-2022-KR';
10101
10102 case 'cswindows30latin1':
10103 case 'iso88591windows30latin1':
10104 return 'ISO-8859-1-Windows-3.0-Latin-1';
10105
10106 case 'cswindows31latin1':
10107 case 'iso88591windows31latin1':
10108 return 'ISO-8859-1-Windows-3.1-Latin-1';
10109
10110 case 'csisolatin2':
10111 case 'iso88592':
10112 case 'iso885921987':
10113 case 'isoir101':
10114 case 'l2':
10115 case 'latin2':
10116 return 'ISO-8859-2';
10117
10118 case 'cswindows31latin2':
10119 case 'iso88592windowslatin2':
10120 return 'ISO-8859-2-Windows-Latin-2';
10121
10122 case 'csisolatin3':
10123 case 'iso88593':
10124 case 'iso885931988':
10125 case 'isoir109':
10126 case 'l3':
10127 case 'latin3':
10128 return 'ISO-8859-3';
10129
10130 case 'csisolatin4':
10131 case 'iso88594':
10132 case 'iso885941988':
10133 case 'isoir110':
10134 case 'l4':
10135 case 'latin4':
10136 return 'ISO-8859-4';
10137
10138 case 'csisolatincyrillic':
10139 case 'cyrillic':
10140 case 'iso88595':
10141 case 'iso885951988':
10142 case 'isoir144':
10143 return 'ISO-8859-5';
10144
10145 case 'arabic':
10146 case 'asmo708':
10147 case 'csisolatinarabic':
10148 case 'ecma114':
10149 case 'iso88596':
10150 case 'iso885961987':
10151 case 'isoir127':
10152 return 'ISO-8859-6';
10153
10154 case 'csiso88596e':
10155 case 'iso88596e':
10156 return 'ISO-8859-6-E';
10157
10158 case 'csiso88596i':
10159 case 'iso88596i':
10160 return 'ISO-8859-6-I';
10161
10162 case 'csisolatingreek':
10163 case 'ecma118':
10164 case 'elot928':
10165 case 'greek':
10166 case 'greek8':
10167 case 'iso88597':
10168 case 'iso885971987':
10169 case 'isoir126':
10170 return 'ISO-8859-7';
10171
10172 case 'csisolatinhebrew':
10173 case 'hebrew':
10174 case 'iso88598':
10175 case 'iso885981988':
10176 case 'isoir138':
10177 return 'ISO-8859-8';
10178
10179 case 'csiso88598e':
10180 case 'iso88598e':
10181 return 'ISO-8859-8-E';
10182
10183 case 'csiso88598i':
10184 case 'iso88598i':
10185 return 'ISO-8859-8-I';
10186
10187 case 'cswindows31latin5':
10188 case 'iso88599windowslatin5':
10189 return 'ISO-8859-9-Windows-Latin-5';
10190
10191 case 'csisolatin6':
10192 case 'iso885910':
10193 case 'iso8859101992':
10194 case 'isoir157':
10195 case 'l6':
10196 case 'latin6':
10197 return 'ISO-8859-10';
10198
10199 case 'iso885913':
10200 return 'ISO-8859-13';
10201
10202 case 'iso885914':
10203 case 'iso8859141998':
10204 case 'isoceltic':
10205 case 'isoir199':
10206 case 'l8':
10207 case 'latin8':
10208 return 'ISO-8859-14';
10209
10210 case 'iso885915':
10211 case 'latin9':
10212 return 'ISO-8859-15';
10213
10214 case 'iso885916':
10215 case 'iso8859162001':
10216 case 'isoir226':
10217 case 'l10':
10218 case 'latin10':
10219 return 'ISO-8859-16';
10220
10221 case 'iso10646j1':
10222 return 'ISO-10646-J-1';
10223
10224 case 'csunicode':
10225 case 'iso10646ucs2':
10226 return 'ISO-10646-UCS-2';
10227
10228 case 'csucs4':
10229 case 'iso10646ucs4':
10230 return 'ISO-10646-UCS-4';
10231
10232 case 'csunicodeascii':
10233 case 'iso10646ucsbasic':
10234 return 'ISO-10646-UCS-Basic';
10235
10236 case 'csunicodelatin1':
10237 case 'iso10646':
10238 case 'iso10646unicodelatin1':
10239 return 'ISO-10646-Unicode-Latin1';
10240
10241 case 'csiso10646utf1':
10242 case 'iso10646utf1':
10243 return 'ISO-10646-UTF-1';
10244
10245 case 'csiso115481':
10246 case 'iso115481':
10247 case 'isotr115481':
10248 return 'ISO-11548-1';
10249
10250 case 'csiso90':
10251 case 'isoir90':
10252 return 'iso-ir-90';
10253
10254 case 'csunicodeibm1261':
10255 case 'isounicodeibm1261':
10256 return 'ISO-Unicode-IBM-1261';
10257
10258 case 'csunicodeibm1264':
10259 case 'isounicodeibm1264':
10260 return 'ISO-Unicode-IBM-1264';
10261
10262 case 'csunicodeibm1265':
10263 case 'isounicodeibm1265':
10264 return 'ISO-Unicode-IBM-1265';
10265
10266 case 'csunicodeibm1268':
10267 case 'isounicodeibm1268':
10268 return 'ISO-Unicode-IBM-1268';
10269
10270 case 'csunicodeibm1276':
10271 case 'isounicodeibm1276':
10272 return 'ISO-Unicode-IBM-1276';
10273
10274 case 'csiso646basic1983':
10275 case 'iso646basic1983':
10276 case 'ref':
10277 return 'ISO_646.basic:1983';
10278
10279 case 'csiso2intlrefversion':
10280 case 'irv':
10281 case 'iso646irv1983':
10282 case 'isoir2':
10283 return 'ISO_646.irv:1983';
10284
10285 case 'csiso2033':
10286 case 'e13b':
10287 case 'iso20331983':
10288 case 'isoir98':
10289 return 'ISO_2033-1983';
10290
10291 case 'csiso5427cyrillic':
10292 case 'iso5427':
10293 case 'isoir37':
10294 return 'ISO_5427';
10295
10296 case 'iso5427cyrillic1981':
10297 case 'iso54271981':
10298 case 'isoir54':
10299 return 'ISO_5427:1981';
10300
10301 case 'csiso5428greek':
10302 case 'iso54281980':
10303 case 'isoir55':
10304 return 'ISO_5428:1980';
10305
10306 case 'csiso6937add':
10307 case 'iso6937225':
10308 case 'isoir152':
10309 return 'ISO_6937-2-25';
10310
10311 case 'csisotextcomm':
10312 case 'iso69372add':
10313 case 'isoir142':
10314 return 'ISO_6937-2-add';
10315
10316 case 'csiso8859supp':
10317 case 'iso8859supp':
10318 case 'isoir154':
10319 case 'latin125':
10320 return 'ISO_8859-supp';
10321
10322 case 'csiso10367box':
10323 case 'iso10367box':
10324 case 'isoir155':
10325 return 'ISO_10367-box';
10326
10327 case 'csiso15italian':
10328 case 'iso646it':
10329 case 'isoir15':
10330 case 'it':
10331 return 'IT';
10332
10333 case 'csiso13jisc6220jp':
10334 case 'isoir13':
10335 case 'jisc62201969':
10336 case 'jisc62201969jp':
10337 case 'katakana':
10338 case 'x2017':
10339 return 'JIS_C6220-1969-jp';
10340
10341 case 'csiso14jisc6220ro':
10342 case 'iso646jp':
10343 case 'isoir14':
10344 case 'jisc62201969ro':
10345 case 'jp':
10346 return 'JIS_C6220-1969-ro';
10347
10348 case 'csiso42jisc62261978':
10349 case 'isoir42':
10350 case 'jisc62261978':
10351 return 'JIS_C6226-1978';
10352
10353 case 'csiso87jisx208':
10354 case 'isoir87':
10355 case 'jisc62261983':
10356 case 'jisx2081983':
10357 case 'x208':
10358 return 'JIS_C6226-1983';
10359
10360 case 'csiso91jisc62291984a':
10361 case 'isoir91':
10362 case 'jisc62291984a':
10363 case 'jpocra':
10364 return 'JIS_C6229-1984-a';
10365
10366 case 'csiso92jisc62991984b':
10367 case 'iso646jpocrb':
10368 case 'isoir92':
10369 case 'jisc62291984b':
10370 case 'jpocrb':
10371 return 'JIS_C6229-1984-b';
10372
10373 case 'csiso93jis62291984badd':
10374 case 'isoir93':
10375 case 'jisc62291984badd':
10376 case 'jpocrbadd':
10377 return 'JIS_C6229-1984-b-add';
10378
10379 case 'csiso94jis62291984hand':
10380 case 'isoir94':
10381 case 'jisc62291984hand':
10382 case 'jpocrhand':
10383 return 'JIS_C6229-1984-hand';
10384
10385 case 'csiso95jis62291984handadd':
10386 case 'isoir95':
10387 case 'jisc62291984handadd':
10388 case 'jpocrhandadd':
10389 return 'JIS_C6229-1984-hand-add';
10390
10391 case 'csiso96jisc62291984kana':
10392 case 'isoir96':
10393 case 'jisc62291984kana':
10394 return 'JIS_C6229-1984-kana';
10395
10396 case 'csjisencoding':
10397 case 'jisencoding':
10398 return 'JIS_Encoding';
10399
10400 case 'cshalfwidthkatakana':
10401 case 'jisx201':
10402 case 'x201':
10403 return 'JIS_X0201';
10404
10405 case 'csiso159jisx2121990':
10406 case 'isoir159':
10407 case 'jisx2121990':
10408 case 'x212':
10409 return 'JIS_X0212-1990';
10410
10411 case 'csiso141jusib1002':
10412 case 'iso646yu':
10413 case 'isoir141':
10414 case 'js':
10415 case 'jusib1002':
10416 case 'yu':
10417 return 'JUS_I.B1.002';
10418
10419 case 'csiso147macedonian':
10420 case 'isoir147':
10421 case 'jusib1003mac':
10422 case 'macedonian':
10423 return 'JUS_I.B1.003-mac';
10424
10425 case 'csiso146serbian':
10426 case 'isoir146':
10427 case 'jusib1003serb':
10428 case 'serbian':
10429 return 'JUS_I.B1.003-serb';
10430
10431 case 'koi7switched':
10432 return 'KOI7-switched';
10433
10434 case 'cskoi8r':
10435 case 'koi8r':
10436 return 'KOI8-R';
10437
10438 case 'koi8u':
10439 return 'KOI8-U';
10440
10441 case 'csksc5636':
10442 case 'iso646kr':
10443 case 'ksc5636':
10444 return 'KSC5636';
10445
10446 case 'cskz1048':
10447 case 'kz1048':
10448 case 'rk1048':
10449 case 'strk10482002':
10450 return 'KZ-1048';
10451
10452 case 'csiso19latingreek':
10453 case 'isoir19':
10454 case 'latingreek':
10455 return 'latin-greek';
10456
10457 case 'csiso27latingreek1':
10458 case 'isoir27':
10459 case 'latingreek1':
10460 return 'Latin-greek-1';
10461
10462 case 'csiso158lap':
10463 case 'isoir158':
10464 case 'lap':
10465 case 'latinlap':
10466 return 'latin-lap';
10467
10468 case 'csmacintosh':
10469 case 'mac':
10470 case 'macintosh':
10471 return 'macintosh';
10472
10473 case 'csmicrosoftpublishing':
10474 case 'microsoftpublishing':
10475 return 'Microsoft-Publishing';
10476
10477 case 'csmnem':
10478 case 'mnem':
10479 return 'MNEM';
10480
10481 case 'csmnemonic':
10482 case 'mnemonic':
10483 return 'MNEMONIC';
10484
10485 case 'csiso86hungarian':
10486 case 'hu':
10487 case 'iso646hu':
10488 case 'isoir86':
10489 case 'msz77953':
10490 return 'MSZ_7795.3';
10491
10492 case 'csnatsdano':
10493 case 'isoir91':
10494 case 'natsdano':
10495 return 'NATS-DANO';
10496
10497 case 'csnatsdanoadd':
10498 case 'isoir92':
10499 case 'natsdanoadd':
10500 return 'NATS-DANO-ADD';
10501
10502 case 'csnatssefi':
10503 case 'isoir81':
10504 case 'natssefi':
10505 return 'NATS-SEFI';
10506
10507 case 'csnatssefiadd':
10508 case 'isoir82':
10509 case 'natssefiadd':
10510 return 'NATS-SEFI-ADD';
10511
10512 case 'csiso151cuba':
10513 case 'cuba':
10514 case 'iso646cu':
10515 case 'isoir151':
10516 case 'ncnc1081':
10517 return 'NC_NC00-10:81';
10518
10519 case 'csiso69french':
10520 case 'fr':
10521 case 'iso646fr':
10522 case 'isoir69':
10523 case 'nfz62010':
10524 return 'NF_Z_62-010';
10525
10526 case 'csiso25french':
10527 case 'iso646fr1':
10528 case 'isoir25':
10529 case 'nfz620101973':
10530 return 'NF_Z_62-010_(1973)';
10531
10532 case 'csiso60danishnorwegian':
10533 case 'csiso60norwegian1':
10534 case 'iso646no':
10535 case 'isoir60':
10536 case 'no':
10537 case 'ns45511':
10538 return 'NS_4551-1';
10539
10540 case 'csiso61norwegian2':
10541 case 'iso646no2':
10542 case 'isoir61':
10543 case 'no2':
10544 case 'ns45512':
10545 return 'NS_4551-2';
10546
10547 case 'osdebcdicdf3irv':
10548 return 'OSD_EBCDIC_DF03_IRV';
10549
10550 case 'osdebcdicdf41':
10551 return 'OSD_EBCDIC_DF04_1';
10552
10553 case 'osdebcdicdf415':
10554 return 'OSD_EBCDIC_DF04_15';
10555
10556 case 'cspc8danishnorwegian':
10557 case 'pc8danishnorwegian':
10558 return 'PC8-Danish-Norwegian';
10559
10560 case 'cspc8turkish':
10561 case 'pc8turkish':
10562 return 'PC8-Turkish';
10563
10564 case 'csiso16portuguese':
10565 case 'iso646pt':
10566 case 'isoir16':
10567 case 'pt':
10568 return 'PT';
10569
10570 case 'csiso84portuguese2':
10571 case 'iso646pt2':
10572 case 'isoir84':
10573 case 'pt2':
10574 return 'PT2';
10575
10576 case 'cp154':
10577 case 'csptcp154':
10578 case 'cyrillicasian':
10579 case 'pt154':
10580 case 'ptcp154':
10581 return 'PTCP154';
10582
10583 case 'scsu':
10584 return 'SCSU';
10585
10586 case 'csiso10swedish':
10587 case 'fi':
10588 case 'iso646fi':
10589 case 'iso646se':
10590 case 'isoir10':
10591 case 'se':
10592 case 'sen850200b':
10593 return 'SEN_850200_B';
10594
10595 case 'csiso11swedishfornames':
10596 case 'iso646se2':
10597 case 'isoir11':
10598 case 'se2':
10599 case 'sen850200c':
10600 return 'SEN_850200_C';
10601
10602 case 'csshiftjis':
10603 case 'mskanji':
10604 case 'shiftjis':
10605 return 'Shift_JIS';
10606
10607 case 'csiso102t617bit':
10608 case 'isoir102':
10609 case 't617bit':
10610 return 'T.61-7bit';
10611
10612 case 'csiso103t618bit':
10613 case 'isoir103':
10614 case 't61':
10615 case 't618bit':
10616 return 'T.61-8bit';
10617
10618 case 'csiso128t101g2':
10619 case 'isoir128':
10620 case 't101g2':
10621 return 'T.101-G2';
10622
10623 case 'cstscii':
10624 case 'tscii':
10625 return 'TSCII';
10626
10627 case 'csunicode11':
10628 case 'unicode11':
10629 return 'UNICODE-1-1';
10630
10631 case 'csunicode11utf7':
10632 case 'unicode11utf7':
10633 return 'UNICODE-1-1-UTF-7';
10634
10635 case 'csunknown8bit':
10636 case 'unknown8bit':
10637 return 'UNKNOWN-8BIT';
10638
10639 case 'ansix341968':
10640 case 'ansix341986':
10641 case 'ascii':
10642 case 'cp367':
10643 case 'csascii':
10644 case 'ibm367':
10645 case 'iso646irv1991':
10646 case 'iso646us':
10647 case 'isoir6':
10648 case 'us':
10649 case 'usascii':
10650 return 'US-ASCII';
10651
10652 case 'csusdk':
10653 case 'usdk':
10654 return 'us-dk';
10655
10656 case 'utf7':
10657 return 'UTF-7';
10658
10659 case 'utf8':
10660 return 'UTF-8';
10661
10662 case 'utf16':
10663 return 'UTF-16';
10664
10665 case 'utf16be':
10666 return 'UTF-16BE';
10667
10668 case 'utf16le':
10669 return 'UTF-16LE';
10670
10671 case 'utf32':
10672 return 'UTF-32';
10673
10674 case 'utf32be':
10675 return 'UTF-32BE';
10676
10677 case 'utf32le':
10678 return 'UTF-32LE';
10679
10680 case 'csventurainternational':
10681 case 'venturainternational':
10682 return 'Ventura-International';
10683
10684 case 'csventuramath':
10685 case 'venturamath':
10686 return 'Ventura-Math';
10687
10688 case 'csventuraus':
10689 case 'venturaus':
10690 return 'Ventura-US';
10691
10692 case 'csiso70videotexsupp1':
10693 case 'isoir70':
10694 case 'videotexsuppl':
10695 return 'videotex-suppl';
10696
10697 case 'csviqr':
10698 case 'viqr':
10699 return 'VIQR';
10700
10701 case 'csviscii':
10702 case 'viscii':
10703 return 'VISCII';
10704
10705 case 'cswindows31j':
10706 case 'windows31j':
10707 return 'Windows-31J';
10708
10709 case 'iso885911':
10710 case 'tis620':
10711 return 'windows-874';
10712
10713 case 'cseuckr':
10714 case 'csksc56011987':
10715 case 'euckr':
10716 case 'isoir149':
10717 case 'korean':
10718 case 'ksc5601':
10719 case 'ksc56011987':
10720 case 'ksc56011989':
10721 case 'windows949':
10722 return 'windows-949';
10723
10724 case 'windows1250':
10725 return 'windows-1250';
10726
10727 case 'windows1251':
10728 return 'windows-1251';
10729
10730 case 'cp819':
10731 case 'csisolatin1':
10732 case 'ibm819':
10733 case 'iso88591':
10734 case 'iso885911987':
10735 case 'isoir100':
10736 case 'l1':
10737 case 'latin1':
10738 case 'windows1252':
10739 return 'windows-1252';
10740
10741 case 'windows1253':
10742 return 'windows-1253';
10743
10744 case 'csisolatin5':
10745 case 'iso88599':
10746 case 'iso885991989':
10747 case 'isoir148':
10748 case 'l5':
10749 case 'latin5':
10750 case 'windows1254':
10751 return 'windows-1254';
10752
10753 case 'windows1255':
10754 return 'windows-1255';
10755
10756 case 'windows1256':
10757 return 'windows-1256';
10758
10759 case 'windows1257':
10760 return 'windows-1257';
10761
10762 case 'windows1258':
10763 return 'windows-1258';
10764
10765 default:
10766 return $charset;
10767 }
10768 }
10769
10770 function get_curl_version()
10771 {
10772 if (is_array($curl = curl_version()))
10773 {
10774 $curl = $curl['version'];
10775 }
10776 elseif (substr($curl, 0, 5) === 'curl/')
10777 {
10778 $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10779 }
10780 elseif (substr($curl, 0, 8) === 'libcurl/')
10781 {
10782 $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10783 }
10784 else
10785 {
10786 $curl = 0;
10787 }
10788 return $curl;
10789 }
10790
10791 function is_subclass_of($class1, $class2)
10792 {
10793 if (func_num_args() !== 2)
10794 {
10795 trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10796 }
10797 elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10798 {
10799 return is_subclass_of($class1, $class2);
10800 }
10801 elseif (is_string($class1) && is_string($class2))
10802 {
10803 if (class_exists($class1))
10804 {
10805 if (class_exists($class2))
10806 {
10807 $class2 = strtolower($class2);
10808 while ($class1 = strtolower(get_parent_class($class1)))
10809 {
10810 if ($class1 === $class2)
10811 {
10812 return true;
10813 }
10814 }
10815 }
10816 }
10817 else
10818 {
10819 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10820 }
10821 }
10822 return false;
10823 }
10824
10825 /**
10826 * Strip HTML comments
10827 *
10828 * @access public
10829 * @param string $data Data to strip comments from
10830 * @return string Comment stripped string
10831 */
10832 function strip_comments($data)
10833 {
10834 $output = '';
10835 while (($start = strpos($data, '<!--')) !== false)
10836 {
10837 $output .= substr($data, 0, $start);
10838 if (($end = strpos($data, '-->', $start)) !== false)
10839 {
10840 $data = substr_replace($data, '', 0, $end + 3);
10841 }
10842 else
10843 {
10844 $data = '';
10845 }
10846 }
10847 return $output . $data;
10848 }
10849
10850 function parse_date($dt)
10851 {
10852 $parser = SimplePie_Parse_Date::get();
10853 return $parser->parse($dt);
10854 }
10855
10856 /**
10857 * Decode HTML entities
10858 *
10859 * @static
10860 * @access public
10861 * @param string $data Input data
10862 * @return string Output data
10863 */
10864 function entities_decode($data)
10865 {
10866 $decoder =& new SimplePie_Decode_HTML_Entities($data);
10867 return $decoder->parse();
10868 }
10869
10870 /**
10871 * Remove RFC822 comments
10872 *
10873 * @access public
10874 * @param string $data Data to strip comments from
10875 * @return string Comment stripped string
10876 */
10877 function uncomment_rfc822($string)
10878 {
10879 $string = (string) $string;
10880 $position = 0;
10881 $length = strlen($string);
10882 $depth = 0;
10883
10884 $output = '';
10885
10886 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
10887 {
10888 $output .= substr($string, $position, $pos - $position);
10889 $position = $pos + 1;
10890 if ($string[$pos - 1] !== '\\')
10891 {
10892 $depth++;
10893 while ($depth && $position < $length)
10894 {
10895 $position += strcspn($string, '()', $position);
10896 if ($string[$position - 1] === '\\')
10897 {
10898 $position++;
10899 continue;
10900 }
10901 elseif (isset($string[$position]))
10902 {
10903 switch ($string[$position])
10904 {
10905 case '(':
10906 $depth++;
10907 break;
10908
10909 case ')':
10910 $depth--;
10911 break;
10912 }
10913 $position++;
10914 }
10915 else
10916 {
10917 break;
10918 }
10919 }
10920 }
10921 else
10922 {
10923 $output .= '(';
10924 }
10925 }
10926 $output .= substr($string, $position);
10927
10928 return $output;
10929 }
10930
10931 function parse_mime($mime)
10932 {
10933 if (($pos = strpos($mime, ';')) === false)
10934 {
10935 return trim($mime);
10936 }
10937 else
10938 {
10939 return trim(substr($mime, 0, $pos));
10940 }
10941 }
10942
10943 function htmlspecialchars_decode($string, $quote_style)
10944 {
10945 if (function_exists('htmlspecialchars_decode'))
10946 {
10947 return htmlspecialchars_decode($string, $quote_style);
10948 }
10949 else
10950 {
10951 return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
10952 }
10953 }
10954
10955 function atom_03_construct_type($attribs)
10956 {
10957 if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
10958 {
10959 $mode = SIMPLEPIE_CONSTRUCT_BASE64;
10960 }
10961 else
10962 {
10963 $mode = SIMPLEPIE_CONSTRUCT_NONE;
10964 }
10965 if (isset($attribs['']['type']))
10966 {
10967 switch (strtolower(trim($attribs['']['type'])))
10968 {
10969 case 'text':
10970 case 'text/plain':
10971 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
10972
10973 case 'html':
10974 case 'text/html':
10975 return SIMPLEPIE_CONSTRUCT_HTML | $mode;
10976
10977 case 'xhtml':
10978 case 'application/xhtml+xml':
10979 return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
10980
10981 default:
10982 return SIMPLEPIE_CONSTRUCT_NONE | $mode;
10983 }
10984 }
10985 else
10986 {
10987 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
10988 }
10989 }
10990
10991 function atom_10_construct_type($attribs)
10992 {
10993 if (isset($attribs['']['type']))
10994 {
10995 switch (strtolower(trim($attribs['']['type'])))
10996 {
10997 case 'text':
10998 return SIMPLEPIE_CONSTRUCT_TEXT;
10999
11000 case 'html':
11001 return SIMPLEPIE_CONSTRUCT_HTML;
11002
11003 case 'xhtml':
11004 return SIMPLEPIE_CONSTRUCT_XHTML;
11005
11006 default:
11007 return SIMPLEPIE_CONSTRUCT_NONE;
11008 }
11009 }
11010 return SIMPLEPIE_CONSTRUCT_TEXT;
11011 }
11012
11013 function atom_10_content_construct_type($attribs)
11014 {
11015 if (isset($attribs['']['type']))
11016 {
11017 $type = strtolower(trim($attribs['']['type']));
11018 switch ($type)
11019 {
11020 case 'text':
11021 return SIMPLEPIE_CONSTRUCT_TEXT;
11022
11023 case 'html':
11024 return SIMPLEPIE_CONSTRUCT_HTML;
11025
11026 case 'xhtml':
11027 return SIMPLEPIE_CONSTRUCT_XHTML;
11028 }
11029 if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
11030 {
11031 return SIMPLEPIE_CONSTRUCT_NONE;
11032 }
11033 else
11034 {
11035 return SIMPLEPIE_CONSTRUCT_BASE64;
11036 }
11037 }
11038 else
11039 {
11040 return SIMPLEPIE_CONSTRUCT_TEXT;
11041 }
11042 }
11043
11044 function is_isegment_nz_nc($string)
11045 {
11046 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);
11047 }
11048
11049 function space_seperated_tokens($string)
11050 {
11051 $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
11052 $string_length = strlen($string);
11053
11054 $position = strspn($string, $space_characters);
11055 $tokens = array();
11056
11057 while ($position < $string_length)
11058 {
11059 $len = strcspn($string, $space_characters, $position);
11060 $tokens[] = substr($string, $position, $len);
11061 $position += $len;
11062 $position += strspn($string, $space_characters, $position);
11063 }
11064
11065 return $tokens;
11066 }
11067
11068 function array_unique($array)
11069 {
11070 if (version_compare(PHP_VERSION, '5.2', '>='))
11071 {
11072 return array_unique($array);
11073 }
11074 else
11075 {
11076 $array = (array) $array;
11077 $new_array = array();
11078 $new_array_strings = array();
11079 foreach ($array as $key => $value)
11080 {
11081 if (is_object($value))
11082 {
11083 if (method_exists($value, '__toString'))
11084 {
11085 $cmp = $value->__toString();
11086 }
11087 else
11088 {
11089 trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
11090 }
11091 }
11092 elseif (is_array($value))
11093 {
11094 $cmp = (string) reset($value);
11095 }
11096 else
11097 {
11098 $cmp = (string) $value;
11099 }
11100 if (!in_array($cmp, $new_array_strings))
11101 {
11102 $new_array[$key] = $value;
11103 $new_array_strings[] = $cmp;
11104 }
11105 }
11106 return $new_array;
11107 }
11108 }
11109
11110 /**
11111 * Converts a unicode codepoint to a UTF-8 character
11112 *
11113 * @static
11114 * @access public
11115 * @param int $codepoint Unicode codepoint
11116 * @return string UTF-8 character
11117 */
11118 function codepoint_to_utf8($codepoint)
11119 {
11120 $codepoint = (int) $codepoint;
11121 if ($codepoint < 0)
11122 {
11123 return false;
11124 }
11125 else if ($codepoint <= 0x7f)
11126 {
11127 return chr($codepoint);
11128 }
11129 else if ($codepoint <= 0x7ff)
11130 {
11131 return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
11132 }
11133 else if ($codepoint <= 0xffff)
11134 {
11135 return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11136 }
11137 else if ($codepoint <= 0x10ffff)
11138 {
11139 return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11140 }
11141 else
11142 {
11143 // U+FFFD REPLACEMENT CHARACTER
11144 return "\xEF\xBF\xBD";
11145 }
11146 }
11147
11148 /**
11149 * Re-implementation of PHP 5's stripos()
11150 *
11151 * Returns the numeric position of the first occurrence of needle in the
11152 * haystack string.
11153 *
11154 * @static
11155 * @access string
11156 * @param object $haystack
11157 * @param string $needle Note that the needle may be a string of one or more
11158 * characters. If needle is not a string, it is converted to an integer
11159 * and applied as the ordinal value of a character.
11160 * @param int $offset The optional offset parameter allows you to specify which
11161 * character in haystack to start searching. The position returned is still
11162 * relative to the beginning of haystack.
11163 * @return bool If needle is not found, stripos() will return boolean false.
11164 */
11165 function stripos($haystack, $needle, $offset = 0)
11166 {
11167 if (function_exists('stripos'))
11168 {
11169 return stripos($haystack, $needle, $offset);
11170 }
11171 else
11172 {
11173 if (is_string($needle))
11174 {
11175 $needle = strtolower($needle);
11176 }
11177 elseif (is_int($needle) || is_bool($needle) || is_double($needle))
11178 {
11179 $needle = strtolower(chr($needle));
11180 }
11181 else
11182 {
11183 trigger_error('needle is not a string or an integer', E_USER_WARNING);
11184 return false;
11185 }
11186
11187 return strpos(strtolower($haystack), $needle, $offset);
11188 }
11189 }
11190
11191 /**
11192 * Similar to parse_str()
11193 *
11194 * Returns an associative array of name/value pairs, where the value is an
11195 * array of values that have used the same name
11196 *
11197 * @static
11198 * @access string
11199 * @param string $str The input string.
11200 * @return array
11201 */
11202 function parse_str($str)
11203 {
11204 $return = array();
11205 $str = explode('&', $str);
11206
11207 foreach ($str as $section)
11208 {
11209 if (strpos($section, '=') !== false)
11210 {
11211 list($name, $value) = explode('=', $section, 2);
11212 $return[urldecode($name)][] = urldecode($value);
11213 }
11214 else
11215 {
11216 $return[urldecode($section)][] = null;
11217 }
11218 }
11219
11220 return $return;
11221 }
11222
11223 /**
11224 * Detect XML encoding, as per XML 1.0 Appendix F.1
11225 *
11226 * @todo Add support for EBCDIC
11227 * @param string $data XML data
11228 * @return array Possible encodings
11229 */
11230 function xml_encoding($data)
11231 {
11232 // UTF-32 Big Endian BOM
11233 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
11234 {
11235 $encoding[] = 'UTF-32BE';
11236 }
11237 // UTF-32 Little Endian BOM
11238 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
11239 {
11240 $encoding[] = 'UTF-32LE';
11241 }
11242 // UTF-16 Big Endian BOM
11243 elseif (substr($data, 0, 2) === "\xFE\xFF")
11244 {
11245 $encoding[] = 'UTF-16BE';
11246 }
11247 // UTF-16 Little Endian BOM
11248 elseif (substr($data, 0, 2) === "\xFF\xFE")
11249 {
11250 $encoding[] = 'UTF-16LE';
11251 }
11252 // UTF-8 BOM
11253 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
11254 {
11255 $encoding[] = 'UTF-8';
11256 }
11257 // UTF-32 Big Endian Without BOM
11258 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")
11259 {
11260 if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
11261 {
11262 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
11263 if ($parser->parse())
11264 {
11265 $encoding[] = $parser->encoding;
11266 }
11267 }
11268 $encoding[] = 'UTF-32BE';
11269 }
11270 // UTF-32 Little Endian Without BOM
11271 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")
11272 {
11273 if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
11274 {
11275 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
11276 if ($parser->parse())
11277 {
11278 $encoding[] = $parser->encoding;
11279 }
11280 }
11281 $encoding[] = 'UTF-32LE';
11282 }
11283 // UTF-16 Big Endian Without BOM
11284 elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
11285 {
11286 if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
11287 {
11288 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
11289 if ($parser->parse())
11290 {
11291 $encoding[] = $parser->encoding;
11292 }
11293 }
11294 $encoding[] = 'UTF-16BE';
11295 }
11296 // UTF-16 Little Endian Without BOM
11297 elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
11298 {
11299 if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
11300 {
11301 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
11302 if ($parser->parse())
11303 {
11304 $encoding[] = $parser->encoding;
11305 }
11306 }
11307 $encoding[] = 'UTF-16LE';
11308 }
11309 // US-ASCII (or superset)
11310 elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
11311 {
11312 if ($pos = strpos($data, "\x3F\x3E"))
11313 {
11314 $parser =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
11315 if ($parser->parse())
11316 {
11317 $encoding[] = $parser->encoding;
11318 }
11319 }
11320 $encoding[] = 'UTF-8';
11321 }
11322 // Fallback to UTF-8
11323 else
11324 {
11325 $encoding[] = 'UTF-8';
11326 }
11327 return $encoding;
11328 }
11329
11330 function output_javascript()
11331 {
11332 if (function_exists('ob_gzhandler'))
11333 {
11334 ob_start('ob_gzhandler');
11335 }
11336 header('Content-type: text/javascript; charset: UTF-8');
11337 header('Cache-Control: must-revalidate');
11338 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
11339 ?>
11340 function embed_odeo(link) {
11341 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>');
11342 }
11343
11344 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
11345 if (placeholder != '') {
11346 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>');
11347 }
11348 else {
11349 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>');
11350 }
11351 }
11352
11353 function embed_flash(bgcolor, width, height, link, loop, type) {
11354 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>');
11355 }
11356
11357 function embed_flv(width, height, link, placeholder, loop, player) {
11358 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>');
11359 }
11360
11361 function embed_wmedia(width, height, link) {
11362 document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
11363 }
11364 <?php
11365 }
11366 }
11367
11368 /**
11369 * Decode HTML Entities
11370 *
11371 * This implements HTML5 as of revision 967 (2007-06-28)
11372 *
11373 * @package SimplePie
11374 */
11375 class SimplePie_Decode_HTML_Entities
11376 {
11377 /**
11378 * Data to be parsed
11379 *
11380 * @access private
11381 * @var string
11382 */
11383 var $data = '';
11384
11385 /**
11386 * Currently consumed bytes
11387 *
11388 * @access private
11389 * @var string
11390 */
11391 var $consumed = '';
11392
11393 /**
11394 * Position of the current byte being parsed
11395 *
11396 * @access private
11397 * @var int
11398 */
11399 var $position = 0;
11400
11401 /**
11402 * Create an instance of the class with the input data
11403 *
11404 * @access public
11405 * @param string $data Input data
11406 */
11407 function SimplePie_Decode_HTML_Entities($data)
11408 {
11409 $this->data = $data;
11410 }
11411
11412 /**
11413 * Parse the input data
11414 *
11415 * @access public
11416 * @return string Output data
11417 */
11418 function parse()
11419 {
11420 while (($this->position = strpos($this->data, '&', $this->position)) !== false)
11421 {
11422 $this->consume();
11423 $this->entity();
11424 $this->consumed = '';
11425 }
11426 return $this->data;
11427 }
11428
11429 /**
11430 * Consume the next byte
11431 *
11432 * @access private
11433 * @return mixed The next byte, or false, if there is no more data
11434 */
11435 function consume()
11436 {
11437 if (isset($this->data[$this->position]))
11438 {
11439 $this->consumed .= $this->data[$this->position];
11440 return $this->data[$this->position++];
11441 }
11442 else
11443 {
11444 return false;
11445 }
11446 }
11447
11448 /**
11449 * Consume a range of characters
11450 *
11451 * @access private
11452 * @param string $chars Characters to consume
11453 * @return mixed A series of characters that match the range, or false
11454 */
11455 function consume_range($chars)
11456 {
11457 if ($len = strspn($this->data, $chars, $this->position))
11458 {
11459 $data = substr($this->data, $this->position, $len);
11460 $this->consumed .= $data;
11461 $this->position += $len;
11462 return $data;
11463 }
11464 else
11465 {
11466 return false;
11467 }
11468 }
11469
11470 /**
11471 * Unconsume one byte
11472 *
11473 * @access private
11474 */
11475 function unconsume()
11476 {
11477 $this->consumed = substr($this->consumed, 0, -1);
11478 $this->position--;
11479 }
11480
11481 /**
11482 * Decode an entity
11483 *
11484 * @access private
11485 */
11486 function entity()
11487 {
11488 switch ($this->consume())
11489 {
11490 case "\x09":
11491 case "\x0A":
11492 case "\x0B":
11493 case "\x0B":
11494 case "\x0C":
11495 case "\x20":
11496 case "\x3C":
11497 case "\x26":
11498 case false:
11499 break;
11500
11501 case "\x23":
11502 switch ($this->consume())
11503 {
11504 case "\x78":
11505 case "\x58":
11506 $range = '0123456789ABCDEFabcdef';
11507 $hex = true;
11508 break;
11509
11510 default:
11511 $range = '0123456789';
11512 $hex = false;
11513 $this->unconsume();
11514 break;
11515 }
11516
11517 if ($codepoint = $this->consume_range($range))
11518 {
11519 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");
11520
11521 if ($hex)
11522 {
11523 $codepoint = hexdec($codepoint);
11524 }
11525 else
11526 {
11527 $codepoint = intval($codepoint);
11528 }
11529
11530 if (isset($windows_1252_specials[$codepoint]))
11531 {
11532 $replacement = $windows_1252_specials[$codepoint];
11533 }
11534 else
11535 {
11536 $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
11537 }
11538
11539 if (!in_array($this->consume(), array(';', false), true))
11540 {
11541 $this->unconsume();
11542 }
11543
11544 $consumed_length = strlen($this->consumed);
11545 $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
11546 $this->position += strlen($replacement) - $consumed_length;
11547 }
11548 break;
11549
11550 default:
11551 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");
11552
11553 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
11554 {
11555 $consumed = substr($this->consumed, 1);
11556 if (isset($entities[$consumed]))
11557 {
11558 $match = $consumed;
11559 }
11560 }
11561
11562 if ($match !== null)
11563 {
11564 $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
11565 $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
11566 }
11567 break;
11568 }
11569 }
11570 }
11571
11572 /**
11573 * IRI parser/serialiser
11574 *
11575 * @package SimplePie
11576 */
11577 class SimplePie_IRI
11578 {
11579 /**
11580 * Scheme
11581 *
11582 * @access private
11583 * @var string
11584 */
11585 var $scheme;
11586
11587 /**
11588 * User Information
11589 *
11590 * @access private
11591 * @var string
11592 */
11593 var $userinfo;
11594
11595 /**
11596 * Host
11597 *
11598 * @access private
11599 * @var string
11600 */
11601 var $host;
11602
11603 /**
11604 * Port
11605 *
11606 * @access private
11607 * @var string
11608 */
11609 var $port;
11610
11611 /**
11612 * Path
11613 *
11614 * @access private
11615 * @var string
11616 */
11617 var $path;
11618
11619 /**
11620 * Query
11621 *
11622 * @access private
11623 * @var string
11624 */
11625 var $query;
11626
11627 /**
11628 * Fragment
11629 *
11630 * @access private
11631 * @var string
11632 */
11633 var $fragment;
11634
11635 /**
11636 * Whether the object represents a valid IRI
11637 *
11638 * @access private
11639 * @var array
11640 */
11641 var $valid = array();
11642
11643 /**
11644 * Return the entire IRI when you try and read the object as a string
11645 *
11646 * @access public
11647 * @return string
11648 */
11649 function __toString()
11650 {
11651 return $this->get_iri();
11652 }
11653
11654 /**
11655 * Create a new IRI object, from a specified string
11656 *
11657 * @access public
11658 * @param string $iri
11659 * @return SimplePie_IRI
11660 */
11661 function SimplePie_IRI($iri)
11662 {
11663 $iri = (string) $iri;
11664 if ($iri !== '')
11665 {
11666 $parsed = $this->parse_iri($iri);
11667 $this->set_scheme($parsed['scheme']);
11668 $this->set_authority($parsed['authority']);
11669 $this->set_path($parsed['path']);
11670 $this->set_query($parsed['query']);
11671 $this->set_fragment($parsed['fragment']);
11672 }
11673 }
11674
11675 /**
11676 * Create a new IRI object by resolving a relative IRI
11677 *
11678 * @static
11679 * @access public
11680 * @param SimplePie_IRI $base Base IRI
11681 * @param string $relative Relative IRI
11682 * @return SimplePie_IRI
11683 */
11684 function absolutize($base, $relative)
11685 {
11686 $relative = (string) $relative;
11687 if ($relative !== '')
11688 {
11689 $relative =& new SimplePie_IRI($relative);
11690 if ($relative->get_scheme() !== null)
11691 {
11692 $target = $relative;
11693 }
11694 elseif ($base->get_iri() !== null)
11695 {
11696 if ($relative->get_authority() !== null)
11697 {
11698 $target = $relative;
11699 $target->set_scheme($base->get_scheme());
11700 }
11701 else
11702 {
11703 $target =& new SimplePie_IRI('');
11704 $target->set_scheme($base->get_scheme());
11705 $target->set_userinfo($base->get_userinfo());
11706 $target->set_host($base->get_host());
11707 $target->set_port($base->get_port());
11708 if ($relative->get_path() !== null)
11709 {
11710 if (strpos($relative->get_path(), '/') === 0)
11711 {
11712 $target->set_path($relative->get_path());
11713 }
11714 elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
11715 {
11716 $target->set_path('/' . $relative->get_path());
11717 }
11718 elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
11719 {
11720 $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
11721 }
11722 else
11723 {
11724 $target->set_path($relative->get_path());
11725 }
11726 $target->set_query($relative->get_query());
11727 }
11728 else
11729 {
11730 $target->set_path($base->get_path());
11731 if ($relative->get_query() !== null)
11732 {
11733 $target->set_query($relative->get_query());
11734 }
11735 elseif ($base->get_query() !== null)
11736 {
11737 $target->set_query($base->get_query());
11738 }
11739 }
11740 }
11741 $target->set_fragment($relative->get_fragment());
11742 }
11743 else
11744 {
11745 // No base URL, just return the relative URL
11746 $target = $relative;
11747 }
11748 }
11749 else
11750 {
11751 $target = $base;
11752 }
11753 return $target;
11754 }
11755
11756 /**
11757 * Parse an IRI into scheme/authority/path/query/fragment segments
11758 *
11759 * @access private
11760 * @param string $iri
11761 * @return array
11762 */
11763 function parse_iri($iri)
11764 {
11765 preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
11766 for ($i = count($match); $i <= 9; $i++)
11767 {
11768 $match[$i] = '';
11769 }
11770 return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
11771 }
11772
11773 /**
11774 * Remove dot segments from a path
11775 *
11776 * @access private
11777 * @param string $input
11778 * @return string
11779 */
11780 function remove_dot_segments($input)
11781 {
11782 $output = '';
11783 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
11784 {
11785 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
11786 if (strpos($input, '../') === 0)
11787 {
11788 $input = substr($input, 3);
11789 }
11790 elseif (strpos($input, './') === 0)
11791 {
11792 $input = substr($input, 2);
11793 }
11794 // 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,
11795 elseif (strpos($input, '/./') === 0)
11796 {
11797 $input = substr_replace($input, '/', 0, 3);
11798 }
11799 elseif ($input === '/.')
11800 {
11801 $input = '/';
11802 }
11803 // 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,
11804 elseif (strpos($input, '/../') === 0)
11805 {
11806 $input = substr_replace($input, '/', 0, 4);
11807 $output = substr_replace($output, '', strrpos($output, '/'));
11808 }
11809 elseif ($input === '/..')
11810 {
11811 $input = '/';
11812 $output = substr_replace($output, '', strrpos($output, '/'));
11813 }
11814 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
11815 elseif ($input === '.' || $input === '..')
11816 {
11817 $input = '';
11818 }
11819 // 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
11820 elseif (($pos = strpos($input, '/', 1)) !== false)
11821 {
11822 $output .= substr($input, 0, $pos);
11823 $input = substr_replace($input, '', 0, $pos);
11824 }
11825 else
11826 {
11827 $output .= $input;
11828 $input = '';
11829 }
11830 }
11831 return $output . $input;
11832 }
11833
11834 /**
11835 * Replace invalid character with percent encoding
11836 *
11837 * @access private
11838 * @param string $string Input string
11839 * @param string $valid_chars Valid characters
11840 * @param int $case Normalise case
11841 * @return string
11842 */
11843 function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE)
11844 {
11845 // Normalise case
11846 if ($case & SIMPLEPIE_LOWERCASE)
11847 {
11848 $string = strtolower($string);
11849 }
11850 elseif ($case & SIMPLEPIE_UPPERCASE)
11851 {
11852 $string = strtoupper($string);
11853 }
11854
11855 // Store position and string length (to avoid constantly recalculating this)
11856 $position = 0;
11857 $strlen = strlen($string);
11858
11859 // Loop as long as we have invalid characters, advancing the position to the next invalid character
11860 while (($position += strspn($string, $valid_chars, $position)) < $strlen)
11861 {
11862 // If we have a % character
11863 if ($string[$position] === '%')
11864 {
11865 // If we have a pct-encoded section
11866 if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2)
11867 {
11868 // Get the the represented character
11869 $chr = chr(hexdec(substr($string, $position + 1, 2)));
11870
11871 // If the character is valid, replace the pct-encoded with the actual character while normalising case
11872 if (strpos($valid_chars, $chr) !== false)
11873 {
11874 if ($case & SIMPLEPIE_LOWERCASE)
11875 {
11876 $chr = strtolower($chr);
11877 }
11878 elseif ($case & SIMPLEPIE_UPPERCASE)
11879 {
11880 $chr = strtoupper($chr);
11881 }
11882 $string = substr_replace($string, $chr, $position, 3);
11883 $strlen -= 2;
11884 $position++;
11885 }
11886
11887 // Otherwise just normalise the pct-encoded to uppercase
11888 else
11889 {
11890 $string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2);
11891 $position += 3;
11892 }
11893 }
11894 // If we don't have a pct-encoded section, just replace the % with its own esccaped form
11895 else
11896 {
11897 $string = substr_replace($string, '%25', $position, 1);
11898 $strlen += 2;
11899 $position += 3;
11900 }
11901 }
11902 // If we have an invalid character, change into its pct-encoded form
11903 else
11904 {
11905 $replacement = sprintf("%%%02X", ord($string[$position]));
11906 $string = str_replace($string[$position], $replacement, $string);
11907 $strlen = strlen($string);
11908 }
11909 }
11910 return $string;
11911 }
11912
11913 /**
11914 * Check if the object represents a valid IRI
11915 *
11916 * @access public
11917 * @return bool
11918 */
11919 function is_valid()
11920 {
11921 return array_sum($this->valid) === count($this->valid);
11922 }
11923
11924 /**
11925 * Set the scheme. Returns true on success, false on failure (if there are
11926 * any invalid characters).
11927 *
11928 * @access public
11929 * @param string $scheme
11930 * @return bool
11931 */
11932 function set_scheme($scheme)
11933 {
11934 if ($scheme === null || $scheme === '')
11935 {
11936 $this->scheme = null;
11937 }
11938 else
11939 {
11940 $len = strlen($scheme);
11941 switch (true)
11942 {
11943 case $len > 1:
11944 if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
11945 {
11946 $this->scheme = null;
11947 $this->valid[__FUNCTION__] = false;
11948 return false;
11949 }
11950
11951 case $len > 0:
11952 if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
11953 {
11954 $this->scheme = null;
11955 $this->valid[__FUNCTION__] = false;
11956 return false;
11957 }
11958 }
11959 $this->scheme = strtolower($scheme);
11960 }
11961 $this->valid[__FUNCTION__] = true;
11962 return true;
11963 }
11964
11965 /**
11966 * Set the authority. Returns true on success, false on failure (if there are
11967 * any invalid characters).
11968 *
11969 * @access public
11970 * @param string $authority
11971 * @return bool
11972 */
11973 function set_authority($authority)
11974 {
11975 if (($userinfo_end = strrpos($authority, '@')) !== false)
11976 {
11977 $userinfo = substr($authority, 0, $userinfo_end);
11978 $authority = substr($authority, $userinfo_end + 1);
11979 }
11980 else
11981 {
11982 $userinfo = null;
11983 }
11984
11985 if (($port_start = strpos($authority, ':')) !== false)
11986 {
11987 $port = substr($authority, $port_start + 1);
11988 $authority = substr($authority, 0, $port_start);
11989 }
11990 else
11991 {
11992 $port = null;
11993 }
11994
11995 return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
11996 }
11997
11998 /**
11999 * Set the userinfo.
12000 *
12001 * @access public
12002 * @param string $userinfo
12003 * @return bool
12004 */
12005 function set_userinfo($userinfo)
12006 {
12007 if ($userinfo === null || $userinfo === '')
12008 {
12009 $this->userinfo = null;
12010 }
12011 else
12012 {
12013 $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
12014 }
12015 $this->valid[__FUNCTION__] = true;
12016 return true;
12017 }
12018
12019 /**
12020 * Set the host. Returns true on success, false on failure (if there are
12021 * any invalid characters).
12022 *
12023 * @access public
12024 * @param string $host
12025 * @return bool
12026 */
12027 function set_host($host)
12028 {
12029 if ($host === null || $host === '')
12030 {
12031 $this->host = null;
12032 $this->valid[__FUNCTION__] = true;
12033 return true;
12034 }
12035 elseif ($host[0] === '[' && substr($host, -1) === ']')
12036 {
12037 if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
12038 {
12039 $this->host = $host;
12040 $this->valid[__FUNCTION__] = true;
12041 return true;
12042 }
12043 else
12044 {
12045 $this->host = null;
12046 $this->valid[__FUNCTION__] = false;
12047 return false;
12048 }
12049 }
12050 else
12051 {
12052 $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
12053 $this->valid[__FUNCTION__] = true;
12054 return true;
12055 }
12056 }
12057
12058 /**
12059 * Set the port. Returns true on success, false on failure (if there are
12060 * any invalid characters).
12061 *
12062 * @access public
12063 * @param string $port
12064 * @return bool
12065 */
12066 function set_port($port)
12067 {
12068 if ($port === null || $port === '')
12069 {
12070 $this->port = null;
12071 $this->valid[__FUNCTION__] = true;
12072 return true;
12073 }
12074 elseif (strspn($port, '0123456789') === strlen($port))
12075 {
12076 $this->port = (int) $port;
12077 $this->valid[__FUNCTION__] = true;
12078 return true;
12079 }
12080 else
12081 {
12082 $this->port = null;
12083 $this->valid[__FUNCTION__] = false;
12084 return false;
12085 }
12086 }
12087
12088 /**
12089 * Set the path.
12090 *
12091 * @access public
12092 * @param string $path
12093 * @return bool
12094 */
12095 function set_path($path)
12096 {
12097 if ($path === null || $path === '')
12098 {
12099 $this->path = null;
12100 $this->valid[__FUNCTION__] = true;
12101 return true;
12102 }
12103 elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
12104 {
12105 $this->path = null;
12106 $this->valid[__FUNCTION__] = false;
12107 return false;
12108 }
12109 else
12110 {
12111 $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
12112 if ($this->scheme !== null)
12113 {
12114 $this->path = $this->remove_dot_segments($this->path);
12115 }
12116 $this->valid[__FUNCTION__] = true;
12117 return true;
12118 }
12119 }
12120
12121 /**
12122 * Set the query.
12123 *
12124 * @access public
12125 * @param string $query
12126 * @return bool
12127 */
12128 function set_query($query)
12129 {
12130 if ($query === null || $query === '')
12131 {
12132 $this->query = null;
12133 }
12134 else
12135 {
12136 $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12137 }
12138 $this->valid[__FUNCTION__] = true;
12139 return true;
12140 }
12141
12142 /**
12143 * Set the fragment.
12144 *
12145 * @access public
12146 * @param string $fragment
12147 * @return bool
12148 */
12149 function set_fragment($fragment)
12150 {
12151 if ($fragment === null || $fragment === '')
12152 {
12153 $this->fragment = null;
12154 }
12155 else
12156 {
12157 $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12158 }
12159 $this->valid[__FUNCTION__] = true;
12160 return true;
12161 }
12162
12163 /**
12164 * Get the complete IRI
12165 *
12166 * @access public
12167 * @return string
12168 */
12169 function get_iri()
12170 {
12171 $iri = '';
12172 if ($this->scheme !== null)
12173 {
12174 $iri .= $this->scheme . ':';
12175 }
12176 if (($authority = $this->get_authority()) !== null)
12177 {
12178 $iri .= '//' . $authority;
12179 }
12180 if ($this->path !== null)
12181 {
12182 $iri .= $this->path;
12183 }
12184 if ($this->query !== null)
12185 {
12186 $iri .= '?' . $this->query;
12187 }
12188 if ($this->fragment !== null)
12189 {
12190 $iri .= '#' . $this->fragment;
12191 }
12192
12193 if ($iri !== '')
12194 {
12195 return $iri;
12196 }
12197 else
12198 {
12199 return null;
12200 }
12201 }
12202
12203 /**
12204 * Get the scheme
12205 *
12206 * @access public
12207 * @return string
12208 */
12209 function get_scheme()
12210 {
12211 return $this->scheme;
12212 }
12213
12214 /**
12215 * Get the complete authority
12216 *
12217 * @access public
12218 * @return string
12219 */
12220 function get_authority()
12221 {
12222 $authority = '';
12223 if ($this->userinfo !== null)
12224 {
12225 $authority .= $this->userinfo . '@';
12226 }
12227 if ($this->host !== null)
12228 {
12229 $authority .= $this->host;
12230 }
12231 if ($this->port !== null)
12232 {
12233 $authority .= ':' . $this->port;
12234 }
12235
12236 if ($authority !== '')
12237 {
12238 return $authority;
12239 }
12240 else
12241 {
12242 return null;
12243 }
12244 }
12245
12246 /**
12247 * Get the user information
12248 *
12249 * @access public
12250 * @return string
12251 */
12252 function get_userinfo()
12253 {
12254 return $this->userinfo;
12255 }
12256
12257 /**
12258 * Get the host
12259 *
12260 * @access public
12261 * @return string
12262 */
12263 function get_host()
12264 {
12265 return $this->host;
12266 }
12267
12268 /**
12269 * Get the port
12270 *
12271 * @access public
12272 * @return string
12273 */
12274 function get_port()
12275 {
12276 return $this->port;
12277 }
12278
12279 /**
12280 * Get the path
12281 *
12282 * @access public
12283 * @return string
12284 */
12285 function get_path()
12286 {
12287 return $this->path;
12288 }
12289
12290 /**
12291 * Get the query
12292 *
12293 * @access public
12294 * @return string
12295 */
12296 function get_query()
12297 {
12298 return $this->query;
12299 }
12300
12301 /**
12302 * Get the fragment
12303 *
12304 * @access public
12305 * @return string
12306 */
12307 function get_fragment()
12308 {
12309 return $this->fragment;
12310 }
12311 }
12312
12313 /**
12314 * Class to validate and to work with IPv6 addresses.
12315 *
12316 * @package SimplePie
12317 * @copyright 2003-2005 The PHP Group
12318 * @license http://www.opensource.org/licenses/bsd-license.php
12319 * @link http://pear.php.net/package/Net_IPv6
12320 * @author Alexander Merz <alexander.merz@web.de>
12321 * @author elfrink at introweb dot nl
12322 * @author Josh Peck <jmp at joshpeck dot org>
12323 * @author Geoffrey Sneddon <geoffers@gmail.com>
12324 */
12325 class SimplePie_Net_IPv6
12326 {
12327 /**
12328 * Removes a possible existing netmask specification of an IP address.
12329 *
12330 * @param string $ip the (compressed) IP as Hex representation
12331 * @return string the IP the without netmask
12332 * @since 1.1.0
12333 * @access public
12334 * @static
12335 */
12336 function removeNetmaskSpec($ip)
12337 {
12338 if (strpos($ip, '/') !== false)
12339 {
12340 list($addr, $nm) = explode('/', $ip);
12341 }
12342 else
12343 {
12344 $addr = $ip;
12345 }
12346 return $addr;
12347 }
12348
12349 /**
12350 * Uncompresses an IPv6 address
12351 *
12352 * RFC 2373 allows you to compress zeros in an address to '::'. This
12353 * function expects an valid IPv6 address and expands the '::' to
12354 * the required zeros.
12355 *
12356 * Example: FF01::101 -> FF01:0:0:0:0:0:0:101
12357 * ::1 -> 0:0:0:0:0:0:0:1
12358 *
12359 * @access public
12360 * @static
12361 * @param string $ip a valid IPv6-address (hex format)
12362 * @return string the uncompressed IPv6-address (hex format)
12363 */
12364 function Uncompress($ip)
12365 {
12366 $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
12367 $c1 = -1;
12368 $c2 = -1;
12369 if (strpos($ip, '::') !== false)
12370 {
12371 list($ip1, $ip2) = explode('::', $ip);
12372 if ($ip1 === '')
12373 {
12374 $c1 = -1;
12375 }
12376 else
12377 {
12378 $pos = 0;
12379 if (($pos = substr_count($ip1, ':')) > 0)
12380 {
12381 $c1 = $pos;
12382 }
12383 else
12384 {
12385 $c1 = 0;
12386 }
12387 }
12388 if ($ip2 === '')
12389 {
12390 $c2 = -1;
12391 }
12392 else
12393 {
12394 $pos = 0;
12395 if (($pos = substr_count($ip2, ':')) > 0)
12396 {
12397 $c2 = $pos;
12398 }
12399 else
12400 {
12401 $c2 = 0;
12402 }
12403 }
12404 if (strstr($ip2, '.'))
12405 {
12406 $c2++;
12407 }
12408 // ::
12409 if ($c1 === -1 && $c2 === -1)
12410 {
12411 $uip = '0:0:0:0:0:0:0:0';
12412 }
12413 // ::xxx
12414 else if ($c1 === -1)
12415 {
12416 $fill = str_repeat('0:', 7 - $c2);
12417 $uip = str_replace('::', $fill, $uip);
12418 }
12419 // xxx::
12420 else if ($c2 === -1)
12421 {
12422 $fill = str_repeat(':0', 7 - $c1);
12423 $uip = str_replace('::', $fill, $uip);
12424 }
12425 // xxx::xxx
12426 else
12427 {
12428 $fill = str_repeat(':0:', 6 - $c2 - $c1);
12429 $uip = str_replace('::', $fill, $uip);
12430 $uip = str_replace('::', ':', $uip);
12431 }
12432 }
12433 return $uip;
12434 }
12435
12436 /**
12437 * Splits an IPv6 address into the IPv6 and a possible IPv4 part
12438 *
12439 * RFC 2373 allows you to note the last two parts of an IPv6 address as
12440 * an IPv4 compatible address
12441 *
12442 * Example: 0:0:0:0:0:0:13.1.68.3
12443 * 0:0:0:0:0:FFFF:129.144.52.38
12444 *
12445 * @access public
12446 * @static
12447 * @param string $ip a valid IPv6-address (hex format)
12448 * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
12449 */
12450 function SplitV64($ip)
12451 {
12452 $ip = SimplePie_Net_IPv6::Uncompress($ip);
12453 if (strstr($ip, '.'))
12454 {
12455 $pos = strrpos($ip, ':');
12456 $ip[$pos] = '_';
12457 $ipPart = explode('_', $ip);
12458 return $ipPart;
12459 }
12460 else
12461 {
12462 return array($ip, '');
12463 }
12464 }
12465
12466 /**
12467 * Checks an IPv6 address
12468 *
12469 * Checks if the given IP is IPv6-compatible
12470 *
12471 * @access public
12472 * @static
12473 * @param string $ip a valid IPv6-address
12474 * @return bool true if $ip is an IPv6 address
12475 */
12476 function checkIPv6($ip)
12477 {
12478 $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
12479 $count = 0;
12480 if (!empty($ipPart[0]))
12481 {
12482 $ipv6 = explode(':', $ipPart[0]);
12483 for ($i = 0; $i < count($ipv6); $i++)
12484 {
12485 $dec = hexdec($ipv6[$i]);
12486 $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
12487 if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
12488 {
12489 $count++;
12490 }
12491 }
12492 if ($count === 8)
12493 {
12494 return true;
12495 }
12496 elseif ($count === 6 && !empty($ipPart[1]))
12497 {
12498 $ipv4 = explode('.', $ipPart[1]);
12499 $count = 0;
12500 foreach ($ipv4 as $ipv4_part)
12501 {
12502 if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
12503 {
12504 $count++;
12505 }
12506 }
12507 if ($count === 4)
12508 {
12509 return true;
12510 }
12511 }
12512 else
12513 {
12514 return false;
12515 }
12516
12517 }
12518 else
12519 {
12520 return false;
12521 }
12522 }
12523 }
12524
12525 /**
12526 * Date Parser
12527 *
12528 * @package SimplePie
12529 */
12530 class SimplePie_Parse_Date
12531 {
12532 /**
12533 * Input data
12534 *
12535 * @access protected
12536 * @var string
12537 */
12538 var $date;
12539
12540 /**
12541 * List of days, calendar day name => ordinal day number in the week
12542 *
12543 * @access protected
12544 * @var array
12545 */
12546 var $day = array(
12547 // English
12548 'mon' => 1,
12549 'monday' => 1,
12550 'tue' => 2,
12551 'tuesday' => 2,
12552 'wed' => 3,
12553 'wednesday' => 3,
12554 'thu' => 4,
12555 'thursday' => 4,
12556 'fri' => 5,
12557 'friday' => 5,
12558 'sat' => 6,
12559 'saturday' => 6,
12560 'sun' => 7,
12561 'sunday' => 7,
12562 // Dutch
12563 'maandag' => 1,
12564 'dinsdag' => 2,
12565 'woensdag' => 3,
12566 'donderdag' => 4,
12567 'vrijdag' => 5,
12568 'zaterdag' => 6,
12569 'zondag' => 7,
12570 // French
12571 'lundi' => 1,
12572 'mardi' => 2,
12573 'mercredi' => 3,
12574 'jeudi' => 4,
12575 'vendredi' => 5,
12576 'samedi' => 6,
12577 'dimanche' => 7,
12578 // German
12579 'montag' => 1,
12580 'dienstag' => 2,
12581 'mittwoch' => 3,
12582 'donnerstag' => 4,
12583 'freitag' => 5,
12584 'samstag' => 6,
12585 'sonnabend' => 6,
12586 'sonntag' => 7,
12587 // Italian
12588 'lunedì' => 1,
12589 'martedì' => 2,
12590 'mercoledì' => 3,
12591 'giovedì' => 4,
12592 'venerdì' => 5,
12593 'sabato' => 6,
12594 'domenica' => 7,
12595 // Spanish
12596 'lunes' => 1,
12597 'martes' => 2,
12598 'miércoles' => 3,
12599 'jueves' => 4,
12600 'viernes' => 5,
12601 'sábado' => 6,
12602 'domingo' => 7,
12603 // Finnish
12604 'maanantai' => 1,
12605 'tiistai' => 2,
12606 'keskiviikko' => 3,
12607 'torstai' => 4,
12608 'perjantai' => 5,
12609 'lauantai' => 6,
12610 'sunnuntai' => 7,
12611 // Hungarian
12612 'hétfő' => 1,
12613 'kedd' => 2,
12614 'szerda' => 3,
12615 'csütörtok' => 4,
12616 'péntek' => 5,
12617 'szombat' => 6,
12618 'vasárnap' => 7,
12619 // Greek
12620 'Δευ' => 1,
12621 'Τρι' => 2,
12622 'Τετ' => 3,
12623 'Πεμ' => 4,
12624 'Παρ' => 5,
12625 'Σαβ' => 6,
12626 'Κυρ' => 7,
12627 );
12628
12629 /**
12630 * List of months, calendar month name => calendar month number
12631 *
12632 * @access protected
12633 * @var array
12634 */
12635 var $month = array(
12636 // English
12637 'jan' => 1,
12638 'january' => 1,
12639 'feb' => 2,
12640 'february' => 2,
12641 'mar' => 3,
12642 'march' => 3,
12643 'apr' => 4,
12644 'april' => 4,
12645 'may' => 5,
12646 // No long form of May
12647 'jun' => 6,
12648 'june' => 6,
12649 'jul' => 7,
12650 'july' => 7,
12651 'aug' => 8,
12652 'august' => 8,
12653 'sep' => 9,
12654 'september' => 8,
12655 'oct' => 10,
12656 'october' => 10,
12657 'nov' => 11,
12658 'november' => 11,
12659 'dec' => 12,
12660 'december' => 12,
12661 // Dutch
12662 'januari' => 1,
12663 'februari' => 2,
12664 'maart' => 3,
12665 'april' => 4,
12666 'mei' => 5,
12667 'juni' => 6,
12668 'juli' => 7,
12669 'augustus' => 8,
12670 'september' => 9,
12671 'oktober' => 10,
12672 'november' => 11,
12673 'december' => 12,
12674 // French
12675 'janvier' => 1,
12676 'février' => 2,
12677 'mars' => 3,
12678 'avril' => 4,
12679 'mai' => 5,
12680 'juin' => 6,
12681 'juillet' => 7,
12682 'août' => 8,
12683 'septembre' => 9,
12684 'octobre' => 10,
12685 'novembre' => 11,
12686 'décembre' => 12,
12687 // German
12688 'januar' => 1,
12689 'februar' => 2,
12690 'märz' => 3,
12691 'april' => 4,
12692 'mai' => 5,
12693 'juni' => 6,
12694 'juli' => 7,
12695 'august' => 8,
12696 'september' => 9,
12697 'oktober' => 10,
12698 'november' => 11,
12699 'dezember' => 12,
12700 // Italian
12701 'gennaio' => 1,
12702 'febbraio' => 2,
12703 'marzo' => 3,
12704 'aprile' => 4,
12705 'maggio' => 5,
12706 'giugno' => 6,
12707 'luglio' => 7,
12708 'agosto' => 8,
12709 'settembre' => 9,
12710 'ottobre' => 10,
12711 'novembre' => 11,
12712 'dicembre' => 12,
12713 // Spanish
12714 'enero' => 1,
12715 'febrero' => 2,
12716 'marzo' => 3,
12717 'abril' => 4,
12718 'mayo' => 5,
12719 'junio' => 6,
12720 'julio' => 7,
12721 'agosto' => 8,
12722 'septiembre' => 9,
12723 'setiembre' => 9,
12724 'octubre' => 10,
12725 'noviembre' => 11,
12726 'diciembre' => 12,
12727 // Finnish
12728 'tammikuu' => 1,
12729 'helmikuu' => 2,
12730 'maaliskuu' => 3,
12731 'huhtikuu' => 4,
12732 'toukokuu' => 5,
12733 'kesäkuu' => 6,
12734 'heinäkuu' => 7,
12735 'elokuu' => 8,
12736 'suuskuu' => 9,
12737 'lokakuu' => 10,
12738 'marras' => 11,
12739 'joulukuu' => 12,
12740 // Hungarian
12741 'január' => 1,
12742 'február' => 2,
12743 'március' => 3,
12744 'április' => 4,
12745 'május' => 5,
12746 'június' => 6,
12747 'július' => 7,
12748 'augusztus' => 8,
12749 'szeptember' => 9,
12750 'október' => 10,
12751 'november' => 11,
12752 'december' => 12,
12753 // Greek
12754 'Ιαν' => 1,
12755 'Φεβ' => 2,
12756 'Μάώ' => 3,
12757 'Μαώ' => 3,
12758 'Απρ' => 4,
12759 'Μάι' => 5,
12760 'Μαϊ' => 5,
12761 'Μαι' => 5,
12762 'Ιούν' => 6,
12763 'Ιον' => 6,
12764 'Ιούλ' => 7,
12765 'Ιολ' => 7,
12766 'Αύγ' => 8,
12767 'Αυγ' => 8,
12768 'Σεπ' => 9,
12769 'Οκτ' => 10,
12770 'Νοέ' => 11,
12771 'Δεκ' => 12,
12772 );
12773
12774 /**
12775 * List of timezones, abbreviation => offset from UTC
12776 *
12777 * @access protected
12778 * @var array
12779 */
12780 var $timezone = array(
12781 'ACDT' => 37800,
12782 'ACIT' => 28800,
12783 'ACST' => 34200,
12784 'ACT' => -18000,
12785 'ACWDT' => 35100,
12786 'ACWST' => 31500,
12787 'AEDT' => 39600,
12788 'AEST' => 36000,
12789 'AFT' => 16200,
12790 'AKDT' => -28800,
12791 'AKST' => -32400,
12792 'AMDT' => 18000,
12793 'AMT' => -14400,
12794 'ANAST' => 46800,
12795 'ANAT' => 43200,
12796 'ART' => -10800,
12797 'AZOST' => -3600,
12798 'AZST' => 18000,
12799 'AZT' => 14400,
12800 'BIOT' => 21600,
12801 'BIT' => -43200,
12802 'BOT' => -14400,
12803 'BRST' => -7200,
12804 'BRT' => -10800,
12805 'BST' => 3600,
12806 'BTT' => 21600,
12807 'CAST' => 18000,
12808 'CAT' => 7200,
12809 'CCT' => 23400,
12810 'CDT' => -18000,
12811 'CEDT' => 7200,
12812 'CET' => 3600,
12813 'CGST' => -7200,
12814 'CGT' => -10800,
12815 'CHADT' => 49500,
12816 'CHAST' => 45900,
12817 'CIST' => -28800,
12818 'CKT' => -36000,
12819 'CLDT' => -10800,
12820 'CLST' => -14400,
12821 'COT' => -18000,
12822 'CST' => -21600,
12823 'CVT' => -3600,
12824 'CXT' => 25200,
12825 'DAVT' => 25200,
12826 'DTAT' => 36000,
12827 'EADT' => -18000,
12828 'EAST' => -21600,
12829 'EAT' => 10800,
12830 'ECT' => -18000,
12831 'EDT' => -14400,
12832 'EEST' => 10800,
12833 'EET' => 7200,
12834 'EGT' => -3600,
12835 'EKST' => 21600,
12836 'EST' => -18000,
12837 'FJT' => 43200,
12838 'FKDT' => -10800,
12839 'FKST' => -14400,
12840 'FNT' => -7200,
12841 'GALT' => -21600,
12842 'GEDT' => 14400,
12843 'GEST' => 10800,
12844 'GFT' => -10800,
12845 'GILT' => 43200,
12846 'GIT' => -32400,
12847 'GST' => 14400,
12848 'GST' => -7200,
12849 'GYT' => -14400,
12850 'HAA' => -10800,
12851 'HAC' => -18000,
12852 'HADT' => -32400,
12853 'HAE' => -14400,
12854 'HAP' => -25200,
12855 'HAR' => -21600,
12856 'HAST' => -36000,
12857 'HAT' => -9000,
12858 'HAY' => -28800,
12859 'HKST' => 28800,
12860 'HMT' => 18000,
12861 'HNA' => -14400,
12862 'HNC' => -21600,
12863 'HNE' => -18000,
12864 'HNP' => -28800,
12865 'HNR' => -25200,
12866 'HNT' => -12600,
12867 'HNY' => -32400,
12868 'IRDT' => 16200,
12869 'IRKST' => 32400,
12870 'IRKT' => 28800,
12871 'IRST' => 12600,
12872 'JFDT' => -10800,
12873 'JFST' => -14400,
12874 'JST' => 32400,
12875 'KGST' => 21600,
12876 'KGT' => 18000,
12877 'KOST' => 39600,
12878 'KOVST' => 28800,
12879 'KOVT' => 25200,
12880 'KRAST' => 28800,
12881 'KRAT' => 25200,
12882 'KST' => 32400,
12883 'LHDT' => 39600,
12884 'LHST' => 37800,
12885 'LINT' => 50400,
12886 'LKT' => 21600,
12887 'MAGST' => 43200,
12888 'MAGT' => 39600,
12889 'MAWT' => 21600,
12890 'MDT' => -21600,
12891 'MESZ' => 7200,
12892 'MEZ' => 3600,
12893 'MHT' => 43200,
12894 'MIT' => -34200,
12895 'MNST' => 32400,
12896 'MSDT' => 14400,
12897 'MSST' => 10800,
12898 'MST' => -25200,
12899 'MUT' => 14400,
12900 'MVT' => 18000,
12901 'MYT' => 28800,
12902 'NCT' => 39600,
12903 'NDT' => -9000,
12904 'NFT' => 41400,
12905 'NMIT' => 36000,
12906 'NOVST' => 25200,
12907 'NOVT' => 21600,
12908 'NPT' => 20700,
12909 'NRT' => 43200,
12910 'NST' => -12600,
12911 'NUT' => -39600,
12912 'NZDT' => 46800,
12913 'NZST' => 43200,
12914 'OMSST' => 25200,
12915 'OMST' => 21600,
12916 'PDT' => -25200,
12917 'PET' => -18000,
12918 'PETST' => 46800,
12919 'PETT' => 43200,
12920 'PGT' => 36000,
12921 'PHOT' => 46800,
12922 'PHT' => 28800,
12923 'PKT' => 18000,
12924 'PMDT' => -7200,
12925 'PMST' => -10800,
12926 'PONT' => 39600,
12927 'PST' => -28800,
12928 'PWT' => 32400,
12929 'PYST' => -10800,
12930 'PYT' => -14400,
12931 'RET' => 14400,
12932 'ROTT' => -10800,
12933 'SAMST' => 18000,
12934 'SAMT' => 14400,
12935 'SAST' => 7200,
12936 'SBT' => 39600,
12937 'SCDT' => 46800,
12938 'SCST' => 43200,
12939 'SCT' => 14400,
12940 'SEST' => 3600,
12941 'SGT' => 28800,
12942 'SIT' => 28800,
12943 'SRT' => -10800,
12944 'SST' => -39600,
12945 'SYST' => 10800,
12946 'SYT' => 7200,
12947 'TFT' => 18000,
12948 'THAT' => -36000,
12949 'TJT' => 18000,
12950 'TKT' => -36000,
12951 'TMT' => 18000,
12952 'TOT' => 46800,
12953 'TPT' => 32400,
12954 'TRUT' => 36000,
12955 'TVT' => 43200,
12956 'TWT' => 28800,
12957 'UYST' => -7200,
12958 'UYT' => -10800,
12959 'UZT' => 18000,
12960 'VET' => -14400,
12961 'VLAST' => 39600,
12962 'VLAT' => 36000,
12963 'VOST' => 21600,
12964 'VUT' => 39600,
12965 'WAST' => 7200,
12966 'WAT' => 3600,
12967 'WDT' => 32400,
12968 'WEST' => 3600,
12969 'WFT' => 43200,
12970 'WIB' => 25200,
12971 'WIT' => 32400,
12972 'WITA' => 28800,
12973 'WKST' => 18000,
12974 'WST' => 28800,
12975 'YAKST' => 36000,
12976 'YAKT' => 32400,
12977 'YAPT' => 36000,
12978 'YEKST' => 21600,
12979 'YEKT' => 18000,
12980 );
12981
12982 /**
12983 * Cached PCRE for SimplePie_Parse_Date::$day
12984 *
12985 * @access protected
12986 * @var string
12987 */
12988 var $day_pcre;
12989
12990 /**
12991 * Cached PCRE for SimplePie_Parse_Date::$month
12992 *
12993 * @access protected
12994 * @var string
12995 */
12996 var $month_pcre;
12997
12998 /**
12999 * Array of user-added callback methods
13000 *
13001 * @access private
13002 * @var array
13003 */
13004 var $built_in = array();
13005
13006 /**
13007 * Array of user-added callback methods
13008 *
13009 * @access private
13010 * @var array
13011 */
13012 var $user = array();
13013
13014 /**
13015 * Create new SimplePie_Parse_Date object, and set self::day_pcre,
13016 * self::month_pcre, and self::built_in
13017 *
13018 * @access private
13019 */
13020 function SimplePie_Parse_Date()
13021 {
13022 $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
13023 $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
13024
13025 static $cache;
13026 if (!isset($cache[get_class($this)]))
13027 {
13028 $all_methods = get_class_methods($this);
13029
13030 foreach ($all_methods as $method)
13031 {
13032 if (strtolower(substr($method, 0, 5)) === 'date_')
13033 {
13034 $cache[get_class($this)][] = $method;
13035 }
13036 }
13037 }
13038
13039 foreach ($cache[get_class($this)] as $method)
13040 {
13041 $this->built_in[] = $method;
13042 }
13043 }
13044
13045 /**
13046 * Get the object
13047 *
13048 * @access public
13049 */
13050 function get()
13051 {
13052 static $object;
13053 if (!$object)
13054 {
13055 $object =& new SimplePie_Parse_Date;
13056 }
13057 return $object;
13058 }
13059
13060 /**
13061 * Parse a date
13062 *
13063 * @final
13064 * @access public
13065 * @param string $date Date to parse
13066 * @return int Timestamp corresponding to date string, or false on failure
13067 */
13068 function parse($date)
13069 {
13070 foreach ($this->user as $method)
13071 {
13072 if (($returned = call_user_func($method, $date)) !== false)
13073 {
13074 return $returned;
13075 }
13076 }
13077
13078 foreach ($this->built_in as $method)
13079 {
13080 if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
13081 {
13082 return $returned;
13083 }
13084 }
13085
13086 return false;
13087 }
13088
13089 /**
13090 * Add a callback method to parse a date
13091 *
13092 * @final
13093 * @access public
13094 * @param callback $callback
13095 */
13096 function add_callback($callback)
13097 {
13098 if (is_callable($callback))
13099 {
13100 $this->user[] = $callback;
13101 }
13102 else
13103 {
13104 trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
13105 }
13106 }
13107
13108 /**
13109 * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
13110 * well as allowing any of upper or lower case "T", horizontal tabs, or
13111 * spaces to be used as the time seperator (including more than one))
13112 *
13113 * @access protected
13114 * @return int Timestamp
13115 */
13116 function date_w3cdtf($date)
13117 {
13118 static $pcre;
13119 if (!$pcre)
13120 {
13121 $year = '([0-9]{4})';
13122 $month = $day = $hour = $minute = $second = '([0-9]{2})';
13123 $decimal = '([0-9]*)';
13124 $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
13125 $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
13126 }
13127 if (preg_match($pcre, $date, $match))
13128 {
13129 /*
13130 Capturing subpatterns:
13131 1: Year
13132 2: Month
13133 3: Day
13134 4: Hour
13135 5: Minute
13136 6: Second
13137 7: Decimal fraction of a second
13138 8: Zulu
13139 9: Timezone ±
13140 10: Timezone hours
13141 11: Timezone minutes
13142 */
13143
13144 // Fill in empty matches
13145 for ($i = count($match); $i <= 3; $i++)
13146 {
13147 $match[$i] = '1';
13148 }
13149
13150 for ($i = count($match); $i <= 7; $i++)
13151 {
13152 $match[$i] = '0';
13153 }
13154
13155 // Numeric timezone
13156 if (isset($match[9]) && $match[9] !== '')
13157 {
13158 $timezone = $match[10] * 3600;
13159 $timezone += $match[11] * 60;
13160 if ($match[9] === '-')
13161 {
13162 $timezone = 0 - $timezone;
13163 }
13164 }
13165 else
13166 {
13167 $timezone = 0;
13168 }
13169
13170 // Convert the number of seconds to an integer, taking decimals into account
13171 $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
13172
13173 return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
13174 }
13175 else
13176 {
13177 return false;
13178 }
13179 }
13180
13181 /**
13182 * Remove RFC822 comments
13183 *
13184 * @access protected
13185 * @param string $data Data to strip comments from
13186 * @return string Comment stripped string
13187 */
13188 function remove_rfc2822_comments($string)
13189 {
13190 $string = (string) $string;
13191 $position = 0;
13192 $length = strlen($string);
13193 $depth = 0;
13194
13195 $output = '';
13196
13197 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
13198 {
13199 $output .= substr($string, $position, $pos - $position);
13200 $position = $pos + 1;
13201 if ($string[$pos - 1] !== '\\')
13202 {
13203 $depth++;
13204 while ($depth && $position < $length)
13205 {
13206 $position += strcspn($string, '()', $position);
13207 if ($string[$position - 1] === '\\')
13208 {
13209 $position++;
13210 continue;
13211 }
13212 elseif (isset($string[$position]))
13213 {
13214 switch ($string[$position])
13215 {
13216 case '(':
13217 $depth++;
13218 break;
13219
13220 case ')':
13221 $depth--;
13222 break;
13223 }
13224 $position++;
13225 }
13226 else
13227 {
13228 break;
13229 }
13230 }
13231 }
13232 else
13233 {
13234 $output .= '(';
13235 }
13236 }
13237 $output .= substr($string, $position);
13238
13239 return $output;
13240 }
13241
13242 /**
13243 * Parse RFC2822's date format
13244 *
13245 * @access protected
13246 * @return int Timestamp
13247 */
13248 function date_rfc2822($date)
13249 {
13250 static $pcre;
13251 if (!$pcre)
13252 {
13253 $wsp = '[\x09\x20]';
13254 $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
13255 $optional_fws = $fws . '?';
13256 $day_name = $this->day_pcre;
13257 $month = $this->month_pcre;
13258 $day = '([0-9]{1,2})';
13259 $hour = $minute = $second = '([0-9]{2})';
13260 $year = '([0-9]{2,4})';
13261 $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
13262 $character_zone = '([A-Z]{1,5})';
13263 $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
13264 $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';
13265 }
13266 if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
13267 {
13268 /*
13269 Capturing subpatterns:
13270 1: Day name
13271 2: Day
13272 3: Month
13273 4: Year
13274 5: Hour
13275 6: Minute
13276 7: Second
13277 8: Timezone ±
13278 9: Timezone hours
13279 10: Timezone minutes
13280 11: Alphabetic timezone
13281 */
13282
13283 // Find the month number
13284 $month = $this->month[strtolower($match[3])];
13285
13286 // Numeric timezone
13287 if ($match[8] !== '')
13288 {
13289 $timezone = $match[9] * 3600;
13290 $timezone += $match[10] * 60;
13291 if ($match[8] === '-')
13292 {
13293 $timezone = 0 - $timezone;
13294 }
13295 }
13296 // Character timezone
13297 elseif (isset($this->timezone[strtoupper($match[11])]))
13298 {
13299 $timezone = $this->timezone[strtoupper($match[11])];
13300 }
13301 // Assume everything else to be -0000
13302 else
13303 {
13304 $timezone = 0;
13305 }
13306
13307 // Deal with 2/3 digit years
13308 if ($match[4] < 50)
13309 {
13310 $match[4] += 2000;
13311 }
13312 elseif ($match[4] < 1000)
13313 {
13314 $match[4] += 1900;
13315 }
13316
13317 // Second is optional, if it is empty set it to zero
13318 if ($match[7] !== '')
13319 {
13320 $second = $match[7];
13321 }
13322 else
13323 {
13324 $second = 0;
13325 }
13326
13327 return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
13328 }
13329 else
13330 {
13331 return false;
13332 }
13333 }
13334
13335 /**
13336 * Parse RFC850's date format
13337 *
13338 * @access protected
13339 * @return int Timestamp
13340 */
13341 function date_rfc850($date)
13342 {
13343 static $pcre;
13344 if (!$pcre)
13345 {
13346 $space = '[\x09\x20]+';
13347 $day_name = $this->day_pcre;
13348 $month = $this->month_pcre;
13349 $day = '([0-9]{1,2})';
13350 $year = $hour = $minute = $second = '([0-9]{2})';
13351 $zone = '([A-Z]{1,5})';
13352 $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
13353 }
13354 if (preg_match($pcre, $date, $match))
13355 {
13356 /*
13357 Capturing subpatterns:
13358 1: Day name
13359 2: Day
13360 3: Month
13361 4: Year
13362 5: Hour
13363 6: Minute
13364 7: Second
13365 8: Timezone
13366 */
13367
13368 // Month
13369 $month = $this->month[strtolower($match[3])];
13370
13371 // Character timezone
13372 if (isset($this->timezone[strtoupper($match[8])]))
13373 {
13374 $timezone = $this->timezone[strtoupper($match[8])];
13375 }
13376 // Assume everything else to be -0000
13377 else
13378 {
13379 $timezone = 0;
13380 }
13381
13382 // Deal with 2 digit year
13383 if ($match[4] < 50)
13384 {
13385 $match[4] += 2000;
13386 }
13387 else
13388 {
13389 $match[4] += 1900;
13390 }
13391
13392 return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
13393 }
13394 else
13395 {
13396 return false;
13397 }
13398 }
13399
13400 /**
13401 * Parse C99's asctime()'s date format
13402 *
13403 * @access protected
13404 * @return int Timestamp
13405 */
13406 function date_asctime($date)
13407 {
13408 static $pcre;
13409 if (!$pcre)
13410 {
13411 $space = '[\x09\x20]+';
13412 $wday_name = $this->day_pcre;
13413 $mon_name = $this->month_pcre;
13414 $day = '([0-9]{1,2})';
13415 $hour = $sec = $min = '([0-9]{2})';
13416 $year = '([0-9]{4})';
13417 $terminator = '\x0A?\x00?';
13418 $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
13419 }
13420 if (preg_match($pcre, $date, $match))
13421 {
13422 /*
13423 Capturing subpatterns:
13424 1: Day name
13425 2: Month
13426 3: Day
13427 4: Hour
13428 5: Minute
13429 6: Second
13430 7: Year
13431 */
13432
13433 $month = $this->month[strtolower($match[2])];
13434 return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
13435 }
13436 else
13437 {
13438 return false;
13439 }
13440 }
13441
13442 /**
13443 * Parse dates using strtotime()
13444 *
13445 * @access protected
13446 * @return int Timestamp
13447 */
13448 function date_strtotime($date)
13449 {
13450 $strtotime = strtotime($date);
13451 if ($strtotime === -1 || $strtotime === false)
13452 {
13453 return false;
13454 }
13455 else
13456 {
13457 return $strtotime;
13458 }
13459 }
13460 }
13461
13462 /**
13463 * Content-type sniffing
13464 *
13465 * @package SimplePie
13466 */
13467 class SimplePie_Content_Type_Sniffer
13468 {
13469 /**
13470 * File object
13471 *
13472 * @var SimplePie_File
13473 * @access private
13474 */
13475 var $file;
13476
13477 /**
13478 * Create an instance of the class with the input file
13479 *
13480 * @access public
13481 * @param SimplePie_Content_Type_Sniffer $file Input file
13482 */
13483 function SimplePie_Content_Type_Sniffer($file)
13484 {
13485 $this->file = $file;
13486 }
13487
13488 /**
13489 * Get the Content-Type of the specified file
13490 *
13491 * @access public
13492 * @return string Actual Content-Type
13493 */
13494 function get_type()
13495 {
13496 if (isset($this->file->headers['content-type']))
13497 {
13498 if (!isset($this->file->headers['content-encoding'])
13499 && ($this->file->headers['content-type'] === 'text/plain'
13500 || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
13501 || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
13502 {
13503 return $this->text_or_binary();
13504 }
13505
13506 if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
13507 {
13508 $official = substr($this->file->headers['content-type'], 0, $pos);
13509 }
13510 else
13511 {
13512 $official = $this->file->headers['content-type'];
13513 }
13514 $official = strtolower($official);
13515
13516 if ($official === 'unknown/unknown'
13517 || $official === 'application/unknown')
13518 {
13519 return $this->unknown();
13520 }
13521 elseif (substr($official, -4) === '+xml'
13522 || $official === 'text/xml'
13523 || $official === 'application/xml')
13524 {
13525 return $official;
13526 }
13527 elseif (substr($official, 0, 6) === 'image/')
13528 {
13529 if ($return = $this->image())
13530 {
13531 return $return;
13532 }
13533 else
13534 {
13535 return $official;
13536 }
13537 }
13538 elseif ($official === 'text/html')
13539 {
13540 return $this->feed_or_html();
13541 }
13542 else
13543 {
13544 return $official;
13545 }
13546 }
13547 else
13548 {
13549 return $this->unknown();
13550 }
13551 }
13552
13553 /**
13554 * Sniff text or binary
13555 *
13556 * @access private
13557 * @return string Actual Content-Type
13558 */
13559 function text_or_binary()
13560 {
13561 if (substr($this->file->body, 0, 2) === "\xFE\xFF"
13562 || substr($this->file->body, 0, 2) === "\xFF\xFE"
13563 || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
13564 || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
13565 {
13566 return 'text/plain';
13567 }
13568 elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
13569 {
13570 return 'application/octect-stream';
13571 }
13572 else
13573 {
13574 return 'text/plain';
13575 }
13576 }
13577
13578 /**
13579 * Sniff unknown
13580 *
13581 * @access private
13582 * @return string Actual Content-Type
13583 */
13584 function unknown()
13585 {
13586 $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
13587 if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
13588 || strtolower(substr($this->file->body, $ws, 5)) === '<html'
13589 || strtolower(substr($this->file->body, $ws, 7)) === '<script')
13590 {
13591 return 'text/html';
13592 }
13593 elseif (substr($this->file->body, 0, 5) === '%PDF-')
13594 {
13595 return 'application/pdf';
13596 }
13597 elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
13598 {
13599 return 'application/postscript';
13600 }
13601 elseif (substr($this->file->body, 0, 6) === 'GIF87a'
13602 || substr($this->file->body, 0, 6) === 'GIF89a')
13603 {
13604 return 'image/gif';
13605 }
13606 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13607 {
13608 return 'image/png';
13609 }
13610 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13611 {
13612 return 'image/jpeg';
13613 }
13614 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13615 {
13616 return 'image/bmp';
13617 }
13618 else
13619 {
13620 return $this->text_or_binary();
13621 }
13622 }
13623
13624 /**
13625 * Sniff images
13626 *
13627 * @access private
13628 * @return string Actual Content-Type
13629 */
13630 function image()
13631 {
13632 if (substr($this->file->body, 0, 6) === 'GIF87a'
13633 || substr($this->file->body, 0, 6) === 'GIF89a')
13634 {
13635 return 'image/gif';
13636 }
13637 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13638 {
13639 return 'image/png';
13640 }
13641 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13642 {
13643 return 'image/jpeg';
13644 }
13645 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13646 {
13647 return 'image/bmp';
13648 }
13649 else
13650 {
13651 return false;
13652 }
13653 }
13654
13655 /**
13656 * Sniff HTML
13657 *
13658 * @access private
13659 * @return string Actual Content-Type
13660 */
13661 function feed_or_html()
13662 {
13663 $len = strlen($this->file->body);
13664 $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
13665
13666 while ($pos < $len)
13667 {
13668 switch ($this->file->body[$pos])
13669 {
13670 case "\x09":
13671 case "\x0A":
13672 case "\x0D":
13673 case "\x20":
13674 $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
13675 continue 2;
13676
13677 case '<':
13678 $pos++;
13679 break;
13680
13681 default:
13682 return 'text/html';
13683 }
13684
13685 if (substr($this->file->body, $pos, 3) === '!--')
13686 {
13687 $pos += 3;
13688 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
13689 {
13690 $pos += 3;
13691 }
13692 else
13693 {
13694 return 'text/html';
13695 }
13696 }
13697 elseif (substr($this->file->body, $pos, 1) === '!')
13698 {
13699 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
13700 {
13701 $pos++;
13702 }
13703 else
13704 {
13705 return 'text/html';
13706 }
13707 }
13708 elseif (substr($this->file->body, $pos, 1) === '?')
13709 {
13710 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
13711 {
13712 $pos += 2;
13713 }
13714 else
13715 {
13716 return 'text/html';
13717 }
13718 }
13719 elseif (substr($this->file->body, $pos, 3) === 'rss'
13720 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
13721 {
13722 return 'application/rss+xml';
13723 }
13724 elseif (substr($this->file->body, $pos, 4) === 'feed')
13725 {
13726 return 'application/atom+xml';
13727 }
13728 else
13729 {
13730 return 'text/html';
13731 }
13732 }
13733
13734 return 'text/html';
13735 }
13736 }
13737
13738 /**
13739 * Parses the XML Declaration
13740 *
13741 * @package SimplePie
13742 */
13743 class SimplePie_XML_Declaration_Parser
13744 {
13745 /**
13746 * XML Version
13747 *
13748 * @access public
13749 * @var string
13750 */
13751 var $version = '1.0';
13752
13753 /**
13754 * Encoding
13755 *
13756 * @access public
13757 * @var string
13758 */
13759 var $encoding = 'UTF-8';
13760
13761 /**
13762 * Standalone
13763 *
13764 * @access public
13765 * @var bool
13766 */
13767 var $standalone = false;
13768
13769 /**
13770 * Current state of the state machine
13771 *
13772 * @access private
13773 * @var string
13774 */
13775 var $state = 'before_version_name';
13776
13777 /**
13778 * Input data
13779 *
13780 * @access private
13781 * @var string
13782 */
13783 var $data = '';
13784
13785 /**
13786 * Input data length (to avoid calling strlen() everytime this is needed)
13787 *
13788 * @access private
13789 * @var int
13790 */
13791 var $data_length = 0;
13792
13793 /**
13794 * Current position of the pointer
13795 *
13796 * @var int
13797 * @access private
13798 */
13799 var $position = 0;
13800
13801 /**
13802 * Create an instance of the class with the input data
13803 *
13804 * @access public
13805 * @param string $data Input data
13806 */
13807 function SimplePie_XML_Declaration_Parser($data)
13808 {
13809 $this->data = $data;
13810 $this->data_length = strlen($this->data);
13811 }
13812
13813 /**
13814 * Parse the input data
13815 *
13816 * @access public
13817 * @return bool true on success, false on failure
13818 */
13819 function parse()
13820 {
13821 while ($this->state && $this->state !== 'emit' && $this->has_data())
13822 {
13823 $state = $this->state;
13824 $this->$state();
13825 }
13826 $this->data = '';
13827 if ($this->state === 'emit')
13828 {
13829 return true;
13830 }
13831 else
13832 {
13833 $this->version = '';
13834 $this->encoding = '';
13835 $this->standalone = '';
13836 return false;
13837 }
13838 }
13839
13840 /**
13841 * Check whether there is data beyond the pointer
13842 *
13843 * @access private
13844 * @return bool true if there is further data, false if not
13845 */
13846 function has_data()
13847 {
13848 return (bool) ($this->position < $this->data_length);
13849 }
13850
13851 /**
13852 * Advance past any whitespace
13853 *
13854 * @return int Number of whitespace characters passed
13855 */
13856 function skip_whitespace()
13857 {
13858 $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
13859 $this->position += $whitespace;
13860 return $whitespace;
13861 }
13862
13863 /**
13864 * Read value
13865 */
13866 function get_value()
13867 {
13868 $quote = substr($this->data, $this->position, 1);
13869 if ($quote === '"' || $quote === "'")
13870 {
13871 $this->position++;
13872 $len = strcspn($this->data, $quote, $this->position);
13873 if ($this->has_data())
13874 {
13875 $value = substr($this->data, $this->position, $len);
13876 $this->position += $len + 1;
13877 return $value;
13878 }
13879 }
13880 return false;
13881 }
13882
13883 function before_version_name()
13884 {
13885 if ($this->skip_whitespace())
13886 {
13887 $this->state = 'version_name';
13888 }
13889 else
13890 {
13891 $this->state = false;
13892 }
13893 }
13894
13895 function version_name()
13896 {
13897 if (substr($this->data, $this->position, 7) === 'version')
13898 {
13899 $this->position += 7;
13900 $this->skip_whitespace();
13901 $this->state = 'version_equals';
13902 }
13903 else
13904 {
13905 $this->state = false;
13906 }
13907 }
13908
13909 function version_equals()
13910 {
13911 if (substr($this->data, $this->position, 1) === '=')
13912 {
13913 $this->position++;
13914 $this->skip_whitespace();
13915 $this->state = 'version_value';
13916 }
13917 else
13918 {
13919 $this->state = false;
13920 }
13921 }
13922
13923 function version_value()
13924 {
13925 if ($this->version = $this->get_value())
13926 {
13927 $this->skip_whitespace();
13928 if ($this->has_data())
13929 {
13930 $this->state = 'encoding_name';
13931 }
13932 else
13933 {
13934 $this->state = 'emit';
13935 }
13936 }
13937 else
13938 {
13939 $this->state = 'standalone_name';
13940 }
13941 }
13942
13943 function encoding_name()
13944 {
13945 if (substr($this->data, $this->position, 8) === 'encoding')
13946 {
13947 $this->position += 8;
13948 $this->skip_whitespace();
13949 $this->state = 'encoding_equals';
13950 }
13951 else
13952 {
13953 $this->state = false;
13954 }
13955 }
13956
13957 function encoding_equals()
13958 {
13959 if (substr($this->data, $this->position, 1) === '=')
13960 {
13961 $this->position++;
13962 $this->skip_whitespace();
13963 $this->state = 'encoding_value';
13964 }
13965 else
13966 {
13967 $this->state = false;
13968 }
13969 }
13970
13971 function encoding_value()
13972 {
13973 if ($this->encoding = $this->get_value())
13974 {
13975 $this->skip_whitespace();
13976 if ($this->has_data())
13977 {
13978 $this->state = 'standalone_name';
13979 }
13980 else
13981 {
13982 $this->state = 'emit';
13983 }
13984 }
13985 else
13986 {
13987 $this->state = false;
13988 }
13989 }
13990
13991 function standalone_name()
13992 {
13993 if (substr($this->data, $this->position, 10) === 'standalone')
13994 {
13995 $this->position += 10;
13996 $this->skip_whitespace();
13997 $this->state = 'standalone_equals';
13998 }
13999 else
14000 {
14001 $this->state = false;
14002 }
14003 }
14004
14005 function standalone_equals()
14006 {
14007 if (substr($this->data, $this->position, 1) === '=')
14008 {
14009 $this->position++;
14010 $this->skip_whitespace();
14011 $this->state = 'standalone_value';
14012 }
14013 else
14014 {
14015 $this->state = false;
14016 }
14017 }
14018
14019 function standalone_value()
14020 {
14021 if ($standalone = $this->get_value())
14022 {
14023 switch ($standalone)
14024 {
14025 case 'yes':
14026 $this->standalone = true;
14027 break;
14028
14029 case 'no':
14030 $this->standalone = false;
14031 break;
14032
14033 default:
14034 $this->state = false;
14035 return;
14036 }
14037
14038 $this->skip_whitespace();
14039 if ($this->has_data())
14040 {
14041 $this->state = false;
14042 }
14043 else
14044 {
14045 $this->state = 'emit';
14046 }
14047 }
14048 else
14049 {
14050 $this->state = false;
14051 }
14052 }
14053 }
14054
14055 class SimplePie_Locator
14056 {
14057 var $useragent;
14058 var $timeout;
14059 var $file;
14060 var $local = array();
14061 var $elsewhere = array();
14062 var $file_class = 'SimplePie_File';
14063 var $cached_entities = array();
14064 var $http_base;
14065 var $base;
14066 var $base_location = 0;
14067 var $checked_feeds = 0;
14068 var $max_checked_feeds = 10;
14069 var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
14070
14071 function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
14072 {
14073 $this->file =& $file;
14074 $this->file_class = $file_class;
14075 $this->useragent = $useragent;
14076 $this->timeout = $timeout;
14077 $this->max_checked_feeds = $max_checked_feeds;
14078 $this->content_type_sniffer_class = $content_type_sniffer_class;
14079 }
14080
14081 function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
14082 {
14083 if ($this->is_feed($this->file))
14084 {
14085 return $this->file;
14086 }
14087
14088 if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14089 {
14090 $sniffer =& new $this->content_type_sniffer_class($this->file);
14091 if ($sniffer->get_type() !== 'text/html')
14092 {
14093 return null;
14094 }
14095 }
14096
14097 if ($type & ~SIMPLEPIE_LOCATOR_NONE)
14098 {
14099 $this->get_base();
14100 }
14101
14102 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
14103 {
14104 return $working[0];
14105 }
14106
14107 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
14108 {
14109 if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
14110 {
14111 return $working;
14112 }
14113
14114 if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
14115 {
14116 return $working;
14117 }
14118
14119 if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
14120 {
14121 return $working;
14122 }
14123
14124 if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
14125 {
14126 return $working;
14127 }
14128 }
14129 return null;
14130 }
14131
14132 function is_feed(&$file)
14133 {
14134 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14135 {
14136 $sniffer =& new $this->content_type_sniffer_class($file);
14137 $sniffed = $sniffer->get_type();
14138 if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
14139 {
14140 return true;
14141 }
14142 else
14143 {
14144 return false;
14145 }
14146 }
14147 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
14148 {
14149 return true;
14150 }
14151 else
14152 {
14153 return false;
14154 }
14155 }
14156
14157 function get_base()
14158 {
14159 $this->http_base = $this->file->url;
14160 $this->base = $this->http_base;
14161 $elements = SimplePie_Misc::get_element('base', $this->file->body);
14162 foreach ($elements as $element)
14163 {
14164 if ($element['attribs']['href']['data'] !== '')
14165 {
14166 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
14167 $this->base_location = $element['offset'];
14168 break;
14169 }
14170 }
14171 }
14172
14173 function autodiscovery()
14174 {
14175 $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));
14176 $done = array();
14177 $feeds = array();
14178 foreach ($links as $link)
14179 {
14180 if ($this->checked_feeds === $this->max_checked_feeds)
14181 {
14182 break;
14183 }
14184 if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
14185 {
14186 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
14187
14188 if ($this->base_location < $link['offset'])
14189 {
14190 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14191 }
14192 else
14193 {
14194 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14195 }
14196
14197 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]))
14198 {
14199 $this->checked_feeds++;
14200 $feed =& new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
14201 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))
14202 {
14203 $feeds[$href] = $feed;
14204 }
14205 }
14206 $done[] = $href;
14207 }
14208 }
14209
14210 if (!empty($feeds))
14211 {
14212 return array_values($feeds);
14213 }
14214 else {
14215 return null;
14216 }
14217 }
14218
14219 function get_links()
14220 {
14221 $links = SimplePie_Misc::get_element('a', $this->file->body);
14222 foreach ($links as $link)
14223 {
14224 if (isset($link['attribs']['href']['data']))
14225 {
14226 $href = trim($link['attribs']['href']['data']);
14227 $parsed = SimplePie_Misc::parse_url($href);
14228 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
14229 {
14230 if ($this->base_location < $link['offset'])
14231 {
14232 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14233 }
14234 else
14235 {
14236 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14237 }
14238
14239 $current = SimplePie_Misc::parse_url($this->file->url);
14240
14241 if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
14242 {
14243 $this->local[] = $href;
14244 }
14245 else
14246 {
14247 $this->elsewhere[] = $href;
14248 }
14249 }
14250 }
14251 }
14252 $this->local = array_unique($this->local);
14253 $this->elsewhere = array_unique($this->elsewhere);
14254 if (!empty($this->local) || !empty($this->elsewhere))
14255 {
14256 return true;
14257 }
14258 return null;
14259 }
14260
14261 function extension(&$array)
14262 {
14263 foreach ($array as $key => $value)
14264 {
14265 if ($this->checked_feeds === $this->max_checked_feeds)
14266 {
14267 break;
14268 }
14269 if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
14270 {
14271 $this->checked_feeds++;
14272 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14273 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))
14274 {
14275 return $feed;
14276 }
14277 else
14278 {
14279 unset($array[$key]);
14280 }
14281 }
14282 }
14283 return null;
14284 }
14285
14286 function body(&$array)
14287 {
14288 foreach ($array as $key => $value)
14289 {
14290 if ($this->checked_feeds === $this->max_checked_feeds)
14291 {
14292 break;
14293 }
14294 if (preg_match('/(rss|rdf|atom|xml)/i', $value))
14295 {
14296 $this->checked_feeds++;
14297 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14298 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))
14299 {
14300 return $feed;
14301 }
14302 else
14303 {
14304 unset($array[$key]);
14305 }
14306 }
14307 }
14308 return null;
14309 }
14310 }
14311
14312 class SimplePie_Parser
14313 {
14314 var $error_code;
14315 var $error_string;
14316 var $current_line;
14317 var $current_column;
14318 var $current_byte;
14319 var $separator = ' ';
14320 var $namespace = array('');
14321 var $element = array('');
14322 var $xml_base = array('');
14323 var $xml_base_explicit = array(false);
14324 var $xml_lang = array('');
14325 var $data = array();
14326 var $datas = array(array());
14327 var $current_xhtml_construct = -1;
14328 var $encoding;
14329
14330 function parse(&$data, $encoding)
14331 {
14332 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
14333 if (strtoupper($encoding) === 'US-ASCII')
14334 {
14335 $this->encoding = 'UTF-8';
14336 }
14337 else
14338 {
14339 $this->encoding = $encoding;
14340 }
14341
14342 // Strip BOM:
14343 // UTF-32 Big Endian BOM
14344 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14345 {
14346 $data = substr($data, 4);
14347 }
14348 // UTF-32 Little Endian BOM
14349 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14350 {
14351 $data = substr($data, 4);
14352 }
14353 // UTF-16 Big Endian BOM
14354 elseif (substr($data, 0, 2) === "\xFE\xFF")
14355 {
14356 $data = substr($data, 2);
14357 }
14358 // UTF-16 Little Endian BOM
14359 elseif (substr($data, 0, 2) === "\xFF\xFE")
14360 {
14361 $data = substr($data, 2);
14362 }
14363 // UTF-8 BOM
14364 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14365 {
14366 $data = substr($data, 3);
14367 }
14368
14369 if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
14370 {
14371 $declaration =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
14372 if ($declaration->parse())
14373 {
14374 $data = substr($data, $pos + 2);
14375 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
14376 }
14377 else
14378 {
14379 $this->error_string = 'SimplePie bug! Please report this!';
14380 return false;
14381 }
14382 }
14383
14384 $return = true;
14385
14386 static $xml_is_sane = null;
14387 if ($xml_is_sane === null)
14388 {
14389 $parser_check = xml_parser_create();
14390 xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
14391 xml_parser_free($parser_check);
14392 $xml_is_sane = isset($values[0]['value']);
14393 }
14394
14395 // Create the parser
14396 if ($xml_is_sane)
14397 {
14398 $xml = xml_parser_create_ns($this->encoding, $this->separator);
14399 xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
14400 xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
14401 xml_set_object($xml, $this);
14402 xml_set_character_data_handler($xml, 'cdata');
14403 xml_set_element_handler($xml, 'tag_open', 'tag_close');
14404
14405 // Parse!
14406 if (!xml_parse($xml, $data, true))
14407 {
14408 $this->error_code = xml_get_error_code($xml);
14409 $this->error_string = xml_error_string($this->error_code);
14410 $return = false;
14411 }
14412 $this->current_line = xml_get_current_line_number($xml);
14413 $this->current_column = xml_get_current_column_number($xml);
14414 $this->current_byte = xml_get_current_byte_index($xml);
14415 xml_parser_free($xml);
14416 return $return;
14417 }
14418 else
14419 {
14420 libxml_clear_errors();
14421 $xml =& new XMLReader();
14422 $xml->xml($data);
14423 while (@$xml->read())
14424 {
14425 switch ($xml->nodeType)
14426 {
14427
14428 case constant('XMLReader::END_ELEMENT'):
14429 if ($xml->namespaceURI !== '')
14430 {
14431 $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14432 }
14433 else
14434 {
14435 $tagName = $xml->localName;
14436 }
14437 $this->tag_close(null, $tagName);
14438 break;
14439 case constant('XMLReader::ELEMENT'):
14440 $empty = $xml->isEmptyElement;
14441 if ($xml->namespaceURI !== '')
14442 {
14443 $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14444 }
14445 else
14446 {
14447 $tagName = $xml->localName;
14448 }
14449 $attributes = array();
14450 while ($xml->moveToNextAttribute())
14451 {
14452 if ($xml->namespaceURI !== '')
14453 {
14454 $attrName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14455 }
14456 else
14457 {
14458 $attrName = $xml->localName;
14459 }
14460 $attributes[$attrName] = $xml->value;
14461 }
14462 $this->tag_open(null, $tagName, $attributes);
14463 if ($empty)
14464 {
14465 $this->tag_close(null, $tagName);
14466 }
14467 break;
14468 case constant('XMLReader::TEXT'):
14469
14470 case constant('XMLReader::CDATA'):
14471 $this->cdata(null, $xml->value);
14472 break;
14473 }
14474 }
14475 if ($error = libxml_get_last_error())
14476 {
14477 $this->error_code = $error->code;
14478 $this->error_string = $error->message;
14479 $this->current_line = $error->line;
14480 $this->current_column = $error->column;
14481 return false;
14482 }
14483 else
14484 {
14485 return true;
14486 }
14487 }
14488 }
14489
14490 function get_error_code()
14491 {
14492 return $this->error_code;
14493 }
14494
14495 function get_error_string()
14496 {
14497 return $this->error_string;
14498 }
14499
14500 function get_current_line()
14501 {
14502 return $this->current_line;
14503 }
14504
14505 function get_current_column()
14506 {
14507 return $this->current_column;
14508 }
14509
14510 function get_current_byte()
14511 {
14512 return $this->current_byte;
14513 }
14514
14515 function get_data()
14516 {
14517 return $this->data;
14518 }
14519
14520 function tag_open($parser, $tag, $attributes)
14521 {
14522 list($this->namespace[], $this->element[]) = $this->split_ns($tag);
14523
14524 $attribs = array();
14525 foreach ($attributes as $name => $value)
14526 {
14527 list($attrib_namespace, $attribute) = $this->split_ns($name);
14528 $attribs[$attrib_namespace][$attribute] = $value;
14529 }
14530
14531 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
14532 {
14533 $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
14534 $this->xml_base_explicit[] = true;
14535 }
14536 else
14537 {
14538 $this->xml_base[] = end($this->xml_base);
14539 $this->xml_base_explicit[] = end($this->xml_base_explicit);
14540 }
14541
14542 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
14543 {
14544 $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
14545 }
14546 else
14547 {
14548 $this->xml_lang[] = end($this->xml_lang);
14549 }
14550
14551 if ($this->current_xhtml_construct >= 0)
14552 {
14553 $this->current_xhtml_construct++;
14554 if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
14555 {
14556 $this->data['data'] .= '<' . end($this->element);
14557 if (isset($attribs['']))
14558 {
14559 foreach ($attribs[''] as $name => $value)
14560 {
14561 $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
14562 }
14563 }
14564 $this->data['data'] .= '>';
14565 }
14566 }
14567 else
14568 {
14569 $this->datas[] =& $this->data;
14570 $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
14571 $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));
14572 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')
14573 || (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'))
14574 {
14575 $this->current_xhtml_construct = 0;
14576 }
14577 }
14578 }
14579
14580 function cdata($parser, $cdata)
14581 {
14582 if ($this->current_xhtml_construct >= 0)
14583 {
14584 $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
14585 }
14586 else
14587 {
14588 $this->data['data'] .= $cdata;
14589 }
14590 }
14591
14592 function tag_close($parser, $tag)
14593 {
14594 if ($this->current_xhtml_construct >= 0)
14595 {
14596 $this->current_xhtml_construct--;
14597 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')))
14598 {
14599 $this->data['data'] .= '</' . end($this->element) . '>';
14600 }
14601 }
14602 if ($this->current_xhtml_construct === -1)
14603 {
14604 $this->data =& $this->datas[count($this->datas) - 1];
14605 array_pop($this->datas);
14606 }
14607
14608 array_pop($this->element);
14609 array_pop($this->namespace);
14610 array_pop($this->xml_base);
14611 array_pop($this->xml_base_explicit);
14612 array_pop($this->xml_lang);
14613 }
14614
14615 function split_ns($string)
14616 {
14617 static $cache = array();
14618 if (!isset($cache[$string]))
14619 {
14620 if ($pos = strpos($string, $this->separator))
14621 {
14622 static $separator_length;
14623 if (!$separator_length)
14624 {
14625 $separator_length = strlen($this->separator);
14626 }
14627 $namespace = substr($string, 0, $pos);
14628 $local_name = substr($string, $pos + $separator_length);
14629 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
14630 {
14631 $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
14632 }
14633
14634 // Normalize the Media RSS namespaces
14635 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
14636 {
14637 $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
14638 }
14639 $cache[$string] = array($namespace, $local_name);
14640 }
14641 else
14642 {
14643 $cache[$string] = array('', $string);
14644 }
14645 }
14646 return $cache[$string];
14647 }
14648 }
14649
14650 /**
14651 * @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
14652 */
14653 class SimplePie_Sanitize
14654 {
14655 // Private vars
14656 var $base;
14657
14658 // Options
14659 var $remove_div = true;
14660 var $image_handler = '';
14661 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
14662 var $encode_instead_of_strip = false;
14663 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
14664 var $strip_comments = false;
14665 var $output_encoding = 'UTF-8';
14666 var $enable_cache = true;
14667 var $cache_location = './cache';
14668 var $cache_name_function = 'md5';
14669 var $cache_class = 'SimplePie_Cache';
14670 var $file_class = 'SimplePie_File';
14671 var $timeout = 10;
14672 var $useragent = '';
14673 var $force_fsockopen = false;
14674
14675 var $replace_url_attributes = array(
14676 'a' => 'href',
14677 'area' => 'href',
14678 'blockquote' => 'cite',
14679 'del' => 'cite',
14680 'form' => 'action',
14681 'img' => array('longdesc', 'src'),
14682 'input' => 'src',
14683 'ins' => 'cite',
14684 'q' => 'cite'
14685 );
14686
14687 function remove_div($enable = true)
14688 {
14689 $this->remove_div = (bool) $enable;
14690 }
14691
14692 function set_image_handler($page = false)
14693 {
14694 if ($page)
14695 {
14696 $this->image_handler = (string) $page;
14697 }
14698 else
14699 {
14700 $this->image_handler = false;
14701 }
14702 }
14703
14704 function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
14705 {
14706 if (isset($enable_cache))
14707 {
14708 $this->enable_cache = (bool) $enable_cache;
14709 }
14710
14711 if ($cache_location)
14712 {
14713 $this->cache_location = (string) $cache_location;
14714 }
14715
14716 if ($cache_name_function)
14717 {
14718 $this->cache_name_function = (string) $cache_name_function;
14719 }
14720
14721 if ($cache_class)
14722 {
14723 $this->cache_class = (string) $cache_class;
14724 }
14725 }
14726
14727 function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
14728 {
14729 if ($file_class)
14730 {
14731 $this->file_class = (string) $file_class;
14732 }
14733
14734 if ($timeout)
14735 {
14736 $this->timeout = (string) $timeout;
14737 }
14738
14739 if ($useragent)
14740 {
14741 $this->useragent = (string) $useragent;
14742 }
14743
14744 if ($force_fsockopen)
14745 {
14746 $this->force_fsockopen = (string) $force_fsockopen;
14747 }
14748 }
14749
14750 function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
14751 {
14752 if ($tags)
14753 {
14754 if (is_array($tags))
14755 {
14756 $this->strip_htmltags = $tags;
14757 }
14758 else
14759 {
14760 $this->strip_htmltags = explode(',', $tags);
14761 }
14762 }
14763 else
14764 {
14765 $this->strip_htmltags = false;
14766 }
14767 }
14768
14769 function encode_instead_of_strip($encode = false)
14770 {
14771 $this->encode_instead_of_strip = (bool) $encode;
14772 }
14773
14774 function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
14775 {
14776 if ($attribs)
14777 {
14778 if (is_array($attribs))
14779 {
14780 $this->strip_attributes = $attribs;
14781 }
14782 else
14783 {
14784 $this->strip_attributes = explode(',', $attribs);
14785 }
14786 }
14787 else
14788 {
14789 $this->strip_attributes = false;
14790 }
14791 }
14792
14793 function strip_comments($strip = false)
14794 {
14795 $this->strip_comments = (bool) $strip;
14796 }
14797
14798 function set_output_encoding($encoding = 'UTF-8')
14799 {
14800 $this->output_encoding = (string) $encoding;
14801 }
14802
14803 /**
14804 * Set element/attribute key/value pairs of HTML attributes
14805 * containing URLs that need to be resolved relative to the feed
14806 *
14807 * @access public
14808 * @since 1.0
14809 * @param array $element_attribute Element/attribute key/value pairs
14810 */
14811 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'))
14812 {
14813 $this->replace_url_attributes = (array) $element_attribute;
14814 }
14815
14816 function sanitize($data, $type, $base = '')
14817 {
14818 $data = trim($data);
14819 if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
14820 {
14821 if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
14822 {
14823 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))
14824 {
14825 $type |= SIMPLEPIE_CONSTRUCT_HTML;
14826 }
14827 else
14828 {
14829 $type |= SIMPLEPIE_CONSTRUCT_TEXT;
14830 }
14831 }
14832
14833 if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
14834 {
14835 $data = base64_decode($data);
14836 }
14837
14838 if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
14839 {
14840 if ($this->remove_div)
14841 {
14842 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
14843 $data = preg_replace('/<\/div>$/', '', $data);
14844 }
14845 else
14846 {
14847 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
14848 }
14849 }
14850
14851 if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
14852 {
14853 // Strip comments
14854 if ($this->strip_comments)
14855 {
14856 $data = SimplePie_Misc::strip_comments($data);
14857 }
14858
14859 // Strip out HTML tags and attributes that might cause various security problems.
14860 // Based on recommendations by Mark Pilgrim at:
14861 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
14862 if ($this->strip_htmltags)
14863 {
14864 foreach ($this->strip_htmltags as $tag)
14865 {
14866 $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
14867 while (preg_match($pcre, $data))
14868 {
14869 $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
14870 }
14871 }
14872 }
14873
14874 if ($this->strip_attributes)
14875 {
14876 foreach ($this->strip_attributes as $attrib)
14877 {
14878 $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);
14879 }
14880 }
14881
14882 // Replace relative URLs
14883 $this->base = $base;
14884 foreach ($this->replace_url_attributes as $element => $attributes)
14885 {
14886 $data = $this->replace_urls($data, $element, $attributes);
14887 }
14888
14889 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
14890 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
14891 {
14892 $images = SimplePie_Misc::get_element('img', $data);
14893 foreach ($images as $img)
14894 {
14895 if (isset($img['attribs']['src']['data']))
14896 {
14897 $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
14898 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
14899
14900 if ($cache->load())
14901 {
14902 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
14903 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
14904 }
14905 else
14906 {
14907 $file =& new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
14908 $headers = $file->headers;
14909
14910 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
14911 {
14912 if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
14913 {
14914 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
14915 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
14916 }
14917 else
14918 {
14919 trigger_error("$this->cache_location is not writeable", E_USER_WARNING);
14920 }
14921 }
14922 }
14923 }
14924 }
14925 }
14926
14927 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
14928 $data = trim($data);
14929 }
14930
14931 if ($type & SIMPLEPIE_CONSTRUCT_IRI)
14932 {
14933 $data = SimplePie_Misc::absolutize_url($data, $base);
14934 }
14935
14936 if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
14937 {
14938 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
14939 }
14940
14941 if ($this->output_encoding !== 'UTF-8')
14942 {
14943 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
14944 }
14945 }
14946 return $data;
14947 }
14948
14949 function replace_urls($data, $tag, $attributes)
14950 {
14951 if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
14952 {
14953 $elements = SimplePie_Misc::get_element($tag, $data);
14954 foreach ($elements as $element)
14955 {
14956 if (is_array($attributes))
14957 {
14958 foreach ($attributes as $attribute)
14959 {
14960 if (isset($element['attribs'][$attribute]['data']))
14961 {
14962 $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
14963 $new_element = SimplePie_Misc::element_implode($element);
14964 $data = str_replace($element['full'], $new_element, $data);
14965 $element['full'] = $new_element;
14966 }
14967 }
14968 }
14969 elseif (isset($element['attribs'][$attributes]['data']))
14970 {
14971 $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
14972 $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
14973 }
14974 }
14975 }
14976 return $data;
14977 }
14978
14979 function do_strip_htmltags($match)
14980 {
14981 if ($this->encode_instead_of_strip)
14982 {
14983 if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
14984 {
14985 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
14986 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
14987 return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
14988 }
14989 else
14990 {
14991 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
14992 }
14993 }
14994 elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
14995 {
14996 return $match[4];
14997 }
14998 else
14999 {
15000 return '';
15001 }
15002 }
15003 }
15004
15005 ?>