PluginProbe
FeedWordPress / 2010.0528
FeedWordPress v2010.0528
trunk 0.8 0.9 0.91 0.95 0.96 0.97 0.98 0.981 0.99 0.991 0.992 0.993 2008.1030 2008.1101 2008.1105 2008.1214 2009.0612 2009.0613 2009.0618 2009.0707 2009.1111 2009.1112 2010.0127 2010.0528 All 65 releases
← All changes | feedfinder.class.php +49 -226 trunk2010.0528 View file →
@@ -1,29 +1,15 @@
1 1 <?php
2 -/**
3 - * class FeedFinder: find likely feeds using autodetection and/or guesswork
4 - * @version 2010.0622
5 - * @uses SimplePie_Misc
6 - */
2 +################################################################################
3 +## class FeedFinder: find likely feeds using autodetection and/or guesswork ####
4 +################################################################################
7 5
8 -if ( ! class_exists( 'SimplePie' ) ) :
9 - require_once ABSPATH . WPINC . '/class-simplepie.php';
10 -endif;
11 -require_once dirname( __FILE__ ) . '/feedwordpresshtml.class.php';
12 -
13 -/**
14 - * FeedFinder attempts to get all possible RSS/Atom feeds from a site.
15 - *
16 - * @see SimplePie_Misc
17 - */
18 6 class FeedFinder {
19 7 var $uri = NULL;
20 - var $credentials = NULL;
21 8 var $_cache_uri = NULL;
22 -
9 +
23 10 var $verify = FALSE;
24 - var $fallbacks = 3;
25 -
11 +
26 12 var $_response = NULL;
27 13 var $_data = NULL;
28 14 var $_error = NULL;
29 15 var $_head = NULL;
@@ -33,138 +19,64 @@
33 19 'application/rss+xml',
34 20 'text/xml',
35 21 'application/atom+xml',
36 22 'application/x.atom+xml',
37 - 'application/x-atom+xml',
23 + 'application/x-atom+xml'
38 24 );
39 25 var $_feed_markers = array('\\<feed', '\\<rss', 'xmlns="http://purl.org/rss/1.0');
40 26 var $_html_markers = array('\\<html');
41 - var $_opml_markers = array('\\<opml', '\\<outline');
42 27 var $_obvious_feed_url = array('[./]rss', '[./]rdf', '[./]atom', '[./]feed', '\.xml');
43 28 var $_maybe_feed_url = array ('rss', 'rdf', 'atom', 'feed', 'xml');
44 29
45 - function __construct( $uri = NULL, $params = array(), $fallbacks = 3 ) {
46 - if (is_bool($params)) :
47 - $params = array("verify" => $params);
48 - endif;
49 -
50 - $params = wp_parse_args($params, array(
51 - "verify" => true,
52 - "authentication" => NULL,
53 - "username" => NULL,
54 - "password" => NULL,
55 - ));
56 - $verify = $params['verify'];
57 - $this->credentials = array(
58 - "authentication" => $params['authentication'],
59 - "username" => $params['username'],
60 - "password" => $params['password'],
61 - );
62 -
30 + function FeedFinder ($uri = NULL, $verify = TRUE) {
63 31 $this->uri = $uri; $this->verify = $verify;
64 - $this->fallbacks = $fallbacks;
65 32 } /* FeedFinder::FeedFinder () */
66 33
67 - function FeedFinder( $uri = NULL, $params = array(), $fallbacks = 3 ) {
68 - self::__construct( $uri, $params, $fallbacks );
69 - }
70 -
71 - function find ($uri = NULL, $params = array()) {
72 - $params = wp_parse_args($params, array( // Defaults
73 - "authentication" => -1,
74 - "username" => NULL,
75 - "password" => NULL,
76 - ));
77 -
78 - // Equivalents
79 - if ($params['authentication']=='-') :
80 - $params['authentication'] = NULL;
81 - $params['username'] = NULL;
82 - $params['password'] = NULL;
83 - endif;
84 -
85 - // Set/reset
86 - if ($params['authentication'] != -1) :
87 - $this->credentials = array(
88 - "authentication" => $params['authentication'],
89 - "username" => $params['username'],
90 - "password" => $params['password'],
91 - );
92 - endif;
93 -
34 + function find ($uri = NULL) {
94 35 $ret = array ();
95 - if ( !is_null($this->data($uri))) :
96 - if ($this->is_opml($uri)) :
97 - $href = $this->_opml_rss_uris();
98 - else :
99 - if ($this->is_feed($uri)) :
100 - $href = array($this->uri);
101 - else :
102 - // Assume that we have HTML or XHTML (even if we don't, who's
103 - // it gonna hurt?) Autodiscovery is the preferred method.
104 - $href = $this->_link_rel_feeds();
36 + if (!is_null($this->data($uri))) {
37 + if ($this->is_feed($uri)) {
38 + $ret = array($this->uri);
39 + } else {
40 + // Assume that we have HTML or XHTML (even if we don't, who's it gonna hurt?)
41 + // Autodiscovery is the preferred method
42 + $href = $this->_link_rel_feeds();
43 +
44 + // ... but we'll also take the little orange buttons
45 + $href = array_merge($href, $this->_a_href_feeds(TRUE));
46 +
47 + // If all that failed, look harder
48 + if (count($href) == 0) $href = $this->_a_href_feeds(FALSE);
105 49
106 - // ... but we'll also take the little orange buttons
107 - if ($this->fallbacks > 0) :
108 - $href = array_merge($href, $this->_a_href_feeds(TRUE));
109 - endif;
50 + // Our search may turn up duplicate URIs. We only need to do any given URI once.
51 + // Props to Camilo <http://projects.radgeek.com/2008/12/14/feedwordpress-20081214/#comment-20090122160414>
52 + $href = array_unique($href);
110 53
111 - // If all that failed, look harder
112 - if ($this->fallbacks > 1) :
113 - if (count($href) == 0) :
114 - $href = $this->_a_href_feeds(FALSE);
115 - endif;
116 - endif;
117 -
118 - // Our search may turn up duplicate URIs. We only need to do
119 - // any given URI once. Props to Camilo <http://projects.radgeek.com/2008/12/14/feedwordpress-20081214/#comment-20090122160414>
120 - $href = array_unique($href);
121 - endif;
122 -
123 - // Try some clever URL little tricks before we go
124 - if ($this->fallbacks > 2) :
125 - $href = array_merge($href, $this->_url_manipulation_feeds());
126 - endif;
127 - endif;
128 -
129 - $href = array_unique($href);
130 -
131 - // Verify feeds and resolve relative URIs
132 - foreach ($href as $u) :
133 - $the_uri = SimplePie_Misc::absolutize_url($u, $this->uri);
134 - if ($this->verify and ($u != $this->uri and $the_uri != $this->uri)) :
135 - $feed = new FeedFinder($the_uri, $this->credentials);
136 - if ($feed->is_feed()) : $ret[] = $the_uri; endif;
137 - unset($feed);
138 - else :
139 - $ret[] = $the_uri;
140 - endif;
141 - endforeach;
142 - endif;
143 -
144 - if ($this->is_401($uri)) :
145 - $ret = array_merge(array(
146 - new WP_Error('http_request_failed', '401 Not authorized', array("uri" => $this->uri, "status" => 401)),
147 - ), $ret);
148 - endif;
149 -
150 - return array_values($ret);
54 + // Verify feeds and resolve relative URIs
55 + foreach ($href as $u) {
56 + $the_uri = Relative_URI::resolve($u, $this->uri);
57 + if ($this->verify) {
58 + $feed = new FeedFinder($the_uri);
59 + if ($feed->is_feed()) $ret[] = $the_uri;
60 + unset($feed);
61 + } else {
62 + $ret[] = $the_uri;
63 + }
64 + } /* foreach */
65 + } /* if */
66 + } /* if */
67 + return array_unique($ret);
151 68 } /* FeedFinder::find () */
152 69
153 70 function data ($uri = NULL) {
154 71 $this->_get($uri);
155 72 return $this->_data;
156 - } /* FeedFinder::data () */
73 + }
157 74
158 - function upload_data ($data) {
159 - $this->uri = 'tag:localhost';
160 - $this->_data = $data;
161 - } /* FeedFinder::upload_data () */
162 -
163 75 function status ($uri = NULL) {
164 76 $this->_get($uri);
165 -
166 - if ( !is_wp_error($this->_response) and isset($this->_response['response']['code'])) :
77 +
78 + if (!is_wp_error($this->_response) and isset($this->_response['response']['code'])) :
167 79 $ret = $this->_response['response']['code'];
168 80 else :
169 81 $ret = NULL;
170 82 endif;
@@ -181,13 +93,9 @@
181 93 endif;
182 94 endif;
183 95 return $message;
184 96 }
185 -
186 - function is_401 ($uri = NULL) {
187 - return (intval($this->status($uri))==401);
188 - } /* FeedFinder::is_401 () */
189 -
97 +
190 98 function is_feed ($uri = NULL) {
191 99 $data = $this->data($uri);
192 100
193 101 return (
@@ -200,35 +108,22 @@
200 108 )
201 109 );
202 110 } /* FeedFinder::is_feed () */
203 111
204 - function is_opml ($uri = NULL) {
205 - $data = $this->data($uri);
206 - return (
207 - preg_match (
208 - "\007(".implode('|',$this->_opml_markers).")\007i",
209 - $data
210 - )
211 - );
212 - } /* FeedFinder::is_opml () */
213 -
214 112 # --- Private methods ---
215 113 function _get ($uri = NULL) {
216 114 if ($uri) $this->uri = $uri;
217 115
218 116 // Is the result not yet cached?
219 - if ($this->uri != 'tag:localhost' and $this->_cache_uri !== $this->uri) :
117 + if ($this->_cache_uri !== $this->uri) :
220 118 $headers['Connection'] = 'close';
221 119 $headers['Accept'] = 'application/atom+xml application/rdf+xml application/rss+xml application/xml text/html */*';
222 120 $headers['User-Agent'] = 'feedfinder/1.2 (compatible; PHP FeedFinder) +http://projects.radgeek.com/feedwordpress';
223 121
224 122 // Use WordPress API function
225 - $client = wp_remote_request($this->uri, array_merge(
226 - $this->credentials,
227 - array(
123 + $client = wp_remote_request($this->uri, array(
228 124 'headers' => $headers,
229 - 'timeout' => FeedWordPress::fetch_timeout(),
230 - )
125 + 'timeout' => FEEDWORDPRESS_FETCH_TIME_OUT,
231 126 ));
232 127
233 128 $this->_response = $client;
234 129 if (is_wp_error($client)) :
@@ -243,25 +138,8 @@
243 138 $this->_cache_uri = $this->uri;
244 139 endif;
245 140 } /* FeedFinder::_get () */
246 141
247 - function _opml_rss_uris () {
248 - // Really we should parse the XML and use the structure to
249 - // return something intelligent to programs that want to use it
250 - // Oh babe! maybe some day...
251 -
252 - $opml = $this->data();
253 -
254 - $rx = FeedWordPressHTML::attributeRegex('outline', 'xmlUrl');
255 - if (preg_match_all($rx, $opml, $matches, PREG_SET_ORDER)) :
256 - foreach ($matches as $m) :
257 - $match = FeedWordPressHTML::attributeMatch($m);
258 - $r[] = $match['value'];
259 - endforeach;
260 - endif;
261 - return $r;
262 - } /* FeedFinder::_opml_rss_uris () */
263 -
264 142 function _link_rel_feeds () {
265 143 $links = $this->_tags('link');
266 144 $link_count = count($links);
267 145
@@ -274,9 +152,9 @@
274 152 } /* if */
275 153 } /* if */
276 154 } /* for */
277 155 return $href;
278 - } /* FeedFinder::_link_rel_feeds () */
156 + }
279 157
280 158 function _a_href_feeds ($obvious = TRUE) {
281 159 $pattern = ($obvious ? $this->_obvious_feed_url : $this->_maybe_feed_url);
282 160
@@ -290,68 +168,13 @@
290 168 $href[] = $links[$n]['href'];
291 169 } /* if */
292 170 } /* for */
293 171 return $href;
294 - } /* FeedFinder::_link_a_href_feeds () */
172 + }
295 173
296 - function _url_manipulation_feeds () {
297 - $href = array();
298 -
299 - // check for HTTP GET parameters that look feed-like.
300 - $bits = parse_url($this->uri);
301 - foreach (array('rss', 'rss2', 'atom', 'rdf') as $format) :
302 - if (isset($bits['query']) and (strlen($bits['query']) > 0)) :
303 - $newQuery = preg_replace('/([?&=])(rss2?|atom|rdf)/i', '$1'.$format, $bits['query']);
304 - else :
305 - $newQuery = NULL;
306 - endif;
307 -
308 - if (isset($bits['path']) and (strlen($bits['path']) > 0)) :
309 - $newPath = preg_replace('!([/.])(rss2?|atom|rdf)!i', '$1'.$format, $bits['path']);
310 - else :
311 - $newPath = NULL;
312 - endif;
313 -
314 - // Reassemble, check and return
315 - $credentials = '';
316 - if (isset($bits['user'])) :
317 - $credentials = $bits['user'];
318 - if (isset($bits['pass'])) :
319 - $credentials .= ':'.$bits['pass'];
320 - endif;
321 - $credentials .= '@';
322 - endif;
323 -
324 - // Variations on a theme
325 - $newUrl[0] = (''
326 - .(isset($bits['scheme']) ? $bits['scheme'].':' : '')
327 - .(isset($bits['host']) ? '//'.$credentials.$bits['host'] : '')
328 - .( !is_null($newPath) ? $newPath : '')
329 - .( !is_null($newQuery) ? '?'.$newQuery : '')
330 - .(isset($bits['fragment']) ? '#'.$bits['fragment'] : '')
331 - );
332 - $newUrl[1] = (''
333 - .(isset($bits['scheme']) ? $bits['scheme'].':' : '')
334 - .(isset($bits['host']) ? '//'.$credentials.$bits['host'] : '')
335 - .( !is_null($newPath) ? $newPath : '')
336 - .(isset($bits['query']) ? '?'.$bits['query'] : '')
337 - .(isset($bits['fragment']) ? '#'.$bits['fragment'] : '')
338 - );
339 - $newUrl[2] = (''
340 - .(isset($bits['scheme']) ? $bits['scheme'].':' : '')
341 - .(isset($bits['host']) ? '//'.$credentials.$bits['host'] : '')
342 - .(isset($bits['path']) ? $bits['path'] : '')
343 - .( !is_null($newQuery) ? '?'.$newQuery : '')
344 - .(isset($bits['fragment']) ? '#'.$bits['fragment'] : '')
345 - );
346 - $href = array_merge($href, $newUrl);
347 - endforeach;
348 - return array_unique($href);
349 - } /* FeedFinder::_url_manipulation_feeds () */
350 -
351 174 function _tags ($tag) {
352 175 $html = $this->data();
353 -
176 +
354 177 // search through the HTML, save all <link> tags
355 178 // and store each link's attributes in an associative array
356 179 preg_match_all('/<'.$tag.'\s+(.*?)\s*\/?>/si', $html, $matches);
357 180 $links = $matches[1];
@@ -368,7 +191,7 @@
368 191 } /* foreach */
369 192 $ret[$n] = $final_link;
370 193 } /* for */
371 194 return $ret;
372 - } /* FeedFinder::_tags () */
195 + }
373 196 } /* class FeedFinder */
374 197