PluginProbe
FeedWordPress / 2009.1111
FeedWordPress v2009.1111
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
feedwordpress / feedwordpress.php

feedwordpress.php in FeedWordPress 2009.1111, at feedwordpress.php

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