PluginProbe
FeedWordPress / 2011.0211.2
FeedWordPress v2011.0211.2
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 +178 -50 2009.11112011.0211.2 View file →
@@ -1,15 +1,23 @@
1 1 <?php
2 -################################################################################
3 -## class FeedFinder: find likely feeds using autodetection and/or guesswork ####
4 -################################################################################
2 +/**
3 + * class FeedFinder: find likely feeds using autodetection and/or guesswork
4 + * @version 2010.0622
5 + * @uses SimplePie_Misc
6 + */
5 7
8 +if (!class_exists('SimplePie')) :
9 + require_once(ABSPATH . WPINC . '/class-simplepie.php');
10 +endif;
11 +require_once(dirname(__FILE__).'/feedwordpresshtml.class.php');
12 +
6 13 class FeedFinder {
7 14 var $uri = NULL;
8 15 var $_cache_uri = NULL;
9 16
10 17 var $verify = FALSE;
11 -
18 + var $fallbacks = 3;
19 +
12 20 var $_response = NULL;
13 21 var $_data = NULL;
14 22 var $_error = NULL;
15 23 var $_head = NULL;
@@ -23,61 +31,86 @@
23 31 'application/x-atom+xml'
24 32 );
25 33 var $_feed_markers = array('\\<feed', '\\<rss', 'xmlns="http://purl.org/rss/1.0');
26 34 var $_html_markers = array('\\<html');
35 + var $_opml_markers = array('\\<opml', '\\<outline');
27 36 var $_obvious_feed_url = array('[./]rss', '[./]rdf', '[./]atom', '[./]feed', '\.xml');
28 37 var $_maybe_feed_url = array ('rss', 'rdf', 'atom', 'feed', 'xml');
29 38
30 - function FeedFinder ($uri = NULL, $verify = TRUE) {
39 + function FeedFinder ($uri = NULL, $verify = TRUE, $fallbacks = 3) {
31 40 $this->uri = $uri; $this->verify = $verify;
41 + $this->fallbacks = $fallbacks;
32 42 } /* FeedFinder::FeedFinder () */
33 43
34 44 function find ($uri = NULL) {
35 45 $ret = array ();
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);
46 + if (!is_null($this->data($uri))) :
47 + if ($this->is_opml($uri)) :
48 + $href = $this->_opml_rss_uris();
49 + else :
50 + if ($this->is_feed($uri)) :
51 + $href = array($this->uri);
52 + else :
53 + // Assume that we have HTML or XHTML (even if we don't, who's it gonna hurt?)
54 + // Autodiscovery is the preferred method
55 + $href = $this->_link_rel_feeds();
56 +
57 + // ... but we'll also take the little orange buttons
58 + if ($this->fallbacks > 0) :
59 + $href = array_merge($href, $this->_a_href_feeds(TRUE));
60 + endif;
61 +
62 + // If all that failed, look harder
63 + if ($this->fallbacks > 1) :
64 + if (count($href) == 0) :
65 + $href = $this->_a_href_feeds(FALSE);
66 + endif;
67 + endif;
68 +
69 + // Our search may turn up duplicate URIs. We only need to do any given URI once.
70 + // Props to Camilo <http://projects.radgeek.com/2008/12/14/feedwordpress-20081214/#comment-20090122160414>
71 + $href = array_unique($href);
72 + endif;
49 73
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);
74 + // Try some clever URL little tricks before we go
75 + if ($this->fallbacks > 2) :
76 + $href = array_merge($href, $this->_url_manipulation_feeds());
77 + endif;
78 + endif;
79 +
80 + $href = array_unique($href);
53 81
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 - $feed = NULL;
61 - } else {
62 - $ret[] = $the_uri;
63 - }
64 - } /* foreach */
65 - } /* if */
66 - } /* if */
67 - return array_unique($ret);
82 + // Verify feeds and resolve relative URIs
83 + foreach ($href as $u) :
84 + $the_uri = SimplePie_Misc::absolutize_url($u, $this->uri);
85 + if ($this->verify and ($u != $this->uri and $the_uri != $this->uri)) :
86 + $feed = new FeedFinder($the_uri);
87 + if ($feed->is_feed()) : $ret[] = $the_uri; endif;
88 + unset($feed);
89 + else :
90 + $ret[] = $the_uri;
91 + endif;
92 + endforeach;
93 + endif;
94 +
95 + return array_values($ret);
68 96 } /* FeedFinder::find () */
69 97
70 98 function data ($uri = NULL) {
71 99 $this->_get($uri);
72 100 return $this->_data;
73 - }
101 + } /* FeedFinder::data () */
74 102
103 + function upload_data ($data) {
104 + $this->uri = 'tag:localhost';
105 + $this->_data = $data;
106 + } /* FeedFinder::upload_data () */
107 +
75 108 function status ($uri = NULL) {
76 109 $this->_get($uri);
77 110
78 - if (isset($this->_response->status)) :
79 - $ret = $this->_response->status;
111 + if (!is_wp_error($this->_response) and isset($this->_response['response']['code'])) :
112 + $ret = $this->_response['response']['code'];
80 113 else :
81 114 $ret = NULL;
82 115 endif;
83 116 return $ret;
@@ -82,10 +115,18 @@
82 115 endif;
83 116 return $ret;
84 117 }
85 118
86 - function error () {
87 - return $this->_error;
119 + function error ($index = NULL) {
120 + $message = NULL;
121 + if (count($this->_error) > 0) :
122 + if (is_scalar($index) and !is_null($index)) :
123 + $message = $this->_error[$index];
124 + else :
125 + $message = implode(" / ", $this->_error)."\n";
126 + endif;
127 + endif;
128 + return $message;
88 129 }
89 130
90 131 function is_feed ($uri = NULL) {
91 132 $data = $this->data($uri);
@@ -100,27 +141,42 @@
100 141 )
101 142 );
102 143 } /* FeedFinder::is_feed () */
103 144
145 + function is_opml ($uri = NULL) {
146 + $data = $this->data($uri);
147 + return (
148 + preg_match (
149 + "\007(".implode('|',$this->_opml_markers).")\007i",
150 + $data
151 + )
152 + );
153 + } /* FeedFinder::is_opml () */
154 +
104 155 # --- Private methods ---
105 156 function _get ($uri = NULL) {
106 157 if ($uri) $this->uri = $uri;
107 158
108 159 // Is the result not yet cached?
109 - if ($this->_cache_uri !== $this->uri) :
160 + if ($this->uri != 'tag:localhost' and $this->_cache_uri !== $this->uri) :
110 161 $headers['Connection'] = 'close';
111 162 $headers['Accept'] = 'application/atom+xml application/rdf+xml application/rss+xml application/xml text/html */*';
112 163 $headers['User-Agent'] = 'feedfinder/1.2 (compatible; PHP FeedFinder) +http://projects.radgeek.com/feedwordpress';
113 164
114 - // Use function provided by MagpieRSS package
115 - $client = _fetch_remote_file($this->uri, $headers);
116 - if (isset($client->error)) :
117 - $this->_error = $client->error;
165 + // Use WordPress API function
166 + $client = wp_remote_request($this->uri, array(
167 + 'headers' => $headers,
168 + 'timeout' => FeedWordPress::fetch_timeout(),
169 + ));
170 +
171 + $this->_response = $client;
172 + if (is_wp_error($client)) :
173 + $this->_data = NULL;
174 + $this->_error = $client->get_error_messages();
118 175 else :
176 + $this->_data = $client['body'];
119 177 $this->_error = NULL;
120 178 endif;
121 - $this->_response = $client;
122 - $this->_data = $client->results;
123 179
124 180 // Kilroy was here
125 181 $this->_cache_uri = $this->uri;
126 182 endif;
@@ -125,8 +181,25 @@
125 181 $this->_cache_uri = $this->uri;
126 182 endif;
127 183 } /* FeedFinder::_get () */
128 184
185 + function _opml_rss_uris () {
186 + // Really we should parse the XML and use the structure to
187 + // return something intelligent to programs that want to use it
188 + // Oh babe! maybe some day...
189 +
190 + $opml = $this->data();
191 +
192 + $rx = FeedWordPressHTML::attributeRegex('outline', 'xmlUrl');
193 + if (preg_match_all($rx, $opml, $matches, PREG_SET_ORDER)) :
194 + foreach ($matches as $m) :
195 + $match = FeedWordPressHTML::attributeMatch($m);
196 + $r[] = $match['value'];
197 + endforeach;
198 + endif;
199 + return $r;
200 + } /* FeedFinder::_opml_rss_uris () */
201 +
129 202 function _link_rel_feeds () {
130 203 $links = $this->_tags('link');
131 204 $link_count = count($links);
132 205
@@ -139,9 +212,9 @@
139 212 } /* if */
140 213 } /* if */
141 214 } /* for */
142 215 return $href;
143 - }
216 + } /* FeedFinder::_link_rel_feeds () */
144 217
145 218 function _a_href_feeds ($obvious = TRUE) {
146 219 $pattern = ($obvious ? $this->_obvious_feed_url : $this->_maybe_feed_url);
147 220
@@ -155,10 +228,65 @@
155 228 $href[] = $links[$n]['href'];
156 229 } /* if */
157 230 } /* for */
158 231 return $href;
159 - }
232 + } /* FeedFinder::_link_a_href_feeds () */
160 233
234 + function _url_manipulation_feeds () {
235 + $href = array();
236 +
237 + // check for HTTP GET parameters that look feed-like.
238 + $bits = parse_url($this->uri);
239 + foreach (array('rss', 'rss2', 'atom', 'rdf') as $format) :
240 + if (isset($bits['query']) and (strlen($bits['query']) > 0)) :
241 + $newQuery = preg_replace('/([?&=])(rss2?|atom|rdf)/i', '$1'.$format, $bits['query']);
242 + else :
243 + $newQuery = NULL;
244 + endif;
245 +
246 + if (isset($bits['path']) and (strlen($bits['path']) > 0)) :
247 + $newPath = preg_replace('!([/.])(rss2?|atom|rdf)!i', '$1'.$format, $bits['path']);
248 + else :
249 + $newPath = NULL;
250 + endif;
251 +
252 + // Reassemble, check and return
253 + $credentials = '';
254 + if (isset($bits['user'])) :
255 + $credentials = $bits['user'];
256 + if (isset($bits['pass'])) :
257 + $credentials .= ':'.$bits['pass'];
258 + endif;
259 + $credentials .= '@';
260 + endif;
261 +
262 + // Variations on a theme
263 + $newUrl[0] = (''
264 + .(isset($bits['scheme']) ? $bits['scheme'].':' : '')
265 + .(isset($bits['host']) ? '//'.$credentials.$bits['host'] : '')
266 + .(!is_null($newPath) ? $newPath : '')
267 + .(!is_null($newQuery) ? '?'.$newQuery : '')
268 + .(isset($bits['fragment']) ? '#'.$bits['fragment'] : '')
269 + );
270 + $newUrl[1] = (''
271 + .(isset($bits['scheme']) ? $bits['scheme'].':' : '')
272 + .(isset($bits['host']) ? '//'.$credentials.$bits['host'] : '')
273 + .(!is_null($newPath) ? $newPath : '')
274 + .(isset($bits['query']) ? '?'.$bits['query'] : '')
275 + .(isset($bits['fragment']) ? '#'.$bits['fragment'] : '')
276 + );
277 + $newUrl[2] = (''
278 + .(isset($bits['scheme']) ? $bits['scheme'].':' : '')
279 + .(isset($bits['host']) ? '//'.$credentials.$bits['host'] : '')
280 + .(isset($bits['path']) ? $bits['path'] : '')
281 + .(!is_null($newQuery) ? '?'.$newQuery : '')
282 + .(isset($bits['fragment']) ? '#'.$bits['fragment'] : '')
283 + );
284 + $href = array_merge($href, $newUrl);
285 + endforeach;
286 + return array_unique($href);
287 + } /* FeedFinder::_url_manipulation_feeds () */
288 +
161 289 function _tags ($tag) {
162 290 $html = $this->data();
163 291
164 292 // search through the HTML, save all <link> tags
@@ -178,7 +306,7 @@
178 306 } /* foreach */
179 307 $ret[$n] = $final_link;
180 308 } /* for */
181 309 return $ret;
182 - }
310 + } /* FeedFinder::_tags () */
183 311 } /* class FeedFinder */
184 312