3 * SimplePie |
3 * SimplePie |
4 * |
4 * |
5 * A PHP-Based RSS and Atom Feed Framework. |
5 * A PHP-Based RSS and Atom Feed Framework. |
6 * Takes the hard work out of managing a complete RSS/Atom solution. |
6 * Takes the hard work out of managing a complete RSS/Atom solution. |
7 * |
7 * |
8 * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors |
8 * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors |
9 * All rights reserved. |
9 * All rights reserved. |
10 * |
10 * |
11 * Redistribution and use in source and binary forms, with or without modification, are |
11 * Redistribution and use in source and binary forms, with or without modification, are |
12 * permitted provided that the following conditions are met: |
12 * permitted provided that the following conditions are met: |
13 * |
13 * |
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
33 * POSSIBILITY OF SUCH DAMAGE. |
33 * POSSIBILITY OF SUCH DAMAGE. |
34 * |
34 * |
35 * @package SimplePie |
35 * @package SimplePie |
36 * @version 1.3.1 |
36 * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue |
37 * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue |
|
38 * @author Ryan Parman |
37 * @author Ryan Parman |
39 * @author Geoffrey Sneddon |
38 * @author Sam Sneddon |
40 * @author Ryan McCue |
39 * @author Ryan McCue |
41 * @link http://simplepie.org/ SimplePie |
40 * @link http://simplepie.org/ SimplePie |
42 * @license http://www.opensource.org/licenses/bsd-license.php BSD License |
41 * @license http://www.opensource.org/licenses/bsd-license.php BSD License |
43 */ |
42 */ |
44 |
43 |
61 var $http_base; |
60 var $http_base; |
62 var $base; |
61 var $base; |
63 var $base_location = 0; |
62 var $base_location = 0; |
64 var $checked_feeds = 0; |
63 var $checked_feeds = 0; |
65 var $max_checked_feeds = 10; |
64 var $max_checked_feeds = 10; |
|
65 var $force_fsockopen = false; |
|
66 var $curl_options = array(); |
66 protected $registry; |
67 protected $registry; |
67 |
68 |
68 public function __construct(SimplePie_File $file, $timeout = 10, $useragent = null, $max_checked_feeds = 10) |
69 public function __construct(SimplePie_File $file, $timeout = 10, $useragent = null, $max_checked_feeds = 10, $force_fsockopen = false, $curl_options = array()) |
69 { |
70 { |
70 $this->file = $file; |
71 $this->file = $file; |
71 $this->useragent = $useragent; |
72 $this->useragent = $useragent; |
72 $this->timeout = $timeout; |
73 $this->timeout = $timeout; |
73 $this->max_checked_feeds = $max_checked_feeds; |
74 $this->max_checked_feeds = $max_checked_feeds; |
|
75 $this->force_fsockopen = $force_fsockopen; |
|
76 $this->curl_options = $curl_options; |
74 |
77 |
75 if (class_exists('DOMDocument')) |
78 if (class_exists('DOMDocument')) |
76 { |
79 { |
77 $this->dom = new DOMDocument(); |
80 $this->dom = new DOMDocument(); |
78 |
81 |
119 |
122 |
120 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links()) |
123 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links()) |
121 { |
124 { |
122 if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local)) |
125 if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local)) |
123 { |
126 { |
124 return $working; |
127 return $working[0]; |
125 } |
128 } |
126 |
129 |
127 if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local)) |
130 if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local)) |
128 { |
131 { |
129 return $working; |
132 return $working[0]; |
130 } |
133 } |
131 |
134 |
132 if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere)) |
135 if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere)) |
133 { |
136 { |
134 return $working; |
137 return $working[0]; |
135 } |
138 } |
136 |
139 |
137 if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere)) |
140 if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere)) |
138 { |
141 { |
139 return $working; |
142 return $working[0]; |
140 } |
143 } |
141 } |
144 } |
142 return null; |
145 return null; |
143 } |
146 } |
144 |
147 |
145 public function is_feed($file) |
148 public function is_feed($file, $check_html = false) |
146 { |
149 { |
147 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE) |
150 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE) |
148 { |
151 { |
149 $sniffer = $this->registry->create('Content_Type_Sniffer', array($file)); |
152 $sniffer = $this->registry->create('Content_Type_Sniffer', array($file)); |
150 $sniffed = $sniffer->get_type(); |
153 $sniffed = $sniffer->get_type(); |
151 if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml'))) |
154 $mime_types = array('application/rss+xml', 'application/rdf+xml', |
152 { |
155 'text/rdf', 'application/atom+xml', 'text/xml', |
153 return true; |
156 'application/xml', 'application/x-rss+xml'); |
154 } |
157 if ($check_html) |
155 else |
158 { |
156 { |
159 $mime_types[] = 'text/html'; |
157 return false; |
160 } |
158 } |
161 |
|
162 return in_array($sniffed, $mime_types); |
159 } |
163 } |
160 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL) |
164 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL) |
161 { |
165 { |
162 return true; |
166 return true; |
163 } |
167 } |
224 { |
226 { |
225 break; |
227 break; |
226 } |
228 } |
227 if ($link->hasAttribute('href') && $link->hasAttribute('rel')) |
229 if ($link->hasAttribute('href') && $link->hasAttribute('rel')) |
228 { |
230 { |
229 $rel = array_unique($this->registry->call('Misc', 'space_seperated_tokens', array(strtolower($link->getAttribute('rel'))))); |
231 $rel = array_unique($this->registry->call('Misc', 'space_separated_tokens', array(strtolower($link->getAttribute('rel'))))); |
230 $line = method_exists($link, 'getLineNo') ? $link->getLineNo() : 1; |
232 $line = method_exists($link, 'getLineNo') ? $link->getLineNo() : 1; |
231 |
233 |
232 if ($this->base_location < $line) |
234 if ($this->base_location < $line) |
233 { |
235 { |
234 $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base)); |
236 $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base)); |
240 if ($href === false) |
242 if ($href === false) |
241 { |
243 { |
242 continue; |
244 continue; |
243 } |
245 } |
244 |
246 |
245 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('application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href])) |
247 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])) |
246 { |
248 { |
247 $this->checked_feeds++; |
249 $this->checked_feeds++; |
248 $headers = array( |
250 $headers = array( |
249 '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', |
251 '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', |
250 ); |
252 ); |
251 $feed = $this->registry->create('File', array($href, $this->timeout, 5, $headers, $this->useragent)); |
253 $feed = $this->registry->create('File', array($href, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options)); |
252 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)) |
254 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)) |
253 { |
255 { |
254 $feeds[$href] = $feed; |
256 $feeds[$href] = $feed; |
255 } |
257 } |
256 } |
258 } |
257 $done[] = $href; |
259 $done[] = $href; |
273 { |
275 { |
274 if ($link->hasAttribute('href')) |
276 if ($link->hasAttribute('href')) |
275 { |
277 { |
276 $href = trim($link->getAttribute('href')); |
278 $href = trim($link->getAttribute('href')); |
277 $parsed = $this->registry->call('Misc', 'parse_url', array($href)); |
279 $parsed = $this->registry->call('Misc', 'parse_url', array($href)); |
278 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme'])) |
280 if ($parsed['scheme'] === '' || preg_match('/^(https?|feed)?$/i', $parsed['scheme'])) |
279 { |
281 { |
280 if (method_exists($link, 'getLineNo') && $this->base_location < $link->getLineNo()) |
282 if (method_exists($link, 'getLineNo') && $this->base_location < $link->getLineNo()) |
281 { |
283 { |
282 $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base)); |
284 $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base)); |
283 } |
285 } |
310 return true; |
312 return true; |
311 } |
313 } |
312 return null; |
314 return null; |
313 } |
315 } |
314 |
316 |
|
317 public function get_rel_link($rel) |
|
318 { |
|
319 if ($this->dom === null) |
|
320 { |
|
321 throw new SimplePie_Exception('DOMDocument not found, unable to use '. |
|
322 'locator'); |
|
323 } |
|
324 if (!class_exists('DOMXpath')) |
|
325 { |
|
326 throw new SimplePie_Exception('DOMXpath not found, unable to use '. |
|
327 'get_rel_link'); |
|
328 } |
|
329 |
|
330 $xpath = new DOMXpath($this->dom); |
|
331 $query = '//a[@rel and @href] | //link[@rel and @href]'; |
|
332 foreach ($xpath->query($query) as $link) |
|
333 { |
|
334 $href = trim($link->getAttribute('href')); |
|
335 $parsed = $this->registry->call('Misc', 'parse_url', array($href)); |
|
336 if ($parsed['scheme'] === '' || |
|
337 preg_match('/^https?$/i', $parsed['scheme'])) |
|
338 { |
|
339 if (method_exists($link, 'getLineNo') && |
|
340 $this->base_location < $link->getLineNo()) |
|
341 { |
|
342 $href = |
|
343 $this->registry->call('Misc', 'absolutize_url', |
|
344 array(trim($link->getAttribute('href')), |
|
345 $this->base)); |
|
346 } |
|
347 else |
|
348 { |
|
349 $href = |
|
350 $this->registry->call('Misc', 'absolutize_url', |
|
351 array(trim($link->getAttribute('href')), |
|
352 $this->http_base)); |
|
353 } |
|
354 if ($href === false) |
|
355 { |
|
356 return null; |
|
357 } |
|
358 $rel_values = explode(' ', strtolower($link->getAttribute('rel'))); |
|
359 if (in_array($rel, $rel_values)) |
|
360 { |
|
361 return $href; |
|
362 } |
|
363 } |
|
364 } |
|
365 return null; |
|
366 } |
|
367 |
315 public function extension(&$array) |
368 public function extension(&$array) |
316 { |
369 { |
317 foreach ($array as $key => $value) |
370 foreach ($array as $key => $value) |
318 { |
371 { |
319 if ($this->checked_feeds === $this->max_checked_feeds) |
372 if ($this->checked_feeds === $this->max_checked_feeds) |
325 $this->checked_feeds++; |
378 $this->checked_feeds++; |
326 |
379 |
327 $headers = array( |
380 $headers = array( |
328 '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', |
381 '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', |
329 ); |
382 ); |
330 $feed = $this->registry->create('File', array($value, $this->timeout, 5, $headers, $this->useragent)); |
383 $feed = $this->registry->create('File', array($value, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options)); |
331 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)) |
384 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)) |
332 { |
385 { |
333 return $feed; |
386 return array($feed); |
334 } |
387 } |
335 else |
388 else |
336 { |
389 { |
337 unset($array[$key]); |
390 unset($array[$key]); |
338 } |
391 } |
347 { |
400 { |
348 if ($this->checked_feeds === $this->max_checked_feeds) |
401 if ($this->checked_feeds === $this->max_checked_feeds) |
349 { |
402 { |
350 break; |
403 break; |
351 } |
404 } |
352 if (preg_match('/(rss|rdf|atom|xml)/i', $value)) |
405 if (preg_match('/(feed|rss|rdf|atom|xml)/i', $value)) |
353 { |
406 { |
354 $this->checked_feeds++; |
407 $this->checked_feeds++; |
355 $headers = array( |
408 $headers = array( |
356 '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', |
409 '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', |
357 ); |
410 ); |
358 $feed = $this->registry->create('File', array($value, $this->timeout, 5, null, $this->useragent)); |
411 $feed = $this->registry->create('File', array($value, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen, $this->curl_options)); |
359 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)) |
412 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)) |
360 { |
413 { |
361 return $feed; |
414 return array($feed); |
362 } |
415 } |
363 else |
416 else |
364 { |
417 { |
365 unset($array[$key]); |
418 unset($array[$key]); |
366 } |
419 } |
367 } |
420 } |
368 } |
421 } |
369 return null; |
422 return null; |
370 } |
423 } |
371 } |
424 } |
372 |
|