/[drupal]/contributions/modules/feedparser/simplepie.inc
ViewVC logotype

Contents of /contributions/modules/feedparser/simplepie.inc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2 - (show annotations) (download) (as text)
Tue Nov 28 23:46:58 2006 UTC (2 years, 11 months ago) by budda
Branch: MAIN
CVS Tags: DRUPAL-5--0-1-dev, HEAD
Branch point for: DRUPAL-5, DRUPAL-4-7
Changes since 1.1: +67 -5 lines
File MIME type: text/x-php
Latest piece of the SimplePie.

See http://simplepie.org/docs/misc/release-notes/beta3/ for features/fixes
1 <?php
2 /****************************************************
3 SIMPLEPIE
4 A PHP-Based RSS and Atom Feed Framework
5 Takes the hard work out of managing a complete RSS/Atom solution.
6
7 Version: "Lemon Meringue"
8 Updated: 24 November 2006
9 Copyright: 2004-2006 Ryan Parman, Geoffrey Sneddon
10 http://simplepie.org
11
12 *****************************************************
13 LICENSE:
14
15 GNU Lesser General Public License 2.1 (LGPL)
16 http://creativecommons.org/licenses/LGPL/2.1/
17
18 *****************************************************
19 Please submit all bug reports and feature requests to the SimplePie forums.
20 http://simplepie.org/support/
21
22 ****************************************************/
23
24 class SimplePie
25 {
26 // SimplePie Info
27 var $name = 'SimplePie';
28 var $version = '1.0 b3.2';
29 var $build = '20061124';
30 var $url = 'http://simplepie.org/';
31 var $useragent;
32 var $linkback;
33
34 // Other objects, instances created here so we can set options on them
35 var $sanitize;
36
37 // Options
38 var $rss_url;
39 var $file;
40 var $timeout = 10;
41 var $xml_dump = false;
42 var $enable_cache = true;
43 var $max_minutes = 60;
44 var $cache_location = './cache';
45 var $order_by_date = true;
46 var $input_encoding = false;
47 var $cache_class = 'SimplePie_Cache';
48 var $locator_class = 'SimplePie_Locator';
49 var $parser_class = 'SimplePie_Parser';
50 var $file_class = 'SimplePie_File';
51 var $force_fsockopen = false;
52 var $cache_name_type = 'sha1';
53
54 // Misc. variables
55 var $data;
56 var $error;
57
58 function SimplePie($feed_url = null, $cache_location = null, $cache_max_minutes = null)
59 {
60 // Couple of variables built up from other variables
61 $this->useragent = $this->name . '/' . $this->version . ' (Feed Parser; ' . $this->url . '; Allow like Gecko) Build/' . $this->build;
62 $this->linkback = '<a href="' . $this->url . '" title="' . $this->name . ' ' . $this->version . '">' . $this->name . '</a>';
63
64 // Other objects, instances created here so we can set options on them
65 $this->sanitize = new SimplePie_Sanitize;
66
67 // Set options if they're passed to the constructor
68 if (!is_null($feed_url))
69 {
70 $this->feed_url($feed_url);
71 }
72
73 if (!is_null($cache_location))
74 {
75 $this->cache_location($cache_location);
76 }
77
78 if (!is_null($cache_max_minutes))
79 {
80 $this->cache_max_minutes($cache_max_minutes);
81 }
82
83 // If we've passed an xmldump variable in the URL, snap into XMLdump mode
84 if (isset($_GET['xmldump']))
85 {
86 $this->enable_xmldump(true);
87 }
88
89 // Only init the script if we're passed a feed URL
90 if (!is_null($feed_url))
91 {
92 return $this->init();
93 }
94 }
95
96 function feed_url($url)
97 {
98 $this->rss_url = SimplePie_Misc::fix_protocol($url, 1);
99 }
100
101 function set_file(&$file)
102 {
103 if (is_a($file, 'SimplePie_File'))
104 {
105 $this->rss_url = $file->url;
106 $this->file =& $file;
107 }
108 }
109
110 function set_timeout($timeout = 10)
111 {
112 $this->timeout = (int) $timeout;
113 }
114
115 function set_raw_data($data)
116 {
117 $this->raw_data = trim((string) $data);
118 }
119
120 function enable_xmldump($enable = false)
121 {
122 $this->xml_dump = (bool) $enable;
123 }
124
125 function enable_caching($enable = true)
126 {
127 $this->enable_cache = (bool) $enable;
128 }
129
130 function cache_max_minutes($minutes = 60)
131 {
132 $this->max_minutes = (float) $minutes;
133 }
134
135 function cache_location($location = './cache')
136 {
137 $this->cache_location = (string) $location;
138 }
139
140 function order_by_date($enable = true)
141 {
142 $this->order_by_date = (bool) $enable;
143 }
144
145 function input_encoding($encoding = false)
146 {
147 if ($encoding)
148 {
149 $this->input_encoding = (string) $encoding;
150 }
151 else
152 {
153 $this->input_encoding = false;
154 }
155 }
156
157 function set_cache_class($class = 'SimplePie_Cache')
158 {
159 if (SimplePie_Misc::is_a_class($class, 'SimplePie_Cache'))
160 {
161 $this->cache_class = $class;
162 return true;
163 }
164 return false;
165 }
166
167 function set_locator_class($class = 'SimplePie_Locator')
168 {
169 if (SimplePie_Misc::is_a_class($class, 'SimplePie_Locator'))
170 {
171 $this->locator_class = $class;
172 return true;
173 }
174 return false;
175 }
176
177 function set_parser_class($class = 'SimplePie_Parser')
178 {
179 if (SimplePie_Misc::is_a_class($class, 'SimplePie_Parser'))
180 {
181 $this->parser_class = $class;
182 return true;
183 }
184 return false;
185 }
186
187 function set_file_class($class = 'SimplePie_File')
188 {
189 if (SimplePie_Misc::is_a_class($class, 'SimplePie_File'))
190 {
191 $this->file_class = $class;
192 return true;
193 }
194 return false;
195 }
196
197 function set_sanitize_class($object = 'SimplePie_Sanitize')
198 {
199 if (class_exists($object))
200 {
201 $this->sanitize = new $object;
202 return true;
203 }
204 return false;
205 }
206
207 function set_useragent($ua)
208 {
209 $this->useragent = (string) $ua;
210 }
211
212 function force_fsockopen($enable = false)
213 {
214 $this->force_fsockopen = (bool) $enable;
215 }
216
217 function set_cache_name_type($type = 'sha1')
218 {
219 $type = strtolower(trim($type));
220 switch ($type)
221 {
222 case 'crc32':
223 $this->cache_name_type = 'crc32';
224 break;
225
226 case 'md5':
227 $this->cache_name_type = 'md5';
228 break;
229
230 case 'rawurlencode':
231 $this->cache_name_type = 'rawurlencode';
232 break;
233
234 case 'urlencode':
235 $this->cache_name_type = 'urlencode';
236 break;
237
238 default:
239 $this->cache_name_type = 'sha1';
240 break;
241 }
242 }
243
244 function bypass_image_hotlink($get = false)
245 {
246 $this->sanitize->bypass_image_hotlink($get);
247 }
248
249 function bypass_image_hotlink_page($page = false)
250 {
251 $this->sanitize->bypass_image_hotlink_page($page);
252 }
253
254 function replace_headers($enable = false)
255 {
256 $this->sanitize->replace_headers($enable);
257 }
258
259 function remove_div($enable = true)
260 {
261 $this->sanitize->remove_div($enable);
262 }
263
264 function strip_ads($enable = false)
265 {
266 $this->sanitize->strip_ads($enable);
267 }
268
269 function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'), $encode = null)
270 {
271 $this->sanitize->strip_htmltags($tags);
272 if (!is_null($encode))
273 {
274 $this->sanitize->encode_instead_of_strip($tags);
275 }
276 }
277
278 function encode_instead_of_strip($enable = true)
279 {
280 $this->sanitize->encode_instead_of_strip($enable);
281 }
282
283 function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur'))
284 {
285 $this->sanitize->strip_attributes($attribs);
286 }
287
288 function output_encoding($encoding = 'UTF-8')
289 {
290 $this->sanitize->output_encoding($encoding);
291 }
292
293 function set_item_class($class = 'SimplePie_Item')
294 {
295 return $this->sanitize->set_item_class($class);
296 }
297
298 function set_author_class($class = 'SimplePie_Author')
299 {
300 return $this->sanitize->set_author_class($class);
301 }
302
303 function set_enclosure_class($class = 'SimplePie_Enclosure')
304 {
305 return $this->sanitize->set_enclosure_class($class);
306 }
307
308 function init()
309 {
310 if (!(function_exists('version_compare') && ((version_compare(phpversion(), '4.3.2', '>=') && version_compare(phpversion(), '5', '<')) || version_compare(phpversion(), '5.0.3', '>='))) || !extension_loaded('xml') || !extension_loaded('pcre'))
311 {
312 return false;
313 }
314 if ($this->sanitize->bypass_image_hotlink && !empty($_GET[$this->sanitize->bypass_image_hotlink]))
315 {
316 if (get_magic_quotes_gpc())
317 {
318 $_GET[$this->sanitize->bypass_image_hotlink] = stripslashes($_GET[$this->sanitize->bypass_image_hotlink]);
319 }
320 SimplePie_Misc::display_file($_GET[$this->sanitize->bypass_image_hotlink], 10, $this->useragent);
321 }
322
323 if (isset($_GET['js']))
324 {
325 $embed = <<<EOT
326 function embed_odeo(link) {
327 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>');
328 }
329
330 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
331 if (placeholder != '') {
332 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>');
333 }
334 else {
335 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>');
336 }
337 }
338
339 function embed_flash(bgcolor, width, height, link, loop, type) {
340 document.writeln('<embed src="'+link+'" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" type="'+type+'" quality="high" width="'+width+'" height="'+height+'" bgcolor="'+bgcolor+'" loop="'+loop+'"></embed>');
341 }
342
343 function embed_wmedia(width, height, link) {
344 document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
345 }
346 EOT;
347
348 if (function_exists('ob_gzhandler'))
349 {
350 ob_start('ob_gzhandler');
351 }
352 header('Content-type: text/javascript; charset: UTF-8');
353 header('Cache-Control: must-revalidate');
354 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 86400) . ' GMT');
355 echo $embed;
356 exit;
357 }
358
359 if (!empty($this->rss_url) || !empty($this->raw_data))
360 {
361 $this->data = array();
362 $cache = false;
363
364 if (!empty($this->rss_url))
365 {
366 // Decide whether to enable caching
367 if ($this->enable_cache && preg_match('/^http(s)?:\/\//i', $this->rss_url))
368 {
369 $cache = new $this->cache_class($this->cache_location, call_user_func($this->cache_name_type, $this->rss_url), 'spc');
370 }
371 // If it's enabled and we don't want an XML dump, use the cache
372 if ($cache && !$this->xml_dump)
373 {
374 // Load the Cache
375 $this->data = $cache->load();
376 if (!empty($this->data))
377 {
378 // If we've hit a collision just rerun it with caching disabled
379 if (isset($this->data['url']) && $this->data['url'] != $this->rss_url)
380 {
381 $cache = false;
382 }
383 // If we've got a feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL
384 else if (!empty($this->data['feed_url']))
385 {
386 if ($this->data['feed_url'] == $this->data['url'])
387 {
388 $cache->unlink();
389 }
390 else
391 {
392 $this->feed_url($this->data['feed_url']);
393 return $this->init();
394 }
395 }
396 // If the cache is new enough
397 else if ($cache->mtime() + $this->max_minutes * 60 < time())
398 {
399 // If we have last-modified and/or etag set
400 if (!empty($this->data['last-modified']) || !empty($this->data['etag']))
401 {
402 $headers = array();
403 if (!empty($this->data['last-modified']))
404 {
405 $headers['if-modified-since'] = $this->data['last-modified'];
406 }
407 if (!empty($this->data['etag']))
408 {
409 $headers['if-none-match'] = $this->data['etag'];
410 }
411 $file = new $this->file_class($this->rss_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
412 if ($file->success)
413 {
414 $headers = $file->headers();
415 if ($headers['status']['code'] == 304)
416 {
417 $cache->touch();
418 return true;
419 }
420 }
421 else
422 {
423 unset($file);
424 }
425 }
426 // If we don't have last-modified or etag set, just clear the cache
427 else
428 {
429 $cache->unlink();
430 }
431 }
432 // If the cache is still valid, just return true
433 else
434 {
435 return true;
436 }
437 }
438 // If the cache is empty, delete it
439 else
440 {
441 $cache->unlink();
442 }
443 }
444 $this->data = array();
445 // 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.
446 if (!isset($file))
447 {
448 if (is_a($this->file, 'SimplePie_File') && $this->file->url == $this->rss_url)
449 {
450 $file =& $this->file;
451 }
452 else
453 {
454 $file = new $this->file_class($this->rss_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
455 }
456 }
457 // If the file connection has an error, set SimplePie::error to that and quit
458 if (!$file->success)
459 {
460 $this->error = $file->error;
461 return false;
462 }
463
464 // Check if the supplied URL is a feed, if it isn't, look for it.
465 $locate = new $this->locator_class($file, $this->timeout, $this->useragent);
466 if (!$locate->is_feed($file))
467 {
468 $feed = $locate->find();
469 if ($feed)
470 {
471 if ($cache && !$cache->save(array('url' => $this->rss_url, 'feed_url' => $feed)))
472 {
473 $this->error = "$cache->name is not writeable";
474 SimplePie_Misc::error($this->error, E_USER_WARNING, __FILE__, __LINE__);
475 }
476 $this->rss_url = $feed;
477 return $this->init();
478 }
479 else
480 {
481 $this->error = "A feed could not be found at $this->rss_url";
482 SimplePie_Misc::error($this->error, E_USER_WARNING, __FILE__, __LINE__);
483 return false;
484 }
485 }
486
487 $headers = $file->headers();
488 $data = trim($file->body());
489 $file->close();
490 unset($file);
491 }
492 else
493 {
494 $data = $this->raw_data;
495 }
496
497 // First check to see if input has been overridden.
498 if (!empty($this->input_encoding))
499 {
500 $encoding = $this->input_encoding;
501 }
502 // Second try HTTP headers
503 else if (!empty($headers['content-type']) && preg_match('/charset\s*=\s*([^;]*)/i', $headers['content-type'], $charset))
504 {
505 $encoding = $charset[1];
506 }
507 // Then prolog, if at the very start of the document
508 else if (preg_match('/^<\?xml(.*)?>/msiU', $data, $prolog) && preg_match('/encoding\s*=\s*("([^"]*)"|\'([^\']*)\')/Ui', $prolog[1], $encoding))
509 {
510 $encoding = substr($encoding[1], 1, -1);
511 }
512 // UTF-32 Big Endian BOM
513 else if (strpos($data, sprintf('%c%c%c%c', 0x00, 0x00, 0xFE, 0xFF)) === 0)
514 {
515 $encoding = 'UTF-32be';
516 }
517 // UTF-32 Little Endian BOM
518 else if (strpos($data, sprintf('%c%c%c%c', 0xFF, 0xFE, 0x00, 0x00)) === 0)
519 {
520 $encoding = 'UTF-32';
521 }
522 // UTF-16 Big Endian BOM
523 else if (strpos($data, sprintf('%c%c', 0xFE, 0xFF)) === 0)
524 {
525 $encoding = 'UTF-16be';
526 }
527 // UTF-16 Little Endian BOM
528 else if (strpos($data, sprintf('%c%c', 0xFF, 0xFE)) === 0)
529 {
530 $encoding = 'UTF-16le';
531 }
532 // UTF-8 BOM
533 else if (strpos($data, sprintf('%c%c%c', 0xEF, 0xBB, 0xBF)) === 0)
534 {
535 $encoding = 'UTF-8';
536 }
537 // Fallback to the default
538 else
539 {
540 $encoding = null;
541 }
542
543 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
544 $data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8');
545
546 // Strip illegal characters (if on less than PHP5, as on PHP5 expat can manage fine)
547 if (version_compare(phpversion(), '5', '<'))
548 {
549 if (function_exists('iconv'))
550 {
551 $data = iconv('UTF-8', 'UTF-8//IGNORE', $data);
552 }
553 else if (function_exists('mb_convert_encoding'))
554 {
555 $data = mb_convert_encoding($data, 'UTF-8', 'UTF-8');
556 }
557 else
558 {
559 $data = SimplePie_Misc::utf8_bad_replace($data);
560 }
561 }
562
563 // Start parsing
564 $data = new $this->parser_class($data, 'UTF-8', $this->xml_dump);
565 // If we want the XML, just output that and quit
566 if ($this->xml_dump)
567 {
568 header('Content-type: text/xml; charset=UTF-8');
569 echo $data->data;
570 exit;
571 }
572 // If it's parsed fine
573 else if (!$data->error_code)
574 {
575 // Parse the data, and make it sane
576 $this->sanitize->parse_data_array($data->data, $this->rss_url);
577 unset($data);
578 // Get the sane data
579 $this->data['feedinfo'] = $this->sanitize->feedinfo;
580 unset($this->sanitize->feedinfo);
581 $this->data['info'] = $this->sanitize->info;
582 unset($this->sanitize->info);
583 $this->data['items'] = $this->sanitize->items;
584 unset($this->sanitize->items);
585 $this->data['feedinfo']['encoding'] = $this->sanitize->output_encoding;
586 $this->data['url'] = $this->rss_url;
587
588 // Store the headers that we need
589 if (!empty($headers['last-modified']))
590 {
591 $this->data['last-modified'] = $headers['last-modified'];
592 }
593 if (!empty($headers['etag']))
594 {
595 $this->data['etag'] = $headers['etag'];
596 }
597
598 // If we want to order it by date, check if all items have a date, and then sort it
599 if ($this->order_by_date && !empty($this->data['items']))
600 {
601 $do_sort = true;
602 foreach ($this->data['items'] as $item)
603 {
604 if (!$item->get_date('U'))
605 {
606 $do_sort = false;
607 break;
608 }
609 }
610 if ($do_sort)
611 {
612 usort($this->data['items'], create_function('$a, $b', 'if ($a->get_date(\'U\') == $b->get_date(\'U\')) return 1; return ($a->get_date(\'U\') < $b->get_date(\'U\')) ? 1 : -1;'));
613 }
614 }
615
616 // Cache the file if caching is enabled
617 if ($cache && !$cache->save($this->data))
618 {
619 $this->error = "$cache->name is not writeable";
620 SimplePie_Misc::error($this->error, E_USER_WARNING, __FILE__, __LINE__);
621 }
622 return true;
623 }
624 // If we have an error, just set SimplePie::error to it and quit
625 else
626 {
627 $this->error = "XML error: $data->error_string at line $data->current_line, column $data->current_column";
628 SimplePie_Misc::error($this->error, E_USER_WARNING, __FILE__, __LINE__);
629 return false;
630 }
631 }
632 }
633
634 function get_encoding()
635 {
636 if (!empty($this->data['feedinfo']['encoding']))
637 {
638 return $this->data['feedinfo']['encoding'];
639 }
640 else
641 {
642 return false;
643 }
644 }
645
646 function handle_content_type($mime = 'text/html')
647 {
648 if (!headers_sent())
649 {
650 $header = "Content-type: $mime;";
651 if ($this->get_encoding())
652 {
653 $header .= ' charset=' . $this->get_encoding();
654 }
655 else
656 {
657 $header .= ' charset=UTF-8';
658 }
659 header($header);
660 }
661 }
662
663 function get_type()
664 {
665 if (!empty($this->data['feedinfo']['type']))
666 {
667 return $this->data['feedinfo']['type'];
668 }
669 else
670 {
671 return false;
672 }
673 }
674
675 function get_version()
676 {
677 if (!empty($this->data['feedinfo']['version']))
678 {
679 return $this->data['feedinfo']['version'];
680 }
681 else
682 {
683 return false;
684 }
685 }
686
687 function get_favicon($check = false, $alternate = null)
688 {
689 if (!empty($this->data['info']['link']['alternate'][0]))
690 {
691 $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $this->get_feed_link());
692
693 if ($check)
694 {
695 $file = new $this->file_class($favicon, $this->timeout/10, 5, null, $this->useragent, $this->force_fsockopen);
696 $headers = $file->headers();
697 $file->close();
698
699 if ($headers['status']['code'] == 200)
700 {
701 return $favicon;
702 }
703 }
704 else
705 {
706 return $favicon;
707 }
708 }
709 if (!is_null($alternate))
710 {
711 return $alternate;
712 }
713 else
714 {
715 return false;
716 }
717 }
718
719 function subscribe_url()
720 {
721 if (!empty($this->rss_url))
722 {
723 return $this->rss_url;
724 }
725 else
726 {
727 return false;
728 }
729 }
730
731 function subscribe_feed()
732 {
733 if (!empty($this->rss_url))
734 {
735 return SimplePie_Misc::fix_protocol($this->rss_url, 2);
736 }
737 else
738 {
739 return false;
740 }
741 }
742
743 function subscribe_outlook()
744 {
745 if (!empty($this->rss_url))
746 {
747 return 'outlook' . SimplePie_Misc::fix_protocol($this->rss_url, 2);
748 }
749 else
750 {
751 return false;
752 }
753 }
754
755 function subscribe_podcast()
756 {
757 if (!empty($this->rss_url))
758 {
759 return SimplePie_Misc::fix_protocol($this->rss_url, 3);
760 }
761 else
762 {
763 return false;
764 }
765 }
766
767 function subscribe_aol()
768 {
769 if ($this->subscribe_url())
770 {
771 return 'http://feeds.my.aol.com/add.jsp?url=' . rawurlencode($this->subscribe_url());
772 }
773 else
774 {
775 return false;
776 }
777 }
778
779 function subscribe_bloglines()
780 {
781 if ($this->subscribe_url())
782 {
783 return 'http://www.bloglines.com/sub/' . rawurlencode($this->subscribe_url());
784 }
785 else
786 {
787 return false;
788 }
789 }
790
791 function subscribe_eskobo()
792 {
793 if ($this->subscribe_url())
794 {
795 return 'http://www.eskobo.com/?AddToMyPage=' . rawurlencode($this->subscribe_url());
796 }
797 else
798 {
799 return false;
800 }
801 }
802
803 function subscribe_feedfeeds()
804 {
805 if ($this->subscribe_url())
806 {
807 return 'http://www.feedfeeds.com/add?feed=' . rawurlencode($this->subscribe_url());
808 }
809 else
810 {
811 return false;
812 }
813 }
814
815 function subscribe_feedlounge()
816 {
817 if ($this->subscribe_url())
818 {
819 return 'http://my.feedlounge.com/external/subscribe?url=' . rawurlencode($this->subscribe_url());
820 }
821 else
822 {
823 return false;
824 }
825 }
826
827 function subscribe_feedster()
828 {
829 if ($this->subscribe_url())
830 {
831 return 'http://www.feedster.com/myfeedster.php?action=addrss&amp;confirm=no&amp;rssurl=' . rawurlencode($this->subscribe_url());
832 }
833 else
834 {
835 return false;
836 }
837 }
838
839 function subscribe_google()
840 {
841 if ($this->subscribe_url())
842 {
843 return 'http://fusion.google.com/add?feedurl=' . rawurlencode($this->subscribe_url());
844 }
845 else
846 {
847 return false;
848 }
849 }
850
851 function subscribe_gritwire()
852 {
853 if ($this->subscribe_url())
854 {
855 return 'http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=' . rawurlencode($this->subscribe_url());
856 }
857 else
858 {
859 return false;
860 }
861 }
862
863 function subscribe_msn()
864 {
865 if ($this->subscribe_url())
866 {
867 $url = 'http://my.msn.com/addtomymsn.armx?id=rss&amp;ut=' . rawurlencode($this->subscribe_url());
868 if ($this->get_feed_link())
869 {
870 $url .= '&amp;ru=' . rawurlencode($this->get_feed_link());
871 }
872 return $url;
873 }
874 else
875 {
876 return false;
877 }
878 }
879
880 function subscribe_netvibes()
881 {
882 if ($this->subscribe_url())
883 {
884 return 'http://www.netvibes.com/subscribe.php?url=' . rawurlencode($this->subscribe_url());
885 }
886 else
887 {
888 return false;
889 }
890 }
891
892 function subscribe_newsburst()
893 {
894 if ($this->subscribe_url())
895 {
896 return 'http://www.newsburst.com/Source/?add=' . rawurlencode($this->subscribe_url());
897 }
898 else
899 {
900 return false;
901 }
902 }
903
904 function subscribe_newsgator()
905 {
906 if ($this->subscribe_url())
907 {
908 return 'http://www.newsgator.com/ngs/subscriber/subext.aspx?url=' . rawurlencode($this->subscribe_url());
909 }
910 else
911 {
912 return false;
913 }
914 }
915
916 function subscribe_odeo()
917 {
918 if ($this->subscribe_url())
919 {
920 return 'http://www.odeo.com/listen/subscribe?feed=' . rawurlencode($this->subscribe_url());
921 }
922 else
923 {
924 return false;
925 }
926 }
927
928 function subscribe_pluck()
929 {
930 if ($this->subscribe_url())
931 {
932 return 'http://client.pluck.com/pluckit/prompt.aspx?GCID=C12286x053&amp;a=' . rawurlencode($this->subscribe_url());
933 }
934 else
935 {
936 return false;
937 }
938 }
939
940 function subscribe_podnova()
941 {
942 if ($this->subscribe_url())
943 {
944 return 'http://www.podnova.com/index_your_podcasts.srf?action=add&amp;url=' . rawurlencode($this->subscribe_url());
945 }
946 else
947 {
948 return false;
949 }
950 }
951
952 function subscribe_rojo()
953 {
954 if ($this->subscribe_url())
955 {
956 return 'http://www.rojo.com/add-subscription?resource=' . rawurlencode($this->subscribe_url());
957 }
958 else
959 {
960 return false;
961 }
962 }
963
964 function subscribe_yahoo()
965 {
966 if ($this->subscribe_url())
967 {
968 return 'http://add.my.yahoo.com/rss?url=' . rawurlencode($this->subscribe_url());
969 }
970 else
971 {
972 return false;
973 }
974 }
975
976 function get_feed_title()
977 {
978 if (!empty($this->data['info']['title']))
979 {
980 return $this->data['info']['title'];
981 }
982 else
983 {
984 return false;
985 }
986 }
987
988 function get_feed_link()
989 {
990 if (!empty($this->data['info']['link']['alternate'][0]))
991 {
992 return $this->data['info']['link']['alternate'][0];
993 }
994 else
995 {
996 return false;
997 }
998 }
999
1000 function get_feed_links()
1001 {
1002 if (!empty($this->data['info']['link']))
1003 {
1004 return $this->data['info']['link'];
1005 }
1006 else
1007 {
1008 return false;
1009 }
1010 }
1011
1012 function get_feed_description()
1013 {
1014 if (!empty($this->data['info']['description']))
1015 {
1016 return $this->data['info']['description'];
1017 }
1018 else if (!empty($this->data['info']['dc:description']))
1019 {
1020 return $this->data['info']['dc:description'];
1021 }
1022 else if (!empty($this->data['info']['tagline']))
1023 {
1024 return $this->data['info']['tagline'];
1025 }
1026 else if (!empty($this->data['info']['subtitle']))
1027 {
1028 return $this->data['info']['subtitle'];
1029 }
1030 else
1031 {
1032 return false;
1033 }
1034 }
1035
1036 function get_feed_copyright()
1037 {
1038 if (!empty($this->data['info']['copyright']))
1039 {
1040 return $this->data['info']['copyright'];
1041 }
1042 else
1043 {
1044 return false;
1045 }
1046 }
1047
1048 function get_feed_language()
1049 {
1050 if (!empty($this->data['info']['language']))
1051 {
1052 return $this->data['info']['language'];
1053 }
1054 else if (!empty($this->data['info']['xml:lang']))
1055 {
1056 return $this->data['info']['xml:lang'];
1057 }
1058 else
1059 {
1060 return false;
1061 }
1062 }
1063
1064 function get_image_exist()
1065 {
1066 if (!empty($this->data['info']['image']['url']) || !empty($this->data['info']['image']['logo']))
1067 {
1068 return true;
1069 }
1070 else
1071 {
1072 return false;
1073 }
1074 }
1075
1076 function get_image_title()
1077 {
1078 if (!empty($this->data['info']['image']['title']))
1079 {
1080 return $this->data['info']['image']['title'];
1081 }
1082 else
1083 {
1084 return false;
1085 }
1086 }
1087
1088 function get_image_url()
1089 {
1090 if (!empty($this->data['info']['image']['url']))
1091 {
1092 return $this->data['info']['image']['url'];
1093 }
1094 else if (!empty($this->data['info']['image']['logo']))
1095 {
1096 return $this->data['info']['image']['logo'];
1097 }
1098 else
1099 {
1100 return false;
1101 }
1102 }
1103
1104 function get_image_link()
1105 {
1106 if (!empty($this->data['info']['image']['link']))
1107 {
1108 return $this->data['info']['image']['link'];
1109 }
1110 else
1111 {
1112 return false;
1113 }
1114 }
1115
1116 function get_image_width()
1117 {
1118 if (!empty($this->data['info']['image']['width']))
1119 {
1120 return $this->data['info']['image']['width'];
1121 }
1122 else
1123 {
1124 return false;
1125 }
1126 }
1127
1128 function get_image_height()
1129 {
1130 if (!empty($this->data['info']['image']['height']))
1131 {
1132 return $this->data['info']['image']['height'];
1133 }
1134 else
1135 {
1136 return false;
1137 }
1138 }
1139
1140 function get_item_quantity($max = 0)
1141 {
1142 if (!empty($this->data['items']))
1143 {
1144 $qty = sizeof($this->data['items']);
1145 }
1146 else
1147 {
1148 $qty = 0;
1149 }
1150 if ($max == 0)
1151 {
1152 return $qty;
1153 }
1154 else
1155 {
1156 return ($qty > $max) ? $max : $qty;
1157 }
1158 }
1159
1160 function get_item($key = 0)
1161 {
1162 if (!empty($this->data['items'][$key]))
1163 {
1164 return $this->data['items'][$key];
1165 }
1166 else
1167 {
1168 return false;
1169 }
1170 }
1171
1172 function get_items($start = 0, $end = 0)
1173 {
1174 if ($this->get_item_quantity() > 0)
1175 {
1176 if ($end == 0)
1177 {
1178 return array_slice($this->data['items'], $start);
1179 }
1180 else
1181 {
1182 return array_slice($this->data['items'], $start, $end);
1183 }
1184 }
1185 else
1186 {
1187 return false;
1188 }
1189 }
1190 }
1191
1192 class SimplePie_Item
1193 {
1194 var $data;
1195
1196 function SimplePie_Item($data)
1197 {
1198 $this->data =& $data;
1199 }
1200
1201 function get_id()
1202 {
1203 if (!empty($this->data['guid']['data']))
1204 {
1205 return $this->data['guid']['data'];
1206 }
1207 else if (!empty($this->data['id']))
1208 {
1209 return $this->data['id'];
1210 }
1211 else
1212 {
1213 return false;
1214 }
1215 }
1216
1217 function get_title()
1218 {
1219 if (!empty($this->data['title']))
1220 {
1221 return $this->data['title'];
1222 }
1223 else if (!empty($this->data['dc:title']))
1224 {
1225 return $this->data['dc:title'];
1226 }
1227 else
1228 {
1229 return false;
1230 }
1231 }
1232
1233 function get_description()
1234 {
1235 if (!empty($this->data['content']))
1236 {
1237 return $this->data['content'];
1238 }
1239 else if (!empty($this->data['encoded']))
1240 {
1241 return $this->data['encoded'];
1242 }
1243 else if (!empty($this->data['summary']))
1244 {
1245 return $this->data['summary'];
1246 }
1247 else if (!empty($this->data['description']))
1248 {
1249 return $this->data['description'];
1250 }
1251 else if (!empty($this->data['dc:description']))
1252 {
1253 return $this->data['dc:description'];
1254 }
1255 else if (!empty($this->data['longdesc']))
1256 {
1257 return $this->data['longdesc'];
1258 }
1259 else
1260 {
1261 return false;
1262 }
1263 }
1264
1265 function get_category($key = 0)
1266 {
1267 $categories =