SimplePie::set_timeout()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * SimplePie
4
 *
5
 * A PHP-Based RSS and Atom Feed Framework.
6
 * Takes the hard work out of managing a complete RSS/Atom solution.
7
 *
8
 * Please note: This file is automatically generated by a build script. The
9
 * full original source is always available from http://simplepie.org/
10
 *
11
 * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
12
 * All rights reserved.
13
 *
14
 * Redistribution and use in source and binary forms, with or without modification, are
15
 * permitted provided that the following conditions are met:
16
 *
17
 * 	* Redistributions of source code must retain the above copyright notice, this list of
18
 * 	  conditions and the following disclaimer.
19
 *
20
 * 	* Redistributions in binary form must reproduce the above copyright notice, this list
21
 * 	  of conditions and the following disclaimer in the documentation and/or other materials
22
 * 	  provided with the distribution.
23
 *
24
 * 	* Neither the name of the SimplePie Team nor the names of its contributors may be used
25
 * 	  to endorse or promote products derived from this software without specific prior
26
 * 	  written permission.
27
 *
28
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
29
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
30
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
31
 * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
35
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36
 * POSSIBILITY OF SUCH DAMAGE.
37
 *
38
 * @package SimplePie
39
 * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
40
 * @author Ryan Parman
41
 * @author Geoffrey Sneddon
42
 * @author Ryan McCue
43
 * @link http://simplepie.org/ SimplePie
44
 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
45
 */
46
47
/**
48
 * SimplePie Name
49
 */
50
define('SIMPLEPIE_NAME', 'SimplePie');
51
52
/**
53
 * SimplePie Version
54
 */
55
define('SIMPLEPIE_VERSION', '1.5');
56
57
/**
58
 * SimplePie Build
59
 * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::get_build() only every load of simplepie.inc)
60
 */
61
define('SIMPLEPIE_BUILD', '20170825121938');
62
63
/**
64
 * SimplePie Website URL
65
 */
66
define('SIMPLEPIE_URL', 'http://simplepie.org');
67
68
/**
69
 * SimplePie Useragent
70
 * @see SimplePie::set_useragent()
71
 */
72
define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
73
74
/**
75
 * SimplePie Linkback
76
 */
77
define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
78
79
/**
80
 * No Autodiscovery
81
 * @see SimplePie::set_autodiscovery_level()
82
 */
83
define('SIMPLEPIE_LOCATOR_NONE', 0);
84
85
/**
86
 * Feed Link Element Autodiscovery
87
 * @see SimplePie::set_autodiscovery_level()
88
 */
89
define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
90
91
/**
92
 * Local Feed Extension Autodiscovery
93
 * @see SimplePie::set_autodiscovery_level()
94
 */
95
define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
96
97
/**
98
 * Local Feed Body Autodiscovery
99
 * @see SimplePie::set_autodiscovery_level()
100
 */
101
define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
102
103
/**
104
 * Remote Feed Extension Autodiscovery
105
 * @see SimplePie::set_autodiscovery_level()
106
 */
107
define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
108
109
/**
110
 * Remote Feed Body Autodiscovery
111
 * @see SimplePie::set_autodiscovery_level()
112
 */
113
define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
114
115
/**
116
 * All Feed Autodiscovery
117
 * @see SimplePie::set_autodiscovery_level()
118
 */
119
define('SIMPLEPIE_LOCATOR_ALL', 31);
120
121
/**
122
 * No known feed type
123
 */
124
define('SIMPLEPIE_TYPE_NONE', 0);
125
126
/**
127
 * RSS 0.90
128
 */
129
define('SIMPLEPIE_TYPE_RSS_090', 1);
130
131
/**
132
 * RSS 0.91 (Netscape)
133
 */
134
define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
135
136
/**
137
 * RSS 0.91 (Userland)
138
 */
139
define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
140
141
/**
142
 * RSS 0.91 (both Netscape and Userland)
143
 */
144
define('SIMPLEPIE_TYPE_RSS_091', 6);
145
146
/**
147
 * RSS 0.92
148
 */
149
define('SIMPLEPIE_TYPE_RSS_092', 8);
150
151
/**
152
 * RSS 0.93
153
 */
154
define('SIMPLEPIE_TYPE_RSS_093', 16);
155
156
/**
157
 * RSS 0.94
158
 */
159
define('SIMPLEPIE_TYPE_RSS_094', 32);
160
161
/**
162
 * RSS 1.0
163
 */
164
define('SIMPLEPIE_TYPE_RSS_10', 64);
165
166
/**
167
 * RSS 2.0
168
 */
169
define('SIMPLEPIE_TYPE_RSS_20', 128);
170
171
/**
172
 * RDF-based RSS
173
 */
174
define('SIMPLEPIE_TYPE_RSS_RDF', 65);
175
176
/**
177
 * Non-RDF-based RSS (truly intended as syndication format)
178
 */
179
define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
180
181
/**
182
 * All RSS
183
 */
184
define('SIMPLEPIE_TYPE_RSS_ALL', 255);
185
186
/**
187
 * Atom 0.3
188
 */
189
define('SIMPLEPIE_TYPE_ATOM_03', 256);
190
191
/**
192
 * Atom 1.0
193
 */
194
define('SIMPLEPIE_TYPE_ATOM_10', 512);
195
196
/**
197
 * All Atom
198
 */
199
define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
200
201
/**
202
 * All feed types
203
 */
204
define('SIMPLEPIE_TYPE_ALL', 1023);
205
206
/**
207
 * No construct
208
 */
209
define('SIMPLEPIE_CONSTRUCT_NONE', 0);
210
211
/**
212
 * Text construct
213
 */
214
define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
215
216
/**
217
 * HTML construct
218
 */
219
define('SIMPLEPIE_CONSTRUCT_HTML', 2);
220
221
/**
222
 * XHTML construct
223
 */
224
define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
225
226
/**
227
 * base64-encoded construct
228
 */
229
define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
230
231
/**
232
 * IRI construct
233
 */
234
define('SIMPLEPIE_CONSTRUCT_IRI', 16);
235
236
/**
237
 * A construct that might be HTML
238
 */
239
define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
240
241
/**
242
 * All constructs
243
 */
244
define('SIMPLEPIE_CONSTRUCT_ALL', 63);
245
246
/**
247
 * Don't change case
248
 */
249
define('SIMPLEPIE_SAME_CASE', 1);
250
251
/**
252
 * Change to lowercase
253
 */
254
define('SIMPLEPIE_LOWERCASE', 2);
255
256
/**
257
 * Change to uppercase
258
 */
259
define('SIMPLEPIE_UPPERCASE', 4);
260
261
/**
262
 * PCRE for HTML attributes
263
 */
264
define('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*');
265
266
/**
267
 * PCRE for XML attributes
268
 */
269
define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
270
271
/**
272
 * XML Namespace
273
 */
274
define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
275
276
/**
277
 * Atom 1.0 Namespace
278
 */
279
define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
280
281
/**
282
 * Atom 0.3 Namespace
283
 */
284
define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
285
286
/**
287
 * RDF Namespace
288
 */
289
define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
290
291
/**
292
 * RSS 0.90 Namespace
293
 */
294
define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
295
296
/**
297
 * RSS 1.0 Namespace
298
 */
299
define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
300
301
/**
302
 * RSS 1.0 Content Module Namespace
303
 */
304
define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
305
306
/**
307
 * RSS 2.0 Namespace
308
 * (Stupid, I know, but I'm certain it will confuse people less with support.)
309
 */
310
define('SIMPLEPIE_NAMESPACE_RSS_20', '');
311
312
/**
313
 * DC 1.0 Namespace
314
 */
315
define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
316
317
/**
318
 * DC 1.1 Namespace
319
 */
320
define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
321
322
/**
323
 * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
324
 */
325
define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
326
327
/**
328
 * GeoRSS Namespace
329
 */
330
define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
331
332
/**
333
 * Media RSS Namespace
334
 */
335
define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
336
337
/**
338
 * Wrong Media RSS Namespace. Caused by a long-standing typo in the spec.
339
 */
340
define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
341
342
/**
343
 * Wrong Media RSS Namespace #2. New namespace introduced in Media RSS 1.5.
344
 */
345
define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2', 'http://video.search.yahoo.com/mrss');
346
347
/**
348
 * Wrong Media RSS Namespace #3. A possible typo of the Media RSS 1.5 namespace.
349
 */
350
define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3', 'http://video.search.yahoo.com/mrss/');
351
352
/**
353
 * Wrong Media RSS Namespace #4. New spec location after the RSS Advisory Board takes it over, but not a valid namespace.
354
 */
355
define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4', 'http://www.rssboard.org/media-rss');
356
357
/**
358
 * Wrong Media RSS Namespace #5. A possible typo of the RSS Advisory Board URL.
359
 */
360
define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5', 'http://www.rssboard.org/media-rss/');
361
362
/**
363
 * iTunes RSS Namespace
364
 */
365
define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
366
367
/**
368
 * XHTML Namespace
369
 */
370
define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
371
372
/**
373
 * IANA Link Relations Registry
374
 */
375
define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
376
377
/**
378
 * No file source
379
 */
380
define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
381
382
/**
383
 * Remote file source
384
 */
385
define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
386
387
/**
388
 * Local file source
389
 */
390
define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
391
392
/**
393
 * fsockopen() file source
394
 */
395
define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
396
397
/**
398
 * cURL file source
399
 */
400
define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
401
402
/**
403
 * file_get_contents() file source
404
 */
405
define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
406
407
/**
408
 * SimplePie
409
 *
410
 * @package SimplePie
411
 * @subpackage API
412
 */
413
class SimplePie
414
{
415
	/**
416
	 * @var array Raw data
417
	 * @access private
418
	 */
419
	public $data = array();
420
421
	/**
422
	 * @var mixed Error string
423
	 * @access private
424
	 */
425
	public $error;
426
427
	/**
428
	 * @var object Instance of SimplePie_Sanitize (or other class)
429
	 * @see SimplePie::set_sanitize_class()
430
	 * @access private
431
	 */
432
	public $sanitize;
433
434
	/**
435
	 * @var string SimplePie Useragent
436
	 * @see SimplePie::set_useragent()
437
	 * @access private
438
	 */
439
	public $useragent = SIMPLEPIE_USERAGENT;
440
441
	/**
442
	 * @var string Feed URL
443
	 * @see SimplePie::set_feed_url()
444
	 * @access private
445
	 */
446
	public $feed_url;
447
448
	/**
449
	 * @var string Original feed URL, or new feed URL iff HTTP 301 Moved Permanently
450
	 * @see SimplePie::subscribe_url()
451
	 * @access private
452
	 */
453
	public $permanent_url = null;
454
455
	/**
456
	 * @var object Instance of SimplePie_File to use as a feed
457
	 * @see SimplePie::set_file()
458
	 * @access private
459
	 */
460
	public $file;
461
462
	/**
463
	 * @var string Raw feed data
464
	 * @see SimplePie::set_raw_data()
465
	 * @access private
466
	 */
467
	public $raw_data;
468
469
	/**
470
	 * @var int Timeout for fetching remote files
471
	 * @see SimplePie::set_timeout()
472
	 * @access private
473
	 */
474
	public $timeout = 10;
475
476
	/**
477
	 * @var array Custom curl options
478
	 * @see SimplePie::set_curl_options()
479
	 * @access private
480
	 */
481
	public $curl_options = array();
482
483
	/**
484
	 * @var bool Forces fsockopen() to be used for remote files instead
485
	 * of cURL, even if a new enough version is installed
486
	 * @see SimplePie::force_fsockopen()
487
	 * @access private
488
	 */
489
	public $force_fsockopen = false;
490
491
	/**
492
	 * @var bool Force the given data/URL to be treated as a feed no matter what
493
	 * it appears like
494
	 * @see SimplePie::force_feed()
495
	 * @access private
496
	 */
497
	public $force_feed = false;
498
499
	/**
500
	 * @var bool Enable/Disable Caching
501
	 * @see SimplePie::enable_cache()
502
	 * @access private
503
	 */
504
	public $cache = true;
505
506
	/**
507
	 * @var bool Force SimplePie to fallback to expired cache, if enabled,
508
	 * when feed is unavailable.
509
	 * @see SimplePie::force_cache_fallback()
510
	 * @access private
511
	 */
512
	public $force_cache_fallback = false;
513
514
	/**
515
	 * @var int Cache duration (in seconds)
516
	 * @see SimplePie::set_cache_duration()
517
	 * @access private
518
	 */
519
	public $cache_duration = 3600;
520
521
	/**
522
	 * @var int Auto-discovery cache duration (in seconds)
523
	 * @see SimplePie::set_autodiscovery_cache_duration()
524
	 * @access private
525
	 */
526
	public $autodiscovery_cache_duration = 604800; // 7 Days.
527
528
	/**
529
	 * @var string Cache location (relative to executing script)
530
	 * @see SimplePie::set_cache_location()
531
	 * @access private
532
	 */
533
	public $cache_location = './cache';
534
535
	/**
536
	 * @var string Function that creates the cache filename
537
	 * @see SimplePie::set_cache_name_function()
538
	 * @access private
539
	 */
540
	public $cache_name_function = 'md5';
541
542
	/**
543
	 * @var bool Reorder feed by date descending
544
	 * @see SimplePie::enable_order_by_date()
545
	 * @access private
546
	 */
547
	public $order_by_date = true;
548
549
	/**
550
	 * @var mixed Force input encoding to be set to the follow value
551
	 * (false, or anything type-cast to false, disables this feature)
552
	 * @see SimplePie::set_input_encoding()
553
	 * @access private
554
	 */
555
	public $input_encoding = false;
556
557
	/**
558
	 * @var int Feed Autodiscovery Level
559
	 * @see SimplePie::set_autodiscovery_level()
560
	 * @access private
561
	 */
562
	public $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
563
564
	/**
565
	 * Class registry object
566
	 *
567
	 * @var SimplePie_Registry
568
	 */
569
	public $registry;
570
571
	/**
572
	 * @var int Maximum number of feeds to check with autodiscovery
573
	 * @see SimplePie::set_max_checked_feeds()
574
	 * @access private
575
	 */
576
	public $max_checked_feeds = 10;
577
578
	/**
579
	 * @var array All the feeds found during the autodiscovery process
580
	 * @see SimplePie::get_all_discovered_feeds()
581
	 * @access private
582
	 */
583
	public $all_discovered_feeds = array();
584
585
	/**
586
	 * @var string Web-accessible path to the handler_image.php file.
587
	 * @see SimplePie::set_image_handler()
588
	 * @access private
589
	 */
590
	public $image_handler = '';
591
592
	/**
593
	 * @var array Stores the URLs when multiple feeds are being initialized.
594
	 * @see SimplePie::set_feed_url()
595
	 * @access private
596
	 */
597
	public $multifeed_url = array();
598
599
	/**
600
	 * @var array Stores SimplePie objects when multiple feeds initialized.
601
	 * @access private
602
	 */
603
	public $multifeed_objects = array();
604
605
	/**
606
	 * @var array Stores the get_object_vars() array for use with multifeeds.
607
	 * @see SimplePie::set_feed_url()
608
	 * @access private
609
	 */
610
	public $config_settings = null;
611
612
	/**
613
	 * @var integer Stores the number of items to return per-feed with multifeeds.
614
	 * @see SimplePie::set_item_limit()
615
	 * @access private
616
	 */
617
	public $item_limit = 0;
618
619
	/**
620
	 * @var bool Stores if last-modified and/or etag headers were sent with the
621
	 * request when checking a feed.
622
	 */
623
	public $check_modified = false;
624
625
	/**
626
	 * @var array Stores the default attributes to be stripped by strip_attributes().
627
	 * @see SimplePie::strip_attributes()
628
	 * @access private
629
	 */
630
	public $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
631
632
	/**
633
	 * @var array Stores the default attributes to add to different tags by add_attributes().
634
	 * @see SimplePie::add_attributes()
635
	 * @access private
636
	 */
637
	public $add_attributes = array('audio' => array('preload' => 'none'), 'iframe' => array('sandbox' => 'allow-scripts allow-same-origin'), 'video' => array('preload' => 'none'));
638
639
	/**
640
	 * @var array Stores the default tags to be stripped by strip_htmltags().
641
	 * @see SimplePie::strip_htmltags()
642
	 * @access private
643
	 */
644
	public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
645
646
	/**
647
	 * @var bool Should we throw exceptions, or use the old-style error property?
648
	 * @access private
649
	 */
650
	public $enable_exceptions = false;
651
	
652
	/**
653
	 * The SimplePie class contains feed level data and options
654
	 *
655
	 * To use SimplePie, create the SimplePie object with no parameters. You can
656
	 * then set configuration options using the provided methods. After setting
657
	 * them, you must initialise the feed using $feed->init(). At that point the
658
	 * object's methods and properties will be available to you.
659
	 *
660
	 * Previously, it was possible to pass in the feed URL along with cache
661
	 * options directly into the constructor. This has been removed as of 1.3 as
662
	 * it caused a lot of confusion.
663
	 *
664
	 * @since 1.0 Preview Release
665
	 */
666
	public function __construct()
667
	{
668
		if (version_compare(PHP_VERSION, '5.3', '<'))
669
		{
670
			trigger_error('Please upgrade to PHP 5.3 or newer.');
671
			die();
672
		}
673
674
		// Other objects, instances created here so we can set options on them
675
		$this->sanitize = new SimplePie_Sanitize();
676
		$this->registry = new SimplePie_Registry();
677
678
		if (func_num_args() > 0)
679
		{
680
			$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
681
			trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_duration() directly.', $level);
682
683
			$args = func_get_args();
684
			switch (count($args)) {
685
				case 3:
686
					$this->set_cache_duration($args[2]);
687
				case 2:
688
					$this->set_cache_location($args[1]);
689
				case 1:
690
					$this->set_feed_url($args[0]);
691
					$this->init();
692
			}
693
		}
694
	}
695
696
	/**
697
	 * Used for converting object to a string
698
	 */
699
	public function __toString()
700
	{
701
		return md5(serialize($this->data));
702
	}
703
704
	/**
705
	 * Remove items that link back to this before destroying this object
706
	 */
707
	public function __destruct()
708
	{
709
		if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
710
		{
711
			if (!empty($this->data['items']))
712
			{
713
				foreach ($this->data['items'] as $item)
714
				{
715
					$item->__destruct();
716
				}
717
				unset($item, $this->data['items']);
718
			}
719
			if (!empty($this->data['ordered_items']))
720
			{
721
				foreach ($this->data['ordered_items'] as $item)
722
				{
723
					$item->__destruct();
724
				}
725
				unset($item, $this->data['ordered_items']);
726
			}
727
		}
728
	}
729
730
	/**
731
	 * Force the given data/URL to be treated as a feed
732
	 *
733
	 * This tells SimplePie to ignore the content-type provided by the server.
734
	 * Be careful when using this option, as it will also disable autodiscovery.
735
	 *
736
	 * @since 1.1
737
	 * @param bool $enable Force the given data/URL to be treated as a feed
738
	 */
739
	public function force_feed($enable = false)
740
	{
741
		$this->force_feed = (bool) $enable;
742
	}
743
744
	/**
745
	 * Set the URL of the feed you want to parse
746
	 *
747
	 * This allows you to enter the URL of the feed you want to parse, or the
748
	 * website you want to try to use auto-discovery on. This takes priority
749
	 * over any set raw data.
750
	 *
751
	 * You can set multiple feeds to mash together by passing an array instead
752
	 * of a string for the $url. Remember that with each additional feed comes
753
	 * additional processing and resources.
754
	 *
755
	 * @since 1.0 Preview Release
756
	 * @see set_raw_data()
757
	 * @param string|array $url This is the URL (or array of URLs) that you want to parse.
758
	 */
759
	public function set_feed_url($url)
760
	{
761
		$this->multifeed_url = array();
762
		if (is_array($url))
763
		{
764
			foreach ($url as $value)
765
			{
766
				$this->multifeed_url[] = $this->registry->call('Misc', 'fix_protocol', array($value, 1));
767
			}
768
		}
769
		else
770
		{
771
			$this->feed_url = $this->registry->call('Misc', 'fix_protocol', array($url, 1));
772
			$this->permanent_url = $this->feed_url;
773
		}
774
	}
775
776
	/**
777
	 * Set an instance of {@see SimplePie_File} to use as a feed
778
	 *
779
	 * @param SimplePie_File &$file
780
	 * @return bool True on success, false on failure
781
	 */
782
	public function set_file(&$file)
783
	{
784
		if ($file instanceof SimplePie_File)
785
		{
786
			$this->feed_url = $file->url;
787
			$this->permanent_url = $this->feed_url;
788
			$this->file =& $file;
789
			return true;
790
		}
791
		return false;
792
	}
793
794
	/**
795
	 * Set the raw XML data to parse
796
	 *
797
	 * Allows you to use a string of RSS/Atom data instead of a remote feed.
798
	 *
799
	 * If you have a feed available as a string in PHP, you can tell SimplePie
800
	 * to parse that data string instead of a remote feed. Any set feed URL
801
	 * takes precedence.
802
	 *
803
	 * @since 1.0 Beta 3
804
	 * @param string $data RSS or Atom data as a string.
805
	 * @see set_feed_url()
806
	 */
807
	public function set_raw_data($data)
808
	{
809
		$this->raw_data = $data;
810
	}
811
812
	/**
813
	 * Set the the default timeout for fetching remote feeds
814
	 *
815
	 * This allows you to change the maximum time the feed's server to respond
816
	 * and send the feed back.
817
	 *
818
	 * @since 1.0 Beta 3
819
	 * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
820
	 */
821
	public function set_timeout($timeout = 10)
822
	{
823
		$this->timeout = (int) $timeout;
824
	}
825
826
	/**
827
	 * Set custom curl options
828
	 *
829
	 * This allows you to change default curl options
830
	 *
831
	 * @since 1.0 Beta 3
832
	 * @param array $curl_options Curl options to add to default settings
833
	 */
834
	public function set_curl_options(array $curl_options = array())
835
	{
836
		$this->curl_options = $curl_options;
837
	}
838
839
	/**
840
	 * Force SimplePie to use fsockopen() instead of cURL
841
	 *
842
	 * @since 1.0 Beta 3
843
	 * @param bool $enable Force fsockopen() to be used
844
	 */
845
	public function force_fsockopen($enable = false)
846
	{
847
		$this->force_fsockopen = (bool) $enable;
848
	}
849
850
	/**
851
	 * Enable/disable caching in SimplePie.
852
	 *
853
	 * This option allows you to disable caching all-together in SimplePie.
854
	 * However, disabling the cache can lead to longer load times.
855
	 *
856
	 * @since 1.0 Preview Release
857
	 * @param bool $enable Enable caching
858
	 */
859
	public function enable_cache($enable = true)
860
	{
861
		$this->cache = (bool) $enable;
862
	}
863
864
	/**
865
	 * SimplePie to continue to fall back to expired cache, if enabled, when
866
	 * feed is unavailable.
867
	 *
868
	 * This tells SimplePie to ignore any file errors and fall back to cache
869
	 * instead. This only works if caching is enabled and cached content
870
	 * still exists.
871
872
	 * @param bool $enable Force use of cache on fail.
873
	 */
874
	public function force_cache_fallback($enable = false)
875
	{
876
		$this->force_cache_fallback= (bool) $enable;
877
	}
878
879
	/**
880
	 * Set the length of time (in seconds) that the contents of a feed will be
881
	 * cached
882
	 *
883
	 * @param int $seconds The feed content cache duration
884
	 */
885
	public function set_cache_duration($seconds = 3600)
886
	{
887
		$this->cache_duration = (int) $seconds;
888
	}
889
890
	/**
891
	 * Set the length of time (in seconds) that the autodiscovered feed URL will
892
	 * be cached
893
	 *
894
	 * @param int $seconds The autodiscovered feed URL cache duration.
895
	 */
896
	public function set_autodiscovery_cache_duration($seconds = 604800)
897
	{
898
		$this->autodiscovery_cache_duration = (int) $seconds;
899
	}
900
901
	/**
902
	 * Set the file system location where the cached files should be stored
903
	 *
904
	 * @param string $location The file system location.
905
	 */
906
	public function set_cache_location($location = './cache')
907
	{
908
		$this->cache_location = (string) $location;
909
	}
910
911
	/**
912
	 * Set whether feed items should be sorted into reverse chronological order
913
	 *
914
	 * @param bool $enable Sort as reverse chronological order.
915
	 */
916
	public function enable_order_by_date($enable = true)
917
	{
918
		$this->order_by_date = (bool) $enable;
919
	}
920
921
	/**
922
	 * Set the character encoding used to parse the feed
923
	 *
924
	 * This overrides the encoding reported by the feed, however it will fall
925
	 * back to the normal encoding detection if the override fails
926
	 *
927
	 * @param string $encoding Character encoding
928
	 */
929
	public function set_input_encoding($encoding = false)
930
	{
931
		if ($encoding)
0 ignored issues
show
Bug Best Practice introduced by
The expression $encoding of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
932
		{
933
			$this->input_encoding = (string) $encoding;
934
		}
935
		else
936
		{
937
			$this->input_encoding = false;
938
		}
939
	}
940
941
	/**
942
	 * Set how much feed autodiscovery to do
943
	 *
944
	 * @see SIMPLEPIE_LOCATOR_NONE
945
	 * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
946
	 * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
947
	 * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
948
	 * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
949
	 * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
950
	 * @see SIMPLEPIE_LOCATOR_ALL
951
	 * @param int $level Feed Autodiscovery Level (level can be a combination of the above constants, see bitwise OR operator)
952
	 */
953
	public function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
954
	{
955
		$this->autodiscovery = (int) $level;
956
	}
957
958
	/**
959
	 * Get the class registry
960
	 *
961
	 * Use this to override SimplePie's default classes
962
	 * @see SimplePie_Registry
963
	 * @return SimplePie_Registry
964
	 */
965
	public function &get_registry()
966
	{
967
		return $this->registry;
968
	}
969
970
	/**#@+
971
	 * Useful when you are overloading or extending SimplePie's default classes.
972
	 *
973
	 * @deprecated Use {@see get_registry()} instead
974
	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
975
	 * @param string $class Name of custom class
976
	 * @return boolean True on success, false otherwise
977
	 */
978
	/**
979
	 * Set which class SimplePie uses for caching
980
	 */
981
	public function set_cache_class($class = 'SimplePie_Cache')
982
	{
983
		return $this->registry->register('Cache', $class, true);
984
	}
985
986
	/**
987
	 * Set which class SimplePie uses for auto-discovery
988
	 */
989
	public function set_locator_class($class = 'SimplePie_Locator')
990
	{
991
		return $this->registry->register('Locator', $class, true);
992
	}
993
994
	/**
995
	 * Set which class SimplePie uses for XML parsing
996
	 */
997
	public function set_parser_class($class = 'SimplePie_Parser')
998
	{
999
		return $this->registry->register('Parser', $class, true);
1000
	}
1001
1002
	/**
1003
	 * Set which class SimplePie uses for remote file fetching
1004
	 */
1005
	public function set_file_class($class = 'SimplePie_File')
1006
	{
1007
		return $this->registry->register('File', $class, true);
1008
	}
1009
1010
	/**
1011
	 * Set which class SimplePie uses for data sanitization
1012
	 */
1013
	public function set_sanitize_class($class = 'SimplePie_Sanitize')
1014
	{
1015
		return $this->registry->register('Sanitize', $class, true);
1016
	}
1017
1018
	/**
1019
	 * Set which class SimplePie uses for handling feed items
1020
	 */
1021
	public function set_item_class($class = 'SimplePie_Item')
1022
	{
1023
		return $this->registry->register('Item', $class, true);
1024
	}
1025
1026
	/**
1027
	 * Set which class SimplePie uses for handling author data
1028
	 */
1029
	public function set_author_class($class = 'SimplePie_Author')
1030
	{
1031
		return $this->registry->register('Author', $class, true);
1032
	}
1033
1034
	/**
1035
	 * Set which class SimplePie uses for handling category data
1036
	 */
1037
	public function set_category_class($class = 'SimplePie_Category')
1038
	{
1039
		return $this->registry->register('Category', $class, true);
1040
	}
1041
1042
	/**
1043
	 * Set which class SimplePie uses for feed enclosures
1044
	 */
1045
	public function set_enclosure_class($class = 'SimplePie_Enclosure')
1046
	{
1047
		return $this->registry->register('Enclosure', $class, true);
1048
	}
1049
1050
	/**
1051
	 * Set which class SimplePie uses for `<media:text>` captions
1052
	 */
1053
	public function set_caption_class($class = 'SimplePie_Caption')
1054
	{
1055
		return $this->registry->register('Caption', $class, true);
1056
	}
1057
1058
	/**
1059
	 * Set which class SimplePie uses for `<media:copyright>`
1060
	 */
1061
	public function set_copyright_class($class = 'SimplePie_Copyright')
1062
	{
1063
		return $this->registry->register('Copyright', $class, true);
1064
	}
1065
1066
	/**
1067
	 * Set which class SimplePie uses for `<media:credit>`
1068
	 */
1069
	public function set_credit_class($class = 'SimplePie_Credit')
1070
	{
1071
		return $this->registry->register('Credit', $class, true);
1072
	}
1073
1074
	/**
1075
	 * Set which class SimplePie uses for `<media:rating>`
1076
	 */
1077
	public function set_rating_class($class = 'SimplePie_Rating')
1078
	{
1079
		return $this->registry->register('Rating', $class, true);
1080
	}
1081
1082
	/**
1083
	 * Set which class SimplePie uses for `<media:restriction>`
1084
	 */
1085
	public function set_restriction_class($class = 'SimplePie_Restriction')
1086
	{
1087
		return $this->registry->register('Restriction', $class, true);
1088
	}
1089
1090
	/**
1091
	 * Set which class SimplePie uses for content-type sniffing
1092
	 */
1093
	public function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1094
	{
1095
		return $this->registry->register('Content_Type_Sniffer', $class, true);
1096
	}
1097
1098
	/**
1099
	 * Set which class SimplePie uses item sources
1100
	 */
1101
	public function set_source_class($class = 'SimplePie_Source')
1102
	{
1103
		return $this->registry->register('Source', $class, true);
1104
	}
1105
	/**#@-*/
1106
1107
	/**
1108
	 * Set the user agent string
1109
	 *
1110
	 * @param string $ua New user agent string.
1111
	 */
1112
	public function set_useragent($ua = SIMPLEPIE_USERAGENT)
1113
	{
1114
		$this->useragent = (string) $ua;
1115
	}
1116
1117
	/**
1118
	 * Set callback function to create cache filename with
1119
	 *
1120
	 * @param mixed $function Callback function
1121
	 */
1122
	public function set_cache_name_function($function = 'md5')
1123
	{
1124
		if (is_callable($function))
1125
		{
1126
			$this->cache_name_function = $function;
0 ignored issues
show
Documentation Bug introduced by
It seems like $function of type callable is incompatible with the declared type string of property $cache_name_function.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
1127
		}
1128
	}
1129
1130
	/**
1131
	 * Set options to make SP as fast as possible
1132
	 *
1133
	 * Forgoes a substantial amount of data sanitization in favor of speed. This
1134
	 * turns SimplePie into a dumb parser of feeds.
1135
	 *
1136
	 * @param bool $set Whether to set them or not
1137
	 */
1138
	public function set_stupidly_fast($set = false)
1139
	{
1140
		if ($set)
1141
		{
1142
			$this->enable_order_by_date(false);
1143
			$this->remove_div(false);
1144
			$this->strip_comments(false);
1145
			$this->strip_htmltags(false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1146
			$this->strip_attributes(false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1147
			$this->add_attributes(false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1148
			$this->set_image_handler(false);
1149
		}
1150
	}
1151
1152
	/**
1153
	 * Set maximum number of feeds to check with autodiscovery
1154
	 *
1155
	 * @param int $max Maximum number of feeds to check
1156
	 */
1157
	public function set_max_checked_feeds($max = 10)
1158
	{
1159
		$this->max_checked_feeds = (int) $max;
1160
	}
1161
1162
	public function remove_div($enable = true)
1163
	{
1164
		$this->sanitize->remove_div($enable);
1165
	}
1166
1167
	public function strip_htmltags($tags = '', $encode = null)
1168
	{
1169
		if ($tags === '')
1170
		{
1171
			$tags = $this->strip_htmltags;
1172
		}
1173
		$this->sanitize->strip_htmltags($tags);
1174
		if ($encode !== null)
1175
		{
1176
			$this->sanitize->encode_instead_of_strip($tags);
1177
		}
1178
	}
1179
1180
	public function encode_instead_of_strip($enable = true)
1181
	{
1182
		$this->sanitize->encode_instead_of_strip($enable);
1183
	}
1184
1185
	public function strip_attributes($attribs = '')
1186
	{
1187
		if ($attribs === '')
1188
		{
1189
			$attribs = $this->strip_attributes;
1190
		}
1191
		$this->sanitize->strip_attributes($attribs);
1192
	}
1193
1194
	public function add_attributes($attribs = '')
1195
	{
1196
		if ($attribs === '')
1197
		{
1198
			$attribs = $this->add_attributes;
1199
		}
1200
		$this->sanitize->add_attributes($attribs);
1201
	}
1202
1203
	/**
1204
	 * Set the output encoding
1205
	 *
1206
	 * Allows you to override SimplePie's output to match that of your webpage.
1207
	 * This is useful for times when your webpages are not being served as
1208
	 * UTF-8. This setting will be obeyed by {@see handle_content_type()}, and
1209
	 * is similar to {@see set_input_encoding()}.
1210
	 *
1211
	 * It should be noted, however, that not all character encodings can support
1212
	 * all characters. If your page is being served as ISO-8859-1 and you try
1213
	 * to display a Japanese feed, you'll likely see garbled characters.
1214
	 * Because of this, it is highly recommended to ensure that your webpages
1215
	 * are served as UTF-8.
1216
	 *
1217
	 * The number of supported character encodings depends on whether your web
1218
	 * host supports {@link http://php.net/mbstring mbstring},
1219
	 * {@link http://php.net/iconv iconv}, or both. See
1220
	 * {@link http://simplepie.org/wiki/faq/Supported_Character_Encodings} for
1221
	 * more information.
1222
	 *
1223
	 * @param string $encoding
1224
	 */
1225
	public function set_output_encoding($encoding = 'UTF-8')
1226
	{
1227
		$this->sanitize->set_output_encoding($encoding);
1228
	}
1229
1230
	public function strip_comments($strip = false)
1231
	{
1232
		$this->sanitize->strip_comments($strip);
1233
	}
1234
1235
	/**
1236
	 * Set element/attribute key/value pairs of HTML attributes
1237
	 * containing URLs that need to be resolved relative to the feed
1238
	 *
1239
	 * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite,
1240
	 * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite,
1241
	 * |q|@cite
1242
	 *
1243
	 * @since 1.0
1244
	 * @param array|null $element_attribute Element/attribute key/value pairs, null for default
1245
	 */
1246
	public function set_url_replacements($element_attribute = null)
1247
	{
1248
		$this->sanitize->set_url_replacements($element_attribute);
1249
	}
1250
1251
	/**
1252
	 * Set the handler to enable the display of cached images.
1253
	 *
1254
	 * @param str $page Web-accessible path to the handler_image.php file.
1255
	 * @param str $qs The query string that the value should be passed to.
1256
	 */
1257
	public function set_image_handler($page = false, $qs = 'i')
1258
	{
1259
		if ($page !== false)
1260
		{
1261
			$this->sanitize->set_image_handler($page . '?' . $qs . '=');
1262
		}
1263
		else
1264
		{
1265
			$this->image_handler = '';
1266
		}
1267
	}
1268
1269
	/**
1270
	 * Set the limit for items returned per-feed with multifeeds
1271
	 *
1272
	 * @param integer $limit The maximum number of items to return.
1273
	 */
1274
	public function set_item_limit($limit = 0)
1275
	{
1276
		$this->item_limit = (int) $limit;
1277
	}
1278
1279
	/**
1280
	 * Enable throwing exceptions
1281
	 *
1282
	 * @param boolean $enable Should we throw exceptions, or use the old-style error property?
1283
	 */
1284
	public function enable_exceptions($enable = true)
1285
	{
1286
		$this->enable_exceptions = $enable;
1287
	}
1288
1289
	/**
1290
	 * Initialize the feed object
1291
	 *
1292
	 * This is what makes everything happen. Period. This is where all of the
1293
	 * configuration options get processed, feeds are fetched, cached, and
1294
	 * parsed, and all of that other good stuff.
1295
	 *
1296
	 * @return boolean True if successful, false otherwise
1297
	 */
1298
	public function init()
1299
	{
1300
		// Check absolute bare minimum requirements.
1301
		if (!extension_loaded('xml') || !extension_loaded('pcre'))
1302
		{
1303
			$this->error = 'XML or PCRE extensions not loaded!';
1304
			return false;
1305
		}
1306
		// 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.
1307
		elseif (!extension_loaded('xmlreader'))
1308
		{
1309
			static $xml_is_sane = null;
1310
			if ($xml_is_sane === null)
1311
			{
1312
				$parser_check = xml_parser_create();
1313
				xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
1314
				xml_parser_free($parser_check);
1315
				$xml_is_sane = isset($values[0]['value']);
1316
			}
1317
			if (!$xml_is_sane)
0 ignored issues
show
Bug Best Practice introduced by
The expression $xml_is_sane of type boolean|null is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
1318
			{
1319
				return false;
1320
			}
1321
		}
1322
1323
		// The default sanitize class gets set in the constructor, check if it has
1324
		// changed.
1325
		if ($this->registry->get_class('Sanitize') !== 'SimplePie_Sanitize') {
1326
			$this->sanitize = $this->registry->create('Sanitize');
1327
		}
1328
		if (method_exists($this->sanitize, 'set_registry'))
1329
		{
1330
			$this->sanitize->set_registry($this->registry);
1331
		}
1332
1333
		// Pass whatever was set with config options over to the sanitizer.
1334
		// Pass the classes in for legacy support; new classes should use the registry instead
1335
		$this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->registry->get_class('Cache'));
1336
		$this->sanitize->pass_file_data($this->registry->get_class('File'), $this->timeout, $this->useragent, $this->force_fsockopen, $this->curl_options);
1337
1338
		if (!empty($this->multifeed_url))
1339
		{
1340
			$i = 0;
1341
			$success = 0;
1342
			$this->multifeed_objects = array();
1343
			$this->error = array();
1344
			foreach ($this->multifeed_url as $url)
1345
			{
1346
				$this->multifeed_objects[$i] = clone $this;
1347
				$this->multifeed_objects[$i]->set_feed_url($url);
1348
				$single_success = $this->multifeed_objects[$i]->init();
1349
				$success |= $single_success;
1350
				if (!$single_success)
1351
				{
1352
					$this->error[$i] = $this->multifeed_objects[$i]->error();
1353
				}
1354
				$i++;
1355
			}
1356
			return (bool) $success;
1357
		}
1358
		elseif ($this->feed_url === null && $this->raw_data === null)
1359
		{
1360
			return false;
1361
		}
1362
1363
		$this->error = null;
1364
		$this->data = array();
1365
		$this->check_modified = false;
1366
		$this->multifeed_objects = array();
1367
		$cache = false;
1368
1369
		if ($this->feed_url !== null)
1370
		{
1371
			$parsed_feed_url = $this->registry->call('Misc', 'parse_url', array($this->feed_url));
1372
1373
			// Decide whether to enable caching
1374
			if ($this->cache && $parsed_feed_url['scheme'] !== '')
1375
			{
1376
				$cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc'));
1377
			}
1378
1379
			// Fetch the data via SimplePie_File into $this->raw_data
1380
			if (($fetched = $this->fetch_data($cache)) === true)
1381
			{
1382
				return true;
1383
			}
1384
			elseif ($fetched === false) {
1385
				return false;
1386
			}
1387
1388
			list($headers, $sniffed) = $fetched;
1389
		}
1390
		
1391
		// Empty response check
1392
		if(empty($this->raw_data)){
1393
			$this->error = "A feed could not be found at `$this->feed_url`. Empty body.";
1394
			$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
1395
			return false;
1396
		}
1397
1398
		// Set up array of possible encodings
1399
		$encodings = array();
1400
1401
		// First check to see if input has been overridden.
1402
		if ($this->input_encoding !== false)
1403
		{
1404
			$encodings[] = strtoupper($this->input_encoding);
1405
		}
1406
1407
		$application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1408
		$text_types = array('text/xml', 'text/xml-external-parsed-entity');
1409
1410
		// RFC 3023 (only applies to sniffed content)
1411
		if (isset($sniffed))
1412
		{
1413
			if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1414
			{
1415
				if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1416
				{
1417
					$encodings[] = strtoupper($charset[1]);
1418
				}
1419
				$encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
1420
				$encodings[] = 'UTF-8';
1421
			}
1422
			elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1423
			{
1424
				if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1425
				{
1426
					$encodings[] = strtoupper($charset[1]);
1427
				}
1428
				$encodings[] = 'US-ASCII';
1429
			}
1430
			// Text MIME-type default
1431
			elseif (substr($sniffed, 0, 5) === 'text/')
1432
			{
1433
				$encodings[] = 'UTF-8';
1434
			}
1435
		}
1436
1437
		// Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1438
		$encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
1439
		$encodings[] = 'UTF-8';
1440
		$encodings[] = 'ISO-8859-1';
1441
1442
		// There's no point in trying an encoding twice
1443
		$encodings = array_unique($encodings);
1444
1445
		// Loop through each possible encoding, till we return something, or run out of possibilities
1446
		foreach ($encodings as $encoding)
1447
		{
1448
			// Change the encoding to UTF-8 (as we always use UTF-8 internally)
1449
			if ($utf8_data = $this->registry->call('Misc', 'change_encoding', array($this->raw_data, $encoding, 'UTF-8')))
1450
			{
1451
				// Create new parser
1452
				$parser = $this->registry->create('Parser');
1453
1454
				// If it's parsed fine
1455
				if ($parser->parse($utf8_data, 'UTF-8', $this->permanent_url))
1456
				{
1457
					$this->data = $parser->get_data();
1458
					if (!($this->get_type() & ~SIMPLEPIE_TYPE_NONE))
1459
					{
1460
						$this->error = "A feed could not be found at `$this->feed_url`. This does not appear to be a valid RSS or Atom feed.";
1461
						$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
1462
						return false;
1463
					}
1464
1465
					if (isset($headers))
1466
					{
1467
						$this->data['headers'] = $headers;
1468
					}
1469
					$this->data['build'] = SIMPLEPIE_BUILD;
1470
1471
					// Cache the file if caching is enabled
1472
					if ($cache && !$cache->save($this))
0 ignored issues
show
Bug introduced by
The method save() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1473
					{
1474
						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);
1475
					}
1476
					return true;
1477
				}
1478
			}
1479
		}
1480
1481
		if (isset($parser))
1482
		{
1483
			// We have an error, just set SimplePie_Misc::error to it and quit
1484
			$this->error = $this->feed_url;
1485
			$this->error .= sprintf(' is invalid XML, 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());
1486
		}
1487
		else
1488
		{
1489
			$this->error = 'The data could not be converted to UTF-8.';
1490
			if (!extension_loaded('mbstring') && !extension_loaded('iconv') && !class_exists('\UConverter')) {
1491
				$this->error .= ' You MUST have either the iconv, mbstring or intl (PHP 5.5+) extension installed and enabled.';
1492
			} else {
1493
				$missingExtensions = array();
1494
				if (!extension_loaded('iconv')) {
1495
					$missingExtensions[] = 'iconv';
1496
				}
1497
				if (!extension_loaded('mbstring')) {
1498
					$missingExtensions[] = 'mbstring';
1499
				}
1500
				if (!class_exists('\UConverter')) {
1501
					$missingExtensions[] = 'intl (PHP 5.5+)';
1502
				}
1503
				$this->error .= ' Try installing/enabling the ' . implode(' or ', $missingExtensions) . ' extension.';
1504
			}
1505
		}
1506
1507
		$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
1508
1509
		return false;
1510
	}
1511
1512
	/**
1513
	 * Fetch the data via SimplePie_File
1514
	 *
1515
	 * If the data is already cached, attempt to fetch it from there instead
1516
	 * @param SimplePie_Cache|false $cache Cache handler, or false to not load from the cache
1517
	 * @return array|true Returns true if the data was loaded from the cache, or an array of HTTP headers and sniffed type
1518
	 */
1519
	protected function fetch_data(&$cache)
1520
	{
1521
		// If it's enabled, use the cache
1522
		if ($cache)
1523
		{
1524
			// Load the Cache
1525
			$this->data = $cache->load();
0 ignored issues
show
Bug introduced by
The method load() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1526
			if (!empty($this->data))
1527
			{
1528
				// If the cache is for an outdated build of SimplePie
1529
				if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
1530
				{
1531
					$cache->unlink();
0 ignored issues
show
Bug introduced by
The method unlink() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1532
					$this->data = array();
1533
				}
1534
				// If we've hit a collision just rerun it with caching disabled
1535
				elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
1536
				{
1537
					$cache = false;
1538
					$this->data = array();
1539
				}
1540
				// If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1541
				elseif (isset($this->data['feed_url']))
1542
				{
1543
					// If the autodiscovery cache is still valid use it.
1544
					if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
0 ignored issues
show
Bug introduced by
The method mtime() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1545
					{
1546
						// Do not need to do feed autodiscovery yet.
1547
						if ($this->data['feed_url'] !== $this->data['url'])
1548
						{
1549
							$this->set_feed_url($this->data['feed_url']);
1550
							return $this->init();
1551
						}
1552
1553
						$cache->unlink();
0 ignored issues
show
Bug introduced by
The method unlink() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1554
						$this->data = array();
1555
					}
1556
				}
1557
				// Check if the cache has been updated
1558
				elseif ($cache->mtime() + $this->cache_duration < time())
0 ignored issues
show
Bug introduced by
The method mtime() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1559
				{
1560
					// Want to know if we tried to send last-modified and/or etag headers
1561
					// when requesting this file. (Note that it's up to the file to
1562
					// support this, but we don't always send the headers either.)
1563
					$this->check_modified = true;
1564
					if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1565
					{
1566
						$headers = array(
1567
							'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',
1568
						);
1569
						if (isset($this->data['headers']['last-modified']))
1570
						{
1571
							$headers['if-modified-since'] = $this->data['headers']['last-modified'];
1572
						}
1573
						if (isset($this->data['headers']['etag']))
1574
						{
1575
							$headers['if-none-match'] = $this->data['headers']['etag'];
1576
						}
1577
1578
						$file = $this->registry->create('File', array($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options));
1579
1580
						if ($file->success)
1581
						{
1582
							if ($file->status_code === 304)
1583
							{
1584
								// Set raw_data to false here too, to signify that the cache
1585
								// is still valid.
1586
								$this->raw_data = false;
0 ignored issues
show
Documentation Bug introduced by
The property $raw_data was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
1587
								$cache->touch();
0 ignored issues
show
Bug introduced by
The method touch() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1588
								return true;
1589
							}
1590
						}
1591
						else
1592
						{
1593
							$this->check_modified = false;
1594
							if($this->force_cache_fallback)
1595
							{
1596
								$cache->touch();
0 ignored issues
show
Bug introduced by
The method touch() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1597
								return true;
1598
							}
1599
1600
							unset($file);
1601
						}
1602
					}
1603
				}
1604
				// If the cache is still valid, just return true
1605
				else
1606
				{
1607
					$this->raw_data = false;
1608
					return true;
1609
				}
1610
			}
1611
			// If the cache is empty, delete it
1612
			else
1613
			{
1614
				$cache->unlink();
0 ignored issues
show
Bug introduced by
The method unlink() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1615
				$this->data = array();
1616
			}
1617
		}
1618
		// 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.
1619
		if (!isset($file))
1620
		{
1621
			if ($this->file instanceof SimplePie_File && $this->file->url === $this->feed_url)
1622
			{
1623
				$file =& $this->file;
1624
			}
1625
			else
1626
			{
1627
				$headers = array(
1628
					'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',
1629
				);
1630
				$file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options));
1631
			}
1632
		}
1633
		// If the file connection has an error, set SimplePie::error to that and quit
1634
		if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
1635
		{
1636
			$this->error = $file->error;
1637
			return !empty($this->data);
1638
		}
1639
1640
		if (!$this->force_feed)
1641
		{
1642
			// Check if the supplied URL is a feed, if it isn't, look for it.
1643
			$locate = $this->registry->create('Locator', array(&$file, $this->timeout, $this->useragent, $this->max_checked_feeds));
1644
1645
			if (!$locate->is_feed($file))
1646
			{
1647
				$copyStatusCode = $file->status_code;
1648
				$copyContentType = $file->headers['content-type'];
1649
				try
1650
				{
1651
					$microformats = false;
1652
					if (class_exists('DOMXpath') && function_exists('Mf2\parse')) {
1653
						$doc = new DOMDocument();
1654
						@$doc->loadHTML($file->body);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1655
						$xpath = new DOMXpath($doc);
1656
						// Check for both h-feed and h-entry, as both a feed with no entries
1657
						// and a list of entries without an h-feed wrapper are both valid.
1658
						$query = '//*[contains(concat(" ", @class, " "), " h-feed ") or '.
1659
							'contains(concat(" ", @class, " "), " h-entry ")]';
1660
						$result = $xpath->query($query);
1661
						$microformats = $result->length !== 0;
1662
					}
1663
					// Now also do feed discovery, but if microformats were found don't
1664
					// overwrite the current value of file.
1665
					$discovered = $locate->find($this->autodiscovery,
1666
					                            $this->all_discovered_feeds);
1667
					if ($microformats)
1668
					{
1669
						if ($hub = $locate->get_rel_link('hub'))
1670
						{
1671
							$self = $locate->get_rel_link('self');
1672
							$this->store_links($file, $hub, $self);
1673
						}
1674
						// Push the current file onto all_discovered feeds so the user can
1675
						// be shown this as one of the options.
1676
						if (isset($this->all_discovered_feeds)) {
1677
							$this->all_discovered_feeds[] = $file;
1678
						}
1679
					}
1680
					else
1681
					{
1682
						if ($discovered)
1683
						{
1684
							$file = $discovered;
1685
						}
1686
						else
1687
						{
1688
							// We need to unset this so that if SimplePie::set_file() has
1689
							// been called that object is untouched
1690
							unset($file);
1691
							$this->error = "A feed could not be found at `$this->feed_url`; the status code is `$copyStatusCode` and content-type is `$copyContentType`";
1692
							$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
1693
							return false;
1694
						}
1695
					}
1696
				}
1697
				catch (SimplePie_Exception $e)
1698
				{
1699
					// We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1700
					unset($file);
1701
					// This is usually because DOMDocument doesn't exist
1702
					$this->error = $e->getMessage();
1703
					$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, $e->getFile(), $e->getLine()));
1704
					return false;
1705
				}
1706
				if ($cache)
1707
				{
1708
					$this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1709
					if (!$cache->save($this))
0 ignored issues
show
Bug introduced by
The method save() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1710
					{
1711
						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);
1712
					}
1713
					$cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc'));
1714
				}
1715
				$this->feed_url = $file->url;
1716
			}
1717
			$locate = null;
0 ignored issues
show
Unused Code introduced by
$locate is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1718
		}
1719
1720
		$this->raw_data = $file->body;
1721
		$this->permanent_url = $file->permanent_url;
1722
		$headers = $file->headers;
1723
		$sniffer = $this->registry->create('Content_Type_Sniffer', array(&$file));
1724
		$sniffed = $sniffer->get_type();
1725
1726
		return array($headers, $sniffed);
1727
	}
1728
1729
	/**
1730
	 * Get the error message for the occured error
1731
	 *
1732
	 * @return string|array Error message, or array of messages for multifeeds
1733
	 */
1734
	public function error()
1735
	{
1736
		return $this->error;
1737
	}
1738
1739
	/**
1740
	 * Get the raw XML
1741
	 *
1742
	 * This is the same as the old `$feed->enable_xml_dump(true)`, but returns
1743
	 * the data instead of printing it.
1744
	 *
1745
	 * @return string|boolean Raw XML data, false if the cache is used
1746
	 */
1747
	public function get_raw_data()
1748
	{
1749
		return $this->raw_data;
1750
	}
1751
1752
	/**
1753
	 * Get the character encoding used for output
1754
	 *
1755
	 * @since Preview Release
1756
	 * @return string
1757
	 */
1758
	public function get_encoding()
1759
	{
1760
		return $this->sanitize->output_encoding;
1761
	}
1762
1763
	/**
1764
	 * Send the content-type header with correct encoding
1765
	 *
1766
	 * This method ensures that the SimplePie-enabled page is being served with
1767
	 * the correct {@link http://www.iana.org/assignments/media-types/ mime-type}
1768
	 * and character encoding HTTP headers (character encoding determined by the
1769
	 * {@see set_output_encoding} config option).
1770
	 *
1771
	 * This won't work properly if any content or whitespace has already been
1772
	 * sent to the browser, because it relies on PHP's
1773
	 * {@link http://php.net/header header()} function, and these are the
1774
	 * circumstances under which the function works.
1775
	 *
1776
	 * Because it's setting these settings for the entire page (as is the nature
1777
	 * of HTTP headers), this should only be used once per page (again, at the
1778
	 * top).
1779
	 *
1780
	 * @param string $mime MIME type to serve the page as
1781
	 */
1782
	public function handle_content_type($mime = 'text/html')
1783
	{
1784
		if (!headers_sent())
1785
		{
1786
			$header = "Content-type: $mime;";
1787
			if ($this->get_encoding())
1788
			{
1789
				$header .= ' charset=' . $this->get_encoding();
1790
			}
1791
			else
1792
			{
1793
				$header .= ' charset=UTF-8';
1794
			}
1795
			header($header);
1796
		}
1797
	}
1798
1799
	/**
1800
	 * Get the type of the feed
1801
	 *
1802
	 * This returns a SIMPLEPIE_TYPE_* constant, which can be tested against
1803
	 * using {@link http://php.net/language.operators.bitwise bitwise operators}
1804
	 *
1805
	 * @since 0.8 (usage changed to using constants in 1.0)
1806
	 * @see SIMPLEPIE_TYPE_NONE Unknown.
1807
	 * @see SIMPLEPIE_TYPE_RSS_090 RSS 0.90.
1808
	 * @see SIMPLEPIE_TYPE_RSS_091_NETSCAPE RSS 0.91 (Netscape).
1809
	 * @see SIMPLEPIE_TYPE_RSS_091_USERLAND RSS 0.91 (Userland).
1810
	 * @see SIMPLEPIE_TYPE_RSS_091 RSS 0.91.
1811
	 * @see SIMPLEPIE_TYPE_RSS_092 RSS 0.92.
1812
	 * @see SIMPLEPIE_TYPE_RSS_093 RSS 0.93.
1813
	 * @see SIMPLEPIE_TYPE_RSS_094 RSS 0.94.
1814
	 * @see SIMPLEPIE_TYPE_RSS_10 RSS 1.0.
1815
	 * @see SIMPLEPIE_TYPE_RSS_20 RSS 2.0.x.
1816
	 * @see SIMPLEPIE_TYPE_RSS_RDF RDF-based RSS.
1817
	 * @see SIMPLEPIE_TYPE_RSS_SYNDICATION Non-RDF-based RSS (truly intended as syndication format).
1818
	 * @see SIMPLEPIE_TYPE_RSS_ALL Any version of RSS.
1819
	 * @see SIMPLEPIE_TYPE_ATOM_03 Atom 0.3.
1820
	 * @see SIMPLEPIE_TYPE_ATOM_10 Atom 1.0.
1821
	 * @see SIMPLEPIE_TYPE_ATOM_ALL Any version of Atom.
1822
	 * @see SIMPLEPIE_TYPE_ALL Any known/supported feed type.
1823
	 * @return int SIMPLEPIE_TYPE_* constant
1824
	 */
1825
	public function get_type()
1826
	{
1827
		if (!isset($this->data['type']))
1828
		{
1829
			$this->data['type'] = SIMPLEPIE_TYPE_ALL;
1830
			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1831
			{
1832
				$this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1833
			}
1834
			elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1835
			{
1836
				$this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1837
			}
1838
			elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1839
			{
1840
				if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1841
				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1842
				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1843
				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1844
				{
1845
					$this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1846
				}
1847
				if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1848
				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1849
				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1850
				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1851
				{
1852
					$this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1853
				}
1854
			}
1855
			elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
1856
			{
1857
				$this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1858
				if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1859
				{
1860
					switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1861
					{
1862
						case '0.91':
1863
							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1864
							if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1865
							{
1866
								switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1867
								{
1868
									case '0':
1869
										$this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1870
										break;
1871
1872
									case '24':
1873
										$this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1874
										break;
1875
								}
1876
							}
1877
							break;
1878
1879
						case '0.92':
1880
							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1881
							break;
1882
1883
						case '0.93':
1884
							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1885
							break;
1886
1887
						case '0.94':
1888
							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1889
							break;
1890
1891
						case '2.0':
1892
							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1893
							break;
1894
					}
1895
				}
1896
			}
1897
			else
1898
			{
1899
				$this->data['type'] = SIMPLEPIE_TYPE_NONE;
1900
			}
1901
		}
1902
		return $this->data['type'];
1903
	}
1904
1905
	/**
1906
	 * Get the URL for the feed
1907
	 * 
1908
	 * When the 'permanent' mode is enabled, returns the original feed URL,
1909
	 * except in the case of an `HTTP 301 Moved Permanently` status response,
1910
	 * in which case the location of the first redirection is returned.
1911
	 *
1912
	 * When the 'permanent' mode is disabled (default),
1913
	 * may or may not be different from the URL passed to {@see set_feed_url()},
1914
	 * depending on whether auto-discovery was used.
1915
	 *
1916
	 * @since Preview Release (previously called `get_feed_url()` since SimplePie 0.8.)
1917
	 * @todo Support <itunes:new-feed-url>
1918
	 * @todo Also, |atom:link|@rel=self
1919
	 * @param bool $permanent Permanent mode to return only the original URL or the first redirection
1920
	 * iff it is a 301 redirection
1921
	 * @return string|null
1922
	 */
1923
	public function subscribe_url($permanent = false)
1924
	{
1925
		if ($permanent)
1926
		{
1927
			if ($this->permanent_url !== null)
1928
			{
1929
				// sanitize encodes ampersands which are required when used in a url.
1930
				return str_replace('&amp;', '&',
1931
				                   $this->sanitize($this->permanent_url,
1932
				                                   SIMPLEPIE_CONSTRUCT_IRI));
1933
			}
1934
		}
1935
		else
1936
		{
1937
			if ($this->feed_url !== null)
1938
			{
1939
				return str_replace('&amp;', '&',
1940
				                   $this->sanitize($this->feed_url,
1941
				                                   SIMPLEPIE_CONSTRUCT_IRI));
1942
			}
1943
		}
1944
		return null;
1945
	}
1946
1947
	/**
1948
	 * Get data for an feed-level element
1949
	 *
1950
	 * This method allows you to get access to ANY element/attribute that is a
1951
	 * sub-element of the opening feed tag.
1952
	 *
1953
	 * The return value is an indexed array of elements matching the given
1954
	 * namespace and tag name. Each element has `attribs`, `data` and `child`
1955
	 * subkeys. For `attribs` and `child`, these contain namespace subkeys.
1956
	 * `attribs` then has one level of associative name => value data (where
1957
	 * `value` is a string) after the namespace. `child` has tag-indexed keys
1958
	 * after the namespace, each member of which is an indexed array matching
1959
	 * this same format.
1960
	 *
1961
	 * For example:
1962
	 * <pre>
1963
	 * // This is probably a bad example because we already support
1964
	 * // <media:content> natively, but it shows you how to parse through
1965
	 * // the nodes.
1966
	 * $group = $item->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group');
1967
	 * $content = $group[0]['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'];
1968
	 * $file = $content[0]['attribs']['']['url'];
1969
	 * echo $file;
1970
	 * </pre>
1971
	 *
1972
	 * @since 1.0
1973
	 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
1974
	 * @param string $namespace The URL of the XML namespace of the elements you're trying to access
1975
	 * @param string $tag Tag name
1976
	 * @return array
1977
	 */
1978
	public function get_feed_tags($namespace, $tag)
1979
	{
1980
		$type = $this->get_type();
1981
		if ($type & SIMPLEPIE_TYPE_ATOM_10)
1982
		{
1983
			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
1984
			{
1985
				return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
1986
			}
1987
		}
1988
		if ($type & SIMPLEPIE_TYPE_ATOM_03)
1989
		{
1990
			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
1991
			{
1992
				return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
1993
			}
1994
		}
1995
		if ($type & SIMPLEPIE_TYPE_RSS_RDF)
1996
		{
1997
			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
1998
			{
1999
				return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
2000
			}
2001
		}
2002
		if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2003
		{
2004
			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
2005
			{
2006
				return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
2007
			}
2008
		}
2009
		return null;
2010
	}
2011
2012
	/**
2013
	 * Get data for an channel-level element
2014
	 *
2015
	 * This method allows you to get access to ANY element/attribute in the
2016
	 * channel/header section of the feed.
2017
	 *
2018
	 * See {@see SimplePie::get_feed_tags()} for a description of the return value
2019
	 *
2020
	 * @since 1.0
2021
	 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
2022
	 * @param string $namespace The URL of the XML namespace of the elements you're trying to access
2023
	 * @param string $tag Tag name
2024
	 * @return array
2025
	 */
2026
	public function get_channel_tags($namespace, $tag)
2027
	{
2028
		$type = $this->get_type();
2029
		if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
2030
		{
2031
			if ($return = $this->get_feed_tags($namespace, $tag))
2032
			{
2033
				return $return;
2034
			}
2035
		}
2036
		if ($type & SIMPLEPIE_TYPE_RSS_10)
2037
		{
2038
			if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
2039
			{
2040
				if (isset($channel[0]['child'][$namespace][$tag]))
2041
				{
2042
					return $channel[0]['child'][$namespace][$tag];
2043
				}
2044
			}
2045
		}
2046
		if ($type & SIMPLEPIE_TYPE_RSS_090)
2047
		{
2048
			if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
2049
			{
2050
				if (isset($channel[0]['child'][$namespace][$tag]))
2051
				{
2052
					return $channel[0]['child'][$namespace][$tag];
2053
				}
2054
			}
2055
		}
2056
		if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2057
		{
2058
			if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
2059
			{
2060
				if (isset($channel[0]['child'][$namespace][$tag]))
2061
				{
2062
					return $channel[0]['child'][$namespace][$tag];
2063
				}
2064
			}
2065
		}
2066
		return null;
2067
	}
2068
2069
	/**
2070
	 * Get data for an channel-level element
2071
	 *
2072
	 * This method allows you to get access to ANY element/attribute in the
2073
	 * image/logo section of the feed.
2074
	 *
2075
	 * See {@see SimplePie::get_feed_tags()} for a description of the return value
2076
	 *
2077
	 * @since 1.0
2078
	 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
2079
	 * @param string $namespace The URL of the XML namespace of the elements you're trying to access
2080
	 * @param string $tag Tag name
2081
	 * @return array
2082
	 */
2083
	public function get_image_tags($namespace, $tag)
2084
	{
2085
		$type = $this->get_type();
2086
		if ($type & SIMPLEPIE_TYPE_RSS_10)
2087
		{
2088
			if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
2089
			{
2090
				if (isset($image[0]['child'][$namespace][$tag]))
2091
				{
2092
					return $image[0]['child'][$namespace][$tag];
2093
				}
2094
			}
2095
		}
2096
		if ($type & SIMPLEPIE_TYPE_RSS_090)
2097
		{
2098
			if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2099
			{
2100
				if (isset($image[0]['child'][$namespace][$tag]))
2101
				{
2102
					return $image[0]['child'][$namespace][$tag];
2103
				}
2104
			}
2105
		}
2106
		if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2107
		{
2108
			if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
2109
			{
2110
				if (isset($image[0]['child'][$namespace][$tag]))
2111
				{
2112
					return $image[0]['child'][$namespace][$tag];
2113
				}
2114
			}
2115
		}
2116
		return null;
2117
	}
2118
2119
	/**
2120
	 * Get the base URL value from the feed
2121
	 *
2122
	 * Uses `<xml:base>` if available, otherwise uses the first link in the
2123
	 * feed, or failing that, the URL of the feed itself.
2124
	 *
2125
	 * @see get_link
2126
	 * @see subscribe_url
2127
	 *
2128
	 * @param array $element
2129
	 * @return string
2130
	 */
2131
	public function get_base($element = array())
2132
	{
2133
		if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2134
		{
2135
			return $element['xml_base'];
2136
		}
2137
		elseif ($this->get_link() !== null)
2138
		{
2139
			return $this->get_link();
2140
		}
2141
		else
2142
		{
2143
			return $this->subscribe_url();
2144
		}
2145
	}
2146
2147
	/**
2148
	 * Sanitize feed data
2149
	 *
2150
	 * @access private
2151
	 * @see SimplePie_Sanitize::sanitize()
2152
	 * @param string $data Data to sanitize
2153
	 * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants
2154
	 * @param string $base Base URL to resolve URLs against
2155
	 * @return string Sanitized data
2156
	 */
2157
	public function sanitize($data, $type, $base = '')
2158
	{
2159
		try
2160
		{
2161
			return $this->sanitize->sanitize($data, $type, $base);
2162
		}
2163
		catch (SimplePie_Exception $e)
2164
		{
2165
			if (!$this->enable_exceptions)
2166
			{
2167
				$this->error = $e->getMessage();
2168
				$this->registry->call('Misc', 'error', array($this->error, E_USER_WARNING, $e->getFile(), $e->getLine()));
2169
				return '';
2170
			}
2171
2172
			throw $e;
2173
		}
2174
	}
2175
2176
	/**
2177
	 * Get the title of the feed
2178
	 *
2179
	 * Uses `<atom:title>`, `<title>` or `<dc:title>`
2180
	 *
2181
	 * @since 1.0 (previously called `get_feed_title` since 0.8)
2182
	 * @return string|null
2183
	 */
2184
	public function get_title()
2185
	{
2186
		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2187
		{
2188
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2189
		}
2190
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2191
		{
2192
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2193
		}
2194
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2195
		{
2196
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2197
		}
2198
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2199
		{
2200
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2201
		}
2202
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2203
		{
2204
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2205
		}
2206
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2207
		{
2208
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2209
		}
2210
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2211
		{
2212
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2213
		}
2214
		else
2215
		{
2216
			return null;
2217
		}
2218
	}
2219
2220
	/**
2221
	 * Get a category for the feed
2222
	 *
2223
	 * @since Unknown
2224
	 * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1
2225
	 * @return SimplePie_Category|null
2226
	 */
2227
	public function get_category($key = 0)
2228
	{
2229
		$categories = $this->get_categories();
2230
		if (isset($categories[$key]))
2231
		{
2232
			return $categories[$key];
2233
		}
2234
		else
2235
		{
2236
			return null;
2237
		}
2238
	}
2239
2240
	/**
2241
	 * Get all categories for the feed
2242
	 *
2243
	 * Uses `<atom:category>`, `<category>` or `<dc:subject>`
2244
	 *
2245
	 * @since Unknown
2246
	 * @return array|null List of {@see SimplePie_Category} objects
2247
	 */
2248
	public function get_categories()
2249
	{
2250
		$categories = array();
2251
2252
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2253
		{
2254
			$term = null;
2255
			$scheme = null;
2256
			$label = null;
2257
			if (isset($category['attribs']['']['term']))
2258
			{
2259
				$term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2260
			}
2261
			if (isset($category['attribs']['']['scheme']))
2262
			{
2263
				$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2264
			}
2265
			if (isset($category['attribs']['']['label']))
2266
			{
2267
				$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2268
			}
2269
			$categories[] = $this->registry->create('Category', array($term, $scheme, $label));
2270
		}
2271
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
2272
		{
2273
			// This is really the label, but keep this as the term also for BC.
2274
			// Label will also work on retrieving because that falls back to term.
2275
			$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2276
			if (isset($category['attribs']['']['domain']))
2277
			{
2278
				$scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
2279
			}
2280
			else
2281
			{
2282
				$scheme = null;
2283
			}
2284
			$categories[] = $this->registry->create('Category', array($term, $scheme, null));
2285
		}
2286
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2287
		{
2288
			$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
2289
		}
2290
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2291
		{
2292
			$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
2293
		}
2294
2295
		if (!empty($categories))
2296
		{
2297
			return array_unique($categories);
2298
		}
2299
		else
2300
		{
2301
			return null;
2302
		}
2303
	}
2304
2305
	/**
2306
	 * Get an author for the feed
2307
	 *
2308
	 * @since 1.1
2309
	 * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1
2310
	 * @return SimplePie_Author|null
2311
	 */
2312
	public function get_author($key = 0)
2313
	{
2314
		$authors = $this->get_authors();
2315
		if (isset($authors[$key]))
2316
		{
2317
			return $authors[$key];
2318
		}
2319
		else
2320
		{
2321
			return null;
2322
		}
2323
	}
2324
2325
	/**
2326
	 * Get all authors for the feed
2327
	 *
2328
	 * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`
2329
	 *
2330
	 * @since 1.1
2331
	 * @return array|null List of {@see SimplePie_Author} objects
2332
	 */
2333
	public function get_authors()
2334
	{
2335
		$authors = array();
2336
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2337
		{
2338
			$name = null;
2339
			$uri = null;
2340
			$email = null;
2341
			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2342
			{
2343
				$name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2344
			}
2345
			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2346
			{
2347
				$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]));
2348
			}
2349
			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2350
			{
2351
				$email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2352
			}
2353
			if ($name !== null || $email !== null || $uri !== null)
2354
			{
2355
				$authors[] = $this->registry->create('Author', array($name, $uri, $email));
2356
			}
2357
		}
2358
		if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2359
		{
2360
			$name = null;
2361
			$url = null;
2362
			$email = null;
2363
			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2364
			{
2365
				$name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2366
			}
2367
			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2368
			{
2369
				$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]));
2370
			}
2371
			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2372
			{
2373
				$email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2374
			}
2375
			if ($name !== null || $email !== null || $url !== null)
2376
			{
2377
				$authors[] = $this->registry->create('Author', array($name, $url, $email));
2378
			}
2379
		}
2380
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2381
		{
2382
			$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
2383
		}
2384
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2385
		{
2386
			$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
2387
		}
2388
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2389
		{
2390
			$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
2391
		}
2392
2393
		if (!empty($authors))
2394
		{
2395
			return array_unique($authors);
2396
		}
2397
		else
2398
		{
2399
			return null;
2400
		}
2401
	}
2402
2403
	/**
2404
	 * Get a contributor for the feed
2405
	 *
2406
	 * @since 1.1
2407
	 * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1
2408
	 * @return SimplePie_Author|null
2409
	 */
2410
	public function get_contributor($key = 0)
2411
	{
2412
		$contributors = $this->get_contributors();
2413
		if (isset($contributors[$key]))
2414
		{
2415
			return $contributors[$key];
2416
		}
2417
		else
2418
		{
2419
			return null;
2420
		}
2421
	}
2422
2423
	/**
2424
	 * Get all contributors for the feed
2425
	 *
2426
	 * Uses `<atom:contributor>`
2427
	 *
2428
	 * @since 1.1
2429
	 * @return array|null List of {@see SimplePie_Author} objects
2430
	 */
2431
	public function get_contributors()
2432
	{
2433
		$contributors = array();
2434
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2435
		{
2436
			$name = null;
2437
			$uri = null;
2438
			$email = null;
2439
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2440
			{
2441
				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2442
			}
2443
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2444
			{
2445
				$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]));
2446
			}
2447
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2448
			{
2449
				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2450
			}
2451
			if ($name !== null || $email !== null || $uri !== null)
2452
			{
2453
				$contributors[] = $this->registry->create('Author', array($name, $uri, $email));
2454
			}
2455
		}
2456
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2457
		{
2458
			$name = null;
2459
			$url = null;
2460
			$email = null;
2461
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2462
			{
2463
				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2464
			}
2465
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2466
			{
2467
				$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]));
2468
			}
2469
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2470
			{
2471
				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2472
			}
2473
			if ($name !== null || $email !== null || $url !== null)
2474
			{
2475
				$contributors[] = $this->registry->create('Author', array($name, $url, $email));
2476
			}
2477
		}
2478
2479
		if (!empty($contributors))
2480
		{
2481
			return array_unique($contributors);
2482
		}
2483
		else
2484
		{
2485
			return null;
2486
		}
2487
	}
2488
2489
	/**
2490
	 * Get a single link for the feed
2491
	 *
2492
	 * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
2493
	 * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1
2494
	 * @param string $rel The relationship of the link to return
2495
	 * @return string|null Link URL
2496
	 */
2497
	public function get_link($key = 0, $rel = 'alternate')
2498
	{
2499
		$links = $this->get_links($rel);
2500
		if (isset($links[$key]))
2501
		{
2502
			return $links[$key];
2503
		}
2504
		else
2505
		{
2506
			return null;
2507
		}
2508
	}
2509
2510
	/**
2511
	 * Get the permalink for the item
2512
	 *
2513
	 * Returns the first link available with a relationship of "alternate".
2514
	 * Identical to {@see get_link()} with key 0
2515
	 *
2516
	 * @see get_link
2517
	 * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
2518
	 * @internal Added for parity between the parent-level and the item/entry-level.
2519
	 * @return string|null Link URL
2520
	 */
2521
	public function get_permalink()
2522
	{
2523
		return $this->get_link(0);
2524
	}
2525
2526
	/**
2527
	 * Get all links for the feed
2528
	 *
2529
	 * Uses `<atom:link>` or `<link>`
2530
	 *
2531
	 * @since Beta 2
2532
	 * @param string $rel The relationship of links to return
2533
	 * @return array|null Links found for the feed (strings)
2534
	 */
2535
	public function get_links($rel = 'alternate')
2536
	{
2537
		if (!isset($this->data['links']))
2538
		{
2539
			$this->data['links'] = array();
2540
			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2541
			{
2542
				foreach ($links as $link)
2543
				{
2544
					if (isset($link['attribs']['']['href']))
2545
					{
2546
						$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2547
						$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2548
					}
2549
				}
2550
			}
2551
			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2552
			{
2553
				foreach ($links as $link)
2554
				{
2555
					if (isset($link['attribs']['']['href']))
2556
					{
2557
						$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2558
						$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2559
2560
					}
2561
				}
2562
			}
2563
			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2564
			{
2565
				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2566
			}
2567
			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2568
			{
2569
				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2570
			}
2571
			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2572
			{
2573
				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2574
			}
2575
2576
			$keys = array_keys($this->data['links']);
2577
			foreach ($keys as $key)
2578
			{
2579
				if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))
2580
				{
2581
					if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2582
					{
2583
						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2584
						$this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2585
					}
2586
					else
2587
					{
2588
						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2589
					}
2590
				}
2591
				elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2592
				{
2593
					$this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2594
				}
2595
				$this->data['links'][$key] = array_unique($this->data['links'][$key]);
2596
			}
2597
		}
2598
2599
		if (isset($this->data['headers']['link']) &&
2600
		    preg_match('/<([^>]+)>; rel='.preg_quote($rel).'/',
2601
		               $this->data['headers']['link'], $match))
2602
		{
2603
			return array($match[1]);
2604
		}
2605
		else if (isset($this->data['links'][$rel]))
2606
		{
2607
			return $this->data['links'][$rel];
2608
		}
2609
		else
2610
		{
2611
			return null;
2612
		}
2613
	}
2614
2615
	public function get_all_discovered_feeds()
2616
	{
2617
		return $this->all_discovered_feeds;
2618
	}
2619
2620
	/**
2621
	 * Get the content for the item
2622
	 *
2623
	 * Uses `<atom:subtitle>`, `<atom:tagline>`, `<description>`,
2624
	 * `<dc:description>`, `<itunes:summary>` or `<itunes:subtitle>`
2625
	 *
2626
	 * @since 1.0 (previously called `get_feed_description()` since 0.8)
2627
	 * @return string|null
2628
	 */
2629
	public function get_description()
2630
	{
2631
		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2632
		{
2633
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2634
		}
2635
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2636
		{
2637
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2638
		}
2639
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2640
		{
2641
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2642
		}
2643
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2644
		{
2645
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2646
		}
2647
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2648
		{
2649
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2650
		}
2651
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2652
		{
2653
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2654
		}
2655
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2656
		{
2657
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2658
		}
2659
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2660
		{
2661
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2662
		}
2663
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2664
		{
2665
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2666
		}
2667
		else
2668
		{
2669
			return null;
2670
		}
2671
	}
2672
2673
	/**
2674
	 * Get the copyright info for the feed
2675
	 *
2676
	 * Uses `<atom:rights>`, `<atom:copyright>` or `<dc:rights>`
2677
	 *
2678
	 * @since 1.0 (previously called `get_feed_copyright()` since 0.8)
2679
	 * @return string|null
2680
	 */
2681
	public function get_copyright()
2682
	{
2683
		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2684
		{
2685
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2686
		}
2687
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2688
		{
2689
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2690
		}
2691
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2692
		{
2693
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2694
		}
2695
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2696
		{
2697
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2698
		}
2699
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2700
		{
2701
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2702
		}
2703
		else
2704
		{
2705
			return null;
2706
		}
2707
	}
2708
2709
	/**
2710
	 * Get the language for the feed
2711
	 *
2712
	 * Uses `<language>`, `<dc:language>`, or @xml_lang
2713
	 *
2714
	 * @since 1.0 (previously called `get_feed_language()` since 0.8)
2715
	 * @return string|null
2716
	 */
2717
	public function get_language()
2718
	{
2719
		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2720
		{
2721
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2722
		}
2723
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2724
		{
2725
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2726
		}
2727
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2728
		{
2729
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2730
		}
2731
		elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2732
		{
2733
			return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2734
		}
2735
		elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2736
		{
2737
			return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2738
		}
2739
		elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2740
		{
2741
			return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2742
		}
2743
		elseif (isset($this->data['headers']['content-language']))
2744
		{
2745
			return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2746
		}
2747
		else
2748
		{
2749
			return null;
2750
		}
2751
	}
2752
2753
	/**
2754
	 * Get the latitude coordinates for the item
2755
	 *
2756
	 * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
2757
	 *
2758
	 * Uses `<geo:lat>` or `<georss:point>`
2759
	 *
2760
	 * @since 1.0
2761
	 * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
2762
	 * @link http://www.georss.org/ GeoRSS
2763
	 * @return string|null
2764
	 */
2765
	public function get_latitude()
2766
	{
2767
2768
		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2769
		{
2770
			return (float) $return[0]['data'];
2771
		}
2772
		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))
2773
		{
2774
			return (float) $match[1];
2775
		}
2776
		else
2777
		{
2778
			return null;
2779
		}
2780
	}
2781
2782
	/**
2783
	 * Get the longitude coordinates for the feed
2784
	 *
2785
	 * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
2786
	 *
2787
	 * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`
2788
	 *
2789
	 * @since 1.0
2790
	 * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
2791
	 * @link http://www.georss.org/ GeoRSS
2792
	 * @return string|null
2793
	 */
2794
	public function get_longitude()
2795
	{
2796
		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2797
		{
2798
			return (float) $return[0]['data'];
2799
		}
2800
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2801
		{
2802
			return (float) $return[0]['data'];
2803
		}
2804
		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))
2805
		{
2806
			return (float) $match[2];
2807
		}
2808
		else
2809
		{
2810
			return null;
2811
		}
2812
	}
2813
2814
	/**
2815
	 * Get the feed logo's title
2816
	 *
2817
	 * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" title.
2818
	 *
2819
	 * Uses `<image><title>` or `<image><dc:title>`
2820
	 *
2821
	 * @return string|null
2822
	 */
2823
	public function get_image_title()
2824
	{
2825
		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2826
		{
2827
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2828
		}
2829
		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2830
		{
2831
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2832
		}
2833
		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2834
		{
2835
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2836
		}
2837
		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2838
		{
2839
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2840
		}
2841
		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2842
		{
2843
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2844
		}
2845
		else
2846
		{
2847
			return null;
2848
		}
2849
	}
2850
2851
	/**
2852
	 * Get the feed logo's URL
2853
	 *
2854
	 * RSS 0.9.0, 2.0, Atom 1.0, and feeds with iTunes RSS tags are allowed to
2855
	 * have a "feed logo" URL. This points directly to the image itself.
2856
	 *
2857
	 * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
2858
	 * `<image><title>` or `<image><dc:title>`
2859
	 *
2860
	 * @return string|null
2861
	 */
2862
	public function get_image_url()
2863
	{
2864
		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2865
		{
2866
			return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2867
		}
2868
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2869
		{
2870
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2871
		}
2872
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2873
		{
2874
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2875
		}
2876
		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2877
		{
2878
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2879
		}
2880
		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2881
		{
2882
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2883
		}
2884
		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2885
		{
2886
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2887
		}
2888
		else
2889
		{
2890
			return null;
2891
		}
2892
	}
2893
2894
	/**
2895
	 * Get the feed logo's link
2896
	 *
2897
	 * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" link. This
2898
	 * points to a human-readable page that the image should link to.
2899
	 *
2900
	 * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
2901
	 * `<image><title>` or `<image><dc:title>`
2902
	 *
2903
	 * @return string|null
2904
	 */
2905
	public function get_image_link()
2906
	{
2907
		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2908
		{
2909
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2910
		}
2911
		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2912
		{
2913
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2914
		}
2915
		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2916
		{
2917
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2918
		}
2919
		else
2920
		{
2921
			return null;
2922
		}
2923
	}
2924
2925
	/**
2926
	 * Get the feed logo's link
2927
	 *
2928
	 * RSS 2.0 feeds are allowed to have a "feed logo" width.
2929
	 *
2930
	 * Uses `<image><width>` or defaults to 88.0 if no width is specified and
2931
	 * the feed is an RSS 2.0 feed.
2932
	 *
2933
	 * @return int|float|null
2934
	 */
2935
	public function get_image_width()
2936
	{
2937
		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2938
		{
2939
			return round($return[0]['data']);
2940
		}
2941
		elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2942
		{
2943
			return 88.0;
2944
		}
2945
		else
2946
		{
2947
			return null;
2948
		}
2949
	}
2950
2951
	/**
2952
	 * Get the feed logo's height
2953
	 *
2954
	 * RSS 2.0 feeds are allowed to have a "feed logo" height.
2955
	 *
2956
	 * Uses `<image><height>` or defaults to 31.0 if no height is specified and
2957
	 * the feed is an RSS 2.0 feed.
2958
	 *
2959
	 * @return int|float|null
2960
	 */
2961
	public function get_image_height()
2962
	{
2963
		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2964
		{
2965
			return round($return[0]['data']);
2966
		}
2967
		elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2968
		{
2969
			return 31.0;
2970
		}
2971
		else
2972
		{
2973
			return null;
2974
		}
2975
	}
2976
2977
	/**
2978
	 * Get the number of items in the feed
2979
	 *
2980
	 * This is well-suited for {@link http://php.net/for for()} loops with
2981
	 * {@see get_item()}
2982
	 *
2983
	 * @param int $max Maximum value to return. 0 for no limit
2984
	 * @return int Number of items in the feed
2985
	 */
2986
	public function get_item_quantity($max = 0)
2987
	{
2988
		$max = (int) $max;
2989
		$qty = count($this->get_items());
2990
		if ($max === 0)
2991
		{
2992
			return $qty;
2993
		}
2994
		else
2995
		{
2996
			return ($qty > $max) ? $max : $qty;
2997
		}
2998
	}
2999
3000
	/**
3001
	 * Get a single item from the feed
3002
	 *
3003
	 * This is better suited for {@link http://php.net/for for()} loops, whereas
3004
	 * {@see get_items()} is better suited for
3005
	 * {@link http://php.net/foreach foreach()} loops.
3006
	 *
3007
	 * @see get_item_quantity()
3008
	 * @since Beta 2
3009
	 * @param int $key The item that you want to return. Remember that arrays begin with 0, not 1
3010
	 * @return SimplePie_Item|null
3011
	 */
3012
	public function get_item($key = 0)
3013
	{
3014
		$items = $this->get_items();
3015
		if (isset($items[$key]))
3016
		{
3017
			return $items[$key];
3018
		}
3019
		else
3020
		{
3021
			return null;
3022
		}
3023
	}
3024
3025
	/**
3026
	 * Get all items from the feed
3027
	 *
3028
	 * This is better suited for {@link http://php.net/for for()} loops, whereas
3029
	 * {@see get_items()} is better suited for
3030
	 * {@link http://php.net/foreach foreach()} loops.
3031
	 *
3032
	 * @see get_item_quantity
3033
	 * @since Beta 2
3034
	 * @param int $start Index to start at
3035
	 * @param int $end Number of items to return. 0 for all items after `$start`
3036
	 * @return SimplePie_Item[]|null List of {@see SimplePie_Item} objects
3037
	 */
3038
	public function get_items($start = 0, $end = 0)
3039
	{
3040
		if (!isset($this->data['items']))
3041
		{
3042
			if (!empty($this->multifeed_objects))
3043
			{
3044
				$this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
3045
				if (empty($this->data['items']))
3046
				{
3047
					return array();
3048
				}
3049
				return $this->data['items'];
3050
			}
3051
			$this->data['items'] = array();
3052
			if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
3053
			{
3054
				$keys = array_keys($items);
3055
				foreach ($keys as $key)
3056
				{
3057
					$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
3058
				}
3059
			}
3060
			if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
3061
			{
3062
				$keys = array_keys($items);
3063
				foreach ($keys as $key)
3064
				{
3065
					$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
3066
				}
3067
			}
3068
			if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
3069
			{
3070
				$keys = array_keys($items);
3071
				foreach ($keys as $key)
3072
				{
3073
					$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
3074
				}
3075
			}
3076
			if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
3077
			{
3078
				$keys = array_keys($items);
3079
				foreach ($keys as $key)
3080
				{
3081
					$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
3082
				}
3083
			}
3084
			if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
3085
			{
3086
				$keys = array_keys($items);
3087
				foreach ($keys as $key)
3088
				{
3089
					$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
3090
				}
3091
			}
3092
		}
3093
3094
		if (empty($this->data['items']))
3095
		{
3096
			return array();
3097
		}
3098
3099
		if ($this->order_by_date)
3100
		{
3101
			if (!isset($this->data['ordered_items']))
3102
			{
3103
				$this->data['ordered_items'] = $this->data['items'];
3104
				usort($this->data['ordered_items'], array(get_class($this), 'sort_items'));
3105
		 	}
3106
			$items = $this->data['ordered_items'];
3107
		}
3108
		else
3109
		{
3110
			$items = $this->data['items'];
3111
		}
3112
		// Slice the data as desired
3113
		if ($end === 0)
3114
		{
3115
			return array_slice($items, $start);
3116
		}
3117
		else
3118
		{
3119
			return array_slice($items, $start, $end);
3120
		}
3121
	}
3122
3123
	/**
3124
	 * Set the favicon handler
3125
	 *
3126
	 * @deprecated Use your own favicon handling instead
3127
	 */
3128
	public function set_favicon_handler($page = false, $qs = 'i')
0 ignored issues
show
Unused Code introduced by
The parameter $page is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $qs is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
3129
	{
3130
		$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
3131
		trigger_error('Favicon handling has been removed, please use your own handling', $level);
3132
		return false;
3133
	}
3134
3135
	/**
3136
	 * Get the favicon for the current feed
3137
	 *
3138
	 * @deprecated Use your own favicon handling instead
3139
	 */
3140
	public function get_favicon()
3141
	{
3142
		$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
3143
		trigger_error('Favicon handling has been removed, please use your own handling', $level);
3144
3145
		if (($url = $this->get_link()) !== null)
3146
		{
3147
			return 'https://www.google.com/s2/favicons?domain=' . urlencode($url);
3148
		}
3149
3150
		return false;
3151
	}
3152
3153
	/**
3154
	 * Magic method handler
3155
	 *
3156
	 * @param string $method Method name
3157
	 * @param array $args Arguments to the method
3158
	 * @return mixed
3159
	 */
3160
	public function __call($method, $args)
3161
	{
3162
		if (strpos($method, 'subscribe_') === 0)
3163
		{
3164
			$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
3165
			trigger_error('subscribe_*() has been deprecated, implement the callback yourself', $level);
3166
			return '';
3167
		}
3168
		if ($method === 'enable_xml_dump')
3169
		{
3170
			$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
3171
			trigger_error('enable_xml_dump() has been deprecated, use get_raw_data() instead', $level);
3172
			return false;
3173
		}
3174
3175
		$class = get_class($this);
3176
		$trace = debug_backtrace();
3177
		$file = $trace[0]['file'];
3178
		$line = $trace[0]['line'];
3179
		trigger_error("Call to undefined method $class::$method() in $file on line $line", E_USER_ERROR);
3180
	}
3181
3182
	/**
3183
	 * Sorting callback for items
3184
	 *
3185
	 * @access private
3186
	 * @param SimplePie $a
3187
	 * @param SimplePie $b
3188
	 * @return boolean
3189
	 */
3190
	public static function sort_items($a, $b)
3191
	{
3192
		$a_date = $a->get_date('U');
0 ignored issues
show
Documentation Bug introduced by
The method get_date does not exist on object<SimplePie>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
3193
		$b_date = $b->get_date('U');
0 ignored issues
show
Documentation Bug introduced by
The method get_date does not exist on object<SimplePie>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
3194
		if ($a_date && $b_date) {
3195
			return $a_date > $b_date ? -1 : 1;
3196
		}
3197
		// Sort items without dates to the top.
3198
		if ($a_date) {
3199
			return 1;
3200
		}
3201
		if ($b_date) {
3202
			return -1;
3203
		}
3204
		return 0;
3205
	}
3206
3207
	/**
3208
	 * Merge items from several feeds into one
3209
	 *
3210
	 * If you're merging multiple feeds together, they need to all have dates
3211
	 * for the items or else SimplePie will refuse to sort them.
3212
	 *
3213
	 * @link http://simplepie.org/wiki/tutorial/sort_multiple_feeds_by_time_and_date#if_feeds_require_separate_per-feed_settings
3214
	 * @param array $urls List of SimplePie feed objects to merge
3215
	 * @param int $start Starting item
3216
	 * @param int $end Number of items to return
3217
	 * @param int $limit Maximum number of items per feed
3218
	 * @return array
3219
	 */
3220
	public static function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3221
	{
3222
		if (is_array($urls) && sizeof($urls) > 0)
3223
		{
3224
			$items = array();
3225
			foreach ($urls as $arg)
3226
			{
3227
				if ($arg instanceof SimplePie)
3228
				{
3229
					$items = array_merge($items, $arg->get_items(0, $limit));
3230
				}
3231
				else
3232
				{
3233
					trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3234
				}
3235
			}
3236
3237
			usort($items, array(get_class($urls[0]), 'sort_items'));
3238
3239
			if ($end === 0)
3240
			{
3241
				return array_slice($items, $start);
3242
			}
3243
			else
3244
			{
3245
				return array_slice($items, $start, $end);
3246
			}
3247
		}
3248
		else
3249
		{
3250
			trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3251
			return array();
3252
		}
3253
	}
3254
3255
	/**
3256
	 * Store PubSubHubbub links as headers
3257
	 *
3258
	 * There is no way to find PuSH links in the body of a microformats feed,
3259
	 * so they are added to the headers when found, to be used later by get_links.
3260
	 * @param SimplePie_File $file
3261
	 * @param string $hub
3262
	 * @param string $self
3263
	 */
3264
	private function store_links(&$file, $hub, $self) {
3265
		if (isset($file->headers['link']['hub']) ||
3266
			  (isset($file->headers['link']) &&
3267
			   preg_match('/rel=hub/', $file->headers['link'])))
3268
		{
3269
			return;
3270
		}
3271
3272
		if ($hub)
3273
		{
3274
			if (isset($file->headers['link']))
3275
			{
3276
				if ($file->headers['link'] !== '')
3277
				{
3278
					$file->headers['link'] = ', ';
3279
				}
3280
			}
3281
			else
3282
			{
3283
				$file->headers['link'] = '';
3284
			}
3285
			$file->headers['link'] .= '<'.$hub.'>; rel=hub';
3286
			if ($self)
3287
			{
3288
				$file->headers['link'] .= ', <'.$self.'>; rel=self';
3289
			}
3290
		}
3291
	}
3292
}
3293
3294
/**
3295
 * Manages all author-related data
3296
 *
3297
 * Used by {@see SimplePie_Item::get_author()} and {@see SimplePie::get_authors()}
3298
 *
3299
 * This class can be overloaded with {@see SimplePie::set_author_class()}
3300
 *
3301
 * @package SimplePie
3302
 * @subpackage API
3303
 */
3304
class SimplePie_Author
3305
{
3306
	/**
3307
	 * Author's name
3308
	 *
3309
	 * @var string
3310
	 * @see get_name()
3311
	 */
3312
	var $name;
3313
3314
	/**
3315
	 * Author's link
3316
	 *
3317
	 * @var string
3318
	 * @see get_link()
3319
	 */
3320
	var $link;
3321
3322
	/**
3323
	 * Author's email address
3324
	 *
3325
	 * @var string
3326
	 * @see get_email()
3327
	 */
3328
	var $email;
3329
3330
	/**
3331
	 * Constructor, used to input the data
3332
	 *
3333
	 * @param string $name
3334
	 * @param string $link
3335
	 * @param string $email
3336
	 */
3337
	public function __construct($name = null, $link = null, $email = null)
3338
	{
3339
		$this->name = $name;
3340
		$this->link = $link;
3341
		$this->email = $email;
3342
	}
3343
3344
	/**
3345
	 * String-ified version
3346
	 *
3347
	 * @return string
3348
	 */
3349
	public function __toString()
3350
	{
3351
		// There is no $this->data here
3352
		return md5(serialize($this));
3353
	}
3354
3355
	/**
3356
	 * Author's name
3357
	 *
3358
	 * @return string|null
3359
	 */
3360
	public function get_name()
3361
	{
3362
		if ($this->name !== null)
3363
		{
3364
			return $this->name;
3365
		}
3366
		else
3367
		{
3368
			return null;
3369
		}
3370
	}
3371
3372
	/**
3373
	 * Author's link
3374
	 *
3375
	 * @return string|null
3376
	 */
3377
	public function get_link()
3378
	{
3379
		if ($this->link !== null)
3380
		{
3381
			return $this->link;
3382
		}
3383
		else
3384
		{
3385
			return null;
3386
		}
3387
	}
3388
3389
	/**
3390
	 * Author's email address
3391
	 *
3392
	 * @return string|null
3393
	 */
3394
	public function get_email()
3395
	{
3396
		if ($this->email !== null)
3397
		{
3398
			return $this->email;
3399
		}
3400
		else
3401
		{
3402
			return null;
3403
		}
3404
	}
3405
}
3406
3407
/**
3408
 * Used to create cache objects
3409
 *
3410
 * This class can be overloaded with {@see SimplePie::set_cache_class()},
3411
 * although the preferred way is to create your own handler
3412
 * via {@see register()}
3413
 *
3414
 * @package SimplePie
3415
 * @subpackage Caching
3416
 */
3417
class SimplePie_Cache
3418
{
3419
	/**
3420
	 * Cache handler classes
3421
	 *
3422
	 * These receive 3 parameters to their constructor, as documented in
3423
	 * {@see register()}
3424
	 * @var array
3425
	 */
3426
	protected static $handlers = array(
3427
		'mysql'     => 'SimplePie_Cache_MySQL',
3428
		'memcache'  => 'SimplePie_Cache_Memcache',
3429
		'memcached' => 'SimplePie_Cache_Memcached',
3430
		'redis'     => 'SimplePie_Cache_Redis'
3431
	);
3432
3433
	/**
3434
	 * Don't call the constructor. Please.
3435
	 */
3436
	private function __construct() { }
3437
3438
	/**
3439
	 * Create a new SimplePie_Cache object
3440
	 *
3441
	 * @param string $location URL location (scheme is used to determine handler)
3442
	 * @param string $filename Unique identifier for cache object
3443
	 * @param string $extension 'spi' or 'spc'
3444
	 * @return SimplePie_Cache_Base Type of object depends on scheme of `$location`
3445
	 */
3446
	public static function get_handler($location, $filename, $extension)
3447
	{
3448
		$type = explode(':', $location, 2);
3449
		$type = $type[0];
3450
		if (!empty(self::$handlers[$type]))
3451
		{
3452
			$class = self::$handlers[$type];
3453
			return new $class($location, $filename, $extension);
3454
		}
3455
3456
		return new SimplePie_Cache_File($location, $filename, $extension);
3457
	}
3458
3459
	/**
3460
	 * Create a new SimplePie_Cache object
3461
	 *
3462
	 * @deprecated Use {@see get_handler} instead
3463
	 */
3464
	public function create($location, $filename, $extension)
3465
	{
3466
		trigger_error('Cache::create() has been replaced with Cache::get_handler(). Switch to the registry system to use this.', E_USER_DEPRECATED);
3467
		return self::get_handler($location, $filename, $extension);
3468
	}
3469
3470
	/**
3471
	 * Register a handler
3472
	 *
3473
	 * @param string $type DSN type to register for
3474
	 * @param string $class Name of handler class. Must implement SimplePie_Cache_Base
3475
	 */
3476
	public static function register($type, $class)
3477
	{
3478
		self::$handlers[$type] = $class;
3479
	}
3480
3481
	/**
3482
	 * Parse a URL into an array
3483
	 *
3484
	 * @param string $url
3485
	 * @return array
3486
	 */
3487
	public static function parse_URL($url)
3488
	{
3489
		$params = parse_url($url);
3490
		$params['extras'] = array();
3491
		if (isset($params['query']))
3492
		{
3493
			parse_str($params['query'], $params['extras']);
3494
		}
3495
		return $params;
3496
	}
3497
}
3498
3499
/**
3500
 * Base for cache objects
3501
 *
3502
 * Classes to be used with {@see SimplePie_Cache::register()} are expected
3503
 * to implement this interface.
3504
 *
3505
 * @package SimplePie
3506
 * @subpackage Caching
3507
 */
3508
interface SimplePie_Cache_Base
3509
{
3510
	/**
3511
	 * Feed cache type
3512
	 *
3513
	 * @var string
3514
	 */
3515
	const TYPE_FEED = 'spc';
3516
3517
	/**
3518
	 * Image cache type
3519
	 *
3520
	 * @var string
3521
	 */
3522
	const TYPE_IMAGE = 'spi';
3523
3524
	/**
3525
	 * Create a new cache object
3526
	 *
3527
	 * @param string $location Location string (from SimplePie::$cache_location)
3528
	 * @param string $name Unique ID for the cache
3529
	 * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data
3530
	 */
3531
	public function __construct($location, $name, $type);
3532
3533
	/**
3534
	 * Save data to the cache
3535
	 *
3536
	 * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property
3537
	 * @return bool Successfulness
3538
	 */
3539
	public function save($data);
3540
3541
	/**
3542
	 * Retrieve the data saved to the cache
3543
	 *
3544
	 * @return array Data for SimplePie::$data
3545
	 */
3546
	public function load();
3547
3548
	/**
3549
	 * Retrieve the last modified time for the cache
3550
	 *
3551
	 * @return int Timestamp
3552
	 */
3553
	public function mtime();
3554
3555
	/**
3556
	 * Set the last modified time to the current time
3557
	 *
3558
	 * @return bool Success status
3559
	 */
3560
	public function touch();
3561
3562
	/**
3563
	 * Remove the cache
3564
	 *
3565
	 * @return bool Success status
3566
	 */
3567
	public function unlink();
3568
}
3569
3570
/**
3571
 * Base class for database-based caches
3572
 *
3573
 * @package SimplePie
3574
 * @subpackage Caching
3575
 */
3576
abstract class SimplePie_Cache_DB implements SimplePie_Cache_Base
3577
{
3578
	/**
3579
	 * Helper for database conversion
3580
	 *
3581
	 * Converts a given {@see SimplePie} object into data to be stored
3582
	 *
3583
	 * @param SimplePie $data
3584
	 * @return array First item is the serialized data for storage, second item is the unique ID for this item
3585
	 */
3586
	protected static function prepare_simplepie_object_for_cache($data)
3587
	{
3588
		$items = $data->get_items();
3589
		$items_by_id = array();
3590
3591
		if (!empty($items))
3592
		{
3593
			foreach ($items as $item)
3594
			{
3595
				$items_by_id[$item->get_id()] = $item;
3596
			}
3597
3598
			if (count($items_by_id) !== count($items))
3599
			{
3600
				$items_by_id = array();
3601
				foreach ($items as $item)
3602
				{
3603
					$items_by_id[$item->get_id(true)] = $item;
3604
				}
3605
			}
3606
3607
			if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
3608
			{
3609
				$channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
3610
			}
3611
			elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
3612
			{
3613
				$channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
3614
			}
3615
			elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
3616
			{
3617
				$channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
3618
			}
3619
			elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
3620
			{
3621
				$channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
3622
			}
3623
			else
3624
			{
3625
				$channel = null;
3626
			}
3627
3628
			if ($channel !== null)
3629
			{
3630
				if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
3631
				{
3632
					unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
3633
				}
3634
				if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
3635
				{
3636
					unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
3637
				}
3638
				if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
3639
				{
3640
					unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
3641
				}
3642
				if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
3643
				{
3644
					unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
3645
				}
3646
				if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
3647
				{
3648
					unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
3649
				}
3650
			}
3651
			if (isset($data->data['items']))
3652
			{
3653
				unset($data->data['items']);
3654
			}
3655
			if (isset($data->data['ordered_items']))
3656
			{
3657
				unset($data->data['ordered_items']);
3658
			}
3659
		}
3660
		return array(serialize($data->data), $items_by_id);
3661
	}
3662
}
3663
3664
/**
3665
 * Caches data to the filesystem
3666
 *
3667
 * @package SimplePie
3668
 * @subpackage Caching
3669
 */
3670
class SimplePie_Cache_File implements SimplePie_Cache_Base
3671
{
3672
	/**
3673
	 * Location string
3674
	 *
3675
	 * @see SimplePie::$cache_location
3676
	 * @var string
3677
	 */
3678
	protected $location;
3679
3680
	/**
3681
	 * Filename
3682
	 *
3683
	 * @var string
3684
	 */
3685
	protected $filename;
3686
3687
	/**
3688
	 * File extension
3689
	 *
3690
	 * @var string
3691
	 */
3692
	protected $extension;
3693
3694
	/**
3695
	 * File path
3696
	 *
3697
	 * @var string
3698
	 */
3699
	protected $name;
3700
3701
	/**
3702
	 * Create a new cache object
3703
	 *
3704
	 * @param string $location Location string (from SimplePie::$cache_location)
3705
	 * @param string $name Unique ID for the cache
3706
	 * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data
3707
	 */
3708
	public function __construct($location, $name, $type)
3709
	{
3710
		$this->location = $location;
3711
		$this->filename = $name;
3712
		$this->extension = $type;
3713
		$this->name = "$this->location/$this->filename.$this->extension";
3714
	}
3715
3716
	/**
3717
	 * Save data to the cache
3718
	 *
3719
	 * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property
3720
	 * @return bool Successfulness
3721
	 */
3722
	public function save($data)
3723
	{
3724
		if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
3725
		{
3726
			if ($data instanceof SimplePie)
3727
			{
3728
				$data = $data->data;
3729
			}
3730
3731
			$data = serialize($data);
3732
			return (bool) file_put_contents($this->name, $data);
3733
		}
3734
		return false;
3735
	}
3736
3737
	/**
3738
	 * Retrieve the data saved to the cache
3739
	 *
3740
	 * @return array Data for SimplePie::$data
3741
	 */
3742
	public function load()
3743
	{
3744
		if (file_exists($this->name) && is_readable($this->name))
3745
		{
3746
			return unserialize(file_get_contents($this->name));
3747
		}
3748
		return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type declared by the interface SimplePie_Cache_Base::load of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
3749
	}
3750
3751
	/**
3752
	 * Retrieve the last modified time for the cache
3753
	 *
3754
	 * @return int Timestamp
3755
	 */
3756
	public function mtime()
3757
	{
3758
		return @filemtime($this->name);
3759
	}
3760
3761
	/**
3762
	 * Set the last modified time to the current time
3763
	 *
3764
	 * @return bool Success status
3765
	 */
3766
	public function touch()
3767
	{
3768
		return @touch($this->name);
3769
	}
3770
3771
	/**
3772
	 * Remove the cache
3773
	 *
3774
	 * @return bool Success status
3775
	 */
3776
	public function unlink()
3777
	{
3778
		if (file_exists($this->name))
3779
		{
3780
			return unlink($this->name);
3781
		}
3782
		return false;
3783
	}
3784
}
3785
3786
/**
3787
 * Caches data to memcache
3788
 *
3789
 * Registered for URLs with the "memcache" protocol
3790
 *
3791
 * For example, `memcache://localhost:11211/?timeout=3600&prefix=sp_` will
3792
 * connect to memcache on `localhost` on port 11211. All tables will be
3793
 * prefixed with `sp_` and data will expire after 3600 seconds
3794
 *
3795
 * @package SimplePie
3796
 * @subpackage Caching
3797
 * @uses Memcache
3798
 */
3799
class SimplePie_Cache_Memcache implements SimplePie_Cache_Base
3800
{
3801
	/**
3802
	 * Memcache instance
3803
	 *
3804
	 * @var Memcache
3805
	 */
3806
	protected $cache;
3807
3808
	/**
3809
	 * Options
3810
	 *
3811
	 * @var array
3812
	 */
3813
	protected $options;
3814
3815
	/**
3816
	 * Cache name
3817
	 *
3818
	 * @var string
3819
	 */
3820
	protected $name;
3821
3822
	/**
3823
	 * Create a new cache object
3824
	 *
3825
	 * @param string $location Location string (from SimplePie::$cache_location)
3826
	 * @param string $name Unique ID for the cache
3827
	 * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data
3828
	 */
3829
	public function __construct($location, $name, $type)
3830
	{
3831
		$this->options = array(
3832
			'host' => '127.0.0.1',
3833
			'port' => 11211,
3834
			'extras' => array(
3835
				'timeout' => 3600, // one hour
3836
				'prefix' => 'simplepie_',
3837
			),
3838
		);
3839
		$this->options = SimplePie_Misc::array_merge_recursive($this->options, SimplePie_Cache::parse_URL($location));
3840
3841
		$this->name = $this->options['extras']['prefix'] . md5("$name:$type");
3842
3843
		$this->cache = new Memcache();
3844
		$this->cache->addServer($this->options['host'], (int) $this->options['port']);
3845
	}
3846
3847
	/**
3848
	 * Save data to the cache
3849
	 *
3850
	 * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property
3851
	 * @return bool Successfulness
3852
	 */
3853
	public function save($data)
3854
	{
3855
		if ($data instanceof SimplePie)
3856
		{
3857
			$data = $data->data;
3858
		}
3859
		return $this->cache->set($this->name, serialize($data), MEMCACHE_COMPRESSED, (int) $this->options['extras']['timeout']);
3860
	}
3861
3862
	/**
3863
	 * Retrieve the data saved to the cache
3864
	 *
3865
	 * @return array Data for SimplePie::$data
3866
	 */
3867
	public function load()
3868
	{
3869
		$data = $this->cache->get($this->name);
3870
3871
		if ($data !== false)
3872
		{
3873
			return unserialize($data);
3874
		}
3875
		return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type declared by the interface SimplePie_Cache_Base::load of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
3876
	}
3877
3878
	/**
3879
	 * Retrieve the last modified time for the cache
3880
	 *
3881
	 * @return int Timestamp
3882
	 */
3883
	public function mtime()
3884
	{
3885
		$data = $this->cache->get($this->name);
3886
3887
		if ($data !== false)
3888
		{
3889
			// essentially ignore the mtime because Memcache expires on its own
3890
			return time();
3891
		}
3892
3893
		return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type declared by the interface SimplePie_Cache_Base::mtime of type integer.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
3894
	}
3895
3896
	/**
3897
	 * Set the last modified time to the current time
3898
	 *
3899
	 * @return bool Success status
3900
	 */
3901
	public function touch()
3902
	{
3903
		$data = $this->cache->get($this->name);
3904
3905
		if ($data !== false)
3906
		{
3907
			return $this->cache->set($this->name, $data, MEMCACHE_COMPRESSED, (int) $this->options['extras']['timeout']);
3908
		}
3909
3910
		return false;
3911
	}
3912
3913
	/**
3914
	 * Remove the cache
3915
	 *
3916
	 * @return bool Success status
3917
	 */
3918
	public function unlink()
3919
	{
3920
		return $this->cache->delete($this->name, 0);
3921
	}
3922
}
3923
3924
/**
3925
 * Caches data to memcached
3926
 *
3927
 * Registered for URLs with the "memcached" protocol
3928
 *
3929
 * For example, `memcached://localhost:11211/?timeout=3600&prefix=sp_` will
3930
 * connect to memcached on `localhost` on port 11211. All tables will be
3931
 * prefixed with `sp_` and data will expire after 3600 seconds
3932
 *
3933
 * @package    SimplePie
3934
 * @subpackage Caching
3935
 * @author     Paul L. McNeely
3936
 * @uses       Memcached
3937
 */
3938
class SimplePie_Cache_Memcached implements SimplePie_Cache_Base
3939
{
3940
    /**
3941
     * Memcached instance
3942
     * @var Memcached
3943
     */
3944
    protected $cache;
3945
3946
    /**
3947
     * Options
3948
     * @var array
3949
     */
3950
    protected $options;
3951
3952
    /**
3953
     * Cache name
3954
     * @var string
3955
     */
3956
    protected $name;
3957
3958
    /**
3959
     * Create a new cache object
3960
     * @param string $location Location string (from SimplePie::$cache_location)
3961
     * @param string $name     Unique ID for the cache
3962
     * @param string $type     Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data
3963
     */
3964
    public function __construct($location, $name, $type) {
3965
        $this->options = array(
3966
            'host'   => '127.0.0.1',
3967
            'port'   => 11211,
3968
            'extras' => array(
3969
                'timeout' => 3600, // one hour
3970
                'prefix'  => 'simplepie_',
3971
            ),
3972
        );
3973
        $this->options = SimplePie_Misc::array_merge_recursive($this->options, SimplePie_Cache::parse_URL($location));
3974
3975
        $this->name = $this->options['extras']['prefix'] . md5("$name:$type");
3976
3977
        $this->cache = new Memcached();
3978
        $this->cache->addServer($this->options['host'], (int)$this->options['port']);
3979
    }
3980
3981
    /**
3982
     * Save data to the cache
3983
     * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property
3984
     * @return bool Successfulness
3985
     */
3986
    public function save($data) {
3987
        if ($data instanceof SimplePie) {
3988
            $data = $data->data;
3989
        }
3990
3991
        return $this->setData(serialize($data));
3992
    }
3993
3994
    /**
3995
     * Retrieve the data saved to the cache
3996
     * @return array Data for SimplePie::$data
3997
     */
3998
    public function load() {
3999
        $data = $this->cache->get($this->name);
4000
4001
        if ($data !== false) {
4002
            return unserialize($data);
4003
        }
4004
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type declared by the interface SimplePie_Cache_Base::load of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
4005
    }
4006
4007
    /**
4008
     * Retrieve the last modified time for the cache
4009
     * @return int Timestamp
4010
     */
4011
    public function mtime() {
4012
        $data = $this->cache->get($this->name . '_mtime');
4013
        return (int) $data;
4014
    }
4015
4016
    /**
4017
     * Set the last modified time to the current time
4018
     * @return bool Success status
4019
     */
4020
    public function touch() {
4021
        $data = $this->cache->get($this->name);
4022
        return $this->setData($data);
4023
    }
4024
4025
    /**
4026
     * Remove the cache
4027
     * @return bool Success status
4028
     */
4029
    public function unlink() {
4030
        return $this->cache->delete($this->name, 0);
4031
    }
4032
4033
    /**
4034
     * Set the last modified time and data to Memcached
4035
     * @return bool Success status
4036
     */
4037
    private function setData($data) {
4038
4039
        if ($data !== false) {
4040
            $this->cache->set($this->name . '_mtime', time(), (int)$this->options['extras']['timeout']);
4041
            return $this->cache->set($this->name, $data, (int)$this->options['extras']['timeout']);
4042
        }
4043
4044
        return false;
4045
    }
4046
}
4047
4048
/**
4049
 * Caches data to a MySQL database
4050
 *
4051
 * Registered for URLs with the "mysql" protocol
4052
 *
4053
 * For example, `mysql://root:password@localhost:3306/mydb?prefix=sp_` will
4054
 * connect to the `mydb` database on `localhost` on port 3306, with the user
4055
 * `root` and the password `password`. All tables will be prefixed with `sp_`
4056
 *
4057
 * @package SimplePie
4058
 * @subpackage Caching
4059
 */
4060
class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
4061
{
4062
	/**
4063
	 * PDO instance
4064
	 *
4065
	 * @var PDO
4066
	 */
4067
	protected $mysql;
4068
4069
	/**
4070
	 * Options
4071
	 *
4072
	 * @var array
4073
	 */
4074
	protected $options;
4075
4076
	/**
4077
	 * Cache ID
4078
	 *
4079
	 * @var string
4080
	 */
4081
	protected $id;
4082
4083
	/**
4084
	 * Create a new cache object
4085
	 *
4086
	 * @param string $location Location string (from SimplePie::$cache_location)
4087
	 * @param string $name Unique ID for the cache
4088
	 * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data
4089
	 */
4090
	public function __construct($location, $name, $type)
4091
	{
4092
		$this->options = array(
4093
			'user' => null,
4094
			'pass' => null,
4095
			'host' => '127.0.0.1',
4096
			'port' => '3306',
4097
			'path' => '',
4098
			'extras' => array(
4099
				'prefix' => '',
4100
				'cache_purge_time' => 2592000
4101
			),
4102
		);
4103
		
4104
		$this->options = SimplePie_Misc::array_merge_recursive($this->options, SimplePie_Cache::parse_URL($location));
4105
4106
		// Path is prefixed with a "/"
4107
		$this->options['dbname'] = substr($this->options['path'], 1);
4108
4109
		try
4110
		{
4111
			$this->mysql = new PDO("mysql:dbname={$this->options['dbname']};host={$this->options['host']};port={$this->options['port']}", $this->options['user'], $this->options['pass'], array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
4112
		}
4113
		catch (PDOException $e)
4114
		{
4115
			$this->mysql = null;
4116
			return;
4117
		}
4118
4119
		$this->id = $name . $type;
4120
4121
		if (!$query = $this->mysql->query('SHOW TABLES'))
4122
		{
4123
			$this->mysql = null;
4124
			return;
4125
		}
4126
4127
		$db = array();
4128
		while ($row = $query->fetchColumn())
4129
		{
4130
			$db[] = $row;
4131
		}
4132
4133
		if (!in_array($this->options['extras']['prefix'] . 'cache_data', $db))
4134
		{
4135
			$query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'cache_data` (`id` TEXT CHARACTER SET utf8 NOT NULL, `items` SMALLINT NOT NULL DEFAULT 0, `data` BLOB NOT NULL, `mtime` INT UNSIGNED NOT NULL, UNIQUE (`id`(125)))');
4136
			if ($query === false)
4137
			{
4138
				trigger_error("Can't create " . $this->options['extras']['prefix'] . "cache_data table, check permissions", E_USER_WARNING);
4139
				$this->mysql = null;
4140
				return;
4141
			}
4142
		}
4143
4144
		if (!in_array($this->options['extras']['prefix'] . 'items', $db))
4145
		{
4146
			$query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'items` (`feed_id` TEXT CHARACTER SET utf8 NOT NULL, `id` TEXT CHARACTER SET utf8 NOT NULL, `data` MEDIUMBLOB NOT NULL, `posted` INT UNSIGNED NOT NULL, INDEX `feed_id` (`feed_id`(125)))');
4147
			if ($query === false)
4148
			{
4149
				trigger_error("Can't create " . $this->options['extras']['prefix'] . "items table, check permissions", E_USER_WARNING);
4150
				$this->mysql = null;
4151
				return;
4152
			}
4153
		}
4154
	}
4155
4156
	/**
4157
	 * Save data to the cache
4158
	 *
4159
	 * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property
4160
	 * @return bool Successfulness
4161
	 */
4162
	public function save($data)
4163
	{
4164
		if ($this->mysql === null)
4165
		{
4166
			return false;
4167
		}
4168
4169
		$query = $this->mysql->prepare('DELETE i, cd FROM `' . $this->options['extras']['prefix'] . 'cache_data` cd, ' .
4170
			'`' . $this->options['extras']['prefix'] . 'items` i ' .
4171
			'WHERE cd.id = i.feed_id ' .
4172
			'AND cd.mtime < (unix_timestamp() - :purge_time)');
4173
		$query->bindValue(':purge_time', $this->options['extras']['cache_purge_time']);
4174
4175
		if (!$query->execute())
4176
		{
4177
			return false;
4178
		}
4179
4180
		if ($data instanceof SimplePie)
4181
		{
4182
			$data = clone $data;
4183
4184
			$prepared = self::prepare_simplepie_object_for_cache($data);
4185
4186
			$query = $this->mysql->prepare('SELECT COUNT(*) FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :feed');
4187
			$query->bindValue(':feed', $this->id);
4188
			if ($query->execute())
4189
			{
4190
				if ($query->fetchColumn() > 0)
4191
				{
4192
					$items = count($prepared[1]);
4193
					if ($items)
4194
					{
4195
						$sql = 'UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `items` = :items, `data` = :data, `mtime` = :time WHERE `id` = :feed';
4196
						$query = $this->mysql->prepare($sql);
4197
						$query->bindValue(':items', $items);
4198
					}
4199
					else
4200
					{
4201
						$sql = 'UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `data` = :data, `mtime` = :time WHERE `id` = :feed';
4202
						$query = $this->mysql->prepare($sql);
4203
					}
4204
4205
					$query->bindValue(':data', $prepared[0]);
4206
					$query->bindValue(':time', time());
4207
					$query->bindValue(':feed', $this->id);
4208
					if (!$query->execute())
4209
					{
4210
						return false;
4211
					}
4212
				}
4213
				else
4214
				{
4215
					$query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(:feed, :count, :data, :time)');
4216
					$query->bindValue(':feed', $this->id);
4217
					$query->bindValue(':count', count($prepared[1]));
4218
					$query->bindValue(':data', $prepared[0]);
4219
					$query->bindValue(':time', time());
4220
					if (!$query->execute())
4221
					{
4222
						return false;
4223
					}
4224
				}
4225
4226
				$ids = array_keys($prepared[1]);
4227
				if (!empty($ids))
4228
				{
4229
					foreach ($ids as $id)
4230
					{
4231
						$database_ids[] = $this->mysql->quote($id);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$database_ids was never initialized. Although not strictly required by PHP, it is generally a good practice to add $database_ids = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
4232
					}
4233
4234
					$query = $this->mysql->prepare('SELECT `id` FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `id` = ' . implode(' OR `id` = ', $database_ids) . ' AND `feed_id` = :feed');
0 ignored issues
show
Bug introduced by
The variable $database_ids does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
4235
					$query->bindValue(':feed', $this->id);
4236
4237
					if ($query->execute())
4238
					{
4239
						$existing_ids = array();
4240
						while ($row = $query->fetchColumn())
4241
						{
4242
							$existing_ids[] = $row;
4243
						}
4244
4245
						$new_ids = array_diff($ids, $existing_ids);
4246
4247
						foreach ($new_ids as $new_id)
4248
						{
4249
							if (!($date = $prepared[1][$new_id]->get_date('U')))
4250
							{
4251
								$date = time();
4252
							}
4253
4254
							$query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'items` (`feed_id`, `id`, `data`, `posted`) VALUES(:feed, :id, :data, :date)');
4255
							$query->bindValue(':feed', $this->id);
4256
							$query->bindValue(':id', $new_id);
4257
							$query->bindValue(':data', serialize($prepared[1][$new_id]->data));
4258
							$query->bindValue(':date', $date);
4259
							if (!$query->execute())
4260
							{
4261
								return false;
4262
							}
4263
						}
4264
						return true;
4265
					}
4266
				}
4267
				else
4268
				{
4269
					return true;
4270
				}
4271
			}
4272
		}
4273
		else
4274
		{
4275
			$query = $this->mysql->prepare('SELECT `id` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :feed');
4276
			$query->bindValue(':feed', $this->id);
4277
			if ($query->execute())
4278
			{
4279
				if ($query->rowCount() > 0)
4280
				{
4281
					$query = $this->mysql->prepare('UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `items` = 0, `data` = :data, `mtime` = :time WHERE `id` = :feed');
4282
					$query->bindValue(':data', serialize($data));
4283
					$query->bindValue(':time', time());
4284
					$query->bindValue(':feed', $this->id);
4285
					if ($this->execute())
0 ignored issues
show
Bug introduced by
The method execute() does not seem to exist on object<SimplePie_Cache_MySQL>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
4286
					{
4287
						return true;
4288
					}
4289
				}
4290
				else
4291
				{
4292
					$query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(:id, 0, :data, :time)');
4293
					$query->bindValue(':id', $this->id);
4294
					$query->bindValue(':data', serialize($data));
4295
					$query->bindValue(':time', time());
4296
					if ($query->execute())
4297
					{
4298
						return true;
4299
					}
4300
				}
4301
			}
4302
		}
4303
		return false;
4304
	}
4305
4306
	/**
4307
	 * Retrieve the data saved to the cache
4308
	 *
4309
	 * @return array Data for SimplePie::$data
4310
	 */
4311
	public function load()
4312
	{
4313
		if ($this->mysql === null)
4314
		{
4315
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type declared by the interface SimplePie_Cache_Base::load of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
4316
		}
4317
4318
		$query = $this->mysql->prepare('SELECT `items`, `data` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id');
4319
		$query->bindValue(':id', $this->id);
4320
		if ($query->execute() && ($row = $query->fetch()))
4321
		{
4322
			$data = unserialize($row[1]);
4323
4324
			if (isset($this->options['items'][0]))
4325
			{
4326
				$items = (int) $this->options['items'][0];
4327
			}
4328
			else
4329
			{
4330
				$items = (int) $row[0];
4331
			}
4332
4333
			if ($items !== 0)
4334
			{
4335
				if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
4336
				{
4337
					$feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
4338
				}
4339
				elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
4340
				{
4341
					$feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
4342
				}
4343
				elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
4344
				{
4345
					$feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
4346
				}
4347
				elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
4348
				{
4349
					$feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
4350
				}
4351
				else
4352
				{
4353
					$feed = null;
4354
				}
4355
4356
				if ($feed !== null)
4357
				{
4358
					$sql = 'SELECT `data` FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `feed_id` = :feed ORDER BY `posted` DESC';
4359
					if ($items > 0)
4360
					{
4361
						$sql .= ' LIMIT ' . $items;
4362
					}
4363
4364
					$query = $this->mysql->prepare($sql);
4365
					$query->bindValue(':feed', $this->id);
4366
					if ($query->execute())
4367
					{
4368
						while ($row = $query->fetchColumn())
4369
						{
4370
							$feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row);
4371
						}
4372
					}
4373
					else
4374
					{
4375
						return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type declared by the interface SimplePie_Cache_Base::load of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
4376
					}
4377
				}
4378
			}
4379
			return $data;
4380
		}
4381
		return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type declared by the interface SimplePie_Cache_Base::load of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
4382
	}
4383
4384
	/**
4385
	 * Retrieve the last modified time for the cache
4386
	 *
4387
	 * @return int Timestamp
4388
	 */
4389
	public function mtime()
4390
	{
4391
		if ($this->mysql === null)
4392
		{
4393
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type declared by the interface SimplePie_Cache_Base::mtime of type integer.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
4394
		}
4395
4396
		$query = $this->mysql->prepare('SELECT `mtime` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id');
4397
		$query->bindValue(':id', $this->id);
4398
		if ($query->execute() && ($time = $query->fetchColumn()))
4399
		{
4400
			return $time;
4401
		}
4402
		else
4403
		{
4404
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type declared by the interface SimplePie_Cache_Base::mtime of type integer.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
4405
		}
4406
	}
4407
4408
	/**
4409
	 * Set the last modified time to the current time
4410
	 *
4411
	 * @return bool Success status
4412
	 */
4413
	public function touch()
4414
	{
4415
		if ($this->mysql === null)
4416
		{
4417
			return false;
4418
		}
4419
4420
		$query = $this->mysql->prepare('UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `mtime` = :time WHERE `id` = :id');
4421
		$query->bindValue(':time', time());
4422
		$query->bindValue(':id', $this->id);
4423
		if ($query->execute() && $query->rowCount() > 0)
4424
		{
4425
			return true;
4426
		}
4427
		else
4428
		{
4429
			return false;
4430
		}
4431
	}
4432
4433
	/**
4434
	 * Remove the cache
4435
	 *
4436
	 * @return bool Success status
4437
	 */
4438
	public function unlink()
4439
	{
4440
		if ($this->mysql === null)
4441
		{
4442
			return false;
4443
		}
4444
4445
		$query = $this->mysql->prepare('DELETE FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id');
4446
		$query->bindValue(':id', $this->id);
4447
		$query2 = $this->mysql->prepare('DELETE FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `feed_id` = :id');
4448
		$query2->bindValue(':id', $this->id);
4449
		if ($query->execute() && $query2->execute())
4450
		{
4451
			return true;
4452
		}
4453
		else
4454
		{
4455
			return false;
4456
		}
4457
	}
4458
}
4459
4460
/**
4461
 * Caches data to redis
4462
 *
4463
 * Registered for URLs with the "redis" protocol
4464
 *
4465
 * For example, `redis://localhost:6379/?timeout=3600&prefix=sp_&dbIndex=0` will
4466
 * connect to redis on `localhost` on port 6379. All tables will be
4467
 * prefixed with `simple_primary-` and data will expire after 3600 seconds
4468
 *
4469
 * @package SimplePie
4470
 * @subpackage Caching
4471
 * @uses Redis
4472
 */
4473
class SimplePie_Cache_Redis implements SimplePie_Cache_Base {
4474
    /**
4475
     * Redis instance
4476
     *
4477
     * @var \Redis
4478
     */
4479
    protected $cache;
4480
4481
    /**
4482
     * Options
4483
     *
4484
     * @var array
4485
     */
4486
    protected $options;
4487
4488
    /**
4489
     * Cache name
4490
     *
4491
     * @var string
4492
     */
4493
    protected $name;
4494
4495
    /**
4496
     * Cache Data
4497
     *
4498
     * @var type
4499
     */
4500
    protected $data;
4501
4502
    /**
4503
     * Create a new cache object
4504
     *
4505
     * @param string $location Location string (from SimplePie::$cache_location)
4506
     * @param string $name Unique ID for the cache
4507
     * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data
0 ignored issues
show
Bug introduced by
There is no parameter named $type. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
4508
     */
4509
    public function __construct($location, $name, $options = null) {
4510
        //$this->cache = \flow\simple\cache\Redis::getRedisClientInstance();
4511
        $parsed = SimplePie_Cache::parse_URL($location);
4512
        $redis = new Redis();
4513
        $redis->connect($parsed['host'], $parsed['port']);
4514
        $this->cache = $redis;
4515
4516
        if (!is_null($options) && is_array($options)) {
4517
            $this->options = $options;
4518
        } else {
4519
            $this->options = array (
4520
                'prefix' => 'rss:simple_primary:',
4521
                'expire' => 0,
4522
            );
4523
        }
4524
4525
        $this->name = $this->options['prefix'] . $name;
4526
    }
4527
4528
    /**
4529
     * @param \Redis $cache
4530
     */
4531
    public function setRedisClient(\Redis $cache) {
4532
        $this->cache = $cache;
4533
    }
4534
4535
    /**
4536
     * Save data to the cache
4537
     *
4538
     * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property
4539
     * @return bool Successfulness
4540
     */
4541
    public function save($data) {
4542
        if ($data instanceof SimplePie) {
4543
            $data = $data->data;
4544
        }
4545
        $response = $this->cache->set($this->name, serialize($data));
4546
        if ($this->options['expire']) {
4547
            $this->cache->expire($this->name, $this->options['expire']);
4548
        }
4549
4550
        return $response;
4551
    }
4552
4553
    /**
4554
     * Retrieve the data saved to the cache
4555
     *
4556
     * @return array Data for SimplePie::$data
4557
     */
4558
    public function load() {
4559
        $data = $this->cache->get($this->name);
4560
4561
        if ($data !== false) {
4562
            return unserialize($data);
4563
        }
4564
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type declared by the interface SimplePie_Cache_Base::load of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
4565
    }
4566
4567
    /**
4568
     * Retrieve the last modified time for the cache
4569
     *
4570
     * @return int Timestamp
4571
     */
4572
    public function mtime() {
4573
4574
        $data = $this->cache->get($this->name);
4575
4576
        if ($data !== false) {
4577
            return time();
4578
        }
4579
4580
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type declared by the interface SimplePie_Cache_Base::mtime of type integer.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
4581
    }
4582
4583
    /**
4584
     * Set the last modified time to the current time
4585
     *
4586
     * @return bool Success status
4587
     */
4588
    public function touch() {
4589
4590
        $data = $this->cache->get($this->name);
4591
4592
        if ($data !== false) {
4593
            $return = $this->cache->set($this->name, $data);
4594
            if ($this->options['expire']) {
4595
                return $this->cache->expire($this->name, $this->ttl);
0 ignored issues
show
Bug introduced by
The property ttl does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
4596
            }
4597
            return $return;
4598
        }
4599
4600
        return false;
4601
    }
4602
4603
    /**
4604
     * Remove the cache
4605
     *
4606
     * @return bool Success status
4607
     */
4608
    public function unlink() {
4609
        return $this->cache->set($this->name, null);
4610
    }
4611
4612
}
4613
4614
/**
4615
 * Handles `<media:text>` captions as defined in Media RSS.
4616
 *
4617
 * Used by {@see SimplePie_Enclosure::get_caption()} and {@see SimplePie_Enclosure::get_captions()}
4618
 *
4619
 * This class can be overloaded with {@see SimplePie::set_caption_class()}
4620
 *
4621
 * @package SimplePie
4622
 * @subpackage API
4623
 */
4624
class SimplePie_Caption
4625
{
4626
	/**
4627
	 * Content type
4628
	 *
4629
	 * @var string
4630
	 * @see get_type()
4631
	 */
4632
	var $type;
4633
4634
	/**
4635
	 * Language
4636
	 *
4637
	 * @var string
4638
	 * @see get_language()
4639
	 */
4640
	var $lang;
4641
4642
	/**
4643
	 * Start time
4644
	 *
4645
	 * @var string
4646
	 * @see get_starttime()
4647
	 */
4648
	var $startTime;
4649
4650
	/**
4651
	 * End time
4652
	 *
4653
	 * @var string
4654
	 * @see get_endtime()
4655
	 */
4656
	var $endTime;
4657
4658
	/**
4659
	 * Caption text
4660
	 *
4661
	 * @var string
4662
	 * @see get_text()
4663
	 */
4664
	var $text;
4665
4666
	/**
4667
	 * Constructor, used to input the data
4668
	 *
4669
	 * For documentation on all the parameters, see the corresponding
4670
	 * properties and their accessors
4671
	 */
4672
	public function __construct($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
4673
	{
4674
		$this->type = $type;
4675
		$this->lang = $lang;
4676
		$this->startTime = $startTime;
4677
		$this->endTime = $endTime;
4678
		$this->text = $text;
4679
	}
4680
4681
	/**
4682
	 * String-ified version
4683
	 *
4684
	 * @return string
4685
	 */
4686
	public function __toString()
4687
	{
4688
		// There is no $this->data here
4689
		return md5(serialize($this));
4690
	}
4691
4692
	/**
4693
	 * Get the end time
4694
	 *
4695
	 * @return string|null Time in the format 'hh:mm:ss.SSS'
4696
	 */
4697
	public function get_endtime()
4698
	{
4699
		if ($this->endTime !== null)
4700
		{
4701
			return $this->endTime;
4702
		}
4703
		else
4704
		{
4705
			return null;
4706
		}
4707
	}
4708
4709
	/**
4710
	 * Get the language
4711
	 *
4712
	 * @link http://tools.ietf.org/html/rfc3066
4713
	 * @return string|null Language code as per RFC 3066
4714
	 */
4715
	public function get_language()
4716
	{
4717
		if ($this->lang !== null)
4718
		{
4719
			return $this->lang;
4720
		}
4721
		else
4722
		{
4723
			return null;
4724
		}
4725
	}
4726
4727
	/**
4728
	 * Get the start time
4729
	 *
4730
	 * @return string|null Time in the format 'hh:mm:ss.SSS'
4731
	 */
4732
	public function get_starttime()
4733
	{
4734
		if ($this->startTime !== null)
4735
		{
4736
			return $this->startTime;
4737
		}
4738
		else
4739
		{
4740
			return null;
4741
		}
4742
	}
4743
4744
	/**
4745
	 * Get the text of the caption
4746
	 *
4747
	 * @return string|null
4748
	 */
4749
	public function get_text()
4750
	{
4751
		if ($this->text !== null)
4752
		{
4753
			return $this->text;
4754
		}
4755
		else
4756
		{
4757
			return null;
4758
		}
4759
	}
4760
4761
	/**
4762
	 * Get the content type (not MIME type)
4763
	 *
4764
	 * @return string|null Either 'text' or 'html'
4765
	 */
4766
	public function get_type()
4767
	{
4768
		if ($this->type !== null)
4769
		{
4770
			return $this->type;
4771
		}
4772
		else
4773
		{
4774
			return null;
4775
		}
4776
	}
4777
}
4778
4779
/**
4780
 * Manages all category-related data
4781
 *
4782
 * Used by {@see SimplePie_Item::get_category()} and {@see SimplePie_Item::get_categories()}
4783
 *
4784
 * This class can be overloaded with {@see SimplePie::set_category_class()}
4785
 *
4786
 * @package SimplePie
4787
 * @subpackage API
4788
 */
4789
class SimplePie_Category
4790
{
4791
	/**
4792
	 * Category identifier
4793
	 *
4794
	 * @var string|null
4795
	 * @see get_term
4796
	 */
4797
	var $term;
4798
4799
	/**
4800
	 * Categorization scheme identifier
4801
	 *
4802
	 * @var string|null
4803
	 * @see get_scheme()
4804
	 */
4805
	var $scheme;
4806
4807
	/**
4808
	 * Human readable label
4809
	 *
4810
	 * @var string|null
4811
	 * @see get_label()
4812
	 */
4813
	var $label;
4814
4815
	/**
4816
	 * Category type
4817
	 * 
4818
	 * category for <category>
4819
	 * subject for <dc:subject>
4820
	 *
4821
	 * @var string|null
4822
	 * @see get_type()
4823
	 */
4824
	var $type;
4825
4826
	/**
4827
	 * Constructor, used to input the data
4828
	 *
4829
	 * @param string|null $term
4830
	 * @param string|null $scheme
4831
	 * @param string|null $label
4832
	 * @param string|null $type
4833
	 */
4834
	public function __construct($term = null, $scheme = null, $label = null, $type = null)
4835
	{
4836
		$this->term = $term;
4837
		$this->scheme = $scheme;
4838
		$this->label = $label;
4839
		$this->type = $type;
4840
	}
4841
4842
	/**
4843
	 * String-ified version
4844
	 *
4845
	 * @return string
4846
	 */
4847
	public function __toString()
4848
	{
4849
		// There is no $this->data here
4850
		return md5(serialize($this));
4851
	}
4852
4853
	/**
4854
	 * Get the category identifier
4855
	 *
4856
	 * @return string|null
4857
	 */
4858
	public function get_term()
4859
	{
4860
		return $this->term;
4861
	}
4862
4863
	/**
4864
	 * Get the categorization scheme identifier
4865
	 *
4866
	 * @return string|null
4867
	 */
4868
	public function get_scheme()
4869
	{
4870
		return $this->scheme;
4871
	}
4872
4873
	/**
4874
	 * Get the human readable label
4875
	 *
4876
	 * @param bool $strict
4877
	 * @return string|null
4878
	 */
4879
	public function get_label($strict = false)
4880
	{
4881
		if ($this->label === null && $strict !== true)
4882
		{
4883
			return $this->get_term();
4884
		}
4885
		return $this->label;
4886
	}
4887
4888
	/**
4889
	 * Get the category type
4890
	 *
4891
	 * @return string|null
4892
	 */
4893
	public function get_type()
4894
	{
4895
		return $this->type;
4896
	}
4897
}
4898
4899
/**
4900
 * Content-type sniffing
4901
 *
4902
 * Based on the rules in http://tools.ietf.org/html/draft-abarth-mime-sniff-06
4903
 *
4904
 * This is used since we can't always trust Content-Type headers, and is based
4905
 * upon the HTML5 parsing rules.
4906
 *
4907
 *
4908
 * This class can be overloaded with {@see SimplePie::set_content_type_sniffer_class()}
4909
 *
4910
 * @package SimplePie
4911
 * @subpackage HTTP
4912
 */
4913
class SimplePie_Content_Type_Sniffer
4914
{
4915
	/**
4916
	 * File object
4917
	 *
4918
	 * @var SimplePie_File
4919
	 */
4920
	var $file;
4921
4922
	/**
4923
	 * Create an instance of the class with the input file
4924
	 *
4925
	 * @param SimplePie_Content_Type_Sniffer $file Input file
4926
	 */
4927
	public function __construct($file)
4928
	{
4929
		$this->file = $file;
0 ignored issues
show
Documentation Bug introduced by
It seems like $file of type object<SimplePie_Content_Type_Sniffer> is incompatible with the declared type object<SimplePie_File> of property $file.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
4930
	}
4931
4932
	/**
4933
	 * Get the Content-Type of the specified file
4934
	 *
4935
	 * @return string Actual Content-Type
4936
	 */
4937
	public function get_type()
4938
	{
4939
		if (isset($this->file->headers['content-type']))
4940
		{
4941
			if (!isset($this->file->headers['content-encoding'])
4942
				&& ($this->file->headers['content-type'] === 'text/plain'
4943
					|| $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
4944
					|| $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'
4945
					|| $this->file->headers['content-type'] === 'text/plain; charset=UTF-8'))
4946
			{
4947
				return $this->text_or_binary();
4948
			}
4949
4950
			if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
4951
			{
4952
				$official = substr($this->file->headers['content-type'], 0, $pos);
4953
			}
4954
			else
4955
			{
4956
				$official = $this->file->headers['content-type'];
4957
			}
4958
			$official = trim(strtolower($official));
4959
4960
			if ($official === 'unknown/unknown'
4961
				|| $official === 'application/unknown')
4962
			{
4963
				return $this->unknown();
4964
			}
4965
			elseif (substr($official, -4) === '+xml'
4966
				|| $official === 'text/xml'
4967
				|| $official === 'application/xml')
4968
			{
4969
				return $official;
4970
			}
4971
			elseif (substr($official, 0, 6) === 'image/')
4972
			{
4973
				if ($return = $this->image())
4974
				{
4975
					return $return;
4976
				}
4977
				else
4978
				{
4979
					return $official;
4980
				}
4981
			}
4982
			elseif ($official === 'text/html')
4983
			{
4984
				return $this->feed_or_html();
4985
			}
4986
			else
4987
			{
4988
				return $official;
4989
			}
4990
		}
4991
		else
4992
		{
4993
			return $this->unknown();
4994
		}
4995
	}
4996
4997
	/**
4998
	 * Sniff text or binary
4999
	 *
5000
	 * @return string Actual Content-Type
5001
	 */
5002
	public function text_or_binary()
5003
	{
5004
		if (substr($this->file->body, 0, 2) === "\xFE\xFF"
5005
			|| substr($this->file->body, 0, 2) === "\xFF\xFE"
5006
			|| substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
5007
			|| substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
5008
		{
5009
			return 'text/plain';
5010
		}
5011
		elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
5012
		{
5013
			return 'application/octect-stream';
5014
		}
5015
		else
5016
		{
5017
			return 'text/plain';
5018
		}
5019
	}
5020
5021
	/**
5022
	 * Sniff unknown
5023
	 *
5024
	 * @return string Actual Content-Type
5025
	 */
5026
	public function unknown()
5027
	{
5028
		$ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
5029
		if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
5030
			|| strtolower(substr($this->file->body, $ws, 5)) === '<html'
5031
			|| strtolower(substr($this->file->body, $ws, 7)) === '<script')
5032
		{
5033
			return 'text/html';
5034
		}
5035
		elseif (substr($this->file->body, 0, 5) === '%PDF-')
5036
		{
5037
			return 'application/pdf';
5038
		}
5039
		elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
5040
		{
5041
			return 'application/postscript';
5042
		}
5043
		elseif (substr($this->file->body, 0, 6) === 'GIF87a'
5044
			|| substr($this->file->body, 0, 6) === 'GIF89a')
5045
		{
5046
			return 'image/gif';
5047
		}
5048
		elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
5049
		{
5050
			return 'image/png';
5051
		}
5052
		elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
5053
		{
5054
			return 'image/jpeg';
5055
		}
5056
		elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
5057
		{
5058
			return 'image/bmp';
5059
		}
5060
		elseif (substr($this->file->body, 0, 4) === "\x00\x00\x01\x00")
5061
		{
5062
			return 'image/vnd.microsoft.icon';
5063
		}
5064
		else
5065
		{
5066
			return $this->text_or_binary();
5067
		}
5068
	}
5069
5070
	/**
5071
	 * Sniff images
5072
	 *
5073
	 * @return string Actual Content-Type
5074
	 */
5075
	public function image()
5076
	{
5077
		if (substr($this->file->body, 0, 6) === 'GIF87a'
5078
			|| substr($this->file->body, 0, 6) === 'GIF89a')
5079
		{
5080
			return 'image/gif';
5081
		}
5082
		elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
5083
		{
5084
			return 'image/png';
5085
		}
5086
		elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
5087
		{
5088
			return 'image/jpeg';
5089
		}
5090
		elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
5091
		{
5092
			return 'image/bmp';
5093
		}
5094
		elseif (substr($this->file->body, 0, 4) === "\x00\x00\x01\x00")
5095
		{
5096
			return 'image/vnd.microsoft.icon';
5097
		}
5098
		else
5099
		{
5100
			return false;
5101
		}
5102
	}
5103
5104
	/**
5105
	 * Sniff HTML
5106
	 *
5107
	 * @return string Actual Content-Type
5108
	 */
5109
	public function feed_or_html()
5110
	{
5111
		$len = strlen($this->file->body);
5112
		$pos = strspn($this->file->body, "\x09\x0A\x0D\x20\xEF\xBB\xBF");
5113
5114
		while ($pos < $len)
5115
		{
5116
			switch ($this->file->body[$pos])
5117
			{
5118
				case "\x09":
5119
				case "\x0A":
5120
				case "\x0D":
5121
				case "\x20":
5122
					$pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
5123
					continue 2;
5124
5125
				case '<':
5126
					$pos++;
5127
					break;
5128
5129
				default:
5130
					return 'text/html';
5131
			}
5132
5133
			if (substr($this->file->body, $pos, 3) === '!--')
5134
			{
5135
				$pos += 3;
5136
				if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
5137
				{
5138
					$pos += 3;
5139
				}
5140
				else
5141
				{
5142
					return 'text/html';
5143
				}
5144
			}
5145
			elseif (substr($this->file->body, $pos, 1) === '!')
5146
			{
5147
				if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
5148
				{
5149
					$pos++;
5150
				}
5151
				else
5152
				{
5153
					return 'text/html';
5154
				}
5155
			}
5156
			elseif (substr($this->file->body, $pos, 1) === '?')
5157
			{
5158
				if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
5159
				{
5160
					$pos += 2;
5161
				}
5162
				else
5163
				{
5164
					return 'text/html';
5165
				}
5166
			}
5167
			elseif (substr($this->file->body, $pos, 3) === 'rss'
5168
				|| substr($this->file->body, $pos, 7) === 'rdf:RDF')
5169
			{
5170
				return 'application/rss+xml';
5171
			}
5172
			elseif (substr($this->file->body, $pos, 4) === 'feed')
5173
			{
5174
				return 'application/atom+xml';
5175
			}
5176
			else
5177
			{
5178
				return 'text/html';
5179
			}
5180
		}
5181
5182
		return 'text/html';
5183
	}
5184
}
5185
5186
/**
5187
 * Manages `<media:copyright>` copyright tags as defined in Media RSS
5188
 *
5189
 * Used by {@see SimplePie_Enclosure::get_copyright()}
5190
 *
5191
 * This class can be overloaded with {@see SimplePie::set_copyright_class()}
5192
 *
5193
 * @package SimplePie
5194
 * @subpackage API
5195
 */
5196
class SimplePie_Copyright
5197
{
5198
	/**
5199
	 * Copyright URL
5200
	 *
5201
	 * @var string
5202
	 * @see get_url()
5203
	 */
5204
	var $url;
5205
5206
	/**
5207
	 * Attribution
5208
	 *
5209
	 * @var string
5210
	 * @see get_attribution()
5211
	 */
5212
	var $label;
5213
5214
	/**
5215
	 * Constructor, used to input the data
5216
	 *
5217
	 * For documentation on all the parameters, see the corresponding
5218
	 * properties and their accessors
5219
	 */
5220
	public function __construct($url = null, $label = null)
5221
	{
5222
		$this->url = $url;
5223
		$this->label = $label;
5224
	}
5225
5226
	/**
5227
	 * String-ified version
5228
	 *
5229
	 * @return string
5230
	 */
5231
	public function __toString()
5232
	{
5233
		// There is no $this->data here
5234
		return md5(serialize($this));
5235
	}
5236
5237
	/**
5238
	 * Get the copyright URL
5239
	 *
5240
	 * @return string|null URL to copyright information
5241
	 */
5242
	public function get_url()
5243
	{
5244
		if ($this->url !== null)
5245
		{
5246
			return $this->url;
5247
		}
5248
		else
5249
		{
5250
			return null;
5251
		}
5252
	}
5253
5254
	/**
5255
	 * Get the attribution text
5256
	 *
5257
	 * @return string|null
5258
	 */
5259
	public function get_attribution()
5260
	{
5261
		if ($this->label !== null)
5262
		{
5263
			return $this->label;
5264
		}
5265
		else
5266
		{
5267
			return null;
5268
		}
5269
	}
5270
}
5271
5272
/**
5273
 * SimplePie class.
5274
 *
5275
 * Class for backward compatibility.
5276
 *
5277
 * @deprecated Use {@see SimplePie} directly
5278
 * @package SimplePie
5279
 * @subpackage API
5280
 */
5281
class SimplePie_Core extends SimplePie
5282
{
5283
5284
}
5285
5286
/**
5287
 * Handles `<media:credit>` as defined in Media RSS
5288
 *
5289
 * Used by {@see SimplePie_Enclosure::get_credit()} and {@see SimplePie_Enclosure::get_credits()}
5290
 *
5291
 * This class can be overloaded with {@see SimplePie::set_credit_class()}
5292
 *
5293
 * @package SimplePie
5294
 * @subpackage API
5295
 */
5296
class SimplePie_Credit
5297
{
5298
	/**
5299
	 * Credited role
5300
	 *
5301
	 * @var string
5302
	 * @see get_role()
5303
	 */
5304
	var $role;
5305
5306
	/**
5307
	 * Organizational scheme
5308
	 *
5309
	 * @var string
5310
	 * @see get_scheme()
5311
	 */
5312
	var $scheme;
5313
5314
	/**
5315
	 * Credited name
5316
	 *
5317
	 * @var string
5318
	 * @see get_name()
5319
	 */
5320
	var $name;
5321
5322
	/**
5323
	 * Constructor, used to input the data
5324
	 *
5325
	 * For documentation on all the parameters, see the corresponding
5326
	 * properties and their accessors
5327
	 */
5328
	public function __construct($role = null, $scheme = null, $name = null)
5329
	{
5330
		$this->role = $role;
5331
		$this->scheme = $scheme;
5332
		$this->name = $name;
5333
	}
5334
5335
	/**
5336
	 * String-ified version
5337
	 *
5338
	 * @return string
5339
	 */
5340
	public function __toString()
5341
	{
5342
		// There is no $this->data here
5343
		return md5(serialize($this));
5344
	}
5345
5346
	/**
5347
	 * Get the role of the person receiving credit
5348
	 *
5349
	 * @return string|null
5350
	 */
5351
	public function get_role()
5352
	{
5353
		if ($this->role !== null)
5354
		{
5355
			return $this->role;
5356
		}
5357
		else
5358
		{
5359
			return null;
5360
		}
5361
	}
5362
5363
	/**
5364
	 * Get the organizational scheme
5365
	 *
5366
	 * @return string|null
5367
	 */
5368
	public function get_scheme()
5369
	{
5370
		if ($this->scheme !== null)
5371
		{
5372
			return $this->scheme;
5373
		}
5374
		else
5375
		{
5376
			return null;
5377
		}
5378
	}
5379
5380
	/**
5381
	 * Get the credited person/entity's name
5382
	 *
5383
	 * @return string|null
5384
	 */
5385
	public function get_name()
5386
	{
5387
		if ($this->name !== null)
5388
		{
5389
			return $this->name;
5390
		}
5391
		else
5392
		{
5393
			return null;
5394
		}
5395
	}
5396
}
5397
5398
/**
5399
 * Decode HTML Entities
5400
 *
5401
 * This implements HTML5 as of revision 967 (2007-06-28)
5402
 *
5403
 * @deprecated Use DOMDocument instead!
5404
 * @package SimplePie
5405
 */
5406
class SimplePie_Decode_HTML_Entities
5407
{
5408
	/**
5409
	 * Data to be parsed
5410
	 *
5411
	 * @access private
5412
	 * @var string
5413
	 */
5414
	var $data = '';
5415
5416
	/**
5417
	 * Currently consumed bytes
5418
	 *
5419
	 * @access private
5420
	 * @var string
5421
	 */
5422
	var $consumed = '';
5423
5424
	/**
5425
	 * Position of the current byte being parsed
5426
	 *
5427
	 * @access private
5428
	 * @var int
5429
	 */
5430
	var $position = 0;
5431
5432
	/**
5433
	 * Create an instance of the class with the input data
5434
	 *
5435
	 * @access public
5436
	 * @param string $data Input data
5437
	 */
5438
	public function __construct($data)
5439
	{
5440
		$this->data = $data;
5441
	}
5442
5443
	/**
5444
	 * Parse the input data
5445
	 *
5446
	 * @access public
5447
	 * @return string Output data
5448
	 */
5449
	public function parse()
5450
	{
5451
		while (($this->position = strpos($this->data, '&', $this->position)) !== false)
5452
		{
5453
			$this->consume();
5454
			$this->entity();
5455
			$this->consumed = '';
5456
		}
5457
		return $this->data;
5458
	}
5459
5460
	/**
5461
	 * Consume the next byte
5462
	 *
5463
	 * @access private
5464
	 * @return mixed The next byte, or false, if there is no more data
5465
	 */
5466
	public function consume()
5467
	{
5468
		if (isset($this->data[$this->position]))
5469
		{
5470
			$this->consumed .= $this->data[$this->position];
5471
			return $this->data[$this->position++];
5472
		}
5473
		else
5474
		{
5475
			return false;
5476
		}
5477
	}
5478
5479
	/**
5480
	 * Consume a range of characters
5481
	 *
5482
	 * @access private
5483
	 * @param string $chars Characters to consume
5484
	 * @return mixed A series of characters that match the range, or false
5485
	 */
5486
	public function consume_range($chars)
5487
	{
5488
		if ($len = strspn($this->data, $chars, $this->position))
5489
		{
5490
			$data = substr($this->data, $this->position, $len);
5491
			$this->consumed .= $data;
5492
			$this->position += $len;
5493
			return $data;
5494
		}
5495
		else
5496
		{
5497
			return false;
5498
		}
5499
	}
5500
5501
	/**
5502
	 * Unconsume one byte
5503
	 *
5504
	 * @access private
5505
	 */
5506
	public function unconsume()
5507
	{
5508
		$this->consumed = substr($this->consumed, 0, -1);
5509
		$this->position--;
5510
	}
5511
5512
	/**
5513
	 * Decode an entity
5514
	 *
5515
	 * @access private
5516
	 */
5517
	public function entity()
5518
	{
5519
		switch ($this->consume())
5520
		{
5521
			case "\x09":
5522
			case "\x0A":
5523
			case "\x0B":
5524
			case "\x0C":
5525
			case "\x20":
5526
			case "\x3C":
5527
			case "\x26":
5528
			case false:
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $this->consume() of type string|false against false; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
5529
				break;
5530
5531
			case "\x23":
5532
				switch ($this->consume())
5533
				{
5534
					case "\x78":
5535
					case "\x58":
5536
						$range = '0123456789ABCDEFabcdef';
5537
						$hex = true;
5538
						break;
5539
5540
					default:
5541
						$range = '0123456789';
5542
						$hex = false;
5543
						$this->unconsume();
5544
						break;
5545
				}
5546
5547
				if ($codepoint = $this->consume_range($range))
5548
				{
5549
					static $windows_1252_specials = array(0x0D => "\x0A", 0x80 => "\xE2\x82\xAC", 0x81 => "\xEF\xBF\xBD", 0x82 => "\xE2\x80\x9A", 0x83 => "\xC6\x92", 0x84 => "\xE2\x80\x9E", 0x85 => "\xE2\x80\xA6", 0x86 => "\xE2\x80\xA0", 0x87 => "\xE2\x80\xA1", 0x88 => "\xCB\x86", 0x89 => "\xE2\x80\xB0", 0x8A => "\xC5\xA0", 0x8B => "\xE2\x80\xB9", 0x8C => "\xC5\x92", 0x8D => "\xEF\xBF\xBD", 0x8E => "\xC5\xBD", 0x8F => "\xEF\xBF\xBD", 0x90 => "\xEF\xBF\xBD", 0x91 => "\xE2\x80\x98", 0x92 => "\xE2\x80\x99", 0x93 => "\xE2\x80\x9C", 0x94 => "\xE2\x80\x9D", 0x95 => "\xE2\x80\xA2", 0x96 => "\xE2\x80\x93", 0x97 => "\xE2\x80\x94", 0x98 => "\xCB\x9C", 0x99 => "\xE2\x84\xA2", 0x9A => "\xC5\xA1", 0x9B => "\xE2\x80\xBA", 0x9C => "\xC5\x93", 0x9D => "\xEF\xBF\xBD", 0x9E => "\xC5\xBE", 0x9F => "\xC5\xB8");
5550
5551
					if ($hex)
5552
					{
5553
						$codepoint = hexdec($codepoint);
5554
					}
5555
					else
5556
					{
5557
						$codepoint = intval($codepoint);
5558
					}
5559
5560
					if (isset($windows_1252_specials[$codepoint]))
5561
					{
5562
						$replacement = $windows_1252_specials[$codepoint];
5563
					}
5564
					else
5565
					{
5566
						$replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
5567
					}
5568
5569
					if (!in_array($this->consume(), array(';', false), true))
5570
					{
5571
						$this->unconsume();
5572
					}
5573
5574
					$consumed_length = strlen($this->consumed);
5575
					$this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
5576
					$this->position += strlen($replacement) - $consumed_length;
5577
				}
5578
				break;
5579
5580
			default:
5581
				static $entities = array(
5582
					'Aacute' => "\xC3\x81",
5583
					'aacute' => "\xC3\xA1",
5584
					'Aacute;' => "\xC3\x81",
5585
					'aacute;' => "\xC3\xA1",
5586
					'Acirc' => "\xC3\x82",
5587
					'acirc' => "\xC3\xA2",
5588
					'Acirc;' => "\xC3\x82",
5589
					'acirc;' => "\xC3\xA2",
5590
					'acute' => "\xC2\xB4",
5591
					'acute;' => "\xC2\xB4",
5592
					'AElig' => "\xC3\x86",
5593
					'aelig' => "\xC3\xA6",
5594
					'AElig;' => "\xC3\x86",
5595
					'aelig;' => "\xC3\xA6",
5596
					'Agrave' => "\xC3\x80",
5597
					'agrave' => "\xC3\xA0",
5598
					'Agrave;' => "\xC3\x80",
5599
					'agrave;' => "\xC3\xA0",
5600
					'alefsym;' => "\xE2\x84\xB5",
5601
					'Alpha;' => "\xCE\x91",
5602
					'alpha;' => "\xCE\xB1",
5603
					'AMP' => "\x26",
5604
					'amp' => "\x26",
5605
					'AMP;' => "\x26",
5606
					'amp;' => "\x26",
5607
					'and;' => "\xE2\x88\xA7",
5608
					'ang;' => "\xE2\x88\xA0",
5609
					'apos;' => "\x27",
5610
					'Aring' => "\xC3\x85",
5611
					'aring' => "\xC3\xA5",
5612
					'Aring;' => "\xC3\x85",
5613
					'aring;' => "\xC3\xA5",
5614
					'asymp;' => "\xE2\x89\x88",
5615
					'Atilde' => "\xC3\x83",
5616
					'atilde' => "\xC3\xA3",
5617
					'Atilde;' => "\xC3\x83",
5618
					'atilde;' => "\xC3\xA3",
5619
					'Auml' => "\xC3\x84",
5620
					'auml' => "\xC3\xA4",
5621
					'Auml;' => "\xC3\x84",
5622
					'auml;' => "\xC3\xA4",
5623
					'bdquo;' => "\xE2\x80\x9E",
5624
					'Beta;' => "\xCE\x92",
5625
					'beta;' => "\xCE\xB2",
5626
					'brvbar' => "\xC2\xA6",
5627
					'brvbar;' => "\xC2\xA6",
5628
					'bull;' => "\xE2\x80\xA2",
5629
					'cap;' => "\xE2\x88\xA9",
5630
					'Ccedil' => "\xC3\x87",
5631
					'ccedil' => "\xC3\xA7",
5632
					'Ccedil;' => "\xC3\x87",
5633
					'ccedil;' => "\xC3\xA7",
5634
					'cedil' => "\xC2\xB8",
5635
					'cedil;' => "\xC2\xB8",
5636
					'cent' => "\xC2\xA2",
5637
					'cent;' => "\xC2\xA2",
5638
					'Chi;' => "\xCE\xA7",
5639
					'chi;' => "\xCF\x87",
5640
					'circ;' => "\xCB\x86",
5641
					'clubs;' => "\xE2\x99\xA3",
5642
					'cong;' => "\xE2\x89\x85",
5643
					'COPY' => "\xC2\xA9",
5644
					'copy' => "\xC2\xA9",
5645
					'COPY;' => "\xC2\xA9",
5646
					'copy;' => "\xC2\xA9",
5647
					'crarr;' => "\xE2\x86\xB5",
5648
					'cup;' => "\xE2\x88\xAA",
5649
					'curren' => "\xC2\xA4",
5650
					'curren;' => "\xC2\xA4",
5651
					'Dagger;' => "\xE2\x80\xA1",
5652
					'dagger;' => "\xE2\x80\xA0",
5653
					'dArr;' => "\xE2\x87\x93",
5654
					'darr;' => "\xE2\x86\x93",
5655
					'deg' => "\xC2\xB0",
5656
					'deg;' => "\xC2\xB0",
5657
					'Delta;' => "\xCE\x94",
5658
					'delta;' => "\xCE\xB4",
5659
					'diams;' => "\xE2\x99\xA6",
5660
					'divide' => "\xC3\xB7",
5661
					'divide;' => "\xC3\xB7",
5662
					'Eacute' => "\xC3\x89",
5663
					'eacute' => "\xC3\xA9",
5664
					'Eacute;' => "\xC3\x89",
5665
					'eacute;' => "\xC3\xA9",
5666
					'Ecirc' => "\xC3\x8A",
5667
					'ecirc' => "\xC3\xAA",
5668
					'Ecirc;' => "\xC3\x8A",
5669
					'ecirc;' => "\xC3\xAA",
5670
					'Egrave' => "\xC3\x88",
5671
					'egrave' => "\xC3\xA8",
5672
					'Egrave;' => "\xC3\x88",
5673
					'egrave;' => "\xC3\xA8",
5674
					'empty;' => "\xE2\x88\x85",
5675
					'emsp;' => "\xE2\x80\x83",
5676
					'ensp;' => "\xE2\x80\x82",
5677
					'Epsilon;' => "\xCE\x95",
5678
					'epsilon;' => "\xCE\xB5",
5679
					'equiv;' => "\xE2\x89\xA1",
5680
					'Eta;' => "\xCE\x97",
5681
					'eta;' => "\xCE\xB7",
5682
					'ETH' => "\xC3\x90",
5683
					'eth' => "\xC3\xB0",
5684
					'ETH;' => "\xC3\x90",
5685
					'eth;' => "\xC3\xB0",
5686
					'Euml' => "\xC3\x8B",
5687
					'euml' => "\xC3\xAB",
5688
					'Euml;' => "\xC3\x8B",
5689
					'euml;' => "\xC3\xAB",
5690
					'euro;' => "\xE2\x82\xAC",
5691
					'exist;' => "\xE2\x88\x83",
5692
					'fnof;' => "\xC6\x92",
5693
					'forall;' => "\xE2\x88\x80",
5694
					'frac12' => "\xC2\xBD",
5695
					'frac12;' => "\xC2\xBD",
5696
					'frac14' => "\xC2\xBC",
5697
					'frac14;' => "\xC2\xBC",
5698
					'frac34' => "\xC2\xBE",
5699
					'frac34;' => "\xC2\xBE",
5700
					'frasl;' => "\xE2\x81\x84",
5701
					'Gamma;' => "\xCE\x93",
5702
					'gamma;' => "\xCE\xB3",
5703
					'ge;' => "\xE2\x89\xA5",
5704
					'GT' => "\x3E",
5705
					'gt' => "\x3E",
5706
					'GT;' => "\x3E",
5707
					'gt;' => "\x3E",
5708
					'hArr;' => "\xE2\x87\x94",
5709
					'harr;' => "\xE2\x86\x94",
5710
					'hearts;' => "\xE2\x99\xA5",
5711
					'hellip;' => "\xE2\x80\xA6",
5712
					'Iacute' => "\xC3\x8D",
5713
					'iacute' => "\xC3\xAD",
5714
					'Iacute;' => "\xC3\x8D",
5715
					'iacute;' => "\xC3\xAD",
5716
					'Icirc' => "\xC3\x8E",
5717
					'icirc' => "\xC3\xAE",
5718
					'Icirc;' => "\xC3\x8E",
5719
					'icirc;' => "\xC3\xAE",
5720
					'iexcl' => "\xC2\xA1",
5721
					'iexcl;' => "\xC2\xA1",
5722
					'Igrave' => "\xC3\x8C",
5723
					'igrave' => "\xC3\xAC",
5724
					'Igrave;' => "\xC3\x8C",
5725
					'igrave;' => "\xC3\xAC",
5726
					'image;' => "\xE2\x84\x91",
5727
					'infin;' => "\xE2\x88\x9E",
5728
					'int;' => "\xE2\x88\xAB",
5729
					'Iota;' => "\xCE\x99",
5730
					'iota;' => "\xCE\xB9",
5731
					'iquest' => "\xC2\xBF",
5732
					'iquest;' => "\xC2\xBF",
5733
					'isin;' => "\xE2\x88\x88",
5734
					'Iuml' => "\xC3\x8F",
5735
					'iuml' => "\xC3\xAF",
5736
					'Iuml;' => "\xC3\x8F",
5737
					'iuml;' => "\xC3\xAF",
5738
					'Kappa;' => "\xCE\x9A",
5739
					'kappa;' => "\xCE\xBA",
5740
					'Lambda;' => "\xCE\x9B",
5741
					'lambda;' => "\xCE\xBB",
5742
					'lang;' => "\xE3\x80\x88",
5743
					'laquo' => "\xC2\xAB",
5744
					'laquo;' => "\xC2\xAB",
5745
					'lArr;' => "\xE2\x87\x90",
5746
					'larr;' => "\xE2\x86\x90",
5747
					'lceil;' => "\xE2\x8C\x88",
5748
					'ldquo;' => "\xE2\x80\x9C",
5749
					'le;' => "\xE2\x89\xA4",
5750
					'lfloor;' => "\xE2\x8C\x8A",
5751
					'lowast;' => "\xE2\x88\x97",
5752
					'loz;' => "\xE2\x97\x8A",
5753
					'lrm;' => "\xE2\x80\x8E",
5754
					'lsaquo;' => "\xE2\x80\xB9",
5755
					'lsquo;' => "\xE2\x80\x98",
5756
					'LT' => "\x3C",
5757
					'lt' => "\x3C",
5758
					'LT;' => "\x3C",
5759
					'lt;' => "\x3C",
5760
					'macr' => "\xC2\xAF",
5761
					'macr;' => "\xC2\xAF",
5762
					'mdash;' => "\xE2\x80\x94",
5763
					'micro' => "\xC2\xB5",
5764
					'micro;' => "\xC2\xB5",
5765
					'middot' => "\xC2\xB7",
5766
					'middot;' => "\xC2\xB7",
5767
					'minus;' => "\xE2\x88\x92",
5768
					'Mu;' => "\xCE\x9C",
5769
					'mu;' => "\xCE\xBC",
5770
					'nabla;' => "\xE2\x88\x87",
5771
					'nbsp' => "\xC2\xA0",
5772
					'nbsp;' => "\xC2\xA0",
5773
					'ndash;' => "\xE2\x80\x93",
5774
					'ne;' => "\xE2\x89\xA0",
5775
					'ni;' => "\xE2\x88\x8B",
5776
					'not' => "\xC2\xAC",
5777
					'not;' => "\xC2\xAC",
5778
					'notin;' => "\xE2\x88\x89",
5779
					'nsub;' => "\xE2\x8A\x84",
5780
					'Ntilde' => "\xC3\x91",
5781
					'ntilde' => "\xC3\xB1",
5782
					'Ntilde;' => "\xC3\x91",
5783
					'ntilde;' => "\xC3\xB1",
5784
					'Nu;' => "\xCE\x9D",
5785
					'nu;' => "\xCE\xBD",
5786
					'Oacute' => "\xC3\x93",
5787
					'oacute' => "\xC3\xB3",
5788
					'Oacute;' => "\xC3\x93",
5789
					'oacute;' => "\xC3\xB3",
5790
					'Ocirc' => "\xC3\x94",
5791
					'ocirc' => "\xC3\xB4",
5792
					'Ocirc;' => "\xC3\x94",
5793
					'ocirc;' => "\xC3\xB4",
5794
					'OElig;' => "\xC5\x92",
5795
					'oelig;' => "\xC5\x93",
5796
					'Ograve' => "\xC3\x92",
5797
					'ograve' => "\xC3\xB2",
5798
					'Ograve;' => "\xC3\x92",
5799
					'ograve;' => "\xC3\xB2",
5800
					'oline;' => "\xE2\x80\xBE",
5801
					'Omega;' => "\xCE\xA9",
5802
					'omega;' => "\xCF\x89",
5803
					'Omicron;' => "\xCE\x9F",
5804
					'omicron;' => "\xCE\xBF",
5805
					'oplus;' => "\xE2\x8A\x95",
5806
					'or;' => "\xE2\x88\xA8",
5807
					'ordf' => "\xC2\xAA",
5808
					'ordf;' => "\xC2\xAA",
5809
					'ordm' => "\xC2\xBA",
5810
					'ordm;' => "\xC2\xBA",
5811
					'Oslash' => "\xC3\x98",
5812
					'oslash' => "\xC3\xB8",
5813
					'Oslash;' => "\xC3\x98",
5814
					'oslash;' => "\xC3\xB8",
5815
					'Otilde' => "\xC3\x95",
5816
					'otilde' => "\xC3\xB5",
5817
					'Otilde;' => "\xC3\x95",
5818
					'otilde;' => "\xC3\xB5",
5819
					'otimes;' => "\xE2\x8A\x97",
5820
					'Ouml' => "\xC3\x96",
5821
					'ouml' => "\xC3\xB6",
5822
					'Ouml;' => "\xC3\x96",
5823
					'ouml;' => "\xC3\xB6",
5824
					'para' => "\xC2\xB6",
5825
					'para;' => "\xC2\xB6",
5826
					'part;' => "\xE2\x88\x82",
5827
					'permil;' => "\xE2\x80\xB0",
5828
					'perp;' => "\xE2\x8A\xA5",
5829
					'Phi;' => "\xCE\xA6",
5830
					'phi;' => "\xCF\x86",
5831
					'Pi;' => "\xCE\xA0",
5832
					'pi;' => "\xCF\x80",
5833
					'piv;' => "\xCF\x96",
5834
					'plusmn' => "\xC2\xB1",
5835
					'plusmn;' => "\xC2\xB1",
5836
					'pound' => "\xC2\xA3",
5837
					'pound;' => "\xC2\xA3",
5838
					'Prime;' => "\xE2\x80\xB3",
5839
					'prime;' => "\xE2\x80\xB2",
5840
					'prod;' => "\xE2\x88\x8F",
5841
					'prop;' => "\xE2\x88\x9D",
5842
					'Psi;' => "\xCE\xA8",
5843
					'psi;' => "\xCF\x88",
5844
					'QUOT' => "\x22",
5845
					'quot' => "\x22",
5846
					'QUOT;' => "\x22",
5847
					'quot;' => "\x22",
5848
					'radic;' => "\xE2\x88\x9A",
5849
					'rang;' => "\xE3\x80\x89",
5850
					'raquo' => "\xC2\xBB",
5851
					'raquo;' => "\xC2\xBB",
5852
					'rArr;' => "\xE2\x87\x92",
5853
					'rarr;' => "\xE2\x86\x92",
5854
					'rceil;' => "\xE2\x8C\x89",
5855
					'rdquo;' => "\xE2\x80\x9D",
5856
					'real;' => "\xE2\x84\x9C",
5857
					'REG' => "\xC2\xAE",
5858
					'reg' => "\xC2\xAE",
5859
					'REG;' => "\xC2\xAE",
5860
					'reg;' => "\xC2\xAE",
5861
					'rfloor;' => "\xE2\x8C\x8B",
5862
					'Rho;' => "\xCE\xA1",
5863
					'rho;' => "\xCF\x81",
5864
					'rlm;' => "\xE2\x80\x8F",
5865
					'rsaquo;' => "\xE2\x80\xBA",
5866
					'rsquo;' => "\xE2\x80\x99",
5867
					'sbquo;' => "\xE2\x80\x9A",
5868
					'Scaron;' => "\xC5\xA0",
5869
					'scaron;' => "\xC5\xA1",
5870
					'sdot;' => "\xE2\x8B\x85",
5871
					'sect' => "\xC2\xA7",
5872
					'sect;' => "\xC2\xA7",
5873
					'shy' => "\xC2\xAD",
5874
					'shy;' => "\xC2\xAD",
5875
					'Sigma;' => "\xCE\xA3",
5876
					'sigma;' => "\xCF\x83",
5877
					'sigmaf;' => "\xCF\x82",
5878
					'sim;' => "\xE2\x88\xBC",
5879
					'spades;' => "\xE2\x99\xA0",
5880
					'sub;' => "\xE2\x8A\x82",
5881
					'sube;' => "\xE2\x8A\x86",
5882
					'sum;' => "\xE2\x88\x91",
5883
					'sup;' => "\xE2\x8A\x83",
5884
					'sup1' => "\xC2\xB9",
5885
					'sup1;' => "\xC2\xB9",
5886
					'sup2' => "\xC2\xB2",
5887
					'sup2;' => "\xC2\xB2",
5888
					'sup3' => "\xC2\xB3",
5889
					'sup3;' => "\xC2\xB3",
5890
					'supe;' => "\xE2\x8A\x87",
5891
					'szlig' => "\xC3\x9F",
5892
					'szlig;' => "\xC3\x9F",
5893
					'Tau;' => "\xCE\xA4",
5894
					'tau;' => "\xCF\x84",
5895
					'there4;' => "\xE2\x88\xB4",
5896
					'Theta;' => "\xCE\x98",
5897
					'theta;' => "\xCE\xB8",
5898
					'thetasym;' => "\xCF\x91",
5899
					'thinsp;' => "\xE2\x80\x89",
5900
					'THORN' => "\xC3\x9E",
5901
					'thorn' => "\xC3\xBE",
5902
					'THORN;' => "\xC3\x9E",
5903
					'thorn;' => "\xC3\xBE",
5904
					'tilde;' => "\xCB\x9C",
5905
					'times' => "\xC3\x97",
5906
					'times;' => "\xC3\x97",
5907
					'TRADE;' => "\xE2\x84\xA2",
5908
					'trade;' => "\xE2\x84\xA2",
5909
					'Uacute' => "\xC3\x9A",
5910
					'uacute' => "\xC3\xBA",
5911
					'Uacute;' => "\xC3\x9A",
5912
					'uacute;' => "\xC3\xBA",
5913
					'uArr;' => "\xE2\x87\x91",
5914
					'uarr;' => "\xE2\x86\x91",
5915
					'Ucirc' => "\xC3\x9B",
5916
					'ucirc' => "\xC3\xBB",
5917
					'Ucirc;' => "\xC3\x9B",
5918
					'ucirc;' => "\xC3\xBB",
5919
					'Ugrave' => "\xC3\x99",
5920
					'ugrave' => "\xC3\xB9",
5921
					'Ugrave;' => "\xC3\x99",
5922
					'ugrave;' => "\xC3\xB9",
5923
					'uml' => "\xC2\xA8",
5924
					'uml;' => "\xC2\xA8",
5925
					'upsih;' => "\xCF\x92",
5926
					'Upsilon;' => "\xCE\xA5",
5927
					'upsilon;' => "\xCF\x85",
5928
					'Uuml' => "\xC3\x9C",
5929
					'uuml' => "\xC3\xBC",
5930
					'Uuml;' => "\xC3\x9C",
5931
					'uuml;' => "\xC3\xBC",
5932
					'weierp;' => "\xE2\x84\x98",
5933
					'Xi;' => "\xCE\x9E",
5934
					'xi;' => "\xCE\xBE",
5935
					'Yacute' => "\xC3\x9D",
5936
					'yacute' => "\xC3\xBD",
5937
					'Yacute;' => "\xC3\x9D",
5938
					'yacute;' => "\xC3\xBD",
5939
					'yen' => "\xC2\xA5",
5940
					'yen;' => "\xC2\xA5",
5941
					'yuml' => "\xC3\xBF",
5942
					'Yuml;' => "\xC5\xB8",
5943
					'yuml;' => "\xC3\xBF",
5944
					'Zeta;' => "\xCE\x96",
5945
					'zeta;' => "\xCE\xB6",
5946
					'zwj;' => "\xE2\x80\x8D",
5947
					'zwnj;' => "\xE2\x80\x8C"
5948
				);
5949
5950
				for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
5951
				{
5952
					$consumed = substr($this->consumed, 1);
5953
					if (isset($entities[$consumed]))
5954
					{
5955
						$match = $consumed;
5956
					}
5957
				}
5958
5959
				if ($match !== null)
5960
				{
5961
 					$this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
0 ignored issues
show
Bug introduced by
The variable $consumed does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
5962
					$this->position += strlen($entities[$match]) - strlen($consumed) - 1;
5963
				}
5964
				break;
5965
		}
5966
	}
5967
}
5968
5969
/**
5970
 * Handles everything related to enclosures (including Media RSS and iTunes RSS)
5971
 *
5972
 * Used by {@see SimplePie_Item::get_enclosure()} and {@see SimplePie_Item::get_enclosures()}
5973
 *
5974
 * This class can be overloaded with {@see SimplePie::set_enclosure_class()}
5975
 *
5976
 * @package SimplePie
5977
 * @subpackage API
5978
 */
5979
class SimplePie_Enclosure
5980
{
5981
	/**
5982
	 * @var string
5983
	 * @see get_bitrate()
5984
	 */
5985
	var $bitrate;
5986
5987
	/**
5988
	 * @var array
5989
	 * @see get_captions()
5990
	 */
5991
	var $captions;
5992
5993
	/**
5994
	 * @var array
5995
	 * @see get_categories()
5996
	 */
5997
	var $categories;
5998
5999
	/**
6000
	 * @var int
6001
	 * @see get_channels()
6002
	 */
6003
	var $channels;
6004
6005
	/**
6006
	 * @var SimplePie_Copyright
6007
	 * @see get_copyright()
6008
	 */
6009
	var $copyright;
6010
6011
	/**
6012
	 * @var array
6013
	 * @see get_credits()
6014
	 */
6015
	var $credits;
6016
6017
	/**
6018
	 * @var string
6019
	 * @see get_description()
6020
	 */
6021
	var $description;
6022
6023
	/**
6024
	 * @var int
6025
	 * @see get_duration()
6026
	 */
6027
	var $duration;
6028
6029
	/**
6030
	 * @var string
6031
	 * @see get_expression()
6032
	 */
6033
	var $expression;
6034
6035
	/**
6036
	 * @var string
6037
	 * @see get_framerate()
6038
	 */
6039
	var $framerate;
6040
6041
	/**
6042
	 * @var string
6043
	 * @see get_handler()
6044
	 */
6045
	var $handler;
6046
6047
	/**
6048
	 * @var array
6049
	 * @see get_hashes()
6050
	 */
6051
	var $hashes;
6052
6053
	/**
6054
	 * @var string
6055
	 * @see get_height()
6056
	 */
6057
	var $height;
6058
6059
	/**
6060
	 * @deprecated
6061
	 * @var null
6062
	 */
6063
	var $javascript;
6064
6065
	/**
6066
	 * @var array
6067
	 * @see get_keywords()
6068
	 */
6069
	var $keywords;
6070
6071
	/**
6072
	 * @var string
6073
	 * @see get_language()
6074
	 */
6075
	var $lang;
6076
6077
	/**
6078
	 * @var string
6079
	 * @see get_length()
6080
	 */
6081
	var $length;
6082
6083
	/**
6084
	 * @var string
6085
	 * @see get_link()
6086
	 */
6087
	var $link;
6088
6089
	/**
6090
	 * @var string
6091
	 * @see get_medium()
6092
	 */
6093
	var $medium;
6094
6095
	/**
6096
	 * @var string
6097
	 * @see get_player()
6098
	 */
6099
	var $player;
6100
6101
	/**
6102
	 * @var array
6103
	 * @see get_ratings()
6104
	 */
6105
	var $ratings;
6106
6107
	/**
6108
	 * @var array
6109
	 * @see get_restrictions()
6110
	 */
6111
	var $restrictions;
6112
6113
	/**
6114
	 * @var string
6115
	 * @see get_sampling_rate()
6116
	 */
6117
	var $samplingrate;
6118
6119
	/**
6120
	 * @var array
6121
	 * @see get_thumbnails()
6122
	 */
6123
	var $thumbnails;
6124
6125
	/**
6126
	 * @var string
6127
	 * @see get_title()
6128
	 */
6129
	var $title;
6130
6131
	/**
6132
	 * @var string
6133
	 * @see get_type()
6134
	 */
6135
	var $type;
6136
6137
	/**
6138
	 * @var string
6139
	 * @see get_width()
6140
	 */
6141
	var $width;
6142
6143
	/**
6144
	 * Constructor, used to input the data
6145
	 *
6146
	 * For documentation on all the parameters, see the corresponding
6147
	 * properties and their accessors
6148
	 *
6149
	 * @uses idna_convert If available, this will convert an IDN
6150
	 */
6151
	public function __construct($link = null, $type = null, $length = null, $javascript = null, $bitrate = null, $captions = null, $categories = null, $channels = null, $copyright = null, $credits = null, $description = null, $duration = null, $expression = null, $framerate = null, $hashes = null, $height = null, $keywords = null, $lang = null, $medium = null, $player = null, $ratings = null, $restrictions = null, $samplingrate = null, $thumbnails = null, $title = null, $width = null)
0 ignored issues
show
Unused Code introduced by
The parameter $javascript is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
6152
	{
6153
		$this->bitrate = $bitrate;
6154
		$this->captions = $captions;
6155
		$this->categories = $categories;
6156
		$this->channels = $channels;
6157
		$this->copyright = $copyright;
6158
		$this->credits = $credits;
6159
		$this->description = $description;
6160
		$this->duration = $duration;
6161
		$this->expression = $expression;
6162
		$this->framerate = $framerate;
6163
		$this->hashes = $hashes;
6164
		$this->height = $height;
6165
		$this->keywords = $keywords;
6166
		$this->lang = $lang;
6167
		$this->length = $length;
6168
		$this->link = $link;
6169
		$this->medium = $medium;
6170
		$this->player = $player;
6171
		$this->ratings = $ratings;
6172
		$this->restrictions = $restrictions;
6173
		$this->samplingrate = $samplingrate;
6174
		$this->thumbnails = $thumbnails;
6175
		$this->title = $title;
6176
		$this->type = $type;
6177
		$this->width = $width;
6178
6179
		if (class_exists('idna_convert'))
6180
		{
6181
			$idn = new idna_convert();
6182
			$parsed = SimplePie_Misc::parse_url($link);
6183
			$this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6184
		}
6185
		$this->handler = $this->get_handler(); // Needs to load last
6186
	}
6187
6188
	/**
6189
	 * String-ified version
6190
	 *
6191
	 * @return string
6192
	 */
6193
	public function __toString()
6194
	{
6195
		// There is no $this->data here
6196
		return md5(serialize($this));
6197
	}
6198
6199
	/**
6200
	 * Get the bitrate
6201
	 *
6202
	 * @return string|null
6203
	 */
6204
	public function get_bitrate()
6205
	{
6206
		if ($this->bitrate !== null)
6207
		{
6208
			return $this->bitrate;
6209
		}
6210
		else
6211
		{
6212
			return null;
6213
		}
6214
	}
6215
6216
	/**
6217
	 * Get a single caption
6218
	 *
6219
	 * @param int $key
6220
	 * @return SimplePie_Caption|null
6221
	 */
6222
	public function get_caption($key = 0)
6223
	{
6224
		$captions = $this->get_captions();
6225
		if (isset($captions[$key]))
6226
		{
6227
			return $captions[$key];
6228
		}
6229
		else
6230
		{
6231
			return null;
6232
		}
6233
	}
6234
6235
	/**
6236
	 * Get all captions
6237
	 *
6238
	 * @return array|null Array of {@see SimplePie_Caption} objects
6239
	 */
6240
	public function get_captions()
6241
	{
6242
		if ($this->captions !== null)
6243
		{
6244
			return $this->captions;
6245
		}
6246
		else
6247
		{
6248
			return null;
6249
		}
6250
	}
6251
6252
	/**
6253
	 * Get a single category
6254
	 *
6255
	 * @param int $key
6256
	 * @return SimplePie_Category|null
6257
	 */
6258
	public function get_category($key = 0)
6259
	{
6260
		$categories = $this->get_categories();
6261
		if (isset($categories[$key]))
6262
		{
6263
			return $categories[$key];
6264
		}
6265
		else
6266
		{
6267
			return null;
6268
		}
6269
	}
6270
6271
	/**
6272
	 * Get all categories
6273
	 *
6274
	 * @return array|null Array of {@see SimplePie_Category} objects
6275
	 */
6276
	public function get_categories()
6277
	{
6278
		if ($this->categories !== null)
6279
		{
6280
			return $this->categories;
6281
		}
6282
		else
6283
		{
6284
			return null;
6285
		}
6286
	}
6287
6288
	/**
6289
	 * Get the number of audio channels
6290
	 *
6291
	 * @return int|null
6292
	 */
6293
	public function get_channels()
6294
	{
6295
		if ($this->channels !== null)
6296
		{
6297
			return $this->channels;
6298
		}
6299
		else
6300
		{
6301
			return null;
6302
		}
6303
	}
6304
6305
	/**
6306
	 * Get the copyright information
6307
	 *
6308
	 * @return SimplePie_Copyright|null
6309
	 */
6310
	public function get_copyright()
6311
	{
6312
		if ($this->copyright !== null)
6313
		{
6314
			return $this->copyright;
6315
		}
6316
		else
6317
		{
6318
			return null;
6319
		}
6320
	}
6321
6322
	/**
6323
	 * Get a single credit
6324
	 *
6325
	 * @param int $key
6326
	 * @return SimplePie_Credit|null
6327
	 */
6328
	public function get_credit($key = 0)
6329
	{
6330
		$credits = $this->get_credits();
6331
		if (isset($credits[$key]))
6332
		{
6333
			return $credits[$key];
6334
		}
6335
		else
6336
		{
6337
			return null;
6338
		}
6339
	}
6340
6341
	/**
6342
	 * Get all credits
6343
	 *
6344
	 * @return array|null Array of {@see SimplePie_Credit} objects
6345
	 */
6346
	public function get_credits()
6347
	{
6348
		if ($this->credits !== null)
6349
		{
6350
			return $this->credits;
6351
		}
6352
		else
6353
		{
6354
			return null;
6355
		}
6356
	}
6357
6358
	/**
6359
	 * Get the description of the enclosure
6360
	 *
6361
	 * @return string|null
6362
	 */
6363
	public function get_description()
6364
	{
6365
		if ($this->description !== null)
6366
		{
6367
			return $this->description;
6368
		}
6369
		else
6370
		{
6371
			return null;
6372
		}
6373
	}
6374
6375
	/**
6376
	 * Get the duration of the enclosure
6377
	 *
6378
	 * @param bool $convert Convert seconds into hh:mm:ss
6379
	 * @return string|int|null 'hh:mm:ss' string if `$convert` was specified, otherwise integer (or null if none found)
6380
	 */
6381
	public function get_duration($convert = false)
6382
	{
6383
		if ($this->duration !== null)
6384
		{
6385
			if ($convert)
6386
			{
6387
				$time = SimplePie_Misc::time_hms($this->duration);
6388
				return $time;
6389
			}
6390
			else
6391
			{
6392
				return $this->duration;
6393
			}
6394
		}
6395
		else
6396
		{
6397
			return null;
6398
		}
6399
	}
6400
6401
	/**
6402
	 * Get the expression
6403
	 *
6404
	 * @return string Probably one of 'sample', 'full', 'nonstop', 'clip'. Defaults to 'full'
6405
	 */
6406
	public function get_expression()
6407
	{
6408
		if ($this->expression !== null)
6409
		{
6410
			return $this->expression;
6411
		}
6412
		else
6413
		{
6414
			return 'full';
6415
		}
6416
	}
6417
6418
	/**
6419
	 * Get the file extension
6420
	 *
6421
	 * @return string|null
6422
	 */
6423
	public function get_extension()
6424
	{
6425
		if ($this->link !== null)
6426
		{
6427
			$url = SimplePie_Misc::parse_url($this->link);
6428
			if ($url['path'] !== '')
6429
			{
6430
				return pathinfo($url['path'], PATHINFO_EXTENSION);
6431
			}
6432
		}
6433
		return null;
6434
	}
6435
6436
	/**
6437
	 * Get the framerate (in frames-per-second)
6438
	 *
6439
	 * @return string|null
6440
	 */
6441
	public function get_framerate()
6442
	{
6443
		if ($this->framerate !== null)
6444
		{
6445
			return $this->framerate;
6446
		}
6447
		else
6448
		{
6449
			return null;
6450
		}
6451
	}
6452
6453
	/**
6454
	 * Get the preferred handler
6455
	 *
6456
	 * @return string|null One of 'flash', 'fmedia', 'quicktime', 'wmedia', 'mp3'
6457
	 */
6458
	public function get_handler()
6459
	{
6460
		return $this->get_real_type(true);
6461
	}
6462
6463
	/**
6464
	 * Get a single hash
6465
	 *
6466
	 * @link http://www.rssboard.org/media-rss#media-hash
6467
	 * @param int $key
6468
	 * @return string|null Hash as per `media:hash`, prefixed with "$algo:"
6469
	 */
6470
	public function get_hash($key = 0)
6471
	{
6472
		$hashes = $this->get_hashes();
6473
		if (isset($hashes[$key]))
6474
		{
6475
			return $hashes[$key];
6476
		}
6477
		else
6478
		{
6479
			return null;
6480
		}
6481
	}
6482
6483
	/**
6484
	 * Get all credits
6485
	 *
6486
	 * @return array|null Array of strings, see {@see get_hash()}
6487
	 */
6488
	public function get_hashes()
6489
	{
6490
		if ($this->hashes !== null)
6491
		{
6492
			return $this->hashes;
6493
		}
6494
		else
6495
		{
6496
			return null;
6497
		}
6498
	}
6499
6500
	/**
6501
	 * Get the height
6502
	 *
6503
	 * @return string|null
6504
	 */
6505
	public function get_height()
6506
	{
6507
		if ($this->height !== null)
6508
		{
6509
			return $this->height;
6510
		}
6511
		else
6512
		{
6513
			return null;
6514
		}
6515
	}
6516
6517
	/**
6518
	 * Get the language
6519
	 *
6520
	 * @link http://tools.ietf.org/html/rfc3066
6521
	 * @return string|null Language code as per RFC 3066
6522
	 */
6523
	public function get_language()
6524
	{
6525
		if ($this->lang !== null)
6526
		{
6527
			return $this->lang;
6528
		}
6529
		else
6530
		{
6531
			return null;
6532
		}
6533
	}
6534
6535
	/**
6536
	 * Get a single keyword
6537
	 *
6538
	 * @param int $key
6539
	 * @return string|null
6540
	 */
6541
	public function get_keyword($key = 0)
6542
	{
6543
		$keywords = $this->get_keywords();
6544
		if (isset($keywords[$key]))
6545
		{
6546
			return $keywords[$key];
6547
		}
6548
		else
6549
		{
6550
			return null;
6551
		}
6552
	}
6553
6554
	/**
6555
	 * Get all keywords
6556
	 *
6557
	 * @return array|null Array of strings
6558
	 */
6559
	public function get_keywords()
6560
	{
6561
		if ($this->keywords !== null)
6562
		{
6563
			return $this->keywords;
6564
		}
6565
		else
6566
		{
6567
			return null;
6568
		}
6569
	}
6570
6571
	/**
6572
	 * Get length
6573
	 *
6574
	 * @return float Length in bytes
6575
	 */
6576
	public function get_length()
6577
	{
6578
		if ($this->length !== null)
6579
		{
6580
			return $this->length;
6581
		}
6582
		else
6583
		{
6584
			return null;
6585
		}
6586
	}
6587
6588
	/**
6589
	 * Get the URL
6590
	 *
6591
	 * @return string|null
6592
	 */
6593
	public function get_link()
6594
	{
6595
		if ($this->link !== null)
6596
		{
6597
			return urldecode($this->link);
6598
		}
6599
		else
6600
		{
6601
			return null;
6602
		}
6603
	}
6604
6605
	/**
6606
	 * Get the medium
6607
	 *
6608
	 * @link http://www.rssboard.org/media-rss#media-content
6609
	 * @return string|null Should be one of 'image', 'audio', 'video', 'document', 'executable'
6610
	 */
6611
	public function get_medium()
6612
	{
6613
		if ($this->medium !== null)
6614
		{
6615
			return $this->medium;
6616
		}
6617
		else
6618
		{
6619
			return null;
6620
		}
6621
	}
6622
6623
	/**
6624
	 * Get the player URL
6625
	 *
6626
	 * Typically the same as {@see get_permalink()}
6627
	 * @return string|null Player URL
6628
	 */
6629
	public function get_player()
6630
	{
6631
		if ($this->player !== null)
6632
		{
6633
			return $this->player;
6634
		}
6635
		else
6636
		{
6637
			return null;
6638
		}
6639
	}
6640
6641
	/**
6642
	 * Get a single rating
6643
	 *
6644
	 * @param int $key
6645
	 * @return SimplePie_Rating|null
6646
	 */
6647
	public function get_rating($key = 0)
6648
	{
6649
		$ratings = $this->get_ratings();
6650
		if (isset($ratings[$key]))
6651
		{
6652
			return $ratings[$key];
6653
		}
6654
		else
6655
		{
6656
			return null;
6657
		}
6658
	}
6659
6660
	/**
6661
	 * Get all ratings
6662
	 *
6663
	 * @return array|null Array of {@see SimplePie_Rating} objects
6664
	 */
6665
	public function get_ratings()
6666
	{
6667
		if ($this->ratings !== null)
6668
		{
6669
			return $this->ratings;
6670
		}
6671
		else
6672
		{
6673
			return null;
6674
		}
6675
	}
6676
6677
	/**
6678
	 * Get a single restriction
6679
	 *
6680
	 * @param int $key
6681
	 * @return SimplePie_Restriction|null
6682
	 */
6683
	public function get_restriction($key = 0)
6684
	{
6685
		$restrictions = $this->get_restrictions();
6686
		if (isset($restrictions[$key]))
6687
		{
6688
			return $restrictions[$key];
6689
		}
6690
		else
6691
		{
6692
			return null;
6693
		}
6694
	}
6695
6696
	/**
6697
	 * Get all restrictions
6698
	 *
6699
	 * @return array|null Array of {@see SimplePie_Restriction} objects
6700
	 */
6701
	public function get_restrictions()
6702
	{
6703
		if ($this->restrictions !== null)
6704
		{
6705
			return $this->restrictions;
6706
		}
6707
		else
6708
		{
6709
			return null;
6710
		}
6711
	}
6712
6713
	/**
6714
	 * Get the sampling rate (in kHz)
6715
	 *
6716
	 * @return string|null
6717
	 */
6718
	public function get_sampling_rate()
6719
	{
6720
		if ($this->samplingrate !== null)
6721
		{
6722
			return $this->samplingrate;
6723
		}
6724
		else
6725
		{
6726
			return null;
6727
		}
6728
	}
6729
6730
	/**
6731
	 * Get the file size (in MiB)
6732
	 *
6733
	 * @return float|null File size in mebibytes (1048 bytes)
6734
	 */
6735
	public function get_size()
6736
	{
6737
		$length = $this->get_length();
6738
		if ($length !== null)
6739
		{
6740
			return round($length/1048576, 2);
6741
		}
6742
		else
6743
		{
6744
			return null;
6745
		}
6746
	}
6747
6748
	/**
6749
	 * Get a single thumbnail
6750
	 *
6751
	 * @param int $key
6752
	 * @return string|null Thumbnail URL
6753
	 */
6754
	public function get_thumbnail($key = 0)
6755
	{
6756
		$thumbnails = $this->get_thumbnails();
6757
		if (isset($thumbnails[$key]))
6758
		{
6759
			return $thumbnails[$key];
6760
		}
6761
		else
6762
		{
6763
			return null;
6764
		}
6765
	}
6766
6767
	/**
6768
	 * Get all thumbnails
6769
	 *
6770
	 * @return array|null Array of thumbnail URLs
6771
	 */
6772
	public function get_thumbnails()
6773
	{
6774
		if ($this->thumbnails !== null)
6775
		{
6776
			return $this->thumbnails;
6777
		}
6778
		else
6779
		{
6780
			return null;
6781
		}
6782
	}
6783
6784
	/**
6785
	 * Get the title
6786
	 *
6787
	 * @return string|null
6788
	 */
6789
	public function get_title()
6790
	{
6791
		if ($this->title !== null)
6792
		{
6793
			return $this->title;
6794
		}
6795
		else
6796
		{
6797
			return null;
6798
		}
6799
	}
6800
6801
	/**
6802
	 * Get mimetype of the enclosure
6803
	 *
6804
	 * @see get_real_type()
6805
	 * @return string|null MIME type
6806
	 */
6807
	public function get_type()
6808
	{
6809
		if ($this->type !== null)
6810
		{
6811
			return $this->type;
6812
		}
6813
		else
6814
		{
6815
			return null;
6816
		}
6817
	}
6818
6819
	/**
6820
	 * Get the width
6821
	 *
6822
	 * @return string|null
6823
	 */
6824
	public function get_width()
6825
	{
6826
		if ($this->width !== null)
6827
		{
6828
			return $this->width;
6829
		}
6830
		else
6831
		{
6832
			return null;
6833
		}
6834
	}
6835
6836
	/**
6837
	 * Embed the enclosure using `<embed>`
6838
	 *
6839
	 * @deprecated Use the second parameter to {@see embed} instead
6840
	 *
6841
	 * @param array|string $options See first paramter to {@see embed}
6842
	 * @return string HTML string to output
6843
	 */
6844
	public function native_embed($options='')
6845
	{
6846
		return $this->embed($options, true);
6847
	}
6848
6849
	/**
6850
	 * Embed the enclosure using Javascript
6851
	 *
6852
	 * `$options` is an array or comma-separated key:value string, with the
6853
	 * following properties:
6854
	 *
6855
	 * - `alt` (string): Alternate content for when an end-user does not have
6856
	 *    the appropriate handler installed or when a file type is
6857
	 *    unsupported. Can be any text or HTML. Defaults to blank.
6858
	 * - `altclass` (string): If a file type is unsupported, the end-user will
6859
	 *    see the alt text (above) linked directly to the content. That link
6860
	 *    will have this value as its class name. Defaults to blank.
6861
	 * - `audio` (string): This is an image that should be used as a
6862
	 *    placeholder for audio files before they're loaded (QuickTime-only).
6863
	 *    Can be any relative or absolute URL. Defaults to blank.
6864
	 * - `bgcolor` (string): The background color for the media, if not
6865
	 *    already transparent. Defaults to `#ffffff`.
6866
	 * - `height` (integer): The height of the embedded media. Accepts any
6867
	 *    numeric pixel value (such as `360`) or `auto`. Defaults to `auto`,
6868
	 *    and it is recommended that you use this default.
6869
	 * - `loop` (boolean): Do you want the media to loop when it's done?
6870
	 *    Defaults to `false`.
6871
	 * - `mediaplayer` (string): The location of the included
6872
	 *    `mediaplayer.swf` file. This allows for the playback of Flash Video
6873
	 *    (`.flv`) files, and is the default handler for non-Odeo MP3's.
6874
	 *    Defaults to blank.
6875
	 * - `video` (string): This is an image that should be used as a
6876
	 *    placeholder for video files before they're loaded (QuickTime-only).
6877
	 *    Can be any relative or absolute URL. Defaults to blank.
6878
	 * - `width` (integer): The width of the embedded media. Accepts any
6879
	 *    numeric pixel value (such as `480`) or `auto`. Defaults to `auto`,
6880
	 *    and it is recommended that you use this default.
6881
	 * - `widescreen` (boolean): Is the enclosure widescreen or standard?
6882
	 *    This applies only to video enclosures, and will automatically resize
6883
	 *    the content appropriately.  Defaults to `false`, implying 4:3 mode.
6884
	 *
6885
	 * Note: Non-widescreen (4:3) mode with `width` and `height` set to `auto`
6886
	 * will default to 480x360 video resolution.  Widescreen (16:9) mode with
6887
	 * `width` and `height` set to `auto` will default to 480x270 video resolution.
6888
	 *
6889
	 * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
6890
	 * @param array|string $options Comma-separated key:value list, or array
6891
	 * @param bool $native Use `<embed>`
6892
	 * @return string HTML string to output
6893
	 */
6894
	public function embed($options = '', $native = false)
6895
	{
6896
		// Set up defaults
6897
		$audio = '';
6898
		$video = '';
6899
		$alt = '';
6900
		$altclass = '';
6901
		$loop = 'false';
6902
		$width = 'auto';
6903
		$height = 'auto';
6904
		$bgcolor = '#ffffff';
6905
		$mediaplayer = '';
6906
		$widescreen = false;
6907
		$handler = $this->get_handler();
6908
		$type = $this->get_real_type();
6909
6910
		// Process options and reassign values as necessary
6911
		if (is_array($options))
6912
		{
6913
			extract($options);
6914
		}
6915
		else
6916
		{
6917
			$options = explode(',', $options);
6918
			foreach($options as $option)
6919
			{
6920
				$opt = explode(':', $option, 2);
6921
				if (isset($opt[0], $opt[1]))
6922
				{
6923
					$opt[0] = trim($opt[0]);
6924
					$opt[1] = trim($opt[1]);
6925
					switch ($opt[0])
6926
					{
6927
						case 'audio':
6928
							$audio = $opt[1];
6929
							break;
6930
6931
						case 'video':
6932
							$video = $opt[1];
6933
							break;
6934
6935
						case 'alt':
6936
							$alt = $opt[1];
6937
							break;
6938
6939
						case 'altclass':
6940
							$altclass = $opt[1];
6941
							break;
6942
6943
						case 'loop':
6944
							$loop = $opt[1];
6945
							break;
6946
6947
						case 'width':
6948
							$width = $opt[1];
6949
							break;
6950
6951
						case 'height':
6952
							$height = $opt[1];
6953
							break;
6954
6955
						case 'bgcolor':
6956
							$bgcolor = $opt[1];
6957
							break;
6958
6959
						case 'mediaplayer':
6960
							$mediaplayer = $opt[1];
6961
							break;
6962
6963
						case 'widescreen':
6964
							$widescreen = $opt[1];
6965
							break;
6966
					}
6967
				}
6968
			}
6969
		}
6970
6971
		$mime = explode('/', $type, 2);
6972
		$mime = $mime[0];
6973
6974
		// Process values for 'auto'
6975
		if ($width === 'auto')
6976
		{
6977
			if ($mime === 'video')
6978
			{
6979
				if ($height === 'auto')
6980
				{
6981
					$width = 480;
6982
				}
6983
				elseif ($widescreen)
0 ignored issues
show
Bug Best Practice introduced by
The expression $widescreen of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
6984
				{
6985
					$width = round((intval($height)/9)*16);
6986
				}
6987
				else
6988
				{
6989
					$width = round((intval($height)/3)*4);
6990
				}
6991
			}
6992
			else
6993
			{
6994
				$width = '100%';
6995
			}
6996
		}
6997
6998
		if ($height === 'auto')
6999
		{
7000
			if ($mime === 'audio')
7001
			{
7002
				$height = 0;
7003
			}
7004
			elseif ($mime === 'video')
7005
			{
7006
				if ($width === 'auto')
7007
				{
7008
					if ($widescreen)
0 ignored issues
show
Bug Best Practice introduced by
The expression $widescreen of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
7009
					{
7010
						$height = 270;
7011
					}
7012
					else
7013
					{
7014
						$height = 360;
7015
					}
7016
				}
7017
				elseif ($widescreen)
0 ignored issues
show
Bug Best Practice introduced by
The expression $widescreen of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
7018
				{
7019
					$height = round((intval($width)/16)*9);
7020
				}
7021
				else
7022
				{
7023
					$height = round((intval($width)/4)*3);
7024
				}
7025
			}
7026
			else
7027
			{
7028
				$height = 376;
7029
			}
7030
		}
7031
		elseif ($mime === 'audio')
7032
		{
7033
			$height = 0;
7034
		}
7035
7036
		// Set proper placeholder value
7037
		if ($mime === 'audio')
7038
		{
7039
			$placeholder = $audio;
7040
		}
7041
		elseif ($mime === 'video')
7042
		{
7043
			$placeholder = $video;
7044
		}
7045
7046
		$embed = '';
7047
7048
		// Flash
7049
		if ($handler === 'flash')
7050
		{
7051
			if ($native)
7052
			{
7053
				$embed .= "<embed src=\"" . $this->get_link() . "\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"$type\" quality=\"high\" width=\"$width\" height=\"$height\" bgcolor=\"$bgcolor\" loop=\"$loop\"></embed>";
7054
			}
7055
			else
7056
			{
7057
				$embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
7058
			}
7059
		}
7060
7061
		// Flash Media Player file types.
7062
		// Preferred handler for MP3 file types.
7063
		elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
7064
		{
7065
			$height += 20;
7066
			if ($native)
7067
			{
7068
				$embed .= "<embed src=\"$mediaplayer\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" quality=\"high\" width=\"$width\" height=\"$height\" wmode=\"transparent\" flashvars=\"file=" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "&autostart=false&repeat=$loop&showdigits=true&showfsbutton=false\"></embed>";
7069
			}
7070
			else
7071
			{
7072
				$embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7073
			}
7074
		}
7075
7076
		// QuickTime 7 file types.  Need to test with QuickTime 6.
7077
		// Only handle MP3's if the Flash Media Player is not present.
7078
		elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
7079
		{
7080
			$height += 16;
7081
			if ($native)
7082
			{
7083
				if ($placeholder !== '')
7084
				{
7085
					$embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" href=\"" . $this->get_link() . "\" src=\"$placeholder\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"false\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
7086
				}
7087
				else
7088
				{
7089
					$embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" src=\"" . $this->get_link() . "\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"true\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
7090
				}
7091
			}
7092
			else
7093
			{
7094
				$embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7095
			}
7096
		}
7097
7098
		// Windows Media
7099
		elseif ($handler === 'wmedia')
7100
		{
7101
			$height += 45;
7102
			if ($native)
7103
			{
7104
				$embed .= "<embed type=\"application/x-mplayer2\" src=\"" . $this->get_link() . "\" autosize=\"1\" width=\"$width\" height=\"$height\" showcontrols=\"1\" showstatusbar=\"0\" showdisplay=\"0\" autostart=\"0\"></embed>";
7105
			}
7106
			else
7107
			{
7108
				$embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7109
			}
7110
		}
7111
7112
		// Everything else
7113
		else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7114
7115
		return $embed;
7116
	}
7117
7118
	/**
7119
	 * Get the real media type
7120
	 *
7121
	 * Often, feeds lie to us, necessitating a bit of deeper inspection. This
7122
	 * converts types to their canonical representations based on the file
7123
	 * extension
7124
	 *
7125
	 * @see get_type()
7126
	 * @param bool $find_handler Internal use only, use {@see get_handler()} instead
7127
	 * @return string MIME type
7128
	 */
7129
	public function get_real_type($find_handler = false)
7130
	{
7131
		// Mime-types by handler.
7132
		$types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
7133
		$types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
7134
		$types_quicktime = array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video'); // QuickTime
7135
		$types_wmedia = array('application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx'); // Windows Media
7136
		$types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7137
7138
		if ($this->get_type() !== null)
7139
		{
7140
			$type = strtolower($this->type);
7141
		}
7142
		else
7143
		{
7144
			$type = null;
7145
		}
7146
7147
		// If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7148
		if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7149
		{
7150
			switch (strtolower($this->get_extension()))
7151
			{
7152
				// Audio mime-types
7153
				case 'aac':
7154
				case 'adts':
7155
					$type = 'audio/acc';
7156
					break;
7157
7158
				case 'aif':
7159
				case 'aifc':
7160
				case 'aiff':
7161
				case 'cdda':
7162
					$type = 'audio/aiff';
7163
					break;
7164
7165
				case 'bwf':
7166
					$type = 'audio/wav';
7167
					break;
7168
7169
				case 'kar':
7170
				case 'mid':
7171
				case 'midi':
7172
				case 'smf':
7173
					$type = 'audio/midi';
7174
					break;
7175
7176
				case 'm4a':
7177
					$type = 'audio/x-m4a';
7178
					break;
7179
7180
				case 'mp3':
7181
				case 'swa':
7182
					$type = 'audio/mp3';
7183
					break;
7184
7185
				case 'wav':
7186
					$type = 'audio/wav';
7187
					break;
7188
7189
				case 'wax':
7190
					$type = 'audio/x-ms-wax';
7191
					break;
7192
7193
				case 'wma':
7194
					$type = 'audio/x-ms-wma';
7195
					break;
7196
7197
				// Video mime-types
7198
				case '3gp':
7199
				case '3gpp':
7200
					$type = 'video/3gpp';
7201
					break;
7202
7203
				case '3g2':
7204
				case '3gp2':
7205
					$type = 'video/3gpp2';
7206
					break;
7207
7208
				case 'asf':
7209
					$type = 'video/x-ms-asf';
7210
					break;
7211
7212
				case 'flv':
7213
					$type = 'video/x-flv';
7214
					break;
7215
7216
				case 'm1a':
7217
				case 'm1s':
7218
				case 'm1v':
7219
				case 'm15':
7220
				case 'm75':
7221
				case 'mp2':
7222
				case 'mpa':
7223
				case 'mpeg':
7224
				case 'mpg':
7225
				case 'mpm':
7226
				case 'mpv':
7227
					$type = 'video/mpeg';
7228
					break;
7229
7230
				case 'm4v':
7231
					$type = 'video/x-m4v';
7232
					break;
7233
7234
				case 'mov':
7235
				case 'qt':
7236
					$type = 'video/quicktime';
7237
					break;
7238
7239
				case 'mp4':
7240
				case 'mpg4':
7241
					$type = 'video/mp4';
7242
					break;
7243
7244
				case 'sdv':
7245
					$type = 'video/sd-video';
7246
					break;
7247
7248
				case 'wm':
7249
					$type = 'video/x-ms-wm';
7250
					break;
7251
7252
				case 'wmv':
7253
					$type = 'video/x-ms-wmv';
7254
					break;
7255
7256
				case 'wvx':
7257
					$type = 'video/x-ms-wvx';
7258
					break;
7259
7260
				// Flash mime-types
7261
				case 'spl':
7262
					$type = 'application/futuresplash';
7263
					break;
7264
7265
				case 'swf':
7266
					$type = 'application/x-shockwave-flash';
7267
					break;
7268
			}
7269
		}
7270
7271
		if ($find_handler)
7272
		{
7273
			if (in_array($type, $types_flash))
7274
			{
7275
				return 'flash';
7276
			}
7277
			elseif (in_array($type, $types_fmedia))
7278
			{
7279
				return 'fmedia';
7280
			}
7281
			elseif (in_array($type, $types_quicktime))
7282
			{
7283
				return 'quicktime';
7284
			}
7285
			elseif (in_array($type, $types_wmedia))
7286
			{
7287
				return 'wmedia';
7288
			}
7289
			elseif (in_array($type, $types_mp3))
7290
			{
7291
				return 'mp3';
7292
			}
7293
			else
7294
			{
7295
				return null;
7296
			}
7297
		}
7298
		else
7299
		{
7300
			return $type;
7301
		}
7302
	}
7303
}
7304
7305
/**
7306
 * General SimplePie exception class
7307
 *
7308
 * @package SimplePie
7309
 */
7310
class SimplePie_Exception extends Exception
7311
{
7312
}
7313
7314
/**
7315
 * Used for fetching remote files and reading local files
7316
 *
7317
 * Supports HTTP 1.0 via cURL or fsockopen, with spotty HTTP 1.1 support
7318
 *
7319
 * This class can be overloaded with {@see SimplePie::set_file_class()}
7320
 *
7321
 * @package SimplePie
7322
 * @subpackage HTTP
7323
 * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7324
 */
7325
class SimplePie_File
7326
{
7327
	var $url;
7328
	var $useragent;
7329
	var $success = true;
7330
	var $headers = array();
7331
	var $body;
7332
	var $status_code;
7333
	var $redirects = 0;
7334
	var $error;
7335
	var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7336
	var $permanent_url;
7337
7338
	public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false, $curl_options = array())
7339
	{
7340
		if (class_exists('idna_convert'))
7341
		{
7342
			$idn = new idna_convert();
7343
			$parsed = SimplePie_Misc::parse_url($url);
7344
			$url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7345
		}
7346
		$this->url = $url;
7347
		$this->permanent_url = $url;
7348
		$this->useragent = $useragent;
7349
		if (preg_match('/^http(s)?:\/\//i', $url))
7350
		{
7351
			if ($useragent === null)
7352
			{
7353
				$useragent = ini_get('user_agent');
7354
				$this->useragent = $useragent;
7355
			}
7356
			if (!is_array($headers))
7357
			{
7358
				$headers = array();
7359
			}
7360
			if (!$force_fsockopen && function_exists('curl_exec'))
7361
			{
7362
				$this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7363
				$fp = curl_init();
7364
				$headers2 = array();
7365
				foreach ($headers as $key => $value)
7366
				{
7367
					$headers2[] = "$key: $value";
7368
				}
7369
				if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7370
				{
7371
					curl_setopt($fp, CURLOPT_ENCODING, '');
7372
				}
7373
				curl_setopt($fp, CURLOPT_URL, $url);
7374
				curl_setopt($fp, CURLOPT_HEADER, 1);
7375
				curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7376
				curl_setopt($fp, CURLOPT_FAILONERROR, 1);
7377
				curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7378
				curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7379
				curl_setopt($fp, CURLOPT_REFERER, $url);
7380
				curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7381
				curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7382
				if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7383
				{
7384
					curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7385
					curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7386
				}
7387
				foreach ($curl_options as $curl_param => $curl_value) {
7388
					curl_setopt($fp, $curl_param, $curl_value);
7389
				}
7390
7391
				$this->headers = curl_exec($fp);
0 ignored issues
show
Documentation Bug introduced by
It seems like curl_exec($fp) of type * is incompatible with the declared type array of property $headers.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
7392
				if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7393
				{
7394
					curl_setopt($fp, CURLOPT_ENCODING, 'none');
7395
					$this->headers = curl_exec($fp);
7396
				}
7397
				if (curl_errno($fp))
7398
				{
7399
					$this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7400
					$this->success = false;
7401
				}
7402
				else
7403
				{
7404
					// Use the updated url provided by curl_getinfo after any redirects.
7405
					if ($info = curl_getinfo($fp)) {
7406
						$this->url = $info['url'];
7407
					}
7408
					curl_close($fp);
7409
					$this->headers = SimplePie_HTTP_Parser::prepareHeaders($this->headers, $info['redirect_count'] + 1);
0 ignored issues
show
Documentation Bug introduced by
It seems like \SimplePie_HTTP_Parser::...['redirect_count'] + 1) of type string is incompatible with the declared type array of property $headers.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
7410
					$parser = new SimplePie_HTTP_Parser($this->headers);
7411
					if ($parser->parse())
7412
					{
7413
						$this->headers = $parser->headers;
7414
						$this->body = trim($parser->body);
7415
						$this->status_code = $parser->status_code;
7416
						if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
7417
						{
7418
							$this->redirects++;
7419
							$location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7420
							$previousStatusCode = $this->status_code;
7421
							$this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7422
							$this->permanent_url = ($previousStatusCode == 301) ? $location : $url;
7423
							return;
7424
						}
7425
					}
7426
				}
7427
			}
7428
			else
7429
			{
7430
				$this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7431
				$url_parts = parse_url($url);
7432
				$socket_host = $url_parts['host'];
7433
				if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7434
				{
7435
					$socket_host = "ssl://$url_parts[host]";
7436
					$url_parts['port'] = 443;
7437
				}
7438
				if (!isset($url_parts['port']))
7439
				{
7440
					$url_parts['port'] = 80;
7441
				}
7442
				$fp = @fsockopen($socket_host, $url_parts['port'], $errno, $errstr, $timeout);
7443
				if (!$fp)
7444
				{
7445
					$this->error = 'fsockopen error: ' . $errstr;
7446
					$this->success = false;
7447
				}
7448
				else
7449
				{
7450
					stream_set_timeout($fp, $timeout);
7451
					if (isset($url_parts['path']))
7452
					{
7453
						if (isset($url_parts['query']))
7454
						{
7455
							$get = "$url_parts[path]?$url_parts[query]";
7456
						}
7457
						else
7458
						{
7459
							$get = $url_parts['path'];
7460
						}
7461
					}
7462
					else
7463
					{
7464
						$get = '/';
7465
					}
7466
					$out = "GET $get HTTP/1.1\r\n";
7467
					$out .= "Host: $url_parts[host]\r\n";
7468
					$out .= "User-Agent: $useragent\r\n";
7469
					if (extension_loaded('zlib'))
7470
					{
7471
						$out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7472
					}
7473
7474
					if (isset($url_parts['user']) && isset($url_parts['pass']))
7475
					{
7476
						$out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7477
					}
7478
					foreach ($headers as $key => $value)
7479
					{
7480
						$out .= "$key: $value\r\n";
7481
					}
7482
					$out .= "Connection: Close\r\n\r\n";
7483
					fwrite($fp, $out);
7484
7485
					$info = stream_get_meta_data($fp);
7486
7487
					$this->headers = '';
0 ignored issues
show
Documentation Bug introduced by
It seems like '' of type string is incompatible with the declared type array of property $headers.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
7488
					while (!$info['eof'] && !$info['timed_out'])
7489
					{
7490
						$this->headers .= fread($fp, 1160);
7491
						$info = stream_get_meta_data($fp);
7492
					}
7493
					if (!$info['timed_out'])
7494
					{
7495
						$parser = new SimplePie_HTTP_Parser($this->headers);
7496
						if ($parser->parse())
7497
						{
7498
							$this->headers = $parser->headers;
7499
							$this->body = $parser->body;
7500
							$this->status_code = $parser->status_code;
7501
							if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
7502
							{
7503
								$this->redirects++;
7504
								$location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7505
								$previousStatusCode = $this->status_code;
7506
								$this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7507
								$this->permanent_url = ($previousStatusCode == 301) ? $location : $url;
7508
								return;
7509
							}
7510
							if (isset($this->headers['content-encoding']))
7511
							{
7512
								// Hey, we act dumb elsewhere, so let's do that here too
7513
								switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7514
								{
7515
									case 'gzip':
7516
									case 'x-gzip':
7517
										$decoder = new SimplePie_gzdecode($this->body);
7518
										if (!$decoder->parse())
7519
										{
7520
											$this->error = 'Unable to decode HTTP "gzip" stream';
7521
											$this->success = false;
7522
										}
7523
										else
7524
										{
7525
											$this->body = trim($decoder->data);
7526
										}
7527
										break;
7528
7529
									case 'deflate':
7530
										if (($decompressed = gzinflate($this->body)) !== false)
7531
										{
7532
											$this->body = $decompressed;
7533
										}
7534
										else if (($decompressed = gzuncompress($this->body)) !== false)
7535
										{
7536
											$this->body = $decompressed;
7537
										}
7538
										else if (function_exists('gzdecode') && ($decompressed = gzdecode($this->body)) !== false)
7539
										{
7540
											$this->body = $decompressed;
7541
										}
7542
										else
7543
										{
7544
											$this->error = 'Unable to decode HTTP "deflate" stream';
7545
											$this->success = false;
7546
										}
7547
										break;
7548
7549
									default:
7550
										$this->error = 'Unknown content coding';
7551
										$this->success = false;
7552
								}
7553
							}
7554
						}
7555
					}
7556
					else
7557
					{
7558
						$this->error = 'fsocket timed out';
7559
						$this->success = false;
7560
					}
7561
					fclose($fp);
7562
				}
7563
			}
7564
		}
7565
		else
7566
		{
7567
			$this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7568
			if (empty($url) || !($this->body = trim(file_get_contents($url))))
7569
			{
7570
				$this->error = 'file_get_contents could not read the file';
7571
				$this->success = false;
7572
			}
7573
		}
7574
	}
7575
}
7576
7577
/**
7578
 * HTTP Response Parser
7579
 *
7580
 * @package SimplePie
7581
 * @subpackage HTTP
7582
 */
7583
class SimplePie_HTTP_Parser
7584
{
7585
	/**
7586
	 * HTTP Version
7587
	 *
7588
	 * @var float
7589
	 */
7590
	public $http_version = 0.0;
7591
7592
	/**
7593
	 * Status code
7594
	 *
7595
	 * @var int
7596
	 */
7597
	public $status_code = 0;
7598
7599
	/**
7600
	 * Reason phrase
7601
	 *
7602
	 * @var string
7603
	 */
7604
	public $reason = '';
7605
7606
	/**
7607
	 * Key/value pairs of the headers
7608
	 *
7609
	 * @var array
7610
	 */
7611
	public $headers = array();
7612
7613
	/**
7614
	 * Body of the response
7615
	 *
7616
	 * @var string
7617
	 */
7618
	public $body = '';
7619
7620
	/**
7621
	 * Current state of the state machine
7622
	 *
7623
	 * @var string
7624
	 */
7625
	protected $state = 'http_version';
7626
7627
	/**
7628
	 * Input data
7629
	 *
7630
	 * @var string
7631
	 */
7632
	protected $data = '';
7633
7634
	/**
7635
	 * Input data length (to avoid calling strlen() everytime this is needed)
7636
	 *
7637
	 * @var int
7638
	 */
7639
	protected $data_length = 0;
7640
7641
	/**
7642
	 * Current position of the pointer
7643
	 *
7644
	 * @var int
7645
	 */
7646
	protected $position = 0;
7647
7648
	/**
7649
	 * Name of the hedaer currently being parsed
7650
	 *
7651
	 * @var string
7652
	 */
7653
	protected $name = '';
7654
7655
	/**
7656
	 * Value of the hedaer currently being parsed
7657
	 *
7658
	 * @var string
7659
	 */
7660
	protected $value = '';
7661
7662
	/**
7663
	 * Create an instance of the class with the input data
7664
	 *
7665
	 * @param string $data Input data
7666
	 */
7667
	public function __construct($data)
7668
	{
7669
		$this->data = $data;
7670
		$this->data_length = strlen($this->data);
7671
	}
7672
7673
	/**
7674
	 * Parse the input data
7675
	 *
7676
	 * @return bool true on success, false on failure
7677
	 */
7678
	public function parse()
7679
	{
7680
		while ($this->state && $this->state !== 'emit' && $this->has_data())
7681
		{
7682
			$state = $this->state;
7683
			$this->$state();
7684
		}
7685
		$this->data = '';
7686
		if ($this->state === 'emit' || $this->state === 'body')
7687
		{
7688
			return true;
7689
		}
7690
		else
7691
		{
7692
			$this->http_version = '';
0 ignored issues
show
Documentation Bug introduced by
The property $http_version was declared of type double, but '' is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
7693
			$this->status_code = '';
0 ignored issues
show
Documentation Bug introduced by
The property $status_code was declared of type integer, but '' is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
7694
			$this->reason = '';
7695
			$this->headers = array();
7696
			$this->body = '';
7697
			return false;
7698
		}
7699
	}
7700
7701
	/**
7702
	 * Check whether there is data beyond the pointer
7703
	 *
7704
	 * @return bool true if there is further data, false if not
7705
	 */
7706
	protected function has_data()
7707
	{
7708
		return (bool) ($this->position < $this->data_length);
7709
	}
7710
7711
	/**
7712
	 * See if the next character is LWS
7713
	 *
7714
	 * @return bool true if the next character is LWS, false if not
7715
	 */
7716
	protected function is_linear_whitespace()
7717
	{
7718
		return (bool) ($this->data[$this->position] === "\x09"
7719
			|| $this->data[$this->position] === "\x20"
7720
			|| ($this->data[$this->position] === "\x0A"
7721
				&& isset($this->data[$this->position + 1])
7722
				&& ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
7723
	}
7724
7725
	/**
7726
	 * Parse the HTTP version
7727
	 */
7728
	protected function http_version()
7729
	{
7730
		if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
7731
		{
7732
			$len = strspn($this->data, '0123456789.', 5);
7733
			$this->http_version = substr($this->data, 5, $len);
0 ignored issues
show
Documentation Bug introduced by
The property $http_version was declared of type double, but substr($this->data, 5, $len) is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
7734
			$this->position += 5 + $len;
7735
			if (substr_count($this->http_version, '.') <= 1)
7736
			{
7737
				$this->http_version = (float) $this->http_version;
7738
				$this->position += strspn($this->data, "\x09\x20", $this->position);
7739
				$this->state = 'status';
7740
			}
7741
			else
7742
			{
7743
				$this->state = false;
0 ignored issues
show
Documentation Bug introduced by
The property $state was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
7744
			}
7745
		}
7746
		else
7747
		{
7748
			$this->state = false;
7749
		}
7750
	}
7751
7752
	/**
7753
	 * Parse the status code
7754
	 */
7755
	protected function status()
7756
	{
7757
		if ($len = strspn($this->data, '0123456789', $this->position))
7758
		{
7759
			$this->status_code = (int) substr($this->data, $this->position, $len);
7760
			$this->position += $len;
7761
			$this->state = 'reason';
7762
		}
7763
		else
7764
		{
7765
			$this->state = false;
0 ignored issues
show
Documentation Bug introduced by
The property $state was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
7766
		}
7767
	}
7768
7769
	/**
7770
	 * Parse the reason phrase
7771
	 */
7772
	protected function reason()
7773
	{
7774
		$len = strcspn($this->data, "\x0A", $this->position);
7775
		$this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
7776
		$this->position += $len + 1;
7777
		$this->state = 'new_line';
7778
	}
7779
7780
	/**
7781
	 * Deal with a new line, shifting data around as needed
7782
	 */
7783
	protected function new_line()
7784
	{
7785
		$this->value = trim($this->value, "\x0D\x20");
7786
		if ($this->name !== '' && $this->value !== '')
7787
		{
7788
			$this->name = strtolower($this->name);
7789
			// We should only use the last Content-Type header. c.f. issue #1
7790
			if (isset($this->headers[$this->name]) && $this->name !== 'content-type')
7791
			{
7792
				$this->headers[$this->name] .= ', ' . $this->value;
7793
			}
7794
			else
7795
			{
7796
				$this->headers[$this->name] = $this->value;
7797
			}
7798
		}
7799
		$this->name = '';
7800
		$this->value = '';
7801
		if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
7802
		{
7803
			$this->position += 2;
7804
			$this->state = 'body';
7805
		}
7806
		elseif ($this->data[$this->position] === "\x0A")
7807
		{
7808
			$this->position++;
7809
			$this->state = 'body';
7810
		}
7811
		else
7812
		{
7813
			$this->state = 'name';
7814
		}
7815
	}
7816
7817
	/**
7818
	 * Parse a header name
7819
	 */
7820
	protected function name()
7821
	{
7822
		$len = strcspn($this->data, "\x0A:", $this->position);
7823
		if (isset($this->data[$this->position + $len]))
7824
		{
7825
			if ($this->data[$this->position + $len] === "\x0A")
7826
			{
7827
				$this->position += $len;
7828
				$this->state = 'new_line';
7829
			}
7830
			else
7831
			{
7832
				$this->name = substr($this->data, $this->position, $len);
7833
				$this->position += $len + 1;
7834
				$this->state = 'value';
7835
			}
7836
		}
7837
		else
7838
		{
7839
			$this->state = false;
0 ignored issues
show
Documentation Bug introduced by
The property $state was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
7840
		}
7841
	}
7842
7843
	/**
7844
	 * Parse LWS, replacing consecutive LWS characters with a single space
7845
	 */
7846
	protected function linear_whitespace()
7847
	{
7848
		do
7849
		{
7850
			if (substr($this->data, $this->position, 2) === "\x0D\x0A")
7851
			{
7852
				$this->position += 2;
7853
			}
7854
			elseif ($this->data[$this->position] === "\x0A")
7855
			{
7856
				$this->position++;
7857
			}
7858
			$this->position += strspn($this->data, "\x09\x20", $this->position);
7859
		} while ($this->has_data() && $this->is_linear_whitespace());
7860
		$this->value .= "\x20";
7861
	}
7862
7863
	/**
7864
	 * See what state to move to while within non-quoted header values
7865
	 */
7866
	protected function value()
7867
	{
7868
		if ($this->is_linear_whitespace())
7869
		{
7870
			$this->linear_whitespace();
7871
		}
7872
		else
7873
		{
7874
			switch ($this->data[$this->position])
7875
			{
7876
				case '"':
7877
					// Workaround for ETags: we have to include the quotes as
7878
					// part of the tag.
7879
					if (strtolower($this->name) === 'etag')
7880
					{
7881
						$this->value .= '"';
7882
						$this->position++;
7883
						$this->state = 'value_char';
7884
						break;
7885
					}
7886
					$this->position++;
7887
					$this->state = 'quote';
7888
					break;
7889
7890
				case "\x0A":
7891
					$this->position++;
7892
					$this->state = 'new_line';
7893
					break;
7894
7895
				default:
7896
					$this->state = 'value_char';
7897
					break;
7898
			}
7899
		}
7900
	}
7901
7902
	/**
7903
	 * Parse a header value while outside quotes
7904
	 */
7905
	protected function value_char()
7906
	{
7907
		$len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
7908
		$this->value .= substr($this->data, $this->position, $len);
7909
		$this->position += $len;
7910
		$this->state = 'value';
7911
	}
7912
7913
	/**
7914
	 * See what state to move to while within quoted header values
7915
	 */
7916
	protected function quote()
7917
	{
7918
		if ($this->is_linear_whitespace())
7919
		{
7920
			$this->linear_whitespace();
7921
		}
7922
		else
7923
		{
7924
			switch ($this->data[$this->position])
7925
			{
7926
				case '"':
7927
					$this->position++;
7928
					$this->state = 'value';
7929
					break;
7930
7931
				case "\x0A":
7932
					$this->position++;
7933
					$this->state = 'new_line';
7934
					break;
7935
7936
				case '\\':
7937
					$this->position++;
7938
					$this->state = 'quote_escaped';
7939
					break;
7940
7941
				default:
7942
					$this->state = 'quote_char';
7943
					break;
7944
			}
7945
		}
7946
	}
7947
7948
	/**
7949
	 * Parse a header value while within quotes
7950
	 */
7951
	protected function quote_char()
7952
	{
7953
		$len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
7954
		$this->value .= substr($this->data, $this->position, $len);
7955
		$this->position += $len;
7956
		$this->state = 'value';
7957
	}
7958
7959
	/**
7960
	 * Parse an escaped character within quotes
7961
	 */
7962
	protected function quote_escaped()
7963
	{
7964
		$this->value .= $this->data[$this->position];
7965
		$this->position++;
7966
		$this->state = 'quote';
7967
	}
7968
7969
	/**
7970
	 * Parse the body
7971
	 */
7972
	protected function body()
7973
	{
7974
		$this->body = substr($this->data, $this->position);
7975
		if (!empty($this->headers['transfer-encoding']))
7976
		{
7977
			unset($this->headers['transfer-encoding']);
7978
			$this->state = 'chunked';
7979
		}
7980
		else
7981
		{
7982
			$this->state = 'emit';
7983
		}
7984
	}
7985
7986
	/**
7987
	 * Parsed a "Transfer-Encoding: chunked" body
7988
	 */
7989
	protected function chunked()
7990
	{
7991
		if (!preg_match('/^([0-9a-f]+)[^\r\n]*\r\n/i', trim($this->body)))
7992
		{
7993
			$this->state = 'emit';
7994
			return;
7995
		}
7996
7997
		$decoded = '';
7998
		$encoded = $this->body;
7999
8000
		while (true)
8001
		{
8002
			$is_chunked = (bool) preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', $encoded, $matches );
8003
			if (!$is_chunked)
8004
			{
8005
				// Looks like it's not chunked after all
8006
				$this->state = 'emit';
8007
				return;
8008
			}
8009
8010
			$length = hexdec(trim($matches[1]));
8011
			if ($length === 0)
8012
			{
8013
				// Ignore trailer headers
8014
				$this->state = 'emit';
8015
				$this->body = $decoded;
8016
				return;
8017
			}
8018
8019
			$chunk_length = strlen($matches[0]);
8020
			$decoded .= $part = substr($encoded, $chunk_length, $length);
0 ignored issues
show
Unused Code introduced by
$part is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
8021
			$encoded = substr($encoded, $chunk_length + $length + 2);
8022
8023
			if (trim($encoded) === '0' || empty($encoded))
8024
			{
8025
				$this->state = 'emit';
8026
				$this->body = $decoded;
8027
				return;
8028
			}
8029
		}
8030
	}
8031
8032
	/**
8033
	 * Prepare headers (take care of proxies headers)
8034
	 *
8035
	 * @param string  $headers Raw headers
8036
	 * @param integer $count   Redirection count. Default to 1.
8037
	 *
8038
	 * @return string
8039
	 */
8040
	static public function prepareHeaders($headers, $count = 1)
8041
	{
8042
		$data = explode("\r\n\r\n", $headers, $count);
8043
		$data = array_pop($data);
8044
		if (false !== stripos($data, "HTTP/1.0 200 Connection established\r\n\r\n")) {
8045
			$data = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $data);
8046
		}
8047
		return $data;
8048
	}
8049
}
8050
8051
/**
8052
 * IRI parser/serialiser/normaliser
8053
 *
8054
 * @package SimplePie
8055
 * @subpackage HTTP
8056
 * @author Geoffrey Sneddon
8057
 * @author Steve Minutillo
8058
 * @author Ryan McCue
8059
 * @copyright 2007-2012 Geoffrey Sneddon, Steve Minutillo, Ryan McCue
8060
 * @license http://www.opensource.org/licenses/bsd-license.php
8061
 */
8062
class SimplePie_IRI
8063
{
8064
	/**
8065
	 * Scheme
8066
	 *
8067
	 * @var string
8068
	 */
8069
	protected $scheme = null;
8070
8071
	/**
8072
	 * User Information
8073
	 *
8074
	 * @var string
8075
	 */
8076
	protected $iuserinfo = null;
8077
8078
	/**
8079
	 * ihost
8080
	 *
8081
	 * @var string
8082
	 */
8083
	protected $ihost = null;
8084
8085
	/**
8086
	 * Port
8087
	 *
8088
	 * @var string
8089
	 */
8090
	protected $port = null;
8091
8092
	/**
8093
	 * ipath
8094
	 *
8095
	 * @var string
8096
	 */
8097
	protected $ipath = '';
8098
8099
	/**
8100
	 * iquery
8101
	 *
8102
	 * @var string
8103
	 */
8104
	protected $iquery = null;
8105
8106
	/**
8107
	 * ifragment
8108
	 *
8109
	 * @var string
8110
	 */
8111
	protected $ifragment = null;
8112
8113
	/**
8114
	 * Normalization database
8115
	 *
8116
	 * Each key is the scheme, each value is an array with each key as the IRI
8117
	 * part and value as the default value for that part.
8118
	 */
8119
	protected $normalization = array(
8120
		'acap' => array(
8121
			'port' => 674
8122
		),
8123
		'dict' => array(
8124
			'port' => 2628
8125
		),
8126
		'file' => array(
8127
			'ihost' => 'localhost'
8128
		),
8129
		'http' => array(
8130
			'port' => 80,
8131
			'ipath' => '/'
8132
		),
8133
		'https' => array(
8134
			'port' => 443,
8135
			'ipath' => '/'
8136
		),
8137
	);
8138
8139
	/**
8140
	 * Return the entire IRI when you try and read the object as a string
8141
	 *
8142
	 * @return string
8143
	 */
8144
	public function __toString()
8145
	{
8146
		return $this->get_iri();
8147
	}
8148
8149
	/**
8150
	 * Overload __set() to provide access via properties
8151
	 *
8152
	 * @param string $name Property name
8153
	 * @param mixed $value Property value
8154
	 */
8155
	public function __set($name, $value)
8156
	{
8157
		if (method_exists($this, 'set_' . $name))
8158
		{
8159
			call_user_func(array($this, 'set_' . $name), $value);
8160
		}
8161
		elseif (
8162
			   $name === 'iauthority'
8163
			|| $name === 'iuserinfo'
8164
			|| $name === 'ihost'
8165
			|| $name === 'ipath'
8166
			|| $name === 'iquery'
8167
			|| $name === 'ifragment'
8168
		)
8169
		{
8170
			call_user_func(array($this, 'set_' . substr($name, 1)), $value);
8171
		}
8172
	}
8173
8174
	/**
8175
	 * Overload __get() to provide access via properties
8176
	 *
8177
	 * @param string $name Property name
8178
	 * @return mixed
8179
	 */
8180
	public function __get($name)
8181
	{
8182
		// isset() returns false for null, we don't want to do that
8183
		// Also why we use array_key_exists below instead of isset()
8184
		$props = get_object_vars($this);
8185
8186
		if (
8187
			$name === 'iri' ||
8188
			$name === 'uri' ||
8189
			$name === 'iauthority' ||
8190
			$name === 'authority'
8191
		)
8192
		{
8193
			$return = $this->{"get_$name"}();
8194
		}
8195
		elseif (array_key_exists($name, $props))
8196
		{
8197
			$return = $this->$name;
8198
		}
8199
		// host -> ihost
8200
		elseif (($prop = 'i' . $name) && array_key_exists($prop, $props))
8201
		{
8202
			$name = $prop;
8203
			$return = $this->$prop;
8204
		}
8205
		// ischeme -> scheme
8206
		elseif (($prop = substr($name, 1)) && array_key_exists($prop, $props))
8207
		{
8208
			$name = $prop;
8209
			$return = $this->$prop;
8210
		}
8211
		else
8212
		{
8213
			trigger_error('Undefined property: ' . get_class($this) . '::' . $name, E_USER_NOTICE);
8214
			$return = null;
8215
		}
8216
8217
		if ($return === null && isset($this->normalization[$this->scheme][$name]))
8218
		{
8219
			return $this->normalization[$this->scheme][$name];
8220
		}
8221
		else
8222
		{
8223
			return $return;
8224
		}
8225
	}
8226
8227
	/**
8228
	 * Overload __isset() to provide access via properties
8229
	 *
8230
	 * @param string $name Property name
8231
	 * @return bool
8232
	 */
8233
	public function __isset($name)
8234
	{
8235
		if (method_exists($this, 'get_' . $name) || isset($this->$name))
8236
		{
8237
			return true;
8238
		}
8239
		else
8240
		{
8241
			return false;
8242
		}
8243
	}
8244
8245
	/**
8246
	 * Overload __unset() to provide access via properties
8247
	 *
8248
	 * @param string $name Property name
8249
	 */
8250
	public function __unset($name)
8251
	{
8252
		if (method_exists($this, 'set_' . $name))
8253
		{
8254
			call_user_func(array($this, 'set_' . $name), '');
8255
		}
8256
	}
8257
8258
	/**
8259
	 * Create a new IRI object, from a specified string
8260
	 *
8261
	 * @param string $iri
8262
	 */
8263
	public function __construct($iri = null)
8264
	{
8265
		$this->set_iri($iri);
8266
	}
8267
8268
	/**
8269
	 * Clean up
8270
	 */
8271
	public function __destruct() {
8272
	    $this->set_iri(null, true);
8273
	    $this->set_path(null, true);
8274
	    $this->set_authority(null, true);
8275
	}
8276
8277
	/**
8278
	 * Create a new IRI object by resolving a relative IRI
8279
	 *
8280
	 * Returns false if $base is not absolute, otherwise an IRI.
8281
	 *
8282
	 * @param IRI|string $base (Absolute) Base IRI
8283
	 * @param IRI|string $relative Relative IRI
8284
	 * @return IRI|false
8285
	 */
8286
	public static function absolutize($base, $relative)
8287
	{
8288
		if (!($relative instanceof SimplePie_IRI))
8289
		{
8290
			$relative = new SimplePie_IRI($relative);
8291
		}
8292
		if (!$relative->is_valid())
8293
		{
8294
			return false;
8295
		}
8296
		elseif ($relative->scheme !== null)
8297
		{
8298
			return clone $relative;
8299
		}
8300
		else
8301
		{
8302
			if (!($base instanceof SimplePie_IRI))
8303
			{
8304
				$base = new SimplePie_IRI($base);
8305
			}
8306
			if ($base->scheme !== null && $base->is_valid())
8307
			{
8308
				if ($relative->get_iri() !== '')
8309
				{
8310
					if ($relative->iuserinfo !== null || $relative->ihost !== null || $relative->port !== null)
8311
					{
8312
						$target = clone $relative;
8313
						$target->scheme = $base->scheme;
8314
					}
8315
					else
8316
					{
8317
						$target = new SimplePie_IRI;
8318
						$target->scheme = $base->scheme;
8319
						$target->iuserinfo = $base->iuserinfo;
8320
						$target->ihost = $base->ihost;
8321
						$target->port = $base->port;
8322
						if ($relative->ipath !== '')
8323
						{
8324
							if ($relative->ipath[0] === '/')
8325
							{
8326
								$target->ipath = $relative->ipath;
8327
							}
8328
							elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '')
8329
							{
8330
								$target->ipath = '/' . $relative->ipath;
8331
							}
8332
							elseif (($last_segment = strrpos($base->ipath, '/')) !== false)
8333
							{
8334
								$target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath;
8335
							}
8336
							else
8337
							{
8338
								$target->ipath = $relative->ipath;
8339
							}
8340
							$target->ipath = $target->remove_dot_segments($target->ipath);
8341
							$target->iquery = $relative->iquery;
8342
						}
8343
						else
8344
						{
8345
							$target->ipath = $base->ipath;
8346
							if ($relative->iquery !== null)
8347
							{
8348
								$target->iquery = $relative->iquery;
8349
							}
8350
							elseif ($base->iquery !== null)
8351
							{
8352
								$target->iquery = $base->iquery;
8353
							}
8354
						}
8355
						$target->ifragment = $relative->ifragment;
8356
					}
8357
				}
8358
				else
8359
				{
8360
					$target = clone $base;
8361
					$target->ifragment = null;
8362
				}
8363
				$target->scheme_normalization();
8364
				return $target;
8365
			}
8366
			else
8367
			{
8368
				return false;
8369
			}
8370
		}
8371
	}
8372
8373
	/**
8374
	 * Parse an IRI into scheme/authority/path/query/fragment segments
8375
	 *
8376
	 * @param string $iri
8377
	 * @return array
8378
	 */
8379
	protected function parse_iri($iri)
8380
	{
8381
		$iri = trim($iri, "\x20\x09\x0A\x0C\x0D");
8382
		if (preg_match('/^((?P<scheme>[^:\/?#]+):)?(\/\/(?P<authority>[^\/?#]*))?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))?$/', $iri, $match))
8383
		{
8384
			if ($match[1] === '')
8385
			{
8386
				$match['scheme'] = null;
8387
			}
8388
			if (!isset($match[3]) || $match[3] === '')
8389
			{
8390
				$match['authority'] = null;
8391
			}
8392
			if (!isset($match[5]))
8393
			{
8394
				$match['path'] = '';
8395
			}
8396
			if (!isset($match[6]) || $match[6] === '')
8397
			{
8398
				$match['query'] = null;
8399
			}
8400
			if (!isset($match[8]) || $match[8] === '')
8401
			{
8402
				$match['fragment'] = null;
8403
			}
8404
			return $match;
8405
		}
8406
		else
8407
		{
8408
			// This can occur when a paragraph is accidentally parsed as a URI
8409
			return false;
8410
		}
8411
	}
8412
8413
	/**
8414
	 * Remove dot segments from a path
8415
	 *
8416
	 * @param string $input
8417
	 * @return string
8418
	 */
8419
	protected function remove_dot_segments($input)
8420
	{
8421
		$output = '';
8422
		while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
8423
		{
8424
			// A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
8425
			if (strpos($input, '../') === 0)
8426
			{
8427
				$input = substr($input, 3);
8428
			}
8429
			elseif (strpos($input, './') === 0)
8430
			{
8431
				$input = substr($input, 2);
8432
			}
8433
			// B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise,
8434
			elseif (strpos($input, '/./') === 0)
8435
			{
8436
				$input = substr($input, 2);
8437
			}
8438
			elseif ($input === '/.')
8439
			{
8440
				$input = '/';
8441
			}
8442
			// C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise,
8443
			elseif (strpos($input, '/../') === 0)
8444
			{
8445
				$input = substr($input, 3);
8446
				$output = substr_replace($output, '', strrpos($output, '/'));
8447
			}
8448
			elseif ($input === '/..')
8449
			{
8450
				$input = '/';
8451
				$output = substr_replace($output, '', strrpos($output, '/'));
8452
			}
8453
			// D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
8454
			elseif ($input === '.' || $input === '..')
8455
			{
8456
				$input = '';
8457
			}
8458
			// E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer
8459
			elseif (($pos = strpos($input, '/', 1)) !== false)
8460
			{
8461
				$output .= substr($input, 0, $pos);
8462
				$input = substr_replace($input, '', 0, $pos);
8463
			}
8464
			else
8465
			{
8466
				$output .= $input;
8467
				$input = '';
8468
			}
8469
		}
8470
		return $output . $input;
8471
	}
8472
8473
	/**
8474
	 * Replace invalid character with percent encoding
8475
	 *
8476
	 * @param string $string Input string
8477
	 * @param string $extra_chars Valid characters not in iunreserved or
8478
	 *                            iprivate (this is ASCII-only)
8479
	 * @param bool $iprivate Allow iprivate
8480
	 * @return string
8481
	 */
8482
	protected function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false)
8483
	{
8484
		// Normalize as many pct-encoded sections as possible
8485
		$string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array($this, 'remove_iunreserved_percent_encoded'), $string);
8486
8487
		// Replace invalid percent characters
8488
		$string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string);
8489
8490
		// Add unreserved and % to $extra_chars (the latter is safe because all
8491
		// pct-encoded sections are now valid).
8492
		$extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%';
8493
8494
		// Now replace any bytes that aren't allowed with their pct-encoded versions
8495
		$position = 0;
8496
		$strlen = strlen($string);
8497
		while (($position += strspn($string, $extra_chars, $position)) < $strlen)
8498
		{
8499
			$value = ord($string[$position]);
8500
8501
			// Start position
8502
			$start = $position;
8503
8504
			// By default we are valid
8505
			$valid = true;
8506
8507
			// No one byte sequences are valid due to the while.
8508
			// Two byte sequence:
8509
			if (($value & 0xE0) === 0xC0)
8510
			{
8511
				$character = ($value & 0x1F) << 6;
8512
				$length = 2;
8513
				$remaining = 1;
8514
			}
8515
			// Three byte sequence:
8516
			elseif (($value & 0xF0) === 0xE0)
8517
			{
8518
				$character = ($value & 0x0F) << 12;
8519
				$length = 3;
8520
				$remaining = 2;
8521
			}
8522
			// Four byte sequence:
8523
			elseif (($value & 0xF8) === 0xF0)
8524
			{
8525
				$character = ($value & 0x07) << 18;
8526
				$length = 4;
8527
				$remaining = 3;
8528
			}
8529
			// Invalid byte:
8530
			else
8531
			{
8532
				$valid = false;
8533
				$length = 1;
8534
				$remaining = 0;
8535
			}
8536
8537
			if ($remaining)
8538
			{
8539
				if ($position + $length <= $strlen)
8540
				{
8541
					for ($position++; $remaining; $position++)
8542
					{
8543
						$value = ord($string[$position]);
8544
8545
						// Check that the byte is valid, then add it to the character:
8546
						if (($value & 0xC0) === 0x80)
8547
						{
8548
							$character |= ($value & 0x3F) << (--$remaining * 6);
0 ignored issues
show
Bug introduced by
The variable $character does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
8549
						}
8550
						// If it is invalid, count the sequence as invalid and reprocess the current byte:
8551
						else
8552
						{
8553
							$valid = false;
8554
							$position--;
8555
							break;
8556
						}
8557
					}
8558
				}
8559
				else
8560
				{
8561
					$position = $strlen - 1;
8562
					$valid = false;
8563
				}
8564
			}
8565
8566
			// Percent encode anything invalid or not in ucschar
8567
			if (
8568
				// Invalid sequences
8569
				!$valid
8570
				// Non-shortest form sequences are invalid
8571
				|| $length > 1 && $character <= 0x7F
8572
				|| $length > 2 && $character <= 0x7FF
8573
				|| $length > 3 && $character <= 0xFFFF
8574
				// Outside of range of ucschar codepoints
8575
				// Noncharacters
8576
				|| ($character & 0xFFFE) === 0xFFFE
8577
				|| $character >= 0xFDD0 && $character <= 0xFDEF
8578
				|| (
8579
					// Everything else not in ucschar
8580
					   $character > 0xD7FF && $character < 0xF900
8581
					|| $character < 0xA0
8582
					|| $character > 0xEFFFD
8583
				)
8584
				&& (
8585
					// Everything not in iprivate, if it applies
8586
					   !$iprivate
8587
					|| $character < 0xE000
8588
					|| $character > 0x10FFFD
8589
				)
8590
			)
8591
			{
8592
				// If we were a character, pretend we weren't, but rather an error.
8593
				if ($valid)
8594
					$position--;
8595
8596
				for ($j = $start; $j <= $position; $j++)
8597
				{
8598
					$string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1);
8599
					$j += 2;
8600
					$position += 2;
8601
					$strlen += 2;
8602
				}
8603
			}
8604
		}
8605
8606
		return $string;
8607
	}
8608
8609
	/**
8610
	 * Callback function for preg_replace_callback.
8611
	 *
8612
	 * Removes sequences of percent encoded bytes that represent UTF-8
8613
	 * encoded characters in iunreserved
8614
	 *
8615
	 * @param array $match PCRE match
8616
	 * @return string Replacement
8617
	 */
8618
	protected function remove_iunreserved_percent_encoded($match)
8619
	{
8620
		// As we just have valid percent encoded sequences we can just explode
8621
		// and ignore the first member of the returned array (an empty string).
8622
		$bytes = explode('%', $match[0]);
8623
8624
		// Initialize the new string (this is what will be returned) and that
8625
		// there are no bytes remaining in the current sequence (unsurprising
8626
		// at the first byte!).
8627
		$string = '';
8628
		$remaining = 0;
8629
8630
		// Loop over each and every byte, and set $value to its value
8631
		for ($i = 1, $len = count($bytes); $i < $len; $i++)
8632
		{
8633
			$value = hexdec($bytes[$i]);
8634
8635
			// If we're the first byte of sequence:
8636
			if (!$remaining)
8637
			{
8638
				// Start position
8639
				$start = $i;
8640
8641
				// By default we are valid
8642
				$valid = true;
8643
8644
				// One byte sequence:
8645
				if ($value <= 0x7F)
8646
				{
8647
					$character = $value;
8648
					$length = 1;
8649
				}
8650
				// Two byte sequence:
8651
				elseif (($value & 0xE0) === 0xC0)
8652
				{
8653
					$character = ($value & 0x1F) << 6;
8654
					$length = 2;
8655
					$remaining = 1;
8656
				}
8657
				// Three byte sequence:
8658
				elseif (($value & 0xF0) === 0xE0)
8659
				{
8660
					$character = ($value & 0x0F) << 12;
8661
					$length = 3;
8662
					$remaining = 2;
8663
				}
8664
				// Four byte sequence:
8665
				elseif (($value & 0xF8) === 0xF0)
8666
				{
8667
					$character = ($value & 0x07) << 18;
8668
					$length = 4;
8669
					$remaining = 3;
8670
				}
8671
				// Invalid byte:
8672
				else
8673
				{
8674
					$valid = false;
8675
					$remaining = 0;
8676
				}
8677
			}
8678
			// Continuation byte:
8679
			else
8680
			{
8681
				// Check that the byte is valid, then add it to the character:
8682
				if (($value & 0xC0) === 0x80)
8683
				{
8684
					$remaining--;
8685
					$character |= ($value & 0x3F) << ($remaining * 6);
0 ignored issues
show
Bug introduced by
The variable $character does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
8686
				}
8687
				// If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence:
8688
				else
8689
				{
8690
					$valid = false;
8691
					$remaining = 0;
8692
					$i--;
8693
				}
8694
			}
8695
8696
			// If we've reached the end of the current byte sequence, append it to Unicode::$data
8697
			if (!$remaining)
8698
			{
8699
				// Percent encode anything invalid or not in iunreserved
8700
				if (
8701
					// Invalid sequences
8702
					!$valid
0 ignored issues
show
Bug introduced by
The variable $valid does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
8703
					// Non-shortest form sequences are invalid
8704
					|| $length > 1 && $character <= 0x7F
0 ignored issues
show
Bug introduced by
The variable $length does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
8705
					|| $length > 2 && $character <= 0x7FF
8706
					|| $length > 3 && $character <= 0xFFFF
8707
					// Outside of range of iunreserved codepoints
8708
					|| $character < 0x2D
8709
					|| $character > 0xEFFFD
8710
					// Noncharacters
8711
					|| ($character & 0xFFFE) === 0xFFFE
8712
					|| $character >= 0xFDD0 && $character <= 0xFDEF
8713
					// Everything else not in iunreserved (this is all BMP)
8714
					|| $character === 0x2F
8715
					|| $character > 0x39 && $character < 0x41
8716
					|| $character > 0x5A && $character < 0x61
8717
					|| $character > 0x7A && $character < 0x7E
8718
					|| $character > 0x7E && $character < 0xA0
8719
					|| $character > 0xD7FF && $character < 0xF900
8720
				)
8721
				{
8722
					for ($j = $start; $j <= $i; $j++)
0 ignored issues
show
Bug introduced by
The variable $start does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
8723
					{
8724
						$string .= '%' . strtoupper($bytes[$j]);
8725
					}
8726
				}
8727
				else
8728
				{
8729
					for ($j = $start; $j <= $i; $j++)
8730
					{
8731
						$string .= chr(hexdec($bytes[$j]));
8732
					}
8733
				}
8734
			}
8735
		}
8736
8737
		// If we have any bytes left over they are invalid (i.e., we are
8738
		// mid-way through a multi-byte sequence)
8739
		if ($remaining)
8740
		{
8741
			for ($j = $start; $j < $len; $j++)
8742
			{
8743
				$string .= '%' . strtoupper($bytes[$j]);
8744
			}
8745
		}
8746
8747
		return $string;
8748
	}
8749
8750
	protected function scheme_normalization()
8751
	{
8752
		if (isset($this->normalization[$this->scheme]['iuserinfo']) && $this->iuserinfo === $this->normalization[$this->scheme]['iuserinfo'])
8753
		{
8754
			$this->iuserinfo = null;
8755
		}
8756
		if (isset($this->normalization[$this->scheme]['ihost']) && $this->ihost === $this->normalization[$this->scheme]['ihost'])
8757
		{
8758
			$this->ihost = null;
8759
		}
8760
		if (isset($this->normalization[$this->scheme]['port']) && $this->port === $this->normalization[$this->scheme]['port'])
8761
		{
8762
			$this->port = null;
8763
		}
8764
		if (isset($this->normalization[$this->scheme]['ipath']) && $this->ipath === $this->normalization[$this->scheme]['ipath'])
8765
		{
8766
			$this->ipath = '';
8767
		}
8768
		if (isset($this->normalization[$this->scheme]['iquery']) && $this->iquery === $this->normalization[$this->scheme]['iquery'])
8769
		{
8770
			$this->iquery = null;
8771
		}
8772
		if (isset($this->normalization[$this->scheme]['ifragment']) && $this->ifragment === $this->normalization[$this->scheme]['ifragment'])
8773
		{
8774
			$this->ifragment = null;
8775
		}
8776
	}
8777
8778
	/**
8779
	 * Check if the object represents a valid IRI. This needs to be done on each
8780
	 * call as some things change depending on another part of the IRI.
8781
	 *
8782
	 * @return bool
8783
	 */
8784
	public function is_valid()
8785
	{
8786
		if ($this->ipath === '') return true;
8787
8788
		$isauthority = $this->iuserinfo !== null || $this->ihost !== null ||
8789
			$this->port !== null;
8790
		if ($isauthority && $this->ipath[0] === '/') return true;
8791
8792
		if (!$isauthority && (substr($this->ipath, 0, 2) === '//')) return false;
8793
8794
		// Relative urls cannot have a colon in the first path segment (and the
8795
		// slashes themselves are not included so skip the first character).
8796
		if (!$this->scheme && !$isauthority &&
8797
		    strpos($this->ipath, ':') !== false &&
8798
		    strpos($this->ipath, '/', 1) !== false &&
8799
		    strpos($this->ipath, ':') < strpos($this->ipath, '/', 1)) return false;
8800
8801
		return true;
8802
	}
8803
8804
	/**
8805
	 * Set the entire IRI. Returns true on success, false on failure (if there
8806
	 * are any invalid characters).
8807
	 *
8808
	 * @param string $iri
8809
	 * @return bool
8810
	 */
8811
	public function set_iri($iri, $clear_cache = false)
8812
	{
8813
		static $cache;
8814
		if ($clear_cache) 
8815
		{
8816
			$cache = null;
8817
			return;
8818
		}
8819
		if (!$cache)
8820
		{
8821
			$cache = array();
8822
		}
8823
8824
		if ($iri === null)
8825
		{
8826
			return true;
8827
		}
8828
		elseif (isset($cache[$iri]))
8829
		{
8830
			list($this->scheme,
8831
				 $this->iuserinfo,
8832
				 $this->ihost,
8833
				 $this->port,
8834
				 $this->ipath,
8835
				 $this->iquery,
8836
				 $this->ifragment,
8837
				 $return) = $cache[$iri];
8838
			return $return;
8839
		}
8840
		else
8841
		{
8842
			$parsed = $this->parse_iri((string) $iri);
8843
			if (!$parsed)
8844
			{
8845
				return false;
8846
			}
8847
8848
			$return = $this->set_scheme($parsed['scheme'])
8849
				&& $this->set_authority($parsed['authority'])
8850
				&& $this->set_path($parsed['path'])
8851
				&& $this->set_query($parsed['query'])
8852
				&& $this->set_fragment($parsed['fragment']);
8853
8854
			$cache[$iri] = array($this->scheme,
8855
								 $this->iuserinfo,
8856
								 $this->ihost,
8857
								 $this->port,
8858
								 $this->ipath,
8859
								 $this->iquery,
8860
								 $this->ifragment,
8861
								 $return);
8862
			return $return;
8863
		}
8864
	}
8865
8866
	/**
8867
	 * Set the scheme. Returns true on success, false on failure (if there are
8868
	 * any invalid characters).
8869
	 *
8870
	 * @param string $scheme
8871
	 * @return bool
8872
	 */
8873
	public function set_scheme($scheme)
8874
	{
8875
		if ($scheme === null)
8876
		{
8877
			$this->scheme = null;
8878
		}
8879
		elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme))
8880
		{
8881
			$this->scheme = null;
8882
			return false;
8883
		}
8884
		else
8885
		{
8886
			$this->scheme = strtolower($scheme);
8887
		}
8888
		return true;
8889
	}
8890
8891
	/**
8892
	 * Set the authority. Returns true on success, false on failure (if there are
8893
	 * any invalid characters).
8894
	 *
8895
	 * @param string $authority
8896
	 * @return bool
8897
	 */
8898
	public function set_authority($authority, $clear_cache = false)
8899
	{
8900
		static $cache;
8901
		if ($clear_cache)
8902
		{
8903
			$cache = null;
8904
			return;
8905
		}
8906
		if (!$cache)
8907
			$cache = array();
8908
8909
		if ($authority === null)
8910
		{
8911
			$this->iuserinfo = null;
8912
			$this->ihost = null;
8913
			$this->port = null;
8914
			return true;
8915
		}
8916
		elseif (isset($cache[$authority]))
8917
		{
8918
			list($this->iuserinfo,
8919
				 $this->ihost,
8920
				 $this->port,
8921
				 $return) = $cache[$authority];
8922
8923
			return $return;
8924
		}
8925
		else
8926
		{
8927
			$remaining = $authority;
8928
			if (($iuserinfo_end = strrpos($remaining, '@')) !== false)
8929
			{
8930
				$iuserinfo = substr($remaining, 0, $iuserinfo_end);
8931
				$remaining = substr($remaining, $iuserinfo_end + 1);
8932
			}
8933
			else
8934
			{
8935
				$iuserinfo = null;
8936
			}
8937
			if (($port_start = strpos($remaining, ':', strpos($remaining, ']'))) !== false)
8938
			{
8939
				if (($port = substr($remaining, $port_start + 1)) === false)
8940
				{
8941
					$port = null;
8942
				}
8943
				$remaining = substr($remaining, 0, $port_start);
8944
			}
8945
			else
8946
			{
8947
				$port = null;
8948
			}
8949
8950
			$return = $this->set_userinfo($iuserinfo) &&
8951
					  $this->set_host($remaining) &&
8952
					  $this->set_port($port);
8953
8954
			$cache[$authority] = array($this->iuserinfo,
8955
									   $this->ihost,
8956
									   $this->port,
8957
									   $return);
8958
8959
			return $return;
8960
		}
8961
	}
8962
8963
	/**
8964
	 * Set the iuserinfo.
8965
	 *
8966
	 * @param string $iuserinfo
8967
	 * @return bool
8968
	 */
8969
	public function set_userinfo($iuserinfo)
8970
	{
8971
		if ($iuserinfo === null)
8972
		{
8973
			$this->iuserinfo = null;
8974
		}
8975
		else
8976
		{
8977
			$this->iuserinfo = $this->replace_invalid_with_pct_encoding($iuserinfo, '!$&\'()*+,;=:');
8978
			$this->scheme_normalization();
8979
		}
8980
8981
		return true;
8982
	}
8983
8984
	/**
8985
	 * Set the ihost. Returns true on success, false on failure (if there are
8986
	 * any invalid characters).
8987
	 *
8988
	 * @param string $ihost
8989
	 * @return bool
8990
	 */
8991
	public function set_host($ihost)
8992
	{
8993
		if ($ihost === null)
8994
		{
8995
			$this->ihost = null;
8996
			return true;
8997
		}
8998
		elseif (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']')
8999
		{
9000
			if (SimplePie_Net_IPv6::check_ipv6(substr($ihost, 1, -1)))
9001
			{
9002
				$this->ihost = '[' . SimplePie_Net_IPv6::compress(substr($ihost, 1, -1)) . ']';
9003
			}
9004
			else
9005
			{
9006
				$this->ihost = null;
9007
				return false;
9008
			}
9009
		}
9010
		else
9011
		{
9012
			$ihost = $this->replace_invalid_with_pct_encoding($ihost, '!$&\'()*+,;=');
9013
9014
			// Lowercase, but ignore pct-encoded sections (as they should
9015
			// remain uppercase). This must be done after the previous step
9016
			// as that can add unescaped characters.
9017
			$position = 0;
9018
			$strlen = strlen($ihost);
9019
			while (($position += strcspn($ihost, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ%', $position)) < $strlen)
9020
			{
9021
				if ($ihost[$position] === '%')
9022
				{
9023
					$position += 3;
9024
				}
9025
				else
9026
				{
9027
					$ihost[$position] = strtolower($ihost[$position]);
9028
					$position++;
9029
				}
9030
			}
9031
9032
			$this->ihost = $ihost;
9033
		}
9034
9035
		$this->scheme_normalization();
9036
9037
		return true;
9038
	}
9039
9040
	/**
9041
	 * Set the port. Returns true on success, false on failure (if there are
9042
	 * any invalid characters).
9043
	 *
9044
	 * @param string $port
9045
	 * @return bool
9046
	 */
9047
	public function set_port($port)
9048
	{
9049
		if ($port === null)
9050
		{
9051
			$this->port = null;
9052
			return true;
9053
		}
9054
		elseif (strspn($port, '0123456789') === strlen($port))
9055
		{
9056
			$this->port = (int) $port;
0 ignored issues
show
Documentation Bug introduced by
The property $port was declared of type string, but (int) $port is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
9057
			$this->scheme_normalization();
9058
			return true;
9059
		}
9060
		else
9061
		{
9062
			$this->port = null;
9063
			return false;
9064
		}
9065
	}
9066
9067
	/**
9068
	 * Set the ipath.
9069
	 *
9070
	 * @param string $ipath
9071
	 * @return bool
9072
	 */
9073
	public function set_path($ipath, $clear_cache = false)
9074
	{
9075
		static $cache;
9076
		if ($clear_cache) 
9077
		{
9078
			$cache = null;
9079
			return;
9080
		}
9081
		if (!$cache)
9082
		{
9083
			$cache = array();
9084
		}
9085
9086
		$ipath = (string) $ipath;
9087
9088
		if (isset($cache[$ipath]))
9089
		{
9090
			$this->ipath = $cache[$ipath][(int) ($this->scheme !== null)];
9091
		}
9092
		else
9093
		{
9094
			$valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\'()*+,;=@:/');
9095
			$removed = $this->remove_dot_segments($valid);
9096
9097
			$cache[$ipath] = array($valid, $removed);
9098
			$this->ipath =  ($this->scheme !== null) ? $removed : $valid;
9099
		}
9100
9101
		$this->scheme_normalization();
9102
		return true;
9103
	}
9104
9105
	/**
9106
	 * Set the iquery.
9107
	 *
9108
	 * @param string $iquery
9109
	 * @return bool
9110
	 */
9111
	public function set_query($iquery)
9112
	{
9113
		if ($iquery === null)
9114
		{
9115
			$this->iquery = null;
9116
		}
9117
		else
9118
		{
9119
			$this->iquery = $this->replace_invalid_with_pct_encoding($iquery, '!$&\'()*+,;=:@/?', true);
9120
			$this->scheme_normalization();
9121
		}
9122
		return true;
9123
	}
9124
9125
	/**
9126
	 * Set the ifragment.
9127
	 *
9128
	 * @param string $ifragment
9129
	 * @return bool
9130
	 */
9131
	public function set_fragment($ifragment)
9132
	{
9133
		if ($ifragment === null)
9134
		{
9135
			$this->ifragment = null;
9136
		}
9137
		else
9138
		{
9139
			$this->ifragment = $this->replace_invalid_with_pct_encoding($ifragment, '!$&\'()*+,;=:@/?');
9140
			$this->scheme_normalization();
9141
		}
9142
		return true;
9143
	}
9144
9145
	/**
9146
	 * Convert an IRI to a URI (or parts thereof)
9147
	 *
9148
	 * @return string
9149
	 */
9150
	public function to_uri($string)
9151
	{
9152
		static $non_ascii;
9153
		if (!$non_ascii)
9154
		{
9155
			$non_ascii = implode('', range("\x80", "\xFF"));
9156
		}
9157
9158
		$position = 0;
9159
		$strlen = strlen($string);
9160
		while (($position += strcspn($string, $non_ascii, $position)) < $strlen)
9161
		{
9162
			$string = substr_replace($string, sprintf('%%%02X', ord($string[$position])), $position, 1);
9163
			$position += 3;
9164
			$strlen += 2;
9165
		}
9166
9167
		return $string;
9168
	}
9169
9170
	/**
9171
	 * Get the complete IRI
9172
	 *
9173
	 * @return string
9174
	 */
9175
	public function get_iri()
9176
	{
9177
		if (!$this->is_valid())
9178
		{
9179
			return false;
9180
		}
9181
9182
		$iri = '';
9183
		if ($this->scheme !== null)
9184
		{
9185
			$iri .= $this->scheme . ':';
9186
		}
9187
		if (($iauthority = $this->get_iauthority()) !== null)
9188
		{
9189
			$iri .= '//' . $iauthority;
9190
		}
9191
		if ($this->ipath !== '')
9192
		{
9193
			$iri .= $this->ipath;
9194
		}
9195
		elseif (!empty($this->normalization[$this->scheme]['ipath']) && $iauthority !== null && $iauthority !== '')
9196
		{
9197
			$iri .= $this->normalization[$this->scheme]['ipath'];
9198
		}
9199
		if ($this->iquery !== null)
9200
		{
9201
			$iri .= '?' . $this->iquery;
9202
		}
9203
		if ($this->ifragment !== null)
9204
		{
9205
			$iri .= '#' . $this->ifragment;
9206
		}
9207
9208
		return $iri;
9209
	}
9210
9211
	/**
9212
	 * Get the complete URI
9213
	 *
9214
	 * @return string
9215
	 */
9216
	public function get_uri()
9217
	{
9218
		return $this->to_uri($this->get_iri());
9219
	}
9220
9221
	/**
9222
	 * Get the complete iauthority
9223
	 *
9224
	 * @return string
9225
	 */
9226
	protected function get_iauthority()
9227
	{
9228
		if ($this->iuserinfo !== null || $this->ihost !== null || $this->port !== null)
9229
		{
9230
			$iauthority = '';
9231
			if ($this->iuserinfo !== null)
9232
			{
9233
				$iauthority .= $this->iuserinfo . '@';
9234
			}
9235
			if ($this->ihost !== null)
9236
			{
9237
				$iauthority .= $this->ihost;
9238
			}
9239
			if ($this->port !== null)
9240
			{
9241
				$iauthority .= ':' . $this->port;
9242
			}
9243
			return $iauthority;
9244
		}
9245
		else
9246
		{
9247
			return null;
9248
		}
9249
	}
9250
9251
	/**
9252
	 * Get the complete authority
9253
	 *
9254
	 * @return string
9255
	 */
9256
	protected function get_authority()
9257
	{
9258
		$iauthority = $this->get_iauthority();
9259
		if (is_string($iauthority))
9260
			return $this->to_uri($iauthority);
9261
		else
9262
			return $iauthority;
9263
	}
9264
}
9265
9266
/**
9267
 * Manages all item-related data
9268
 *
9269
 * Used by {@see SimplePie::get_item()} and {@see SimplePie::get_items()}
9270
 *
9271
 * This class can be overloaded with {@see SimplePie::set_item_class()}
9272
 *
9273
 * @package SimplePie
9274
 * @subpackage API
9275
 */
9276
class SimplePie_Item
9277
{
9278
	/**
9279
	 * Parent feed
9280
	 *
9281
	 * @access private
9282
	 * @var SimplePie
9283
	 */
9284
	var $feed;
9285
9286
	/**
9287
	 * Raw data
9288
	 *
9289
	 * @access private
9290
	 * @var array
9291
	 */
9292
	var $data = array();
9293
9294
	/**
9295
	 * Registry object
9296
	 *
9297
	 * @see set_registry
9298
	 * @var SimplePie_Registry
9299
	 */
9300
	protected $registry;
9301
9302
	/**
9303
	 * Create a new item object
9304
	 *
9305
	 * This is usually used by {@see SimplePie::get_items} and
9306
	 * {@see SimplePie::get_item}. Avoid creating this manually.
9307
	 *
9308
	 * @param SimplePie $feed Parent feed
9309
	 * @param array $data Raw data
9310
	 */
9311
	public function __construct($feed, $data)
9312
	{
9313
		$this->feed = $feed;
9314
		$this->data = $data;
9315
	}
9316
9317
	/**
9318
	 * Set the registry handler
9319
	 *
9320
	 * This is usually used by {@see SimplePie_Registry::create}
9321
	 *
9322
	 * @since 1.3
9323
	 * @param SimplePie_Registry $registry
9324
	 */
9325
	public function set_registry(SimplePie_Registry $registry)
9326
	{
9327
		$this->registry = $registry;
9328
	}
9329
9330
	/**
9331
	 * Get a string representation of the item
9332
	 *
9333
	 * @return string
9334
	 */
9335
	public function __toString()
9336
	{
9337
		return md5(serialize($this->data));
9338
	}
9339
9340
	/**
9341
	 * Remove items that link back to this before destroying this object
9342
	 */
9343
	public function __destruct()
9344
	{
9345
		if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
9346
		{
9347
			unset($this->feed);
9348
		}
9349
	}
9350
9351
	/**
9352
	 * Get data for an item-level element
9353
	 *
9354
	 * This method allows you to get access to ANY element/attribute that is a
9355
	 * sub-element of the item/entry tag.
9356
	 *
9357
	 * See {@see SimplePie::get_feed_tags()} for a description of the return value
9358
	 *
9359
	 * @since 1.0
9360
	 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
9361
	 * @param string $namespace The URL of the XML namespace of the elements you're trying to access
9362
	 * @param string $tag Tag name
9363
	 * @return array
9364
	 */
9365
	public function get_item_tags($namespace, $tag)
9366
	{
9367
		if (isset($this->data['child'][$namespace][$tag]))
9368
		{
9369
			return $this->data['child'][$namespace][$tag];
9370
		}
9371
		else
9372
		{
9373
			return null;
9374
		}
9375
	}
9376
9377
	/**
9378
	 * Get the base URL value from the parent feed
9379
	 *
9380
	 * Uses `<xml:base>`
9381
	 *
9382
	 * @param array $element
9383
	 * @return string
9384
	 */
9385
	public function get_base($element = array())
9386
	{
9387
		return $this->feed->get_base($element);
9388
	}
9389
9390
	/**
9391
	 * Sanitize feed data
9392
	 *
9393
	 * @access private
9394
	 * @see SimplePie::sanitize()
9395
	 * @param string $data Data to sanitize
9396
	 * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants
9397
	 * @param string $base Base URL to resolve URLs against
9398
	 * @return string Sanitized data
9399
	 */
9400
	public function sanitize($data, $type, $base = '')
9401
	{
9402
		return $this->feed->sanitize($data, $type, $base);
9403
	}
9404
9405
	/**
9406
	 * Get the parent feed
9407
	 *
9408
	 * Note: this may not work as you think for multifeeds!
9409
	 *
9410
	 * @link http://simplepie.org/faq/typical_multifeed_gotchas#missing_data_from_feed
9411
	 * @since 1.0
9412
	 * @return SimplePie
9413
	 */
9414
	public function get_feed()
9415
	{
9416
		return $this->feed;
9417
	}
9418
9419
	/**
9420
	 * Get the unique identifier for the item
9421
	 *
9422
	 * This is usually used when writing code to check for new items in a feed.
9423
	 *
9424
	 * Uses `<atom:id>`, `<guid>`, `<dc:identifier>` or the `about` attribute
9425
	 * for RDF. If none of these are supplied (or `$hash` is true), creates an
9426
	 * MD5 hash based on the permalink, title and content.
9427
	 *
9428
	 * @since Beta 2
9429
	 * @param boolean $hash Should we force using a hash instead of the supplied ID?
9430
	 * @param string|false $fn User-supplied function to generate an hash
9431
	 * @return string|null
9432
	 */
9433
	public function get_id($hash = false, $fn = 'md5')
9434
	{
9435
		if (!$hash)
9436
		{
9437
			if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
9438
			{
9439
				return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
9440
			}
9441
			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
9442
			{
9443
				return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
9444
			}
9445
			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
9446
			{
9447
				return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
9448
			}
9449
			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
9450
			{
9451
				return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
9452
			}
9453
			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
9454
			{
9455
				return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
9456
			}
9457
			elseif (isset($this->data['attribs'][SIMPLEPIE_NAMESPACE_RDF]['about']))
9458
			{
9459
				return $this->sanitize($this->data['attribs'][SIMPLEPIE_NAMESPACE_RDF]['about'], SIMPLEPIE_CONSTRUCT_TEXT);
9460
			}
9461
		}
9462
		if ($fn === false)
9463
		{
9464
			return null;
9465
		}
9466
		elseif (!is_callable($fn))
9467
		{
9468
			trigger_error('User-supplied function $fn must be callable', E_USER_WARNING);
9469
			$fn = 'md5';
9470
		}
9471
		return call_user_func($fn,
9472
		       $this->get_permalink().$this->get_title().$this->get_content());
9473
	}
9474
9475
	/**
9476
	 * Get the title of the item
9477
	 *
9478
	 * Uses `<atom:title>`, `<title>` or `<dc:title>`
9479
	 *
9480
	 * @since Beta 2 (previously called `get_item_title` since 0.8)
9481
	 * @return string|null
9482
	 */
9483
	public function get_title()
9484
	{
9485
		if (!isset($this->data['title']))
9486
		{
9487
			if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
9488
			{
9489
				$this->data['title'] = $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
9490
			}
9491
			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
9492
			{
9493
				$this->data['title'] = $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
9494
			}
9495
			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
9496
			{
9497
				$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
9498
			}
9499
			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
9500
			{
9501
				$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
9502
			}
9503
			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
9504
			{
9505
				$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
9506
			}
9507
			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
9508
			{
9509
				$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
9510
			}
9511
			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
9512
			{
9513
				$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
9514
			}
9515
			else
9516
			{
9517
				$this->data['title'] = null;
9518
			}
9519
		}
9520
		return $this->data['title'];
9521
	}
9522
9523
	/**
9524
	 * Get the content for the item
9525
	 *
9526
	 * Prefers summaries over full content , but will return full content if a
9527
	 * summary does not exist.
9528
	 *
9529
	 * To prefer full content instead, use {@see get_content}
9530
	 *
9531
	 * Uses `<atom:summary>`, `<description>`, `<dc:description>` or
9532
	 * `<itunes:subtitle>`
9533
	 *
9534
	 * @since 0.8
9535
	 * @param boolean $description_only Should we avoid falling back to the content?
9536
	 * @return string|null
9537
	 */
9538
	public function get_description($description_only = false)
9539
	{
9540
		if (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary')) &&
9541
		    ($return = $this->sanitize($tags[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($tags[0]['attribs'])), $this->get_base($tags[0]))))
9542
		{
9543
			return $return;
9544
		}
9545
		elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary')) &&
9546
		        ($return = $this->sanitize($tags[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($tags[0]['attribs'])), $this->get_base($tags[0]))))
9547
		{
9548
			return $return;
9549
		}
9550
		elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description')) &&
9551
		        ($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($tags[0]))))
9552
		{
9553
			return $return;
9554
		}
9555
		elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description')) &&
9556
		        ($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($tags[0]))))
9557
		{
9558
			return $return;
9559
		}
9560
		elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description')) &&
9561
		        ($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)))
9562
		{
9563
			return $return;
9564
		}
9565
		elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description')) &&
9566
		        ($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)))
9567
		{
9568
			return $return;
9569
		}
9570
		elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary')) &&
9571
		        ($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($tags[0]))))
9572
		{
9573
			return $return;
9574
		}
9575
		elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle')) &&
9576
		        ($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)))
9577
		{
9578
			return $return;
9579
		}
9580
		elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description')) &&
9581
		        ($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_HTML)))
9582
		{
9583
			return $return;
9584
		}
9585
9586
		elseif (!$description_only)
9587
		{
9588
			return $this->get_content(true);
9589
		}
9590
		else
9591
		{
9592
			return null;
9593
		}
9594
	}
9595
9596
	/**
9597
	 * Get the content for the item
9598
	 *
9599
	 * Prefers full content over summaries, but will return a summary if full
9600
	 * content does not exist.
9601
	 *
9602
	 * To prefer summaries instead, use {@see get_description}
9603
	 *
9604
	 * Uses `<atom:content>` or `<content:encoded>` (RSS 1.0 Content Module)
9605
	 *
9606
	 * @since 1.0
9607
	 * @param boolean $content_only Should we avoid falling back to the description?
9608
	 * @return string|null
9609
	 */
9610
	public function get_content($content_only = false)
9611
	{
9612
		if (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content')) &&
9613
		    ($return = $this->sanitize($tags[0]['data'], $this->registry->call('Misc', 'atom_10_content_construct_type', array($tags[0]['attribs'])), $this->get_base($tags[0]))))
9614
		{
9615
			return $return;
9616
		}
9617
		elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content')) &&
9618
		        ($return = $this->sanitize($tags[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($tags[0]['attribs'])), $this->get_base($tags[0]))))
9619
		{
9620
			return $return;
9621
		}
9622
		elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded')) &&
9623
		        ($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($tags[0]))))
9624
		{
9625
			return $return;
9626
		}
9627
		elseif (!$content_only)
9628
		{
9629
			return $this->get_description(true);
9630
		}
9631
		else
9632
		{
9633
			return null;
9634
		}
9635
	}
9636
	
9637
	/**
9638
	 * Get the media:thumbnail of the item
9639
	 *
9640
	 * Uses `<media:thumbnail>`
9641
	 *
9642
	 * 
9643
	 * @return array|null
9644
	 */
9645
	public function get_thumbnail()
9646
	{
9647
		if (!isset($this->data['thumbnail']))
9648
		{
9649
			if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
9650
			{
9651
				$this->data['thumbnail'] = $return[0]['attribs'][''];
9652
			}
9653
			else
9654
			{
9655
				$this->data['thumbnail'] = null;
9656
			}
9657
		}
9658
		return $this->data['thumbnail'];
9659
	}	
9660
9661
	/**
9662
	 * Get a category for the item
9663
	 *
9664
	 * @since Beta 3 (previously called `get_categories()` since Beta 2)
9665
	 * @param int $key The category that you want to return.  Remember that arrays begin with 0, not 1
9666
	 * @return SimplePie_Category|null
9667
	 */
9668
	public function get_category($key = 0)
9669
	{
9670
		$categories = $this->get_categories();
9671
		if (isset($categories[$key]))
9672
		{
9673
			return $categories[$key];
9674
		}
9675
		else
9676
		{
9677
			return null;
9678
		}
9679
	}
9680
9681
	/**
9682
	 * Get all categories for the item
9683
	 *
9684
	 * Uses `<atom:category>`, `<category>` or `<dc:subject>`
9685
	 *
9686
	 * @since Beta 3
9687
	 * @return SimplePie_Category[]|null List of {@see SimplePie_Category} objects
9688
	 */
9689
	public function get_categories()
9690
	{
9691
		$categories = array();
9692
9693
		$type = 'category';
9694
		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, $type) as $category)
9695
		{
9696
			$term = null;
9697
			$scheme = null;
9698
			$label = null;
9699
			if (isset($category['attribs']['']['term']))
9700
			{
9701
				$term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
9702
			}
9703
			if (isset($category['attribs']['']['scheme']))
9704
			{
9705
				$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
9706
			}
9707
			if (isset($category['attribs']['']['label']))
9708
			{
9709
				$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
9710
			}
9711
			$categories[] = $this->registry->create('Category', array($term, $scheme, $label, $type));
9712
		}
9713
		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, $type) as $category)
9714
		{
9715
			// This is really the label, but keep this as the term also for BC.
9716
			// Label will also work on retrieving because that falls back to term.
9717
			$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
9718
			if (isset($category['attribs']['']['domain']))
9719
			{
9720
				$scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
9721
			}
9722
			else
9723
			{
9724
				$scheme = null;
9725
			}
9726
			$categories[] = $this->registry->create('Category', array($term, $scheme, null, $type));
9727
		}
9728
9729
		$type = 'subject';
9730
		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, $type) as $category)
9731
		{
9732
			$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null, $type));
9733
		}
9734
		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, $type) as $category)
9735
		{
9736
			$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null, $type));
9737
		}
9738
9739
		if (!empty($categories))
9740
		{
9741
			return array_unique($categories);
9742
		}
9743
		else
9744
		{
9745
			return null;
9746
		}
9747
	}
9748
9749
	/**
9750
	 * Get an author for the item
9751
	 *
9752
	 * @since Beta 2
9753
	 * @param int $key The author that you want to return.  Remember that arrays begin with 0, not 1
9754
	 * @return SimplePie_Author|null
9755
	 */
9756
	public function get_author($key = 0)
9757
	{
9758
		$authors = $this->get_authors();
9759
		if (isset($authors[$key]))
9760
		{
9761
			return $authors[$key];
9762
		}
9763
		else
9764
		{
9765
			return null;
9766
		}
9767
	}
9768
9769
	/**
9770
	 * Get a contributor for the item
9771
	 *
9772
	 * @since 1.1
9773
	 * @param int $key The contrbutor that you want to return.  Remember that arrays begin with 0, not 1
9774
	 * @return SimplePie_Author|null
9775
	 */
9776
	public function get_contributor($key = 0)
9777
	{
9778
		$contributors = $this->get_contributors();
9779
		if (isset($contributors[$key]))
9780
		{
9781
			return $contributors[$key];
9782
		}
9783
		else
9784
		{
9785
			return null;
9786
		}
9787
	}
9788
9789
	/**
9790
	 * Get all contributors for the item
9791
	 *
9792
	 * Uses `<atom:contributor>`
9793
	 *
9794
	 * @since 1.1
9795
	 * @return array|null List of {@see SimplePie_Author} objects
9796
	 */
9797
	public function get_contributors()
9798
	{
9799
		$contributors = array();
9800
		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
9801
		{
9802
			$name = null;
9803
			$uri = null;
9804
			$email = null;
9805
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
9806
			{
9807
				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
9808
			}
9809
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
9810
			{
9811
				$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]));
9812
			}
9813
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
9814
			{
9815
				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
9816
			}
9817
			if ($name !== null || $email !== null || $uri !== null)
9818
			{
9819
				$contributors[] = $this->registry->create('Author', array($name, $uri, $email));
9820
			}
9821
		}
9822
		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
9823
		{
9824
			$name = null;
9825
			$url = null;
9826
			$email = null;
9827
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
9828
			{
9829
				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
9830
			}
9831
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
9832
			{
9833
				$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]));
9834
			}
9835
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
9836
			{
9837
				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
9838
			}
9839
			if ($name !== null || $email !== null || $url !== null)
9840
			{
9841
				$contributors[] = $this->registry->create('Author', array($name, $url, $email));
9842
			}
9843
		}
9844
9845
		if (!empty($contributors))
9846
		{
9847
			return array_unique($contributors);
9848
		}
9849
		else
9850
		{
9851
			return null;
9852
		}
9853
	}
9854
9855
	/**
9856
	 * Get all authors for the item
9857
	 *
9858
	 * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`
9859
	 *
9860
	 * @since Beta 2
9861
	 * @return array|null List of {@see SimplePie_Author} objects
9862
	 */
9863
	public function get_authors()
9864
	{
9865
		$authors = array();
9866
		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
9867
		{
9868
			$name = null;
9869
			$uri = null;
9870
			$email = null;
9871
			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
9872
			{
9873
				$name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
9874
			}
9875
			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
9876
			{
9877
				$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]));
9878
			}
9879
			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
9880
			{
9881
				$email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
9882
			}
9883
			if ($name !== null || $email !== null || $uri !== null)
9884
			{
9885
				$authors[] = $this->registry->create('Author', array($name, $uri, $email));
9886
			}
9887
		}
9888
		if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
9889
		{
9890
			$name = null;
9891
			$url = null;
9892
			$email = null;
9893
			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
9894
			{
9895
				$name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
9896
			}
9897
			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
9898
			{
9899
				$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]));
9900
			}
9901
			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
9902
			{
9903
				$email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
9904
			}
9905
			if ($name !== null || $email !== null || $url !== null)
9906
			{
9907
				$authors[] = $this->registry->create('Author', array($name, $url, $email));
9908
			}
9909
		}
9910
		if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
9911
		{
9912
			$authors[] = $this->registry->create('Author', array(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)));
9913
		}
9914
		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
9915
		{
9916
			$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
9917
		}
9918
		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
9919
		{
9920
			$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
9921
		}
9922
		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
9923
		{
9924
			$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
9925
		}
9926
9927
		if (!empty($authors))
9928
		{
9929
			return array_unique($authors);
9930
		}
9931
		elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
9932
		{
9933
			return $authors;
9934
		}
9935
		elseif ($authors = $this->feed->get_authors())
9936
		{
9937
			return $authors;
9938
		}
9939
		else
9940
		{
9941
			return null;
9942
		}
9943
	}
9944
9945
	/**
9946
	 * Get the copyright info for the item
9947
	 *
9948
	 * Uses `<atom:rights>` or `<dc:rights>`
9949
	 *
9950
	 * @since 1.1
9951
	 * @return string
9952
	 */
9953
	public function get_copyright()
9954
	{
9955
		if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
9956
		{
9957
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
9958
		}
9959
		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
9960
		{
9961
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
9962
		}
9963
		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
9964
		{
9965
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
9966
		}
9967
		else
9968
		{
9969
			return null;
9970
		}
9971
	}
9972
9973
	/**
9974
	 * Get the posting date/time for the item
9975
	 *
9976
	 * Uses `<atom:published>`, `<atom:updated>`, `<atom:issued>`,
9977
	 * `<atom:modified>`, `<pubDate>` or `<dc:date>`
9978
	 *
9979
	 * Note: obeys PHP's timezone setting. To get a UTC date/time, use
9980
	 * {@see get_gmdate}
9981
	 *
9982
	 * @since Beta 2 (previously called `get_item_date` since 0.8)
9983
	 *
9984
	 * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data)
9985
	 * @return int|string|null
9986
	 */
9987
	public function get_date($date_format = 'j F Y, g:i a')
9988
	{
9989
		if (!isset($this->data['date']))
9990
		{
9991
			if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
9992
			{
9993
				$this->data['date']['raw'] = $return[0]['data'];
9994
			}
9995
			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
9996
			{
9997
				$this->data['date']['raw'] = $return[0]['data'];
9998
			}
9999
			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
10000
			{
10001
				$this->data['date']['raw'] = $return[0]['data'];
10002
			}
10003
			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
10004
			{
10005
				$this->data['date']['raw'] = $return[0]['data'];
10006
			}
10007
			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
10008
			{
10009
				$this->data['date']['raw'] = $return[0]['data'];
10010
			}
10011
			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
10012
			{
10013
				$this->data['date']['raw'] = $return[0]['data'];
10014
			}
10015
			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
10016
			{
10017
				$this->data['date']['raw'] = $return[0]['data'];
10018
			}
10019
			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
10020
			{
10021
				$this->data['date']['raw'] = $return[0]['data'];
10022
			}
10023
10024
			if (!empty($this->data['date']['raw']))
10025
			{
10026
				$parser = $this->registry->call('Parse_Date', 'get');
10027
				$this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
10028
			}
10029
			else
10030
			{
10031
				$this->data['date'] = null;
10032
			}
10033
		}
10034
		if ($this->data['date'])
10035
		{
10036
			$date_format = (string) $date_format;
10037
			switch ($date_format)
10038
			{
10039
				case '':
10040
					return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
10041
10042
				case 'U':
10043
					return $this->data['date']['parsed'];
10044
10045
				default:
10046
					return date($date_format, $this->data['date']['parsed']);
10047
			}
10048
		}
10049
		else
10050
		{
10051
			return null;
10052
		}
10053
	}
10054
10055
	/**
10056
	 * Get the update date/time for the item
10057
	 *
10058
	 * Uses `<atom:updated>`
10059
	 *
10060
	 * Note: obeys PHP's timezone setting. To get a UTC date/time, use
10061
	 * {@see get_gmdate}
10062
	 *
10063
	 * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data)
10064
	 * @return int|string|null
10065
	 */
10066
	public function get_updated_date($date_format = 'j F Y, g:i a')
10067
	{
10068
		if (!isset($this->data['updated']))
10069
		{
10070
			if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
10071
			{
10072
				$this->data['updated']['raw'] = $return[0]['data'];
10073
			}
10074
10075
			if (!empty($this->data['updated']['raw']))
10076
			{
10077
				$parser = $this->registry->call('Parse_Date', 'get');
10078
				$this->data['updated']['parsed'] = $parser->parse($this->data['updated']['raw']);
10079
			}
10080
			else
10081
			{
10082
				$this->data['updated'] = null;
10083
			}
10084
		}
10085
		if ($this->data['updated'])
10086
		{
10087
			$date_format = (string) $date_format;
10088
			switch ($date_format)
10089
			{
10090
				case '':
10091
					return $this->sanitize($this->data['updated']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
10092
10093
				case 'U':
10094
					return $this->data['updated']['parsed'];
10095
10096
				default:
10097
					return date($date_format, $this->data['updated']['parsed']);
10098
			}
10099
		}
10100
		else
10101
		{
10102
			return null;
10103
		}
10104
	}
10105
10106
	/**
10107
	 * Get the localized posting date/time for the item
10108
	 *
10109
	 * Returns the date formatted in the localized language. To display in
10110
	 * languages other than the server's default, you need to change the locale
10111
	 * with {@link http://php.net/setlocale setlocale()}. The available
10112
	 * localizations depend on which ones are installed on your web server.
10113
	 *
10114
	 * @since 1.0
10115
	 *
10116
	 * @param string $date_format Supports any PHP date format from {@see http://php.net/strftime} (empty for the raw data)
10117
	 * @return int|string|null
10118
	 */
10119
	public function get_local_date($date_format = '%c')
10120
	{
10121
		if (!$date_format)
10122
		{
10123
			return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
10124
		}
10125
		elseif (($date = $this->get_date('U')) !== null && $date !== false)
10126
		{
10127
			return strftime($date_format, $date);
10128
		}
10129
		else
10130
		{
10131
			return null;
10132
		}
10133
	}
10134
10135
	/**
10136
	 * Get the posting date/time for the item (UTC time)
10137
	 *
10138
	 * @see get_date
10139
	 * @param string $date_format Supports any PHP date format from {@see http://php.net/date}
10140
	 * @return int|string|null
10141
	 */
10142
	public function get_gmdate($date_format = 'j F Y, g:i a')
10143
	{
10144
		$date = $this->get_date('U');
10145
		if ($date === null)
10146
		{
10147
			return null;
10148
		}
10149
10150
		return gmdate($date_format, $date);
10151
	}
10152
10153
	/**
10154
	 * Get the update date/time for the item (UTC time)
10155
	 *
10156
	 * @see get_updated_date
10157
	 * @param string $date_format Supports any PHP date format from {@see http://php.net/date}
10158
	 * @return int|string|null
10159
	 */
10160
	public function get_updated_gmdate($date_format = 'j F Y, g:i a')
10161
	{
10162
		$date = $this->get_updated_date('U');
10163
		if ($date === null)
10164
		{
10165
			return null;
10166
		}
10167
10168
		return gmdate($date_format, $date);
10169
	}
10170
10171
	/**
10172
	 * Get the permalink for the item
10173
	 *
10174
	 * Returns the first link available with a relationship of "alternate".
10175
	 * Identical to {@see get_link()} with key 0
10176
	 *
10177
	 * @see get_link
10178
	 * @since 0.8
10179
	 * @return string|null Permalink URL
10180
	 */
10181
	public function get_permalink()
10182
	{
10183
		$link = $this->get_link();
10184
		$enclosure = $this->get_enclosure(0);
10185
		if ($link !== null)
10186
		{
10187
			return $link;
10188
		}
10189
		elseif ($enclosure !== null)
10190
		{
10191
			return $enclosure->get_link();
10192
		}
10193
		else
10194
		{
10195
			return null;
10196
		}
10197
	}
10198
10199
	/**
10200
	 * Get a single link for the item
10201
	 *
10202
	 * @since Beta 3
10203
	 * @param int $key The link that you want to return.  Remember that arrays begin with 0, not 1
10204
	 * @param string $rel The relationship of the link to return
10205
	 * @return string|null Link URL
10206
	 */
10207
	public function get_link($key = 0, $rel = 'alternate')
10208
	{
10209
		$links = $this->get_links($rel);
10210
		if ($links[$key] !== null)
10211
		{
10212
			return $links[$key];
10213
		}
10214
		else
10215
		{
10216
			return null;
10217
		}
10218
	}
10219
10220
	/**
10221
	 * Get all links for the item
10222
	 *
10223
	 * Uses `<atom:link>`, `<link>` or `<guid>`
10224
	 *
10225
	 * @since Beta 2
10226
	 * @param string $rel The relationship of links to return
10227
	 * @return array|null Links found for the item (strings)
10228
	 */
10229
	public function get_links($rel = 'alternate')
10230
	{
10231
		if (!isset($this->data['links']))
10232
		{
10233
			$this->data['links'] = array();
10234
			foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
10235
			{
10236
				if (isset($link['attribs']['']['href']))
10237
				{
10238
					$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
10239
					$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
10240
10241
				}
10242
			}
10243
			foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
10244
			{
10245
				if (isset($link['attribs']['']['href']))
10246
				{
10247
					$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
10248
					$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
10249
				}
10250
			}
10251
			if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
10252
			{
10253
				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
10254
			}
10255
			if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
10256
			{
10257
				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
10258
			}
10259
			if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
10260
			{
10261
				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
10262
			}
10263
			if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
10264
			{
10265
				if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
10266
				{
10267
					$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
10268
				}
10269
			}
10270
10271
			$keys = array_keys($this->data['links']);
10272
			foreach ($keys as $key)
10273
			{
10274
				if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))
10275
				{
10276
					if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
10277
					{
10278
						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
10279
						$this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
10280
					}
10281
					else
10282
					{
10283
						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
10284
					}
10285
				}
10286
				elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
10287
				{
10288
					$this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
10289
				}
10290
				$this->data['links'][$key] = array_unique($this->data['links'][$key]);
10291
			}
10292
		}
10293
		if (isset($this->data['links'][$rel]))
10294
		{
10295
			return $this->data['links'][$rel];
10296
		}
10297
		else
10298
		{
10299
			return null;
10300
		}
10301
	}
10302
10303
	/**
10304
	 * Get an enclosure from the item
10305
	 *
10306
	 * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
10307
	 *
10308
	 * @since Beta 2
10309
	 * @todo Add ability to prefer one type of content over another (in a media group).
10310
	 * @param int $key The enclosure that you want to return.  Remember that arrays begin with 0, not 1
10311
	 * @return SimplePie_Enclosure|null
10312
	 */
10313
	public function get_enclosure($key = 0, $prefer = null)
0 ignored issues
show
Unused Code introduced by
The parameter $prefer is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
10314
	{
10315
		$enclosures = $this->get_enclosures();
10316
		if (isset($enclosures[$key]))
10317
		{
10318
			return $enclosures[$key];
10319
		}
10320
		else
10321
		{
10322
			return null;
10323
		}
10324
	}
10325
10326
	/**
10327
	 * Get all available enclosures (podcasts, etc.)
10328
	 *
10329
	 * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
10330
	 *
10331
	 * At this point, we're pretty much assuming that all enclosures for an item
10332
	 * are the same content.  Anything else is too complicated to
10333
	 * properly support.
10334
	 *
10335
	 * @since Beta 2
10336
	 * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
10337
	 * @todo If an element exists at a level, but its value is empty, we should fall back to the value from the parent (if it exists).
10338
	 * @return SimplePie_Enclosure[]|null List of SimplePie_Enclosure items
10339
	 */
10340
	public function get_enclosures()
10341
	{
10342
		if (!isset($this->data['enclosures']))
10343
		{
10344
			$this->data['enclosures'] = array();
10345
10346
			// Elements
10347
			$captions_parent = null;
10348
			$categories_parent = null;
10349
			$copyrights_parent = null;
10350
			$credits_parent = null;
10351
			$description_parent = null;
0 ignored issues
show
Unused Code introduced by
$description_parent is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10352
			$duration_parent = null;
0 ignored issues
show
Unused Code introduced by
$duration_parent is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10353
			$hashes_parent = null;
10354
			$keywords_parent = null;
10355
			$player_parent = null;
0 ignored issues
show
Unused Code introduced by
$player_parent is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10356
			$ratings_parent = null;
10357
			$restrictions_parent = null;
10358
			$thumbnails_parent = null;
10359
			$title_parent = null;
0 ignored issues
show
Unused Code introduced by
$title_parent is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10360
10361
			// Let's do the channel and item-level ones first, and just re-use them if we need to.
10362
			$parent = $this->get_feed();
10363
10364
			// CAPTIONS
10365
			if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
10366
			{
10367
				foreach ($captions as $caption)
10368
				{
10369
					$caption_type = null;
10370
					$caption_lang = null;
10371
					$caption_startTime = null;
10372
					$caption_endTime = null;
10373
					$caption_text = null;
10374
					if (isset($caption['attribs']['']['type']))
10375
					{
10376
						$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
10377
					}
10378
					if (isset($caption['attribs']['']['lang']))
10379
					{
10380
						$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
10381
					}
10382
					if (isset($caption['attribs']['']['start']))
10383
					{
10384
						$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
10385
					}
10386
					if (isset($caption['attribs']['']['end']))
10387
					{
10388
						$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
10389
					}
10390
					if (isset($caption['data']))
10391
					{
10392
						$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10393
					}
10394
					$captions_parent[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
10395
				}
10396
			}
10397
			elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
10398
			{
10399
				foreach ($captions as $caption)
10400
				{
10401
					$caption_type = null;
10402
					$caption_lang = null;
10403
					$caption_startTime = null;
10404
					$caption_endTime = null;
10405
					$caption_text = null;
10406
					if (isset($caption['attribs']['']['type']))
10407
					{
10408
						$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
10409
					}
10410
					if (isset($caption['attribs']['']['lang']))
10411
					{
10412
						$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
10413
					}
10414
					if (isset($caption['attribs']['']['start']))
10415
					{
10416
						$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
10417
					}
10418
					if (isset($caption['attribs']['']['end']))
10419
					{
10420
						$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
10421
					}
10422
					if (isset($caption['data']))
10423
					{
10424
						$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10425
					}
10426
					$captions_parent[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
10427
				}
10428
			}
10429
			if (is_array($captions_parent))
10430
			{
10431
				$captions_parent = array_values(array_unique($captions_parent));
10432
			}
10433
10434
			// CATEGORIES
10435
			foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
10436
			{
10437
				$term = null;
10438
				$scheme = null;
0 ignored issues
show
Unused Code introduced by
$scheme is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10439
				$label = null;
10440
				if (isset($category['data']))
10441
				{
10442
					$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10443
				}
10444
				if (isset($category['attribs']['']['scheme']))
10445
				{
10446
					$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
10447
				}
10448
				else
10449
				{
10450
					$scheme = 'http://search.yahoo.com/mrss/category_schema';
10451
				}
10452
				if (isset($category['attribs']['']['label']))
10453
				{
10454
					$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
10455
				}
10456
				$categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label));
10457
			}
10458
			foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
10459
			{
10460
				$term = null;
10461
				$scheme = null;
0 ignored issues
show
Unused Code introduced by
$scheme is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10462
				$label = null;
10463
				if (isset($category['data']))
10464
				{
10465
					$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10466
				}
10467
				if (isset($category['attribs']['']['scheme']))
10468
				{
10469
					$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
10470
				}
10471
				else
10472
				{
10473
					$scheme = 'http://search.yahoo.com/mrss/category_schema';
10474
				}
10475
				if (isset($category['attribs']['']['label']))
10476
				{
10477
					$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
10478
				}
10479
				$categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label));
10480
			}
10481
			foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
10482
			{
10483
				$term = null;
10484
				$scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
10485
				$label = null;
10486
				if (isset($category['attribs']['']['text']))
10487
				{
10488
					$label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
10489
				}
10490
				$categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label));
10491
10492
				if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
10493
				{
10494
					foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
10495
					{
10496
						if (isset($subcategory['attribs']['']['text']))
10497
						{
10498
							$label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
10499
						}
10500
						$categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label));
10501
					}
10502
				}
10503
			}
10504
			if (is_array($categories_parent))
10505
			{
10506
				$categories_parent = array_values(array_unique($categories_parent));
10507
			}
10508
10509
			// COPYRIGHT
10510
			if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
10511
			{
10512
				$copyright_url = null;
10513
				$copyright_label = null;
10514
				if (isset($copyright[0]['attribs']['']['url']))
10515
				{
10516
					$copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
10517
				}
10518
				if (isset($copyright[0]['data']))
10519
				{
10520
					$copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10521
				}
10522
				$copyrights_parent = $this->registry->create('Copyright', array($copyright_url, $copyright_label));
10523
			}
10524
			elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
10525
			{
10526
				$copyright_url = null;
10527
				$copyright_label = null;
10528
				if (isset($copyright[0]['attribs']['']['url']))
10529
				{
10530
					$copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
10531
				}
10532
				if (isset($copyright[0]['data']))
10533
				{
10534
					$copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10535
				}
10536
				$copyrights_parent = $this->registry->create('Copyright', array($copyright_url, $copyright_label));
10537
			}
10538
10539
			// CREDITS
10540
			if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
10541
			{
10542
				foreach ($credits as $credit)
10543
				{
10544
					$credit_role = null;
10545
					$credit_scheme = null;
0 ignored issues
show
Unused Code introduced by
$credit_scheme is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10546
					$credit_name = null;
10547
					if (isset($credit['attribs']['']['role']))
10548
					{
10549
						$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
10550
					}
10551
					if (isset($credit['attribs']['']['scheme']))
10552
					{
10553
						$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
10554
					}
10555
					else
10556
					{
10557
						$credit_scheme = 'urn:ebu';
10558
					}
10559
					if (isset($credit['data']))
10560
					{
10561
						$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10562
					}
10563
					$credits_parent[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));
10564
				}
10565
			}
10566
			elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
10567
			{
10568
				foreach ($credits as $credit)
10569
				{
10570
					$credit_role = null;
10571
					$credit_scheme = null;
0 ignored issues
show
Unused Code introduced by
$credit_scheme is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10572
					$credit_name = null;
10573
					if (isset($credit['attribs']['']['role']))
10574
					{
10575
						$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
10576
					}
10577
					if (isset($credit['attribs']['']['scheme']))
10578
					{
10579
						$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
10580
					}
10581
					else
10582
					{
10583
						$credit_scheme = 'urn:ebu';
10584
					}
10585
					if (isset($credit['data']))
10586
					{
10587
						$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10588
					}
10589
					$credits_parent[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));
10590
				}
10591
			}
10592
			if (is_array($credits_parent))
10593
			{
10594
				$credits_parent = array_values(array_unique($credits_parent));
10595
			}
10596
10597
			// DESCRIPTION
10598
			if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
10599
			{
10600
				if (isset($description_parent[0]['data']))
10601
				{
10602
					$description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10603
				}
10604
			}
10605
			elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
10606
			{
10607
				if (isset($description_parent[0]['data']))
10608
				{
10609
					$description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10610
				}
10611
			}
10612
10613
			// DURATION
10614
			if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
10615
			{
10616
				$seconds = null;
10617
				$minutes = null;
0 ignored issues
show
Unused Code introduced by
$minutes is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10618
				$hours = null;
0 ignored issues
show
Unused Code introduced by
$hours is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10619
				if (isset($duration_parent[0]['data']))
10620
				{
10621
					$temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
10622
					if (sizeof($temp) > 0)
10623
					{
10624
						$seconds = (int) array_pop($temp);
10625
					}
10626
					if (sizeof($temp) > 0)
10627
					{
10628
						$minutes = (int) array_pop($temp);
10629
						$seconds += $minutes * 60;
10630
					}
10631
					if (sizeof($temp) > 0)
10632
					{
10633
						$hours = (int) array_pop($temp);
10634
						$seconds += $hours * 3600;
10635
					}
10636
					unset($temp);
10637
					$duration_parent = $seconds;
10638
				}
10639
			}
10640
10641
			// HASHES
10642
			if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
10643
			{
10644
				foreach ($hashes_iterator as $hash)
10645
				{
10646
					$value = null;
10647
					$algo = null;
0 ignored issues
show
Unused Code introduced by
$algo is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10648
					if (isset($hash['data']))
10649
					{
10650
						$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10651
					}
10652
					if (isset($hash['attribs']['']['algo']))
10653
					{
10654
						$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
10655
					}
10656
					else
10657
					{
10658
						$algo = 'md5';
10659
					}
10660
					$hashes_parent[] = $algo.':'.$value;
10661
				}
10662
			}
10663
			elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
10664
			{
10665
				foreach ($hashes_iterator as $hash)
10666
				{
10667
					$value = null;
10668
					$algo = null;
0 ignored issues
show
Unused Code introduced by
$algo is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10669
					if (isset($hash['data']))
10670
					{
10671
						$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10672
					}
10673
					if (isset($hash['attribs']['']['algo']))
10674
					{
10675
						$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
10676
					}
10677
					else
10678
					{
10679
						$algo = 'md5';
10680
					}
10681
					$hashes_parent[] = $algo.':'.$value;
10682
				}
10683
			}
10684
			if (is_array($hashes_parent))
10685
			{
10686
				$hashes_parent = array_values(array_unique($hashes_parent));
10687
			}
10688
10689
			// KEYWORDS
10690
			if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
10691
			{
10692
				if (isset($keywords[0]['data']))
10693
				{
10694
					$temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
10695
					foreach ($temp as $word)
10696
					{
10697
						$keywords_parent[] = trim($word);
10698
					}
10699
				}
10700
				unset($temp);
10701
			}
10702
			elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
10703
			{
10704
				if (isset($keywords[0]['data']))
10705
				{
10706
					$temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
10707
					foreach ($temp as $word)
10708
					{
10709
						$keywords_parent[] = trim($word);
10710
					}
10711
				}
10712
				unset($temp);
10713
			}
10714
			elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
10715
			{
10716
				if (isset($keywords[0]['data']))
10717
				{
10718
					$temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
10719
					foreach ($temp as $word)
10720
					{
10721
						$keywords_parent[] = trim($word);
10722
					}
10723
				}
10724
				unset($temp);
10725
			}
10726
			elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
10727
			{
10728
				if (isset($keywords[0]['data']))
10729
				{
10730
					$temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
10731
					foreach ($temp as $word)
10732
					{
10733
						$keywords_parent[] = trim($word);
10734
					}
10735
				}
10736
				unset($temp);
10737
			}
10738
			if (is_array($keywords_parent))
10739
			{
10740
				$keywords_parent = array_values(array_unique($keywords_parent));
10741
			}
10742
10743
			// PLAYER
10744
			if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
10745
			{
10746
				if (isset($player_parent[0]['attribs']['']['url']))
10747
				{
10748
					$player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
10749
				}
10750
			}
10751
			elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
10752
			{
10753
				if (isset($player_parent[0]['attribs']['']['url']))
10754
				{
10755
					$player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
10756
				}
10757
			}
10758
10759
			// RATINGS
10760
			if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
10761
			{
10762
				foreach ($ratings as $rating)
10763
				{
10764
					$rating_scheme = null;
0 ignored issues
show
Unused Code introduced by
$rating_scheme is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10765
					$rating_value = null;
10766
					if (isset($rating['attribs']['']['scheme']))
10767
					{
10768
						$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
10769
					}
10770
					else
10771
					{
10772
						$rating_scheme = 'urn:simple';
10773
					}
10774
					if (isset($rating['data']))
10775
					{
10776
						$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10777
					}
10778
					$ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
10779
				}
10780
			}
10781
			elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
10782
			{
10783
				foreach ($ratings as $rating)
10784
				{
10785
					$rating_scheme = 'urn:itunes';
10786
					$rating_value = null;
10787
					if (isset($rating['data']))
10788
					{
10789
						$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10790
					}
10791
					$ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
10792
				}
10793
			}
10794
			elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
10795
			{
10796
				foreach ($ratings as $rating)
10797
				{
10798
					$rating_scheme = null;
0 ignored issues
show
Unused Code introduced by
$rating_scheme is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10799
					$rating_value = null;
10800
					if (isset($rating['attribs']['']['scheme']))
10801
					{
10802
						$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
10803
					}
10804
					else
10805
					{
10806
						$rating_scheme = 'urn:simple';
10807
					}
10808
					if (isset($rating['data']))
10809
					{
10810
						$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10811
					}
10812
					$ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
10813
				}
10814
			}
10815
			elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
10816
			{
10817
				foreach ($ratings as $rating)
10818
				{
10819
					$rating_scheme = 'urn:itunes';
10820
					$rating_value = null;
10821
					if (isset($rating['data']))
10822
					{
10823
						$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10824
					}
10825
					$ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
10826
				}
10827
			}
10828
			if (is_array($ratings_parent))
10829
			{
10830
				$ratings_parent = array_values(array_unique($ratings_parent));
10831
			}
10832
10833
			// RESTRICTIONS
10834
			if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
10835
			{
10836
				foreach ($restrictions as $restriction)
10837
				{
10838
					$restriction_relationship = null;
10839
					$restriction_type = null;
10840
					$restriction_value = null;
10841
					if (isset($restriction['attribs']['']['relationship']))
10842
					{
10843
						$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
10844
					}
10845
					if (isset($restriction['attribs']['']['type']))
10846
					{
10847
						$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
10848
					}
10849
					if (isset($restriction['data']))
10850
					{
10851
						$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10852
					}
10853
					$restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
10854
				}
10855
			}
10856
			elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
10857
			{
10858
				foreach ($restrictions as $restriction)
10859
				{
10860
					$restriction_relationship = 'allow';
10861
					$restriction_type = null;
10862
					$restriction_value = 'itunes';
10863
					if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
10864
					{
10865
						$restriction_relationship = 'deny';
10866
					}
10867
					$restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
10868
				}
10869
			}
10870
			elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
10871
			{
10872
				foreach ($restrictions as $restriction)
10873
				{
10874
					$restriction_relationship = null;
10875
					$restriction_type = null;
10876
					$restriction_value = null;
10877
					if (isset($restriction['attribs']['']['relationship']))
10878
					{
10879
						$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
10880
					}
10881
					if (isset($restriction['attribs']['']['type']))
10882
					{
10883
						$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
10884
					}
10885
					if (isset($restriction['data']))
10886
					{
10887
						$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10888
					}
10889
					$restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
10890
				}
10891
			}
10892
			elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
10893
			{
10894
				foreach ($restrictions as $restriction)
10895
				{
10896
					$restriction_relationship = 'allow';
10897
					$restriction_type = null;
10898
					$restriction_value = 'itunes';
10899
					if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
10900
					{
10901
						$restriction_relationship = 'deny';
10902
					}
10903
					$restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
10904
				}
10905
			}
10906
			if (is_array($restrictions_parent))
10907
			{
10908
				$restrictions_parent = array_values(array_unique($restrictions_parent));
10909
			}
10910
			else
10911
			{
10912
				$restrictions_parent = array(new SimplePie_Restriction('allow', null, 'default'));
10913
			}
10914
10915
			// THUMBNAILS
10916
			if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
10917
			{
10918
				foreach ($thumbnails as $thumbnail)
10919
				{
10920
					if (isset($thumbnail['attribs']['']['url']))
10921
					{
10922
						$thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
10923
					}
10924
				}
10925
			}
10926
			elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
10927
			{
10928
				foreach ($thumbnails as $thumbnail)
10929
				{
10930
					if (isset($thumbnail['attribs']['']['url']))
10931
					{
10932
						$thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
10933
					}
10934
				}
10935
			}
10936
10937
			// TITLES
10938
			if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
10939
			{
10940
				if (isset($title_parent[0]['data']))
10941
				{
10942
					$title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10943
				}
10944
			}
10945
			elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
10946
			{
10947
				if (isset($title_parent[0]['data']))
10948
				{
10949
					$title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
10950
				}
10951
			}
10952
10953
			// Clear the memory
10954
			unset($parent);
10955
10956
			// Attributes
10957
			$bitrate = null;
10958
			$channels = null;
10959
			$duration = null;
0 ignored issues
show
Unused Code introduced by
$duration is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10960
			$expression = null;
10961
			$framerate = null;
10962
			$height = null;
10963
			$javascript = null;
0 ignored issues
show
Unused Code introduced by
$javascript is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10964
			$lang = null;
10965
			$length = null;
10966
			$medium = null;
10967
			$samplingrate = null;
10968
			$type = null;
10969
			$url = null;
10970
			$width = null;
10971
10972
			// Elements
10973
			$captions = null;
0 ignored issues
show
Unused Code introduced by
$captions is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10974
			$categories = null;
0 ignored issues
show
Unused Code introduced by
$categories is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10975
			$copyrights = null;
0 ignored issues
show
Unused Code introduced by
$copyrights is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10976
			$credits = null;
0 ignored issues
show
Unused Code introduced by
$credits is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10977
			$description = null;
0 ignored issues
show
Unused Code introduced by
$description is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10978
			$hashes = null;
0 ignored issues
show
Unused Code introduced by
$hashes is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10979
			$keywords = null;
0 ignored issues
show
Unused Code introduced by
$keywords is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10980
			$player = null;
0 ignored issues
show
Unused Code introduced by
$player is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10981
			$ratings = null;
0 ignored issues
show
Unused Code introduced by
$ratings is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10982
			$restrictions = null;
0 ignored issues
show
Unused Code introduced by
$restrictions is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10983
			$thumbnails = null;
0 ignored issues
show
Unused Code introduced by
$thumbnails is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10984
			$title = null;
0 ignored issues
show
Unused Code introduced by
$title is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
10985
10986
			// If we have media:group tags, loop through them.
10987
			foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
10988
			{
10989
				if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
10990
				{
10991
					// If we have media:content tags, loop through them.
10992
					foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
10993
					{
10994
						if (isset($content['attribs']['']['url']))
10995
						{
10996
							// Attributes
10997
							$bitrate = null;
10998
							$channels = null;
10999
							$duration = null;
0 ignored issues
show
Unused Code introduced by
$duration is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11000
							$expression = null;
11001
							$framerate = null;
11002
							$height = null;
11003
							$javascript = null;
0 ignored issues
show
Unused Code introduced by
$javascript is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11004
							$lang = null;
11005
							$length = null;
11006
							$medium = null;
11007
							$samplingrate = null;
11008
							$type = null;
11009
							$url = null;
0 ignored issues
show
Unused Code introduced by
$url is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11010
							$width = null;
11011
11012
							// Elements
11013
							$captions = null;
11014
							$categories = null;
11015
							$copyrights = null;
0 ignored issues
show
Unused Code introduced by
$copyrights is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11016
							$credits = null;
11017
							$description = null;
0 ignored issues
show
Unused Code introduced by
$description is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11018
							$hashes = null;
11019
							$keywords = null;
11020
							$player = null;
0 ignored issues
show
Unused Code introduced by
$player is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11021
							$ratings = null;
11022
							$restrictions = null;
11023
							$thumbnails = null;
11024
							$title = null;
0 ignored issues
show
Unused Code introduced by
$title is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11025
11026
							// Start checking the attributes of media:content
11027
							if (isset($content['attribs']['']['bitrate']))
11028
							{
11029
								$bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
11030
							}
11031
							if (isset($content['attribs']['']['channels']))
11032
							{
11033
								$channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
11034
							}
11035
							if (isset($content['attribs']['']['duration']))
11036
							{
11037
								$duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
11038
							}
11039
							else
11040
							{
11041
								$duration = $duration_parent;
11042
							}
11043
							if (isset($content['attribs']['']['expression']))
11044
							{
11045
								$expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
11046
							}
11047
							if (isset($content['attribs']['']['framerate']))
11048
							{
11049
								$framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
11050
							}
11051
							if (isset($content['attribs']['']['height']))
11052
							{
11053
								$height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
11054
							}
11055
							if (isset($content['attribs']['']['lang']))
11056
							{
11057
								$lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
11058
							}
11059
							if (isset($content['attribs']['']['fileSize']))
11060
							{
11061
								$length = ceil($content['attribs']['']['fileSize']);
11062
							}
11063
							if (isset($content['attribs']['']['medium']))
11064
							{
11065
								$medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
11066
							}
11067
							if (isset($content['attribs']['']['samplingrate']))
11068
							{
11069
								$samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
11070
							}
11071
							if (isset($content['attribs']['']['type']))
11072
							{
11073
								$type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
11074
							}
11075
							if (isset($content['attribs']['']['width']))
11076
							{
11077
								$width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
11078
							}
11079
							$url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
11080
11081
							// Checking the other optional media: elements. Priority: media:content, media:group, item, channel
11082
11083
							// CAPTIONS
11084
							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
11085
							{
11086
								foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
11087
								{
11088
									$caption_type = null;
11089
									$caption_lang = null;
11090
									$caption_startTime = null;
11091
									$caption_endTime = null;
11092
									$caption_text = null;
11093
									if (isset($caption['attribs']['']['type']))
11094
									{
11095
										$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
11096
									}
11097
									if (isset($caption['attribs']['']['lang']))
11098
									{
11099
										$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
11100
									}
11101
									if (isset($caption['attribs']['']['start']))
11102
									{
11103
										$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
11104
									}
11105
									if (isset($caption['attribs']['']['end']))
11106
									{
11107
										$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
11108
									}
11109
									if (isset($caption['data']))
11110
									{
11111
										$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11112
									}
11113
									$captions[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
11114
								}
11115
								if (is_array($captions))
11116
								{
11117
									$captions = array_values(array_unique($captions));
11118
								}
11119
							}
11120
							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
11121
							{
11122
								foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
11123
								{
11124
									$caption_type = null;
11125
									$caption_lang = null;
11126
									$caption_startTime = null;
11127
									$caption_endTime = null;
11128
									$caption_text = null;
11129
									if (isset($caption['attribs']['']['type']))
11130
									{
11131
										$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
11132
									}
11133
									if (isset($caption['attribs']['']['lang']))
11134
									{
11135
										$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
11136
									}
11137
									if (isset($caption['attribs']['']['start']))
11138
									{
11139
										$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
11140
									}
11141
									if (isset($caption['attribs']['']['end']))
11142
									{
11143
										$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
11144
									}
11145
									if (isset($caption['data']))
11146
									{
11147
										$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11148
									}
11149
									$captions[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
11150
								}
11151
								if (is_array($captions))
11152
								{
11153
									$captions = array_values(array_unique($captions));
11154
								}
11155
							}
11156
							else
11157
							{
11158
								$captions = $captions_parent;
11159
							}
11160
11161
							// CATEGORIES
11162
							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
11163
							{
11164
								foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
11165
								{
11166
									$term = null;
11167
									$scheme = null;
0 ignored issues
show
Unused Code introduced by
$scheme is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11168
									$label = null;
11169
									if (isset($category['data']))
11170
									{
11171
										$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11172
									}
11173
									if (isset($category['attribs']['']['scheme']))
11174
									{
11175
										$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
11176
									}
11177
									else
11178
									{
11179
										$scheme = 'http://search.yahoo.com/mrss/category_schema';
11180
									}
11181
									if (isset($category['attribs']['']['label']))
11182
									{
11183
										$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
11184
									}
11185
									$categories[] = $this->registry->create('Category', array($term, $scheme, $label));
11186
								}
11187
							}
11188
							if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
11189
							{
11190
								foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
11191
								{
11192
									$term = null;
11193
									$scheme = null;
0 ignored issues
show
Unused Code introduced by
$scheme is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11194
									$label = null;
11195
									if (isset($category['data']))
11196
									{
11197
										$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11198
									}
11199
									if (isset($category['attribs']['']['scheme']))
11200
									{
11201
										$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
11202
									}
11203
									else
11204
									{
11205
										$scheme = 'http://search.yahoo.com/mrss/category_schema';
11206
									}
11207
									if (isset($category['attribs']['']['label']))
11208
									{
11209
										$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
11210
									}
11211
									$categories[] = $this->registry->create('Category', array($term, $scheme, $label));
11212
								}
11213
							}
11214
							if (is_array($categories) && is_array($categories_parent))
11215
							{
11216
								$categories = array_values(array_unique(array_merge($categories, $categories_parent)));
11217
							}
11218
							elseif (is_array($categories))
11219
							{
11220
								$categories = array_values(array_unique($categories));
11221
							}
11222
							elseif (is_array($categories_parent))
11223
							{
11224
								$categories = array_values(array_unique($categories_parent));
11225
							}
11226
11227
							// COPYRIGHTS
11228
							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
11229
							{
11230
								$copyright_url = null;
11231
								$copyright_label = null;
11232
								if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
11233
								{
11234
									$copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
11235
								}
11236
								if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
11237
								{
11238
									$copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11239
								}
11240
								$copyrights = $this->registry->create('Copyright', array($copyright_url, $copyright_label));
11241
							}
11242
							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
11243
							{
11244
								$copyright_url = null;
11245
								$copyright_label = null;
11246
								if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
11247
								{
11248
									$copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
11249
								}
11250
								if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
11251
								{
11252
									$copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11253
								}
11254
								$copyrights = $this->registry->create('Copyright', array($copyright_url, $copyright_label));
11255
							}
11256
							else
11257
							{
11258
								$copyrights = $copyrights_parent;
11259
							}
11260
11261
							// CREDITS
11262
							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
11263
							{
11264
								foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
11265
								{
11266
									$credit_role = null;
11267
									$credit_scheme = null;
0 ignored issues
show
Unused Code introduced by
$credit_scheme is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11268
									$credit_name = null;
11269
									if (isset($credit['attribs']['']['role']))
11270
									{
11271
										$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
11272
									}
11273
									if (isset($credit['attribs']['']['scheme']))
11274
									{
11275
										$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
11276
									}
11277
									else
11278
									{
11279
										$credit_scheme = 'urn:ebu';
11280
									}
11281
									if (isset($credit['data']))
11282
									{
11283
										$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11284
									}
11285
									$credits[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));
11286
								}
11287
								if (is_array($credits))
11288
								{
11289
									$credits = array_values(array_unique($credits));
11290
								}
11291
							}
11292
							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
11293
							{
11294
								foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
11295
								{
11296
									$credit_role = null;
11297
									$credit_scheme = null;
0 ignored issues
show
Unused Code introduced by
$credit_scheme is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11298
									$credit_name = null;
11299
									if (isset($credit['attribs']['']['role']))
11300
									{
11301
										$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
11302
									}
11303
									if (isset($credit['attribs']['']['scheme']))
11304
									{
11305
										$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
11306
									}
11307
									else
11308
									{
11309
										$credit_scheme = 'urn:ebu';
11310
									}
11311
									if (isset($credit['data']))
11312
									{
11313
										$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11314
									}
11315
									$credits[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));
11316
								}
11317
								if (is_array($credits))
11318
								{
11319
									$credits = array_values(array_unique($credits));
11320
								}
11321
							}
11322
							else
11323
							{
11324
								$credits = $credits_parent;
11325
							}
11326
11327
							// DESCRIPTION
11328
							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
11329
							{
11330
								$description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11331
							}
11332
							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
11333
							{
11334
								$description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11335
							}
11336
							else
11337
							{
11338
								$description = $description_parent;
11339
							}
11340
11341
							// HASHES
11342
							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
11343
							{
11344
								foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
11345
								{
11346
									$value = null;
11347
									$algo = null;
0 ignored issues
show
Unused Code introduced by
$algo is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11348
									if (isset($hash['data']))
11349
									{
11350
										$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11351
									}
11352
									if (isset($hash['attribs']['']['algo']))
11353
									{
11354
										$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
11355
									}
11356
									else
11357
									{
11358
										$algo = 'md5';
11359
									}
11360
									$hashes[] = $algo.':'.$value;
11361
								}
11362
								if (is_array($hashes))
11363
								{
11364
									$hashes = array_values(array_unique($hashes));
11365
								}
11366
							}
11367
							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
11368
							{
11369
								foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
11370
								{
11371
									$value = null;
11372
									$algo = null;
0 ignored issues
show
Unused Code introduced by
$algo is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11373
									if (isset($hash['data']))
11374
									{
11375
										$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11376
									}
11377
									if (isset($hash['attribs']['']['algo']))
11378
									{
11379
										$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
11380
									}
11381
									else
11382
									{
11383
										$algo = 'md5';
11384
									}
11385
									$hashes[] = $algo.':'.$value;
11386
								}
11387
								if (is_array($hashes))
11388
								{
11389
									$hashes = array_values(array_unique($hashes));
11390
								}
11391
							}
11392
							else
11393
							{
11394
								$hashes = $hashes_parent;
11395
							}
11396
11397
							// KEYWORDS
11398
							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
11399
							{
11400
								if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
11401
								{
11402
									$temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
11403
									foreach ($temp as $word)
11404
									{
11405
										$keywords[] = trim($word);
11406
									}
11407
									unset($temp);
11408
								}
11409
								if (is_array($keywords))
11410
								{
11411
									$keywords = array_values(array_unique($keywords));
11412
								}
11413
							}
11414
							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
11415
							{
11416
								if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
11417
								{
11418
									$temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
11419
									foreach ($temp as $word)
11420
									{
11421
										$keywords[] = trim($word);
11422
									}
11423
									unset($temp);
11424
								}
11425
								if (is_array($keywords))
11426
								{
11427
									$keywords = array_values(array_unique($keywords));
11428
								}
11429
							}
11430
							else
11431
							{
11432
								$keywords = $keywords_parent;
11433
							}
11434
11435
							// PLAYER
11436
							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
11437
							{
11438
								$player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
11439
							}
11440
							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
11441
							{
11442
								$player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
11443
							}
11444
							else
11445
							{
11446
								$player = $player_parent;
11447
							}
11448
11449
							// RATINGS
11450
							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
11451
							{
11452
								foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
11453
								{
11454
									$rating_scheme = null;
0 ignored issues
show
Unused Code introduced by
$rating_scheme is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11455
									$rating_value = null;
11456
									if (isset($rating['attribs']['']['scheme']))
11457
									{
11458
										$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
11459
									}
11460
									else
11461
									{
11462
										$rating_scheme = 'urn:simple';
11463
									}
11464
									if (isset($rating['data']))
11465
									{
11466
										$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11467
									}
11468
									$ratings[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
11469
								}
11470
								if (is_array($ratings))
11471
								{
11472
									$ratings = array_values(array_unique($ratings));
11473
								}
11474
							}
11475
							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
11476
							{
11477
								foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
11478
								{
11479
									$rating_scheme = null;
0 ignored issues
show
Unused Code introduced by
$rating_scheme is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11480
									$rating_value = null;
11481
									if (isset($rating['attribs']['']['scheme']))
11482
									{
11483
										$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
11484
									}
11485
									else
11486
									{
11487
										$rating_scheme = 'urn:simple';
11488
									}
11489
									if (isset($rating['data']))
11490
									{
11491
										$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11492
									}
11493
									$ratings[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
11494
								}
11495
								if (is_array($ratings))
11496
								{
11497
									$ratings = array_values(array_unique($ratings));
11498
								}
11499
							}
11500
							else
11501
							{
11502
								$ratings = $ratings_parent;
11503
							}
11504
11505
							// RESTRICTIONS
11506
							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
11507
							{
11508
								foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
11509
								{
11510
									$restriction_relationship = null;
11511
									$restriction_type = null;
11512
									$restriction_value = null;
11513
									if (isset($restriction['attribs']['']['relationship']))
11514
									{
11515
										$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
11516
									}
11517
									if (isset($restriction['attribs']['']['type']))
11518
									{
11519
										$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
11520
									}
11521
									if (isset($restriction['data']))
11522
									{
11523
										$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11524
									}
11525
									$restrictions[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
11526
								}
11527
								if (is_array($restrictions))
11528
								{
11529
									$restrictions = array_values(array_unique($restrictions));
11530
								}
11531
							}
11532
							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
11533
							{
11534
								foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
11535
								{
11536
									$restriction_relationship = null;
11537
									$restriction_type = null;
11538
									$restriction_value = null;
11539
									if (isset($restriction['attribs']['']['relationship']))
11540
									{
11541
										$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
11542
									}
11543
									if (isset($restriction['attribs']['']['type']))
11544
									{
11545
										$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
11546
									}
11547
									if (isset($restriction['data']))
11548
									{
11549
										$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11550
									}
11551
									$restrictions[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
11552
								}
11553
								if (is_array($restrictions))
11554
								{
11555
									$restrictions = array_values(array_unique($restrictions));
11556
								}
11557
							}
11558
							else
11559
							{
11560
								$restrictions = $restrictions_parent;
11561
							}
11562
11563
							// THUMBNAILS
11564
							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
11565
							{
11566
								foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
11567
								{
11568
									$thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
11569
								}
11570
								if (is_array($thumbnails))
11571
								{
11572
									$thumbnails = array_values(array_unique($thumbnails));
11573
								}
11574
							}
11575
							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
11576
							{
11577
								foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
11578
								{
11579
									$thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
11580
								}
11581
								if (is_array($thumbnails))
11582
								{
11583
									$thumbnails = array_values(array_unique($thumbnails));
11584
								}
11585
							}
11586
							else
11587
							{
11588
								$thumbnails = $thumbnails_parent;
11589
							}
11590
11591
							// TITLES
11592
							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
11593
							{
11594
								$title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11595
							}
11596
							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
11597
							{
11598
								$title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11599
							}
11600
							else
11601
							{
11602
								$title = $title_parent;
11603
							}
11604
11605
							$this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width));
11606
						}
11607
					}
11608
				}
11609
			}
11610
11611
			// If we have standalone media:content tags, loop through them.
11612
			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
11613
			{
11614
				foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
11615
				{
11616
					if (isset($content['attribs']['']['url']) || isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
11617
					{
11618
						// Attributes
11619
						$bitrate = null;
11620
						$channels = null;
11621
						$duration = null;
0 ignored issues
show
Unused Code introduced by
$duration is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11622
						$expression = null;
11623
						$framerate = null;
11624
						$height = null;
11625
						$javascript = null;
0 ignored issues
show
Unused Code introduced by
$javascript is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11626
						$lang = null;
11627
						$length = null;
11628
						$medium = null;
11629
						$samplingrate = null;
11630
						$type = null;
11631
						$url = null;
11632
						$width = null;
11633
11634
						// Elements
11635
						$captions = null;
11636
						$categories = null;
11637
						$copyrights = null;
0 ignored issues
show
Unused Code introduced by
$copyrights is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11638
						$credits = null;
11639
						$description = null;
0 ignored issues
show
Unused Code introduced by
$description is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11640
						$hashes = null;
11641
						$keywords = null;
11642
						$player = null;
11643
						$ratings = null;
11644
						$restrictions = null;
11645
						$thumbnails = null;
11646
						$title = null;
0 ignored issues
show
Unused Code introduced by
$title is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11647
11648
						// Start checking the attributes of media:content
11649
						if (isset($content['attribs']['']['bitrate']))
11650
						{
11651
							$bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
11652
						}
11653
						if (isset($content['attribs']['']['channels']))
11654
						{
11655
							$channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
11656
						}
11657
						if (isset($content['attribs']['']['duration']))
11658
						{
11659
							$duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
11660
						}
11661
						else
11662
						{
11663
							$duration = $duration_parent;
11664
						}
11665
						if (isset($content['attribs']['']['expression']))
11666
						{
11667
							$expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
11668
						}
11669
						if (isset($content['attribs']['']['framerate']))
11670
						{
11671
							$framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
11672
						}
11673
						if (isset($content['attribs']['']['height']))
11674
						{
11675
							$height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
11676
						}
11677
						if (isset($content['attribs']['']['lang']))
11678
						{
11679
							$lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
11680
						}
11681
						if (isset($content['attribs']['']['fileSize']))
11682
						{
11683
							$length = ceil($content['attribs']['']['fileSize']);
11684
						}
11685
						if (isset($content['attribs']['']['medium']))
11686
						{
11687
							$medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
11688
						}
11689
						if (isset($content['attribs']['']['samplingrate']))
11690
						{
11691
							$samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
11692
						}
11693
						if (isset($content['attribs']['']['type']))
11694
						{
11695
							$type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
11696
						}
11697
						if (isset($content['attribs']['']['width']))
11698
						{
11699
							$width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
11700
						}
11701
						if (isset($content['attribs']['']['url']))
11702
						{
11703
							$url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
11704
						}
11705
						// Checking the other optional media: elements. Priority: media:content, media:group, item, channel
11706
11707
						// CAPTIONS
11708
						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
11709
						{
11710
							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
11711
							{
11712
								$caption_type = null;
11713
								$caption_lang = null;
11714
								$caption_startTime = null;
11715
								$caption_endTime = null;
11716
								$caption_text = null;
11717
								if (isset($caption['attribs']['']['type']))
11718
								{
11719
									$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
11720
								}
11721
								if (isset($caption['attribs']['']['lang']))
11722
								{
11723
									$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
11724
								}
11725
								if (isset($caption['attribs']['']['start']))
11726
								{
11727
									$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
11728
								}
11729
								if (isset($caption['attribs']['']['end']))
11730
								{
11731
									$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
11732
								}
11733
								if (isset($caption['data']))
11734
								{
11735
									$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11736
								}
11737
								$captions[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
11738
							}
11739
							if (is_array($captions))
11740
							{
11741
								$captions = array_values(array_unique($captions));
11742
							}
11743
						}
11744
						else
11745
						{
11746
							$captions = $captions_parent;
11747
						}
11748
11749
						// CATEGORIES
11750
						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
11751
						{
11752
							foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
11753
							{
11754
								$term = null;
11755
								$scheme = null;
0 ignored issues
show
Unused Code introduced by
$scheme is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11756
								$label = null;
11757
								if (isset($category['data']))
11758
								{
11759
									$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11760
								}
11761
								if (isset($category['attribs']['']['scheme']))
11762
								{
11763
									$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
11764
								}
11765
								else
11766
								{
11767
									$scheme = 'http://search.yahoo.com/mrss/category_schema';
11768
								}
11769
								if (isset($category['attribs']['']['label']))
11770
								{
11771
									$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
11772
								}
11773
								$categories[] = $this->registry->create('Category', array($term, $scheme, $label));
11774
							}
11775
						}
11776
						if (is_array($categories) && is_array($categories_parent))
11777
						{
11778
							$categories = array_values(array_unique(array_merge($categories, $categories_parent)));
11779
						}
11780
						elseif (is_array($categories))
11781
						{
11782
							$categories = array_values(array_unique($categories));
11783
						}
11784
						elseif (is_array($categories_parent))
11785
						{
11786
							$categories = array_values(array_unique($categories_parent));
11787
						}
11788
						else
11789
						{
11790
							$categories = null;
11791
						}
11792
11793
						// COPYRIGHTS
11794
						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
11795
						{
11796
							$copyright_url = null;
11797
							$copyright_label = null;
11798
							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
11799
							{
11800
								$copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
11801
							}
11802
							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
11803
							{
11804
								$copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11805
							}
11806
							$copyrights = $this->registry->create('Copyright', array($copyright_url, $copyright_label));
11807
						}
11808
						else
11809
						{
11810
							$copyrights = $copyrights_parent;
11811
						}
11812
11813
						// CREDITS
11814
						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
11815
						{
11816
							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
11817
							{
11818
								$credit_role = null;
11819
								$credit_scheme = null;
0 ignored issues
show
Unused Code introduced by
$credit_scheme is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11820
								$credit_name = null;
11821
								if (isset($credit['attribs']['']['role']))
11822
								{
11823
									$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
11824
								}
11825
								if (isset($credit['attribs']['']['scheme']))
11826
								{
11827
									$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
11828
								}
11829
								else
11830
								{
11831
									$credit_scheme = 'urn:ebu';
11832
								}
11833
								if (isset($credit['data']))
11834
								{
11835
									$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11836
								}
11837
								$credits[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));
11838
							}
11839
							if (is_array($credits))
11840
							{
11841
								$credits = array_values(array_unique($credits));
11842
							}
11843
						}
11844
						else
11845
						{
11846
							$credits = $credits_parent;
11847
						}
11848
11849
						// DESCRIPTION
11850
						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
11851
						{
11852
							$description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11853
						}
11854
						else
11855
						{
11856
							$description = $description_parent;
11857
						}
11858
11859
						// HASHES
11860
						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
11861
						{
11862
							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
11863
							{
11864
								$value = null;
11865
								$algo = null;
0 ignored issues
show
Unused Code introduced by
$algo is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11866
								if (isset($hash['data']))
11867
								{
11868
									$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11869
								}
11870
								if (isset($hash['attribs']['']['algo']))
11871
								{
11872
									$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
11873
								}
11874
								else
11875
								{
11876
									$algo = 'md5';
11877
								}
11878
								$hashes[] = $algo.':'.$value;
11879
							}
11880
							if (is_array($hashes))
11881
							{
11882
								$hashes = array_values(array_unique($hashes));
11883
							}
11884
						}
11885
						else
11886
						{
11887
							$hashes = $hashes_parent;
11888
						}
11889
11890
						// KEYWORDS
11891
						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
11892
						{
11893
							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
11894
							{
11895
								$temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
11896
								foreach ($temp as $word)
11897
								{
11898
									$keywords[] = trim($word);
11899
								}
11900
								unset($temp);
11901
							}
11902
							if (is_array($keywords))
11903
							{
11904
								$keywords = array_values(array_unique($keywords));
11905
							}
11906
						}
11907
						else
11908
						{
11909
							$keywords = $keywords_parent;
11910
						}
11911
11912
						// PLAYER
11913
						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
11914
						{
11915
							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'])) {
11916
								$player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
11917
							}
11918
						}
11919
						else
11920
						{
11921
							$player = $player_parent;
11922
						}
11923
11924
						// RATINGS
11925
						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
11926
						{
11927
							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
11928
							{
11929
								$rating_scheme = null;
0 ignored issues
show
Unused Code introduced by
$rating_scheme is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
11930
								$rating_value = null;
11931
								if (isset($rating['attribs']['']['scheme']))
11932
								{
11933
									$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
11934
								}
11935
								else
11936
								{
11937
									$rating_scheme = 'urn:simple';
11938
								}
11939
								if (isset($rating['data']))
11940
								{
11941
									$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11942
								}
11943
								$ratings[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
11944
							}
11945
							if (is_array($ratings))
11946
							{
11947
								$ratings = array_values(array_unique($ratings));
11948
							}
11949
						}
11950
						else
11951
						{
11952
							$ratings = $ratings_parent;
11953
						}
11954
11955
						// RESTRICTIONS
11956
						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
11957
						{
11958
							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
11959
							{
11960
								$restriction_relationship = null;
11961
								$restriction_type = null;
11962
								$restriction_value = null;
11963
								if (isset($restriction['attribs']['']['relationship']))
11964
								{
11965
									$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
11966
								}
11967
								if (isset($restriction['attribs']['']['type']))
11968
								{
11969
									$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
11970
								}
11971
								if (isset($restriction['data']))
11972
								{
11973
									$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
11974
								}
11975
								$restrictions[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
11976
							}
11977
							if (is_array($restrictions))
11978
							{
11979
								$restrictions = array_values(array_unique($restrictions));
11980
							}
11981
						}
11982
						else
11983
						{
11984
							$restrictions = $restrictions_parent;
11985
						}
11986
11987
						// THUMBNAILS
11988
						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
11989
						{
11990
							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
11991
							{
11992
								if (isset($thumbnail['attribs']['']['url'])) {
11993
									$thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
11994
								}
11995
							}
11996
							if (is_array($thumbnails))
11997
							{
11998
								$thumbnails = array_values(array_unique($thumbnails));
11999
							}
12000
						}
12001
						else
12002
						{
12003
							$thumbnails = $thumbnails_parent;
12004
						}
12005
12006
						// TITLES
12007
						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
12008
						{
12009
							$title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
12010
						}
12011
						else
12012
						{
12013
							$title = $title_parent;
12014
						}
12015
12016
						$this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width));
12017
					}
12018
				}
12019
			}
12020
12021
			foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
12022
			{
12023
				if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
12024
				{
12025
					// Attributes
12026
					$bitrate = null;
12027
					$channels = null;
12028
					$duration = null;
0 ignored issues
show
Unused Code introduced by
$duration is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
12029
					$expression = null;
12030
					$framerate = null;
12031
					$height = null;
12032
					$javascript = null;
0 ignored issues
show
Unused Code introduced by
$javascript is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
12033
					$lang = null;
12034
					$length = null;
12035
					$medium = null;
12036
					$samplingrate = null;
12037
					$type = null;
12038
					$url = null;
0 ignored issues
show
Unused Code introduced by
$url is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
12039
					$width = null;
12040
12041
					$url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
12042
					if (isset($link['attribs']['']['type']))
12043
					{
12044
						$type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
12045
					}
12046
					if (isset($link['attribs']['']['length']))
12047
					{
12048
						$length = ceil($link['attribs']['']['length']);
12049
					}
12050
					if (isset($link['attribs']['']['title']))
12051
					{
12052
						$title = $this->sanitize($link['attribs']['']['title'], SIMPLEPIE_CONSTRUCT_TEXT);
12053
					}
12054
					else
12055
					{
12056
						$title = $title_parent;
12057
					}
12058
12059
					// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
12060
					$this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title, $width));
12061
				}
12062
			}
12063
12064
			foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
12065
			{
12066
				if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
12067
				{
12068
					// Attributes
12069
					$bitrate = null;
12070
					$channels = null;
12071
					$duration = null;
0 ignored issues
show
Unused Code introduced by
$duration is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
12072
					$expression = null;
12073
					$framerate = null;
12074
					$height = null;
12075
					$javascript = null;
0 ignored issues
show
Unused Code introduced by
$javascript is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
12076
					$lang = null;
12077
					$length = null;
12078
					$medium = null;
12079
					$samplingrate = null;
12080
					$type = null;
12081
					$url = null;
0 ignored issues
show
Unused Code introduced by
$url is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
12082
					$width = null;
12083
12084
					$url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
12085
					if (isset($link['attribs']['']['type']))
12086
					{
12087
						$type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
12088
					}
12089
					if (isset($link['attribs']['']['length']))
12090
					{
12091
						$length = ceil($link['attribs']['']['length']);
12092
					}
12093
12094
					// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
12095
					$this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width));
12096
				}
12097
			}
12098
12099
			if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
12100
			{
12101
				if (isset($enclosure[0]['attribs']['']['url']))
12102
				{
12103
					// Attributes
12104
					$bitrate = null;
12105
					$channels = null;
12106
					$duration = null;
0 ignored issues
show
Unused Code introduced by
$duration is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
12107
					$expression = null;
12108
					$framerate = null;
12109
					$height = null;
12110
					$javascript = null;
0 ignored issues
show
Unused Code introduced by
$javascript is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
12111
					$lang = null;
12112
					$length = null;
12113
					$medium = null;
12114
					$samplingrate = null;
12115
					$type = null;
12116
					$url = null;
0 ignored issues
show
Unused Code introduced by
$url is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
12117
					$width = null;
12118
12119
					$url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
12120
					if (isset($enclosure[0]['attribs']['']['type']))
12121
					{
12122
						$type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
12123
					}
12124
					if (isset($enclosure[0]['attribs']['']['length']))
12125
					{
12126
						$length = ceil($enclosure[0]['attribs']['']['length']);
12127
					}
12128
12129
					// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
12130
					$this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width));
12131
				}
12132
			}
12133
12134
			if (sizeof($this->data['enclosures']) === 0 && ($url || $type || $length || $bitrate || $captions_parent || $categories_parent || $channels || $copyrights_parent || $credits_parent || $description_parent || $duration_parent || $expression || $framerate || $hashes_parent || $height || $keywords_parent || $lang || $medium || $player_parent || $ratings_parent || $restrictions_parent || $samplingrate || $thumbnails_parent || $title_parent || $width))
0 ignored issues
show
Bug Best Practice introduced by
The expression $url of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Bug Best Practice introduced by
The expression $type of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Bug Best Practice introduced by
The expression $bitrate of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Bug Best Practice introduced by
The expression $channels of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Bug Best Practice introduced by
The expression $expression of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Bug Best Practice introduced by
The expression $framerate of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Bug Best Practice introduced by
The expression $height of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Bug Best Practice introduced by
The expression $lang of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Bug Best Practice introduced by
The expression $medium of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Bug Best Practice introduced by
The expression $restrictions_parent of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
Bug Best Practice introduced by
The expression $samplingrate of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Bug Best Practice introduced by
The expression $width of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
12135
			{
12136
				// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
12137
				$this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width));
12138
			}
12139
12140
			$this->data['enclosures'] = array_values(array_unique($this->data['enclosures']));
12141
		}
12142
		if (!empty($this->data['enclosures']))
12143
		{
12144
			return $this->data['enclosures'];
12145
		}
12146
		else
12147
		{
12148
			return null;
12149
		}
12150
	}
12151
12152
	/**
12153
	 * Get the latitude coordinates for the item
12154
	 *
12155
	 * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
12156
	 *
12157
	 * Uses `<geo:lat>` or `<georss:point>`
12158
	 *
12159
	 * @since 1.0
12160
	 * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
12161
	 * @link http://www.georss.org/ GeoRSS
12162
	 * @return string|null
12163
	 */
12164
	public function get_latitude()
12165
	{
12166
		if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
12167
		{
12168
			return (float) $return[0]['data'];
12169
		}
12170
		elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
12171
		{
12172
			return (float) $match[1];
12173
		}
12174
		else
12175
		{
12176
			return null;
12177
		}
12178
	}
12179
12180
	/**
12181
	 * Get the longitude coordinates for the item
12182
	 *
12183
	 * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
12184
	 *
12185
	 * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`
12186
	 *
12187
	 * @since 1.0
12188
	 * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
12189
	 * @link http://www.georss.org/ GeoRSS
12190
	 * @return string|null
12191
	 */
12192
	public function get_longitude()
12193
	{
12194
		if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
12195
		{
12196
			return (float) $return[0]['data'];
12197
		}
12198
		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
12199
		{
12200
			return (float) $return[0]['data'];
12201
		}
12202
		elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
12203
		{
12204
			return (float) $match[2];
12205
		}
12206
		else
12207
		{
12208
			return null;
12209
		}
12210
	}
12211
12212
	/**
12213
	 * Get the `<atom:source>` for the item
12214
	 *
12215
	 * @since 1.1
12216
	 * @return SimplePie_Source|null
12217
	 */
12218
	public function get_source()
12219
	{
12220
		if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
12221
		{
12222
			return $this->registry->create('Source', array($this, $return[0]));
12223
		}
12224
		else
12225
		{
12226
			return null;
12227
		}
12228
	}
12229
}
12230
12231
/**
12232
 * Used for feed auto-discovery
12233
 *
12234
 *
12235
 * This class can be overloaded with {@see SimplePie::set_locator_class()}
12236
 *
12237
 * @package SimplePie
12238
 */
12239
class SimplePie_Locator
12240
{
12241
	var $useragent;
12242
	var $timeout;
12243
	var $file;
12244
	var $local = array();
12245
	var $elsewhere = array();
12246
	var $cached_entities = array();
12247
	var $http_base;
12248
	var $base;
12249
	var $base_location = 0;
12250
	var $checked_feeds = 0;
12251
	var $max_checked_feeds = 10;
12252
	protected $registry;
12253
12254
	public function __construct(SimplePie_File $file, $timeout = 10, $useragent = null, $max_checked_feeds = 10)
12255
	{
12256
		$this->file = $file;
12257
		$this->useragent = $useragent;
12258
		$this->timeout = $timeout;
12259
		$this->max_checked_feeds = $max_checked_feeds;
12260
12261
		if (class_exists('DOMDocument'))
12262
		{
12263
			$this->dom = new DOMDocument();
0 ignored issues
show
Bug introduced by
The property dom does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
12264
12265
			set_error_handler(array('SimplePie_Misc', 'silence_errors'));
12266
			$this->dom->loadHTML($this->file->body);
12267
			restore_error_handler();
12268
		}
12269
		else
12270
		{
12271
			$this->dom = null;
12272
		}
12273
	}
12274
12275
	public function set_registry(SimplePie_Registry $registry)
12276
	{
12277
		$this->registry = $registry;
12278
	}
12279
12280
	public function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
12281
	{
12282
		if ($this->is_feed($this->file))
12283
		{
12284
			return $this->file;
12285
		}
12286
12287
		if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
12288
		{
12289
			$sniffer = $this->registry->create('Content_Type_Sniffer', array($this->file));
12290
			if ($sniffer->get_type() !== 'text/html')
12291
			{
12292
				return null;
12293
			}
12294
		}
12295
12296
		if ($type & ~SIMPLEPIE_LOCATOR_NONE)
12297
		{
12298
			$this->get_base();
12299
		}
12300
12301
		if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
12302
		{
12303
			return $working[0];
12304
		}
12305
12306
		if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
12307
		{
12308
			if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
12309
			{
12310
				return $working[0];
12311
			}
12312
12313
			if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
12314
			{
12315
				return $working[0];
12316
			}
12317
12318
			if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
12319
			{
12320
				return $working[0];
12321
			}
12322
12323
			if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
12324
			{
12325
				return $working[0];
12326
			}
12327
		}
12328
		return null;
12329
	}
12330
12331
	public function is_feed($file, $check_html = false)
12332
	{
12333
		if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
12334
		{
12335
			$sniffer = $this->registry->create('Content_Type_Sniffer', array($file));
12336
			$sniffed = $sniffer->get_type();
12337
			$mime_types = array('application/rss+xml', 'application/rdf+xml',
12338
			                    'text/rdf', 'application/atom+xml', 'text/xml',
12339
			                    'application/xml', 'application/x-rss+xml');
12340
			if ($check_html)
12341
			{
12342
				$mime_types[] = 'text/html';
12343
			}
12344
			if (in_array($sniffed, $mime_types))
12345
			{
12346
				return true;
12347
			}
12348
			else
12349
			{
12350
				return false;
12351
			}
12352
		}
12353
		elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
12354
		{
12355
			return true;
12356
		}
12357
		else
12358
		{
12359
			return false;
12360
		}
12361
	}
12362
12363
	public function get_base()
12364
	{
12365
		if ($this->dom === null)
12366
		{
12367
			throw new SimplePie_Exception('DOMDocument not found, unable to use locator');
12368
		}
12369
		$this->http_base = $this->file->url;
12370
		$this->base = $this->http_base;
12371
		$elements = $this->dom->getElementsByTagName('base');
12372
		foreach ($elements as $element)
12373
		{
12374
			if ($element->hasAttribute('href'))
12375
			{
12376
				$base = $this->registry->call('Misc', 'absolutize_url', array(trim($element->getAttribute('href')), $this->http_base));
12377
				if ($base === false)
12378
				{
12379
					continue;
12380
				}
12381
				$this->base = $base;
12382
				$this->base_location = method_exists($element, 'getLineNo') ? $element->getLineNo() : 0;
12383
				break;
12384
			}
12385
		}
12386
	}
12387
12388
	public function autodiscovery()
12389
	{
12390
		$done = array();
12391
		$feeds = array();
12392
		$feeds = array_merge($feeds, $this->search_elements_by_tag('link', $done, $feeds));
12393
		$feeds = array_merge($feeds, $this->search_elements_by_tag('a', $done, $feeds));
12394
		$feeds = array_merge($feeds, $this->search_elements_by_tag('area', $done, $feeds));
12395
12396
		if (!empty($feeds))
12397
		{
12398
			return array_values($feeds);
12399
		}
12400
		else
12401
		{
12402
			return null;
12403
		}
12404
	}
12405
12406
	protected function search_elements_by_tag($name, &$done, $feeds)
12407
	{
12408
		if ($this->dom === null)
12409
		{
12410
			throw new SimplePie_Exception('DOMDocument not found, unable to use locator');
12411
		}
12412
12413
		$links = $this->dom->getElementsByTagName($name);
12414
		foreach ($links as $link)
12415
		{
12416
			if ($this->checked_feeds === $this->max_checked_feeds)
12417
			{
12418
				break;
12419
			}
12420
			if ($link->hasAttribute('href') && $link->hasAttribute('rel'))
12421
			{
12422
				$rel = array_unique($this->registry->call('Misc', 'space_separated_tokens', array(strtolower($link->getAttribute('rel')))));
12423
				$line = method_exists($link, 'getLineNo') ? $link->getLineNo() : 1;
12424
12425
				if ($this->base_location < $line)
12426
				{
12427
					$href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base));
12428
				}
12429
				else
12430
				{
12431
					$href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->http_base));
12432
				}
12433
				if ($href === false)
12434
				{
12435
					continue;
12436
				}
12437
12438
				if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !in_array('stylesheet', $rel) && $link->hasAttribute('type') && in_array(strtolower($this->registry->call('Misc', 'parse_mime', array($link->getAttribute('type')))), array('text/html', 'application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href]))
12439
				{
12440
					$this->checked_feeds++;
12441
					$headers = array(
12442
						'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',
12443
					);
12444
					$feed = $this->registry->create('File', array($href, $this->timeout, 5, $headers, $this->useragent));
12445
					if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed, true))
12446
					{
12447
						$feeds[$href] = $feed;
12448
					}
12449
				}
12450
				$done[] = $href;
12451
			}
12452
		}
12453
12454
		return $feeds;
12455
	}
12456
12457
	public function get_links()
12458
	{
12459
		if ($this->dom === null)
12460
		{
12461
			throw new SimplePie_Exception('DOMDocument not found, unable to use locator');
12462
		}
12463
12464
		$links = $this->dom->getElementsByTagName('a');
12465
		foreach ($links as $link)
12466
		{
12467
			if ($link->hasAttribute('href'))
12468
			{
12469
				$href = trim($link->getAttribute('href'));
12470
				$parsed = $this->registry->call('Misc', 'parse_url', array($href));
12471
				if ($parsed['scheme'] === '' || preg_match('/^(https?|feed)?$/i', $parsed['scheme']))
12472
				{
12473
					if (method_exists($link, 'getLineNo') && $this->base_location < $link->getLineNo())
12474
					{
12475
						$href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base));
12476
					}
12477
					else
12478
					{
12479
						$href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->http_base));
12480
					}
12481
					if ($href === false)
12482
					{
12483
						continue;
12484
					}
12485
12486
					$current = $this->registry->call('Misc', 'parse_url', array($this->file->url));
12487
12488
					if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
12489
					{
12490
						$this->local[] = $href;
12491
					}
12492
					else
12493
					{
12494
						$this->elsewhere[] = $href;
12495
					}
12496
				}
12497
			}
12498
		}
12499
		$this->local = array_unique($this->local);
12500
		$this->elsewhere = array_unique($this->elsewhere);
12501
		if (!empty($this->local) || !empty($this->elsewhere))
12502
		{
12503
			return true;
12504
		}
12505
		return null;
12506
	}
12507
12508
	public function get_rel_link($rel)
12509
	{
12510
		if ($this->dom === null)
12511
		{
12512
			throw new SimplePie_Exception('DOMDocument not found, unable to use '.
12513
			                              'locator');
12514
		}
12515
		if (!class_exists('DOMXpath'))
12516
		{
12517
			throw new SimplePie_Exception('DOMXpath not found, unable to use '.
12518
			                              'get_rel_link');
12519
		}
12520
12521
		$xpath = new DOMXpath($this->dom);
12522
		$query = '//a[@rel and @href] | //link[@rel and @href]';
12523
		foreach ($xpath->query($query) as $link)
12524
		{
12525
			$href = trim($link->getAttribute('href'));
12526
			$parsed = $this->registry->call('Misc', 'parse_url', array($href));
12527
			if ($parsed['scheme'] === '' ||
12528
			    preg_match('/^https?$/i', $parsed['scheme']))
12529
			{
12530
				if (method_exists($link, 'getLineNo') &&
12531
				    $this->base_location < $link->getLineNo())
12532
				{
12533
					$href =
12534
						$this->registry->call('Misc', 'absolutize_url',
12535
						                      array(trim($link->getAttribute('href')),
12536
						                            $this->base));
12537
				}
12538
				else
12539
				{
12540
					$href =
12541
						$this->registry->call('Misc', 'absolutize_url',
12542
						                      array(trim($link->getAttribute('href')),
12543
						                            $this->http_base));
12544
				}
12545
				if ($href === false)
12546
				{
12547
					return null;
12548
				}
12549
				$rel_values = explode(' ', strtolower($link->getAttribute('rel')));
12550
				if (in_array($rel, $rel_values))
12551
				{
12552
					return $href;
12553
				}
12554
			}
12555
		}
12556
		return null;
12557
	}
12558
12559
	public function extension(&$array)
12560
	{
12561
		foreach ($array as $key => $value)
12562
		{
12563
			if ($this->checked_feeds === $this->max_checked_feeds)
12564
			{
12565
				break;
12566
			}
12567
			if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
12568
			{
12569
				$this->checked_feeds++;
12570
12571
				$headers = array(
12572
					'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',
12573
				);
12574
				$feed = $this->registry->create('File', array($value, $this->timeout, 5, $headers, $this->useragent));
12575
				if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
12576
				{
12577
					return array($feed);
12578
				}
12579
				else
12580
				{
12581
					unset($array[$key]);
12582
				}
12583
			}
12584
		}
12585
		return null;
12586
	}
12587
12588
	public function body(&$array)
12589
	{
12590
		foreach ($array as $key => $value)
12591
		{
12592
			if ($this->checked_feeds === $this->max_checked_feeds)
12593
			{
12594
				break;
12595
			}
12596
			if (preg_match('/(rss|rdf|atom|xml)/i', $value))
12597
			{
12598
				$this->checked_feeds++;
12599
				$headers = array(
0 ignored issues
show
Unused Code introduced by
$headers is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
12600
					'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',
12601
				);
12602
				$feed = $this->registry->create('File', array($value, $this->timeout, 5, null, $this->useragent));
12603
				if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
12604
				{
12605
					return array($feed);
12606
				}
12607
				else
12608
				{
12609
					unset($array[$key]);
12610
				}
12611
			}
12612
		}
12613
		return null;
12614
	}
12615
}
12616
12617
/**
12618
 * Miscellanous utilities
12619
 *
12620
 * @package SimplePie
12621
 */
12622
class SimplePie_Misc
12623
{
12624
	public static function time_hms($seconds)
12625
	{
12626
		$time = '';
12627
12628
		$hours = floor($seconds / 3600);
12629
		$remainder = $seconds % 3600;
12630
		if ($hours > 0)
12631
		{
12632
			$time .= $hours.':';
12633
		}
12634
12635
		$minutes = floor($remainder / 60);
12636
		$seconds = $remainder % 60;
12637
		if ($minutes < 10 && $hours > 0)
12638
		{
12639
			$minutes = '0' . $minutes;
12640
		}
12641
		if ($seconds < 10)
12642
		{
12643
			$seconds = '0' . $seconds;
12644
		}
12645
12646
		$time .= $minutes.':';
12647
		$time .= $seconds;
12648
12649
		return $time;
12650
	}
12651
12652
	public static function absolutize_url($relative, $base)
12653
	{
12654
		$iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
12655
		if ($iri === false)
12656
		{
12657
			return false;
12658
		}
12659
		return $iri->get_uri();
12660
	}
12661
12662
	/**
12663
	 * Get a HTML/XML element from a HTML string
12664
	 *
12665
	 * @deprecated Use DOMDocument instead (parsing HTML with regex is bad!)
12666
	 * @param string $realname Element name (including namespace prefix if applicable)
12667
	 * @param string $string HTML document
12668
	 * @return array
12669
	 */
12670
	public static function get_element($realname, $string)
12671
	{
12672
		$return = array();
12673
		$name = preg_quote($realname, '/');
12674
		if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
12675
		{
12676
			for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
12677
			{
12678
				$return[$i]['tag'] = $realname;
12679
				$return[$i]['full'] = $matches[$i][0][0];
12680
				$return[$i]['offset'] = $matches[$i][0][1];
12681
				if (strlen($matches[$i][3][0]) <= 2)
12682
				{
12683
					$return[$i]['self_closing'] = true;
12684
				}
12685
				else
12686
				{
12687
					$return[$i]['self_closing'] = false;
12688
					$return[$i]['content'] = $matches[$i][4][0];
12689
				}
12690
				$return[$i]['attribs'] = array();
12691
				if (isset($matches[$i][2][0]) && preg_match_all('/[\x09\x0A\x0B\x0C\x0D\x20]+([^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*)(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"([^"]*)"|\'([^\']*)\'|([^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?/', ' ' . $matches[$i][2][0] . ' ', $attribs, PREG_SET_ORDER))
12692
				{
12693
					for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
12694
					{
12695
						if (count($attribs[$j]) === 2)
12696
						{
12697
							$attribs[$j][2] = $attribs[$j][1];
12698
						}
12699
						$return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]));
0 ignored issues
show
Security Bug introduced by
It seems like end($attribs[$j]) targeting end() can also be of type false; however, SimplePie_Misc::entities_decode() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
Deprecated Code introduced by
The method SimplePie_Misc::entities_decode() has been deprecated with message: Use DOMDocument instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
12700
					}
12701
				}
12702
			}
12703
		}
12704
		return $return;
12705
	}
12706
12707
	public static function element_implode($element)
12708
	{
12709
		$full = "<$element[tag]";
12710
		foreach ($element['attribs'] as $key => $value)
12711
		{
12712
			$key = strtolower($key);
12713
			$full .= " $key=\"" . htmlspecialchars($value['data'], ENT_COMPAT, 'UTF-8') . '"';
12714
		}
12715
		if ($element['self_closing'])
12716
		{
12717
			$full .= ' />';
12718
		}
12719
		else
12720
		{
12721
			$full .= ">$element[content]</$element[tag]>";
12722
		}
12723
		return $full;
12724
	}
12725
12726
	public static function error($message, $level, $file, $line)
12727
	{
12728
		if ((ini_get('error_reporting') & $level) > 0)
12729
		{
12730
			switch ($level)
12731
			{
12732
				case E_USER_ERROR:
12733
					$note = 'PHP Error';
12734
					break;
12735
				case E_USER_WARNING:
12736
					$note = 'PHP Warning';
12737
					break;
12738
				case E_USER_NOTICE:
12739
					$note = 'PHP Notice';
12740
					break;
12741
				default:
12742
					$note = 'Unknown Error';
12743
					break;
12744
			}
12745
12746
			$log_error = true;
12747
			if (!function_exists('error_log'))
12748
			{
12749
				$log_error = false;
12750
			}
12751
12752
			$log_file = @ini_get('error_log');
12753
			if (!empty($log_file) && ('syslog' !== $log_file) && !@is_writable($log_file))
12754
			{
12755
				$log_error = false;
12756
			}
12757
12758
			if ($log_error)
12759
			{
12760
				@error_log("$note: $message in $file on line $line", 0);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
12761
			}
12762
		}
12763
12764
		return $message;
12765
	}
12766
12767
	public static function fix_protocol($url, $http = 1)
12768
	{
12769
		$url = SimplePie_Misc::normalize_url($url);
12770
		$parsed = SimplePie_Misc::parse_url($url);
12771
		if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
12772
		{
12773
			return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
12774
		}
12775
12776
		if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
12777
		{
12778
			return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
12779
		}
12780
12781
		if ($http === 2 && $parsed['scheme'] !== '')
12782
		{
12783
			return "feed:$url";
12784
		}
12785
		elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
12786
		{
12787
			return substr_replace($url, 'podcast', 0, 4);
12788
		}
12789
		elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
12790
		{
12791
			return substr_replace($url, 'itpc', 0, 4);
12792
		}
12793
		else
12794
		{
12795
			return $url;
12796
		}
12797
	}
12798
12799
	public static function array_merge_recursive($array1, $array2)
12800
	{
12801
		foreach ($array2 as $key => $value)
12802
		{
12803
			if (is_array($value))
12804
			{
12805
				$array1[$key] = SimplePie_Misc::array_merge_recursive($array1[$key], $value);
12806
			}
12807
			else
12808
			{
12809
				$array1[$key] = $value;
12810
			}            
12811
		}
12812
		
12813
		return $array1;
12814
	}
12815
12816
	public static function parse_url($url)
12817
	{
12818
		$iri = new SimplePie_IRI($url);
12819
		return array(
12820
			'scheme' => (string) $iri->scheme,
0 ignored issues
show
Documentation introduced by
The property $scheme is declared protected in SimplePie_IRI. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
12821
			'authority' => (string) $iri->authority,
0 ignored issues
show
Documentation introduced by
The property authority does not exist on object<SimplePie_IRI>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
12822
			'path' => (string) $iri->path,
0 ignored issues
show
Documentation introduced by
The property path does not exist on object<SimplePie_IRI>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
12823
			'query' => (string) $iri->query,
0 ignored issues
show
Bug introduced by
The property query does not seem to exist. Did you mean iquery?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
12824
			'fragment' => (string) $iri->fragment
0 ignored issues
show
Bug introduced by
The property fragment does not seem to exist. Did you mean ifragment?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
12825
		);
12826
	}
12827
12828
	public static function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
12829
	{
12830
		$iri = new SimplePie_IRI('');
12831
		$iri->scheme = $scheme;
0 ignored issues
show
Documentation introduced by
The property $scheme is declared protected in SimplePie_IRI. Since you implemented __set(), maybe consider adding a @property or @property-write annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
12832
		$iri->authority = $authority;
0 ignored issues
show
Documentation introduced by
The property authority does not exist on object<SimplePie_IRI>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
12833
		$iri->path = $path;
0 ignored issues
show
Documentation introduced by
The property path does not exist on object<SimplePie_IRI>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
12834
		$iri->query = $query;
0 ignored issues
show
Bug introduced by
The property query does not seem to exist. Did you mean iquery?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
12835
		$iri->fragment = $fragment;
0 ignored issues
show
Bug introduced by
The property fragment does not seem to exist. Did you mean ifragment?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
12836
		return $iri->get_uri();
12837
	}
12838
12839
	public static function normalize_url($url)
12840
	{
12841
		$iri = new SimplePie_IRI($url);
12842
		return $iri->get_uri();
12843
	}
12844
12845
	public static function percent_encoding_normalization($match)
12846
	{
12847
		$integer = hexdec($match[1]);
12848
		if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
12849
		{
12850
			return chr($integer);
12851
		}
12852
		else
12853
		{
12854
			return strtoupper($match[0]);
12855
		}
12856
	}
12857
12858
	/**
12859
	 * Converts a Windows-1252 encoded string to a UTF-8 encoded string
12860
	 *
12861
	 * @static
12862
	 * @param string $string Windows-1252 encoded string
12863
	 * @return string UTF-8 encoded string
12864
	 */
12865
	public static function windows_1252_to_utf8($string)
12866
	{
12867
		static $convert_table = array("\x80" => "\xE2\x82\xAC", "\x81" => "\xEF\xBF\xBD", "\x82" => "\xE2\x80\x9A", "\x83" => "\xC6\x92", "\x84" => "\xE2\x80\x9E", "\x85" => "\xE2\x80\xA6", "\x86" => "\xE2\x80\xA0", "\x87" => "\xE2\x80\xA1", "\x88" => "\xCB\x86", "\x89" => "\xE2\x80\xB0", "\x8A" => "\xC5\xA0", "\x8B" => "\xE2\x80\xB9", "\x8C" => "\xC5\x92", "\x8D" => "\xEF\xBF\xBD", "\x8E" => "\xC5\xBD", "\x8F" => "\xEF\xBF\xBD", "\x90" => "\xEF\xBF\xBD", "\x91" => "\xE2\x80\x98", "\x92" => "\xE2\x80\x99", "\x93" => "\xE2\x80\x9C", "\x94" => "\xE2\x80\x9D", "\x95" => "\xE2\x80\xA2", "\x96" => "\xE2\x80\x93", "\x97" => "\xE2\x80\x94", "\x98" => "\xCB\x9C", "\x99" => "\xE2\x84\xA2", "\x9A" => "\xC5\xA1", "\x9B" => "\xE2\x80\xBA", "\x9C" => "\xC5\x93", "\x9D" => "\xEF\xBF\xBD", "\x9E" => "\xC5\xBE", "\x9F" => "\xC5\xB8", "\xA0" => "\xC2\xA0", "\xA1" => "\xC2\xA1", "\xA2" => "\xC2\xA2", "\xA3" => "\xC2\xA3", "\xA4" => "\xC2\xA4", "\xA5" => "\xC2\xA5", "\xA6" => "\xC2\xA6", "\xA7" => "\xC2\xA7", "\xA8" => "\xC2\xA8", "\xA9" => "\xC2\xA9", "\xAA" => "\xC2\xAA", "\xAB" => "\xC2\xAB", "\xAC" => "\xC2\xAC", "\xAD" => "\xC2\xAD", "\xAE" => "\xC2\xAE", "\xAF" => "\xC2\xAF", "\xB0" => "\xC2\xB0", "\xB1" => "\xC2\xB1", "\xB2" => "\xC2\xB2", "\xB3" => "\xC2\xB3", "\xB4" => "\xC2\xB4", "\xB5" => "\xC2\xB5", "\xB6" => "\xC2\xB6", "\xB7" => "\xC2\xB7", "\xB8" => "\xC2\xB8", "\xB9" => "\xC2\xB9", "\xBA" => "\xC2\xBA", "\xBB" => "\xC2\xBB", "\xBC" => "\xC2\xBC", "\xBD" => "\xC2\xBD", "\xBE" => "\xC2\xBE", "\xBF" => "\xC2\xBF", "\xC0" => "\xC3\x80", "\xC1" => "\xC3\x81", "\xC2" => "\xC3\x82", "\xC3" => "\xC3\x83", "\xC4" => "\xC3\x84", "\xC5" => "\xC3\x85", "\xC6" => "\xC3\x86", "\xC7" => "\xC3\x87", "\xC8" => "\xC3\x88", "\xC9" => "\xC3\x89", "\xCA" => "\xC3\x8A", "\xCB" => "\xC3\x8B", "\xCC" => "\xC3\x8C", "\xCD" => "\xC3\x8D", "\xCE" => "\xC3\x8E", "\xCF" => "\xC3\x8F", "\xD0" => "\xC3\x90", "\xD1" => "\xC3\x91", "\xD2" => "\xC3\x92", "\xD3" => "\xC3\x93", "\xD4" => "\xC3\x94", "\xD5" => "\xC3\x95", "\xD6" => "\xC3\x96", "\xD7" => "\xC3\x97", "\xD8" => "\xC3\x98", "\xD9" => "\xC3\x99", "\xDA" => "\xC3\x9A", "\xDB" => "\xC3\x9B", "\xDC" => "\xC3\x9C", "\xDD" => "\xC3\x9D", "\xDE" => "\xC3\x9E", "\xDF" => "\xC3\x9F", "\xE0" => "\xC3\xA0", "\xE1" => "\xC3\xA1", "\xE2" => "\xC3\xA2", "\xE3" => "\xC3\xA3", "\xE4" => "\xC3\xA4", "\xE5" => "\xC3\xA5", "\xE6" => "\xC3\xA6", "\xE7" => "\xC3\xA7", "\xE8" => "\xC3\xA8", "\xE9" => "\xC3\xA9", "\xEA" => "\xC3\xAA", "\xEB" => "\xC3\xAB", "\xEC" => "\xC3\xAC", "\xED" => "\xC3\xAD", "\xEE" => "\xC3\xAE", "\xEF" => "\xC3\xAF", "\xF0" => "\xC3\xB0", "\xF1" => "\xC3\xB1", "\xF2" => "\xC3\xB2", "\xF3" => "\xC3\xB3", "\xF4" => "\xC3\xB4", "\xF5" => "\xC3\xB5", "\xF6" => "\xC3\xB6", "\xF7" => "\xC3\xB7", "\xF8" => "\xC3\xB8", "\xF9" => "\xC3\xB9", "\xFA" => "\xC3\xBA", "\xFB" => "\xC3\xBB", "\xFC" => "\xC3\xBC", "\xFD" => "\xC3\xBD", "\xFE" => "\xC3\xBE", "\xFF" => "\xC3\xBF");
12868
12869
		return strtr($string, $convert_table);
12870
	}
12871
12872
	/**
12873
	 * Change a string from one encoding to another
12874
	 *
12875
	 * @param string $data Raw data in $input encoding
12876
	 * @param string $input Encoding of $data
12877
	 * @param string $output Encoding you want
12878
	 * @return string|boolean False if we can't convert it
12879
	 */
12880
	public static function change_encoding($data, $input, $output)
12881
	{
12882
		$input = SimplePie_Misc::encoding($input);
12883
		$output = SimplePie_Misc::encoding($output);
12884
12885
		// We fail to fail on non US-ASCII bytes
12886
		if ($input === 'US-ASCII')
12887
		{
12888
			static $non_ascii_octects = '';
12889
			if (!$non_ascii_octects)
12890
			{
12891
				for ($i = 0x80; $i <= 0xFF; $i++)
12892
				{
12893
					$non_ascii_octects .= chr($i);
12894
				}
12895
			}
12896
			$data = substr($data, 0, strcspn($data, $non_ascii_octects));
12897
		}
12898
12899
		// This is first, as behaviour of this is completely predictable
12900
		if ($input === 'windows-1252' && $output === 'UTF-8')
12901
		{
12902
			return SimplePie_Misc::windows_1252_to_utf8($data);
12903
		}
12904
		// This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
12905
		elseif (function_exists('mb_convert_encoding') && ($return = SimplePie_Misc::change_encoding_mbstring($data, $input, $output)))
12906
		{
12907
			return $return;
12908
 		}
12909
		// This is third, as behaviour of this varies with OS userland and PHP version
12910
		elseif (function_exists('iconv') && ($return = SimplePie_Misc::change_encoding_iconv($data, $input, $output)))
12911
		{
12912
			return $return;
12913
		}
12914
		// This is last, as behaviour of this varies with OS userland and PHP version
12915
		elseif (class_exists('\UConverter') && ($return = SimplePie_Misc::change_encoding_uconverter($data, $input, $output)))
12916
		{
12917
			return $return;
12918
		}
12919
		// If we can't do anything, just fail
12920
		else
12921
		{
12922
			return false;
12923
		}
12924
	}
12925
12926
	protected static function change_encoding_mbstring($data, $input, $output)
12927
	{
12928
		if ($input === 'windows-949')
12929
		{
12930
			$input = 'EUC-KR';
12931
		}
12932
		if ($output === 'windows-949')
12933
		{
12934
			$output = 'EUC-KR';
12935
		}
12936
		if ($input === 'Windows-31J')
12937
		{
12938
			$input = 'SJIS';
12939
		}
12940
		if ($output === 'Windows-31J')
12941
		{
12942
			$output = 'SJIS';
12943
		}
12944
12945
		// Check that the encoding is supported
12946
		if (@mb_convert_encoding("\x80", 'UTF-16BE', $input) === "\x00\x80")
12947
		{
12948
			return false;
12949
		}
12950
		if (!in_array($input, mb_list_encodings()))
12951
		{
12952
			return false;
12953
		}
12954
12955
		// Let's do some conversion
12956
		if ($return = @mb_convert_encoding($data, $output, $input))
12957
		{
12958
			return $return;
12959
		}
12960
12961
		return false;
12962
	}
12963
12964
	protected static function change_encoding_iconv($data, $input, $output)
12965
	{
12966
		return @iconv($input, $output, $data);
12967
	}
12968
12969
	/**
12970
	 * @param string $data
12971
	 * @param string $input
12972
	 * @param string $output
12973
	 * @return string|false
12974
	 */
12975
	protected static function change_encoding_uconverter($data, $input, $output)
12976
	{
12977
		return @\UConverter::transcode($data, $output, $input);
12978
	}
12979
12980
	/**
12981
	 * Normalize an encoding name
12982
	 *
12983
	 * This is automatically generated by create.php
12984
	 *
12985
	 * To generate it, run `php create.php` on the command line, and copy the
12986
	 * output to replace this function.
12987
	 *
12988
	 * @param string $charset Character set to standardise
12989
	 * @return string Standardised name
12990
	 */
12991
	public static function encoding($charset)
12992
	{
12993
		// Normalization from UTS #22
12994
		switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
12995
		{
12996
			case 'adobestandardencoding':
12997
			case 'csadobestandardencoding':
12998
				return 'Adobe-Standard-Encoding';
12999
13000
			case 'adobesymbolencoding':
13001
			case 'cshppsmath':
13002
				return 'Adobe-Symbol-Encoding';
13003
13004
			case 'ami1251':
13005
			case 'amiga1251':
13006
				return 'Amiga-1251';
13007
13008
			case 'ansix31101983':
13009
			case 'csat5001983':
13010
			case 'csiso99naplps':
13011
			case 'isoir99':
13012
			case 'naplps':
13013
				return 'ANSI_X3.110-1983';
13014
13015
			case 'arabic7':
13016
			case 'asmo449':
13017
			case 'csiso89asmo449':
13018
			case 'iso9036':
13019
			case 'isoir89':
13020
				return 'ASMO_449';
13021
13022
			case 'big5':
13023
			case 'csbig5':
13024
				return 'Big5';
13025
13026
			case 'big5hkscs':
13027
				return 'Big5-HKSCS';
13028
13029
			case 'bocu1':
13030
			case 'csbocu1':
13031
				return 'BOCU-1';
13032
13033
			case 'brf':
13034
			case 'csbrf':
13035
				return 'BRF';
13036
13037
			case 'bs4730':
13038
			case 'csiso4unitedkingdom':
13039
			case 'gb':
13040
			case 'iso646gb':
13041
			case 'isoir4':
13042
			case 'uk':
13043
				return 'BS_4730';
13044
13045
			case 'bsviewdata':
13046
			case 'csiso47bsviewdata':
13047
			case 'isoir47':
13048
				return 'BS_viewdata';
13049
13050
			case 'cesu8':
13051
			case 'cscesu8':
13052
				return 'CESU-8';
13053
13054
			case 'ca':
13055
			case 'csa71':
13056
			case 'csaz243419851':
13057
			case 'csiso121canadian1':
13058
			case 'iso646ca':
13059
			case 'isoir121':
13060
				return 'CSA_Z243.4-1985-1';
13061
13062
			case 'csa72':
13063
			case 'csaz243419852':
13064
			case 'csiso122canadian2':
13065
			case 'iso646ca2':
13066
			case 'isoir122':
13067
				return 'CSA_Z243.4-1985-2';
13068
13069
			case 'csaz24341985gr':
13070
			case 'csiso123csaz24341985gr':
13071
			case 'isoir123':
13072
				return 'CSA_Z243.4-1985-gr';
13073
13074
			case 'csiso139csn369103':
13075
			case 'csn369103':
13076
			case 'isoir139':
13077
				return 'CSN_369103';
13078
13079
			case 'csdecmcs':
13080
			case 'dec':
13081
			case 'decmcs':
13082
				return 'DEC-MCS';
13083
13084
			case 'csiso21german':
13085
			case 'de':
13086
			case 'din66003':
13087
			case 'iso646de':
13088
			case 'isoir21':
13089
				return 'DIN_66003';
13090
13091
			case 'csdkus':
13092
			case 'dkus':
13093
				return 'dk-us';
13094
13095
			case 'csiso646danish':
13096
			case 'dk':
13097
			case 'ds2089':
13098
			case 'iso646dk':
13099
				return 'DS_2089';
13100
13101
			case 'csibmebcdicatde':
13102
			case 'ebcdicatde':
13103
				return 'EBCDIC-AT-DE';
13104
13105
			case 'csebcdicatdea':
13106
			case 'ebcdicatdea':
13107
				return 'EBCDIC-AT-DE-A';
13108
13109
			case 'csebcdiccafr':
13110
			case 'ebcdiccafr':
13111
				return 'EBCDIC-CA-FR';
13112
13113
			case 'csebcdicdkno':
13114
			case 'ebcdicdkno':
13115
				return 'EBCDIC-DK-NO';
13116
13117
			case 'csebcdicdknoa':
13118
			case 'ebcdicdknoa':
13119
				return 'EBCDIC-DK-NO-A';
13120
13121
			case 'csebcdices':
13122
			case 'ebcdices':
13123
				return 'EBCDIC-ES';
13124
13125
			case 'csebcdicesa':
13126
			case 'ebcdicesa':
13127
				return 'EBCDIC-ES-A';
13128
13129
			case 'csebcdicess':
13130
			case 'ebcdicess':
13131
				return 'EBCDIC-ES-S';
13132
13133
			case 'csebcdicfise':
13134
			case 'ebcdicfise':
13135
				return 'EBCDIC-FI-SE';
13136
13137
			case 'csebcdicfisea':
13138
			case 'ebcdicfisea':
13139
				return 'EBCDIC-FI-SE-A';
13140
13141
			case 'csebcdicfr':
13142
			case 'ebcdicfr':
13143
				return 'EBCDIC-FR';
13144
13145
			case 'csebcdicit':
13146
			case 'ebcdicit':
13147
				return 'EBCDIC-IT';
13148
13149
			case 'csebcdicpt':
13150
			case 'ebcdicpt':
13151
				return 'EBCDIC-PT';
13152
13153
			case 'csebcdicuk':
13154
			case 'ebcdicuk':
13155
				return 'EBCDIC-UK';
13156
13157
			case 'csebcdicus':
13158
			case 'ebcdicus':
13159
				return 'EBCDIC-US';
13160
13161
			case 'csiso111ecmacyrillic':
13162
			case 'ecmacyrillic':
13163
			case 'isoir111':
13164
			case 'koi8e':
13165
				return 'ECMA-cyrillic';
13166
13167
			case 'csiso17spanish':
13168
			case 'es':
13169
			case 'iso646es':
13170
			case 'isoir17':
13171
				return 'ES';
13172
13173
			case 'csiso85spanish2':
13174
			case 'es2':
13175
			case 'iso646es2':
13176
			case 'isoir85':
13177
				return 'ES2';
13178
13179
			case 'cseucpkdfmtjapanese':
13180
			case 'eucjp':
13181
			case 'extendedunixcodepackedformatforjapanese':
13182
				return 'EUC-JP';
13183
13184
			case 'cseucfixwidjapanese':
13185
			case 'extendedunixcodefixedwidthforjapanese':
13186
				return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
13187
13188
			case 'gb18030':
13189
				return 'GB18030';
13190
13191
			case 'chinese':
13192
			case 'cp936':
13193
			case 'csgb2312':
13194
			case 'csiso58gb231280':
13195
			case 'gb2312':
13196
			case 'gb231280':
13197
			case 'gbk':
13198
			case 'isoir58':
13199
			case 'ms936':
13200
			case 'windows936':
13201
				return 'GBK';
13202
13203
			case 'cn':
13204
			case 'csiso57gb1988':
13205
			case 'gb198880':
13206
			case 'iso646cn':
13207
			case 'isoir57':
13208
				return 'GB_1988-80';
13209
13210
			case 'csiso153gost1976874':
13211
			case 'gost1976874':
13212
			case 'isoir153':
13213
			case 'stsev35888':
13214
				return 'GOST_19768-74';
13215
13216
			case 'csiso150':
13217
			case 'csiso150greekccitt':
13218
			case 'greekccitt':
13219
			case 'isoir150':
13220
				return 'greek-ccitt';
13221
13222
			case 'csiso88greek7':
13223
			case 'greek7':
13224
			case 'isoir88':
13225
				return 'greek7';
13226
13227
			case 'csiso18greek7old':
13228
			case 'greek7old':
13229
			case 'isoir18':
13230
				return 'greek7-old';
13231
13232
			case 'cshpdesktop':
13233
			case 'hpdesktop':
13234
				return 'HP-DeskTop';
13235
13236
			case 'cshplegal':
13237
			case 'hplegal':
13238
				return 'HP-Legal';
13239
13240
			case 'cshpmath8':
13241
			case 'hpmath8':
13242
				return 'HP-Math8';
13243
13244
			case 'cshppifont':
13245
			case 'hppifont':
13246
				return 'HP-Pi-font';
13247
13248
			case 'cshproman8':
13249
			case 'hproman8':
13250
			case 'r8':
13251
			case 'roman8':
13252
				return 'hp-roman8';
13253
13254
			case 'hzgb2312':
13255
				return 'HZ-GB-2312';
13256
13257
			case 'csibmsymbols':
13258
			case 'ibmsymbols':
13259
				return 'IBM-Symbols';
13260
13261
			case 'csibmthai':
13262
			case 'ibmthai':
13263
				return 'IBM-Thai';
13264
13265
			case 'cp37':
13266
			case 'csibm37':
13267
			case 'ebcdiccpca':
13268
			case 'ebcdiccpnl':
13269
			case 'ebcdiccpus':
13270
			case 'ebcdiccpwt':
13271
			case 'ibm37':
13272
				return 'IBM037';
13273
13274
			case 'cp38':
13275
			case 'csibm38':
13276
			case 'ebcdicint':
13277
			case 'ibm38':
13278
				return 'IBM038';
13279
13280
			case 'cp273':
13281
			case 'csibm273':
13282
			case 'ibm273':
13283
				return 'IBM273';
13284
13285
			case 'cp274':
13286
			case 'csibm274':
13287
			case 'ebcdicbe':
13288
			case 'ibm274':
13289
				return 'IBM274';
13290
13291
			case 'cp275':
13292
			case 'csibm275':
13293
			case 'ebcdicbr':
13294
			case 'ibm275':
13295
				return 'IBM275';
13296
13297
			case 'csibm277':
13298
			case 'ebcdiccpdk':
13299
			case 'ebcdiccpno':
13300
			case 'ibm277':
13301
				return 'IBM277';
13302
13303
			case 'cp278':
13304
			case 'csibm278':
13305
			case 'ebcdiccpfi':
13306
			case 'ebcdiccpse':
13307
			case 'ibm278':
13308
				return 'IBM278';
13309
13310
			case 'cp280':
13311
			case 'csibm280':
13312
			case 'ebcdiccpit':
13313
			case 'ibm280':
13314
				return 'IBM280';
13315
13316
			case 'cp281':
13317
			case 'csibm281':
13318
			case 'ebcdicjpe':
13319
			case 'ibm281':
13320
				return 'IBM281';
13321
13322
			case 'cp284':
13323
			case 'csibm284':
13324
			case 'ebcdiccpes':
13325
			case 'ibm284':
13326
				return 'IBM284';
13327
13328
			case 'cp285':
13329
			case 'csibm285':
13330
			case 'ebcdiccpgb':
13331
			case 'ibm285':
13332
				return 'IBM285';
13333
13334
			case 'cp290':
13335
			case 'csibm290':
13336
			case 'ebcdicjpkana':
13337
			case 'ibm290':
13338
				return 'IBM290';
13339
13340
			case 'cp297':
13341
			case 'csibm297':
13342
			case 'ebcdiccpfr':
13343
			case 'ibm297':
13344
				return 'IBM297';
13345
13346
			case 'cp420':
13347
			case 'csibm420':
13348
			case 'ebcdiccpar1':
13349
			case 'ibm420':
13350
				return 'IBM420';
13351
13352
			case 'cp423':
13353
			case 'csibm423':
13354
			case 'ebcdiccpgr':
13355
			case 'ibm423':
13356
				return 'IBM423';
13357
13358
			case 'cp424':
13359
			case 'csibm424':
13360
			case 'ebcdiccphe':
13361
			case 'ibm424':
13362
				return 'IBM424';
13363
13364
			case '437':
13365
			case 'cp437':
13366
			case 'cspc8codepage437':
13367
			case 'ibm437':
13368
				return 'IBM437';
13369
13370
			case 'cp500':
13371
			case 'csibm500':
13372
			case 'ebcdiccpbe':
13373
			case 'ebcdiccpch':
13374
			case 'ibm500':
13375
				return 'IBM500';
13376
13377
			case 'cp775':
13378
			case 'cspc775baltic':
13379
			case 'ibm775':
13380
				return 'IBM775';
13381
13382
			case '850':
13383
			case 'cp850':
13384
			case 'cspc850multilingual':
13385
			case 'ibm850':
13386
				return 'IBM850';
13387
13388
			case '851':
13389
			case 'cp851':
13390
			case 'csibm851':
13391
			case 'ibm851':
13392
				return 'IBM851';
13393
13394
			case '852':
13395
			case 'cp852':
13396
			case 'cspcp852':
13397
			case 'ibm852':
13398
				return 'IBM852';
13399
13400
			case '855':
13401
			case 'cp855':
13402
			case 'csibm855':
13403
			case 'ibm855':
13404
				return 'IBM855';
13405
13406
			case '857':
13407
			case 'cp857':
13408
			case 'csibm857':
13409
			case 'ibm857':
13410
				return 'IBM857';
13411
13412
			case 'ccsid858':
13413
			case 'cp858':
13414
			case 'ibm858':
13415
			case 'pcmultilingual850euro':
13416
				return 'IBM00858';
13417
13418
			case '860':
13419
			case 'cp860':
13420
			case 'csibm860':
13421
			case 'ibm860':
13422
				return 'IBM860';
13423
13424
			case '861':
13425
			case 'cp861':
13426
			case 'cpis':
13427
			case 'csibm861':
13428
			case 'ibm861':
13429
				return 'IBM861';
13430
13431
			case '862':
13432
			case 'cp862':
13433
			case 'cspc862latinhebrew':
13434
			case 'ibm862':
13435
				return 'IBM862';
13436
13437
			case '863':
13438
			case 'cp863':
13439
			case 'csibm863':
13440
			case 'ibm863':
13441
				return 'IBM863';
13442
13443
			case 'cp864':
13444
			case 'csibm864':
13445
			case 'ibm864':
13446
				return 'IBM864';
13447
13448
			case '865':
13449
			case 'cp865':
13450
			case 'csibm865':
13451
			case 'ibm865':
13452
				return 'IBM865';
13453
13454
			case '866':
13455
			case 'cp866':
13456
			case 'csibm866':
13457
			case 'ibm866':
13458
				return 'IBM866';
13459
13460
			case 'cp868':
13461
			case 'cpar':
13462
			case 'csibm868':
13463
			case 'ibm868':
13464
				return 'IBM868';
13465
13466
			case '869':
13467
			case 'cp869':
13468
			case 'cpgr':
13469
			case 'csibm869':
13470
			case 'ibm869':
13471
				return 'IBM869';
13472
13473
			case 'cp870':
13474
			case 'csibm870':
13475
			case 'ebcdiccproece':
13476
			case 'ebcdiccpyu':
13477
			case 'ibm870':
13478
				return 'IBM870';
13479
13480
			case 'cp871':
13481
			case 'csibm871':
13482
			case 'ebcdiccpis':
13483
			case 'ibm871':
13484
				return 'IBM871';
13485
13486
			case 'cp880':
13487
			case 'csibm880':
13488
			case 'ebcdiccyrillic':
13489
			case 'ibm880':
13490
				return 'IBM880';
13491
13492
			case 'cp891':
13493
			case 'csibm891':
13494
			case 'ibm891':
13495
				return 'IBM891';
13496
13497
			case 'cp903':
13498
			case 'csibm903':
13499
			case 'ibm903':
13500
				return 'IBM903';
13501
13502
			case '904':
13503
			case 'cp904':
13504
			case 'csibbm904':
13505
			case 'ibm904':
13506
				return 'IBM904';
13507
13508
			case 'cp905':
13509
			case 'csibm905':
13510
			case 'ebcdiccptr':
13511
			case 'ibm905':
13512
				return 'IBM905';
13513
13514
			case 'cp918':
13515
			case 'csibm918':
13516
			case 'ebcdiccpar2':
13517
			case 'ibm918':
13518
				return 'IBM918';
13519
13520
			case 'ccsid924':
13521
			case 'cp924':
13522
			case 'ebcdiclatin9euro':
13523
			case 'ibm924':
13524
				return 'IBM00924';
13525
13526
			case 'cp1026':
13527
			case 'csibm1026':
13528
			case 'ibm1026':
13529
				return 'IBM1026';
13530
13531
			case 'ibm1047':
13532
				return 'IBM1047';
13533
13534
			case 'ccsid1140':
13535
			case 'cp1140':
13536
			case 'ebcdicus37euro':
13537
			case 'ibm1140':
13538
				return 'IBM01140';
13539
13540
			case 'ccsid1141':
13541
			case 'cp1141':
13542
			case 'ebcdicde273euro':
13543
			case 'ibm1141':
13544
				return 'IBM01141';
13545
13546
			case 'ccsid1142':
13547
			case 'cp1142':
13548
			case 'ebcdicdk277euro':
13549
			case 'ebcdicno277euro':
13550
			case 'ibm1142':
13551
				return 'IBM01142';
13552
13553
			case 'ccsid1143':
13554
			case 'cp1143':
13555
			case 'ebcdicfi278euro':
13556
			case 'ebcdicse278euro':
13557
			case 'ibm1143':
13558
				return 'IBM01143';
13559
13560
			case 'ccsid1144':
13561
			case 'cp1144':
13562
			case 'ebcdicit280euro':
13563
			case 'ibm1144':
13564
				return 'IBM01144';
13565
13566
			case 'ccsid1145':
13567
			case 'cp1145':
13568
			case 'ebcdices284euro':
13569
			case 'ibm1145':
13570
				return 'IBM01145';
13571
13572
			case 'ccsid1146':
13573
			case 'cp1146':
13574
			case 'ebcdicgb285euro':
13575
			case 'ibm1146':
13576
				return 'IBM01146';
13577
13578
			case 'ccsid1147':
13579
			case 'cp1147':
13580
			case 'ebcdicfr297euro':
13581
			case 'ibm1147':
13582
				return 'IBM01147';
13583
13584
			case 'ccsid1148':
13585
			case 'cp1148':
13586
			case 'ebcdicinternational500euro':
13587
			case 'ibm1148':
13588
				return 'IBM01148';
13589
13590
			case 'ccsid1149':
13591
			case 'cp1149':
13592
			case 'ebcdicis871euro':
13593
			case 'ibm1149':
13594
				return 'IBM01149';
13595
13596
			case 'csiso143iecp271':
13597
			case 'iecp271':
13598
			case 'isoir143':
13599
				return 'IEC_P27-1';
13600
13601
			case 'csiso49inis':
13602
			case 'inis':
13603
			case 'isoir49':
13604
				return 'INIS';
13605
13606
			case 'csiso50inis8':
13607
			case 'inis8':
13608
			case 'isoir50':
13609
				return 'INIS-8';
13610
13611
			case 'csiso51iniscyrillic':
13612
			case 'iniscyrillic':
13613
			case 'isoir51':
13614
				return 'INIS-cyrillic';
13615
13616
			case 'csinvariant':
13617
			case 'invariant':
13618
				return 'INVARIANT';
13619
13620
			case 'iso2022cn':
13621
				return 'ISO-2022-CN';
13622
13623
			case 'iso2022cnext':
13624
				return 'ISO-2022-CN-EXT';
13625
13626
			case 'csiso2022jp':
13627
			case 'iso2022jp':
13628
				return 'ISO-2022-JP';
13629
13630
			case 'csiso2022jp2':
13631
			case 'iso2022jp2':
13632
				return 'ISO-2022-JP-2';
13633
13634
			case 'csiso2022kr':
13635
			case 'iso2022kr':
13636
				return 'ISO-2022-KR';
13637
13638
			case 'cswindows30latin1':
13639
			case 'iso88591windows30latin1':
13640
				return 'ISO-8859-1-Windows-3.0-Latin-1';
13641
13642
			case 'cswindows31latin1':
13643
			case 'iso88591windows31latin1':
13644
				return 'ISO-8859-1-Windows-3.1-Latin-1';
13645
13646
			case 'csisolatin2':
13647
			case 'iso88592':
13648
			case 'iso885921987':
13649
			case 'isoir101':
13650
			case 'l2':
13651
			case 'latin2':
13652
				return 'ISO-8859-2';
13653
13654
			case 'cswindows31latin2':
13655
			case 'iso88592windowslatin2':
13656
				return 'ISO-8859-2-Windows-Latin-2';
13657
13658
			case 'csisolatin3':
13659
			case 'iso88593':
13660
			case 'iso885931988':
13661
			case 'isoir109':
13662
			case 'l3':
13663
			case 'latin3':
13664
				return 'ISO-8859-3';
13665
13666
			case 'csisolatin4':
13667
			case 'iso88594':
13668
			case 'iso885941988':
13669
			case 'isoir110':
13670
			case 'l4':
13671
			case 'latin4':
13672
				return 'ISO-8859-4';
13673
13674
			case 'csisolatincyrillic':
13675
			case 'cyrillic':
13676
			case 'iso88595':
13677
			case 'iso885951988':
13678
			case 'isoir144':
13679
				return 'ISO-8859-5';
13680
13681
			case 'arabic':
13682
			case 'asmo708':
13683
			case 'csisolatinarabic':
13684
			case 'ecma114':
13685
			case 'iso88596':
13686
			case 'iso885961987':
13687
			case 'isoir127':
13688
				return 'ISO-8859-6';
13689
13690
			case 'csiso88596e':
13691
			case 'iso88596e':
13692
				return 'ISO-8859-6-E';
13693
13694
			case 'csiso88596i':
13695
			case 'iso88596i':
13696
				return 'ISO-8859-6-I';
13697
13698
			case 'csisolatingreek':
13699
			case 'ecma118':
13700
			case 'elot928':
13701
			case 'greek':
13702
			case 'greek8':
13703
			case 'iso88597':
13704
			case 'iso885971987':
13705
			case 'isoir126':
13706
				return 'ISO-8859-7';
13707
13708
			case 'csisolatinhebrew':
13709
			case 'hebrew':
13710
			case 'iso88598':
13711
			case 'iso885981988':
13712
			case 'isoir138':
13713
				return 'ISO-8859-8';
13714
13715
			case 'csiso88598e':
13716
			case 'iso88598e':
13717
				return 'ISO-8859-8-E';
13718
13719
			case 'csiso88598i':
13720
			case 'iso88598i':
13721
				return 'ISO-8859-8-I';
13722
13723
			case 'cswindows31latin5':
13724
			case 'iso88599windowslatin5':
13725
				return 'ISO-8859-9-Windows-Latin-5';
13726
13727
			case 'csisolatin6':
13728
			case 'iso885910':
13729
			case 'iso8859101992':
13730
			case 'isoir157':
13731
			case 'l6':
13732
			case 'latin6':
13733
				return 'ISO-8859-10';
13734
13735
			case 'iso885913':
13736
				return 'ISO-8859-13';
13737
13738
			case 'iso885914':
13739
			case 'iso8859141998':
13740
			case 'isoceltic':
13741
			case 'isoir199':
13742
			case 'l8':
13743
			case 'latin8':
13744
				return 'ISO-8859-14';
13745
13746
			case 'iso885915':
13747
			case 'latin9':
13748
				return 'ISO-8859-15';
13749
13750
			case 'iso885916':
13751
			case 'iso8859162001':
13752
			case 'isoir226':
13753
			case 'l10':
13754
			case 'latin10':
13755
				return 'ISO-8859-16';
13756
13757
			case 'iso10646j1':
13758
				return 'ISO-10646-J-1';
13759
13760
			case 'csunicode':
13761
			case 'iso10646ucs2':
13762
				return 'ISO-10646-UCS-2';
13763
13764
			case 'csucs4':
13765
			case 'iso10646ucs4':
13766
				return 'ISO-10646-UCS-4';
13767
13768
			case 'csunicodeascii':
13769
			case 'iso10646ucsbasic':
13770
				return 'ISO-10646-UCS-Basic';
13771
13772
			case 'csunicodelatin1':
13773
			case 'iso10646':
13774
			case 'iso10646unicodelatin1':
13775
				return 'ISO-10646-Unicode-Latin1';
13776
13777
			case 'csiso10646utf1':
13778
			case 'iso10646utf1':
13779
				return 'ISO-10646-UTF-1';
13780
13781
			case 'csiso115481':
13782
			case 'iso115481':
13783
			case 'isotr115481':
13784
				return 'ISO-11548-1';
13785
13786
			case 'csiso90':
13787
			case 'isoir90':
13788
				return 'iso-ir-90';
13789
13790
			case 'csunicodeibm1261':
13791
			case 'isounicodeibm1261':
13792
				return 'ISO-Unicode-IBM-1261';
13793
13794
			case 'csunicodeibm1264':
13795
			case 'isounicodeibm1264':
13796
				return 'ISO-Unicode-IBM-1264';
13797
13798
			case 'csunicodeibm1265':
13799
			case 'isounicodeibm1265':
13800
				return 'ISO-Unicode-IBM-1265';
13801
13802
			case 'csunicodeibm1268':
13803
			case 'isounicodeibm1268':
13804
				return 'ISO-Unicode-IBM-1268';
13805
13806
			case 'csunicodeibm1276':
13807
			case 'isounicodeibm1276':
13808
				return 'ISO-Unicode-IBM-1276';
13809
13810
			case 'csiso646basic1983':
13811
			case 'iso646basic1983':
13812
			case 'ref':
13813
				return 'ISO_646.basic:1983';
13814
13815
			case 'csiso2intlrefversion':
13816
			case 'irv':
13817
			case 'iso646irv1983':
13818
			case 'isoir2':
13819
				return 'ISO_646.irv:1983';
13820
13821
			case 'csiso2033':
13822
			case 'e13b':
13823
			case 'iso20331983':
13824
			case 'isoir98':
13825
				return 'ISO_2033-1983';
13826
13827
			case 'csiso5427cyrillic':
13828
			case 'iso5427':
13829
			case 'isoir37':
13830
				return 'ISO_5427';
13831
13832
			case 'iso5427cyrillic1981':
13833
			case 'iso54271981':
13834
			case 'isoir54':
13835
				return 'ISO_5427:1981';
13836
13837
			case 'csiso5428greek':
13838
			case 'iso54281980':
13839
			case 'isoir55':
13840
				return 'ISO_5428:1980';
13841
13842
			case 'csiso6937add':
13843
			case 'iso6937225':
13844
			case 'isoir152':
13845
				return 'ISO_6937-2-25';
13846
13847
			case 'csisotextcomm':
13848
			case 'iso69372add':
13849
			case 'isoir142':
13850
				return 'ISO_6937-2-add';
13851
13852
			case 'csiso8859supp':
13853
			case 'iso8859supp':
13854
			case 'isoir154':
13855
			case 'latin125':
13856
				return 'ISO_8859-supp';
13857
13858
			case 'csiso10367box':
13859
			case 'iso10367box':
13860
			case 'isoir155':
13861
				return 'ISO_10367-box';
13862
13863
			case 'csiso15italian':
13864
			case 'iso646it':
13865
			case 'isoir15':
13866
			case 'it':
13867
				return 'IT';
13868
13869
			case 'csiso13jisc6220jp':
13870
			case 'isoir13':
13871
			case 'jisc62201969':
13872
			case 'jisc62201969jp':
13873
			case 'katakana':
13874
			case 'x2017':
13875
				return 'JIS_C6220-1969-jp';
13876
13877
			case 'csiso14jisc6220ro':
13878
			case 'iso646jp':
13879
			case 'isoir14':
13880
			case 'jisc62201969ro':
13881
			case 'jp':
13882
				return 'JIS_C6220-1969-ro';
13883
13884
			case 'csiso42jisc62261978':
13885
			case 'isoir42':
13886
			case 'jisc62261978':
13887
				return 'JIS_C6226-1978';
13888
13889
			case 'csiso87jisx208':
13890
			case 'isoir87':
13891
			case 'jisc62261983':
13892
			case 'jisx2081983':
13893
			case 'x208':
13894
				return 'JIS_C6226-1983';
13895
13896
			case 'csiso91jisc62291984a':
13897
			case 'isoir91':
13898
			case 'jisc62291984a':
13899
			case 'jpocra':
13900
				return 'JIS_C6229-1984-a';
13901
13902
			case 'csiso92jisc62991984b':
13903
			case 'iso646jpocrb':
13904
			case 'isoir92':
13905
			case 'jisc62291984b':
13906
			case 'jpocrb':
13907
				return 'JIS_C6229-1984-b';
13908
13909
			case 'csiso93jis62291984badd':
13910
			case 'isoir93':
13911
			case 'jisc62291984badd':
13912
			case 'jpocrbadd':
13913
				return 'JIS_C6229-1984-b-add';
13914
13915
			case 'csiso94jis62291984hand':
13916
			case 'isoir94':
13917
			case 'jisc62291984hand':
13918
			case 'jpocrhand':
13919
				return 'JIS_C6229-1984-hand';
13920
13921
			case 'csiso95jis62291984handadd':
13922
			case 'isoir95':
13923
			case 'jisc62291984handadd':
13924
			case 'jpocrhandadd':
13925
				return 'JIS_C6229-1984-hand-add';
13926
13927
			case 'csiso96jisc62291984kana':
13928
			case 'isoir96':
13929
			case 'jisc62291984kana':
13930
				return 'JIS_C6229-1984-kana';
13931
13932
			case 'csjisencoding':
13933
			case 'jisencoding':
13934
				return 'JIS_Encoding';
13935
13936
			case 'cshalfwidthkatakana':
13937
			case 'jisx201':
13938
			case 'x201':
13939
				return 'JIS_X0201';
13940
13941
			case 'csiso159jisx2121990':
13942
			case 'isoir159':
13943
			case 'jisx2121990':
13944
			case 'x212':
13945
				return 'JIS_X0212-1990';
13946
13947
			case 'csiso141jusib1002':
13948
			case 'iso646yu':
13949
			case 'isoir141':
13950
			case 'js':
13951
			case 'jusib1002':
13952
			case 'yu':
13953
				return 'JUS_I.B1.002';
13954
13955
			case 'csiso147macedonian':
13956
			case 'isoir147':
13957
			case 'jusib1003mac':
13958
			case 'macedonian':
13959
				return 'JUS_I.B1.003-mac';
13960
13961
			case 'csiso146serbian':
13962
			case 'isoir146':
13963
			case 'jusib1003serb':
13964
			case 'serbian':
13965
				return 'JUS_I.B1.003-serb';
13966
13967
			case 'koi7switched':
13968
				return 'KOI7-switched';
13969
13970
			case 'cskoi8r':
13971
			case 'koi8r':
13972
				return 'KOI8-R';
13973
13974
			case 'koi8u':
13975
				return 'KOI8-U';
13976
13977
			case 'csksc5636':
13978
			case 'iso646kr':
13979
			case 'ksc5636':
13980
				return 'KSC5636';
13981
13982
			case 'cskz1048':
13983
			case 'kz1048':
13984
			case 'rk1048':
13985
			case 'strk10482002':
13986
				return 'KZ-1048';
13987
13988
			case 'csiso19latingreek':
13989
			case 'isoir19':
13990
			case 'latingreek':
13991
				return 'latin-greek';
13992
13993
			case 'csiso27latingreek1':
13994
			case 'isoir27':
13995
			case 'latingreek1':
13996
				return 'Latin-greek-1';
13997
13998
			case 'csiso158lap':
13999
			case 'isoir158':
14000
			case 'lap':
14001
			case 'latinlap':
14002
				return 'latin-lap';
14003
14004
			case 'csmacintosh':
14005
			case 'mac':
14006
			case 'macintosh':
14007
				return 'macintosh';
14008
14009
			case 'csmicrosoftpublishing':
14010
			case 'microsoftpublishing':
14011
				return 'Microsoft-Publishing';
14012
14013
			case 'csmnem':
14014
			case 'mnem':
14015
				return 'MNEM';
14016
14017
			case 'csmnemonic':
14018
			case 'mnemonic':
14019
				return 'MNEMONIC';
14020
14021
			case 'csiso86hungarian':
14022
			case 'hu':
14023
			case 'iso646hu':
14024
			case 'isoir86':
14025
			case 'msz77953':
14026
				return 'MSZ_7795.3';
14027
14028
			case 'csnatsdano':
14029
			case 'isoir91':
14030
			case 'natsdano':
14031
				return 'NATS-DANO';
14032
14033
			case 'csnatsdanoadd':
14034
			case 'isoir92':
14035
			case 'natsdanoadd':
14036
				return 'NATS-DANO-ADD';
14037
14038
			case 'csnatssefi':
14039
			case 'isoir81':
14040
			case 'natssefi':
14041
				return 'NATS-SEFI';
14042
14043
			case 'csnatssefiadd':
14044
			case 'isoir82':
14045
			case 'natssefiadd':
14046
				return 'NATS-SEFI-ADD';
14047
14048
			case 'csiso151cuba':
14049
			case 'cuba':
14050
			case 'iso646cu':
14051
			case 'isoir151':
14052
			case 'ncnc1081':
14053
				return 'NC_NC00-10:81';
14054
14055
			case 'csiso69french':
14056
			case 'fr':
14057
			case 'iso646fr':
14058
			case 'isoir69':
14059
			case 'nfz62010':
14060
				return 'NF_Z_62-010';
14061
14062
			case 'csiso25french':
14063
			case 'iso646fr1':
14064
			case 'isoir25':
14065
			case 'nfz620101973':
14066
				return 'NF_Z_62-010_(1973)';
14067
14068
			case 'csiso60danishnorwegian':
14069
			case 'csiso60norwegian1':
14070
			case 'iso646no':
14071
			case 'isoir60':
14072
			case 'no':
14073
			case 'ns45511':
14074
				return 'NS_4551-1';
14075
14076
			case 'csiso61norwegian2':
14077
			case 'iso646no2':
14078
			case 'isoir61':
14079
			case 'no2':
14080
			case 'ns45512':
14081
				return 'NS_4551-2';
14082
14083
			case 'osdebcdicdf3irv':
14084
				return 'OSD_EBCDIC_DF03_IRV';
14085
14086
			case 'osdebcdicdf41':
14087
				return 'OSD_EBCDIC_DF04_1';
14088
14089
			case 'osdebcdicdf415':
14090
				return 'OSD_EBCDIC_DF04_15';
14091
14092
			case 'cspc8danishnorwegian':
14093
			case 'pc8danishnorwegian':
14094
				return 'PC8-Danish-Norwegian';
14095
14096
			case 'cspc8turkish':
14097
			case 'pc8turkish':
14098
				return 'PC8-Turkish';
14099
14100
			case 'csiso16portuguese':
14101
			case 'iso646pt':
14102
			case 'isoir16':
14103
			case 'pt':
14104
				return 'PT';
14105
14106
			case 'csiso84portuguese2':
14107
			case 'iso646pt2':
14108
			case 'isoir84':
14109
			case 'pt2':
14110
				return 'PT2';
14111
14112
			case 'cp154':
14113
			case 'csptcp154':
14114
			case 'cyrillicasian':
14115
			case 'pt154':
14116
			case 'ptcp154':
14117
				return 'PTCP154';
14118
14119
			case 'scsu':
14120
				return 'SCSU';
14121
14122
			case 'csiso10swedish':
14123
			case 'fi':
14124
			case 'iso646fi':
14125
			case 'iso646se':
14126
			case 'isoir10':
14127
			case 'se':
14128
			case 'sen850200b':
14129
				return 'SEN_850200_B';
14130
14131
			case 'csiso11swedishfornames':
14132
			case 'iso646se2':
14133
			case 'isoir11':
14134
			case 'se2':
14135
			case 'sen850200c':
14136
				return 'SEN_850200_C';
14137
14138
			case 'csiso102t617bit':
14139
			case 'isoir102':
14140
			case 't617bit':
14141
				return 'T.61-7bit';
14142
14143
			case 'csiso103t618bit':
14144
			case 'isoir103':
14145
			case 't61':
14146
			case 't618bit':
14147
				return 'T.61-8bit';
14148
14149
			case 'csiso128t101g2':
14150
			case 'isoir128':
14151
			case 't101g2':
14152
				return 'T.101-G2';
14153
14154
			case 'cstscii':
14155
			case 'tscii':
14156
				return 'TSCII';
14157
14158
			case 'csunicode11':
14159
			case 'unicode11':
14160
				return 'UNICODE-1-1';
14161
14162
			case 'csunicode11utf7':
14163
			case 'unicode11utf7':
14164
				return 'UNICODE-1-1-UTF-7';
14165
14166
			case 'csunknown8bit':
14167
			case 'unknown8bit':
14168
				return 'UNKNOWN-8BIT';
14169
14170
			case 'ansix341968':
14171
			case 'ansix341986':
14172
			case 'ascii':
14173
			case 'cp367':
14174
			case 'csascii':
14175
			case 'ibm367':
14176
			case 'iso646irv1991':
14177
			case 'iso646us':
14178
			case 'isoir6':
14179
			case 'us':
14180
			case 'usascii':
14181
				return 'US-ASCII';
14182
14183
			case 'csusdk':
14184
			case 'usdk':
14185
				return 'us-dk';
14186
14187
			case 'utf7':
14188
				return 'UTF-7';
14189
14190
			case 'utf8':
14191
				return 'UTF-8';
14192
14193
			case 'utf16':
14194
				return 'UTF-16';
14195
14196
			case 'utf16be':
14197
				return 'UTF-16BE';
14198
14199
			case 'utf16le':
14200
				return 'UTF-16LE';
14201
14202
			case 'utf32':
14203
				return 'UTF-32';
14204
14205
			case 'utf32be':
14206
				return 'UTF-32BE';
14207
14208
			case 'utf32le':
14209
				return 'UTF-32LE';
14210
14211
			case 'csventurainternational':
14212
			case 'venturainternational':
14213
				return 'Ventura-International';
14214
14215
			case 'csventuramath':
14216
			case 'venturamath':
14217
				return 'Ventura-Math';
14218
14219
			case 'csventuraus':
14220
			case 'venturaus':
14221
				return 'Ventura-US';
14222
14223
			case 'csiso70videotexsupp1':
14224
			case 'isoir70':
14225
			case 'videotexsuppl':
14226
				return 'videotex-suppl';
14227
14228
			case 'csviqr':
14229
			case 'viqr':
14230
				return 'VIQR';
14231
14232
			case 'csviscii':
14233
			case 'viscii':
14234
				return 'VISCII';
14235
14236
			case 'csshiftjis':
14237
			case 'cswindows31j':
14238
			case 'mskanji':
14239
			case 'shiftjis':
14240
			case 'windows31j':
14241
				return 'Windows-31J';
14242
14243
			case 'iso885911':
14244
			case 'tis620':
14245
				return 'windows-874';
14246
14247
			case 'cseuckr':
14248
			case 'csksc56011987':
14249
			case 'euckr':
14250
			case 'isoir149':
14251
			case 'korean':
14252
			case 'ksc5601':
14253
			case 'ksc56011987':
14254
			case 'ksc56011989':
14255
			case 'windows949':
14256
				return 'windows-949';
14257
14258
			case 'windows1250':
14259
				return 'windows-1250';
14260
14261
			case 'windows1251':
14262
				return 'windows-1251';
14263
14264
			case 'cp819':
14265
			case 'csisolatin1':
14266
			case 'ibm819':
14267
			case 'iso88591':
14268
			case 'iso885911987':
14269
			case 'isoir100':
14270
			case 'l1':
14271
			case 'latin1':
14272
			case 'windows1252':
14273
				return 'windows-1252';
14274
14275
			case 'windows1253':
14276
				return 'windows-1253';
14277
14278
			case 'csisolatin5':
14279
			case 'iso88599':
14280
			case 'iso885991989':
14281
			case 'isoir148':
14282
			case 'l5':
14283
			case 'latin5':
14284
			case 'windows1254':
14285
				return 'windows-1254';
14286
14287
			case 'windows1255':
14288
				return 'windows-1255';
14289
14290
			case 'windows1256':
14291
				return 'windows-1256';
14292
14293
			case 'windows1257':
14294
				return 'windows-1257';
14295
14296
			case 'windows1258':
14297
				return 'windows-1258';
14298
14299
			default:
14300
				return $charset;
14301
		}
14302
	}
14303
14304
	public static function get_curl_version()
14305
	{
14306
		if (is_array($curl = curl_version()))
14307
		{
14308
			$curl = $curl['version'];
14309
		}
14310
		elseif (substr($curl, 0, 5) === 'curl/')
14311
		{
14312
			$curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
14313
		}
14314
		elseif (substr($curl, 0, 8) === 'libcurl/')
14315
		{
14316
			$curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
14317
		}
14318
		else
14319
		{
14320
			$curl = 0;
14321
		}
14322
		return $curl;
14323
	}
14324
14325
	/**
14326
	 * Strip HTML comments
14327
	 *
14328
	 * @param string $data Data to strip comments from
14329
	 * @return string Comment stripped string
14330
	 */
14331
	public static function strip_comments($data)
14332
	{
14333
		$output = '';
14334
		while (($start = strpos($data, '<!--')) !== false)
14335
		{
14336
			$output .= substr($data, 0, $start);
14337
			if (($end = strpos($data, '-->', $start)) !== false)
14338
			{
14339
				$data = substr_replace($data, '', 0, $end + 3);
14340
			}
14341
			else
14342
			{
14343
				$data = '';
14344
			}
14345
		}
14346
		return $output . $data;
14347
	}
14348
14349
	public static function parse_date($dt)
14350
	{
14351
		$parser = SimplePie_Parse_Date::get();
14352
		return $parser->parse($dt);
14353
	}
14354
14355
	/**
14356
	 * Decode HTML entities
14357
	 *
14358
	 * @deprecated Use DOMDocument instead
14359
	 * @param string $data Input data
14360
	 * @return string Output data
14361
	 */
14362
	public static function entities_decode($data)
14363
	{
14364
		$decoder = new SimplePie_Decode_HTML_Entities($data);
0 ignored issues
show
Deprecated Code introduced by
The class SimplePie_Decode_HTML_Entities has been deprecated with message: Use DOMDocument instead!

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
14365
		return $decoder->parse();
14366
	}
14367
14368
	/**
14369
	 * Remove RFC822 comments
14370
	 *
14371
	 * @param string $data Data to strip comments from
0 ignored issues
show
Bug introduced by
There is no parameter named $data. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
14372
	 * @return string Comment stripped string
14373
	 */
14374
	public static function uncomment_rfc822($string)
14375
	{
14376
		$string = (string) $string;
14377
		$position = 0;
14378
		$length = strlen($string);
14379
		$depth = 0;
14380
14381
		$output = '';
14382
14383
		while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
14384
		{
14385
			$output .= substr($string, $position, $pos - $position);
14386
			$position = $pos + 1;
14387
			if ($string[$pos - 1] !== '\\')
14388
			{
14389
				$depth++;
14390
				while ($depth && $position < $length)
14391
				{
14392
					$position += strcspn($string, '()', $position);
14393
					if ($string[$position - 1] === '\\')
14394
					{
14395
						$position++;
14396
						continue;
14397
					}
14398
					elseif (isset($string[$position]))
14399
					{
14400
						switch ($string[$position])
14401
						{
14402
							case '(':
14403
								$depth++;
14404
								break;
14405
14406
							case ')':
14407
								$depth--;
14408
								break;
14409
						}
14410
						$position++;
14411
					}
14412
					else
14413
					{
14414
						break;
14415
					}
14416
				}
14417
			}
14418
			else
14419
			{
14420
				$output .= '(';
14421
			}
14422
		}
14423
		$output .= substr($string, $position);
14424
14425
		return $output;
14426
	}
14427
14428
	public static function parse_mime($mime)
14429
	{
14430
		if (($pos = strpos($mime, ';')) === false)
14431
		{
14432
			return trim($mime);
14433
		}
14434
		else
14435
		{
14436
			return trim(substr($mime, 0, $pos));
14437
		}
14438
	}
14439
14440
	public static function atom_03_construct_type($attribs)
14441
	{
14442
		if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
14443
		{
14444
			$mode = SIMPLEPIE_CONSTRUCT_BASE64;
14445
		}
14446
		else
14447
		{
14448
			$mode = SIMPLEPIE_CONSTRUCT_NONE;
14449
		}
14450
		if (isset($attribs['']['type']))
14451
		{
14452
			switch (strtolower(trim($attribs['']['type'])))
14453
			{
14454
				case 'text':
14455
				case 'text/plain':
14456
					return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
14457
14458
				case 'html':
14459
				case 'text/html':
14460
					return SIMPLEPIE_CONSTRUCT_HTML | $mode;
14461
14462
				case 'xhtml':
14463
				case 'application/xhtml+xml':
14464
					return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
14465
14466
				default:
14467
					return SIMPLEPIE_CONSTRUCT_NONE | $mode;
14468
			}
14469
		}
14470
		else
14471
		{
14472
			return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
14473
		}
14474
	}
14475
14476
	public static function atom_10_construct_type($attribs)
14477
	{
14478
		if (isset($attribs['']['type']))
14479
		{
14480
			switch (strtolower(trim($attribs['']['type'])))
14481
			{
14482
				case 'text':
14483
					return SIMPLEPIE_CONSTRUCT_TEXT;
14484
14485
				case 'html':
14486
					return SIMPLEPIE_CONSTRUCT_HTML;
14487
14488
				case 'xhtml':
14489
					return SIMPLEPIE_CONSTRUCT_XHTML;
14490
14491
				default:
14492
					return SIMPLEPIE_CONSTRUCT_NONE;
14493
			}
14494
		}
14495
		return SIMPLEPIE_CONSTRUCT_TEXT;
14496
	}
14497
14498
	public static function atom_10_content_construct_type($attribs)
14499
	{
14500
		if (isset($attribs['']['type']))
14501
		{
14502
			$type = strtolower(trim($attribs['']['type']));
14503
			switch ($type)
14504
			{
14505
				case 'text':
14506
					return SIMPLEPIE_CONSTRUCT_TEXT;
14507
14508
				case 'html':
14509
					return SIMPLEPIE_CONSTRUCT_HTML;
14510
14511
				case 'xhtml':
14512
					return SIMPLEPIE_CONSTRUCT_XHTML;
14513
			}
14514
			if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
14515
			{
14516
				return SIMPLEPIE_CONSTRUCT_NONE;
14517
			}
14518
			else
14519
			{
14520
				return SIMPLEPIE_CONSTRUCT_BASE64;
14521
			}
14522
		}
14523
		else
14524
		{
14525
			return SIMPLEPIE_CONSTRUCT_TEXT;
14526
		}
14527
	}
14528
14529
	public static function is_isegment_nz_nc($string)
14530
	{
14531
		return (bool) preg_match('/^([A-Za-z0-9\-._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!$&\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/u', $string);
14532
	}
14533
14534
	public static function space_separated_tokens($string)
14535
	{
14536
		$space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
14537
		$string_length = strlen($string);
14538
14539
		$position = strspn($string, $space_characters);
14540
		$tokens = array();
14541
14542
		while ($position < $string_length)
14543
		{
14544
			$len = strcspn($string, $space_characters, $position);
14545
			$tokens[] = substr($string, $position, $len);
14546
			$position += $len;
14547
			$position += strspn($string, $space_characters, $position);
14548
		}
14549
14550
		return $tokens;
14551
	}
14552
14553
	/**
14554
	 * Converts a unicode codepoint to a UTF-8 character
14555
	 *
14556
	 * @static
14557
	 * @param int $codepoint Unicode codepoint
14558
	 * @return string UTF-8 character
14559
	 */
14560
	public static function codepoint_to_utf8($codepoint)
14561
	{
14562
		$codepoint = (int) $codepoint;
14563
		if ($codepoint < 0)
14564
		{
14565
			return false;
14566
		}
14567
		else if ($codepoint <= 0x7f)
14568
		{
14569
			return chr($codepoint);
14570
		}
14571
		else if ($codepoint <= 0x7ff)
14572
		{
14573
			return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
14574
		}
14575
		else if ($codepoint <= 0xffff)
14576
		{
14577
			return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
14578
		}
14579
		else if ($codepoint <= 0x10ffff)
14580
		{
14581
			return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
14582
		}
14583
		else
14584
		{
14585
			// U+FFFD REPLACEMENT CHARACTER
14586
			return "\xEF\xBF\xBD";
14587
		}
14588
	}
14589
14590
	/**
14591
	 * Similar to parse_str()
14592
	 *
14593
	 * Returns an associative array of name/value pairs, where the value is an
14594
	 * array of values that have used the same name
14595
	 *
14596
	 * @static
14597
	 * @param string $str The input string.
14598
	 * @return array
14599
	 */
14600
	public static function parse_str($str)
14601
	{
14602
		$return = array();
14603
		$str = explode('&', $str);
14604
14605
		foreach ($str as $section)
14606
		{
14607
			if (strpos($section, '=') !== false)
14608
			{
14609
				list($name, $value) = explode('=', $section, 2);
14610
				$return[urldecode($name)][] = urldecode($value);
14611
			}
14612
			else
14613
			{
14614
				$return[urldecode($section)][] = null;
14615
			}
14616
		}
14617
14618
		return $return;
14619
	}
14620
14621
	/**
14622
	 * Detect XML encoding, as per XML 1.0 Appendix F.1
14623
	 *
14624
	 * @todo Add support for EBCDIC
14625
	 * @param string $data XML data
14626
	 * @param SimplePie_Registry $registry Class registry
14627
	 * @return array Possible encodings
14628
	 */
14629
	public static function xml_encoding($data, $registry)
14630
	{
14631
		// UTF-32 Big Endian BOM
14632
		if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14633
		{
14634
			$encoding[] = 'UTF-32BE';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$encoding was never initialized. Although not strictly required by PHP, it is generally a good practice to add $encoding = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
14635
		}
14636
		// UTF-32 Little Endian BOM
14637
		elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14638
		{
14639
			$encoding[] = 'UTF-32LE';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$encoding was never initialized. Although not strictly required by PHP, it is generally a good practice to add $encoding = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
14640
		}
14641
		// UTF-16 Big Endian BOM
14642
		elseif (substr($data, 0, 2) === "\xFE\xFF")
14643
		{
14644
			$encoding[] = 'UTF-16BE';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$encoding was never initialized. Although not strictly required by PHP, it is generally a good practice to add $encoding = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
14645
		}
14646
		// UTF-16 Little Endian BOM
14647
		elseif (substr($data, 0, 2) === "\xFF\xFE")
14648
		{
14649
			$encoding[] = 'UTF-16LE';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$encoding was never initialized. Although not strictly required by PHP, it is generally a good practice to add $encoding = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
14650
		}
14651
		// UTF-8 BOM
14652
		elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14653
		{
14654
			$encoding[] = 'UTF-8';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$encoding was never initialized. Although not strictly required by PHP, it is generally a good practice to add $encoding = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
14655
		}
14656
		// UTF-32 Big Endian Without BOM
14657
		elseif (substr($data, 0, 20) === "\x00\x00\x00\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C")
14658
		{
14659
			if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
14660
			{
14661
				$parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8')));
14662
				if ($parser->parse())
14663
				{
14664
					$encoding[] = $parser->encoding;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$encoding was never initialized. Although not strictly required by PHP, it is generally a good practice to add $encoding = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
14665
				}
14666
			}
14667
			$encoding[] = 'UTF-32BE';
0 ignored issues
show
Bug introduced by
The variable $encoding does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
14668
		}
14669
		// UTF-32 Little Endian Without BOM
14670
		elseif (substr($data, 0, 20) === "\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C\x00\x00\x00")
14671
		{
14672
			if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
14673
			{
14674
				$parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8')));
14675
				if ($parser->parse())
14676
				{
14677
					$encoding[] = $parser->encoding;
14678
				}
14679
			}
14680
			$encoding[] = 'UTF-32LE';
14681
		}
14682
		// UTF-16 Big Endian Without BOM
14683
		elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
14684
		{
14685
			if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
14686
			{
14687
				$parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8')));
14688
				if ($parser->parse())
14689
				{
14690
					$encoding[] = $parser->encoding;
14691
				}
14692
			}
14693
			$encoding[] = 'UTF-16BE';
14694
		}
14695
		// UTF-16 Little Endian Without BOM
14696
		elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
14697
		{
14698
			if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
14699
			{
14700
				$parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8')));
14701
				if ($parser->parse())
14702
				{
14703
					$encoding[] = $parser->encoding;
14704
				}
14705
			}
14706
			$encoding[] = 'UTF-16LE';
14707
		}
14708
		// US-ASCII (or superset)
14709
		elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
14710
		{
14711
			if ($pos = strpos($data, "\x3F\x3E"))
14712
			{
14713
				$parser = $registry->create('XML_Declaration_Parser', array(substr($data, 5, $pos - 5)));
14714
				if ($parser->parse())
14715
				{
14716
					$encoding[] = $parser->encoding;
14717
				}
14718
			}
14719
			$encoding[] = 'UTF-8';
14720
		}
14721
		// Fallback to UTF-8
14722
		else
14723
		{
14724
			$encoding[] = 'UTF-8';
14725
		}
14726
		return $encoding;
14727
	}
14728
14729
	public static function output_javascript()
14730
	{
14731
		if (function_exists('ob_gzhandler'))
14732
		{
14733
			ob_start('ob_gzhandler');
14734
		}
14735
		header('Content-type: text/javascript; charset: UTF-8');
14736
		header('Cache-Control: must-revalidate');
14737
		header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
14738
		?>
14739
function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
14740
	if (placeholder != '') {
14741
		document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" href="'+link+'" src="'+placeholder+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="false" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
14742
	}
14743
	else {
14744
		document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" src="'+link+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="true" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
14745
	}
14746
}
14747
14748
function embed_flash(bgcolor, width, height, link, loop, type) {
14749
	document.writeln('<embed src="'+link+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="'+type+'" quality="high" width="'+width+'" height="'+height+'" bgcolor="'+bgcolor+'" loop="'+loop+'"></embed>');
14750
}
14751
14752
function embed_flv(width, height, link, placeholder, loop, player) {
14753
	document.writeln('<embed src="'+player+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="'+width+'" height="'+height+'" wmode="transparent" flashvars="file='+link+'&autostart=false&repeat='+loop+'&showdigits=true&showfsbutton=false"></embed>');
14754
}
14755
14756
function embed_wmedia(width, height, link) {
14757
	document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
14758
}
14759
		<?php
14760
	}
14761
14762
	/**
14763
	 * Get the SimplePie build timestamp
14764
	 *
14765
	 * Uses the git index if it exists, otherwise uses the modification time
14766
	 * of the newest file.
14767
	 */
14768
	public static function get_build()
14769
	{
14770
		$root = dirname(dirname(__FILE__));
14771
		if (file_exists($root . '/.git/index'))
14772
		{
14773
			return filemtime($root . '/.git/index');
14774
		}
14775
		elseif (file_exists($root . '/SimplePie'))
14776
		{
14777
			$time = 0;
14778
			foreach (glob($root . '/SimplePie/*.php') as $file)
14779
			{
14780
				if (($mtime = filemtime($file)) > $time)
14781
				{
14782
					$time = $mtime;
14783
				}
14784
			}
14785
			return $time;
14786
		}
14787
		elseif (file_exists(dirname(__FILE__) . '/Core.php'))
14788
		{
14789
			return filemtime(dirname(__FILE__) . '/Core.php');
14790
		}
14791
		else
14792
		{
14793
			return filemtime(__FILE__);
14794
		}
14795
	}
14796
14797
	/**
14798
	 * Format debugging information
14799
	 */
14800
	public static function debug(&$sp)
14801
	{
14802
		$info = 'SimplePie ' . SIMPLEPIE_VERSION . ' Build ' . SIMPLEPIE_BUILD . "\n";
14803
		$info .= 'PHP ' . PHP_VERSION . "\n";
14804
		if ($sp->error() !== null)
14805
		{
14806
			$info .= 'Error occurred: ' . $sp->error() . "\n";
14807
		}
14808
		else
14809
		{
14810
			$info .= "No error found.\n";
14811
		}
14812
		$info .= "Extensions:\n";
14813
		$extensions = array('pcre', 'curl', 'zlib', 'mbstring', 'iconv', 'xmlreader', 'xml');
14814
		foreach ($extensions as $ext)
14815
		{
14816
			if (extension_loaded($ext))
14817
			{
14818
				$info .= "    $ext loaded\n";
14819
				switch ($ext)
14820
				{
14821
					case 'pcre':
14822
						$info .= '      Version ' . PCRE_VERSION . "\n";
14823
						break;
14824
					case 'curl':
14825
						$version = curl_version();
14826
						$info .= '      Version ' . $version['version'] . "\n";
14827
						break;
14828
					case 'mbstring':
14829
						$info .= '      Overloading: ' . mb_get_info('func_overload') . "\n";
14830
						break;
14831
					case 'iconv':
14832
						$info .= '      Version ' . ICONV_VERSION . "\n";
14833
						break;
14834
					case 'xml':
14835
						$info .= '      Version ' . LIBXML_DOTTED_VERSION . "\n";
14836
						break;
14837
				}
14838
			}
14839
			else
14840
			{
14841
				$info .= "    $ext not loaded\n";
14842
			}
14843
		}
14844
		return $info;
14845
	}
14846
14847
	public static function silence_errors($num, $str)
0 ignored issues
show
Unused Code introduced by
The parameter $num is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $str is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
14848
	{
14849
		// No-op
14850
	}
14851
}
14852
14853
/**
14854
 * Class to validate and to work with IPv6 addresses.
14855
 *
14856
 * @package SimplePie
14857
 * @subpackage HTTP
14858
 * @copyright 2003-2005 The PHP Group
14859
 * @license http://www.opensource.org/licenses/bsd-license.php
14860
 * @link http://pear.php.net/package/Net_IPv6
14861
 * @author Alexander Merz <[email protected]>
14862
 * @author elfrink at introweb dot nl
14863
 * @author Josh Peck <jmp at joshpeck dot org>
14864
 * @author Geoffrey Sneddon <[email protected]>
14865
 */
14866
class SimplePie_Net_IPv6
14867
{
14868
	/**
14869
	 * Uncompresses an IPv6 address
14870
	 *
14871
	 * RFC 4291 allows you to compress concecutive zero pieces in an address to
14872
	 * '::'. This method expects a valid IPv6 address and expands the '::' to
14873
	 * the required number of zero pieces.
14874
	 *
14875
	 * Example:  FF01::101   ->  FF01:0:0:0:0:0:0:101
14876
	 *           ::1         ->  0:0:0:0:0:0:0:1
14877
	 *
14878
	 * @author Alexander Merz <[email protected]>
14879
	 * @author elfrink at introweb dot nl
14880
	 * @author Josh Peck <jmp at joshpeck dot org>
14881
	 * @copyright 2003-2005 The PHP Group
14882
	 * @license http://www.opensource.org/licenses/bsd-license.php
14883
	 * @param string $ip An IPv6 address
14884
	 * @return string The uncompressed IPv6 address
14885
	 */
14886
	public static function uncompress($ip)
14887
	{
14888
		$c1 = -1;
0 ignored issues
show
Unused Code introduced by
$c1 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
14889
		$c2 = -1;
0 ignored issues
show
Unused Code introduced by
$c2 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
14890
		if (substr_count($ip, '::') === 1)
14891
		{
14892
			list($ip1, $ip2) = explode('::', $ip);
14893
			if ($ip1 === '')
14894
			{
14895
				$c1 = -1;
14896
			}
14897
			else
14898
			{
14899
				$c1 = substr_count($ip1, ':');
14900
			}
14901
			if ($ip2 === '')
14902
			{
14903
				$c2 = -1;
14904
			}
14905
			else
14906
			{
14907
				$c2 = substr_count($ip2, ':');
14908
			}
14909
			if (strpos($ip2, '.') !== false)
14910
			{
14911
				$c2++;
14912
			}
14913
			// ::
14914
			if ($c1 === -1 && $c2 === -1)
14915
			{
14916
				$ip = '0:0:0:0:0:0:0:0';
14917
			}
14918
			// ::xxx
14919
			else if ($c1 === -1)
14920
			{
14921
				$fill = str_repeat('0:', 7 - $c2);
14922
				$ip = str_replace('::', $fill, $ip);
14923
			}
14924
			// xxx::
14925
			else if ($c2 === -1)
14926
			{
14927
				$fill = str_repeat(':0', 7 - $c1);
14928
				$ip = str_replace('::', $fill, $ip);
14929
			}
14930
			// xxx::xxx
14931
			else
14932
			{
14933
				$fill = ':' . str_repeat('0:', 6 - $c2 - $c1);
14934
				$ip = str_replace('::', $fill, $ip);
14935
			}
14936
		}
14937
		return $ip;
14938
	}
14939
14940
	/**
14941
	 * Compresses an IPv6 address
14942
	 *
14943
	 * RFC 4291 allows you to compress concecutive zero pieces in an address to
14944
	 * '::'. This method expects a valid IPv6 address and compresses consecutive
14945
	 * zero pieces to '::'.
14946
	 *
14947
	 * Example:  FF01:0:0:0:0:0:0:101   ->  FF01::101
14948
	 *           0:0:0:0:0:0:0:1        ->  ::1
14949
	 *
14950
	 * @see uncompress()
14951
	 * @param string $ip An IPv6 address
14952
	 * @return string The compressed IPv6 address
14953
	 */
14954
	public static function compress($ip)
14955
	{
14956
		// Prepare the IP to be compressed
14957
		$ip = self::uncompress($ip);
14958
		$ip_parts = self::split_v6_v4($ip);
14959
14960
		// Replace all leading zeros
14961
		$ip_parts[0] = preg_replace('/(^|:)0+([0-9])/', '\1\2', $ip_parts[0]);
14962
14963
		// Find bunches of zeros
14964
		if (preg_match_all('/(?:^|:)(?:0(?::|$))+/', $ip_parts[0], $matches, PREG_OFFSET_CAPTURE))
14965
		{
14966
			$max = 0;
14967
			$pos = null;
14968
			foreach ($matches[0] as $match)
14969
			{
14970
				if (strlen($match[0]) > $max)
14971
				{
14972
					$max = strlen($match[0]);
14973
					$pos = $match[1];
14974
				}
14975
			}
14976
14977
			$ip_parts[0] = substr_replace($ip_parts[0], '::', $pos, $max);
14978
		}
14979
14980
		if ($ip_parts[1] !== '')
14981
		{
14982
			return implode(':', $ip_parts);
14983
		}
14984
		else
14985
		{
14986
			return $ip_parts[0];
14987
		}
14988
	}
14989
14990
	/**
14991
	 * Splits an IPv6 address into the IPv6 and IPv4 representation parts
14992
	 *
14993
	 * RFC 4291 allows you to represent the last two parts of an IPv6 address
14994
	 * using the standard IPv4 representation
14995
	 *
14996
	 * Example:  0:0:0:0:0:0:13.1.68.3
14997
	 *           0:0:0:0:0:FFFF:129.144.52.38
14998
	 *
14999
	 * @param string $ip An IPv6 address
15000
	 * @return array [0] contains the IPv6 represented part, and [1] the IPv4 represented part
15001
	 */
15002
	private static function split_v6_v4($ip)
15003
	{
15004
		if (strpos($ip, '.') !== false)
15005
		{
15006
			$pos = strrpos($ip, ':');
15007
			$ipv6_part = substr($ip, 0, $pos);
15008
			$ipv4_part = substr($ip, $pos + 1);
15009
			return array($ipv6_part, $ipv4_part);
15010
		}
15011
		else
15012
		{
15013
			return array($ip, '');
15014
		}
15015
	}
15016
15017
	/**
15018
	 * Checks an IPv6 address
15019
	 *
15020
	 * Checks if the given IP is a valid IPv6 address
15021
	 *
15022
	 * @param string $ip An IPv6 address
15023
	 * @return bool true if $ip is a valid IPv6 address
15024
	 */
15025
	public static function check_ipv6($ip)
15026
	{
15027
		$ip = self::uncompress($ip);
15028
		list($ipv6, $ipv4) = self::split_v6_v4($ip);
15029
		$ipv6 = explode(':', $ipv6);
15030
		$ipv4 = explode('.', $ipv4);
15031
		if (count($ipv6) === 8 && count($ipv4) === 1 || count($ipv6) === 6 && count($ipv4) === 4)
15032
		{
15033
			foreach ($ipv6 as $ipv6_part)
15034
			{
15035
				// The section can't be empty
15036
				if ($ipv6_part === '')
15037
					return false;
15038
15039
				// Nor can it be over four characters
15040
				if (strlen($ipv6_part) > 4)
15041
					return false;
15042
15043
				// Remove leading zeros (this is safe because of the above)
15044
				$ipv6_part = ltrim($ipv6_part, '0');
15045
				if ($ipv6_part === '')
15046
					$ipv6_part = '0';
15047
15048
				// Check the value is valid
15049
				$value = hexdec($ipv6_part);
15050
				if (dechex($value) !== strtolower($ipv6_part) || $value < 0 || $value > 0xFFFF)
15051
					return false;
15052
			}
15053
			if (count($ipv4) === 4)
15054
			{
15055
				foreach ($ipv4 as $ipv4_part)
15056
				{
15057
					$value = (int) $ipv4_part;
15058
					if ((string) $value !== $ipv4_part || $value < 0 || $value > 0xFF)
15059
						return false;
15060
				}
15061
			}
15062
			return true;
15063
		}
15064
		else
15065
		{
15066
			return false;
15067
		}
15068
	}
15069
15070
	/**
15071
	 * Checks if the given IP is a valid IPv6 address
15072
	 *
15073
	 * @codeCoverageIgnore
15074
	 * @deprecated Use {@see SimplePie_Net_IPv6::check_ipv6()} instead
15075
	 * @see check_ipv6
15076
	 * @param string $ip An IPv6 address
15077
	 * @return bool true if $ip is a valid IPv6 address
15078
	 */
15079
	public static function checkIPv6($ip)
15080
	{
15081
		return self::check_ipv6($ip);
15082
	}
15083
}
15084
15085
/**
15086
 * Date Parser
15087
 *
15088
 * @package SimplePie
15089
 * @subpackage Parsing
15090
 */
15091
class SimplePie_Parse_Date
15092
{
15093
	/**
15094
	 * Input data
15095
	 *
15096
	 * @access protected
15097
	 * @var string
15098
	 */
15099
	var $date;
15100
15101
	/**
15102
	 * List of days, calendar day name => ordinal day number in the week
15103
	 *
15104
	 * @access protected
15105
	 * @var array
15106
	 */
15107
	var $day = array(
15108
		// English
15109
		'mon' => 1,
15110
		'monday' => 1,
15111
		'tue' => 2,
15112
		'tuesday' => 2,
15113
		'wed' => 3,
15114
		'wednesday' => 3,
15115
		'thu' => 4,
15116
		'thursday' => 4,
15117
		'fri' => 5,
15118
		'friday' => 5,
15119
		'sat' => 6,
15120
		'saturday' => 6,
15121
		'sun' => 7,
15122
		'sunday' => 7,
15123
		// Dutch
15124
		'maandag' => 1,
15125
		'dinsdag' => 2,
15126
		'woensdag' => 3,
15127
		'donderdag' => 4,
15128
		'vrijdag' => 5,
15129
		'zaterdag' => 6,
15130
		'zondag' => 7,
15131
		// French
15132
		'lundi' => 1,
15133
		'mardi' => 2,
15134
		'mercredi' => 3,
15135
		'jeudi' => 4,
15136
		'vendredi' => 5,
15137
		'samedi' => 6,
15138
		'dimanche' => 7,
15139
		// German
15140
		'montag' => 1,
15141
		'dienstag' => 2,
15142
		'mittwoch' => 3,
15143
		'donnerstag' => 4,
15144
		'freitag' => 5,
15145
		'samstag' => 6,
15146
		'sonnabend' => 6,
15147
		'sonntag' => 7,
15148
		// Italian
15149
		'lunedì' => 1,
15150
		'martedì' => 2,
15151
		'mercoledì' => 3,
15152
		'giovedì' => 4,
15153
		'venerdì' => 5,
15154
		'sabato' => 6,
15155
		'domenica' => 7,
15156
		// Spanish
15157
		'lunes' => 1,
15158
		'martes' => 2,
15159
		'miércoles' => 3,
15160
		'jueves' => 4,
15161
		'viernes' => 5,
15162
		'sábado' => 6,
15163
		'domingo' => 7,
15164
		// Finnish
15165
		'maanantai' => 1,
15166
		'tiistai' => 2,
15167
		'keskiviikko' => 3,
15168
		'torstai' => 4,
15169
		'perjantai' => 5,
15170
		'lauantai' => 6,
15171
		'sunnuntai' => 7,
15172
		// Hungarian
15173
		'hétfő' => 1,
15174
		'kedd' => 2,
15175
		'szerda' => 3,
15176
		'csütörtok' => 4,
15177
		'péntek' => 5,
15178
		'szombat' => 6,
15179
		'vasárnap' => 7,
15180
		// Greek
15181
		'Δευ' => 1,
15182
		'Τρι' => 2,
15183
		'Τετ' => 3,
15184
		'Πεμ' => 4,
15185
		'Παρ' => 5,
15186
		'Σαβ' => 6,
15187
		'Κυρ' => 7,
15188
	);
15189
15190
	/**
15191
	 * List of months, calendar month name => calendar month number
15192
	 *
15193
	 * @access protected
15194
	 * @var array
15195
	 */
15196
	var $month = array(
15197
		// English
15198
		'jan' => 1,
15199
		'january' => 1,
15200
		'feb' => 2,
15201
		'february' => 2,
15202
		'mar' => 3,
15203
		'march' => 3,
15204
		'apr' => 4,
15205
		'april' => 4,
15206
		'may' => 5,
15207
		// No long form of May
15208
		'jun' => 6,
15209
		'june' => 6,
15210
		'jul' => 7,
15211
		'july' => 7,
15212
		'aug' => 8,
15213
		'august' => 8,
15214
		'sep' => 9,
15215
		'september' => 9,
15216
		'oct' => 10,
15217
		'october' => 10,
15218
		'nov' => 11,
15219
		'november' => 11,
15220
		'dec' => 12,
15221
		'december' => 12,
15222
		// Dutch
15223
		'januari' => 1,
15224
		'februari' => 2,
15225
		'maart' => 3,
15226
		'april' => 4,
15227
		'mei' => 5,
15228
		'juni' => 6,
15229
		'juli' => 7,
15230
		'augustus' => 8,
15231
		'september' => 9,
15232
		'oktober' => 10,
15233
		'november' => 11,
15234
		'december' => 12,
15235
		// French
15236
		'janvier' => 1,
15237
		'février' => 2,
15238
		'mars' => 3,
15239
		'avril' => 4,
15240
		'mai' => 5,
15241
		'juin' => 6,
15242
		'juillet' => 7,
15243
		'août' => 8,
15244
		'septembre' => 9,
15245
		'octobre' => 10,
15246
		'novembre' => 11,
15247
		'décembre' => 12,
15248
		// German
15249
		'januar' => 1,
15250
		'februar' => 2,
15251
		'märz' => 3,
15252
		'april' => 4,
15253
		'mai' => 5,
15254
		'juni' => 6,
15255
		'juli' => 7,
15256
		'august' => 8,
15257
		'september' => 9,
15258
		'oktober' => 10,
15259
		'november' => 11,
15260
		'dezember' => 12,
15261
		// Italian
15262
		'gennaio' => 1,
15263
		'febbraio' => 2,
15264
		'marzo' => 3,
15265
		'aprile' => 4,
15266
		'maggio' => 5,
15267
		'giugno' => 6,
15268
		'luglio' => 7,
15269
		'agosto' => 8,
15270
		'settembre' => 9,
15271
		'ottobre' => 10,
15272
		'novembre' => 11,
15273
		'dicembre' => 12,
15274
		// Spanish
15275
		'enero' => 1,
15276
		'febrero' => 2,
15277
		'marzo' => 3,
15278
		'abril' => 4,
15279
		'mayo' => 5,
15280
		'junio' => 6,
15281
		'julio' => 7,
15282
		'agosto' => 8,
15283
		'septiembre' => 9,
15284
		'setiembre' => 9,
15285
		'octubre' => 10,
15286
		'noviembre' => 11,
15287
		'diciembre' => 12,
15288
		// Finnish
15289
		'tammikuu' => 1,
15290
		'helmikuu' => 2,
15291
		'maaliskuu' => 3,
15292
		'huhtikuu' => 4,
15293
		'toukokuu' => 5,
15294
		'kesäkuu' => 6,
15295
		'heinäkuu' => 7,
15296
		'elokuu' => 8,
15297
		'suuskuu' => 9,
15298
		'lokakuu' => 10,
15299
		'marras' => 11,
15300
		'joulukuu' => 12,
15301
		// Hungarian
15302
		'január' => 1,
15303
		'február' => 2,
15304
		'március' => 3,
15305
		'április' => 4,
15306
		'május' => 5,
15307
		'június' => 6,
15308
		'július' => 7,
15309
		'augusztus' => 8,
15310
		'szeptember' => 9,
15311
		'október' => 10,
15312
		'november' => 11,
15313
		'december' => 12,
15314
		// Greek
15315
		'Ιαν' => 1,
15316
		'Φεβ' => 2,
15317
		'Μάώ' => 3,
15318
		'Μαώ' => 3,
15319
		'Απρ' => 4,
15320
		'Μάι' => 5,
15321
		'Μαϊ' => 5,
15322
		'Μαι' => 5,
15323
		'Ιούν' => 6,
15324
		'Ιον' => 6,
15325
		'Ιούλ' => 7,
15326
		'Ιολ' => 7,
15327
		'Αύγ' => 8,
15328
		'Αυγ' => 8,
15329
		'Σεπ' => 9,
15330
		'Οκτ' => 10,
15331
		'Νοέ' => 11,
15332
		'Δεκ' => 12,
15333
	);
15334
15335
	/**
15336
	 * List of timezones, abbreviation => offset from UTC
15337
	 *
15338
	 * @access protected
15339
	 * @var array
15340
	 */
15341
	var $timezone = array(
15342
		'ACDT' => 37800,
15343
		'ACIT' => 28800,
15344
		'ACST' => 34200,
15345
		'ACT' => -18000,
15346
		'ACWDT' => 35100,
15347
		'ACWST' => 31500,
15348
		'AEDT' => 39600,
15349
		'AEST' => 36000,
15350
		'AFT' => 16200,
15351
		'AKDT' => -28800,
15352
		'AKST' => -32400,
15353
		'AMDT' => 18000,
15354
		'AMT' => -14400,
15355
		'ANAST' => 46800,
15356
		'ANAT' => 43200,
15357
		'ART' => -10800,
15358
		'AZOST' => -3600,
15359
		'AZST' => 18000,
15360
		'AZT' => 14400,
15361
		'BIOT' => 21600,
15362
		'BIT' => -43200,
15363
		'BOT' => -14400,
15364
		'BRST' => -7200,
15365
		'BRT' => -10800,
15366
		'BST' => 3600,
15367
		'BTT' => 21600,
15368
		'CAST' => 18000,
15369
		'CAT' => 7200,
15370
		'CCT' => 23400,
15371
		'CDT' => -18000,
15372
		'CEDT' => 7200,
15373
		'CEST' => 7200,
15374
		'CET' => 3600,
15375
		'CGST' => -7200,
15376
		'CGT' => -10800,
15377
		'CHADT' => 49500,
15378
		'CHAST' => 45900,
15379
		'CIST' => -28800,
15380
		'CKT' => -36000,
15381
		'CLDT' => -10800,
15382
		'CLST' => -14400,
15383
		'COT' => -18000,
15384
		'CST' => -21600,
15385
		'CVT' => -3600,
15386
		'CXT' => 25200,
15387
		'DAVT' => 25200,
15388
		'DTAT' => 36000,
15389
		'EADT' => -18000,
15390
		'EAST' => -21600,
15391
		'EAT' => 10800,
15392
		'ECT' => -18000,
15393
		'EDT' => -14400,
15394
		'EEST' => 10800,
15395
		'EET' => 7200,
15396
		'EGT' => -3600,
15397
		'EKST' => 21600,
15398
		'EST' => -18000,
15399
		'FJT' => 43200,
15400
		'FKDT' => -10800,
15401
		'FKST' => -14400,
15402
		'FNT' => -7200,
15403
		'GALT' => -21600,
15404
		'GEDT' => 14400,
15405
		'GEST' => 10800,
15406
		'GFT' => -10800,
15407
		'GILT' => 43200,
15408
		'GIT' => -32400,
15409
		'GST' => 14400,
15410
		'GST' => -7200,
15411
		'GYT' => -14400,
15412
		'HAA' => -10800,
15413
		'HAC' => -18000,
15414
		'HADT' => -32400,
15415
		'HAE' => -14400,
15416
		'HAP' => -25200,
15417
		'HAR' => -21600,
15418
		'HAST' => -36000,
15419
		'HAT' => -9000,
15420
		'HAY' => -28800,
15421
		'HKST' => 28800,
15422
		'HMT' => 18000,
15423
		'HNA' => -14400,
15424
		'HNC' => -21600,
15425
		'HNE' => -18000,
15426
		'HNP' => -28800,
15427
		'HNR' => -25200,
15428
		'HNT' => -12600,
15429
		'HNY' => -32400,
15430
		'IRDT' => 16200,
15431
		'IRKST' => 32400,
15432
		'IRKT' => 28800,
15433
		'IRST' => 12600,
15434
		'JFDT' => -10800,
15435
		'JFST' => -14400,
15436
		'JST' => 32400,
15437
		'KGST' => 21600,
15438
		'KGT' => 18000,
15439
		'KOST' => 39600,
15440
		'KOVST' => 28800,
15441
		'KOVT' => 25200,
15442
		'KRAST' => 28800,
15443
		'KRAT' => 25200,
15444
		'KST' => 32400,
15445
		'LHDT' => 39600,
15446
		'LHST' => 37800,
15447
		'LINT' => 50400,
15448
		'LKT' => 21600,
15449
		'MAGST' => 43200,
15450
		'MAGT' => 39600,
15451
		'MAWT' => 21600,
15452
		'MDT' => -21600,
15453
		'MESZ' => 7200,
15454
		'MEZ' => 3600,
15455
		'MHT' => 43200,
15456
		'MIT' => -34200,
15457
		'MNST' => 32400,
15458
		'MSDT' => 14400,
15459
		'MSST' => 10800,
15460
		'MST' => -25200,
15461
		'MUT' => 14400,
15462
		'MVT' => 18000,
15463
		'MYT' => 28800,
15464
		'NCT' => 39600,
15465
		'NDT' => -9000,
15466
		'NFT' => 41400,
15467
		'NMIT' => 36000,
15468
		'NOVST' => 25200,
15469
		'NOVT' => 21600,
15470
		'NPT' => 20700,
15471
		'NRT' => 43200,
15472
		'NST' => -12600,
15473
		'NUT' => -39600,
15474
		'NZDT' => 46800,
15475
		'NZST' => 43200,
15476
		'OMSST' => 25200,
15477
		'OMST' => 21600,
15478
		'PDT' => -25200,
15479
		'PET' => -18000,
15480
		'PETST' => 46800,
15481
		'PETT' => 43200,
15482
		'PGT' => 36000,
15483
		'PHOT' => 46800,
15484
		'PHT' => 28800,
15485
		'PKT' => 18000,
15486
		'PMDT' => -7200,
15487
		'PMST' => -10800,
15488
		'PONT' => 39600,
15489
		'PST' => -28800,
15490
		'PWT' => 32400,
15491
		'PYST' => -10800,
15492
		'PYT' => -14400,
15493
		'RET' => 14400,
15494
		'ROTT' => -10800,
15495
		'SAMST' => 18000,
15496
		'SAMT' => 14400,
15497
		'SAST' => 7200,
15498
		'SBT' => 39600,
15499
		'SCDT' => 46800,
15500
		'SCST' => 43200,
15501
		'SCT' => 14400,
15502
		'SEST' => 3600,
15503
		'SGT' => 28800,
15504
		'SIT' => 28800,
15505
		'SRT' => -10800,
15506
		'SST' => -39600,
15507
		'SYST' => 10800,
15508
		'SYT' => 7200,
15509
		'TFT' => 18000,
15510
		'THAT' => -36000,
15511
		'TJT' => 18000,
15512
		'TKT' => -36000,
15513
		'TMT' => 18000,
15514
		'TOT' => 46800,
15515
		'TPT' => 32400,
15516
		'TRUT' => 36000,
15517
		'TVT' => 43200,
15518
		'TWT' => 28800,
15519
		'UYST' => -7200,
15520
		'UYT' => -10800,
15521
		'UZT' => 18000,
15522
		'VET' => -14400,
15523
		'VLAST' => 39600,
15524
		'VLAT' => 36000,
15525
		'VOST' => 21600,
15526
		'VUT' => 39600,
15527
		'WAST' => 7200,
15528
		'WAT' => 3600,
15529
		'WDT' => 32400,
15530
		'WEST' => 3600,
15531
		'WFT' => 43200,
15532
		'WIB' => 25200,
15533
		'WIT' => 32400,
15534
		'WITA' => 28800,
15535
		'WKST' => 18000,
15536
		'WST' => 28800,
15537
		'YAKST' => 36000,
15538
		'YAKT' => 32400,
15539
		'YAPT' => 36000,
15540
		'YEKST' => 21600,
15541
		'YEKT' => 18000,
15542
	);
15543
15544
	/**
15545
	 * Cached PCRE for SimplePie_Parse_Date::$day
15546
	 *
15547
	 * @access protected
15548
	 * @var string
15549
	 */
15550
	var $day_pcre;
15551
15552
	/**
15553
	 * Cached PCRE for SimplePie_Parse_Date::$month
15554
	 *
15555
	 * @access protected
15556
	 * @var string
15557
	 */
15558
	var $month_pcre;
15559
15560
	/**
15561
	 * Array of user-added callback methods
15562
	 *
15563
	 * @access private
15564
	 * @var array
15565
	 */
15566
	var $built_in = array();
15567
15568
	/**
15569
	 * Array of user-added callback methods
15570
	 *
15571
	 * @access private
15572
	 * @var array
15573
	 */
15574
	var $user = array();
15575
15576
	/**
15577
	 * Create new SimplePie_Parse_Date object, and set self::day_pcre,
15578
	 * self::month_pcre, and self::built_in
15579
	 *
15580
	 * @access private
15581
	 */
15582
	public function __construct()
15583
	{
15584
		$this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
15585
		$this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
15586
15587
		static $cache;
15588
		if (!isset($cache[get_class($this)]))
15589
		{
15590
			$all_methods = get_class_methods($this);
15591
15592
			foreach ($all_methods as $method)
15593
			{
15594
				if (strtolower(substr($method, 0, 5)) === 'date_')
15595
				{
15596
					$cache[get_class($this)][] = $method;
15597
				}
15598
			}
15599
		}
15600
15601
		foreach ($cache[get_class($this)] as $method)
15602
		{
15603
			$this->built_in[] = $method;
15604
		}
15605
	}
15606
15607
	/**
15608
	 * Get the object
15609
	 *
15610
	 * @access public
15611
	 */
15612
	public static function get()
15613
	{
15614
		static $object;
15615
		if (!$object)
15616
		{
15617
			$object = new SimplePie_Parse_Date;
15618
		}
15619
		return $object;
15620
	}
15621
15622
	/**
15623
	 * Parse a date
15624
	 *
15625
	 * @final
15626
	 * @access public
15627
	 * @param string $date Date to parse
15628
	 * @return int Timestamp corresponding to date string, or false on failure
15629
	 */
15630
	public function parse($date)
15631
	{
15632
		foreach ($this->user as $method)
15633
		{
15634
			if (($returned = call_user_func($method, $date)) !== false)
15635
			{
15636
				return $returned;
15637
			}
15638
		}
15639
15640
		foreach ($this->built_in as $method)
15641
		{
15642
			if (($returned = call_user_func(array($this, $method), $date)) !== false)
15643
			{
15644
				return $returned;
15645
			}
15646
		}
15647
15648
		return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by SimplePie_Parse_Date::parse of type integer.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
15649
	}
15650
15651
	/**
15652
	 * Add a callback method to parse a date
15653
	 *
15654
	 * @final
15655
	 * @access public
15656
	 * @param callback $callback
15657
	 */
15658
	public function add_callback($callback)
15659
	{
15660
		if (is_callable($callback))
15661
		{
15662
			$this->user[] = $callback;
15663
		}
15664
		else
15665
		{
15666
			trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
15667
		}
15668
	}
15669
15670
	/**
15671
	 * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
15672
	 * well as allowing any of upper or lower case "T", horizontal tabs, or
15673
	 * spaces to be used as the time separator (including more than one))
15674
	 *
15675
	 * @access protected
15676
	 * @return int Timestamp
15677
	 */
15678
	public function date_w3cdtf($date)
15679
	{
15680
		static $pcre;
15681
		if (!$pcre)
15682
		{
15683
			$year = '([0-9]{4})';
15684
			$month = $day = $hour = $minute = $second = '([0-9]{2})';
15685
			$decimal = '([0-9]*)';
15686
			$zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
15687
			$pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
15688
		}
15689
		if (preg_match($pcre, $date, $match))
15690
		{
15691
			/*
15692
			Capturing subpatterns:
15693
			1: Year
15694
			2: Month
15695
			3: Day
15696
			4: Hour
15697
			5: Minute
15698
			6: Second
15699
			7: Decimal fraction of a second
15700
			8: Zulu
15701
			9: Timezone ±
15702
			10: Timezone hours
15703
			11: Timezone minutes
15704
			*/
15705
15706
			// Fill in empty matches
15707
			for ($i = count($match); $i <= 3; $i++)
15708
			{
15709
				$match[$i] = '1';
15710
			}
15711
15712
			for ($i = count($match); $i <= 7; $i++)
15713
			{
15714
				$match[$i] = '0';
15715
			}
15716
15717
			// Numeric timezone
15718
			if (isset($match[9]) && $match[9] !== '')
15719
			{
15720
				$timezone = $match[10] * 3600;
15721
				$timezone += $match[11] * 60;
15722
				if ($match[9] === '-')
15723
				{
15724
					$timezone = 0 - $timezone;
15725
				}
15726
			}
15727
			else
15728
			{
15729
				$timezone = 0;
15730
			}
15731
15732
			// Convert the number of seconds to an integer, taking decimals into account
15733
			$second = round((int)$match[6] + (int)$match[7] / pow(10, strlen($match[7])));
15734
15735
			return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
15736
		}
15737
		else
15738
		{
15739
			return false;
15740
		}
15741
	}
15742
15743
	/**
15744
	 * Remove RFC822 comments
15745
	 *
15746
	 * @access protected
15747
	 * @param string $data Data to strip comments from
0 ignored issues
show
Bug introduced by
There is no parameter named $data. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
15748
	 * @return string Comment stripped string
15749
	 */
15750
	public function remove_rfc2822_comments($string)
15751
	{
15752
		$string = (string) $string;
15753
		$position = 0;
15754
		$length = strlen($string);
15755
		$depth = 0;
15756
15757
		$output = '';
15758
15759
		while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
15760
		{
15761
			$output .= substr($string, $position, $pos - $position);
15762
			$position = $pos + 1;
15763
			if ($pos === 0 || $string[$pos - 1] !== '\\')
15764
			{
15765
				$depth++;
15766
				while ($depth && $position < $length)
15767
				{
15768
					$position += strcspn($string, '()', $position);
15769
					if ($string[$position - 1] === '\\')
15770
					{
15771
						$position++;
15772
						continue;
15773
					}
15774
					elseif (isset($string[$position]))
15775
					{
15776
						switch ($string[$position])
15777
						{
15778
							case '(':
15779
								$depth++;
15780
								break;
15781
15782
							case ')':
15783
								$depth--;
15784
								break;
15785
						}
15786
						$position++;
15787
					}
15788
					else
15789
					{
15790
						break;
15791
					}
15792
				}
15793
			}
15794
			else
15795
			{
15796
				$output .= '(';
15797
			}
15798
		}
15799
		$output .= substr($string, $position);
15800
15801
		return $output;
15802
	}
15803
15804
	/**
15805
	 * Parse RFC2822's date format
15806
	 *
15807
	 * @access protected
15808
	 * @return int Timestamp
15809
	 */
15810
	public function date_rfc2822($date)
15811
	{
15812
		static $pcre;
15813
		if (!$pcre)
15814
		{
15815
			$wsp = '[\x09\x20]';
15816
			$fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
15817
			$optional_fws = $fws . '?';
15818
			$day_name = $this->day_pcre;
15819
			$month = $this->month_pcre;
15820
			$day = '([0-9]{1,2})';
15821
			$hour = $minute = $second = '([0-9]{2})';
15822
			$year = '([0-9]{2,4})';
15823
			$num_zone = '([+\-])([0-9]{2})([0-9]{2})';
15824
			$character_zone = '([A-Z]{1,5})';
15825
			$zone = '(?:' . $num_zone . '|' . $character_zone . ')';
15826
			$pcre = '/(?:' . $optional_fws . $day_name . $optional_fws . ',)?' . $optional_fws . $day . $fws . $month . $fws . $year . $fws . $hour . $optional_fws . ':' . $optional_fws . $minute . '(?:' . $optional_fws . ':' . $optional_fws . $second . ')?' . $fws . $zone . '/i';
15827
		}
15828
		if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
15829
		{
15830
			/*
15831
			Capturing subpatterns:
15832
			1: Day name
15833
			2: Day
15834
			3: Month
15835
			4: Year
15836
			5: Hour
15837
			6: Minute
15838
			7: Second
15839
			8: Timezone ±
15840
			9: Timezone hours
15841
			10: Timezone minutes
15842
			11: Alphabetic timezone
15843
			*/
15844
15845
			// Find the month number
15846
			$month = $this->month[strtolower($match[3])];
15847
15848
			// Numeric timezone
15849
			if ($match[8] !== '')
15850
			{
15851
				$timezone = $match[9] * 3600;
15852
				$timezone += $match[10] * 60;
15853
				if ($match[8] === '-')
15854
				{
15855
					$timezone = 0 - $timezone;
15856
				}
15857
			}
15858
			// Character timezone
15859
			elseif (isset($this->timezone[strtoupper($match[11])]))
15860
			{
15861
				$timezone = $this->timezone[strtoupper($match[11])];
15862
			}
15863
			// Assume everything else to be -0000
15864
			else
15865
			{
15866
				$timezone = 0;
15867
			}
15868
15869
			// Deal with 2/3 digit years
15870
			if ($match[4] < 50)
15871
			{
15872
				$match[4] += 2000;
15873
			}
15874
			elseif ($match[4] < 1000)
15875
			{
15876
				$match[4] += 1900;
15877
			}
15878
15879
			// Second is optional, if it is empty set it to zero
15880
			if ($match[7] !== '')
15881
			{
15882
				$second = $match[7];
15883
			}
15884
			else
15885
			{
15886
				$second = 0;
15887
			}
15888
15889
			return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
15890
		}
15891
		else
15892
		{
15893
			return false;
15894
		}
15895
	}
15896
15897
	/**
15898
	 * Parse RFC850's date format
15899
	 *
15900
	 * @access protected
15901
	 * @return int Timestamp
15902
	 */
15903
	public function date_rfc850($date)
15904
	{
15905
		static $pcre;
15906
		if (!$pcre)
15907
		{
15908
			$space = '[\x09\x20]+';
15909
			$day_name = $this->day_pcre;
15910
			$month = $this->month_pcre;
15911
			$day = '([0-9]{1,2})';
15912
			$year = $hour = $minute = $second = '([0-9]{2})';
15913
			$zone = '([A-Z]{1,5})';
15914
			$pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
15915
		}
15916
		if (preg_match($pcre, $date, $match))
15917
		{
15918
			/*
15919
			Capturing subpatterns:
15920
			1: Day name
15921
			2: Day
15922
			3: Month
15923
			4: Year
15924
			5: Hour
15925
			6: Minute
15926
			7: Second
15927
			8: Timezone
15928
			*/
15929
15930
			// Month
15931
			$month = $this->month[strtolower($match[3])];
15932
15933
			// Character timezone
15934
			if (isset($this->timezone[strtoupper($match[8])]))
15935
			{
15936
				$timezone = $this->timezone[strtoupper($match[8])];
15937
			}
15938
			// Assume everything else to be -0000
15939
			else
15940
			{
15941
				$timezone = 0;
15942
			}
15943
15944
			// Deal with 2 digit year
15945
			if ($match[4] < 50)
15946
			{
15947
				$match[4] += 2000;
15948
			}
15949
			else
15950
			{
15951
				$match[4] += 1900;
15952
			}
15953
15954
			return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
15955
		}
15956
		else
15957
		{
15958
			return false;
15959
		}
15960
	}
15961
15962
	/**
15963
	 * Parse C99's asctime()'s date format
15964
	 *
15965
	 * @access protected
15966
	 * @return int Timestamp
15967
	 */
15968
	public function date_asctime($date)
15969
	{
15970
		static $pcre;
15971
		if (!$pcre)
15972
		{
15973
			$space = '[\x09\x20]+';
15974
			$wday_name = $this->day_pcre;
15975
			$mon_name = $this->month_pcre;
15976
			$day = '([0-9]{1,2})';
15977
			$hour = $sec = $min = '([0-9]{2})';
15978
			$year = '([0-9]{4})';
15979
			$terminator = '\x0A?\x00?';
15980
			$pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
15981
		}
15982
		if (preg_match($pcre, $date, $match))
15983
		{
15984
			/*
15985
			Capturing subpatterns:
15986
			1: Day name
15987
			2: Month
15988
			3: Day
15989
			4: Hour
15990
			5: Minute
15991
			6: Second
15992
			7: Year
15993
			*/
15994
15995
			$month = $this->month[strtolower($match[2])];
15996
			return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
15997
		}
15998
		else
15999
		{
16000
			return false;
16001
		}
16002
	}
16003
16004
	/**
16005
	 * Parse dates using strtotime()
16006
	 *
16007
	 * @access protected
16008
	 * @return int Timestamp
16009
	 */
16010
	public function date_strtotime($date)
16011
	{
16012
		$strtotime = strtotime($date);
16013
		if ($strtotime === -1 || $strtotime === false)
16014
		{
16015
			return false;
16016
		}
16017
		else
16018
		{
16019
			return $strtotime;
16020
		}
16021
	}
16022
}
16023
16024
/**
16025
 * Parses XML into something sane
16026
 *
16027
 *
16028
 * This class can be overloaded with {@see SimplePie::set_parser_class()}
16029
 *
16030
 * @package SimplePie
16031
 * @subpackage Parsing
16032
 */
16033
class SimplePie_Parser
16034
{
16035
	var $error_code;
16036
	var $error_string;
16037
	var $current_line;
16038
	var $current_column;
16039
	var $current_byte;
16040
	var $separator = ' ';
16041
	var $namespace = array('');
16042
	var $element = array('');
16043
	var $xml_base = array('');
16044
	var $xml_base_explicit = array(false);
16045
	var $xml_lang = array('');
16046
	var $data = array();
16047
	var $datas = array(array());
16048
	var $current_xhtml_construct = -1;
16049
	var $encoding;
16050
	protected $registry;
16051
16052
	public function set_registry(SimplePie_Registry $registry)
16053
	{
16054
		$this->registry = $registry;
16055
	}
16056
16057
	public function parse(&$data, $encoding, $url = '')
16058
	{
16059
		if (class_exists('DOMXpath') && function_exists('Mf2\parse')) {
16060
			$doc = new DOMDocument();
16061
			@$doc->loadHTML($data);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
16062
			$xpath = new DOMXpath($doc);
16063
			// Check for both h-feed and h-entry, as both a feed with no entries
16064
			// and a list of entries without an h-feed wrapper are both valid.
16065
			$query = '//*[contains(concat(" ", @class, " "), " h-feed ") or '.
16066
				'contains(concat(" ", @class, " "), " h-entry ")]';
16067
			$result = $xpath->query($query);
16068
			if ($result->length !== 0) {
16069
				return $this->parse_microformats($data, $url);
16070
			}
16071
		}
16072
16073
		// Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
16074
		if (strtoupper($encoding) === 'US-ASCII')
16075
		{
16076
			$this->encoding = 'UTF-8';
16077
		}
16078
		else
16079
		{
16080
			$this->encoding = $encoding;
16081
		}
16082
16083
		// Strip BOM:
16084
		// UTF-32 Big Endian BOM
16085
		if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
16086
		{
16087
			$data = substr($data, 4);
16088
		}
16089
		// UTF-32 Little Endian BOM
16090
		elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
16091
		{
16092
			$data = substr($data, 4);
16093
		}
16094
		// UTF-16 Big Endian BOM
16095
		elseif (substr($data, 0, 2) === "\xFE\xFF")
16096
		{
16097
			$data = substr($data, 2);
16098
		}
16099
		// UTF-16 Little Endian BOM
16100
		elseif (substr($data, 0, 2) === "\xFF\xFE")
16101
		{
16102
			$data = substr($data, 2);
16103
		}
16104
		// UTF-8 BOM
16105
		elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
16106
		{
16107
			$data = substr($data, 3);
16108
		}
16109
16110
		if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
16111
		{
16112
			$declaration = $this->registry->create('XML_Declaration_Parser', array(substr($data, 5, $pos - 5)));
16113
			if ($declaration->parse())
16114
			{
16115
				$data = substr($data, $pos + 2);
16116
				$data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' ."\n". $this->declare_html_entities() . $data;
16117
			}
16118
			else
16119
			{
16120
				$this->error_string = 'SimplePie bug! Please report this!';
16121
				return false;
16122
			}
16123
		}
16124
16125
		$return = true;
16126
16127
		static $xml_is_sane = null;
16128
		if ($xml_is_sane === null)
16129
		{
16130
			$parser_check = xml_parser_create();
16131
			xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
16132
			xml_parser_free($parser_check);
16133
			$xml_is_sane = isset($values[0]['value']);
16134
		}
16135
16136
		// Create the parser
16137
		if ($xml_is_sane)
16138
		{
16139
			$xml = xml_parser_create_ns($this->encoding, $this->separator);
16140
			xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
16141
			xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
16142
			xml_set_object($xml, $this);
16143
			xml_set_character_data_handler($xml, 'cdata');
16144
			xml_set_element_handler($xml, 'tag_open', 'tag_close');
16145
16146
			// Parse!
16147
			if (!xml_parse($xml, $data, true))
16148
			{
16149
				$this->error_code = xml_get_error_code($xml);
16150
				$this->error_string = xml_error_string($this->error_code);
16151
				$return = false;
16152
			}
16153
			$this->current_line = xml_get_current_line_number($xml);
16154
			$this->current_column = xml_get_current_column_number($xml);
16155
			$this->current_byte = xml_get_current_byte_index($xml);
16156
			xml_parser_free($xml);
16157
			return $return;
16158
		}
16159
		else
16160
		{
16161
			libxml_clear_errors();
16162
			$xml = new XMLReader();
16163
			$xml->xml($data);
16164
			while (@$xml->read())
16165
			{
16166
				switch ($xml->nodeType)
16167
				{
16168
16169
					case constant('XMLReader::END_ELEMENT'):
16170
						if ($xml->namespaceURI !== '')
16171
						{
16172
							$tagName = $xml->namespaceURI . $this->separator . $xml->localName;
16173
						}
16174
						else
16175
						{
16176
							$tagName = $xml->localName;
16177
						}
16178
						$this->tag_close(null, $tagName);
16179
						break;
16180
					case constant('XMLReader::ELEMENT'):
16181
						$empty = $xml->isEmptyElement;
16182
						if ($xml->namespaceURI !== '')
16183
						{
16184
							$tagName = $xml->namespaceURI . $this->separator . $xml->localName;
16185
						}
16186
						else
16187
						{
16188
							$tagName = $xml->localName;
16189
						}
16190
						$attributes = array();
16191
						while ($xml->moveToNextAttribute())
16192
						{
16193
							if ($xml->namespaceURI !== '')
16194
							{
16195
								$attrName = $xml->namespaceURI . $this->separator . $xml->localName;
16196
							}
16197
							else
16198
							{
16199
								$attrName = $xml->localName;
16200
							}
16201
							$attributes[$attrName] = $xml->value;
16202
						}
16203
						$this->tag_open(null, $tagName, $attributes);
16204
						if ($empty)
16205
						{
16206
							$this->tag_close(null, $tagName);
16207
						}
16208
						break;
16209
					case constant('XMLReader::TEXT'):
16210
16211
					case constant('XMLReader::CDATA'):
16212
						$this->cdata(null, $xml->value);
16213
						break;
16214
				}
16215
			}
16216
			if ($error = libxml_get_last_error())
16217
			{
16218
				$this->error_code = $error->code;
16219
				$this->error_string = $error->message;
16220
				$this->current_line = $error->line;
16221
				$this->current_column = $error->column;
16222
				return false;
16223
			}
16224
			else
16225
			{
16226
				return true;
16227
			}
16228
		}
16229
	}
16230
16231
	public function get_error_code()
16232
	{
16233
		return $this->error_code;
16234
	}
16235
16236
	public function get_error_string()
16237
	{
16238
		return $this->error_string;
16239
	}
16240
16241
	public function get_current_line()
16242
	{
16243
		return $this->current_line;
16244
	}
16245
16246
	public function get_current_column()
16247
	{
16248
		return $this->current_column;
16249
	}
16250
16251
	public function get_current_byte()
16252
	{
16253
		return $this->current_byte;
16254
	}
16255
16256
	public function get_data()
16257
	{
16258
		return $this->data;
16259
	}
16260
16261
	public function tag_open($parser, $tag, $attributes)
0 ignored issues
show
Unused Code introduced by
The parameter $parser is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
16262
	{
16263
		list($this->namespace[], $this->element[]) = $this->split_ns($tag);
16264
16265
		$attribs = array();
16266
		foreach ($attributes as $name => $value)
16267
		{
16268
			list($attrib_namespace, $attribute) = $this->split_ns($name);
16269
			$attribs[$attrib_namespace][$attribute] = $value;
16270
		}
16271
16272
		if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
16273
		{
16274
			$base = $this->registry->call('Misc', 'absolutize_url', array($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base)));
16275
			if ($base !== false)
16276
			{
16277
				$this->xml_base[] = $base;
16278
				$this->xml_base_explicit[] = true;
16279
			}
16280
		}
16281
		else
16282
		{
16283
			$this->xml_base[] = end($this->xml_base);
16284
			$this->xml_base_explicit[] = end($this->xml_base_explicit);
16285
		}
16286
16287
		if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
16288
		{
16289
			$this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
16290
		}
16291
		else
16292
		{
16293
			$this->xml_lang[] = end($this->xml_lang);
16294
		}
16295
16296
		if ($this->current_xhtml_construct >= 0)
16297
		{
16298
			$this->current_xhtml_construct++;
16299
			if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
16300
			{
16301
				$this->data['data'] .= '<' . end($this->element);
16302
				if (isset($attribs['']))
16303
				{
16304
					foreach ($attribs[''] as $name => $value)
16305
					{
16306
						$this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
16307
					}
16308
				}
16309
				$this->data['data'] .= '>';
16310
			}
16311
		}
16312
		else
16313
		{
16314
			$this->datas[] =& $this->data;
16315
			$this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
16316
			$this->data = array('data' => '', 'attribs' => $attribs, 'xml_base' => end($this->xml_base), 'xml_base_explicit' => end($this->xml_base_explicit), 'xml_lang' => end($this->xml_lang));
16317
			if ((end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_03 && in_array(end($this->element), array('title', 'tagline', 'copyright', 'info', 'summary', 'content')) && isset($attribs['']['mode']) && $attribs['']['mode'] === 'xml')
16318
			|| (end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_10 && in_array(end($this->element), array('rights', 'subtitle', 'summary', 'info', 'title', 'content')) && isset($attribs['']['type']) && $attribs['']['type'] === 'xhtml')
16319
			|| (end($this->namespace) === SIMPLEPIE_NAMESPACE_RSS_20 && in_array(end($this->element), array('title')))
16320
			|| (end($this->namespace) === SIMPLEPIE_NAMESPACE_RSS_090 && in_array(end($this->element), array('title')))
16321
			|| (end($this->namespace) === SIMPLEPIE_NAMESPACE_RSS_10 && in_array(end($this->element), array('title'))))
16322
			{
16323
				$this->current_xhtml_construct = 0;
16324
			}
16325
		}
16326
	}
16327
16328
	public function cdata($parser, $cdata)
0 ignored issues
show
Unused Code introduced by
The parameter $parser is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
16329
	{
16330
		if ($this->current_xhtml_construct >= 0)
16331
		{
16332
			$this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
16333
		}
16334
		else
16335
		{
16336
			$this->data['data'] .= $cdata;
16337
		}
16338
	}
16339
16340
	public function tag_close($parser, $tag)
0 ignored issues
show
Unused Code introduced by
The parameter $parser is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $tag is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
16341
	{
16342
		if ($this->current_xhtml_construct >= 0)
16343
		{
16344
			$this->current_xhtml_construct--;
16345
			if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML && !in_array(end($this->element), array('area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param')))
16346
			{
16347
				$this->data['data'] .= '</' . end($this->element) . '>';
16348
			}
16349
		}
16350
		if ($this->current_xhtml_construct === -1)
16351
		{
16352
			$this->data =& $this->datas[count($this->datas) - 1];
16353
			array_pop($this->datas);
16354
		}
16355
16356
		array_pop($this->element);
16357
		array_pop($this->namespace);
16358
		array_pop($this->xml_base);
16359
		array_pop($this->xml_base_explicit);
16360
		array_pop($this->xml_lang);
16361
	}
16362
16363
	public function split_ns($string)
16364
	{
16365
		static $cache = array();
16366
		if (!isset($cache[$string]))
16367
		{
16368
			if ($pos = strpos($string, $this->separator))
16369
			{
16370
				static $separator_length;
16371
				if (!$separator_length)
16372
				{
16373
					$separator_length = strlen($this->separator);
16374
				}
16375
				$namespace = substr($string, 0, $pos);
16376
				$local_name = substr($string, $pos + $separator_length);
16377
				if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
16378
				{
16379
					$namespace = SIMPLEPIE_NAMESPACE_ITUNES;
16380
				}
16381
16382
				// Normalize the Media RSS namespaces
16383
				if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG ||
16384
					$namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2 ||
16385
					$namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3 ||
16386
					$namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4 ||
16387
					$namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5 )
16388
				{
16389
					$namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
16390
				}
16391
				$cache[$string] = array($namespace, $local_name);
16392
			}
16393
			else
16394
			{
16395
				$cache[$string] = array('', $string);
16396
			}
16397
		}
16398
		return $cache[$string];
16399
	}
16400
16401
	private function parse_hcard($data, $category = false) {
16402
		$name = '';
16403
		$link = '';
0 ignored issues
show
Unused Code introduced by
$link is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
16404
		// Check if h-card is set and pass that information on in the link.
16405
		if (isset($data['type']) && in_array('h-card', $data['type'])) {
16406
			if (isset($data['properties']['name'][0])) {
16407
				$name = $data['properties']['name'][0];
16408
			}
16409
			if (isset($data['properties']['url'][0])) {
16410
				$link = $data['properties']['url'][0];
16411
				if ($name === '') {
16412
					$name = $link;
16413
				}
16414
				else {
16415
					// can't have commas in categories.
16416
					$name = str_replace(',', '', $name);
16417
				}
16418
				$person_tag = $category ? '<span class="person-tag"></span>' : '';
16419
				return '<a class="h-card" href="'.$link.'">'.$person_tag.$name.'</a>';
16420
			}
16421
		}
16422
		return isset($data['value']) ? $data['value'] : '';
16423
	}
16424
16425
	private function parse_microformats(&$data, $url) {
16426
		$feed_title = '';
16427
		$feed_author = NULL;
16428
		$author_cache = array();
16429
		$items = array();
16430
		$entries = array();
16431
		$mf = Mf2\parse($data, $url);
16432
		// First look for an h-feed.
16433
		$h_feed = array();
16434
		foreach ($mf['items'] as $mf_item) {
16435
			if (in_array('h-feed', $mf_item['type'])) {
16436
				$h_feed = $mf_item;
16437
				break;
16438
			}
16439
			// Also look for h-feed or h-entry in the children of each top level item.
16440
			if (!isset($mf_item['children'][0]['type'])) continue;
16441
			if (in_array('h-feed', $mf_item['children'][0]['type'])) {
16442
				$h_feed = $mf_item['children'][0];
16443
				// In this case the parent of the h-feed may be an h-card, so use it as
16444
				// the feed_author.
16445
				if (in_array('h-card', $mf_item['type'])) $feed_author = $mf_item;
16446
				break;
16447
			}
16448
			else if (in_array('h-entry', $mf_item['children'][0]['type'])) {
16449
				$entries = $mf_item['children'];
16450
				// In this case the parent of the h-entry list may be an h-card, so use
16451
				// it as the feed_author.
16452
				if (in_array('h-card', $mf_item['type'])) $feed_author = $mf_item;
16453
				break;
16454
			}
16455
		}
16456
		if (isset($h_feed['children'])) {
16457
			$entries = $h_feed['children'];
16458
			// Also set the feed title and store author from the h-feed if available.
16459
			if (isset($mf['items'][0]['properties']['name'][0])) {
16460
				$feed_title = $mf['items'][0]['properties']['name'][0];
16461
			}
16462
			if (isset($mf['items'][0]['properties']['author'][0])) {
16463
				$feed_author = $mf['items'][0]['properties']['author'][0];
16464
			}
16465
		}
16466
		else if (count($entries) === 0) {
16467
			$entries = $mf['items'];
16468
		}
16469
		for ($i = 0; $i < count($entries); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
16470
			$entry = $entries[$i];
16471
			if (in_array('h-entry', $entry['type'])) {
16472
				$item = array();
16473
				$title = '';
16474
				$description = '';
16475
				if (isset($entry['properties']['url'][0])) {
16476
					$link = $entry['properties']['url'][0];
16477
					if (isset($link['value'])) $link = $link['value'];
16478
					$item['link'] = array(array('data' => $link));
16479
				}
16480
				if (isset($entry['properties']['uid'][0])) {
16481
					$guid = $entry['properties']['uid'][0];
16482
					if (isset($guid['value'])) $guid = $guid['value'];
16483
					$item['guid'] = array(array('data' => $guid));
16484
				}
16485
				if (isset($entry['properties']['name'][0])) {
16486
					$title = $entry['properties']['name'][0];
16487
					if (isset($title['value'])) $title = $title['value'];
16488
					$item['title'] = array(array('data' => $title));
16489
				}
16490
				if (isset($entry['properties']['author'][0]) || isset($feed_author)) {
16491
					// author is a special case, it can be plain text or an h-card array.
16492
					// If it's plain text it can also be a url that should be followed to
16493
					// get the actual h-card.
16494
					$author = isset($entry['properties']['author'][0]) ?
16495
						$entry['properties']['author'][0] : $feed_author;
16496
					if (!is_string($author)) {
16497
						$author = $this->parse_hcard($author);
16498
					}
16499
					else if (strpos($author, 'http') === 0) {
16500
						if (isset($author_cache[$author])) {
16501
							$author = $author_cache[$author];
16502
						}
16503
						else {
16504
							$mf = Mf2\fetch($author);
16505
							foreach ($mf['items'] as $hcard) {
16506
								// Only interested in an h-card by itself in this case.
16507
								if (!in_array('h-card', $hcard['type'])) {
16508
									continue;
16509
								}
16510
								// It must have a url property matching what we fetched.
16511
								if (!isset($hcard['properties']['url']) ||
16512
										!(in_array($author, $hcard['properties']['url']))) {
16513
									continue;
16514
								}
16515
								// Save parse_hcard the trouble of finding the correct url.
16516
								$hcard['properties']['url'][0] = $author;
16517
								// Cache this h-card for the next h-entry to check.
16518
								$author_cache[$author] = $this->parse_hcard($hcard);
16519
								$author = $author_cache[$author];
16520
								break;
16521
							}
16522
						}
16523
					}
16524
					$item['author'] = array(array('data' => $author));
16525
				}
16526
				if (isset($entry['properties']['photo'][0])) {
16527
					// If a photo is also in content, don't need to add it again here.
16528
					$content = '';
16529
					if (isset($entry['properties']['content'][0]['html'])) {
16530
						$content = $entry['properties']['content'][0]['html'];
16531
					}
16532
					$photo_list = array();
16533
					for ($j = 0; $j < count($entry['properties']['photo']); $j++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
16534
						$photo = $entry['properties']['photo'][$j];
16535
						if (!empty($photo) && strpos($content, $photo) === false) {
16536
							$photo_list[] = $photo;
16537
						}
16538
					}
16539
					// When there's more than one photo show the first and use a lightbox.
16540
					// Need a permanent, unique name for the image set, but don't have
16541
					// anything unique except for the content itself, so use that.
16542
					$count = count($photo_list);
16543
					if ($count > 1) {
16544
						$image_set_id = preg_replace('/[[:^alnum:]]/', '', $photo_list[0]);
16545
						$description = '<p>';
16546
						for ($j = 0; $j < $count; $j++) {
16547
							$hidden = $j === 0 ? '' : 'class="hidden" ';
16548
							$description .= '<a href="'.$photo_list[$j].'" '.$hidden.
16549
								'data-lightbox="image-set-'.$image_set_id.'">'.
16550
								'<img src="'.$photo_list[$j].'"></a>';
16551
						}
16552
						$description .= '<br><b>'.$count.' photos</b></p>';
16553
					}
16554
					else if ($count == 1) {
16555
						$description = '<p><img src="'.$photo_list[0].'"></p>';
16556
					}
16557
				}
16558
				if (isset($entry['properties']['content'][0]['html'])) {
16559
					// e-content['value'] is the same as p-name when they are on the same
16560
					// element. Use this to replace title with a strip_tags version so
16561
					// that alt text from images is not included in the title.
16562
					if ($entry['properties']['content'][0]['value'] === $title) {
16563
						$title = strip_tags($entry['properties']['content'][0]['html']);
16564
						$item['title'] = array(array('data' => $title));
16565
					}
16566
					$description .= $entry['properties']['content'][0]['html'];
16567
					if (isset($entry['properties']['in-reply-to'][0])) {
16568
						$in_reply_to = '';
16569
						if (is_string($entry['properties']['in-reply-to'][0])) {
16570
							$in_reply_to = $entry['properties']['in-reply-to'][0];
16571
						}
16572
						else if (isset($entry['properties']['in-reply-to'][0]['value'])) {
16573
							$in_reply_to = $entry['properties']['in-reply-to'][0]['value'];
16574
						}
16575
						if ($in_reply_to !== '') {
16576
							$description .= '<p><span class="in-reply-to"></span> '.
16577
								'<a href="'.$in_reply_to.'">'.$in_reply_to.'</a><p>';
16578
						}
16579
					}
16580
					$item['description'] = array(array('data' => $description));
16581
				}
16582
				if (isset($entry['properties']['category'])) {
16583
					$category_csv = '';
16584
					// Categories can also contain h-cards.
16585
					foreach ($entry['properties']['category'] as $category) {
16586
						if ($category_csv !== '') $category_csv .= ', ';
16587
						if (is_string($category)) {
16588
							// Can't have commas in categories.
16589
							$category_csv .= str_replace(',', '', $category);
16590
						}
16591
						else {
16592
							$category_csv .= $this->parse_hcard($category, true);
16593
						}
16594
					}
16595
					$item['category'] = array(array('data' => $category_csv));
16596
				}
16597
				if (isset($entry['properties']['published'][0])) {
16598
					$timestamp = strtotime($entry['properties']['published'][0]);
16599
					$pub_date = date('F j Y g:ia', $timestamp).' GMT';
16600
					$item['pubDate'] = array(array('data' => $pub_date));
16601
				}
16602
				// The title and description are set to the empty string to represent
16603
				// a deleted item (which also makes it an invalid rss item).
16604
				if (isset($entry['properties']['deleted'][0])) {
16605
					$item['title'] = array(array('data' => ''));
16606
					$item['description'] = array(array('data' => ''));
16607
				}
16608
				$items[] = array('child' => array('' => $item));
16609
			}
16610
		}
16611
		// Mimic RSS data format when storing microformats.
16612
		$link = array(array('data' => $url));
16613
		$image = '';
16614
		if (!is_string($feed_author) &&
16615
				isset($feed_author['properties']['photo'][0])) {
16616
			$image = array(array('child' => array('' => array('url' =>
16617
				array(array('data' => $feed_author['properties']['photo'][0]))))));
16618
		}
16619
		// Use the name given for the h-feed, or get the title from the html.
16620
		if ($feed_title !== '') {
16621
			$feed_title = array(array('data' => htmlspecialchars($feed_title)));
16622
		}
16623
		else if ($position = strpos($data, '<title>')) {
16624
			$start = $position < 200 ? 0 : $position - 200;
16625
			$check = substr($data, $start, 400);
16626
			$matches = array();
16627
			if (preg_match('/<title>(.+)<\/title>/', $check, $matches)) {
16628
				$feed_title = array(array('data' => htmlspecialchars($matches[1])));
16629
			}
16630
		}
16631
		$channel = array('channel' => array(array('child' => array('' =>
16632
			array('link' => $link, 'image' => $image, 'title' => $feed_title,
16633
			      'item' => $items)))));
16634
		$rss = array(array('attribs' => array('' => array('version' => '2.0')),
16635
		                   'child' => array('' => $channel)));
16636
		$this->data = array('child' => array('' => array('rss' => $rss)));
16637
		return true;
16638
	}
16639
16640
	private function declare_html_entities() {
16641
		// This is required because the RSS specification says that entity-encoded
16642
		// html is allowed, but the xml specification says they must be declared.
16643
		return '<!DOCTYPE html [ <!ENTITY nbsp "&#x00A0;"> <!ENTITY iexcl "&#x00A1;"> <!ENTITY cent "&#x00A2;"> <!ENTITY pound "&#x00A3;"> <!ENTITY curren "&#x00A4;"> <!ENTITY yen "&#x00A5;"> <!ENTITY brvbar "&#x00A6;"> <!ENTITY sect "&#x00A7;"> <!ENTITY uml "&#x00A8;"> <!ENTITY copy "&#x00A9;"> <!ENTITY ordf "&#x00AA;"> <!ENTITY laquo "&#x00AB;"> <!ENTITY not "&#x00AC;"> <!ENTITY shy "&#x00AD;"> <!ENTITY reg "&#x00AE;"> <!ENTITY macr "&#x00AF;"> <!ENTITY deg "&#x00B0;"> <!ENTITY plusmn "&#x00B1;"> <!ENTITY sup2 "&#x00B2;"> <!ENTITY sup3 "&#x00B3;"> <!ENTITY acute "&#x00B4;"> <!ENTITY micro "&#x00B5;"> <!ENTITY para "&#x00B6;"> <!ENTITY middot "&#x00B7;"> <!ENTITY cedil "&#x00B8;"> <!ENTITY sup1 "&#x00B9;"> <!ENTITY ordm "&#x00BA;"> <!ENTITY raquo "&#x00BB;"> <!ENTITY frac14 "&#x00BC;"> <!ENTITY frac12 "&#x00BD;"> <!ENTITY frac34 "&#x00BE;"> <!ENTITY iquest "&#x00BF;"> <!ENTITY Agrave "&#x00C0;"> <!ENTITY Aacute "&#x00C1;"> <!ENTITY Acirc "&#x00C2;"> <!ENTITY Atilde "&#x00C3;"> <!ENTITY Auml "&#x00C4;"> <!ENTITY Aring "&#x00C5;"> <!ENTITY AElig "&#x00C6;"> <!ENTITY Ccedil "&#x00C7;"> <!ENTITY Egrave "&#x00C8;"> <!ENTITY Eacute "&#x00C9;"> <!ENTITY Ecirc "&#x00CA;"> <!ENTITY Euml "&#x00CB;"> <!ENTITY Igrave "&#x00CC;"> <!ENTITY Iacute "&#x00CD;"> <!ENTITY Icirc "&#x00CE;"> <!ENTITY Iuml "&#x00CF;"> <!ENTITY ETH "&#x00D0;"> <!ENTITY Ntilde "&#x00D1;"> <!ENTITY Ograve "&#x00D2;"> <!ENTITY Oacute "&#x00D3;"> <!ENTITY Ocirc "&#x00D4;"> <!ENTITY Otilde "&#x00D5;"> <!ENTITY Ouml "&#x00D6;"> <!ENTITY times "&#x00D7;"> <!ENTITY Oslash "&#x00D8;"> <!ENTITY Ugrave "&#x00D9;"> <!ENTITY Uacute "&#x00DA;"> <!ENTITY Ucirc "&#x00DB;"> <!ENTITY Uuml "&#x00DC;"> <!ENTITY Yacute "&#x00DD;"> <!ENTITY THORN "&#x00DE;"> <!ENTITY szlig "&#x00DF;"> <!ENTITY agrave "&#x00E0;"> <!ENTITY aacute "&#x00E1;"> <!ENTITY acirc "&#x00E2;"> <!ENTITY atilde "&#x00E3;"> <!ENTITY auml "&#x00E4;"> <!ENTITY aring "&#x00E5;"> <!ENTITY aelig "&#x00E6;"> <!ENTITY ccedil "&#x00E7;"> <!ENTITY egrave "&#x00E8;"> <!ENTITY eacute "&#x00E9;"> <!ENTITY ecirc "&#x00EA;"> <!ENTITY euml "&#x00EB;"> <!ENTITY igrave "&#x00EC;"> <!ENTITY iacute "&#x00ED;"> <!ENTITY icirc "&#x00EE;"> <!ENTITY iuml "&#x00EF;"> <!ENTITY eth "&#x00F0;"> <!ENTITY ntilde "&#x00F1;"> <!ENTITY ograve "&#x00F2;"> <!ENTITY oacute "&#x00F3;"> <!ENTITY ocirc "&#x00F4;"> <!ENTITY otilde "&#x00F5;"> <!ENTITY ouml "&#x00F6;"> <!ENTITY divide "&#x00F7;"> <!ENTITY oslash "&#x00F8;"> <!ENTITY ugrave "&#x00F9;"> <!ENTITY uacute "&#x00FA;"> <!ENTITY ucirc "&#x00FB;"> <!ENTITY uuml "&#x00FC;"> <!ENTITY yacute "&#x00FD;"> <!ENTITY thorn "&#x00FE;"> <!ENTITY yuml "&#x00FF;"> <!ENTITY OElig "&#x0152;"> <!ENTITY oelig "&#x0153;"> <!ENTITY Scaron "&#x0160;"> <!ENTITY scaron "&#x0161;"> <!ENTITY Yuml "&#x0178;"> <!ENTITY fnof "&#x0192;"> <!ENTITY circ "&#x02C6;"> <!ENTITY tilde "&#x02DC;"> <!ENTITY Alpha "&#x0391;"> <!ENTITY Beta "&#x0392;"> <!ENTITY Gamma "&#x0393;"> <!ENTITY Epsilon "&#x0395;"> <!ENTITY Zeta "&#x0396;"> <!ENTITY Eta "&#x0397;"> <!ENTITY Theta "&#x0398;"> <!ENTITY Iota "&#x0399;"> <!ENTITY Kappa "&#x039A;"> <!ENTITY Lambda "&#x039B;"> <!ENTITY Mu "&#x039C;"> <!ENTITY Nu "&#x039D;"> <!ENTITY Xi "&#x039E;"> <!ENTITY Omicron "&#x039F;"> <!ENTITY Pi "&#x03A0;"> <!ENTITY Rho "&#x03A1;"> <!ENTITY Sigma "&#x03A3;"> <!ENTITY Tau "&#x03A4;"> <!ENTITY Upsilon "&#x03A5;"> <!ENTITY Phi "&#x03A6;"> <!ENTITY Chi "&#x03A7;"> <!ENTITY Psi "&#x03A8;"> <!ENTITY Omega "&#x03A9;"> <!ENTITY alpha "&#x03B1;"> <!ENTITY beta "&#x03B2;"> <!ENTITY gamma "&#x03B3;"> <!ENTITY delta "&#x03B4;"> <!ENTITY epsilon "&#x03B5;"> <!ENTITY zeta "&#x03B6;"> <!ENTITY eta "&#x03B7;"> <!ENTITY theta "&#x03B8;"> <!ENTITY iota "&#x03B9;"> <!ENTITY kappa "&#x03BA;"> <!ENTITY lambda "&#x03BB;"> <!ENTITY mu "&#x03BC;"> <!ENTITY nu "&#x03BD;"> <!ENTITY xi "&#x03BE;"> <!ENTITY omicron "&#x03BF;"> <!ENTITY pi "&#x03C0;"> <!ENTITY rho "&#x03C1;"> <!ENTITY sigmaf "&#x03C2;"> <!ENTITY sigma "&#x03C3;"> <!ENTITY tau "&#x03C4;"> <!ENTITY upsilon "&#x03C5;"> <!ENTITY phi "&#x03C6;"> <!ENTITY chi "&#x03C7;"> <!ENTITY psi "&#x03C8;"> <!ENTITY omega "&#x03C9;"> <!ENTITY thetasym "&#x03D1;"> <!ENTITY upsih "&#x03D2;"> <!ENTITY piv "&#x03D6;"> <!ENTITY ensp "&#x2002;"> <!ENTITY emsp "&#x2003;"> <!ENTITY thinsp "&#x2009;"> <!ENTITY zwnj "&#x200C;"> <!ENTITY zwj "&#x200D;"> <!ENTITY lrm "&#x200E;"> <!ENTITY rlm "&#x200F;"> <!ENTITY ndash "&#x2013;"> <!ENTITY mdash "&#x2014;"> <!ENTITY lsquo "&#x2018;"> <!ENTITY rsquo "&#x2019;"> <!ENTITY sbquo "&#x201A;"> <!ENTITY ldquo "&#x201C;"> <!ENTITY rdquo "&#x201D;"> <!ENTITY bdquo "&#x201E;"> <!ENTITY dagger "&#x2020;"> <!ENTITY Dagger "&#x2021;"> <!ENTITY bull "&#x2022;"> <!ENTITY hellip "&#x2026;"> <!ENTITY permil "&#x2030;"> <!ENTITY prime "&#x2032;"> <!ENTITY Prime "&#x2033;"> <!ENTITY lsaquo "&#x2039;"> <!ENTITY rsaquo "&#x203A;"> <!ENTITY oline "&#x203E;"> <!ENTITY frasl "&#x2044;"> <!ENTITY euro "&#x20AC;"> <!ENTITY image "&#x2111;"> <!ENTITY weierp "&#x2118;"> <!ENTITY real "&#x211C;"> <!ENTITY trade "&#x2122;"> <!ENTITY alefsym "&#x2135;"> <!ENTITY larr "&#x2190;"> <!ENTITY uarr "&#x2191;"> <!ENTITY rarr "&#x2192;"> <!ENTITY darr "&#x2193;"> <!ENTITY harr "&#x2194;"> <!ENTITY crarr "&#x21B5;"> <!ENTITY lArr "&#x21D0;"> <!ENTITY uArr "&#x21D1;"> <!ENTITY rArr "&#x21D2;"> <!ENTITY dArr "&#x21D3;"> <!ENTITY hArr "&#x21D4;"> <!ENTITY forall "&#x2200;"> <!ENTITY part "&#x2202;"> <!ENTITY exist "&#x2203;"> <!ENTITY empty "&#x2205;"> <!ENTITY nabla "&#x2207;"> <!ENTITY isin "&#x2208;"> <!ENTITY notin "&#x2209;"> <!ENTITY ni "&#x220B;"> <!ENTITY prod "&#x220F;"> <!ENTITY sum "&#x2211;"> <!ENTITY minus "&#x2212;"> <!ENTITY lowast "&#x2217;"> <!ENTITY radic "&#x221A;"> <!ENTITY prop "&#x221D;"> <!ENTITY infin "&#x221E;"> <!ENTITY ang "&#x2220;"> <!ENTITY and "&#x2227;"> <!ENTITY or "&#x2228;"> <!ENTITY cap "&#x2229;"> <!ENTITY cup "&#x222A;"> <!ENTITY int "&#x222B;"> <!ENTITY there4 "&#x2234;"> <!ENTITY sim "&#x223C;"> <!ENTITY cong "&#x2245;"> <!ENTITY asymp "&#x2248;"> <!ENTITY ne "&#x2260;"> <!ENTITY equiv "&#x2261;"> <!ENTITY le "&#x2264;"> <!ENTITY ge "&#x2265;"> <!ENTITY sub "&#x2282;"> <!ENTITY sup "&#x2283;"> <!ENTITY nsub "&#x2284;"> <!ENTITY sube "&#x2286;"> <!ENTITY supe "&#x2287;"> <!ENTITY oplus "&#x2295;"> <!ENTITY otimes "&#x2297;"> <!ENTITY perp "&#x22A5;"> <!ENTITY sdot "&#x22C5;"> <!ENTITY lceil "&#x2308;"> <!ENTITY rceil "&#x2309;"> <!ENTITY lfloor "&#x230A;"> <!ENTITY rfloor "&#x230B;"> <!ENTITY lang "&#x2329;"> <!ENTITY rang "&#x232A;"> <!ENTITY loz "&#x25CA;"> <!ENTITY spades "&#x2660;"> <!ENTITY clubs "&#x2663;"> <!ENTITY hearts "&#x2665;"> <!ENTITY diams "&#x2666;"> ]>';
16644
	}
16645
}
16646
16647
/**
16648
 * Handles `<media:rating>` or `<itunes:explicit>` tags as defined in Media RSS and iTunes RSS respectively
16649
 *
16650
 * Used by {@see SimplePie_Enclosure::get_rating()} and {@see SimplePie_Enclosure::get_ratings()}
16651
 *
16652
 * This class can be overloaded with {@see SimplePie::set_rating_class()}
16653
 *
16654
 * @package SimplePie
16655
 * @subpackage API
16656
 */
16657
class SimplePie_Rating
16658
{
16659
	/**
16660
	 * Rating scheme
16661
	 *
16662
	 * @var string
16663
	 * @see get_scheme()
16664
	 */
16665
	var $scheme;
16666
16667
	/**
16668
	 * Rating value
16669
	 *
16670
	 * @var string
16671
	 * @see get_value()
16672
	 */
16673
	var $value;
16674
16675
	/**
16676
	 * Constructor, used to input the data
16677
	 *
16678
	 * For documentation on all the parameters, see the corresponding
16679
	 * properties and their accessors
16680
	 */
16681
	public function __construct($scheme = null, $value = null)
16682
	{
16683
		$this->scheme = $scheme;
16684
		$this->value = $value;
16685
	}
16686
16687
	/**
16688
	 * String-ified version
16689
	 *
16690
	 * @return string
16691
	 */
16692
	public function __toString()
16693
	{
16694
		// There is no $this->data here
16695
		return md5(serialize($this));
16696
	}
16697
16698
	/**
16699
	 * Get the organizational scheme for the rating
16700
	 *
16701
	 * @return string|null
16702
	 */
16703
	public function get_scheme()
16704
	{
16705
		if ($this->scheme !== null)
16706
		{
16707
			return $this->scheme;
16708
		}
16709
		else
16710
		{
16711
			return null;
16712
		}
16713
	}
16714
16715
	/**
16716
	 * Get the value of the rating
16717
	 *
16718
	 * @return string|null
16719
	 */
16720
	public function get_value()
16721
	{
16722
		if ($this->value !== null)
16723
		{
16724
			return $this->value;
16725
		}
16726
		else
16727
		{
16728
			return null;
16729
		}
16730
	}
16731
}
16732
16733
/**
16734
 * Handles creating objects and calling methods
16735
 *
16736
 * Access this via {@see SimplePie::get_registry()}
16737
 *
16738
 * @package SimplePie
16739
 */
16740
class SimplePie_Registry
16741
{
16742
	/**
16743
	 * Default class mapping
16744
	 *
16745
	 * Overriding classes *must* subclass these.
16746
	 *
16747
	 * @var array
16748
	 */
16749
	protected $default = array(
16750
		'Cache' => 'SimplePie_Cache',
16751
		'Locator' => 'SimplePie_Locator',
16752
		'Parser' => 'SimplePie_Parser',
16753
		'File' => 'SimplePie_File',
16754
		'Sanitize' => 'SimplePie_Sanitize',
16755
		'Item' => 'SimplePie_Item',
16756
		'Author' => 'SimplePie_Author',
16757
		'Category' => 'SimplePie_Category',
16758
		'Enclosure' => 'SimplePie_Enclosure',
16759
		'Caption' => 'SimplePie_Caption',
16760
		'Copyright' => 'SimplePie_Copyright',
16761
		'Credit' => 'SimplePie_Credit',
16762
		'Rating' => 'SimplePie_Rating',
16763
		'Restriction' => 'SimplePie_Restriction',
16764
		'Content_Type_Sniffer' => 'SimplePie_Content_Type_Sniffer',
16765
		'Source' => 'SimplePie_Source',
16766
		'Misc' => 'SimplePie_Misc',
16767
		'XML_Declaration_Parser' => 'SimplePie_XML_Declaration_Parser',
16768
		'Parse_Date' => 'SimplePie_Parse_Date',
16769
	);
16770
16771
	/**
16772
	 * Class mapping
16773
	 *
16774
	 * @see register()
16775
	 * @var array
16776
	 */
16777
	protected $classes = array();
16778
16779
	/**
16780
	 * Legacy classes
16781
	 *
16782
	 * @see register()
16783
	 * @var array
16784
	 */
16785
	protected $legacy = array();
16786
16787
	/**
16788
	 * Constructor
16789
	 *
16790
	 * No-op
16791
	 */
16792
	public function __construct() { }
16793
16794
	/**
16795
	 * Register a class
16796
	 *
16797
	 * @param string $type See {@see $default} for names
16798
	 * @param string $class Class name, must subclass the corresponding default
16799
	 * @param bool $legacy Whether to enable legacy support for this class
16800
	 * @return bool Successfulness
16801
	 */
16802
	public function register($type, $class, $legacy = false)
16803
	{
16804
		if (!@is_subclass_of($class, $this->default[$type]))
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if $this->default[$type] can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
16805
		{
16806
			return false;
16807
		}
16808
16809
		$this->classes[$type] = $class;
16810
16811
		if ($legacy)
16812
		{
16813
			$this->legacy[] = $class;
16814
		}
16815
16816
		return true;
16817
	}
16818
16819
	/**
16820
	 * Get the class registered for a type
16821
	 *
16822
	 * Where possible, use {@see create()} or {@see call()} instead
16823
	 *
16824
	 * @param string $type
16825
	 * @return string|null
16826
	 */
16827
	public function get_class($type)
16828
	{
16829
		if (!empty($this->classes[$type]))
16830
		{
16831
			return $this->classes[$type];
16832
		}
16833
		if (!empty($this->default[$type]))
16834
		{
16835
			return $this->default[$type];
16836
		}
16837
16838
		return null;
16839
	}
16840
16841
	/**
16842
	 * Create a new instance of a given type
16843
	 *
16844
	 * @param string $type
16845
	 * @param array $parameters Parameters to pass to the constructor
16846
	 * @return object Instance of class
16847
	 */
16848
	public function &create($type, $parameters = array())
16849
	{
16850
		$class = $this->get_class($type);
16851
16852
		if (in_array($class, $this->legacy))
16853
		{
16854
			switch ($type)
16855
			{
16856
				case 'locator':
16857
					// Legacy: file, timeout, useragent, file_class, max_checked_feeds, content_type_sniffer_class
16858
					// Specified: file, timeout, useragent, max_checked_feeds
16859
					$replacement = array($this->get_class('file'), $parameters[3], $this->get_class('content_type_sniffer'));
16860
					array_splice($parameters, 3, 1, $replacement);
16861
					break;
16862
			}
16863
		}
16864
16865
		if (!method_exists($class, '__construct'))
16866
		{
16867
			$instance = new $class;
16868
		}
16869
		else
16870
		{
16871
			$reflector = new ReflectionClass($class);
16872
			$instance = $reflector->newInstanceArgs($parameters);
16873
		}
16874
16875
		if (method_exists($instance, 'set_registry'))
16876
		{
16877
			$instance->set_registry($this);
16878
		}
16879
		return $instance;
16880
	}
16881
16882
	/**
16883
	 * Call a static method for a type
16884
	 *
16885
	 * @param string $type
16886
	 * @param string $method
16887
	 * @param array $parameters
16888
	 * @return mixed
16889
	 */
16890
	public function &call($type, $method, $parameters = array())
16891
	{
16892
		$class = $this->get_class($type);
16893
16894
		if (in_array($class, $this->legacy))
16895
		{
16896
			switch ($type)
16897
			{
16898
				case 'Cache':
16899
					// For backwards compatibility with old non-static
16900
					// Cache::create() methods
16901
					if ($method === 'get_handler')
16902
					{
16903
						$result = @call_user_func_array(array($class, 'create'), $parameters);
16904
						return $result;
16905
					}
16906
					break;
16907
			}
16908
		}
16909
16910
		$result = call_user_func_array(array($class, $method), $parameters);
16911
		return $result;
16912
	}
16913
}
16914
16915
/**
16916
 * Handles `<media:restriction>` as defined in Media RSS
16917
 *
16918
 * Used by {@see SimplePie_Enclosure::get_restriction()} and {@see SimplePie_Enclosure::get_restrictions()}
16919
 *
16920
 * This class can be overloaded with {@see SimplePie::set_restriction_class()}
16921
 *
16922
 * @package SimplePie
16923
 * @subpackage API
16924
 */
16925
class SimplePie_Restriction
16926
{
16927
	/**
16928
	 * Relationship ('allow'/'deny')
16929
	 *
16930
	 * @var string
16931
	 * @see get_relationship()
16932
	 */
16933
	var $relationship;
16934
16935
	/**
16936
	 * Type of restriction
16937
	 *
16938
	 * @var string
16939
	 * @see get_type()
16940
	 */
16941
	var $type;
16942
16943
	/**
16944
	 * Restricted values
16945
	 *
16946
	 * @var string
16947
	 * @see get_value()
16948
	 */
16949
	var $value;
16950
16951
	/**
16952
	 * Constructor, used to input the data
16953
	 *
16954
	 * For documentation on all the parameters, see the corresponding
16955
	 * properties and their accessors
16956
	 */
16957
	public function __construct($relationship = null, $type = null, $value = null)
16958
	{
16959
		$this->relationship = $relationship;
16960
		$this->type = $type;
16961
		$this->value = $value;
16962
	}
16963
16964
	/**
16965
	 * String-ified version
16966
	 *
16967
	 * @return string
16968
	 */
16969
	public function __toString()
16970
	{
16971
		// There is no $this->data here
16972
		return md5(serialize($this));
16973
	}
16974
16975
	/**
16976
	 * Get the relationship
16977
	 *
16978
	 * @return string|null Either 'allow' or 'deny'
16979
	 */
16980
	public function get_relationship()
16981
	{
16982
		if ($this->relationship !== null)
16983
		{
16984
			return $this->relationship;
16985
		}
16986
		else
16987
		{
16988
			return null;
16989
		}
16990
	}
16991
16992
	/**
16993
	 * Get the type
16994
	 *
16995
	 * @return string|null
16996
	 */
16997
	public function get_type()
16998
	{
16999
		if ($this->type !== null)
17000
		{
17001
			return $this->type;
17002
		}
17003
		else
17004
		{
17005
			return null;
17006
		}
17007
	}
17008
17009
	/**
17010
	 * Get the list of restricted things
17011
	 *
17012
	 * @return string|null
17013
	 */
17014
	public function get_value()
17015
	{
17016
		if ($this->value !== null)
17017
		{
17018
			return $this->value;
17019
		}
17020
		else
17021
		{
17022
			return null;
17023
		}
17024
	}
17025
}
17026
17027
/**
17028
 * Used for data cleanup and post-processing
17029
 *
17030
 *
17031
 * This class can be overloaded with {@see SimplePie::set_sanitize_class()}
17032
 *
17033
 * @package SimplePie
17034
 * @todo Move to using an actual HTML parser (this will allow tags to be properly stripped, and to switch between HTML and XHTML), this will also make it easier to shorten a string while preserving HTML tags
17035
 */
17036
class SimplePie_Sanitize
17037
{
17038
	// Private vars
17039
	var $base;
17040
17041
	// Options
17042
	var $remove_div = true;
17043
	var $image_handler = '';
17044
	var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
17045
	var $encode_instead_of_strip = false;
17046
	var $strip_attributes = array('bgsound', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
17047
	var $add_attributes = array('audio' => array('preload' => 'none'), 'iframe' => array('sandbox' => 'allow-scripts allow-same-origin'), 'video' => array('preload' => 'none'));
17048
	var $strip_comments = false;
17049
	var $output_encoding = 'UTF-8';
17050
	var $enable_cache = true;
17051
	var $cache_location = './cache';
17052
	var $cache_name_function = 'md5';
17053
	var $timeout = 10;
17054
	var $useragent = '';
17055
	var $force_fsockopen = false;
17056
	var $replace_url_attributes = null;
17057
17058
	public function __construct()
17059
	{
17060
		// Set defaults
17061
		$this->set_url_replacements(null);
17062
	}
17063
17064
	public function remove_div($enable = true)
17065
	{
17066
		$this->remove_div = (bool) $enable;
17067
	}
17068
17069
	public function set_image_handler($page = false)
17070
	{
17071
		if ($page)
17072
		{
17073
			$this->image_handler = (string) $page;
17074
		}
17075
		else
17076
		{
17077
			$this->image_handler = false;
0 ignored issues
show
Documentation Bug introduced by
The property $image_handler was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
17078
		}
17079
	}
17080
17081
	public function set_registry(SimplePie_Registry $registry)
17082
	{
17083
		$this->registry = $registry;
0 ignored issues
show
Bug introduced by
The property registry does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
17084
	}
17085
17086
	public function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
0 ignored issues
show
Unused Code introduced by
The parameter $cache_class is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
17087
	{
17088
		if (isset($enable_cache))
17089
		{
17090
			$this->enable_cache = (bool) $enable_cache;
17091
		}
17092
17093
		if ($cache_location)
17094
		{
17095
			$this->cache_location = (string) $cache_location;
17096
		}
17097
17098
		if ($cache_name_function)
17099
		{
17100
			$this->cache_name_function = (string) $cache_name_function;
17101
		}
17102
	}
17103
17104
	public function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
0 ignored issues
show
Unused Code introduced by
The parameter $file_class is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
17105
	{
17106
		if ($timeout)
17107
		{
17108
			$this->timeout = (string) $timeout;
0 ignored issues
show
Documentation Bug introduced by
The property $timeout was declared of type integer, but (string) $timeout is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
17109
		}
17110
17111
		if ($useragent)
17112
		{
17113
			$this->useragent = (string) $useragent;
17114
		}
17115
17116
		if ($force_fsockopen)
17117
		{
17118
			$this->force_fsockopen = (string) $force_fsockopen;
0 ignored issues
show
Documentation Bug introduced by
The property $force_fsockopen was declared of type boolean, but (string) $force_fsockopen is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
17119
		}
17120
	}
17121
17122
	public function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
17123
	{
17124
		if ($tags)
0 ignored issues
show
Bug Best Practice introduced by
The expression $tags of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
17125
		{
17126
			if (is_array($tags))
17127
			{
17128
				$this->strip_htmltags = $tags;
17129
			}
17130
			else
17131
			{
17132
				$this->strip_htmltags = explode(',', $tags);
17133
			}
17134
		}
17135
		else
17136
		{
17137
			$this->strip_htmltags = false;
0 ignored issues
show
Documentation Bug introduced by
It seems like false of type false is incompatible with the declared type array of property $strip_htmltags.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
17138
		}
17139
	}
17140
17141
	public function encode_instead_of_strip($encode = false)
17142
	{
17143
		$this->encode_instead_of_strip = (bool) $encode;
17144
	}
17145
17146
	public function strip_attributes($attribs = array('bgsound', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
17147
	{
17148
		if ($attribs)
0 ignored issues
show
Bug Best Practice introduced by
The expression $attribs of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
17149
		{
17150
			if (is_array($attribs))
17151
			{
17152
				$this->strip_attributes = $attribs;
17153
			}
17154
			else
17155
			{
17156
				$this->strip_attributes = explode(',', $attribs);
17157
			}
17158
		}
17159
		else
17160
		{
17161
			$this->strip_attributes = false;
0 ignored issues
show
Documentation Bug introduced by
It seems like false of type false is incompatible with the declared type array of property $strip_attributes.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
17162
		}
17163
	}
17164
17165
	public function add_attributes($attribs = array('audio' => array('preload' => 'none'), 'iframe' => array('sandbox' => 'allow-scripts allow-same-origin'), 'video' => array('preload' => 'none')))
17166
	{
17167
		if ($attribs)
0 ignored issues
show
Bug Best Practice introduced by
The expression $attribs of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
17168
		{
17169
			if (is_array($attribs))
17170
			{
17171
				$this->add_attributes = $attribs;
17172
			}
17173
			else
17174
			{
17175
				$this->add_attributes = explode(',', $attribs);
17176
			}
17177
		}
17178
		else
17179
		{
17180
			$this->add_attributes = false;
0 ignored issues
show
Documentation Bug introduced by
It seems like false of type false is incompatible with the declared type array of property $add_attributes.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
17181
		}
17182
	}
17183
17184
	public function strip_comments($strip = false)
17185
	{
17186
		$this->strip_comments = (bool) $strip;
17187
	}
17188
17189
	public function set_output_encoding($encoding = 'UTF-8')
17190
	{
17191
		$this->output_encoding = (string) $encoding;
17192
	}
17193
17194
	/**
17195
	 * Set element/attribute key/value pairs of HTML attributes
17196
	 * containing URLs that need to be resolved relative to the feed
17197
	 *
17198
	 * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite,
17199
	 * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite,
17200
	 * |q|@cite
17201
	 *
17202
	 * @since 1.0
17203
	 * @param array|null $element_attribute Element/attribute key/value pairs, null for default
17204
	 */
17205
	public function set_url_replacements($element_attribute = null)
17206
	{
17207
		if ($element_attribute === null)
17208
		{
17209
			$element_attribute = array(
17210
				'a' => 'href',
17211
				'area' => 'href',
17212
				'blockquote' => 'cite',
17213
				'del' => 'cite',
17214
				'form' => 'action',
17215
				'img' => array(
17216
					'longdesc',
17217
					'src'
17218
				),
17219
				'input' => 'src',
17220
				'ins' => 'cite',
17221
				'q' => 'cite'
17222
			);
17223
		}
17224
		$this->replace_url_attributes = (array) $element_attribute;
17225
	}
17226
17227
	public function sanitize($data, $type, $base = '')
17228
	{
17229
		$data = trim($data);
17230
		if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
17231
		{
17232
			if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
17233
			{
17234
				if (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\/[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data))
17235
				{
17236
					$type |= SIMPLEPIE_CONSTRUCT_HTML;
17237
				}
17238
				else
17239
				{
17240
					$type |= SIMPLEPIE_CONSTRUCT_TEXT;
17241
				}
17242
			}
17243
17244
			if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
17245
			{
17246
				$data = base64_decode($data);
17247
			}
17248
17249
			if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
17250
			{
17251
17252
				if (!class_exists('DOMDocument'))
17253
				{
17254
					throw new SimplePie_Exception('DOMDocument not found, unable to use sanitizer');
17255
				}
17256
				$document = new DOMDocument();
17257
				$document->encoding = 'UTF-8';
17258
17259
				$data = $this->preprocess($data, $type);
17260
17261
				set_error_handler(array('SimplePie_Misc', 'silence_errors'));
17262
				$document->loadHTML($data);
17263
				restore_error_handler();
17264
17265
				$xpath = new DOMXPath($document);
17266
17267
				// Strip comments
17268
				if ($this->strip_comments)
17269
				{
17270
					$comments = $xpath->query('//comment()');
17271
17272
					foreach ($comments as $comment)
17273
					{
17274
						$comment->parentNode->removeChild($comment);
17275
					}
17276
				}
17277
17278
				// Strip out HTML tags and attributes that might cause various security problems.
17279
				// Based on recommendations by Mark Pilgrim at:
17280
				// http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
17281
				if ($this->strip_htmltags)
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->strip_htmltags of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
17282
				{
17283
					foreach ($this->strip_htmltags as $tag)
17284
					{
17285
						$this->strip_tag($tag, $document, $xpath, $type);
17286
					}
17287
				}
17288
17289
				if ($this->strip_attributes)
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->strip_attributes of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
17290
				{
17291
					foreach ($this->strip_attributes as $attrib)
17292
					{
17293
						$this->strip_attr($attrib, $xpath);
17294
					}
17295
				}
17296
17297
				if ($this->add_attributes)
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->add_attributes of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
17298
				{
17299
					foreach ($this->add_attributes as $tag => $valuePairs)
17300
					{
17301
						$this->add_attr($tag, $valuePairs, $document);
17302
					}
17303
				}
17304
17305
				// Replace relative URLs
17306
				$this->base = $base;
17307
				foreach ($this->replace_url_attributes as $element => $attributes)
17308
				{
17309
					$this->replace_urls($document, $element, $attributes);
17310
				}
17311
17312
				// If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
17313
				if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
17314
				{
17315
					$images = $document->getElementsByTagName('img');
17316
					foreach ($images as $img)
17317
					{
17318
						if ($img->hasAttribute('src'))
17319
						{
17320
							$image_url = call_user_func($this->cache_name_function, $img->getAttribute('src'));
17321
							$cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, $image_url, 'spi'));
17322
17323
							if ($cache->load())
17324
							{
17325
								$img->setAttribute('src', $this->image_handler . $image_url);
17326
							}
17327
							else
17328
							{
17329
								$file = $this->registry->create('File', array($img->getAttribute('src'), $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen));
17330
								$headers = $file->headers;
0 ignored issues
show
Unused Code introduced by
$headers is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
17331
17332
								if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
17333
								{
17334
									if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
17335
									{
17336
										$img->setAttribute('src', $this->image_handler . $image_url);
17337
									}
17338
									else
17339
									{
17340
										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);
17341
									}
17342
								}
17343
							}
17344
						}
17345
					}
17346
				}
17347
17348
				// Get content node
17349
				$div = $document->getElementsByTagName('body')->item(0)->firstChild;
17350
				// Finally, convert to a HTML string
17351
				if (version_compare(PHP_VERSION, '5.3.6', '>='))
17352
				{
17353
					$data = trim($document->saveHTML($div));
17354
				}
17355
				else
17356
				{
17357
					$data = trim($document->saveXML($div));
17358
				}
17359
17360
				if ($this->remove_div)
17361
				{
17362
					$data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
17363
					$data = preg_replace('/<\/div>$/', '', $data);
17364
				}
17365
				else
17366
				{
17367
					$data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
17368
				}
17369
			}
17370
17371
			if ($type & SIMPLEPIE_CONSTRUCT_IRI)
17372
			{
17373
				$absolute = $this->registry->call('Misc', 'absolutize_url', array($data, $base));
17374
				if ($absolute !== false)
17375
				{
17376
					$data = $absolute;
17377
				}
17378
			}
17379
17380
			if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
17381
			{
17382
				$data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
17383
			}
17384
17385
			if ($this->output_encoding !== 'UTF-8')
17386
			{
17387
				$data = $this->registry->call('Misc', 'change_encoding', array($data, 'UTF-8', $this->output_encoding));
17388
			}
17389
		}
17390
		return $data;
17391
	}
17392
17393
	protected function preprocess($html, $type)
17394
	{
17395
		$ret = '';
17396
		$html = preg_replace('%</?(?:html|body)[^>]*?'.'>%is', '', $html);
17397
		if ($type & ~SIMPLEPIE_CONSTRUCT_XHTML)
17398
		{
17399
			// Atom XHTML constructs are wrapped with a div by default
17400
			// Note: No protection if $html contains a stray </div>!
17401
			$html = '<div>' . $html . '</div>';
17402
			$ret .= '<!DOCTYPE html>';
17403
			$content_type = 'text/html';
17404
		}
17405
		else
17406
		{
17407
			$ret .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
17408
			$content_type = 'application/xhtml+xml';
17409
		}
17410
17411
		$ret .= '<html><head>';
17412
		$ret .= '<meta http-equiv="Content-Type" content="' . $content_type . '; charset=utf-8" />';
17413
		$ret .= '</head><body>' . $html . '</body></html>';
17414
		return $ret;
17415
	}
17416
17417
	public function replace_urls($document, $tag, $attributes)
17418
	{
17419
		if (!is_array($attributes))
17420
		{
17421
			$attributes = array($attributes);
17422
		}
17423
17424
		if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
17425
		{
17426
			$elements = $document->getElementsByTagName($tag);
17427
			foreach ($elements as $element)
17428
			{
17429
				foreach ($attributes as $attribute)
17430
				{
17431
					if ($element->hasAttribute($attribute))
17432
					{
17433
						$value = $this->registry->call('Misc', 'absolutize_url', array($element->getAttribute($attribute), $this->base));
17434
						if ($value !== false)
17435
						{
17436
							$element->setAttribute($attribute, $value);
17437
						}
17438
					}
17439
				}
17440
			}
17441
		}
17442
	}
17443
17444
	public function do_strip_htmltags($match)
17445
	{
17446
		if ($this->encode_instead_of_strip)
17447
		{
17448
			if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
17449
			{
17450
				$match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
17451
				$match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
17452
				return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
17453
			}
17454
			else
17455
			{
17456
				return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
17457
			}
17458
		}
17459
		elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
17460
		{
17461
			return $match[4];
17462
		}
17463
		else
17464
		{
17465
			return '';
17466
		}
17467
	}
17468
17469
	protected function strip_tag($tag, $document, $xpath, $type)
17470
	{
17471
		$elements = $xpath->query('body//' . $tag);
17472
		if ($this->encode_instead_of_strip)
17473
		{
17474
			foreach ($elements as $element)
17475
			{
17476
				$fragment = $document->createDocumentFragment();
17477
17478
				// For elements which aren't script or style, include the tag itself
17479
				if (!in_array($tag, array('script', 'style')))
17480
				{
17481
					$text = '<' . $tag;
17482
					if ($element->hasAttributes())
17483
					{
17484
						$attrs = array();
17485
						foreach ($element->attributes as $name => $attr)
17486
						{
17487
							$value = $attr->value;
17488
17489
							// In XHTML, empty values should never exist, so we repeat the value
17490
							if (empty($value) && ($type & SIMPLEPIE_CONSTRUCT_XHTML))
17491
							{
17492
								$value = $name;
0 ignored issues
show
Unused Code introduced by
$value is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
17493
							}
17494
							// For HTML, empty is fine
17495
							elseif (empty($value) && ($type & SIMPLEPIE_CONSTRUCT_HTML))
17496
							{
17497
								$attrs[] = $name;
17498
								continue;
17499
							}
17500
17501
							// Standard attribute text
17502
							$attrs[] = $name . '="' . $attr->value . '"';
17503
						}
17504
						$text .= ' ' . implode(' ', $attrs);
17505
					}
17506
					$text .= '>';
17507
					$fragment->appendChild(new DOMText($text));
17508
				}
17509
17510
				$number = $element->childNodes->length;
17511
				for ($i = $number; $i > 0; $i--)
17512
				{
17513
					$child = $element->childNodes->item(0);
17514
					$fragment->appendChild($child);
17515
				}
17516
17517
				if (!in_array($tag, array('script', 'style')))
17518
				{
17519
					$fragment->appendChild(new DOMText('</' . $tag . '>'));
17520
				}
17521
17522
				$element->parentNode->replaceChild($fragment, $element);
17523
			}
17524
17525
			return;
17526
		}
17527
		elseif (in_array($tag, array('script', 'style')))
17528
		{
17529
			foreach ($elements as $element)
17530
			{
17531
				$element->parentNode->removeChild($element);
17532
			}
17533
17534
			return;
17535
		}
17536
		else
17537
		{
17538
			foreach ($elements as $element)
17539
			{
17540
				$fragment = $document->createDocumentFragment();
17541
				$number = $element->childNodes->length;
17542
				for ($i = $number; $i > 0; $i--)
17543
				{
17544
					$child = $element->childNodes->item(0);
17545
					$fragment->appendChild($child);
17546
				}
17547
17548
				$element->parentNode->replaceChild($fragment, $element);
17549
			}
17550
		}
17551
	}
17552
17553
	protected function strip_attr($attrib, $xpath)
17554
	{
17555
		$elements = $xpath->query('//*[@' . $attrib . ']');
17556
17557
		foreach ($elements as $element)
17558
		{
17559
			$element->removeAttribute($attrib);
17560
		}
17561
	}
17562
17563
	protected function add_attr($tag, $valuePairs, $document)
17564
	{
17565
		$elements = $document->getElementsByTagName($tag);
17566
		foreach ($elements as $element)
17567
		{
17568
			foreach ($valuePairs as $attrib => $value)
17569
			{
17570
				$element->setAttribute($attrib, $value);
17571
			}
17572
		}
17573
	}
17574
}
17575
17576
/**
17577
 * Handles `<atom:source>`
17578
 *
17579
 * Used by {@see SimplePie_Item::get_source()}
17580
 *
17581
 * This class can be overloaded with {@see SimplePie::set_source_class()}
17582
 *
17583
 * @package SimplePie
17584
 * @subpackage API
17585
 */
17586
class SimplePie_Source
17587
{
17588
	var $item;
17589
	var $data = array();
17590
	protected $registry;
17591
17592
	public function __construct($item, $data)
17593
	{
17594
		$this->item = $item;
17595
		$this->data = $data;
17596
	}
17597
17598
	public function set_registry(SimplePie_Registry $registry)
17599
	{
17600
		$this->registry = $registry;
17601
	}
17602
17603
	public function __toString()
17604
	{
17605
		return md5(serialize($this->data));
17606
	}
17607
17608
	public function get_source_tags($namespace, $tag)
17609
	{
17610
		if (isset($this->data['child'][$namespace][$tag]))
17611
		{
17612
			return $this->data['child'][$namespace][$tag];
17613
		}
17614
		else
17615
		{
17616
			return null;
17617
		}
17618
	}
17619
17620
	public function get_base($element = array())
17621
	{
17622
		return $this->item->get_base($element);
17623
	}
17624
17625
	public function sanitize($data, $type, $base = '')
17626
	{
17627
		return $this->item->sanitize($data, $type, $base);
17628
	}
17629
17630
	public function get_item()
17631
	{
17632
		return $this->item;
17633
	}
17634
17635
	public function get_title()
17636
	{
17637
		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
17638
		{
17639
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
17640
		}
17641
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
17642
		{
17643
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
17644
		}
17645
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
17646
		{
17647
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
17648
		}
17649
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
17650
		{
17651
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
17652
		}
17653
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
17654
		{
17655
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
17656
		}
17657
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
17658
		{
17659
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
17660
		}
17661
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
17662
		{
17663
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
17664
		}
17665
		else
17666
		{
17667
			return null;
17668
		}
17669
	}
17670
17671
	public function get_category($key = 0)
17672
	{
17673
		$categories = $this->get_categories();
17674
		if (isset($categories[$key]))
17675
		{
17676
			return $categories[$key];
17677
		}
17678
		else
17679
		{
17680
			return null;
17681
		}
17682
	}
17683
17684
	public function get_categories()
17685
	{
17686
		$categories = array();
17687
17688
		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
17689
		{
17690
			$term = null;
17691
			$scheme = null;
17692
			$label = null;
17693
			if (isset($category['attribs']['']['term']))
17694
			{
17695
				$term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
17696
			}
17697
			if (isset($category['attribs']['']['scheme']))
17698
			{
17699
				$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
17700
			}
17701
			if (isset($category['attribs']['']['label']))
17702
			{
17703
				$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
17704
			}
17705
			$categories[] = $this->registry->create('Category', array($term, $scheme, $label));
17706
		}
17707
		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
17708
		{
17709
			// This is really the label, but keep this as the term also for BC.
17710
			// Label will also work on retrieving because that falls back to term.
17711
			$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
17712
			if (isset($category['attribs']['']['domain']))
17713
			{
17714
				$scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
17715
			}
17716
			else
17717
			{
17718
				$scheme = null;
17719
			}
17720
			$categories[] = $this->registry->create('Category', array($term, $scheme, null));
17721
		}
17722
		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
17723
		{
17724
			$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
17725
		}
17726
		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
17727
		{
17728
			$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
17729
		}
17730
17731
		if (!empty($categories))
17732
		{
17733
			return array_unique($categories);
17734
		}
17735
		else
17736
		{
17737
			return null;
17738
		}
17739
	}
17740
17741
	public function get_author($key = 0)
17742
	{
17743
		$authors = $this->get_authors();
17744
		if (isset($authors[$key]))
17745
		{
17746
			return $authors[$key];
17747
		}
17748
		else
17749
		{
17750
			return null;
17751
		}
17752
	}
17753
17754
	public function get_authors()
17755
	{
17756
		$authors = array();
17757
		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
17758
		{
17759
			$name = null;
17760
			$uri = null;
17761
			$email = null;
17762
			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
17763
			{
17764
				$name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
17765
			}
17766
			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
17767
			{
17768
				$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]));
17769
			}
17770
			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
17771
			{
17772
				$email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
17773
			}
17774
			if ($name !== null || $email !== null || $uri !== null)
17775
			{
17776
				$authors[] = $this->registry->create('Author', array($name, $uri, $email));
17777
			}
17778
		}
17779
		if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
17780
		{
17781
			$name = null;
17782
			$url = null;
17783
			$email = null;
17784
			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
17785
			{
17786
				$name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
17787
			}
17788
			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
17789
			{
17790
				$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]));
17791
			}
17792
			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
17793
			{
17794
				$email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
17795
			}
17796
			if ($name !== null || $email !== null || $url !== null)
17797
			{
17798
				$authors[] = $this->registry->create('Author', array($name, $url, $email));
17799
			}
17800
		}
17801
		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
17802
		{
17803
			$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
17804
		}
17805
		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
17806
		{
17807
			$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
17808
		}
17809
		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
17810
		{
17811
			$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
17812
		}
17813
17814
		if (!empty($authors))
17815
		{
17816
			return array_unique($authors);
17817
		}
17818
		else
17819
		{
17820
			return null;
17821
		}
17822
	}
17823
17824
	public function get_contributor($key = 0)
17825
	{
17826
		$contributors = $this->get_contributors();
17827
		if (isset($contributors[$key]))
17828
		{
17829
			return $contributors[$key];
17830
		}
17831
		else
17832
		{
17833
			return null;
17834
		}
17835
	}
17836
17837
	public function get_contributors()
17838
	{
17839
		$contributors = array();
17840
		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
17841
		{
17842
			$name = null;
17843
			$uri = null;
17844
			$email = null;
17845
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
17846
			{
17847
				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
17848
			}
17849
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
17850
			{
17851
				$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]));
17852
			}
17853
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
17854
			{
17855
				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
17856
			}
17857
			if ($name !== null || $email !== null || $uri !== null)
17858
			{
17859
				$contributors[] = $this->registry->create('Author', array($name, $uri, $email));
17860
			}
17861
		}
17862
		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
17863
		{
17864
			$name = null;
17865
			$url = null;
17866
			$email = null;
17867
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
17868
			{
17869
				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
17870
			}
17871
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
17872
			{
17873
				$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]));
17874
			}
17875
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
17876
			{
17877
				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
17878
			}
17879
			if ($name !== null || $email !== null || $url !== null)
17880
			{
17881
				$contributors[] = $this->registry->create('Author', array($name, $url, $email));
17882
			}
17883
		}
17884
17885
		if (!empty($contributors))
17886
		{
17887
			return array_unique($contributors);
17888
		}
17889
		else
17890
		{
17891
			return null;
17892
		}
17893
	}
17894
17895
	public function get_link($key = 0, $rel = 'alternate')
17896
	{
17897
		$links = $this->get_links($rel);
17898
		if (isset($links[$key]))
17899
		{
17900
			return $links[$key];
17901
		}
17902
		else
17903
		{
17904
			return null;
17905
		}
17906
	}
17907
17908
	/**
17909
	 * Added for parity between the parent-level and the item/entry-level.
17910
	 */
17911
	public function get_permalink()
17912
	{
17913
		return $this->get_link(0);
17914
	}
17915
17916
	public function get_links($rel = 'alternate')
17917
	{
17918
		if (!isset($this->data['links']))
17919
		{
17920
			$this->data['links'] = array();
17921
			if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
17922
			{
17923
				foreach ($links as $link)
17924
				{
17925
					if (isset($link['attribs']['']['href']))
17926
					{
17927
						$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
17928
						$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
17929
					}
17930
				}
17931
			}
17932
			if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
17933
			{
17934
				foreach ($links as $link)
17935
				{
17936
					if (isset($link['attribs']['']['href']))
17937
					{
17938
						$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
17939
						$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
17940
17941
					}
17942
				}
17943
			}
17944
			if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
17945
			{
17946
				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
17947
			}
17948
			if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
17949
			{
17950
				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
17951
			}
17952
			if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
17953
			{
17954
				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
17955
			}
17956
17957
			$keys = array_keys($this->data['links']);
17958
			foreach ($keys as $key)
17959
			{
17960
				if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))
17961
				{
17962
					if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
17963
					{
17964
						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
17965
						$this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
17966
					}
17967
					else
17968
					{
17969
						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
17970
					}
17971
				}
17972
				elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
17973
				{
17974
					$this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
17975
				}
17976
				$this->data['links'][$key] = array_unique($this->data['links'][$key]);
17977
			}
17978
		}
17979
17980
		if (isset($this->data['links'][$rel]))
17981
		{
17982
			return $this->data['links'][$rel];
17983
		}
17984
		else
17985
		{
17986
			return null;
17987
		}
17988
	}
17989
17990
	public function get_description()
17991
	{
17992
		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
17993
		{
17994
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
17995
		}
17996
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
17997
		{
17998
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
17999
		}
18000
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
18001
		{
18002
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
18003
		}
18004
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
18005
		{
18006
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
18007
		}
18008
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
18009
		{
18010
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
18011
		}
18012
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
18013
		{
18014
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
18015
		}
18016
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
18017
		{
18018
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
18019
		}
18020
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
18021
		{
18022
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
18023
		}
18024
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
18025
		{
18026
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
18027
		}
18028
		else
18029
		{
18030
			return null;
18031
		}
18032
	}
18033
18034
	public function get_copyright()
18035
	{
18036
		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
18037
		{
18038
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
18039
		}
18040
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
18041
		{
18042
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
18043
		}
18044
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
18045
		{
18046
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
18047
		}
18048
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
18049
		{
18050
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
18051
		}
18052
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
18053
		{
18054
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
18055
		}
18056
		else
18057
		{
18058
			return null;
18059
		}
18060
	}
18061
18062
	public function get_language()
18063
	{
18064
		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
18065
		{
18066
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
18067
		}
18068
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
18069
		{
18070
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
18071
		}
18072
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
18073
		{
18074
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
18075
		}
18076
		elseif (isset($this->data['xml_lang']))
18077
		{
18078
			return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
18079
		}
18080
		else
18081
		{
18082
			return null;
18083
		}
18084
	}
18085
18086
	public function get_latitude()
18087
	{
18088
		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
18089
		{
18090
			return (float) $return[0]['data'];
18091
		}
18092
		elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
18093
		{
18094
			return (float) $match[1];
18095
		}
18096
		else
18097
		{
18098
			return null;
18099
		}
18100
	}
18101
18102
	public function get_longitude()
18103
	{
18104
		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
18105
		{
18106
			return (float) $return[0]['data'];
18107
		}
18108
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
18109
		{
18110
			return (float) $return[0]['data'];
18111
		}
18112
		elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
18113
		{
18114
			return (float) $match[2];
18115
		}
18116
		else
18117
		{
18118
			return null;
18119
		}
18120
	}
18121
18122
	public function get_image_url()
18123
	{
18124
		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
18125
		{
18126
			return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
18127
		}
18128
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
18129
		{
18130
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
18131
		}
18132
		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
18133
		{
18134
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
18135
		}
18136
		else
18137
		{
18138
			return null;
18139
		}
18140
	}
18141
}
18142
18143
/**
18144
 * Parses the XML Declaration
18145
 *
18146
 * @package SimplePie
18147
 * @subpackage Parsing
18148
 */
18149
class SimplePie_XML_Declaration_Parser
18150
{
18151
	/**
18152
	 * XML Version
18153
	 *
18154
	 * @access public
18155
	 * @var string
18156
	 */
18157
	var $version = '1.0';
18158
18159
	/**
18160
	 * Encoding
18161
	 *
18162
	 * @access public
18163
	 * @var string
18164
	 */
18165
	var $encoding = 'UTF-8';
18166
18167
	/**
18168
	 * Standalone
18169
	 *
18170
	 * @access public
18171
	 * @var bool
18172
	 */
18173
	var $standalone = false;
18174
18175
	/**
18176
	 * Current state of the state machine
18177
	 *
18178
	 * @access private
18179
	 * @var string
18180
	 */
18181
	var $state = 'before_version_name';
18182
18183
	/**
18184
	 * Input data
18185
	 *
18186
	 * @access private
18187
	 * @var string
18188
	 */
18189
	var $data = '';
18190
18191
	/**
18192
	 * Input data length (to avoid calling strlen() everytime this is needed)
18193
	 *
18194
	 * @access private
18195
	 * @var int
18196
	 */
18197
	var $data_length = 0;
18198
18199
	/**
18200
	 * Current position of the pointer
18201
	 *
18202
	 * @var int
18203
	 * @access private
18204
	 */
18205
	var $position = 0;
18206
18207
	/**
18208
	 * Create an instance of the class with the input data
18209
	 *
18210
	 * @access public
18211
	 * @param string $data Input data
18212
	 */
18213
	public function __construct($data)
18214
	{
18215
		$this->data = $data;
18216
		$this->data_length = strlen($this->data);
18217
	}
18218
18219
	/**
18220
	 * Parse the input data
18221
	 *
18222
	 * @access public
18223
	 * @return bool true on success, false on failure
18224
	 */
18225
	public function parse()
18226
	{
18227
		while ($this->state && $this->state !== 'emit' && $this->has_data())
18228
		{
18229
			$state = $this->state;
18230
			$this->$state();
18231
		}
18232
		$this->data = '';
18233
		if ($this->state === 'emit')
18234
		{
18235
			return true;
18236
		}
18237
		else
18238
		{
18239
			$this->version = '';
18240
			$this->encoding = '';
18241
			$this->standalone = '';
0 ignored issues
show
Documentation Bug introduced by
The property $standalone was declared of type boolean, but '' is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
18242
			return false;
18243
		}
18244
	}
18245
18246
	/**
18247
	 * Check whether there is data beyond the pointer
18248
	 *
18249
	 * @access private
18250
	 * @return bool true if there is further data, false if not
18251
	 */
18252
	public function has_data()
18253
	{
18254
		return (bool) ($this->position < $this->data_length);
18255
	}
18256
18257
	/**
18258
	 * Advance past any whitespace
18259
	 *
18260
	 * @return int Number of whitespace characters passed
18261
	 */
18262
	public function skip_whitespace()
18263
	{
18264
		$whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
18265
		$this->position += $whitespace;
18266
		return $whitespace;
18267
	}
18268
18269
	/**
18270
	 * Read value
18271
	 */
18272
	public function get_value()
18273
	{
18274
		$quote = substr($this->data, $this->position, 1);
18275
		if ($quote === '"' || $quote === "'")
18276
		{
18277
			$this->position++;
18278
			$len = strcspn($this->data, $quote, $this->position);
18279
			if ($this->has_data())
18280
			{
18281
				$value = substr($this->data, $this->position, $len);
18282
				$this->position += $len + 1;
18283
				return $value;
18284
			}
18285
		}
18286
		return false;
18287
	}
18288
18289
	public function before_version_name()
18290
	{
18291
		if ($this->skip_whitespace())
18292
		{
18293
			$this->state = 'version_name';
18294
		}
18295
		else
18296
		{
18297
			$this->state = false;
0 ignored issues
show
Documentation Bug introduced by
The property $state was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
18298
		}
18299
	}
18300
18301
	public function version_name()
18302
	{
18303
		if (substr($this->data, $this->position, 7) === 'version')
18304
		{
18305
			$this->position += 7;
18306
			$this->skip_whitespace();
18307
			$this->state = 'version_equals';
18308
		}
18309
		else
18310
		{
18311
			$this->state = false;
0 ignored issues
show
Documentation Bug introduced by
The property $state was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
18312
		}
18313
	}
18314
18315
	public function version_equals()
18316
	{
18317
		if (substr($this->data, $this->position, 1) === '=')
18318
		{
18319
			$this->position++;
18320
			$this->skip_whitespace();
18321
			$this->state = 'version_value';
18322
		}
18323
		else
18324
		{
18325
			$this->state = false;
0 ignored issues
show
Documentation Bug introduced by
The property $state was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
18326
		}
18327
	}
18328
18329
	public function version_value()
18330
	{
18331
		if ($this->version = $this->get_value())
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->get_value() can also be of type false. However, the property $version is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
18332
		{
18333
			$this->skip_whitespace();
18334
			if ($this->has_data())
18335
			{
18336
				$this->state = 'encoding_name';
18337
			}
18338
			else
18339
			{
18340
				$this->state = 'emit';
18341
			}
18342
		}
18343
		else
18344
		{
18345
			$this->state = false;
0 ignored issues
show
Documentation Bug introduced by
The property $state was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
18346
		}
18347
	}
18348
18349
	public function encoding_name()
18350
	{
18351
		if (substr($this->data, $this->position, 8) === 'encoding')
18352
		{
18353
			$this->position += 8;
18354
			$this->skip_whitespace();
18355
			$this->state = 'encoding_equals';
18356
		}
18357
		else
18358
		{
18359
			$this->state = 'standalone_name';
18360
		}
18361
	}
18362
18363
	public function encoding_equals()
18364
	{
18365
		if (substr($this->data, $this->position, 1) === '=')
18366
		{
18367
			$this->position++;
18368
			$this->skip_whitespace();
18369
			$this->state = 'encoding_value';
18370
		}
18371
		else
18372
		{
18373
			$this->state = false;
0 ignored issues
show
Documentation Bug introduced by
The property $state was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
18374
		}
18375
	}
18376
18377
	public function encoding_value()
18378
	{
18379
		if ($this->encoding = $this->get_value())
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->get_value() can also be of type false. However, the property $encoding is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
18380
		{
18381
			$this->skip_whitespace();
18382
			if ($this->has_data())
18383
			{
18384
				$this->state = 'standalone_name';
18385
			}
18386
			else
18387
			{
18388
				$this->state = 'emit';
18389
			}
18390
		}
18391
		else
18392
		{
18393
			$this->state = false;
0 ignored issues
show
Documentation Bug introduced by
The property $state was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
18394
		}
18395
	}
18396
18397
	public function standalone_name()
18398
	{
18399
		if (substr($this->data, $this->position, 10) === 'standalone')
18400
		{
18401
			$this->position += 10;
18402
			$this->skip_whitespace();
18403
			$this->state = 'standalone_equals';
18404
		}
18405
		else
18406
		{
18407
			$this->state = false;
0 ignored issues
show
Documentation Bug introduced by
The property $state was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
18408
		}
18409
	}
18410
18411
	public function standalone_equals()
18412
	{
18413
		if (substr($this->data, $this->position, 1) === '=')
18414
		{
18415
			$this->position++;
18416
			$this->skip_whitespace();
18417
			$this->state = 'standalone_value';
18418
		}
18419
		else
18420
		{
18421
			$this->state = false;
0 ignored issues
show
Documentation Bug introduced by
The property $state was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
18422
		}
18423
	}
18424
18425
	public function standalone_value()
18426
	{
18427
		if ($standalone = $this->get_value())
18428
		{
18429
			switch ($standalone)
18430
			{
18431
				case 'yes':
18432
					$this->standalone = true;
18433
					break;
18434
18435
				case 'no':
18436
					$this->standalone = false;
18437
					break;
18438
18439
				default:
18440
					$this->state = false;
0 ignored issues
show
Documentation Bug introduced by
The property $state was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
18441
					return;
18442
			}
18443
18444
			$this->skip_whitespace();
18445
			if ($this->has_data())
18446
			{
18447
				$this->state = false;
18448
			}
18449
			else
18450
			{
18451
				$this->state = 'emit';
18452
			}
18453
		}
18454
		else
18455
		{
18456
			$this->state = false;
18457
		}
18458
	}
18459
}
18460
18461
/**
18462
 * Decode 'gzip' encoded HTTP data
18463
 *
18464
 * @package SimplePie
18465
 * @subpackage HTTP
18466
 * @link http://www.gzip.org/format.txt
18467
 */
18468
class SimplePie_gzdecode
18469
{
18470
	/**
18471
	 * Compressed data
18472
	 *
18473
	 * @access private
18474
	 * @var string
18475
	 * @see gzdecode::$data
18476
	 */
18477
	var $compressed_data;
18478
18479
	/**
18480
	 * Size of compressed data
18481
	 *
18482
	 * @access private
18483
	 * @var int
18484
	 */
18485
	var $compressed_size;
18486
18487
	/**
18488
	 * Minimum size of a valid gzip string
18489
	 *
18490
	 * @access private
18491
	 * @var int
18492
	 */
18493
	var $min_compressed_size = 18;
18494
18495
	/**
18496
	 * Current position of pointer
18497
	 *
18498
	 * @access private
18499
	 * @var int
18500
	 */
18501
	var $position = 0;
18502
18503
	/**
18504
	 * Flags (FLG)
18505
	 *
18506
	 * @access private
18507
	 * @var int
18508
	 */
18509
	var $flags;
18510
18511
	/**
18512
	 * Uncompressed data
18513
	 *
18514
	 * @access public
18515
	 * @see gzdecode::$compressed_data
18516
	 * @var string
18517
	 */
18518
	var $data;
18519
18520
	/**
18521
	 * Modified time
18522
	 *
18523
	 * @access public
18524
	 * @var int
18525
	 */
18526
	var $MTIME;
18527
18528
	/**
18529
	 * Extra Flags
18530
	 *
18531
	 * @access public
18532
	 * @var int
18533
	 */
18534
	var $XFL;
18535
18536
	/**
18537
	 * Operating System
18538
	 *
18539
	 * @access public
18540
	 * @var int
18541
	 */
18542
	var $OS;
18543
18544
	/**
18545
	 * Subfield ID 1
18546
	 *
18547
	 * @access public
18548
	 * @see gzdecode::$extra_field
18549
	 * @see gzdecode::$SI2
18550
	 * @var string
18551
	 */
18552
	var $SI1;
18553
18554
	/**
18555
	 * Subfield ID 2
18556
	 *
18557
	 * @access public
18558
	 * @see gzdecode::$extra_field
18559
	 * @see gzdecode::$SI1
18560
	 * @var string
18561
	 */
18562
	var $SI2;
18563
18564
	/**
18565
	 * Extra field content
18566
	 *
18567
	 * @access public
18568
	 * @see gzdecode::$SI1
18569
	 * @see gzdecode::$SI2
18570
	 * @var string
18571
	 */
18572
	var $extra_field;
18573
18574
	/**
18575
	 * Original filename
18576
	 *
18577
	 * @access public
18578
	 * @var string
18579
	 */
18580
	var $filename;
18581
18582
	/**
18583
	 * Human readable comment
18584
	 *
18585
	 * @access public
18586
	 * @var string
18587
	 */
18588
	var $comment;
18589
18590
	/**
18591
	 * Don't allow anything to be set
18592
	 *
18593
	 * @param string $name
18594
	 * @param mixed $value
18595
	 */
18596
	public function __set($name, $value)
18597
	{
18598
		trigger_error("Cannot write property $name", E_USER_ERROR);
18599
	}
18600
18601
	/**
18602
	 * Set the compressed string and related properties
18603
	 *
18604
	 * @param string $data
18605
	 */
18606
	public function __construct($data)
18607
	{
18608
		$this->compressed_data = $data;
18609
		$this->compressed_size = strlen($data);
18610
	}
18611
18612
	/**
18613
	 * Decode the GZIP stream
18614
	 *
18615
	 * @return bool Successfulness
18616
	 */
18617
	public function parse()
18618
	{
18619
		if ($this->compressed_size >= $this->min_compressed_size)
18620
		{
18621
			// Check ID1, ID2, and CM
18622
			if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
18623
			{
18624
				return false;
18625
			}
18626
18627
			// Get the FLG (FLaGs)
18628
			$this->flags = ord($this->compressed_data[3]);
18629
18630
			// FLG bits above (1 << 4) are reserved
18631
			if ($this->flags > 0x1F)
18632
			{
18633
				return false;
18634
			}
18635
18636
			// Advance the pointer after the above
18637
			$this->position += 4;
18638
18639
			// MTIME
18640
			$mtime = substr($this->compressed_data, $this->position, 4);
18641
			// Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
18642
			if (current(unpack('S', "\x00\x01")) === 1)
18643
			{
18644
				$mtime = strrev($mtime);
18645
			}
18646
			$this->MTIME = current(unpack('l', $mtime));
18647
			$this->position += 4;
18648
18649
			// Get the XFL (eXtra FLags)
18650
			$this->XFL = ord($this->compressed_data[$this->position++]);
18651
18652
			// Get the OS (Operating System)
18653
			$this->OS = ord($this->compressed_data[$this->position++]);
18654
18655
			// Parse the FEXTRA
18656
			if ($this->flags & 4)
18657
			{
18658
				// Read subfield IDs
18659
				$this->SI1 = $this->compressed_data[$this->position++];
18660
				$this->SI2 = $this->compressed_data[$this->position++];
18661
18662
				// SI2 set to zero is reserved for future use
18663
				if ($this->SI2 === "\x00")
18664
				{
18665
					return false;
18666
				}
18667
18668
				// Get the length of the extra field
18669
				$len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
18670
				$this->position += 2;
18671
18672
				// Check the length of the string is still valid
18673
				$this->min_compressed_size += $len + 4;
18674
				if ($this->compressed_size >= $this->min_compressed_size)
18675
				{
18676
					// Set the extra field to the given data
18677
					$this->extra_field = substr($this->compressed_data, $this->position, $len);
18678
					$this->position += $len;
18679
				}
18680
				else
18681
				{
18682
					return false;
18683
				}
18684
			}
18685
18686
			// Parse the FNAME
18687
			if ($this->flags & 8)
18688
			{
18689
				// Get the length of the filename
18690
				$len = strcspn($this->compressed_data, "\x00", $this->position);
18691
18692
				// Check the length of the string is still valid
18693
				$this->min_compressed_size += $len + 1;
18694
				if ($this->compressed_size >= $this->min_compressed_size)
18695
				{
18696
					// Set the original filename to the given string
18697
					$this->filename = substr($this->compressed_data, $this->position, $len);
18698
					$this->position += $len + 1;
18699
				}
18700
				else
18701
				{
18702
					return false;
18703
				}
18704
			}
18705
18706
			// Parse the FCOMMENT
18707
			if ($this->flags & 16)
18708
			{
18709
				// Get the length of the comment
18710
				$len = strcspn($this->compressed_data, "\x00", $this->position);
18711
18712
				// Check the length of the string is still valid
18713
				$this->min_compressed_size += $len + 1;
18714
				if ($this->compressed_size >= $this->min_compressed_size)
18715
				{
18716
					// Set the original comment to the given string
18717
					$this->comment = substr($this->compressed_data, $this->position, $len);
18718
					$this->position += $len + 1;
18719
				}
18720
				else
18721
				{
18722
					return false;
18723
				}
18724
			}
18725
18726
			// Parse the FHCRC
18727
			if ($this->flags & 2)
18728
			{
18729
				// Check the length of the string is still valid
18730
				$this->min_compressed_size += $len + 2;
0 ignored issues
show
Bug introduced by
The variable $len does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
18731
				if ($this->compressed_size >= $this->min_compressed_size)
18732
				{
18733
					// Read the CRC
18734
					$crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
18735
18736
					// Check the CRC matches
18737
					if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
18738
					{
18739
						$this->position += 2;
18740
					}
18741
					else
18742
					{
18743
						return false;
18744
					}
18745
				}
18746
				else
18747
				{
18748
					return false;
18749
				}
18750
			}
18751
18752
			// Decompress the actual data
18753
			if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
18754
			{
18755
				return false;
18756
			}
18757
			else
18758
			{
18759
				$this->position = $this->compressed_size - 8;
18760
			}
18761
18762
			// Check CRC of data
18763
			$crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
0 ignored issues
show
Unused Code introduced by
$crc is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
18764
			$this->position += 4;
18765
			/*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
18766
			{
18767
				return false;
18768
			}*/
18769
18770
			// Check ISIZE of data
18771
			$isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
18772
			$this->position += 4;
18773
			if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
18774
			{
18775
				return false;
18776
			}
18777
18778
			// Wow, against all odds, we've actually got a valid gzip string
18779
			return true;
18780
		}
18781
		else
18782
		{
18783
			return false;
18784
		}
18785
	}
18786
}
18787
18788