]> git.immae.eu Git - github/wallabag/wallabag.git/blob - inc/3rdparty/simplepie/SimplePie/Locator.php
Merge pull request #181 from inthepoche/dev
[github/wallabag/wallabag.git] / inc / 3rdparty / simplepie / SimplePie / Locator.php
1 <?php
2 /**
3 * SimplePie
4 *
5 * A PHP-Based RSS and Atom Feed Framework.
6 * Takes the hard work out of managing a complete RSS/Atom solution.
7 *
8 * Copyright (c) 2004-2009, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without modification, are
12 * permitted provided that the following conditions are met:
13 *
14 * * Redistributions of source code must retain the above copyright notice, this list of
15 * conditions and the following disclaimer.
16 *
17 * * Redistributions in binary form must reproduce the above copyright notice, this list
18 * of conditions and the following disclaimer in the documentation and/or other materials
19 * provided with the distribution.
20 *
21 * * Neither the name of the SimplePie Team nor the names of its contributors may be used
22 * to endorse or promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28 * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 * @package SimplePie
36 * @version 1.3-dev
37 * @copyright 2004-2010 Ryan Parman, Geoffrey Sneddon, Ryan McCue
38 * @author Ryan Parman
39 * @author Geoffrey Sneddon
40 * @author Ryan McCue
41 * @link http://simplepie.org/ SimplePie
42 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
43 * @todo phpDoc comments
44 */
45
46
47 class SimplePie_Locator
48 {
49 var $useragent;
50 var $timeout;
51 var $file;
52 var $local = array();
53 var $elsewhere = array();
54 var $file_class = 'SimplePie_File';
55 var $cached_entities = array();
56 var $http_base;
57 var $base;
58 var $base_location = 0;
59 var $checked_feeds = 0;
60 var $max_checked_feeds = 10;
61 var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
62
63 public function __construct(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
64 {
65 $this->file =& $file;
66 $this->file_class = $file_class;
67 $this->useragent = $useragent;
68 $this->timeout = $timeout;
69 $this->max_checked_feeds = $max_checked_feeds;
70 $this->content_type_sniffer_class = $content_type_sniffer_class;
71 }
72
73 public function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
74 {
75 if ($this->is_feed($this->file))
76 {
77 return $this->file;
78 }
79
80 if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
81 {
82 $sniffer = new $this->content_type_sniffer_class($this->file);
83 if ($sniffer->get_type() !== 'text/html')
84 {
85 return null;
86 }
87 }
88
89 if ($type & ~SIMPLEPIE_LOCATOR_NONE)
90 {
91 $this->get_base();
92 }
93
94 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
95 {
96 return $working[0];
97 }
98
99 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
100 {
101 if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
102 {
103 return $working;
104 }
105
106 if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
107 {
108 return $working;
109 }
110
111 if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
112 {
113 return $working;
114 }
115
116 if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
117 {
118 return $working;
119 }
120 }
121 return null;
122 }
123
124 public function is_feed(&$file)
125 {
126 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
127 {
128 $sniffer = new $this->content_type_sniffer_class($file);
129 $sniffed = $sniffer->get_type();
130 if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
131 {
132 return true;
133 }
134 else
135 {
136 return false;
137 }
138 }
139 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
140 {
141 return true;
142 }
143 else
144 {
145 return false;
146 }
147 }
148
149 public function get_base()
150 {
151 $this->http_base = $this->file->url;
152 $this->base = $this->http_base;
153 $elements = SimplePie_Misc::get_element('base', $this->file->body);
154 foreach ($elements as $element)
155 {
156 if ($element['attribs']['href']['data'] !== '')
157 {
158 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
159 $this->base_location = $element['offset'];
160 break;
161 }
162 }
163 }
164
165 public function autodiscovery()
166 {
167 $links = array_merge(SimplePie_Misc::get_element('link', $this->file->body), SimplePie_Misc::get_element('a', $this->file->body), SimplePie_Misc::get_element('area', $this->file->body));
168 $done = array();
169 $feeds = array();
170 foreach ($links as $link)
171 {
172 if ($this->checked_feeds === $this->max_checked_feeds)
173 {
174 break;
175 }
176 if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
177 {
178 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
179
180 if ($this->base_location < $link['offset'])
181 {
182 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
183 }
184 else
185 {
186 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
187 }
188
189 if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !in_array('stylesheet', $rel) && !empty($link['attribs']['type']['data']) && in_array(strtolower(SimplePie_Misc::parse_mime($link['attribs']['type']['data'])), array('application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href]))
190 {
191 $this->checked_feeds++;
192 $headers = array(
193 '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',
194 );
195 $feed = new $this->file_class($href, $this->timeout, 5, $headers, $this->useragent);
196 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))
197 {
198 $feeds[$href] = $feed;
199 }
200 }
201 $done[] = $href;
202 }
203 }
204
205 if (!empty($feeds))
206 {
207 return array_values($feeds);
208 }
209 else
210 {
211 return null;
212 }
213 }
214
215 public function get_links()
216 {
217 $links = SimplePie_Misc::get_element('a', $this->file->body);
218 foreach ($links as $link)
219 {
220 if (isset($link['attribs']['href']['data']))
221 {
222 $href = trim($link['attribs']['href']['data']);
223 $parsed = SimplePie_Misc::parse_url($href);
224 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
225 {
226 if ($this->base_location < $link['offset'])
227 {
228 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
229 }
230 else
231 {
232 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
233 }
234
235 $current = SimplePie_Misc::parse_url($this->file->url);
236
237 if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
238 {
239 $this->local[] = $href;
240 }
241 else
242 {
243 $this->elsewhere[] = $href;
244 }
245 }
246 }
247 }
248 $this->local = array_unique($this->local);
249 $this->elsewhere = array_unique($this->elsewhere);
250 if (!empty($this->local) || !empty($this->elsewhere))
251 {
252 return true;
253 }
254 return null;
255 }
256
257 public function extension(&$array)
258 {
259 foreach ($array as $key => $value)
260 {
261 if ($this->checked_feeds === $this->max_checked_feeds)
262 {
263 break;
264 }
265 if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
266 {
267 $this->checked_feeds++;
268
269 $headers = array(
270 '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',
271 );
272 $feed = new $this->file_class($value, $this->timeout, 5, $headers, $this->useragent);
273 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))
274 {
275 return $feed;
276 }
277 else
278 {
279 unset($array[$key]);
280 }
281 }
282 }
283 return null;
284 }
285
286 public function body(&$array)
287 {
288 foreach ($array as $key => $value)
289 {
290 if ($this->checked_feeds === $this->max_checked_feeds)
291 {
292 break;
293 }
294 if (preg_match('/(rss|rdf|atom|xml)/i', $value))
295 {
296 $this->checked_feeds++;
297 $headers = array(
298 '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',
299 );
300 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
301 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))
302 {
303 return $feed;
304 }
305 else
306 {
307 unset($array[$key]);
308 }
309 }
310 }
311 return null;
312 }
313 }
314