1 | <?php
|
---|
2 | /*
|
---|
3 | Plugin Name: FeedWordPress
|
---|
4 | Plugin URI: http://projects.radgeek.com/feedwordpress
|
---|
5 | Description: simple and flexible Atom/RSS syndication for WordPress
|
---|
6 | Version: 2009.0707
|
---|
7 | Author: Charles Johnson
|
---|
8 | Author URI: http://radgeek.com/
|
---|
9 | License: GPL
|
---|
10 | */
|
---|
11 |
|
---|
12 | # This uses code derived from:
|
---|
13 | # - wp-rss-aggregate.php by Kellan Elliot-McCrea <kellan@protest.net>
|
---|
14 | # - HTTP Navigator 2 by Keyvan Minoukadeh <keyvan@k1m.com>
|
---|
15 | # - Ultra-Liberal Feed Finder by Mark Pilgrim <mark@diveintomark.org>
|
---|
16 | # according to the terms of the GNU General Public License.
|
---|
17 | #
|
---|
18 | # INSTALLATION: see readme.txt or <http://projects.radgeek.com/install>
|
---|
19 | #
|
---|
20 | # USAGE: once FeedWordPress is installed, you manage just about everything from
|
---|
21 | # the WordPress Dashboard, under the Syndication menu. To ensure that fresh
|
---|
22 | # content is added as it becomes available, you can convince your contributors
|
---|
23 | # to put your XML-RPC URI (if WordPress is installed at
|
---|
24 | # <http://www.zyx.com/blog>, XML-RPC requests should be sent to
|
---|
25 | # <http://www.zyx.com/blog/xmlrpc.php>), or update manually under the
|
---|
26 | # Syndication menu, or set up automatic updates under Syndication --> Settings,
|
---|
27 | # or use a cron job.
|
---|
28 |
|
---|
29 | # -- Don't change these unless you know what you're doing...
|
---|
30 |
|
---|
31 | define ('FEEDWORDPRESS_VERSION', '2009.0707');
|
---|
32 | define ('FEEDWORDPRESS_AUTHOR_CONTACT', 'http://radgeek.com/contact');
|
---|
33 | define ('DEFAULT_SYNDICATION_CATEGORY', 'Contributors');
|
---|
34 |
|
---|
35 | $feedwordpress_debug = get_option('feedwordpress_debug');
|
---|
36 | if (is_string($feedwordpress_debug)) :
|
---|
37 | $feedwordpress_debug = ($feedwordpress_debug == 'yes');
|
---|
38 | endif;
|
---|
39 | define ('FEEDWORDPRESS_DEBUG', $feedwordpress_debug);
|
---|
40 |
|
---|
41 | define ('FEEDWORDPRESS_CAT_SEPARATOR_PATTERN', '/[:\n]/');
|
---|
42 | define ('FEEDWORDPRESS_CAT_SEPARATOR', "\n");
|
---|
43 |
|
---|
44 | define ('FEEDVALIDATOR_URI', 'http://feedvalidator.org/check.cgi');
|
---|
45 |
|
---|
46 | define ('FEEDWORDPRESS_FRESHNESS_INTERVAL', 10*60); // Every ten minutes
|
---|
47 |
|
---|
48 | define ('FWP_SCHEMA_HAS_USERMETA', 2966);
|
---|
49 | define ('FWP_SCHEMA_20', 3308); // Database schema # for WP 2.0
|
---|
50 | define ('FWP_SCHEMA_21', 4772); // Database schema # for WP 2.1
|
---|
51 | define ('FWP_SCHEMA_23', 5495); // Database schema # for WP 2.3
|
---|
52 | define ('FWP_SCHEMA_25', 7558); // Database schema # for WP 2.5
|
---|
53 | define ('FWP_SCHEMA_26', 8201); // Database schema # for WP 2.6
|
---|
54 | define ('FWP_SCHEMA_27', 9872); // Database schema # for WP 2.7
|
---|
55 | define ('FWP_SCHEMA_28', 11548); // Database schema # for WP 2.8
|
---|
56 |
|
---|
57 | if (FEEDWORDPRESS_DEBUG) :
|
---|
58 | // Help us to pick out errors, if any.
|
---|
59 | ini_set('error_reporting', E_ALL & ~E_NOTICE);
|
---|
60 | ini_set('display_errors', true);
|
---|
61 | define('MAGPIE_DEBUG', true);
|
---|
62 |
|
---|
63 | // When testing we don't want cache issues to interfere. But this is
|
---|
64 | // a VERY BAD SETTING for a production server. Webmasters will eat your
|
---|
65 | // face for breakfast if you use it, and the baby Jesus will cry. So
|
---|
66 | // make sure FEEDWORDPRESS_DEBUG is FALSE for any site that will be
|
---|
67 | // used for more than testing purposes!
|
---|
68 | define('MAGPIE_CACHE_AGE', 1);
|
---|
69 | else :
|
---|
70 | define('MAGPIE_DEBUG', false);
|
---|
71 | endif;
|
---|
72 |
|
---|
73 | // Note that the rss-functions.php that comes prepackaged with WordPress is
|
---|
74 | // old & busted. For the new hotness, drop a copy of rss.php from
|
---|
75 | // this archive into wp-includes/rss.php
|
---|
76 |
|
---|
77 | if (is_readable(ABSPATH . WPINC . '/rss.php')) :
|
---|
78 | require_once (ABSPATH . WPINC . '/rss.php');
|
---|
79 | else :
|
---|
80 | require_once (ABSPATH . WPINC . '/rss-functions.php');
|
---|
81 | endif;
|
---|
82 |
|
---|
83 | if (isset($wp_db_version)) :
|
---|
84 | if ($wp_db_version >= FWP_SCHEMA_23) :
|
---|
85 | require_once (ABSPATH . WPINC . '/registration.php'); // for wp_insert_user
|
---|
86 | elseif ($wp_db_version >= FWP_SCHEMA_21) : // WordPress 2.1 and 2.2, but not 2.3
|
---|
87 | require_once (ABSPATH . WPINC . '/registration.php'); // for wp_insert_user
|
---|
88 | require_once (ABSPATH . 'wp-admin/admin-db.php'); // for wp_insert_category
|
---|
89 | elseif ($wp_db_version >= FWP_SCHEMA_20) : // WordPress 2.0
|
---|
90 | require_once (ABSPATH . WPINC . '/registration-functions.php'); // for wp_insert_user
|
---|
91 | require_once (ABSPATH . 'wp-admin/admin-db.php'); // for wp_insert_category
|
---|
92 | endif;
|
---|
93 | endif;
|
---|
94 |
|
---|
95 | require_once(dirname(__FILE__) . '/compatability.php'); // LEGACY API: Replicate or mock up functions for legacy support purposes
|
---|
96 | require_once(dirname(__FILE__) . '/feedwordpresshtml.class.php');
|
---|
97 |
|
---|
98 | // Magic quotes are just about the stupidest thing ever.
|
---|
99 | if (is_array($_POST)) :
|
---|
100 | $fwp_post = stripslashes_deep($_POST);
|
---|
101 | endif;
|
---|
102 |
|
---|
103 | // Get the path relative to the plugins directory in which FWP is stored
|
---|
104 | preg_match (
|
---|
105 | '|/wp-content/plugins/(.+)$|',
|
---|
106 | dirname(__FILE__),
|
---|
107 | $ref
|
---|
108 | );
|
---|
109 |
|
---|
110 | if (isset($ref[1])) :
|
---|
111 | $fwp_path = $ref[1];
|
---|
112 | else : // Something went wrong. Let's just guess.
|
---|
113 | $fwp_path = 'feedwordpress';
|
---|
114 | endif;
|
---|
115 |
|
---|
116 | // If this is a FeedWordPress admin page, queue up scripts for AJAX functions that FWP uses
|
---|
117 | // If it is a display page or a non-FeedWordPress admin page, don't.
|
---|
118 | if (is_admin() and isset($_REQUEST['page']) and preg_match("|^{$fwp_path}/|", $_REQUEST['page'])) :
|
---|
119 | if (function_exists('wp_enqueue_script')) :
|
---|
120 | if (isset($wp_db_version) and $wp_db_version >= FWP_SCHEMA_25) :
|
---|
121 | wp_enqueue_script('post'); // for magic tag and category boxes
|
---|
122 | wp_enqueue_script('thickbox'); // for fold-up boxes
|
---|
123 | wp_enqueue_script('admin-forms'); // for checkbox selection
|
---|
124 | else :
|
---|
125 | wp_enqueue_script( 'ajaxcat' ); // Provides the handy-dandy new category text box
|
---|
126 | endif;
|
---|
127 | endif;
|
---|
128 | if (function_exists('wp_enqueue_style')) :
|
---|
129 | if (fwp_test_wp_version(FWP_SCHEMA_25)) :
|
---|
130 | wp_enqueue_style('dashboard');
|
---|
131 | endif;
|
---|
132 | endif;
|
---|
133 | if (function_exists('wp_admin_css')) :
|
---|
134 | if (fwp_test_wp_version(FWP_SCHEMA_25)) :
|
---|
135 | wp_admin_css('css/dashboard');
|
---|
136 | endif;
|
---|
137 | endif;
|
---|
138 | endif;
|
---|
139 |
|
---|
140 | if (!FeedWordPress::needs_upgrade()) : // only work if the conditions are safe!
|
---|
141 |
|
---|
142 | # Syndicated items are generally received in output-ready (X)HTML and
|
---|
143 | # should not be folded, crumpled, mutilated, or spindled by WordPress
|
---|
144 | # formatting filters. But we don't want to interfere with filters for
|
---|
145 | # any locally-authored posts, either.
|
---|
146 | #
|
---|
147 | # What WordPress should really have is a way for upstream filters to
|
---|
148 | # stop downstream filters from running at all. Since it doesn't, and
|
---|
149 | # since a downstream filter can't access the original copy of the text
|
---|
150 | # that is being filtered, what we will do here is (1) save a copy of the
|
---|
151 | # original text upstream, before any other filters run, and then (2)
|
---|
152 | # retrieve that copy downstream, after all the other filters run, *if*
|
---|
153 | # this is a syndicated post
|
---|
154 |
|
---|
155 | add_filter('the_content', 'feedwordpress_preserve_syndicated_content', -10000);
|
---|
156 | add_filter('the_content', 'feedwordpress_restore_syndicated_content', 10000);
|
---|
157 |
|
---|
158 | add_action('atom_entry', 'feedwordpress_item_feed_data');
|
---|
159 |
|
---|
160 | # Filter in original permalinks if the user wants that
|
---|
161 | add_filter('post_link', 'syndication_permalink', 1);
|
---|
162 |
|
---|
163 | # WTF? By default, wp_insert_link runs incoming link_url and link_rss
|
---|
164 | # URIs through default filters that include `wp_kses()`. But `wp_kses()`
|
---|
165 | # just happens to escape any occurrence of & to & -- which just
|
---|
166 | # happens to fuck up any URI with a & to separate GET parameters.
|
---|
167 | remove_filter('pre_link_rss', 'wp_filter_kses');
|
---|
168 | remove_filter('pre_link_url', 'wp_filter_kses');
|
---|
169 |
|
---|
170 | # Admin menu
|
---|
171 | add_action('admin_menu', 'fwp_add_pages');
|
---|
172 | add_action('admin_notices', 'fwp_check_debug');
|
---|
173 | add_action('admin_notices', 'fwp_check_magpie');
|
---|
174 |
|
---|
175 | # Inbound XML-RPC update methods
|
---|
176 | add_filter('xmlrpc_methods', 'feedwordpress_xmlrpc_hook');
|
---|
177 |
|
---|
178 | # Outbound XML-RPC ping reform
|
---|
179 | remove_action('publish_post', 'generic_ping'); // WP 1.5.x
|
---|
180 | remove_action('do_pings', 'do_all_pings', 10, 1); // WP 2.1, 2.2
|
---|
181 | remove_action('publish_post', '_publish_post_hook', 5, 1); // WP 2.3
|
---|
182 |
|
---|
183 | add_action('publish_post', 'fwp_publish_post_hook', 5, 1);
|
---|
184 | add_action('do_pings', 'fwp_do_pings', 10, 1);
|
---|
185 | add_action('feedwordpress_update', 'fwp_hold_pings');
|
---|
186 | add_action('feedwordpress_update_complete', 'fwp_release_pings');
|
---|
187 |
|
---|
188 | # Hook in logging functions only if the logging option is ON
|
---|
189 | $update_logging = get_option('feedwordpress_update_logging');
|
---|
190 | if ($update_logging == 'yes') :
|
---|
191 | add_action('post_syndicated_item', 'log_feedwordpress_post', 100);
|
---|
192 | add_action('update_syndicated_item', 'log_feedwordpress_update_post', 100);
|
---|
193 | add_action('feedwordpress_update', 'log_feedwordpress_update_feeds', 100);
|
---|
194 | add_action('feedwordpress_check_feed', 'log_feedwordpress_check_feed', 100);
|
---|
195 | add_action('feedwordpress_update_complete', 'log_feedwordpress_update_complete', 100);
|
---|
196 | endif;
|
---|
197 |
|
---|
198 | # Cron-less auto-update. Hooray!
|
---|
199 | add_action('init', 'feedwordpress_auto_update');
|
---|
200 | add_action('init', 'feedwordpress_check_for_magpie_fix');
|
---|
201 |
|
---|
202 | # Default sanitizers
|
---|
203 | add_filter('syndicated_item_content', array('SyndicatedPost', 'resolve_relative_uris'), 0, 2);
|
---|
204 | add_filter('syndicated_item_content', array('SyndicatedPost', 'sanitize_content'), 0, 2);
|
---|
205 |
|
---|
206 | else :
|
---|
207 | # Hook in the menus, which will just point to the upgrade interface
|
---|
208 | add_action('admin_menu', 'fwp_add_pages');
|
---|
209 | endif; // if (!FeedWordPress::needs_upgrade())
|
---|
210 |
|
---|
211 | function feedwordpress_check_for_magpie_fix () {
|
---|
212 | if (isset($_POST['action']) and $_POST['action']=='fix_magpie_version') :
|
---|
213 | FeedWordPressCompatibility::validate_http_request(/*action=*/ 'feedwordpress_fix_magpie', /*capability=*/ 'edit_files');
|
---|
214 |
|
---|
215 | $back_to = $_SERVER['REQUEST_URI'];
|
---|
216 | if (isset($_POST['ignore'])) :
|
---|
217 | // kill error message by telling it we ignored the upgrade request for this version
|
---|
218 | update_option('feedwordpress_magpie_ignored_upgrade_to', EXPECTED_MAGPIE_VERSION);
|
---|
219 | $ret = 'ignored';
|
---|
220 | elseif (isset($_POST['upgrade'])) :
|
---|
221 | $source = dirname(__FILE__)."/MagpieRSS-upgrade/rss.php";
|
---|
222 | $destination = ABSPATH . WPINC . '/rss.php';
|
---|
223 | $success = @copy($source, $destination);
|
---|
224 | $ret = (int) $success;
|
---|
225 | endif;
|
---|
226 |
|
---|
227 | if (strpos($back_to, '?')===false) : $sep = '?';
|
---|
228 | else : $sep = '&';
|
---|
229 | endif;
|
---|
230 |
|
---|
231 | header("Location: {$back_to}{$sep}feedwordpress_magpie_fix=".$ret);
|
---|
232 | exit;
|
---|
233 | endif;
|
---|
234 | } /* feedwordpress_check_for_magpie_fix() */
|
---|
235 |
|
---|
236 | function feedwordpress_auto_update () {
|
---|
237 | if (FeedWordPress::stale()) :
|
---|
238 | $feedwordpress =& new FeedWordPress;
|
---|
239 | $feedwordpress->update();
|
---|
240 | endif;
|
---|
241 |
|
---|
242 | if (FeedWordPress::update_requested()) :
|
---|
243 | exit;
|
---|
244 | endif;
|
---|
245 | } /* feedwordpress_auto_update () */
|
---|
246 |
|
---|
247 | ################################################################################
|
---|
248 | ## LOGGING FUNCTIONS: log status updates to error_log if you want it ###########
|
---|
249 | ################################################################################
|
---|
250 |
|
---|
251 | function log_feedwordpress_post ($id) {
|
---|
252 | $post = wp_get_single_post($id);
|
---|
253 | error_log("[".date('Y-m-d H:i:s')."][feedwordpress] posted "
|
---|
254 | ."'{$post->post_title}' ({$post->post_date})");
|
---|
255 | }
|
---|
256 |
|
---|
257 | function log_feedwordpress_update_post ($id) {
|
---|
258 | $post = wp_get_single_post($id);
|
---|
259 | error_log("[".date('Y-m-d H:i:s')."][feedwordpress] updated "
|
---|
260 | ."'{$post->post_title}' ({$post->post_date})"
|
---|
261 | ." (as of {$post->post_modified})");
|
---|
262 | }
|
---|
263 |
|
---|
264 | function log_feedwordpress_update_feeds ($uri) {
|
---|
265 | error_log("[".date('Y-m-d H:i:s')."][feedwordpress] update('$uri')");
|
---|
266 | }
|
---|
267 |
|
---|
268 | function log_feedwordpress_check_feed ($feed) {
|
---|
269 | $uri = $feed['link/uri']; $name = $feed['link/name'];
|
---|
270 | error_log("[".date('Y-m-d H:i:s')."][feedwordpress] Examining $name <$uri>");
|
---|
271 | }
|
---|
272 |
|
---|
273 | function log_feedwordpress_update_complete ($delta) {
|
---|
274 | $mesg = array();
|
---|
275 | if (isset($delta['new'])) $mesg[] = 'added '.$delta['new'].' new posts';
|
---|
276 | if (isset($delta['updated'])) $mesg[] = 'updated '.$delta['updated'].' existing posts';
|
---|
277 | if (empty($mesg)) $mesg[] = 'nothing changed';
|
---|
278 |
|
---|
279 | error_log("[".date('Y-m-d H:i:s')."][feedwordpress] "
|
---|
280 | .(is_null($delta) ? "Error: I don't syndicate that URI"
|
---|
281 | : implode(' and ', $mesg)));
|
---|
282 | }
|
---|
283 |
|
---|
284 | ################################################################################
|
---|
285 | ## TEMPLATE API: functions to make your templates syndication-aware ############
|
---|
286 | ################################################################################
|
---|
287 |
|
---|
288 | function is_syndicated () { return (strlen(get_syndication_feed_id()) > 0); }
|
---|
289 |
|
---|
290 | function get_syndication_source_link ($original = NULL) {
|
---|
291 | if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
|
---|
292 | endif;
|
---|
293 |
|
---|
294 | if ($original) : $vals = get_post_custom_values('syndication_source_uri_original');
|
---|
295 | else : $vals = array();
|
---|
296 | endif;
|
---|
297 |
|
---|
298 | if (count($vals) == 0) : $vals = get_post_custom_values('syndication_source_uri');
|
---|
299 | endif;
|
---|
300 |
|
---|
301 | if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
|
---|
302 |
|
---|
303 | return $ret;
|
---|
304 | } /* function get_syndication_source_link() */
|
---|
305 |
|
---|
306 | function the_syndication_source_link ($original = NULL) { echo get_syndication_source_link($original); }
|
---|
307 |
|
---|
308 | function get_syndication_source ($original = NULL) {
|
---|
309 | if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
|
---|
310 | endif;
|
---|
311 |
|
---|
312 | if ($original) : $vals = get_post_custom_values('syndication_source_original');
|
---|
313 | else : $vals = array();
|
---|
314 | endif;
|
---|
315 |
|
---|
316 | if (count($vals) == 0) : $vals = get_post_custom_values('syndication_source');
|
---|
317 | endif;
|
---|
318 |
|
---|
319 | if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
|
---|
320 |
|
---|
321 | return $ret;
|
---|
322 | } /* function get_syndication_source() */
|
---|
323 |
|
---|
324 | function the_syndication_source ($original = NULL) { echo get_syndication_source($original); }
|
---|
325 |
|
---|
326 | function get_syndication_feed ($original = NULL) {
|
---|
327 | if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
|
---|
328 | endif;
|
---|
329 |
|
---|
330 | if ($original) : $vals = get_post_custom_values('syndication_feed_original');
|
---|
331 | else : $vals = array();
|
---|
332 | endif;
|
---|
333 |
|
---|
334 | if (count($vals) == 0) : $vals = get_post_custom_values('syndication_feed');
|
---|
335 | endif;
|
---|
336 |
|
---|
337 | if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
|
---|
338 |
|
---|
339 | return $ret;
|
---|
340 | } /* function get_syndication_feed() */
|
---|
341 |
|
---|
342 | function the_syndication_feed ($original = NULL) { echo get_syndication_feed ($original); }
|
---|
343 |
|
---|
344 | function get_syndication_feed_guid ($original = NULL) {
|
---|
345 | if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
|
---|
346 | endif;
|
---|
347 |
|
---|
348 | if ($original) : $vals = get_post_custom_values('syndication_source_id_original');
|
---|
349 | else : $vals = array();
|
---|
350 | endif;
|
---|
351 |
|
---|
352 | if (count($vals) == 0) : $vals = array(get_feed_meta('feed/id'));
|
---|
353 | endif;
|
---|
354 |
|
---|
355 | if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
|
---|
356 |
|
---|
357 | return $ret;
|
---|
358 | } /* function get_syndication_feed_guid () */
|
---|
359 |
|
---|
360 | function the_syndication_feed_guid ($original = NULL) { echo get_syndication_feed_guid($original); }
|
---|
361 |
|
---|
362 | function get_syndication_feed_id () { list($u) = get_post_custom_values('syndication_feed_id'); return $u; }
|
---|
363 | function the_syndication_feed_id () { echo get_syndication_feed_id(); }
|
---|
364 |
|
---|
365 | $feedwordpress_linkcache = array (); // only load links from database once
|
---|
366 |
|
---|
367 | function get_feed_meta ($key) {
|
---|
368 | global $wpdb, $feedwordpress_linkcache;
|
---|
369 | $feed_id = get_syndication_feed_id();
|
---|
370 |
|
---|
371 | $ret = NULL;
|
---|
372 | if (strlen($feed_id) > 0):
|
---|
373 | if (isset($feedwordpress_linkcache[$feed_id])) :
|
---|
374 | $link = $feedwordpress_linkcache[$feed_id];
|
---|
375 | else :
|
---|
376 | $link =& new SyndicatedLink($feed_id);
|
---|
377 | $feedwordpress_linkcache[$feed_id] = $link;
|
---|
378 | endif;
|
---|
379 |
|
---|
380 | $ret = $link->settings[$key];
|
---|
381 | endif;
|
---|
382 | return $ret;
|
---|
383 | } /* get_feed_meta() */
|
---|
384 |
|
---|
385 | function get_syndication_permalink () {
|
---|
386 | list($u) = get_post_custom_values('syndication_permalink'); return $u;
|
---|
387 | }
|
---|
388 | function the_syndication_permalink () {
|
---|
389 | echo get_syndication_permalink();
|
---|
390 | }
|
---|
391 |
|
---|
392 | ################################################################################
|
---|
393 | ## FILTERS: syndication-aware handling of post data for templates and feeds ####
|
---|
394 | ################################################################################
|
---|
395 |
|
---|
396 | $feedwordpress_the_syndicated_content = NULL;
|
---|
397 |
|
---|
398 | function feedwordpress_preserve_syndicated_content ($text) {
|
---|
399 | global $feedwordpress_the_syndicated_content;
|
---|
400 |
|
---|
401 | $globalExpose = (get_option('feedwordpress_formatting_filters') == 'yes');
|
---|
402 | $localExpose = get_post_custom_values('_feedwordpress_formatting_filters');
|
---|
403 | $expose = ($globalExpose or ((count($localExpose) > 0) and $localExpose[0]));
|
---|
404 |
|
---|
405 | if ( is_syndicated() and !$expose ) :
|
---|
406 | $feedwordpress_the_syndicated_content = $text;
|
---|
407 | else :
|
---|
408 | $feedwordpress_the_syndicated_content = NULL;
|
---|
409 | endif;
|
---|
410 | return $text;
|
---|
411 | }
|
---|
412 |
|
---|
413 | function feedwordpress_restore_syndicated_content ($text) {
|
---|
414 | global $feedwordpress_the_syndicated_content;
|
---|
415 |
|
---|
416 | if ( !is_null($feedwordpress_the_syndicated_content) ) :
|
---|
417 | $text = $feedwordpress_the_syndicated_content;
|
---|
418 | endif;
|
---|
419 |
|
---|
420 | return $text;
|
---|
421 | }
|
---|
422 |
|
---|
423 | function feedwordpress_item_feed_data () {
|
---|
424 | // In a post context....
|
---|
425 | if (is_syndicated()) :
|
---|
426 | ?>
|
---|
427 | <source>
|
---|
428 | <title><?php the_syndication_source(); ?></title>
|
---|
429 | <link rel="alternate" type="text/html" href="<?php the_syndication_source_link(); ?>" />
|
---|
430 | <link rel="self" href="<?php the_syndication_feed(); ?>" />
|
---|
431 | <?php
|
---|
432 | $id = get_syndication_feed_guid();
|
---|
433 | if (strlen($id) > 0) :
|
---|
434 | ?>
|
---|
435 | <id><?php print $id; ?></id>
|
---|
436 | <?php
|
---|
437 | endif;
|
---|
438 | $updated = get_feed_meta('feed/updated');
|
---|
439 | if (strlen($updated) > 0) : ?>
|
---|
440 | <updated><?php print $updated; ?></updated>
|
---|
441 | <?php
|
---|
442 | endif;
|
---|
443 | ?>
|
---|
444 | </source>
|
---|
445 | <?php
|
---|
446 | endif;
|
---|
447 | }
|
---|
448 |
|
---|
449 | function syndication_permalink ($permalink = '') {
|
---|
450 | if (get_option('feedwordpress_munge_permalink') != 'no'):
|
---|
451 | $uri = get_syndication_permalink();
|
---|
452 | return ((strlen($uri) > 0) ? $uri : $permalink);
|
---|
453 | else:
|
---|
454 | return $permalink;
|
---|
455 | endif;
|
---|
456 | } // function syndication_permalink ()
|
---|
457 |
|
---|
458 | ################################################################################
|
---|
459 | ## ADMIN MENU ADD-ONS: register Dashboard management pages #####################
|
---|
460 | ################################################################################
|
---|
461 |
|
---|
462 | function fwp_add_pages () {
|
---|
463 | global $fwp_capability;
|
---|
464 | global $fwp_path;
|
---|
465 |
|
---|
466 | $menu = array('Syndicated Sites', 'Syndication', $fwp_capability['manage_links'], $fwp_path.'/syndication.php', NULL);
|
---|
467 | if (fwp_test_wp_version(FWP_SCHEMA_27)) :
|
---|
468 | // add icon parameter
|
---|
469 | $menu[] = WP_PLUGIN_URL.'/'.$fwp_path.'/feedwordpress-tiny.png';
|
---|
470 | endif;
|
---|
471 |
|
---|
472 | if (fwp_test_wp_version(FWP_SCHEMA_26)) :
|
---|
473 | $options = __('Settings');
|
---|
474 | $longoptions = __('Syndication Settings');
|
---|
475 | else :
|
---|
476 | $options = __('Options');
|
---|
477 | $longoptions = __('Syndication Options');
|
---|
478 | endif;
|
---|
479 |
|
---|
480 | call_user_func_array('add_menu_page', $menu);
|
---|
481 | add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Posts', 'Posts', $fwp_capability['manage_options'], $fwp_path.'/posts-page.php');
|
---|
482 | add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Authors', 'Authors', $fwp_capability['manage_options'], $fwp_path.'/authors-page.php');
|
---|
483 | add_submenu_page($fwp_path.'/syndication.php', 'Categories & Tags', 'Categories & Tags', $fwp_capability['manage_options'], $fwp_path.'/categories-page.php');
|
---|
484 | add_submenu_page($fwp_path.'/syndication.php', $longoptions, $options, $fwp_capability['manage_options'], $fwp_path.'/syndication-options.php');
|
---|
485 |
|
---|
486 | add_options_page($longoptions, 'Syndication', $fwp_capability['manage_options'], $fwp_path.'/syndication-options.php');
|
---|
487 | } /* function fwp_add_pages () */
|
---|
488 |
|
---|
489 | function fwp_check_debug () {
|
---|
490 | // This is a horrible fucking kludge that I have to do because the
|
---|
491 | // admin notice code is triggered before the code that updates the
|
---|
492 | // setting.
|
---|
493 | if (isset($_POST['feedwordpress_debug'])) :
|
---|
494 | $feedwordpress_debug = $_POST['feedwordpress_debug'];
|
---|
495 | else :
|
---|
496 | $feedwordpress_debug = get_option('feedwordpress_debug');
|
---|
497 | endif;
|
---|
498 | if ($feedwordpress_debug==='yes') :
|
---|
499 | ?>
|
---|
500 | <div class="error">
|
---|
501 | <p><strong>FeedWordPress warning.</strong> Debugging mode is <strong>ON</strong>.
|
---|
502 | While it remains on, FeedWordPress displays many diagnostic error messages,
|
---|
503 | warnings, and notices that are ordinarily suppressed, and also turns off all
|
---|
504 | caching of feeds. Use with caution: this setting is absolutely inappropriate
|
---|
505 | for a production server.</p>
|
---|
506 | </div>
|
---|
507 | <?php
|
---|
508 | endif;
|
---|
509 | } /* function fwp_check_debug () */
|
---|
510 |
|
---|
511 | define('EXPECTED_MAGPIE_VERSION', '2009.0618');
|
---|
512 | function fwp_check_magpie () {
|
---|
513 | if (isset($_REQUEST['feedwordpress_magpie_fix'])) :
|
---|
514 | if ($_REQUEST['feedwordpress_magpie_fix']=='ignored') :
|
---|
515 | ?>
|
---|
516 | <div class="updated fade">
|
---|
517 | <p>O.K., we'll ignore the problem for now. FeedWordPress will not display any
|
---|
518 | more error messages.</p>
|
---|
519 | </div>
|
---|
520 | <?php
|
---|
521 | elseif ((bool) $_REQUEST['feedwordpress_magpie_fix']) :
|
---|
522 | ?>
|
---|
523 | <div class="updated fade">
|
---|
524 | <p>Congratulations! Your MagpieRSS has been successfully upgraded to the version
|
---|
525 | shipped with FeedWordPress.</p>
|
---|
526 | </div>
|
---|
527 | <?php
|
---|
528 | else :
|
---|
529 | $source = dirname(__FILE__)."/MagpieRSS-upgrade/rss.php";
|
---|
530 | $destination = ABSPATH . WPINC . '/rss.php';
|
---|
531 | $cmd = "cp '".htmlspecialchars(addslashes($source))."' '".htmlspecialchars(addslashes($destination))."'";
|
---|
532 | $cmd = wordwrap($cmd, /*width=*/ 75, /*break=*/ " \\\n\t");
|
---|
533 |
|
---|
534 | ?>
|
---|
535 | <div class="error">
|
---|
536 | <p><strong>FeedWordPress was unable to automatically upgrade your copy of MagpieRSS.</strong></p>
|
---|
537 | <p>It's likely that you need to change the file permissions on <code><?php print htmlspecialchars($source); ?></code>
|
---|
538 | to allow FeedWordPress to overwrite it.</p>
|
---|
539 | <p><strong>To perform the upgrade manually,</strong> you can
|
---|
540 | use a SFTP or FTP client to upload a copy of <code>rss.php</code> from the
|
---|
541 | <code>MagpieRSS-upgrades/</code> directory of your FeedWordPress archive so that
|
---|
542 | it overwrites <code><?php print htmlspecialchars($destination); ?></code>. Or,
|
---|
543 | if your web host provides shell access, you can issue the following command from
|
---|
544 | a command prompt to perform the upgrade:</p>
|
---|
545 | <pre>
|
---|
546 | <samp>$</samp> <kbd><?php print $cmd; ?></kbd>
|
---|
547 | </pre>
|
---|
548 | <p><strong>If you've fixed the file permissions,</strong> you can try the
|
---|
549 | automatic upgrade again.</p>
|
---|
550 |
|
---|
551 | <?php feedwordpress_upgrade_old_and_busted_buttons(); ?>
|
---|
552 | </div>
|
---|
553 | <?php
|
---|
554 | endif;
|
---|
555 | else :
|
---|
556 | $magpie_version = FeedWordPress::magpie_version();
|
---|
557 |
|
---|
558 | $ignored = get_option('feedwordpress_magpie_ignored_upgrade_to');
|
---|
559 | if (EXPECTED_MAGPIE_VERSION != $magpie_version and EXPECTED_MAGPIE_VERSION != $ignored) :
|
---|
560 | if (current_user_can('edit_files')) :
|
---|
561 | $youAre = 'you are';
|
---|
562 | $itIsRecommendedThatYou = 'It is <strong>strongly recommended</strong> that you';
|
---|
563 | else :
|
---|
564 | $youAre = 'this site is';
|
---|
565 | $itIsRecommendedThatYou = 'You may want to contact the administrator of the site; it is <strong>strongly recommended</strong> that they';
|
---|
566 | endif;
|
---|
567 | print '<div class="error">';
|
---|
568 | ?>
|
---|
569 | <p style="font-style: italic"><strong>FeedWordPress has detected that <?php print $youAre; ?> currently using a version of
|
---|
570 | MagpieRSS other than the upgraded version that ships with this version of FeedWordPress.</strong></p>
|
---|
571 | <ul>
|
---|
572 | <li><strong>Currently running:</strong> MagpieRSS <?php print $magpie_version; ?></li>
|
---|
573 | <li><strong>Version included with FeedWordPress <?php print FEEDWORDPRESS_VERSION; ?>:</strong> MagpieRSS <?php print EXPECTED_MAGPIE_VERSION; ?></li>
|
---|
574 | </ul>
|
---|
575 | <p><?php print $itIsRecommendedThatYou; ?> install the upgraded
|
---|
576 | version of MagpieRSS supplied with FeedWordPress. The version of
|
---|
577 | MagpieRSS that ships with WordPress is very old and buggy, and
|
---|
578 | encounters a number of errors when trying to parse modern Atom
|
---|
579 | and RSS feeds.</p>
|
---|
580 | <?php
|
---|
581 | feedwordpress_upgrade_old_and_busted_buttons();
|
---|
582 | print '</div>';
|
---|
583 | endif;
|
---|
584 | endif;
|
---|
585 | }
|
---|
586 |
|
---|
587 | function feedwordpress_upgrade_old_and_busted_buttons() {
|
---|
588 | if (current_user_can('edit_files')) :
|
---|
589 | ?>
|
---|
590 | <form action="" method="post"><div>
|
---|
591 | <?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_fix_magpie'); ?>
|
---|
592 | <input type="hidden" name="action" value="fix_magpie_version" />
|
---|
593 | <input class="button-secondary" type="submit" name="ignore" value="<?php _e('Ignore this problem'); ?>" />
|
---|
594 | <input class="button-primary" type="submit" name="upgrade" value="<?php _e('Upgrade'); ?>" />
|
---|
595 | </div></form>
|
---|
596 | <?php
|
---|
597 | endif;
|
---|
598 | }
|
---|
599 |
|
---|
600 | ################################################################################
|
---|
601 | ## fwp_hold_pings() and fwp_release_pings(): Outbound XML-RPC ping reform ####
|
---|
602 | ## ... 'coz it's rude to send 500 pings the first time your aggregator runs ####
|
---|
603 | ################################################################################
|
---|
604 |
|
---|
605 | $fwp_held_ping = NULL; // NULL: not holding pings yet
|
---|
606 |
|
---|
607 | function fwp_hold_pings () {
|
---|
608 | global $fwp_held_ping;
|
---|
609 | if (is_null($fwp_held_ping)):
|
---|
610 | $fwp_held_ping = 0; // 0: ready to hold pings; none yet received
|
---|
611 | endif;
|
---|
612 | }
|
---|
613 |
|
---|
614 | function fwp_release_pings () {
|
---|
615 | global $fwp_held_ping;
|
---|
616 | if ($fwp_held_ping):
|
---|
617 | if (function_exists('wp_schedule_single_event')) :
|
---|
618 | wp_schedule_single_event(time(), 'do_pings');
|
---|
619 | else :
|
---|
620 | generic_ping($fwp_held_ping);
|
---|
621 | endif;
|
---|
622 | endif;
|
---|
623 | $fwp_held_ping = NULL; // NULL: not holding pings anymore
|
---|
624 | }
|
---|
625 |
|
---|
626 | function fwp_do_pings () {
|
---|
627 | if (!is_null($fwp_held_ping) and $post_id) : // Defer until we're done updating
|
---|
628 | $fwp_held_ping = $post_id;
|
---|
629 | elseif (function_exists('do_all_pings')) :
|
---|
630 | do_all_pings();
|
---|
631 | else :
|
---|
632 | generic_ping($fwp_held_ping);
|
---|
633 | endif;
|
---|
634 | }
|
---|
635 |
|
---|
636 | function fwp_publish_post_hook ($post_id) {
|
---|
637 | global $fwp_held_ping;
|
---|
638 |
|
---|
639 | if (!is_null($fwp_held_ping)) : // Syndicated post. Don't mark with _pingme
|
---|
640 | if ( defined('XMLRPC_REQUEST') )
|
---|
641 | do_action('xmlrpc_publish_post', $post_id);
|
---|
642 | if ( defined('APP_REQUEST') )
|
---|
643 | do_action('app_publish_post', $post_id);
|
---|
644 |
|
---|
645 | if ( defined('WP_IMPORTING') )
|
---|
646 | return;
|
---|
647 |
|
---|
648 | // Defer sending out pings until we finish updating
|
---|
649 | $fwp_held_ping = $post_id;
|
---|
650 | else :
|
---|
651 | if (function_exists('_publish_post_hook')) : // WordPress 2.3
|
---|
652 | _publish_post_hook($post_id);
|
---|
653 | endif;
|
---|
654 | endif;
|
---|
655 | }
|
---|
656 |
|
---|
657 | ################################################################################
|
---|
658 | ## class FeedWordPress #########################################################
|
---|
659 | ################################################################################
|
---|
660 |
|
---|
661 | // class FeedWordPress: handles feed updates and plugs in to the XML-RPC interface
|
---|
662 | class FeedWordPress {
|
---|
663 | var $strip_attrs = array (
|
---|
664 | array('[a-z]+', 'style'),
|
---|
665 | array('[a-z]+', 'target'),
|
---|
666 | );
|
---|
667 | var $uri_attrs = array (
|
---|
668 | array('a', 'href'),
|
---|
669 | array('applet', 'codebase'),
|
---|
670 | array('area', 'href'),
|
---|
671 | array('blockquote', 'cite'),
|
---|
672 | array('body', 'background'),
|
---|
673 | array('del', 'cite'),
|
---|
674 | array('form', 'action'),
|
---|
675 | array('frame', 'longdesc'),
|
---|
676 | array('frame', 'src'),
|
---|
677 | array('iframe', 'longdesc'),
|
---|
678 | array('iframe', 'src'),
|
---|
679 | array('head', 'profile'),
|
---|
680 | array('img', 'longdesc'),
|
---|
681 | array('img', 'src'),
|
---|
682 | array('img', 'usemap'),
|
---|
683 | array('input', 'src'),
|
---|
684 | array('input', 'usemap'),
|
---|
685 | array('ins', 'cite'),
|
---|
686 | array('link', 'href'),
|
---|
687 | array('object', 'classid'),
|
---|
688 | array('object', 'codebase'),
|
---|
689 | array('object', 'data'),
|
---|
690 | array('object', 'usemap'),
|
---|
691 | array('q', 'cite'),
|
---|
692 | array('script', 'src')
|
---|
693 | );
|
---|
694 |
|
---|
695 | var $feeds = NULL;
|
---|
696 |
|
---|
697 | # function FeedWordPress (): Contructor; retrieve a list of feeds
|
---|
698 | function FeedWordPress () {
|
---|
699 | $this->feeds = array ();
|
---|
700 | $links = FeedWordPress::syndicated_links();
|
---|
701 | if ($links): foreach ($links as $link):
|
---|
702 | $this->feeds[] =& new SyndicatedLink($link);
|
---|
703 | endforeach; endif;
|
---|
704 | } // FeedWordPress::FeedWordPress ()
|
---|
705 |
|
---|
706 | # function update (): polls for updates on one or more Contributor feeds
|
---|
707 | #
|
---|
708 | # Arguments:
|
---|
709 | # ----------
|
---|
710 | # * $uri (string): either the URI of the feed to poll, the URI of the
|
---|
711 | # (human-readable) website whose feed you want to poll, or NULL.
|
---|
712 | #
|
---|
713 | # If $uri is NULL, then FeedWordPress will poll any feeds that are
|
---|
714 | # ready for polling. It will not poll feeds that are marked as
|
---|
715 | # "Invisible" Links (signifying that the subscription has been
|
---|
716 | # de-activated), or feeds that are not yet stale according to their
|
---|
717 | # TTL setting (which is either set in the feed, or else set
|
---|
718 | # randomly within a window of 30 minutes - 2 hours).
|
---|
719 | #
|
---|
720 | # Returns:
|
---|
721 | # --------
|
---|
722 | # * Normally returns an associative array, with 'new' => the number
|
---|
723 | # of new posts added during the update, and 'updated' => the number
|
---|
724 | # of old posts that were updated during the update. If both numbers
|
---|
725 | # are zero, there was no change since the last poll on that URI.
|
---|
726 | #
|
---|
727 | # * Returns NULL if URI it was passed was not a URI that this
|
---|
728 | # installation of FeedWordPress syndicates.
|
---|
729 | #
|
---|
730 | # Effects:
|
---|
731 | # --------
|
---|
732 | # * One or more feeds are polled for updates
|
---|
733 | #
|
---|
734 | # * If the feed Link does not have a hardcoded name set, its Link
|
---|
735 | # Name is synchronized with the feed's title element
|
---|
736 | #
|
---|
737 | # * If the feed Link does not have a hardcoded URI set, its Link URI
|
---|
738 | # is synchronized with the feed's human-readable link element
|
---|
739 | #
|
---|
740 | # * If the feed Link does not have a hardcoded description set, its
|
---|
741 | # Link Description is synchronized with the feed's description,
|
---|
742 | # tagline, or subtitle element.
|
---|
743 | #
|
---|
744 | # * The time of polling is recorded in the feed's settings, and the
|
---|
745 | # TTL (time until the feed is next available for polling) is set
|
---|
746 | # either from the feed (if it is supplied in the ttl or syndication
|
---|
747 | # module elements) or else from a randomly-generated time window
|
---|
748 | # (between 30 minutes and 2 hours).
|
---|
749 | #
|
---|
750 | # * New posts from the polled feed are added to the WordPress store.
|
---|
751 | #
|
---|
752 | # * Updates to existing posts since the last poll are mirrored in the
|
---|
753 | # WordPress store.
|
---|
754 | #
|
---|
755 | function update ($uri = null, $crash_ts = null) {
|
---|
756 | global $wpdb;
|
---|
757 |
|
---|
758 | if (FeedWordPress::needs_upgrade()) : // Will make duplicate posts if we don't hold off
|
---|
759 | return NULL;
|
---|
760 | endif;
|
---|
761 |
|
---|
762 | if (!is_null($uri)) :
|
---|
763 | $uri = trim($uri);
|
---|
764 | else : // Update all
|
---|
765 | update_option('feedwordpress_last_update_all', time());
|
---|
766 | endif;
|
---|
767 |
|
---|
768 | do_action('feedwordpress_update', $uri);
|
---|
769 |
|
---|
770 | if (is_null($crash_ts)) :
|
---|
771 | $crash_dt = (int) get_option('feedwordpress_update_time_limit');
|
---|
772 | if ($crash_dt > 0) :
|
---|
773 | $crash_ts = time() + $crash_dt;
|
---|
774 | else :
|
---|
775 | $crash_ts = NULL;
|
---|
776 | endif;
|
---|
777 | endif;
|
---|
778 |
|
---|
779 | // Randomize order for load balancing purposes
|
---|
780 | $feed_set = $this->feeds;
|
---|
781 | shuffle($feed_set);
|
---|
782 |
|
---|
783 | // Loop through and check for new posts
|
---|
784 | $delta = NULL;
|
---|
785 | foreach ($feed_set as $feed) :
|
---|
786 | if (!is_null($crash_ts) and (time() > $crash_ts)) : // Check whether we've exceeded the time limit
|
---|
787 | break;
|
---|
788 | endif;
|
---|
789 |
|
---|
790 | $pinged_that = (is_null($uri) or in_array($uri, array($feed->uri(), $feed->homepage())));
|
---|
791 |
|
---|
792 | if (!is_null($uri)) : // A site-specific ping always updates
|
---|
793 | $timely = true;
|
---|
794 | else :
|
---|
795 | $timely = $feed->stale();
|
---|
796 | endif;
|
---|
797 |
|
---|
798 | if ($pinged_that and is_null($delta)) : // If at least one feed was hit for updating...
|
---|
799 | $delta = array('new' => 0, 'updated' => 0); // ... don't return error condition
|
---|
800 | endif;
|
---|
801 |
|
---|
802 | if ($pinged_that and $timely) :
|
---|
803 | do_action('feedwordpress_check_feed', $feed->settings);
|
---|
804 | $start_ts = time();
|
---|
805 | $added = $feed->poll($crash_ts);
|
---|
806 | do_action('feedwordpress_check_feed_complete', $feed->settings, $added, time() - $start_ts);
|
---|
807 |
|
---|
808 | if (isset($added['new'])) : $delta['new'] += $added['new']; endif;
|
---|
809 | if (isset($added['updated'])) : $delta['updated'] += $added['updated']; endif;
|
---|
810 | endif;
|
---|
811 | endforeach;
|
---|
812 |
|
---|
813 | do_action('feedwordpress_update_complete', $delta);
|
---|
814 |
|
---|
815 | return $delta;
|
---|
816 | }
|
---|
817 |
|
---|
818 | function stale () {
|
---|
819 | if (get_option('feedwordpress_automatic_updates')) :
|
---|
820 | $last = get_option('feedwordpress_last_update_all');
|
---|
821 |
|
---|
822 | // If we haven't updated all yet, give it a time window
|
---|
823 | if (false === $last) :
|
---|
824 | $ret = false;
|
---|
825 | update_option('feedwordpress_last_update_all', time());
|
---|
826 |
|
---|
827 | // Otherwise, check against freshness interval
|
---|
828 | elseif (is_numeric($last)) : // Expect a timestamp
|
---|
829 | $freshness = get_option('feedwordpress_freshness');
|
---|
830 | if (false === $freshness) : // Use default
|
---|
831 | $freshness = FEEDWORDPRESS_FRESHNESS_INTERVAL;
|
---|
832 | endif;
|
---|
833 | $ret = ( (time() - $last) > $freshness);
|
---|
834 |
|
---|
835 | // This should never happen.
|
---|
836 | else :
|
---|
837 | FeedWordPress::critical_bug('FeedWordPress::stale::last', $last, __LINE__);
|
---|
838 | endif;
|
---|
839 |
|
---|
840 | // Explicit request for an update (e.g. from a cron job).
|
---|
841 | elseif (FeedWordPress::update_requested()) :
|
---|
842 | $ret = true;
|
---|
843 |
|
---|
844 | else :
|
---|
845 | $ret = false;
|
---|
846 | endif;
|
---|
847 | return $ret;
|
---|
848 | } // FeedWordPress::stale()
|
---|
849 |
|
---|
850 | function update_requested () {
|
---|
851 | return (isset($_REQUEST['update_feedwordpress']) and $_REQUEST['update_feedwordpress']);
|
---|
852 | } // FeedWordPress::update_requested()
|
---|
853 |
|
---|
854 | function syndicate_link ($name, $uri, $rss) {
|
---|
855 | global $wpdb;
|
---|
856 |
|
---|
857 | // Get the category ID#
|
---|
858 | $cat_id = FeedWordPress::link_category_id();
|
---|
859 |
|
---|
860 | // WordPress gets cranky if there's no homepage URI
|
---|
861 | if (!isset($uri) or strlen($uri)<1) : $uri = $rss; endif;
|
---|
862 |
|
---|
863 | if (function_exists('wp_insert_link')) { // WordPress 2.x
|
---|
864 | $link_id = wp_insert_link(array(
|
---|
865 | "link_name" => $name,
|
---|
866 | "link_url" => $uri,
|
---|
867 | "link_category" => (fwp_test_wp_version(0, FWP_SCHEMA_21) ? $cat_id : array($cat_id)),
|
---|
868 | "link_rss" => $rss
|
---|
869 | ));
|
---|
870 | } else { // WordPress 1.5.x
|
---|
871 | $result = $wpdb->query("
|
---|
872 | INSERT INTO $wpdb->links
|
---|
873 | SET
|
---|
874 | link_name = '".$wpdb->escape($name)."',
|
---|
875 | link_url = '".$wpdb->escape($uri)."',
|
---|
876 | link_category = '".$wpdb->escape($cat_id)."',
|
---|
877 | link_rss = '".$wpdb->escape($rss)."'
|
---|
878 | ");
|
---|
879 | $link_id = $wpdb->insert_id;
|
---|
880 | } // if
|
---|
881 | return $link_id;
|
---|
882 | } // function FeedWordPress::syndicate_link()
|
---|
883 |
|
---|
884 | function on_unfamiliar ($what = 'author', $override = NULL) {
|
---|
885 | $set = array(
|
---|
886 | 'author' => array('create', 'default', 'filter'),
|
---|
887 | 'category' => array('create', 'tag', 'default', 'filter'),
|
---|
888 | );
|
---|
889 |
|
---|
890 | if (is_string($override)) :
|
---|
891 | $ret = strtolower($override);
|
---|
892 | endif;
|
---|
893 |
|
---|
894 | if (!is_numeric($override) and !in_array($ret, $set[$what])) :
|
---|
895 | $ret = get_option('feedwordpress_unfamiliar_'.$what);
|
---|
896 | if (!is_numeric($ret) and !in_array($ret, $set[$what])) :
|
---|
897 | $ret = 'create';
|
---|
898 | endif;
|
---|
899 | endif;
|
---|
900 |
|
---|
901 | return $ret;
|
---|
902 | } // function FeedWordPress::on_unfamiliar()
|
---|
903 |
|
---|
904 | function null_email_set () {
|
---|
905 | $base = get_option('feedwordpress_null_email_set');
|
---|
906 |
|
---|
907 | if ($base===false) :
|
---|
908 | $ret = array('noreply@blogger.com'); // default
|
---|
909 | else :
|
---|
910 | $ret = array_map('strtolower',
|
---|
911 | array_map('trim', explode("\n", $base)));
|
---|
912 | endif;
|
---|
913 | $ret = apply_filters('syndicated_item_author_null_email_set', $ret);
|
---|
914 | return $ret;
|
---|
915 |
|
---|
916 | } /* FeedWordPress::null_email_set () */
|
---|
917 |
|
---|
918 | function is_null_email ($email) {
|
---|
919 | $ret = in_array(strtolower(trim($email)), FeedWordPress::null_email_set());
|
---|
920 | $ret = apply_filters('syndicated_item_author_is_null_email', $ret, $email);
|
---|
921 | return $ret;
|
---|
922 | } /* FeedWordPress::is_null_email () */
|
---|
923 |
|
---|
924 | function use_aggregator_source_data () {
|
---|
925 | $ret = get_option('feedwordpress_use_aggregator_source_data');
|
---|
926 | return apply_filters('syndicated_post_use_aggregator_source_data', ($ret=='yes'));
|
---|
927 | }
|
---|
928 |
|
---|
929 | function syndicated_links () {
|
---|
930 | $contributors = FeedWordPress::link_category_id();
|
---|
931 | if (function_exists('get_bookmarks')) :
|
---|
932 | $links = get_bookmarks(array("category" => $contributors));
|
---|
933 | else:
|
---|
934 | $links = get_linkobjects($contributors); // deprecated as of WP 2.1
|
---|
935 | endif;
|
---|
936 | return $links;
|
---|
937 | } // function FeedWordPress::syndicated_links()
|
---|
938 |
|
---|
939 | function link_category_id () {
|
---|
940 | global $wpdb, $wp_db_version;
|
---|
941 |
|
---|
942 | $cat_id = get_option('feedwordpress_cat_id');
|
---|
943 |
|
---|
944 | // If we don't yet *have* the category, we'll have to create it
|
---|
945 | if ($cat_id === false) :
|
---|
946 | $cat = $wpdb->escape(DEFAULT_SYNDICATION_CATEGORY);
|
---|
947 |
|
---|
948 | // Look for something with the right name...
|
---|
949 | // -----------------------------------------
|
---|
950 |
|
---|
951 | // WordPress 2.3 introduces a new taxonomy/term API
|
---|
952 | if (function_exists('is_term')) :
|
---|
953 | $cat_id = is_term($cat, 'link_category');
|
---|
954 | // WordPress 2.1 and 2.2 use a common table for both link and post categories
|
---|
955 | elseif (fwp_test_wp_version(FWP_SCHEMA_21, FWP_SCHEMA_23)) :
|
---|
956 | $cat_id = $wpdb->get_var("SELECT cat_id FROM {$wpdb->categories} WHERE cat_name='$cat'");
|
---|
957 | // WordPress 1.5 and 2.0.x have a separate table for link categories
|
---|
958 | elseif (fwp_test_wp_version(0, FWP_SCHEMA_21)):
|
---|
959 | $cat_id = $wpdb->get_var("SELECT cat_id FROM {$wpdb->linkcategories} WHERE cat_name='$cat'");
|
---|
960 | // This should never happen.
|
---|
961 | else :
|
---|
962 | FeedWordPress::critical_bug('FeedWordPress::link_category_id::wp_db_version', $wp_db_version, __LINE__);
|
---|
963 | endif;
|
---|
964 |
|
---|
965 | // If you still can't find anything, make it for yourself.
|
---|
966 | // -------------------------------------------------------
|
---|
967 | if (!$cat_id) :
|
---|
968 | // WordPress 2.3+ term/taxonomy API
|
---|
969 | if (function_exists('wp_insert_term')) :
|
---|
970 | $term = wp_insert_term($cat, 'link_category');
|
---|
971 | $cat_id = $term['term_id'];
|
---|
972 | // WordPress 2.1, 2.2 category API. By the way, why the fuck is this API function only available in a wp-admin module?
|
---|
973 | elseif (function_exists('wp_insert_category') and !fwp_test_wp_version(FWP_SCHEMA_20, FWP_SCHEMA_21)) :
|
---|
974 | $cat_id = wp_insert_category(array('cat_name' => $cat));
|
---|
975 | // WordPress 1.5 and 2.0.x
|
---|
976 | elseif (fwp_test_wp_version(0, FWP_SCHEMA_21)) :
|
---|
977 | $result = $wpdb->query("
|
---|
978 | INSERT INTO $wpdb->linkcategories
|
---|
979 | SET
|
---|
980 | cat_id = 0,
|
---|
981 | cat_name='$cat',
|
---|
982 | show_images='N',
|
---|
983 | show_description='N',
|
---|
984 | show_rating='N',
|
---|
985 | show_updated='N',
|
---|
986 | sort_order='name'
|
---|
987 | ");
|
---|
988 | $cat_id = $wpdb->insert_id;
|
---|
989 | // This should never happen.
|
---|
990 | else :
|
---|
991 | FeedWordPress::critical_bug('FeedWordPress::link_category_id::wp_db_version', $wp_db_version, __LINE__);
|
---|
992 | endif;
|
---|
993 | endif;
|
---|
994 |
|
---|
995 | update_option('feedwordpress_cat_id', $cat_id);
|
---|
996 | endif;
|
---|
997 | return $cat_id;
|
---|
998 | } // function FeedWordPress::link_category_id()
|
---|
999 |
|
---|
1000 | # Upgrades and maintenance...
|
---|
1001 | function needs_upgrade () {
|
---|
1002 | global $wpdb;
|
---|
1003 | $fwp_db_version = get_option('feedwordpress_version');
|
---|
1004 | $ret = false; // innocent until proven guilty
|
---|
1005 | if (!$fwp_db_version or $fwp_db_version < FEEDWORDPRESS_VERSION) :
|
---|
1006 | // This is an older version or a fresh install. Does it
|
---|
1007 | // require a database upgrade or database initialization?
|
---|
1008 | if ($fwp_db_version <= 0.96) :
|
---|
1009 | // Yes. Check to see whether this is a fresh install or an upgrade.
|
---|
1010 | $syn = $wpdb->get_col("
|
---|
1011 | SELECT post_id
|
---|
1012 | FROM $wpdb->postmeta
|
---|
1013 | WHERE meta_key = 'syndication_feed'
|
---|
1014 | ");
|
---|
1015 | if (count($syn) > 0) : // contains at least one syndicated post
|
---|
1016 | $ret = true;
|
---|
1017 | else : // fresh install; brand it as ours
|
---|
1018 | update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
|
---|
1019 | endif;
|
---|
1020 | elseif ($fwp_db_version < 2009.0707) :
|
---|
1021 | // We need to clear out any busted AJAX crap
|
---|
1022 | if (fwp_test_wp_version(FWP_SCHEMA_HAS_USERMETA)) :
|
---|
1023 | $wpdb->query("
|
---|
1024 | DELETE FROM $wpdb->usermeta
|
---|
1025 | WHERE LOCATE('feedwordpress', meta_key)
|
---|
1026 | AND LOCATE('box', meta_key);
|
---|
1027 | ");
|
---|
1028 | endif;
|
---|
1029 | update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
|
---|
1030 | else :
|
---|
1031 | // No. Just brand it with the new version.
|
---|
1032 | update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
|
---|
1033 | endif;
|
---|
1034 | endif;
|
---|
1035 | return $ret;
|
---|
1036 | }
|
---|
1037 |
|
---|
1038 | function upgrade_database ($from = NULL) {
|
---|
1039 | global $wpdb;
|
---|
1040 |
|
---|
1041 | if (is_null($from) or $from <= 0.96) : $from = 0.96; endif;
|
---|
1042 |
|
---|
1043 | switch ($from) :
|
---|
1044 | case 0.96: // account for changes to syndication custom values and guid
|
---|
1045 | echo "<p>Upgrading database from {$from} to ".FEEDWORDPRESS_VERSION."...</p>\n";
|
---|
1046 |
|
---|
1047 | $cat_id = FeedWordPress::link_category_id();
|
---|
1048 |
|
---|
1049 | // Avoid duplicates
|
---|
1050 | $wpdb->query("DELETE FROM `{$wpdb->postmeta}` WHERE meta_key = 'syndication_feed_id'");
|
---|
1051 |
|
---|
1052 | // Look up all the link IDs
|
---|
1053 | $wpdb->query("
|
---|
1054 | CREATE TEMPORARY TABLE tmp_custom_values
|
---|
1055 | SELECT
|
---|
1056 | NULL AS meta_id,
|
---|
1057 | post_id,
|
---|
1058 | 'syndication_feed_id' AS meta_key,
|
---|
1059 | link_id AS meta_value
|
---|
1060 | FROM `{$wpdb->postmeta}`, `{$wpdb->links}`
|
---|
1061 | WHERE
|
---|
1062 | meta_key='syndication_feed'
|
---|
1063 | AND meta_value=link_rss
|
---|
1064 | AND link_category = {$cat_id}
|
---|
1065 | ");
|
---|
1066 |
|
---|
1067 | // Now attach them to their posts
|
---|
1068 | $wpdb->query("INSERT INTO `{$wpdb->postmeta}` SELECT * FROM tmp_custom_values");
|
---|
1069 |
|
---|
1070 | // And clean up after ourselves.
|
---|
1071 | $wpdb->query("DROP TABLE tmp_custom_values");
|
---|
1072 |
|
---|
1073 | // Now fix the guids to avoid duplicate posts
|
---|
1074 | echo "<ul>";
|
---|
1075 | foreach ($this->feeds as $feed) :
|
---|
1076 | echo "<li>Fixing post meta-data for <cite>".$feed['link/name']."</cite> … "; flush();
|
---|
1077 | $rss = @fetch_rss($feed['link/uri']);
|
---|
1078 | if (is_array($rss->items)) :
|
---|
1079 | foreach ($rss->items as $item) :
|
---|
1080 | $guid = $wpdb->escape(FeedWordPress::guid($item, $feed)); // new GUID algorithm
|
---|
1081 | $link = $wpdb->escape($item['link']);
|
---|
1082 |
|
---|
1083 | $wpdb->query("
|
---|
1084 | UPDATE `{$wpdb->posts}` SET guid='{$guid}' WHERE guid='{$link}'
|
---|
1085 | ");
|
---|
1086 | endforeach;
|
---|
1087 | endif;
|
---|
1088 | echo "<strong>complete.</strong></li>\n";
|
---|
1089 | endforeach;
|
---|
1090 | echo "</ul>\n";
|
---|
1091 |
|
---|
1092 | // Mark the upgrade as successful.
|
---|
1093 | update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
|
---|
1094 | endswitch;
|
---|
1095 | echo "<p>Upgrade complete. FeedWordPress is now ready to use again.</p>";
|
---|
1096 | } /* FeedWordPress::upgrade_database() */
|
---|
1097 |
|
---|
1098 | function create_guid_index () {
|
---|
1099 | global $wpdb;
|
---|
1100 |
|
---|
1101 | $wpdb->query("
|
---|
1102 | CREATE INDEX {$wpdb->posts}_guid_idx ON {$wpdb->posts}(guid)
|
---|
1103 | ");
|
---|
1104 | } /* FeedWordPress::create_guid_index () */
|
---|
1105 |
|
---|
1106 | function magpie_version () {
|
---|
1107 | if (!defined('MAGPIE_VERSION')) : $magpie_version = $GLOBALS['wp_version'].'-default';
|
---|
1108 | else : $magpie_version = MAGPIE_VERSION;
|
---|
1109 | endif;
|
---|
1110 | return $magpie_version;
|
---|
1111 | }
|
---|
1112 |
|
---|
1113 | # Utility functions for handling text settings
|
---|
1114 | function negative ($f, $setting) {
|
---|
1115 | $nego = array ('n', 'no', 'f', 'false');
|
---|
1116 | return (isset($f[$setting]) and in_array(strtolower($f[$setting]), $nego));
|
---|
1117 | }
|
---|
1118 |
|
---|
1119 | function affirmative ($f, $setting) {
|
---|
1120 | $affirmo = array ('y', 'yes', 't', 'true', 1);
|
---|
1121 | return (isset($f[$setting]) and in_array(strtolower($f[$setting]), $affirmo));
|
---|
1122 | }
|
---|
1123 |
|
---|
1124 |
|
---|
1125 | # Internal debugging functions
|
---|
1126 | function critical_bug ($varname, $var, $line) {
|
---|
1127 | global $wp_version;
|
---|
1128 |
|
---|
1129 | if (defined('MAGPIE_VERSION')) : $mv = MAGPIE_VERSION;
|
---|
1130 | else : $mv = 'WordPress '.$wp_version.' default.';
|
---|
1131 | endif;
|
---|
1132 |
|
---|
1133 | echo '<p>There may be a bug in FeedWordPress. Please <a href="'.FEEDWORDPRESS_AUTHOR_CONTACT.'">contact the author</a> and paste the following information into your e-mail:</p>';
|
---|
1134 | echo "\n<plaintext>";
|
---|
1135 | echo "Triggered at line # ".$line."\n";
|
---|
1136 | echo "FeedWordPress version: ".FEEDWORDPRESS_VERSION."\n";
|
---|
1137 | echo "MagpieRSS version: {$mv}\n";
|
---|
1138 | echo "WordPress version: {$wp_version}\n";
|
---|
1139 | echo "PHP version: ".phpversion()."\n";
|
---|
1140 | echo "\n";
|
---|
1141 | echo $varname.": "; var_dump($var); echo "\n";
|
---|
1142 | die;
|
---|
1143 | }
|
---|
1144 |
|
---|
1145 | function noncritical_bug ($varname, $var, $line) {
|
---|
1146 | if (FEEDWORDPRESS_DEBUG) : // halt only when we are doing debugging
|
---|
1147 | FeedWordPress::critical_bug($varname, $var, $line);
|
---|
1148 | endif;
|
---|
1149 | }
|
---|
1150 | } // class FeedWordPress
|
---|
1151 |
|
---|
1152 | require_once(dirname(__FILE__) . '/syndicatedpost.class.php');
|
---|
1153 | require_once(dirname(__FILE__) . '/syndicatedlink.class.php');
|
---|
1154 |
|
---|
1155 | ################################################################################
|
---|
1156 | ## XML-RPC HOOKS: accept XML-RPC update pings from Contributors ################
|
---|
1157 | ################################################################################
|
---|
1158 |
|
---|
1159 | function feedwordpress_xmlrpc_hook ($args = array ()) {
|
---|
1160 | $args['weblogUpdates.ping'] = 'feedwordpress_pong';
|
---|
1161 | return $args;
|
---|
1162 | }
|
---|
1163 |
|
---|
1164 | function feedwordpress_pong ($args) {
|
---|
1165 | $feedwordpress =& new FeedWordPress;
|
---|
1166 | $delta = @$feedwordpress->update($args[1]);
|
---|
1167 | if (is_null($delta)):
|
---|
1168 | return array('flerror' => true, 'message' => "Sorry. I don't syndicate <$args[1]>.");
|
---|
1169 | else:
|
---|
1170 | $mesg = array();
|
---|
1171 | if (isset($delta['new'])) { $mesg[] = ' '.$delta['new'].' new posts were syndicated'; }
|
---|
1172 | if (isset($delta['updated'])) { $mesg[] = ' '.$delta['updated'].' existing posts were updated'; }
|
---|
1173 |
|
---|
1174 | return array('flerror' => false, 'message' => "Thanks for the ping.".implode(' and', $mesg));
|
---|
1175 | endif;
|
---|
1176 | }
|
---|
1177 |
|
---|
1178 | # The upgraded MagpieRSS also uses this class. So if we have it loaded
|
---|
1179 | # in, don't load it again.
|
---|
1180 | if (!class_exists('Relative_URI')) {
|
---|
1181 | require_once(dirname(__FILE__) . '/relative_uri.class.php');
|
---|
1182 | }
|
---|
1183 |
|
---|
1184 | // take your best guess at the realname and e-mail, given a string
|
---|
1185 | define('FWP_REGEX_EMAIL_ADDY', '([^@"(<\s]+@[^"@(<\s]+\.[^"@(<\s]+)');
|
---|
1186 | define('FWP_REGEX_EMAIL_NAME', '("([^"]*)"|([^"<(]+\S))');
|
---|
1187 | define('FWP_REGEX_EMAIL_POSTFIX_NAME', '/^\s*'.FWP_REGEX_EMAIL_ADDY."\s+\(".FWP_REGEX_EMAIL_NAME.'\)\s*$/');
|
---|
1188 | define('FWP_REGEX_EMAIL_PREFIX_NAME', '/^\s*'.FWP_REGEX_EMAIL_NAME.'\s*<'.FWP_REGEX_EMAIL_ADDY.'>\s*$/');
|
---|
1189 | define('FWP_REGEX_EMAIL_JUST_ADDY', '/^\s*'.FWP_REGEX_EMAIL_ADDY.'\s*$/');
|
---|
1190 | define('FWP_REGEX_EMAIL_JUST_NAME', '/^\s*'.FWP_REGEX_EMAIL_NAME.'\s*$/');
|
---|
1191 |
|
---|
1192 | function parse_email_with_realname ($email) {
|
---|
1193 | if (preg_match(FWP_REGEX_EMAIL_POSTFIX_NAME, $email, $matches)) :
|
---|
1194 | ($ret['name'] = $matches[3]) or ($ret['name'] = $matches[2]);
|
---|
1195 | $ret['email'] = $matches[1];
|
---|
1196 | elseif (preg_match(FWP_REGEX_EMAIL_PREFIX_NAME, $email, $matches)) :
|
---|
1197 | ($ret['name'] = $matches[2]) or ($ret['name'] = $matches[3]);
|
---|
1198 | $ret['email'] = $matches[4];
|
---|
1199 | elseif (preg_match(FWP_REGEX_EMAIL_JUST_ADDY, $email, $matches)) :
|
---|
1200 | $ret['name'] = NULL; $ret['email'] = $matches[1];
|
---|
1201 | elseif (preg_match(FWP_REGEX_EMAIL_JUST_NAME, $email, $matches)) :
|
---|
1202 | $ret['email'] = NULL;
|
---|
1203 | ($ret['name'] = $matches[2]) or ($ret['name'] = $matches[3]);
|
---|
1204 | else :
|
---|
1205 | $ret['name'] = NULL; $ret['email'] = NULL;
|
---|
1206 | endif;
|
---|
1207 | return $ret;
|
---|
1208 | }
|
---|
1209 |
|
---|