~canonical-sysadmins/wordpress/4.7.2

« back to all changes in this revision

Viewing changes to wp-includes/class-simplepie.php

  • Committer: Jacek Nykis
  • Date: 2015-01-05 16:17:05 UTC
  • Revision ID: jacek.nykis@canonical.com-20150105161705-w544l1h5mcg7u4w9
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
if ( ! class_exists( 'SimplePie' ) ) :
 
3
 
 
4
// Load classes we will need.
 
5
require ABSPATH . WPINC . '/SimplePie/Misc.php';
 
6
require ABSPATH . WPINC . '/SimplePie/Cache.php';
 
7
require ABSPATH . WPINC . '/SimplePie/File.php';
 
8
require ABSPATH . WPINC . '/SimplePie/Sanitize.php';
 
9
require ABSPATH . WPINC . '/SimplePie/Registry.php';
 
10
require ABSPATH . WPINC . '/SimplePie/IRI.php';
 
11
require ABSPATH . WPINC . '/SimplePie/Locator.php';
 
12
require ABSPATH . WPINC . '/SimplePie/Content/Type/Sniffer.php';
 
13
require ABSPATH . WPINC . '/SimplePie/XML/Declaration/Parser.php';
 
14
require ABSPATH . WPINC . '/SimplePie/Parser.php';
 
15
require ABSPATH . WPINC . '/SimplePie/Item.php';
 
16
require ABSPATH . WPINC . '/SimplePie/Parse/Date.php';
 
17
require ABSPATH . WPINC . '/SimplePie/Author.php';
 
18
 
 
19
/**
 
20
 * WordPress autoloader for SimplePie.
 
21
 *
 
22
 * @since 3.5.0
 
23
 */
 
24
function wp_simplepie_autoload( $class ) {
 
25
        if ( 0 !== strpos( $class, 'SimplePie_' ) )
 
26
                return;
 
27
 
 
28
        $file = ABSPATH . WPINC . '/' . str_replace( '_', '/', $class ) . '.php';
 
29
        include( $file );
 
30
}
 
31
 
 
32
if ( function_exists( 'spl_autoload_register' ) ) {
 
33
        /**
 
34
         * We autoload classes we may not need.
 
35
         *
 
36
         * If SPL is disabled, we load all of SimplePie manually.
 
37
         *
 
38
         * Core.php is not loaded manually, because SimplePie_Core (a deprecated class)
 
39
         * was never included in WordPress core.
 
40
         */
 
41
        spl_autoload_register( 'wp_simplepie_autoload' );
 
42
} else {
 
43
        require ABSPATH . WPINC . '/SimplePie/Cache/Base.php';
 
44
        require ABSPATH . WPINC . '/SimplePie/Cache/DB.php';
 
45
        require ABSPATH . WPINC . '/SimplePie/Cache/File.php';
 
46
        require ABSPATH . WPINC . '/SimplePie/Cache/Memcache.php';
 
47
        require ABSPATH . WPINC . '/SimplePie/Cache/MySQL.php';
 
48
        require ABSPATH . WPINC . '/SimplePie/Caption.php';
 
49
        require ABSPATH . WPINC . '/SimplePie/Category.php';
 
50
        require ABSPATH . WPINC . '/SimplePie/Copyright.php';
 
51
        require ABSPATH . WPINC . '/SimplePie/Credit.php';
 
52
        require ABSPATH . WPINC . '/SimplePie/Decode/HTML/Entities.php';
 
53
        require ABSPATH . WPINC . '/SimplePie/Enclosure.php';
 
54
        require ABSPATH . WPINC . '/SimplePie/gzdecode.php';
 
55
        require ABSPATH . WPINC . '/SimplePie/HTTP/Parser.php';
 
56
        require ABSPATH . WPINC . '/SimplePie/Net/IPv6.php';
 
57
        require ABSPATH . WPINC . '/SimplePie/Rating.php';
 
58
        require ABSPATH . WPINC . '/SimplePie/Restriction.php';
 
59
        require ABSPATH . WPINC . '/SimplePie/Source.php';
 
60
}
 
61
 
 
62
/**
 
63
 * SimplePie
 
64
 *
 
65
 * A PHP-Based RSS and Atom Feed Framework.
 
66
 * Takes the hard work out of managing a complete RSS/Atom solution.
 
67
 *
 
68
 * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
 
69
 * All rights reserved.
 
70
 *
 
71
 * Redistribution and use in source and binary forms, with or without modification, are
 
72
 * permitted provided that the following conditions are met:
 
73
 *
 
74
 *      * Redistributions of source code must retain the above copyright notice, this list of
 
75
 *        conditions and the following disclaimer.
 
76
 *
 
77
 *      * Redistributions in binary form must reproduce the above copyright notice, this list
 
78
 *        of conditions and the following disclaimer in the documentation and/or other materials
 
79
 *        provided with the distribution.
 
80
 *
 
81
 *      * Neither the name of the SimplePie Team nor the names of its contributors may be used
 
82
 *        to endorse or promote products derived from this software without specific prior
 
83
 *        written permission.
 
84
 *
 
85
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
 
86
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 
87
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
 
88
 * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
89
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
90
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
91
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 
92
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
93
 * POSSIBILITY OF SUCH DAMAGE.
 
94
 *
 
95
 * @package SimplePie
 
96
 * @version 1.3.1
 
97
 * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue
 
98
 * @author Ryan Parman
 
99
 * @author Geoffrey Sneddon
 
100
 * @author Ryan McCue
 
101
 * @link http://simplepie.org/ SimplePie
 
102
 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
 
103
 */
 
104
 
 
105
/**
 
106
 * SimplePie Name
 
107
 */
 
108
define('SIMPLEPIE_NAME', 'SimplePie');
 
109
 
 
110
/**
 
111
 * SimplePie Version
 
112
 */
 
113
define('SIMPLEPIE_VERSION', '1.3.1');
 
114
 
 
115
/**
 
116
 * SimplePie Build
 
117
 * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::get_build() only every load of simplepie.inc)
 
118
 */
 
119
define('SIMPLEPIE_BUILD', gmdate('YmdHis', SimplePie_Misc::get_build()));
 
120
 
 
121
/**
 
122
 * SimplePie Website URL
 
123
 */
 
124
define('SIMPLEPIE_URL', 'http://simplepie.org');
 
125
 
 
126
/**
 
127
 * SimplePie Useragent
 
128
 * @see SimplePie::set_useragent()
 
129
 */
 
130
define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
 
131
 
 
132
/**
 
133
 * SimplePie Linkback
 
134
 */
 
135
define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
 
136
 
 
137
/**
 
138
 * No Autodiscovery
 
139
 * @see SimplePie::set_autodiscovery_level()
 
140
 */
 
141
define('SIMPLEPIE_LOCATOR_NONE', 0);
 
142
 
 
143
/**
 
144
 * Feed Link Element Autodiscovery
 
145
 * @see SimplePie::set_autodiscovery_level()
 
146
 */
 
147
define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
 
148
 
 
149
/**
 
150
 * Local Feed Extension Autodiscovery
 
151
 * @see SimplePie::set_autodiscovery_level()
 
152
 */
 
153
define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
 
154
 
 
155
/**
 
156
 * Local Feed Body Autodiscovery
 
157
 * @see SimplePie::set_autodiscovery_level()
 
158
 */
 
159
define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
 
160
 
 
161
/**
 
162
 * Remote Feed Extension Autodiscovery
 
163
 * @see SimplePie::set_autodiscovery_level()
 
164
 */
 
165
define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
 
166
 
 
167
/**
 
168
 * Remote Feed Body Autodiscovery
 
169
 * @see SimplePie::set_autodiscovery_level()
 
170
 */
 
171
define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
 
172
 
 
173
/**
 
174
 * All Feed Autodiscovery
 
175
 * @see SimplePie::set_autodiscovery_level()
 
176
 */
 
177
define('SIMPLEPIE_LOCATOR_ALL', 31);
 
178
 
 
179
/**
 
180
 * No known feed type
 
181
 */
 
182
define('SIMPLEPIE_TYPE_NONE', 0);
 
183
 
 
184
/**
 
185
 * RSS 0.90
 
186
 */
 
187
define('SIMPLEPIE_TYPE_RSS_090', 1);
 
188
 
 
189
/**
 
190
 * RSS 0.91 (Netscape)
 
191
 */
 
192
define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
 
193
 
 
194
/**
 
195
 * RSS 0.91 (Userland)
 
196
 */
 
197
define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
 
198
 
 
199
/**
 
200
 * RSS 0.91 (both Netscape and Userland)
 
201
 */
 
202
define('SIMPLEPIE_TYPE_RSS_091', 6);
 
203
 
 
204
/**
 
205
 * RSS 0.92
 
206
 */
 
207
define('SIMPLEPIE_TYPE_RSS_092', 8);
 
208
 
 
209
/**
 
210
 * RSS 0.93
 
211
 */
 
212
define('SIMPLEPIE_TYPE_RSS_093', 16);
 
213
 
 
214
/**
 
215
 * RSS 0.94
 
216
 */
 
217
define('SIMPLEPIE_TYPE_RSS_094', 32);
 
218
 
 
219
/**
 
220
 * RSS 1.0
 
221
 */
 
222
define('SIMPLEPIE_TYPE_RSS_10', 64);
 
223
 
 
224
/**
 
225
 * RSS 2.0
 
226
 */
 
227
define('SIMPLEPIE_TYPE_RSS_20', 128);
 
228
 
 
229
/**
 
230
 * RDF-based RSS
 
231
 */
 
232
define('SIMPLEPIE_TYPE_RSS_RDF', 65);
 
233
 
 
234
/**
 
235
 * Non-RDF-based RSS (truly intended as syndication format)
 
236
 */
 
237
define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
 
238
 
 
239
/**
 
240
 * All RSS
 
241
 */
 
242
define('SIMPLEPIE_TYPE_RSS_ALL', 255);
 
243
 
 
244
/**
 
245
 * Atom 0.3
 
246
 */
 
247
define('SIMPLEPIE_TYPE_ATOM_03', 256);
 
248
 
 
249
/**
 
250
 * Atom 1.0
 
251
 */
 
252
define('SIMPLEPIE_TYPE_ATOM_10', 512);
 
253
 
 
254
/**
 
255
 * All Atom
 
256
 */
 
257
define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
 
258
 
 
259
/**
 
260
 * All feed types
 
261
 */
 
262
define('SIMPLEPIE_TYPE_ALL', 1023);
 
263
 
 
264
/**
 
265
 * No construct
 
266
 */
 
267
define('SIMPLEPIE_CONSTRUCT_NONE', 0);
 
268
 
 
269
/**
 
270
 * Text construct
 
271
 */
 
272
define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
 
273
 
 
274
/**
 
275
 * HTML construct
 
276
 */
 
277
define('SIMPLEPIE_CONSTRUCT_HTML', 2);
 
278
 
 
279
/**
 
280
 * XHTML construct
 
281
 */
 
282
define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
 
283
 
 
284
/**
 
285
 * base64-encoded construct
 
286
 */
 
287
define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
 
288
 
 
289
/**
 
290
 * IRI construct
 
291
 */
 
292
define('SIMPLEPIE_CONSTRUCT_IRI', 16);
 
293
 
 
294
/**
 
295
 * A construct that might be HTML
 
296
 */
 
297
define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
 
298
 
 
299
/**
 
300
 * All constructs
 
301
 */
 
302
define('SIMPLEPIE_CONSTRUCT_ALL', 63);
 
303
 
 
304
/**
 
305
 * Don't change case
 
306
 */
 
307
define('SIMPLEPIE_SAME_CASE', 1);
 
308
 
 
309
/**
 
310
 * Change to lowercase
 
311
 */
 
312
define('SIMPLEPIE_LOWERCASE', 2);
 
313
 
 
314
/**
 
315
 * Change to uppercase
 
316
 */
 
317
define('SIMPLEPIE_UPPERCASE', 4);
 
318
 
 
319
/**
 
320
 * PCRE for HTML attributes
 
321
 */
 
322
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]*');
 
323
 
 
324
/**
 
325
 * PCRE for XML attributes
 
326
 */
 
327
define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
 
328
 
 
329
/**
 
330
 * XML Namespace
 
331
 */
 
332
define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
 
333
 
 
334
/**
 
335
 * Atom 1.0 Namespace
 
336
 */
 
337
define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
 
338
 
 
339
/**
 
340
 * Atom 0.3 Namespace
 
341
 */
 
342
define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
 
343
 
 
344
/**
 
345
 * RDF Namespace
 
346
 */
 
347
define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
 
348
 
 
349
/**
 
350
 * RSS 0.90 Namespace
 
351
 */
 
352
define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
 
353
 
 
354
/**
 
355
 * RSS 1.0 Namespace
 
356
 */
 
357
define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
 
358
 
 
359
/**
 
360
 * RSS 1.0 Content Module Namespace
 
361
 */
 
362
define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
 
363
 
 
364
/**
 
365
 * RSS 2.0 Namespace
 
366
 * (Stupid, I know, but I'm certain it will confuse people less with support.)
 
367
 */
 
368
define('SIMPLEPIE_NAMESPACE_RSS_20', '');
 
369
 
 
370
/**
 
371
 * DC 1.0 Namespace
 
372
 */
 
373
define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
 
374
 
 
375
/**
 
376
 * DC 1.1 Namespace
 
377
 */
 
378
define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
 
379
 
 
380
/**
 
381
 * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
 
382
 */
 
383
define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
 
384
 
 
385
/**
 
386
 * GeoRSS Namespace
 
387
 */
 
388
define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
 
389
 
 
390
/**
 
391
 * Media RSS Namespace
 
392
 */
 
393
define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
 
394
 
 
395
/**
 
396
 * Wrong Media RSS Namespace. Caused by a long-standing typo in the spec.
 
397
 */
 
398
define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
 
399
 
 
400
/**
 
401
 * Wrong Media RSS Namespace #2. New namespace introduced in Media RSS 1.5.
 
402
 */
 
403
define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2', 'http://video.search.yahoo.com/mrss');
 
404
 
 
405
/**
 
406
 * Wrong Media RSS Namespace #3. A possible typo of the Media RSS 1.5 namespace.
 
407
 */
 
408
define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3', 'http://video.search.yahoo.com/mrss/');
 
409
 
 
410
/**
 
411
 * Wrong Media RSS Namespace #4. New spec location after the RSS Advisory Board takes it over, but not a valid namespace.
 
412
 */
 
413
define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4', 'http://www.rssboard.org/media-rss');
 
414
 
 
415
/**
 
416
 * Wrong Media RSS Namespace #5. A possible typo of the RSS Advisory Board URL.
 
417
 */
 
418
define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5', 'http://www.rssboard.org/media-rss/');
 
419
 
 
420
/**
 
421
 * iTunes RSS Namespace
 
422
 */
 
423
define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
 
424
 
 
425
/**
 
426
 * XHTML Namespace
 
427
 */
 
428
define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
 
429
 
 
430
/**
 
431
 * IANA Link Relations Registry
 
432
 */
 
433
define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
 
434
 
 
435
/**
 
436
 * No file source
 
437
 */
 
438
define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
 
439
 
 
440
/**
 
441
 * Remote file source
 
442
 */
 
443
define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
 
444
 
 
445
/**
 
446
 * Local file source
 
447
 */
 
448
define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
 
449
 
 
450
/**
 
451
 * fsockopen() file source
 
452
 */
 
453
define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
 
454
 
 
455
/**
 
456
 * cURL file source
 
457
 */
 
458
define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
 
459
 
 
460
/**
 
461
 * file_get_contents() file source
 
462
 */
 
463
define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
 
464
 
 
465
 
 
466
 
 
467
/**
 
468
 * SimplePie
 
469
 *
 
470
 * @package SimplePie
 
471
 * @subpackage API
 
472
 */
 
473
class SimplePie
 
474
{
 
475
        /**
 
476
         * @var array Raw data
 
477
         * @access private
 
478
         */
 
479
        public $data = array();
 
480
 
 
481
        /**
 
482
         * @var mixed Error string
 
483
         * @access private
 
484
         */
 
485
        public $error;
 
486
 
 
487
        /**
 
488
         * @var object Instance of SimplePie_Sanitize (or other class)
 
489
         * @see SimplePie::set_sanitize_class()
 
490
         * @access private
 
491
         */
 
492
        public $sanitize;
 
493
 
 
494
        /**
 
495
         * @var string SimplePie Useragent
 
496
         * @see SimplePie::set_useragent()
 
497
         * @access private
 
498
         */
 
499
        public $useragent = SIMPLEPIE_USERAGENT;
 
500
 
 
501
        /**
 
502
         * @var string Feed URL
 
503
         * @see SimplePie::set_feed_url()
 
504
         * @access private
 
505
         */
 
506
        public $feed_url;
 
507
 
 
508
        /**
 
509
         * @var object Instance of SimplePie_File to use as a feed
 
510
         * @see SimplePie::set_file()
 
511
         * @access private
 
512
         */
 
513
        public $file;
 
514
 
 
515
        /**
 
516
         * @var string Raw feed data
 
517
         * @see SimplePie::set_raw_data()
 
518
         * @access private
 
519
         */
 
520
        public $raw_data;
 
521
 
 
522
        /**
 
523
         * @var int Timeout for fetching remote files
 
524
         * @see SimplePie::set_timeout()
 
525
         * @access private
 
526
         */
 
527
        public $timeout = 10;
 
528
 
 
529
        /**
 
530
         * @var bool Forces fsockopen() to be used for remote files instead
 
531
         * of cURL, even if a new enough version is installed
 
532
         * @see SimplePie::force_fsockopen()
 
533
         * @access private
 
534
         */
 
535
        public $force_fsockopen = false;
 
536
 
 
537
        /**
 
538
         * @var bool Force the given data/URL to be treated as a feed no matter what
 
539
         * it appears like
 
540
         * @see SimplePie::force_feed()
 
541
         * @access private
 
542
         */
 
543
        public $force_feed = false;
 
544
 
 
545
        /**
 
546
         * @var bool Enable/Disable Caching
 
547
         * @see SimplePie::enable_cache()
 
548
         * @access private
 
549
         */
 
550
        public $cache = true;
 
551
 
 
552
        /**
 
553
         * @var int Cache duration (in seconds)
 
554
         * @see SimplePie::set_cache_duration()
 
555
         * @access private
 
556
         */
 
557
        public $cache_duration = 3600;
 
558
 
 
559
        /**
 
560
         * @var int Auto-discovery cache duration (in seconds)
 
561
         * @see SimplePie::set_autodiscovery_cache_duration()
 
562
         * @access private
 
563
         */
 
564
        public $autodiscovery_cache_duration = 604800; // 7 Days.
 
565
 
 
566
        /**
 
567
         * @var string Cache location (relative to executing script)
 
568
         * @see SimplePie::set_cache_location()
 
569
         * @access private
 
570
         */
 
571
        public $cache_location = './cache';
 
572
 
 
573
        /**
 
574
         * @var string Function that creates the cache filename
 
575
         * @see SimplePie::set_cache_name_function()
 
576
         * @access private
 
577
         */
 
578
        public $cache_name_function = 'md5';
 
579
 
 
580
        /**
 
581
         * @var bool Reorder feed by date descending
 
582
         * @see SimplePie::enable_order_by_date()
 
583
         * @access private
 
584
         */
 
585
        public $order_by_date = true;
 
586
 
 
587
        /**
 
588
         * @var mixed Force input encoding to be set to the follow value
 
589
         * (false, or anything type-cast to false, disables this feature)
 
590
         * @see SimplePie::set_input_encoding()
 
591
         * @access private
 
592
         */
 
593
        public $input_encoding = false;
 
594
 
 
595
        /**
 
596
         * @var int Feed Autodiscovery Level
 
597
         * @see SimplePie::set_autodiscovery_level()
 
598
         * @access private
 
599
         */
 
600
        public $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
 
601
 
 
602
        /**
 
603
         * Class registry object
 
604
         *
 
605
         * @var SimplePie_Registry
 
606
         */
 
607
        public $registry;
 
608
 
 
609
        /**
 
610
         * @var int Maximum number of feeds to check with autodiscovery
 
611
         * @see SimplePie::set_max_checked_feeds()
 
612
         * @access private
 
613
         */
 
614
        public $max_checked_feeds = 10;
 
615
 
 
616
        /**
 
617
         * @var array All the feeds found during the autodiscovery process
 
618
         * @see SimplePie::get_all_discovered_feeds()
 
619
         * @access private
 
620
         */
 
621
        public $all_discovered_feeds = array();
 
622
 
 
623
        /**
 
624
         * @var string Web-accessible path to the handler_image.php file.
 
625
         * @see SimplePie::set_image_handler()
 
626
         * @access private
 
627
         */
 
628
        public $image_handler = '';
 
629
 
 
630
        /**
 
631
         * @var array Stores the URLs when multiple feeds are being initialized.
 
632
         * @see SimplePie::set_feed_url()
 
633
         * @access private
 
634
         */
 
635
        public $multifeed_url = array();
 
636
 
 
637
        /**
 
638
         * @var array Stores SimplePie objects when multiple feeds initialized.
 
639
         * @access private
 
640
         */
 
641
        public $multifeed_objects = array();
 
642
 
 
643
        /**
 
644
         * @var array Stores the get_object_vars() array for use with multifeeds.
 
645
         * @see SimplePie::set_feed_url()
 
646
         * @access private
 
647
         */
 
648
        public $config_settings = null;
 
649
 
 
650
        /**
 
651
         * @var integer Stores the number of items to return per-feed with multifeeds.
 
652
         * @see SimplePie::set_item_limit()
 
653
         * @access private
 
654
         */
 
655
        public $item_limit = 0;
 
656
 
 
657
        /**
 
658
         * @var array Stores the default attributes to be stripped by strip_attributes().
 
659
         * @see SimplePie::strip_attributes()
 
660
         * @access private
 
661
         */
 
662
        public $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
 
663
 
 
664
        /**
 
665
         * @var array Stores the default tags to be stripped by strip_htmltags().
 
666
         * @see SimplePie::strip_htmltags()
 
667
         * @access private
 
668
         */
 
669
        public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
 
670
 
 
671
        /**
 
672
         * The SimplePie class contains feed level data and options
 
673
         *
 
674
         * To use SimplePie, create the SimplePie object with no parameters. You can
 
675
         * then set configuration options using the provided methods. After setting
 
676
         * them, you must initialise the feed using $feed->init(). At that point the
 
677
         * object's methods and properties will be available to you.
 
678
         *
 
679
         * Previously, it was possible to pass in the feed URL along with cache
 
680
         * options directly into the constructor. This has been removed as of 1.3 as
 
681
         * it caused a lot of confusion.
 
682
         *
 
683
         * @since 1.0 Preview Release
 
684
         */
 
685
        public function __construct()
 
686
        {
 
687
                if (version_compare(PHP_VERSION, '5.2', '<'))
 
688
                {
 
689
                        trigger_error('PHP 4.x, 5.0 and 5.1 are no longer supported. Please upgrade to PHP 5.2 or newer.');
 
690
                        die();
 
691
                }
 
692
 
 
693
                // Other objects, instances created here so we can set options on them
 
694
                $this->sanitize = new SimplePie_Sanitize();
 
695
                $this->registry = new SimplePie_Registry();
 
696
 
 
697
                if (func_num_args() > 0)
 
698
                {
 
699
                        $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
 
700
                        trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_location() directly.', $level);
 
701
 
 
702
                        $args = func_get_args();
 
703
                        switch (count($args)) {
 
704
                                case 3:
 
705
                                        $this->set_cache_duration($args[2]);
 
706
                                case 2:
 
707
                                        $this->set_cache_location($args[1]);
 
708
                                case 1:
 
709
                                        $this->set_feed_url($args[0]);
 
710
                                        $this->init();
 
711
                        }
 
712
                }
 
713
        }
 
714
 
 
715
        /**
 
716
         * Used for converting object to a string
 
717
         */
 
718
        public function __toString()
 
719
        {
 
720
                return md5(serialize($this->data));
 
721
        }
 
722
 
 
723
        /**
 
724
         * Remove items that link back to this before destroying this object
 
725
         */
 
726
        public function __destruct()
 
727
        {
 
728
                if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
 
729
                {
 
730
                        if (!empty($this->data['items']))
 
731
                        {
 
732
                                foreach ($this->data['items'] as $item)
 
733
                                {
 
734
                                        $item->__destruct();
 
735
                                }
 
736
                                unset($item, $this->data['items']);
 
737
                        }
 
738
                        if (!empty($this->data['ordered_items']))
 
739
                        {
 
740
                                foreach ($this->data['ordered_items'] as $item)
 
741
                                {
 
742
                                        $item->__destruct();
 
743
                                }
 
744
                                unset($item, $this->data['ordered_items']);
 
745
                        }
 
746
                }
 
747
        }
 
748
 
 
749
        /**
 
750
         * Force the given data/URL to be treated as a feed
 
751
         *
 
752
         * This tells SimplePie to ignore the content-type provided by the server.
 
753
         * Be careful when using this option, as it will also disable autodiscovery.
 
754
         *
 
755
         * @since 1.1
 
756
         * @param bool $enable Force the given data/URL to be treated as a feed
 
757
         */
 
758
        public function force_feed($enable = false)
 
759
        {
 
760
                $this->force_feed = (bool) $enable;
 
761
        }
 
762
 
 
763
        /**
 
764
         * Set the URL of the feed you want to parse
 
765
         *
 
766
         * This allows you to enter the URL of the feed you want to parse, or the
 
767
         * website you want to try to use auto-discovery on. This takes priority
 
768
         * over any set raw data.
 
769
         *
 
770
         * You can set multiple feeds to mash together by passing an array instead
 
771
         * of a string for the $url. Remember that with each additional feed comes
 
772
         * additional processing and resources.
 
773
         *
 
774
         * @since 1.0 Preview Release
 
775
         * @see set_raw_data()
 
776
         * @param string|array $url This is the URL (or array of URLs) that you want to parse.
 
777
         */
 
778
        public function set_feed_url($url)
 
779
        {
 
780
                $this->multifeed_url = array();
 
781
                if (is_array($url))
 
782
                {
 
783
                        foreach ($url as $value)
 
784
                        {
 
785
                                $this->multifeed_url[] = $this->registry->call('Misc', 'fix_protocol', array($value, 1));
 
786
                        }
 
787
                }
 
788
                else
 
789
                {
 
790
                        $this->feed_url = $this->registry->call('Misc', 'fix_protocol', array($url, 1));
 
791
                }
 
792
        }
 
793
 
 
794
        /**
 
795
         * Set an instance of {@see SimplePie_File} to use as a feed
 
796
         *
 
797
         * @param SimplePie_File &$file
 
798
         * @return bool True on success, false on failure
 
799
         */
 
800
        public function set_file(&$file)
 
801
        {
 
802
                if ($file instanceof SimplePie_File)
 
803
                {
 
804
                        $this->feed_url = $file->url;
 
805
                        $this->file =& $file;
 
806
                        return true;
 
807
                }
 
808
                return false;
 
809
        }
 
810
 
 
811
        /**
 
812
         * Set the raw XML data to parse
 
813
         *
 
814
         * Allows you to use a string of RSS/Atom data instead of a remote feed.
 
815
         *
 
816
         * If you have a feed available as a string in PHP, you can tell SimplePie
 
817
         * to parse that data string instead of a remote feed. Any set feed URL
 
818
         * takes precedence.
 
819
         *
 
820
         * @since 1.0 Beta 3
 
821
         * @param string $data RSS or Atom data as a string.
 
822
         * @see set_feed_url()
 
823
         */
 
824
        public function set_raw_data($data)
 
825
        {
 
826
                $this->raw_data = $data;
 
827
        }
 
828
 
 
829
        /**
 
830
         * Set the the default timeout for fetching remote feeds
 
831
         *
 
832
         * This allows you to change the maximum time the feed's server to respond
 
833
         * and send the feed back.
 
834
         *
 
835
         * @since 1.0 Beta 3
 
836
         * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
 
837
         */
 
838
        public function set_timeout($timeout = 10)
 
839
        {
 
840
                $this->timeout = (int) $timeout;
 
841
        }
 
842
 
 
843
        /**
 
844
         * Force SimplePie to use fsockopen() instead of cURL
 
845
         *
 
846
         * @since 1.0 Beta 3
 
847
         * @param bool $enable Force fsockopen() to be used
 
848
         */
 
849
        public function force_fsockopen($enable = false)
 
850
        {
 
851
                $this->force_fsockopen = (bool) $enable;
 
852
        }
 
853
 
 
854
        /**
 
855
         * Enable/disable caching in SimplePie.
 
856
         *
 
857
         * This option allows you to disable caching all-together in SimplePie.
 
858
         * However, disabling the cache can lead to longer load times.
 
859
         *
 
860
         * @since 1.0 Preview Release
 
861
         * @param bool $enable Enable caching
 
862
         */
 
863
        public function enable_cache($enable = true)
 
864
        {
 
865
                $this->cache = (bool) $enable;
 
866
        }
 
867
 
 
868
        /**
 
869
         * Set the length of time (in seconds) that the contents of a feed will be
 
870
         * cached
 
871
         *
 
872
         * @param int $seconds The feed content cache duration
 
873
         */
 
874
        public function set_cache_duration($seconds = 3600)
 
875
        {
 
876
                $this->cache_duration = (int) $seconds;
 
877
        }
 
878
 
 
879
        /**
 
880
         * Set the length of time (in seconds) that the autodiscovered feed URL will
 
881
         * be cached
 
882
         *
 
883
         * @param int $seconds The autodiscovered feed URL cache duration.
 
884
         */
 
885
        public function set_autodiscovery_cache_duration($seconds = 604800)
 
886
        {
 
887
                $this->autodiscovery_cache_duration = (int) $seconds;
 
888
        }
 
889
 
 
890
        /**
 
891
         * Set the file system location where the cached files should be stored
 
892
         *
 
893
         * @param string $location The file system location.
 
894
         */
 
895
        public function set_cache_location($location = './cache')
 
896
        {
 
897
                $this->cache_location = (string) $location;
 
898
        }
 
899
 
 
900
        /**
 
901
         * Set whether feed items should be sorted into reverse chronological order
 
902
         *
 
903
         * @param bool $enable Sort as reverse chronological order.
 
904
         */
 
905
        public function enable_order_by_date($enable = true)
 
906
        {
 
907
                $this->order_by_date = (bool) $enable;
 
908
        }
 
909
 
 
910
        /**
 
911
         * Set the character encoding used to parse the feed
 
912
         *
 
913
         * This overrides the encoding reported by the feed, however it will fall
 
914
         * back to the normal encoding detection if the override fails
 
915
         *
 
916
         * @param string $encoding Character encoding
 
917
         */
 
918
        public function set_input_encoding($encoding = false)
 
919
        {
 
920
                if ($encoding)
 
921
                {
 
922
                        $this->input_encoding = (string) $encoding;
 
923
                }
 
924
                else
 
925
                {
 
926
                        $this->input_encoding = false;
 
927
                }
 
928
        }
 
929
 
 
930
        /**
 
931
         * Set how much feed autodiscovery to do
 
932
         *
 
933
         * @see SIMPLEPIE_LOCATOR_NONE
 
934
         * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
 
935
         * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
 
936
         * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
 
937
         * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
 
938
         * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
 
939
         * @see SIMPLEPIE_LOCATOR_ALL
 
940
         * @param int $level Feed Autodiscovery Level (level can be a combination of the above constants, see bitwise OR operator)
 
941
         */
 
942
        public function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
 
943
        {
 
944
                $this->autodiscovery = (int) $level;
 
945
        }
 
946
 
 
947
        /**
 
948
         * Get the class registry
 
949
         *
 
950
         * Use this to override SimplePie's default classes
 
951
         * @see SimplePie_Registry
 
952
         * @return SimplePie_Registry
 
953
         */
 
954
        public function &get_registry()
 
955
        {
 
956
                return $this->registry;
 
957
        }
 
958
 
 
959
        /**#@+
 
960
         * Useful when you are overloading or extending SimplePie's default classes.
 
961
         *
 
962
         * @deprecated Use {@see get_registry()} instead
 
963
         * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
 
964
         * @param string $class Name of custom class
 
965
         * @return boolean True on success, false otherwise
 
966
         */
 
967
        /**
 
968
         * Set which class SimplePie uses for caching
 
969
         */
 
970
        public function set_cache_class($class = 'SimplePie_Cache')
 
971
        {
 
972
                return $this->registry->register('Cache', $class, true);
 
973
        }
 
974
 
 
975
        /**
 
976
         * Set which class SimplePie uses for auto-discovery
 
977
         */
 
978
        public function set_locator_class($class = 'SimplePie_Locator')
 
979
        {
 
980
                return $this->registry->register('Locator', $class, true);
 
981
        }
 
982
 
 
983
        /**
 
984
         * Set which class SimplePie uses for XML parsing
 
985
         */
 
986
        public function set_parser_class($class = 'SimplePie_Parser')
 
987
        {
 
988
                return $this->registry->register('Parser', $class, true);
 
989
        }
 
990
 
 
991
        /**
 
992
         * Set which class SimplePie uses for remote file fetching
 
993
         */
 
994
        public function set_file_class($class = 'SimplePie_File')
 
995
        {
 
996
                return $this->registry->register('File', $class, true);
 
997
        }
 
998
 
 
999
        /**
 
1000
         * Set which class SimplePie uses for data sanitization
 
1001
         */
 
1002
        public function set_sanitize_class($class = 'SimplePie_Sanitize')
 
1003
        {
 
1004
                return $this->registry->register('Sanitize', $class, true);
 
1005
        }
 
1006
 
 
1007
        /**
 
1008
         * Set which class SimplePie uses for handling feed items
 
1009
         */
 
1010
        public function set_item_class($class = 'SimplePie_Item')
 
1011
        {
 
1012
                return $this->registry->register('Item', $class, true);
 
1013
        }
 
1014
 
 
1015
        /**
 
1016
         * Set which class SimplePie uses for handling author data
 
1017
         */
 
1018
        public function set_author_class($class = 'SimplePie_Author')
 
1019
        {
 
1020
                return $this->registry->register('Author', $class, true);
 
1021
        }
 
1022
 
 
1023
        /**
 
1024
         * Set which class SimplePie uses for handling category data
 
1025
         */
 
1026
        public function set_category_class($class = 'SimplePie_Category')
 
1027
        {
 
1028
                return $this->registry->register('Category', $class, true);
 
1029
        }
 
1030
 
 
1031
        /**
 
1032
         * Set which class SimplePie uses for feed enclosures
 
1033
         */
 
1034
        public function set_enclosure_class($class = 'SimplePie_Enclosure')
 
1035
        {
 
1036
                return $this->registry->register('Enclosure', $class, true);
 
1037
        }
 
1038
 
 
1039
        /**
 
1040
         * Set which class SimplePie uses for `<media:text>` captions
 
1041
         */
 
1042
        public function set_caption_class($class = 'SimplePie_Caption')
 
1043
        {
 
1044
                return $this->registry->register('Caption', $class, true);
 
1045
        }
 
1046
 
 
1047
        /**
 
1048
         * Set which class SimplePie uses for `<media:copyright>`
 
1049
         */
 
1050
        public function set_copyright_class($class = 'SimplePie_Copyright')
 
1051
        {
 
1052
                return $this->registry->register('Copyright', $class, true);
 
1053
        }
 
1054
 
 
1055
        /**
 
1056
         * Set which class SimplePie uses for `<media:credit>`
 
1057
         */
 
1058
        public function set_credit_class($class = 'SimplePie_Credit')
 
1059
        {
 
1060
                return $this->registry->register('Credit', $class, true);
 
1061
        }
 
1062
 
 
1063
        /**
 
1064
         * Set which class SimplePie uses for `<media:rating>`
 
1065
         */
 
1066
        public function set_rating_class($class = 'SimplePie_Rating')
 
1067
        {
 
1068
                return $this->registry->register('Rating', $class, true);
 
1069
        }
 
1070
 
 
1071
        /**
 
1072
         * Set which class SimplePie uses for `<media:restriction>`
 
1073
         */
 
1074
        public function set_restriction_class($class = 'SimplePie_Restriction')
 
1075
        {
 
1076
                return $this->registry->register('Restriction', $class, true);
 
1077
        }
 
1078
 
 
1079
        /**
 
1080
         * Set which class SimplePie uses for content-type sniffing
 
1081
         */
 
1082
        public function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
 
1083
        {
 
1084
                return $this->registry->register('Content_Type_Sniffer', $class, true);
 
1085
        }
 
1086
 
 
1087
        /**
 
1088
         * Set which class SimplePie uses item sources
 
1089
         */
 
1090
        public function set_source_class($class = 'SimplePie_Source')
 
1091
        {
 
1092
                return $this->registry->register('Source', $class, true);
 
1093
        }
 
1094
        /**#@-*/
 
1095
 
 
1096
        /**
 
1097
         * Set the user agent string
 
1098
         *
 
1099
         * @param string $ua New user agent string.
 
1100
         */
 
1101
        public function set_useragent($ua = SIMPLEPIE_USERAGENT)
 
1102
        {
 
1103
                $this->useragent = (string) $ua;
 
1104
        }
 
1105
 
 
1106
        /**
 
1107
         * Set callback function to create cache filename with
 
1108
         *
 
1109
         * @param mixed $function Callback function
 
1110
         */
 
1111
        public function set_cache_name_function($function = 'md5')
 
1112
        {
 
1113
                if (is_callable($function))
 
1114
                {
 
1115
                        $this->cache_name_function = $function;
 
1116
                }
 
1117
        }
 
1118
 
 
1119
        /**
 
1120
         * Set options to make SP as fast as possible
 
1121
         *
 
1122
         * Forgoes a substantial amount of data sanitization in favor of speed. This
 
1123
         * turns SimplePie into a dumb parser of feeds.
 
1124
         *
 
1125
         * @param bool $set Whether to set them or not
 
1126
         */
 
1127
        public function set_stupidly_fast($set = false)
 
1128
        {
 
1129
                if ($set)
 
1130
                {
 
1131
                        $this->enable_order_by_date(false);
 
1132
                        $this->remove_div(false);
 
1133
                        $this->strip_comments(false);
 
1134
                        $this->strip_htmltags(false);
 
1135
                        $this->strip_attributes(false);
 
1136
                        $this->set_image_handler(false);
 
1137
                }
 
1138
        }
 
1139
 
 
1140
        /**
 
1141
         * Set maximum number of feeds to check with autodiscovery
 
1142
         *
 
1143
         * @param int $max Maximum number of feeds to check
 
1144
         */
 
1145
        public function set_max_checked_feeds($max = 10)
 
1146
        {
 
1147
                $this->max_checked_feeds = (int) $max;
 
1148
        }
 
1149
 
 
1150
        public function remove_div($enable = true)
 
1151
        {
 
1152
                $this->sanitize->remove_div($enable);
 
1153
        }
 
1154
 
 
1155
        public function strip_htmltags($tags = '', $encode = null)
 
1156
        {
 
1157
                if ($tags === '')
 
1158
                {
 
1159
                        $tags = $this->strip_htmltags;
 
1160
                }
 
1161
                $this->sanitize->strip_htmltags($tags);
 
1162
                if ($encode !== null)
 
1163
                {
 
1164
                        $this->sanitize->encode_instead_of_strip($tags);
 
1165
                }
 
1166
        }
 
1167
 
 
1168
        public function encode_instead_of_strip($enable = true)
 
1169
        {
 
1170
                $this->sanitize->encode_instead_of_strip($enable);
 
1171
        }
 
1172
 
 
1173
        public function strip_attributes($attribs = '')
 
1174
        {
 
1175
                if ($attribs === '')
 
1176
                {
 
1177
                        $attribs = $this->strip_attributes;
 
1178
                }
 
1179
                $this->sanitize->strip_attributes($attribs);
 
1180
        }
 
1181
 
 
1182
        /**
 
1183
         * Set the output encoding
 
1184
         *
 
1185
         * Allows you to override SimplePie's output to match that of your webpage.
 
1186
         * This is useful for times when your webpages are not being served as
 
1187
         * UTF-8.  This setting will be obeyed by {@see handle_content_type()}, and
 
1188
         * is similar to {@see set_input_encoding()}.
 
1189
         *
 
1190
         * It should be noted, however, that not all character encodings can support
 
1191
         * all characters.  If your page is being served as ISO-8859-1 and you try
 
1192
         * to display a Japanese feed, you'll likely see garbled characters.
 
1193
         * Because of this, it is highly recommended to ensure that your webpages
 
1194
         * are served as UTF-8.
 
1195
         *
 
1196
         * The number of supported character encodings depends on whether your web
 
1197
         * host supports {@link http://php.net/mbstring mbstring},
 
1198
         * {@link http://php.net/iconv iconv}, or both. See
 
1199
         * {@link http://simplepie.org/wiki/faq/Supported_Character_Encodings} for
 
1200
         * more information.
 
1201
         *
 
1202
         * @param string $encoding
 
1203
         */
 
1204
        public function set_output_encoding($encoding = 'UTF-8')
 
1205
        {
 
1206
                $this->sanitize->set_output_encoding($encoding);
 
1207
        }
 
1208
 
 
1209
        public function strip_comments($strip = false)
 
1210
        {
 
1211
                $this->sanitize->strip_comments($strip);
 
1212
        }
 
1213
 
 
1214
        /**
 
1215
         * Set element/attribute key/value pairs of HTML attributes
 
1216
         * containing URLs that need to be resolved relative to the feed
 
1217
         *
 
1218
         * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite,
 
1219
         * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite,
 
1220
         * |q|@cite
 
1221
         *
 
1222
         * @since 1.0
 
1223
         * @param array|null $element_attribute Element/attribute key/value pairs, null for default
 
1224
         */
 
1225
        public function set_url_replacements($element_attribute = null)
 
1226
        {
 
1227
                $this->sanitize->set_url_replacements($element_attribute);
 
1228
        }
 
1229
 
 
1230
        /**
 
1231
         * Set the handler to enable the display of cached images.
 
1232
         *
 
1233
         * @param str $page Web-accessible path to the handler_image.php file.
 
1234
         * @param str $qs The query string that the value should be passed to.
 
1235
         */
 
1236
        public function set_image_handler($page = false, $qs = 'i')
 
1237
        {
 
1238
                if ($page !== false)
 
1239
                {
 
1240
                        $this->sanitize->set_image_handler($page . '?' . $qs . '=');
 
1241
                }
 
1242
                else
 
1243
                {
 
1244
                        $this->image_handler = '';
 
1245
                }
 
1246
        }
 
1247
 
 
1248
        /**
 
1249
         * Set the limit for items returned per-feed with multifeeds
 
1250
         *
 
1251
         * @param integer $limit The maximum number of items to return.
 
1252
         */
 
1253
        public function set_item_limit($limit = 0)
 
1254
        {
 
1255
                $this->item_limit = (int) $limit;
 
1256
        }
 
1257
 
 
1258
        /**
 
1259
         * Initialize the feed object
 
1260
         *
 
1261
         * This is what makes everything happen.  Period.  This is where all of the
 
1262
         * configuration options get processed, feeds are fetched, cached, and
 
1263
         * parsed, and all of that other good stuff.
 
1264
         *
 
1265
         * @return boolean True if successful, false otherwise
 
1266
         */
 
1267
        public function init()
 
1268
        {
 
1269
                // Check absolute bare minimum requirements.
 
1270
                if (!extension_loaded('xml') || !extension_loaded('pcre'))
 
1271
                {
 
1272
                        return false;
 
1273
                }
 
1274
                // 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.
 
1275
                elseif (!extension_loaded('xmlreader'))
 
1276
                {
 
1277
                        static $xml_is_sane = null;
 
1278
                        if ($xml_is_sane === null)
 
1279
                        {
 
1280
                                $parser_check = xml_parser_create();
 
1281
                                xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
 
1282
                                xml_parser_free($parser_check);
 
1283
                                $xml_is_sane = isset($values[0]['value']);
 
1284
                        }
 
1285
                        if (!$xml_is_sane)
 
1286
                        {
 
1287
                                return false;
 
1288
                        }
 
1289
                }
 
1290
 
 
1291
                if (method_exists($this->sanitize, 'set_registry'))
 
1292
                {
 
1293
                        $this->sanitize->set_registry($this->registry);
 
1294
                }
 
1295
 
 
1296
                // Pass whatever was set with config options over to the sanitizer.
 
1297
                // Pass the classes in for legacy support; new classes should use the registry instead
 
1298
                $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->registry->get_class('Cache'));
 
1299
                $this->sanitize->pass_file_data($this->registry->get_class('File'), $this->timeout, $this->useragent, $this->force_fsockopen);
 
1300
 
 
1301
                if (!empty($this->multifeed_url))
 
1302
                {
 
1303
                        $i = 0;
 
1304
                        $success = 0;
 
1305
                        $this->multifeed_objects = array();
 
1306
                        $this->error = array();
 
1307
                        foreach ($this->multifeed_url as $url)
 
1308
                        {
 
1309
                                $this->multifeed_objects[$i] = clone $this;
 
1310
                                $this->multifeed_objects[$i]->set_feed_url($url);
 
1311
                                $single_success = $this->multifeed_objects[$i]->init();
 
1312
                                $success |= $single_success;
 
1313
                                if (!$single_success)
 
1314
                                {
 
1315
                                        $this->error[$i] = $this->multifeed_objects[$i]->error();
 
1316
                                }
 
1317
                                $i++;
 
1318
                        }
 
1319
                        return (bool) $success;
 
1320
                }
 
1321
                elseif ($this->feed_url === null && $this->raw_data === null)
 
1322
                {
 
1323
                        return false;
 
1324
                }
 
1325
 
 
1326
                $this->error = null;
 
1327
                $this->data = array();
 
1328
                $this->multifeed_objects = array();
 
1329
                $cache = false;
 
1330
 
 
1331
                if ($this->feed_url !== null)
 
1332
                {
 
1333
                        $parsed_feed_url = $this->registry->call('Misc', 'parse_url', array($this->feed_url));
 
1334
 
 
1335
                        // Decide whether to enable caching
 
1336
                        if ($this->cache && $parsed_feed_url['scheme'] !== '')
 
1337
                        {
 
1338
                                $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc'));
 
1339
                        }
 
1340
 
 
1341
                        // Fetch the data via SimplePie_File into $this->raw_data
 
1342
                        if (($fetched = $this->fetch_data($cache)) === true)
 
1343
                        {
 
1344
                                return true;
 
1345
                        }
 
1346
                        elseif ($fetched === false) {
 
1347
                                return false;
 
1348
                        }
 
1349
 
 
1350
                        list($headers, $sniffed) = $fetched;
 
1351
                }
 
1352
 
 
1353
                // Set up array of possible encodings
 
1354
                $encodings = array();
 
1355
 
 
1356
                // First check to see if input has been overridden.
 
1357
                if ($this->input_encoding !== false)
 
1358
                {
 
1359
                        $encodings[] = $this->input_encoding;
 
1360
                }
 
1361
 
 
1362
                $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
 
1363
                $text_types = array('text/xml', 'text/xml-external-parsed-entity');
 
1364
 
 
1365
                // RFC 3023 (only applies to sniffed content)
 
1366
                if (isset($sniffed))
 
1367
                {
 
1368
                        if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
 
1369
                        {
 
1370
                                if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
 
1371
                                {
 
1372
                                        $encodings[] = strtoupper($charset[1]);
 
1373
                                }
 
1374
                                $encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
 
1375
                                $encodings[] = 'UTF-8';
 
1376
                        }
 
1377
                        elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
 
1378
                        {
 
1379
                                if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
 
1380
                                {
 
1381
                                        $encodings[] = $charset[1];
 
1382
                                }
 
1383
                                $encodings[] = 'US-ASCII';
 
1384
                        }
 
1385
                        // Text MIME-type default
 
1386
                        elseif (substr($sniffed, 0, 5) === 'text/')
 
1387
                        {
 
1388
                                $encodings[] = 'US-ASCII';
 
1389
                        }
 
1390
                }
 
1391
 
 
1392
                // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
 
1393
                $encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
 
1394
                $encodings[] = 'UTF-8';
 
1395
                $encodings[] = 'ISO-8859-1';
 
1396
 
 
1397
                // There's no point in trying an encoding twice
 
1398
                $encodings = array_unique($encodings);
 
1399
 
 
1400
                // Loop through each possible encoding, till we return something, or run out of possibilities
 
1401
                foreach ($encodings as $encoding)
 
1402
                {
 
1403
                        // Change the encoding to UTF-8 (as we always use UTF-8 internally)
 
1404
                        if ($utf8_data = $this->registry->call('Misc', 'change_encoding', array($this->raw_data, $encoding, 'UTF-8')))
 
1405
                        {
 
1406
                                // Create new parser
 
1407
                                $parser = $this->registry->create('Parser');
 
1408
 
 
1409
                                // If it's parsed fine
 
1410
                                if ($parser->parse($utf8_data, 'UTF-8'))
 
1411
                                {
 
1412
                                        $this->data = $parser->get_data();
 
1413
                                        if (!($this->get_type() & ~SIMPLEPIE_TYPE_NONE))
 
1414
                                        {
 
1415
                                                $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
 
1416
                                                $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
 
1417
                                                return false;
 
1418
                                        }
 
1419
 
 
1420
                                        if (isset($headers))
 
1421
                                        {
 
1422
                                                $this->data['headers'] = $headers;
 
1423
                                        }
 
1424
                                        $this->data['build'] = SIMPLEPIE_BUILD;
 
1425
 
 
1426
                                        // Cache the file if caching is enabled
 
1427
                                        if ($cache && !$cache->save($this))
 
1428
                                        {
 
1429
                                                trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
 
1430
                                        }
 
1431
                                        return true;
 
1432
                                }
 
1433
                        }
 
1434
                }
 
1435
 
 
1436
                if (isset($parser))
 
1437
                {
 
1438
                        // We have an error, just set SimplePie_Misc::error to it and quit
 
1439
                        $this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
 
1440
                }
 
1441
                else
 
1442
                {
 
1443
                        $this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.';
 
1444
                }
 
1445
 
 
1446
                $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
 
1447
 
 
1448
                return false;
 
1449
        }
 
1450
 
 
1451
        /**
 
1452
         * Fetch the data via SimplePie_File
 
1453
         *
 
1454
         * If the data is already cached, attempt to fetch it from there instead
 
1455
         * @param SimplePie_Cache|false $cache Cache handler, or false to not load from the cache
 
1456
         * @return array|true Returns true if the data was loaded from the cache, or an array of HTTP headers and sniffed type
 
1457
         */
 
1458
        protected function fetch_data(&$cache)
 
1459
        {
 
1460
                // If it's enabled, use the cache
 
1461
                if ($cache)
 
1462
                {
 
1463
                        // Load the Cache
 
1464
                        $this->data = $cache->load();
 
1465
                        if (!empty($this->data))
 
1466
                        {
 
1467
                                // If the cache is for an outdated build of SimplePie
 
1468
                                if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
 
1469
                                {
 
1470
                                        $cache->unlink();
 
1471
                                        $this->data = array();
 
1472
                                }
 
1473
                                // If we've hit a collision just rerun it with caching disabled
 
1474
                                elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
 
1475
                                {
 
1476
                                        $cache = false;
 
1477
                                        $this->data = array();
 
1478
                                }
 
1479
                                // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
 
1480
                                elseif (isset($this->data['feed_url']))
 
1481
                                {
 
1482
                                        // If the autodiscovery cache is still valid use it.
 
1483
                                        if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
 
1484
                                        {
 
1485
                                                // Do not need to do feed autodiscovery yet.
 
1486
                                                if ($this->data['feed_url'] !== $this->data['url'])
 
1487
                                                {
 
1488
                                                        $this->set_feed_url($this->data['feed_url']);
 
1489
                                                        return $this->init();
 
1490
                                                }
 
1491
 
 
1492
                                                $cache->unlink();
 
1493
                                                $this->data = array();
 
1494
                                        }
 
1495
                                }
 
1496
                                // Check if the cache has been updated
 
1497
                                elseif ($cache->mtime() + $this->cache_duration < time())
 
1498
                                {
 
1499
                                        // If we have last-modified and/or etag set
 
1500
                                        if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
 
1501
                                        {
 
1502
                                                $headers = array(
 
1503
                                                        'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
 
1504
                                                );
 
1505
                                                if (isset($this->data['headers']['last-modified']))
 
1506
                                                {
 
1507
                                                        $headers['if-modified-since'] = $this->data['headers']['last-modified'];
 
1508
                                                }
 
1509
                                                if (isset($this->data['headers']['etag']))
 
1510
                                                {
 
1511
                                                        $headers['if-none-match'] = $this->data['headers']['etag'];
 
1512
                                                }
 
1513
 
 
1514
                                                $file = $this->registry->create('File', array($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen));
 
1515
 
 
1516
                                                if ($file->success)
 
1517
                                                {
 
1518
                                                        if ($file->status_code === 304)
 
1519
                                                        {
 
1520
                                                                $cache->touch();
 
1521
                                                                return true;
 
1522
                                                        }
 
1523
                                                }
 
1524
                                                else
 
1525
                                                {
 
1526
                                                        unset($file);
 
1527
                                                }
 
1528
                                        }
 
1529
                                }
 
1530
                                // If the cache is still valid, just return true
 
1531
                                else
 
1532
                                {
 
1533
                                        $this->raw_data = false;
 
1534
                                        return true;
 
1535
                                }
 
1536
                        }
 
1537
                        // If the cache is empty, delete it
 
1538
                        else
 
1539
                        {
 
1540
                                $cache->unlink();
 
1541
                                $this->data = array();
 
1542
                        }
 
1543
                }
 
1544
                // 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.
 
1545
                if (!isset($file))
 
1546
                {
 
1547
                        if ($this->file instanceof SimplePie_File && $this->file->url === $this->feed_url)
 
1548
                        {
 
1549
                                $file =& $this->file;
 
1550
                        }
 
1551
                        else
 
1552
                        {
 
1553
                                $headers = array(
 
1554
                                        'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
 
1555
                                );
 
1556
                                $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen));
 
1557
                        }
 
1558
                }
 
1559
                // If the file connection has an error, set SimplePie::error to that and quit
 
1560
                if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
 
1561
                {
 
1562
                        $this->error = $file->error;
 
1563
                        return !empty($this->data);
 
1564
                }
 
1565
 
 
1566
                if (!$this->force_feed)
 
1567
                {
 
1568
                        // Check if the supplied URL is a feed, if it isn't, look for it.
 
1569
                        $locate = $this->registry->create('Locator', array(&$file, $this->timeout, $this->useragent, $this->max_checked_feeds));
 
1570
 
 
1571
                        if (!$locate->is_feed($file))
 
1572
                        {
 
1573
                                // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
 
1574
                                unset($file);
 
1575
                                try
 
1576
                                {
 
1577
                                        if (!($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds)))
 
1578
                                        {
 
1579
                                                $this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.";
 
1580
                                                $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
 
1581
                                                return false;
 
1582
                                        }
 
1583
                                }
 
1584
                                catch (SimplePie_Exception $e)
 
1585
                                {
 
1586
                                        // This is usually because DOMDocument doesn't exist
 
1587
                                        $this->error = $e->getMessage();
 
1588
                                        $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, $e->getFile(), $e->getLine()));
 
1589
                                        return false;
 
1590
                                }
 
1591
                                if ($cache)
 
1592
                                {
 
1593
                                        $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
 
1594
                                        if (!$cache->save($this))
 
1595
                                        {
 
1596
                                                trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
 
1597
                                        }
 
1598
                                        $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc'));
 
1599
                                }
 
1600
                                $this->feed_url = $file->url;
 
1601
                        }
 
1602
                        $locate = null;
 
1603
                }
 
1604
 
 
1605
                $this->raw_data = $file->body;
 
1606
 
 
1607
                $headers = $file->headers;
 
1608
                $sniffer = $this->registry->create('Content_Type_Sniffer', array(&$file));
 
1609
                $sniffed = $sniffer->get_type();
 
1610
 
 
1611
                return array($headers, $sniffed);
 
1612
        }
 
1613
 
 
1614
        /**
 
1615
         * Get the error message for the occurred error.
 
1616
         *
 
1617
         * @return string|array Error message, or array of messages for multifeeds
 
1618
         */
 
1619
        public function error()
 
1620
        {
 
1621
                return $this->error;
 
1622
        }
 
1623
 
 
1624
        /**
 
1625
         * Get the raw XML
 
1626
         *
 
1627
         * This is the same as the old `$feed->enable_xml_dump(true)`, but returns
 
1628
         * the data instead of printing it.
 
1629
         *
 
1630
         * @return string|boolean Raw XML data, false if the cache is used
 
1631
         */
 
1632
        public function get_raw_data()
 
1633
        {
 
1634
                return $this->raw_data;
 
1635
        }
 
1636
 
 
1637
        /**
 
1638
         * Get the character encoding used for output
 
1639
         *
 
1640
         * @since Preview Release
 
1641
         * @return string
 
1642
         */
 
1643
        public function get_encoding()
 
1644
        {
 
1645
                return $this->sanitize->output_encoding;
 
1646
        }
 
1647
 
 
1648
        /**
 
1649
         * Send the content-type header with correct encoding
 
1650
         *
 
1651
         * This method ensures that the SimplePie-enabled page is being served with
 
1652
         * the correct {@link http://www.iana.org/assignments/media-types/ mime-type}
 
1653
         * and character encoding HTTP headers (character encoding determined by the
 
1654
         * {@see set_output_encoding} config option).
 
1655
         *
 
1656
         * This won't work properly if any content or whitespace has already been
 
1657
         * sent to the browser, because it relies on PHP's
 
1658
         * {@link http://php.net/header header()} function, and these are the
 
1659
         * circumstances under which the function works.
 
1660
         *
 
1661
         * Because it's setting these settings for the entire page (as is the nature
 
1662
         * of HTTP headers), this should only be used once per page (again, at the
 
1663
         * top).
 
1664
         *
 
1665
         * @param string $mime MIME type to serve the page as
 
1666
         */
 
1667
        public function handle_content_type($mime = 'text/html')
 
1668
        {
 
1669
                if (!headers_sent())
 
1670
                {
 
1671
                        $header = "Content-type: $mime;";
 
1672
                        if ($this->get_encoding())
 
1673
                        {
 
1674
                                $header .= ' charset=' . $this->get_encoding();
 
1675
                        }
 
1676
                        else
 
1677
                        {
 
1678
                                $header .= ' charset=UTF-8';
 
1679
                        }
 
1680
                        header($header);
 
1681
                }
 
1682
        }
 
1683
 
 
1684
        /**
 
1685
         * Get the type of the feed
 
1686
         *
 
1687
         * This returns a SIMPLEPIE_TYPE_* constant, which can be tested against
 
1688
         * using {@link http://php.net/language.operators.bitwise bitwise operators}
 
1689
         *
 
1690
         * @since 0.8 (usage changed to using constants in 1.0)
 
1691
         * @see SIMPLEPIE_TYPE_NONE Unknown.
 
1692
         * @see SIMPLEPIE_TYPE_RSS_090 RSS 0.90.
 
1693
         * @see SIMPLEPIE_TYPE_RSS_091_NETSCAPE RSS 0.91 (Netscape).
 
1694
         * @see SIMPLEPIE_TYPE_RSS_091_USERLAND RSS 0.91 (Userland).
 
1695
         * @see SIMPLEPIE_TYPE_RSS_091 RSS 0.91.
 
1696
         * @see SIMPLEPIE_TYPE_RSS_092 RSS 0.92.
 
1697
         * @see SIMPLEPIE_TYPE_RSS_093 RSS 0.93.
 
1698
         * @see SIMPLEPIE_TYPE_RSS_094 RSS 0.94.
 
1699
         * @see SIMPLEPIE_TYPE_RSS_10 RSS 1.0.
 
1700
         * @see SIMPLEPIE_TYPE_RSS_20 RSS 2.0.x.
 
1701
         * @see SIMPLEPIE_TYPE_RSS_RDF RDF-based RSS.
 
1702
         * @see SIMPLEPIE_TYPE_RSS_SYNDICATION Non-RDF-based RSS (truly intended as syndication format).
 
1703
         * @see SIMPLEPIE_TYPE_RSS_ALL Any version of RSS.
 
1704
         * @see SIMPLEPIE_TYPE_ATOM_03 Atom 0.3.
 
1705
         * @see SIMPLEPIE_TYPE_ATOM_10 Atom 1.0.
 
1706
         * @see SIMPLEPIE_TYPE_ATOM_ALL Any version of Atom.
 
1707
         * @see SIMPLEPIE_TYPE_ALL Any known/supported feed type.
 
1708
         * @return int SIMPLEPIE_TYPE_* constant
 
1709
         */
 
1710
        public function get_type()
 
1711
        {
 
1712
                if (!isset($this->data['type']))
 
1713
                {
 
1714
                        $this->data['type'] = SIMPLEPIE_TYPE_ALL;
 
1715
                        if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
 
1716
                        {
 
1717
                                $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
 
1718
                        }
 
1719
                        elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
 
1720
                        {
 
1721
                                $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
 
1722
                        }
 
1723
                        elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
 
1724
                        {
 
1725
                                if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
 
1726
                                || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
 
1727
                                || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
 
1728
                                || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
 
1729
                                {
 
1730
                                        $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
 
1731
                                }
 
1732
                                if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
 
1733
                                || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
 
1734
                                || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
 
1735
                                || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
 
1736
                                {
 
1737
                                        $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
 
1738
                                }
 
1739
                        }
 
1740
                        elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
 
1741
                        {
 
1742
                                $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
 
1743
                                if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
 
1744
                                {
 
1745
                                        switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
 
1746
                                        {
 
1747
                                                case '0.91':
 
1748
                                                        $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
 
1749
                                                        if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
 
1750
                                                        {
 
1751
                                                                switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
 
1752
                                                                {
 
1753
                                                                        case '0':
 
1754
                                                                                $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
 
1755
                                                                                break;
 
1756
 
 
1757
                                                                        case '24':
 
1758
                                                                                $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
 
1759
                                                                                break;
 
1760
                                                                }
 
1761
                                                        }
 
1762
                                                        break;
 
1763
 
 
1764
                                                case '0.92':
 
1765
                                                        $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
 
1766
                                                        break;
 
1767
 
 
1768
                                                case '0.93':
 
1769
                                                        $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
 
1770
                                                        break;
 
1771
 
 
1772
                                                case '0.94':
 
1773
                                                        $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
 
1774
                                                        break;
 
1775
 
 
1776
                                                case '2.0':
 
1777
                                                        $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
 
1778
                                                        break;
 
1779
                                        }
 
1780
                                }
 
1781
                        }
 
1782
                        else
 
1783
                        {
 
1784
                                $this->data['type'] = SIMPLEPIE_TYPE_NONE;
 
1785
                        }
 
1786
                }
 
1787
                return $this->data['type'];
 
1788
        }
 
1789
 
 
1790
        /**
 
1791
         * Get the URL for the feed
 
1792
         *
 
1793
         * May or may not be different from the URL passed to {@see set_feed_url()},
 
1794
         * depending on whether auto-discovery was used.
 
1795
         *
 
1796
         * @since Preview Release (previously called `get_feed_url()` since SimplePie 0.8.)
 
1797
         * @todo If we have a perm redirect we should return the new URL
 
1798
         * @todo When we make the above change, let's support <itunes:new-feed-url> as well
 
1799
         * @todo Also, |atom:link|@rel=self
 
1800
         * @return string|null
 
1801
         */
 
1802
        public function subscribe_url()
 
1803
        {
 
1804
                if ($this->feed_url !== null)
 
1805
                {
 
1806
                        return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
 
1807
                }
 
1808
                else
 
1809
                {
 
1810
                        return null;
 
1811
                }
 
1812
        }
 
1813
 
 
1814
        /**
 
1815
         * Get data for an feed-level element
 
1816
         *
 
1817
         * This method allows you to get access to ANY element/attribute that is a
 
1818
         * sub-element of the opening feed tag.
 
1819
         *
 
1820
         * The return value is an indexed array of elements matching the given
 
1821
         * namespace and tag name. Each element has `attribs`, `data` and `child`
 
1822
         * subkeys. For `attribs` and `child`, these contain namespace subkeys.
 
1823
         * `attribs` then has one level of associative name => value data (where
 
1824
         * `value` is a string) after the namespace. `child` has tag-indexed keys
 
1825
         * after the namespace, each member of which is an indexed array matching
 
1826
         * this same format.
 
1827
         *
 
1828
         * For example:
 
1829
         * <pre>
 
1830
         * // This is probably a bad example because we already support
 
1831
         * // <media:content> natively, but it shows you how to parse through
 
1832
         * // the nodes.
 
1833
         * $group = $item->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group');
 
1834
         * $content = $group[0]['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'];
 
1835
         * $file = $content[0]['attribs']['']['url'];
 
1836
         * echo $file;
 
1837
         * </pre>
 
1838
         *
 
1839
         * @since 1.0
 
1840
         * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
 
1841
         * @param string $namespace The URL of the XML namespace of the elements you're trying to access
 
1842
         * @param string $tag Tag name
 
1843
         * @return array
 
1844
         */
 
1845
        public function get_feed_tags($namespace, $tag)
 
1846
        {
 
1847
                $type = $this->get_type();
 
1848
                if ($type & SIMPLEPIE_TYPE_ATOM_10)
 
1849
                {
 
1850
                        if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
 
1851
                        {
 
1852
                                return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
 
1853
                        }
 
1854
                }
 
1855
                if ($type & SIMPLEPIE_TYPE_ATOM_03)
 
1856
                {
 
1857
                        if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
 
1858
                        {
 
1859
                                return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
 
1860
                        }
 
1861
                }
 
1862
                if ($type & SIMPLEPIE_TYPE_RSS_RDF)
 
1863
                {
 
1864
                        if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
 
1865
                        {
 
1866
                                return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
 
1867
                        }
 
1868
                }
 
1869
                if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
 
1870
                {
 
1871
                        if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
 
1872
                        {
 
1873
                                return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
 
1874
                        }
 
1875
                }
 
1876
                return null;
 
1877
        }
 
1878
 
 
1879
        /**
 
1880
         * Get data for an channel-level element
 
1881
         *
 
1882
         * This method allows you to get access to ANY element/attribute in the
 
1883
         * channel/header section of the feed.
 
1884
         *
 
1885
         * See {@see SimplePie::get_feed_tags()} for a description of the return value
 
1886
         *
 
1887
         * @since 1.0
 
1888
         * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
 
1889
         * @param string $namespace The URL of the XML namespace of the elements you're trying to access
 
1890
         * @param string $tag Tag name
 
1891
         * @return array
 
1892
         */
 
1893
        public function get_channel_tags($namespace, $tag)
 
1894
        {
 
1895
                $type = $this->get_type();
 
1896
                if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
 
1897
                {
 
1898
                        if ($return = $this->get_feed_tags($namespace, $tag))
 
1899
                        {
 
1900
                                return $return;
 
1901
                        }
 
1902
                }
 
1903
                if ($type & SIMPLEPIE_TYPE_RSS_10)
 
1904
                {
 
1905
                        if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
 
1906
                        {
 
1907
                                if (isset($channel[0]['child'][$namespace][$tag]))
 
1908
                                {
 
1909
                                        return $channel[0]['child'][$namespace][$tag];
 
1910
                                }
 
1911
                        }
 
1912
                }
 
1913
                if ($type & SIMPLEPIE_TYPE_RSS_090)
 
1914
                {
 
1915
                        if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
 
1916
                        {
 
1917
                                if (isset($channel[0]['child'][$namespace][$tag]))
 
1918
                                {
 
1919
                                        return $channel[0]['child'][$namespace][$tag];
 
1920
                                }
 
1921
                        }
 
1922
                }
 
1923
                if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
 
1924
                {
 
1925
                        if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
 
1926
                        {
 
1927
                                if (isset($channel[0]['child'][$namespace][$tag]))
 
1928
                                {
 
1929
                                        return $channel[0]['child'][$namespace][$tag];
 
1930
                                }
 
1931
                        }
 
1932
                }
 
1933
                return null;
 
1934
        }
 
1935
 
 
1936
        /**
 
1937
         * Get data for an channel-level element
 
1938
         *
 
1939
         * This method allows you to get access to ANY element/attribute in the
 
1940
         * image/logo section of the feed.
 
1941
         *
 
1942
         * See {@see SimplePie::get_feed_tags()} for a description of the return value
 
1943
         *
 
1944
         * @since 1.0
 
1945
         * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
 
1946
         * @param string $namespace The URL of the XML namespace of the elements you're trying to access
 
1947
         * @param string $tag Tag name
 
1948
         * @return array
 
1949
         */
 
1950
        public function get_image_tags($namespace, $tag)
 
1951
        {
 
1952
                $type = $this->get_type();
 
1953
                if ($type & SIMPLEPIE_TYPE_RSS_10)
 
1954
                {
 
1955
                        if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
 
1956
                        {
 
1957
                                if (isset($image[0]['child'][$namespace][$tag]))
 
1958
                                {
 
1959
                                        return $image[0]['child'][$namespace][$tag];
 
1960
                                }
 
1961
                        }
 
1962
                }
 
1963
                if ($type & SIMPLEPIE_TYPE_RSS_090)
 
1964
                {
 
1965
                        if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
 
1966
                        {
 
1967
                                if (isset($image[0]['child'][$namespace][$tag]))
 
1968
                                {
 
1969
                                        return $image[0]['child'][$namespace][$tag];
 
1970
                                }
 
1971
                        }
 
1972
                }
 
1973
                if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
 
1974
                {
 
1975
                        if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
 
1976
                        {
 
1977
                                if (isset($image[0]['child'][$namespace][$tag]))
 
1978
                                {
 
1979
                                        return $image[0]['child'][$namespace][$tag];
 
1980
                                }
 
1981
                        }
 
1982
                }
 
1983
                return null;
 
1984
        }
 
1985
 
 
1986
        /**
 
1987
         * Get the base URL value from the feed
 
1988
         *
 
1989
         * Uses `<xml:base>` if available, otherwise uses the first link in the
 
1990
         * feed, or failing that, the URL of the feed itself.
 
1991
         *
 
1992
         * @see get_link
 
1993
         * @see subscribe_url
 
1994
         *
 
1995
         * @param array $element
 
1996
         * @return string
 
1997
         */
 
1998
        public function get_base($element = array())
 
1999
        {
 
2000
                if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
 
2001
                {
 
2002
                        return $element['xml_base'];
 
2003
                }
 
2004
                elseif ($this->get_link() !== null)
 
2005
                {
 
2006
                        return $this->get_link();
 
2007
                }
 
2008
                else
 
2009
                {
 
2010
                        return $this->subscribe_url();
 
2011
                }
 
2012
        }
 
2013
 
 
2014
        /**
 
2015
         * Sanitize feed data
 
2016
         *
 
2017
         * @access private
 
2018
         * @see SimplePie_Sanitize::sanitize()
 
2019
         * @param string $data Data to sanitize
 
2020
         * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants
 
2021
         * @param string $base Base URL to resolve URLs against
 
2022
         * @return string Sanitized data
 
2023
         */
 
2024
        public function sanitize($data, $type, $base = '')
 
2025
        {
 
2026
                return $this->sanitize->sanitize($data, $type, $base);
 
2027
        }
 
2028
 
 
2029
        /**
 
2030
         * Get the title of the feed
 
2031
         *
 
2032
         * Uses `<atom:title>`, `<title>` or `<dc:title>`
 
2033
         *
 
2034
         * @since 1.0 (previously called `get_feed_title` since 0.8)
 
2035
         * @return string|null
 
2036
         */
 
2037
        public function get_title()
 
2038
        {
 
2039
                if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
 
2040
                {
 
2041
                        return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
 
2042
                }
 
2043
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
 
2044
                {
 
2045
                        return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
 
2046
                }
 
2047
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
 
2048
                {
 
2049
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
 
2050
                }
 
2051
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
 
2052
                {
 
2053
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
 
2054
                }
 
2055
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
 
2056
                {
 
2057
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
 
2058
                }
 
2059
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
 
2060
                {
 
2061
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2062
                }
 
2063
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
 
2064
                {
 
2065
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2066
                }
 
2067
                else
 
2068
                {
 
2069
                        return null;
 
2070
                }
 
2071
        }
 
2072
 
 
2073
        /**
 
2074
         * Get a category for the feed
 
2075
         *
 
2076
         * @since Unknown
 
2077
         * @param int $key The category that you want to return.  Remember that arrays begin with 0, not 1
 
2078
         * @return SimplePie_Category|null
 
2079
         */
 
2080
        public function get_category($key = 0)
 
2081
        {
 
2082
                $categories = $this->get_categories();
 
2083
                if (isset($categories[$key]))
 
2084
                {
 
2085
                        return $categories[$key];
 
2086
                }
 
2087
                else
 
2088
                {
 
2089
                        return null;
 
2090
                }
 
2091
        }
 
2092
 
 
2093
        /**
 
2094
         * Get all categories for the feed
 
2095
         *
 
2096
         * Uses `<atom:category>`, `<category>` or `<dc:subject>`
 
2097
         *
 
2098
         * @since Unknown
 
2099
         * @return array|null List of {@see SimplePie_Category} objects
 
2100
         */
 
2101
        public function get_categories()
 
2102
        {
 
2103
                $categories = array();
 
2104
 
 
2105
                foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
 
2106
                {
 
2107
                        $term = null;
 
2108
                        $scheme = null;
 
2109
                        $label = null;
 
2110
                        if (isset($category['attribs']['']['term']))
 
2111
                        {
 
2112
                                $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2113
                        }
 
2114
                        if (isset($category['attribs']['']['scheme']))
 
2115
                        {
 
2116
                                $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2117
                        }
 
2118
                        if (isset($category['attribs']['']['label']))
 
2119
                        {
 
2120
                                $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2121
                        }
 
2122
                        $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
 
2123
                }
 
2124
                foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
 
2125
                {
 
2126
                        // This is really the label, but keep this as the term also for BC.
 
2127
                        // Label will also work on retrieving because that falls back to term.
 
2128
                        $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2129
                        if (isset($category['attribs']['']['domain']))
 
2130
                        {
 
2131
                                $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2132
                        }
 
2133
                        else
 
2134
                        {
 
2135
                                $scheme = null;
 
2136
                        }
 
2137
                        $categories[] = $this->registry->create('Category', array($term, $scheme, null));
 
2138
                }
 
2139
                foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
 
2140
                {
 
2141
                        $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
 
2142
                }
 
2143
                foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
 
2144
                {
 
2145
                        $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
 
2146
                }
 
2147
 
 
2148
                if (!empty($categories))
 
2149
                {
 
2150
                        return array_unique($categories);
 
2151
                }
 
2152
                else
 
2153
                {
 
2154
                        return null;
 
2155
                }
 
2156
        }
 
2157
 
 
2158
        /**
 
2159
         * Get an author for the feed
 
2160
         *
 
2161
         * @since 1.1
 
2162
         * @param int $key The author that you want to return.  Remember that arrays begin with 0, not 1
 
2163
         * @return SimplePie_Author|null
 
2164
         */
 
2165
        public function get_author($key = 0)
 
2166
        {
 
2167
                $authors = $this->get_authors();
 
2168
                if (isset($authors[$key]))
 
2169
                {
 
2170
                        return $authors[$key];
 
2171
                }
 
2172
                else
 
2173
                {
 
2174
                        return null;
 
2175
                }
 
2176
        }
 
2177
 
 
2178
        /**
 
2179
         * Get all authors for the feed
 
2180
         *
 
2181
         * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`
 
2182
         *
 
2183
         * @since 1.1
 
2184
         * @return array|null List of {@see SimplePie_Author} objects
 
2185
         */
 
2186
        public function get_authors()
 
2187
        {
 
2188
                $authors = array();
 
2189
                foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
 
2190
                {
 
2191
                        $name = null;
 
2192
                        $uri = null;
 
2193
                        $email = null;
 
2194
                        if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
 
2195
                        {
 
2196
                                $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2197
                        }
 
2198
                        if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
 
2199
                        {
 
2200
                                $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]));
 
2201
                        }
 
2202
                        if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
 
2203
                        {
 
2204
                                $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2205
                        }
 
2206
                        if ($name !== null || $email !== null || $uri !== null)
 
2207
                        {
 
2208
                                $authors[] = $this->registry->create('Author', array($name, $uri, $email));
 
2209
                        }
 
2210
                }
 
2211
                if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
 
2212
                {
 
2213
                        $name = null;
 
2214
                        $url = null;
 
2215
                        $email = null;
 
2216
                        if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
 
2217
                        {
 
2218
                                $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2219
                        }
 
2220
                        if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
 
2221
                        {
 
2222
                                $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]));
 
2223
                        }
 
2224
                        if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
 
2225
                        {
 
2226
                                $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2227
                        }
 
2228
                        if ($name !== null || $email !== null || $url !== null)
 
2229
                        {
 
2230
                                $authors[] = $this->registry->create('Author', array($name, $url, $email));
 
2231
                        }
 
2232
                }
 
2233
                foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
 
2234
                {
 
2235
                        $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
 
2236
                }
 
2237
                foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
 
2238
                {
 
2239
                        $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
 
2240
                }
 
2241
                foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
 
2242
                {
 
2243
                        $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
 
2244
                }
 
2245
 
 
2246
                if (!empty($authors))
 
2247
                {
 
2248
                        return array_unique($authors);
 
2249
                }
 
2250
                else
 
2251
                {
 
2252
                        return null;
 
2253
                }
 
2254
        }
 
2255
 
 
2256
        /**
 
2257
         * Get a contributor for the feed
 
2258
         *
 
2259
         * @since 1.1
 
2260
         * @param int $key The contrbutor that you want to return.  Remember that arrays begin with 0, not 1
 
2261
         * @return SimplePie_Author|null
 
2262
         */
 
2263
        public function get_contributor($key = 0)
 
2264
        {
 
2265
                $contributors = $this->get_contributors();
 
2266
                if (isset($contributors[$key]))
 
2267
                {
 
2268
                        return $contributors[$key];
 
2269
                }
 
2270
                else
 
2271
                {
 
2272
                        return null;
 
2273
                }
 
2274
        }
 
2275
 
 
2276
        /**
 
2277
         * Get all contributors for the feed
 
2278
         *
 
2279
         * Uses `<atom:contributor>`
 
2280
         *
 
2281
         * @since 1.1
 
2282
         * @return array|null List of {@see SimplePie_Author} objects
 
2283
         */
 
2284
        public function get_contributors()
 
2285
        {
 
2286
                $contributors = array();
 
2287
                foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
 
2288
                {
 
2289
                        $name = null;
 
2290
                        $uri = null;
 
2291
                        $email = null;
 
2292
                        if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
 
2293
                        {
 
2294
                                $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2295
                        }
 
2296
                        if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
 
2297
                        {
 
2298
                                $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]));
 
2299
                        }
 
2300
                        if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
 
2301
                        {
 
2302
                                $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2303
                        }
 
2304
                        if ($name !== null || $email !== null || $uri !== null)
 
2305
                        {
 
2306
                                $contributors[] = $this->registry->create('Author', array($name, $uri, $email));
 
2307
                        }
 
2308
                }
 
2309
                foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
 
2310
                {
 
2311
                        $name = null;
 
2312
                        $url = null;
 
2313
                        $email = null;
 
2314
                        if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
 
2315
                        {
 
2316
                                $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2317
                        }
 
2318
                        if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
 
2319
                        {
 
2320
                                $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]));
 
2321
                        }
 
2322
                        if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
 
2323
                        {
 
2324
                                $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2325
                        }
 
2326
                        if ($name !== null || $email !== null || $url !== null)
 
2327
                        {
 
2328
                                $contributors[] = $this->registry->create('Author', array($name, $url, $email));
 
2329
                        }
 
2330
                }
 
2331
 
 
2332
                if (!empty($contributors))
 
2333
                {
 
2334
                        return array_unique($contributors);
 
2335
                }
 
2336
                else
 
2337
                {
 
2338
                        return null;
 
2339
                }
 
2340
        }
 
2341
 
 
2342
        /**
 
2343
         * Get a single link for the feed
 
2344
         *
 
2345
         * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
 
2346
         * @param int $key The link that you want to return.  Remember that arrays begin with 0, not 1
 
2347
         * @param string $rel The relationship of the link to return
 
2348
         * @return string|null Link URL
 
2349
         */
 
2350
        public function get_link($key = 0, $rel = 'alternate')
 
2351
        {
 
2352
                $links = $this->get_links($rel);
 
2353
                if (isset($links[$key]))
 
2354
                {
 
2355
                        return $links[$key];
 
2356
                }
 
2357
                else
 
2358
                {
 
2359
                        return null;
 
2360
                }
 
2361
        }
 
2362
 
 
2363
        /**
 
2364
         * Get the permalink for the item
 
2365
         *
 
2366
         * Returns the first link available with a relationship of "alternate".
 
2367
         * Identical to {@see get_link()} with key 0
 
2368
         *
 
2369
         * @see get_link
 
2370
         * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
 
2371
         * @internal Added for parity between the parent-level and the item/entry-level.
 
2372
         * @return string|null Link URL
 
2373
         */
 
2374
        public function get_permalink()
 
2375
        {
 
2376
                return $this->get_link(0);
 
2377
        }
 
2378
 
 
2379
        /**
 
2380
         * Get all links for the feed
 
2381
         *
 
2382
         * Uses `<atom:link>` or `<link>`
 
2383
         *
 
2384
         * @since Beta 2
 
2385
         * @param string $rel The relationship of links to return
 
2386
         * @return array|null Links found for the feed (strings)
 
2387
         */
 
2388
        public function get_links($rel = 'alternate')
 
2389
        {
 
2390
                if (!isset($this->data['links']))
 
2391
                {
 
2392
                        $this->data['links'] = array();
 
2393
                        if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
 
2394
                        {
 
2395
                                foreach ($links as $link)
 
2396
                                {
 
2397
                                        if (isset($link['attribs']['']['href']))
 
2398
                                        {
 
2399
                                                $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
 
2400
                                                $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
 
2401
                                        }
 
2402
                                }
 
2403
                        }
 
2404
                        if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
 
2405
                        {
 
2406
                                foreach ($links as $link)
 
2407
                                {
 
2408
                                        if (isset($link['attribs']['']['href']))
 
2409
                                        {
 
2410
                                                $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
 
2411
                                                $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
 
2412
 
 
2413
                                        }
 
2414
                                }
 
2415
                        }
 
2416
                        if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
 
2417
                        {
 
2418
                                $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
 
2419
                        }
 
2420
                        if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
 
2421
                        {
 
2422
                                $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
 
2423
                        }
 
2424
                        if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
 
2425
                        {
 
2426
                                $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
 
2427
                        }
 
2428
 
 
2429
                        $keys = array_keys($this->data['links']);
 
2430
                        foreach ($keys as $key)
 
2431
                        {
 
2432
                                if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))
 
2433
                                {
 
2434
                                        if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
 
2435
                                        {
 
2436
                                                $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
 
2437
                                                $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
 
2438
                                        }
 
2439
                                        else
 
2440
                                        {
 
2441
                                                $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
 
2442
                                        }
 
2443
                                }
 
2444
                                elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
 
2445
                                {
 
2446
                                        $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
 
2447
                                }
 
2448
                                $this->data['links'][$key] = array_unique($this->data['links'][$key]);
 
2449
                        }
 
2450
                }
 
2451
 
 
2452
                if (isset($this->data['links'][$rel]))
 
2453
                {
 
2454
                        return $this->data['links'][$rel];
 
2455
                }
 
2456
                else
 
2457
                {
 
2458
                        return null;
 
2459
                }
 
2460
        }
 
2461
 
 
2462
        public function get_all_discovered_feeds()
 
2463
        {
 
2464
                return $this->all_discovered_feeds;
 
2465
        }
 
2466
 
 
2467
        /**
 
2468
         * Get the content for the item
 
2469
         *
 
2470
         * Uses `<atom:subtitle>`, `<atom:tagline>`, `<description>`,
 
2471
         * `<dc:description>`, `<itunes:summary>` or `<itunes:subtitle>`
 
2472
         *
 
2473
         * @since 1.0 (previously called `get_feed_description()` since 0.8)
 
2474
         * @return string|null
 
2475
         */
 
2476
        public function get_description()
 
2477
        {
 
2478
                if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
 
2479
                {
 
2480
                        return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
 
2481
                }
 
2482
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
 
2483
                {
 
2484
                        return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
 
2485
                }
 
2486
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
 
2487
                {
 
2488
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
 
2489
                }
 
2490
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
 
2491
                {
 
2492
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
 
2493
                }
 
2494
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
 
2495
                {
 
2496
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
 
2497
                }
 
2498
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
 
2499
                {
 
2500
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2501
                }
 
2502
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
 
2503
                {
 
2504
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2505
                }
 
2506
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
 
2507
                {
 
2508
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
 
2509
                }
 
2510
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
 
2511
                {
 
2512
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
 
2513
                }
 
2514
                else
 
2515
                {
 
2516
                        return null;
 
2517
                }
 
2518
        }
 
2519
 
 
2520
        /**
 
2521
         * Get the copyright info for the feed
 
2522
         *
 
2523
         * Uses `<atom:rights>`, `<atom:copyright>` or `<dc:rights>`
 
2524
         *
 
2525
         * @since 1.0 (previously called `get_feed_copyright()` since 0.8)
 
2526
         * @return string|null
 
2527
         */
 
2528
        public function get_copyright()
 
2529
        {
 
2530
                if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
 
2531
                {
 
2532
                        return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
 
2533
                }
 
2534
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
 
2535
                {
 
2536
                        return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
 
2537
                }
 
2538
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
 
2539
                {
 
2540
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2541
                }
 
2542
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
 
2543
                {
 
2544
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2545
                }
 
2546
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
 
2547
                {
 
2548
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2549
                }
 
2550
                else
 
2551
                {
 
2552
                        return null;
 
2553
                }
 
2554
        }
 
2555
 
 
2556
        /**
 
2557
         * Get the language for the feed
 
2558
         *
 
2559
         * Uses `<language>`, `<dc:language>`, or @xml_lang
 
2560
         *
 
2561
         * @since 1.0 (previously called `get_feed_language()` since 0.8)
 
2562
         * @return string|null
 
2563
         */
 
2564
        public function get_language()
 
2565
        {
 
2566
                if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
 
2567
                {
 
2568
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2569
                }
 
2570
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
 
2571
                {
 
2572
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2573
                }
 
2574
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
 
2575
                {
 
2576
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2577
                }
 
2578
                elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
 
2579
                {
 
2580
                        return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2581
                }
 
2582
                elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
 
2583
                {
 
2584
                        return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2585
                }
 
2586
                elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
 
2587
                {
 
2588
                        return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2589
                }
 
2590
                elseif (isset($this->data['headers']['content-language']))
 
2591
                {
 
2592
                        return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2593
                }
 
2594
                else
 
2595
                {
 
2596
                        return null;
 
2597
                }
 
2598
        }
 
2599
 
 
2600
        /**
 
2601
         * Get the latitude coordinates for the item
 
2602
         *
 
2603
         * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
 
2604
         *
 
2605
         * Uses `<geo:lat>` or `<georss:point>`
 
2606
         *
 
2607
         * @since 1.0
 
2608
         * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
 
2609
         * @link http://www.georss.org/ GeoRSS
 
2610
         * @return string|null
 
2611
         */
 
2612
        public function get_latitude()
 
2613
        {
 
2614
 
 
2615
                if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
 
2616
                {
 
2617
                        return (float) $return[0]['data'];
 
2618
                }
 
2619
                elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
 
2620
                {
 
2621
                        return (float) $match[1];
 
2622
                }
 
2623
                else
 
2624
                {
 
2625
                        return null;
 
2626
                }
 
2627
        }
 
2628
 
 
2629
        /**
 
2630
         * Get the longitude coordinates for the feed
 
2631
         *
 
2632
         * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
 
2633
         *
 
2634
         * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`
 
2635
         *
 
2636
         * @since 1.0
 
2637
         * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
 
2638
         * @link http://www.georss.org/ GeoRSS
 
2639
         * @return string|null
 
2640
         */
 
2641
        public function get_longitude()
 
2642
        {
 
2643
                if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
 
2644
                {
 
2645
                        return (float) $return[0]['data'];
 
2646
                }
 
2647
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
 
2648
                {
 
2649
                        return (float) $return[0]['data'];
 
2650
                }
 
2651
                elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
 
2652
                {
 
2653
                        return (float) $match[2];
 
2654
                }
 
2655
                else
 
2656
                {
 
2657
                        return null;
 
2658
                }
 
2659
        }
 
2660
 
 
2661
        /**
 
2662
         * Get the feed logo's title
 
2663
         *
 
2664
         * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" title.
 
2665
         *
 
2666
         * Uses `<image><title>` or `<image><dc:title>`
 
2667
         *
 
2668
         * @return string|null
 
2669
         */
 
2670
        public function get_image_title()
 
2671
        {
 
2672
                if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
 
2673
                {
 
2674
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2675
                }
 
2676
                elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
 
2677
                {
 
2678
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2679
                }
 
2680
                elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
 
2681
                {
 
2682
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2683
                }
 
2684
                elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
 
2685
                {
 
2686
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2687
                }
 
2688
                elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
 
2689
                {
 
2690
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
 
2691
                }
 
2692
                else
 
2693
                {
 
2694
                        return null;
 
2695
                }
 
2696
        }
 
2697
 
 
2698
        /**
 
2699
         * Get the feed logo's URL
 
2700
         *
 
2701
         * RSS 0.9.0, 2.0, Atom 1.0, and feeds with iTunes RSS tags are allowed to
 
2702
         * have a "feed logo" URL. This points directly to the image itself.
 
2703
         *
 
2704
         * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
 
2705
         * `<image><title>` or `<image><dc:title>`
 
2706
         *
 
2707
         * @return string|null
 
2708
         */
 
2709
        public function get_image_url()
 
2710
        {
 
2711
                if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
 
2712
                {
 
2713
                        return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
 
2714
                }
 
2715
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
 
2716
                {
 
2717
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
 
2718
                }
 
2719
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
 
2720
                {
 
2721
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
 
2722
                }
 
2723
                elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
 
2724
                {
 
2725
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
 
2726
                }
 
2727
                elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
 
2728
                {
 
2729
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
 
2730
                }
 
2731
                elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
 
2732
                {
 
2733
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
 
2734
                }
 
2735
                else
 
2736
                {
 
2737
                        return null;
 
2738
                }
 
2739
        }
 
2740
 
 
2741
 
 
2742
        /**
 
2743
         * Get the feed logo's link
 
2744
         *
 
2745
         * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" link. This
 
2746
         * points to a human-readable page that the image should link to.
 
2747
         *
 
2748
         * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
 
2749
         * `<image><title>` or `<image><dc:title>`
 
2750
         *
 
2751
         * @return string|null
 
2752
         */
 
2753
        public function get_image_link()
 
2754
        {
 
2755
                if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
 
2756
                {
 
2757
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
 
2758
                }
 
2759
                elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
 
2760
                {
 
2761
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
 
2762
                }
 
2763
                elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
 
2764
                {
 
2765
                        return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
 
2766
                }
 
2767
                else
 
2768
                {
 
2769
                        return null;
 
2770
                }
 
2771
        }
 
2772
 
 
2773
        /**
 
2774
         * Get the feed logo's link
 
2775
         *
 
2776
         * RSS 2.0 feeds are allowed to have a "feed logo" width.
 
2777
         *
 
2778
         * Uses `<image><width>` or defaults to 88.0 if no width is specified and
 
2779
         * the feed is an RSS 2.0 feed.
 
2780
         *
 
2781
         * @return int|float|null
 
2782
         */
 
2783
        public function get_image_width()
 
2784
        {
 
2785
                if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
 
2786
                {
 
2787
                        return round($return[0]['data']);
 
2788
                }
 
2789
                elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
 
2790
                {
 
2791
                        return 88.0;
 
2792
                }
 
2793
                else
 
2794
                {
 
2795
                        return null;
 
2796
                }
 
2797
        }
 
2798
 
 
2799
        /**
 
2800
         * Get the feed logo's height
 
2801
         *
 
2802
         * RSS 2.0 feeds are allowed to have a "feed logo" height.
 
2803
         *
 
2804
         * Uses `<image><height>` or defaults to 31.0 if no height is specified and
 
2805
         * the feed is an RSS 2.0 feed.
 
2806
         *
 
2807
         * @return int|float|null
 
2808
         */
 
2809
        public function get_image_height()
 
2810
        {
 
2811
                if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
 
2812
                {
 
2813
                        return round($return[0]['data']);
 
2814
                }
 
2815
                elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
 
2816
                {
 
2817
                        return 31.0;
 
2818
                }
 
2819
                else
 
2820
                {
 
2821
                        return null;
 
2822
                }
 
2823
        }
 
2824
 
 
2825
        /**
 
2826
         * Get the number of items in the feed
 
2827
         *
 
2828
         * This is well-suited for {@link http://php.net/for for()} loops with
 
2829
         * {@see get_item()}
 
2830
         *
 
2831
         * @param int $max Maximum value to return. 0 for no limit
 
2832
         * @return int Number of items in the feed
 
2833
         */
 
2834
        public function get_item_quantity($max = 0)
 
2835
        {
 
2836
                $max = (int) $max;
 
2837
                $qty = count($this->get_items());
 
2838
                if ($max === 0)
 
2839
                {
 
2840
                        return $qty;
 
2841
                }
 
2842
                else
 
2843
                {
 
2844
                        return ($qty > $max) ? $max : $qty;
 
2845
                }
 
2846
        }
 
2847
 
 
2848
        /**
 
2849
         * Get a single item from the feed
 
2850
         *
 
2851
         * This is better suited for {@link http://php.net/for for()} loops, whereas
 
2852
         * {@see get_items()} is better suited for
 
2853
         * {@link http://php.net/foreach foreach()} loops.
 
2854
         *
 
2855
         * @see get_item_quantity()
 
2856
         * @since Beta 2
 
2857
         * @param int $key The item that you want to return.  Remember that arrays begin with 0, not 1
 
2858
         * @return SimplePie_Item|null
 
2859
         */
 
2860
        public function get_item($key = 0)
 
2861
        {
 
2862
                $items = $this->get_items();
 
2863
                if (isset($items[$key]))
 
2864
                {
 
2865
                        return $items[$key];
 
2866
                }
 
2867
                else
 
2868
                {
 
2869
                        return null;
 
2870
                }
 
2871
        }
 
2872
 
 
2873
        /**
 
2874
         * Get all items from the feed
 
2875
         *
 
2876
         * This is better suited for {@link http://php.net/for for()} loops, whereas
 
2877
         * {@see get_items()} is better suited for
 
2878
         * {@link http://php.net/foreach foreach()} loops.
 
2879
         *
 
2880
         * @see get_item_quantity
 
2881
         * @since Beta 2
 
2882
         * @param int $start Index to start at
 
2883
         * @param int $end Number of items to return. 0 for all items after `$start`
 
2884
         * @return array|null List of {@see SimplePie_Item} objects
 
2885
         */
 
2886
        public function get_items($start = 0, $end = 0)
 
2887
        {
 
2888
                if (!isset($this->data['items']))
 
2889
                {
 
2890
                        if (!empty($this->multifeed_objects))
 
2891
                        {
 
2892
                                $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
 
2893
                        }
 
2894
                        else
 
2895
                        {
 
2896
                                $this->data['items'] = array();
 
2897
                                if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
 
2898
                                {
 
2899
                                        $keys = array_keys($items);
 
2900
                                        foreach ($keys as $key)
 
2901
                                        {
 
2902
                                                $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
 
2903
                                        }
 
2904
                                }
 
2905
                                if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
 
2906
                                {
 
2907
                                        $keys = array_keys($items);
 
2908
                                        foreach ($keys as $key)
 
2909
                                        {
 
2910
                                                $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
 
2911
                                        }
 
2912
                                }
 
2913
                                if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
 
2914
                                {
 
2915
                                        $keys = array_keys($items);
 
2916
                                        foreach ($keys as $key)
 
2917
                                        {
 
2918
                                                $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
 
2919
                                        }
 
2920
                                }
 
2921
                                if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
 
2922
                                {
 
2923
                                        $keys = array_keys($items);
 
2924
                                        foreach ($keys as $key)
 
2925
                                        {
 
2926
                                                $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
 
2927
                                        }
 
2928
                                }
 
2929
                                if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
 
2930
                                {
 
2931
                                        $keys = array_keys($items);
 
2932
                                        foreach ($keys as $key)
 
2933
                                        {
 
2934
                                                $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
 
2935
                                        }
 
2936
                                }
 
2937
                        }
 
2938
                }
 
2939
 
 
2940
                if (!empty($this->data['items']))
 
2941
                {
 
2942
                        // If we want to order it by date, check if all items have a date, and then sort it
 
2943
                        if ($this->order_by_date && empty($this->multifeed_objects))
 
2944
                        {
 
2945
                                if (!isset($this->data['ordered_items']))
 
2946
                                {
 
2947
                                        $do_sort = true;
 
2948
                                        foreach ($this->data['items'] as $item)
 
2949
                                        {
 
2950
                                                if (!$item->get_date('U'))
 
2951
                                                {
 
2952
                                                        $do_sort = false;
 
2953
                                                        break;
 
2954
                                                }
 
2955
                                        }
 
2956
                                        $item = null;
 
2957
                                        $this->data['ordered_items'] = $this->data['items'];
 
2958
                                        if ($do_sort)
 
2959
                                        {
 
2960
                                                usort($this->data['ordered_items'], array(get_class($this), 'sort_items'));
 
2961
                                        }
 
2962
                                }
 
2963
                                $items = $this->data['ordered_items'];
 
2964
                        }
 
2965
                        else
 
2966
                        {
 
2967
                                $items = $this->data['items'];
 
2968
                        }
 
2969
 
 
2970
                        // Slice the data as desired
 
2971
                        if ($end === 0)
 
2972
                        {
 
2973
                                return array_slice($items, $start);
 
2974
                        }
 
2975
                        else
 
2976
                        {
 
2977
                                return array_slice($items, $start, $end);
 
2978
                        }
 
2979
                }
 
2980
                else
 
2981
                {
 
2982
                        return array();
 
2983
                }
 
2984
        }
 
2985
 
 
2986
        /**
 
2987
         * Set the favicon handler
 
2988
         *
 
2989
         * @deprecated Use your own favicon handling instead
 
2990
         */
 
2991
        public function set_favicon_handler($page = false, $qs = 'i')
 
2992
        {
 
2993
                $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
 
2994
                trigger_error('Favicon handling has been removed, please use your own handling', $level);
 
2995
                return false;
 
2996
        }
 
2997
 
 
2998
        /**
 
2999
         * Get the favicon for the current feed
 
3000
         *
 
3001
         * @deprecated Use your own favicon handling instead
 
3002
         */
 
3003
        public function get_favicon()
 
3004
        {
 
3005
                $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
 
3006
                trigger_error('Favicon handling has been removed, please use your own handling', $level);
 
3007
 
 
3008
                if (($url = $this->get_link()) !== null)
 
3009
                {
 
3010
                        return 'http://g.etfv.co/' . urlencode($url);
 
3011
                }
 
3012
 
 
3013
                return false;
 
3014
        }
 
3015
 
 
3016
        /**
 
3017
         * Magic method handler
 
3018
         *
 
3019
         * @param string $method Method name
 
3020
         * @param array $args Arguments to the method
 
3021
         * @return mixed
 
3022
         */
 
3023
        public function __call($method, $args)
 
3024
        {
 
3025
                if (strpos($method, 'subscribe_') === 0)
 
3026
                {
 
3027
                        $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
 
3028
                        trigger_error('subscribe_*() has been deprecated, implement the callback yourself', $level);
 
3029
                        return '';
 
3030
                }
 
3031
                if ($method === 'enable_xml_dump')
 
3032
                {
 
3033
                        $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
 
3034
                        trigger_error('enable_xml_dump() has been deprecated, use get_raw_data() instead', $level);
 
3035
                        return false;
 
3036
                }
 
3037
 
 
3038
                $class = get_class($this);
 
3039
                $trace = debug_backtrace();
 
3040
                $file = $trace[0]['file'];
 
3041
                $line = $trace[0]['line'];
 
3042
                trigger_error("Call to undefined method $class::$method() in $file on line $line", E_USER_ERROR);
 
3043
        }
 
3044
 
 
3045
        /**
 
3046
         * Sorting callback for items
 
3047
         *
 
3048
         * @access private
 
3049
         * @param SimplePie $a
 
3050
         * @param SimplePie $b
 
3051
         * @return boolean
 
3052
         */
 
3053
        public static function sort_items($a, $b)
 
3054
        {
 
3055
                return $a->get_date('U') <= $b->get_date('U');
 
3056
        }
 
3057
 
 
3058
        /**
 
3059
         * Merge items from several feeds into one
 
3060
         *
 
3061
         * If you're merging multiple feeds together, they need to all have dates
 
3062
         * for the items or else SimplePie will refuse to sort them.
 
3063
         *
 
3064
         * @link http://simplepie.org/wiki/tutorial/sort_multiple_feeds_by_time_and_date#if_feeds_require_separate_per-feed_settings
 
3065
         * @param array $urls List of SimplePie feed objects to merge
 
3066
         * @param int $start Starting item
 
3067
         * @param int $end Number of items to return
 
3068
         * @param int $limit Maximum number of items per feed
 
3069
         * @return array
 
3070
         */
 
3071
        public static function merge_items($urls, $start = 0, $end = 0, $limit = 0)
 
3072
        {
 
3073
                if (is_array($urls) && sizeof($urls) > 0)
 
3074
                {
 
3075
                        $items = array();
 
3076
                        foreach ($urls as $arg)
 
3077
                        {
 
3078
                                if ($arg instanceof SimplePie)
 
3079
                                {
 
3080
                                        $items = array_merge($items, $arg->get_items(0, $limit));
 
3081
                                }
 
3082
                                else
 
3083
                                {
 
3084
                                        trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
 
3085
                                }
 
3086
                        }
 
3087
 
 
3088
                        $do_sort = true;
 
3089
                        foreach ($items as $item)
 
3090
                        {
 
3091
                                if (!$item->get_date('U'))
 
3092
                                {
 
3093
                                        $do_sort = false;
 
3094
                                        break;
 
3095
                                }
 
3096
                        }
 
3097
                        $item = null;
 
3098
                        if ($do_sort)
 
3099
                        {
 
3100
                                usort($items, array(get_class($urls[0]), 'sort_items'));
 
3101
                        }
 
3102
 
 
3103
                        if ($end === 0)
 
3104
                        {
 
3105
                                return array_slice($items, $start);
 
3106
                        }
 
3107
                        else
 
3108
                        {
 
3109
                                return array_slice($items, $start, $end);
 
3110
                        }
 
3111
                }
 
3112
                else
 
3113
                {
 
3114
                        trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
 
3115
                        return array();
 
3116
                }
 
3117
        }
 
3118
}
 
3119
endif;
 
 
b'\\ No newline at end of file'