PluginProbe
FeedWordPress / 2008.1214
FeedWordPress v2008.1214
trunk 0.8 0.9 0.91 0.95 0.96 0.97 0.98 0.981 0.99 0.991 0.992 0.993 2008.1030 2008.1101 2008.1105 2008.1214 2009.0612 2009.0613 2009.0618 2009.0707 2009.1111 2009.1112 2010.0127 2010.0528 All 65 releases
← All changes | feedwordpress.php +755 -1277 0.9912008.1214 View file →
@@ -2,13 +2,13 @@
2 2 /*
3 3 Plugin Name: FeedWordPress
4 4 Plugin URI: http://projects.radgeek.com/feedwordpress
5 5 Description: simple and flexible Atom/RSS syndication for WordPress
6 -Version: 0.991
6 +Version: 2008.1214
7 7 Author: Charles Johnson
8 8 Author URI: http://radgeek.com/
9 9 License: GPL
10 -Last modified: 2007-09-25 12:48 PDT
10 +Last modified: 2008-12-14 4:29pm PST
11 11 */
12 12
13 13 # This uses code derived from:
14 14 # - wp-rss-aggregate.php by Kellan Elliot-McCrea <kellan@protest.net>
@@ -15,20 +15,22 @@
15 15 # - HTTP Navigator 2 by Keyvan Minoukadeh <keyvan@k1m.com>
16 16 # - Ultra-Liberal Feed Finder by Mark Pilgrim <mark@diveintomark.org>
17 17 # according to the terms of the GNU General Public License.
18 18 #
19 -# INSTALLATION: see README.text or <http://projects.radgeek.com/install>
19 +# INSTALLATION: see readme.txt or <http://projects.radgeek.com/install>
20 20 #
21 21 # USAGE: once FeedWordPress is installed, you manage just about everything from
22 -# the WordPress Dashboard, under Options --> Syndication or Links --> Syndicated
23 -# To ensure that fresh content is added as it becomes available, get your
24 -# contributors to put your XML-RPC URI (if WordPress is installed at
22 +# the WordPress Dashboard, under the Syndication menu. To ensure that fresh
23 +# content is added as it becomes available, you can convince your contributors
24 +# to put your XML-RPC URI (if WordPress is installed at
25 25 # <http://www.zyx.com/blog>, XML-RPC requests should be sent to
26 -# <http://www.zyx.com/blog/xmlrpc.php>), or see `update-feeds.php`
26 +# <http://www.zyx.com/blog/xmlrpc.php>), or update manually under the
27 +# Syndication menu, or set up automatic updates under Syndication --> Settings,
28 +# or use a cron job.
27 29
28 30 # -- Don't change these unless you know what you're doing...
29 31
30 -define ('FEEDWORDPRESS_VERSION', '0.991');
32 +define ('FEEDWORDPRESS_VERSION', '2008.1214');
31 33 define ('FEEDWORDPRESS_AUTHOR_CONTACT', 'http://radgeek.com/contact');
32 34 define ('DEFAULT_SYNDICATION_CATEGORY', 'Contributors');
33 35
34 36 define ('FEEDWORDPRESS_DEBUG', false);
@@ -39,11 +41,15 @@
39 41 define ('FEEDVALIDATOR_URI', 'http://feedvalidator.org/check.cgi');
40 42
41 43 define ('FEEDWORDPRESS_FRESHNESS_INTERVAL', 10*60); // Every ten minutes
42 44
45 +define ('FWP_SCHEMA_HAS_USERMETA', 2966);
43 46 define ('FWP_SCHEMA_20', 3308); // Database schema # for WP 2.0
44 47 define ('FWP_SCHEMA_21', 4772); // Database schema # for WP 2.1
45 48 define ('FWP_SCHEMA_23', 5495); // Database schema # for WP 2.3
49 +define ('FWP_SCHEMA_25', 7558); // Database schema # for WP 2.5
50 +define ('FWP_SCHEMA_26', 8201); // Database schema # for WP 2.6
51 +define ('FWP_SCHEMA_27', 9872); // Database schema # for WP 2.7
46 52
47 53 if (FEEDWORDPRESS_DEBUG) :
48 54 // Help us to pick out errors, if any.
49 55 ini_set('error_reporting', E_ALL & ~E_NOTICE);
@@ -81,11 +87,9 @@
81 87 require_once (ABSPATH . 'wp-admin/admin-db.php'); // for wp_insert_category
82 88 endif;
83 89 endif;
84 90
85 -if (function_exists('wp_enqueue_script')) :
86 - wp_enqueue_script( 'ajaxcat' ); // Provides the handy-dandy new category text box
87 -endif;
91 +require_once(dirname(__FILE__) . '/compatability.php'); // LEGACY API: Replicate or mock up functions for legacy support purposes
88 92
89 93 // Magic quotes are just about the stupidest thing ever.
90 94 if (is_array($_POST)) :
91 95 $fwp_post = stripslashes_deep($_POST);
@@ -90,9 +94,45 @@
90 94 if (is_array($_POST)) :
91 95 $fwp_post = stripslashes_deep($_POST);
92 96 endif;
93 97
98 +// Get the path relative to the plugins directory in which FWP is stored
99 +preg_match (
100 + '|/wp-content/plugins/(.+)$|',
101 + dirname(__FILE__),
102 + $ref
103 +);
94 104
105 +if (isset($ref[1])) :
106 + $fwp_path = $ref[1];
107 +else : // Something went wrong. Let's just guess.
108 + $fwp_path = 'feedwordpress';
109 +endif;
110 +
111 +// If this is a FeedWordPress admin page, queue up scripts for AJAX functions that FWP uses
112 +// If it is a display page or a non-FeedWordPress admin page, don't.
113 +if (is_admin() and isset($_REQUEST['page']) and preg_match("|^{$fwp_path}/|", $_REQUEST['page'])) :
114 + if (function_exists('wp_enqueue_script')) :
115 + if (isset($wp_db_version) and $wp_db_version >= FWP_SCHEMA_25) :
116 + wp_enqueue_script('post'); // for magic tag and category boxes
117 + wp_enqueue_script('thickbox'); // for fold-up boxes
118 + wp_enqueue_script('admin-forms'); // for checkbox selection
119 + else :
120 + wp_enqueue_script( 'ajaxcat' ); // Provides the handy-dandy new category text box
121 + endif;
122 + endif;
123 + if (function_exists('wp_enqueue_style')) :
124 + if (fwp_test_wp_version(FWP_SCHEMA_25)) :
125 + wp_enqueue_style('dashboard');
126 + endif;
127 + endif;
128 + if (function_exists('wp_admin_css')) :
129 + if (fwp_test_wp_version(FWP_SCHEMA_25)) :
130 + wp_admin_css('css/dashboard');
131 + endif;
132 + endif;
133 +endif;
134 +
95 135 if (!FeedWordPress::needs_upgrade()) : // only work if the conditions are safe!
96 136
97 137 # Syndicated items are generally received in output-ready (X)HTML and
98 138 # should not be folded, crumpled, mutilated, or spindled by WordPress
@@ -109,10 +149,19 @@
109 149
110 150 add_filter('the_content', 'feedwordpress_preserve_syndicated_content', -10000);
111 151 add_filter('the_content', 'feedwordpress_restore_syndicated_content', 10000);
112 152
153 + add_action('atom_entry', 'feedwordpress_item_feed_data');
154 +
113 155 # Filter in original permalinks if the user wants that
114 156 add_filter('post_link', 'syndication_permalink', 1);
157 +
158 + # WTF? By default, wp_insert_link runs incoming link_url and link_rss
159 + # URIs through default filters that include `wp_kses()`. But `wp_kses()`
160 + # just happens to escape any occurrence of & to &amp; -- which just
161 + # happens to fuck up any URI with a & to separate GET parameters.
162 + remove_filter('pre_link_rss', 'wp_filter_kses');
163 + remove_filter('pre_link_url', 'wp_filter_kses');
115 164
116 165 # Admin menu
117 166 add_action('admin_menu', 'fwp_add_pages');
118 167
@@ -140,8 +189,12 @@
140 189 endif;
141 190
142 191 # Cron-less auto-update. Hooray!
143 192 add_action('init', 'feedwordpress_auto_update');
193 +
194 + # Default sanitizers
195 + add_filter('syndicated_item_content', array('SyndicatedPost', 'sanitize_content'), 0, 2);
196 +
144 197 else :
145 198 # Hook in the menus, which will just point to the upgrade interface
146 199 add_action('admin_menu', 'fwp_add_pages');
147 200 endif; // if (!FeedWordPress::needs_upgrade())
@@ -194,60 +247,85 @@
194 247 : implode(' and ', $mesg)));
195 248 }
196 249
197 250 ################################################################################
198 -## LEGACY API: Replicate or mock up functions for legacy support purposes ######
251 +## TEMPLATE API: functions to make your templates syndication-aware ############
199 252 ################################################################################
200 253
201 -if (!function_exists('get_option')) {
202 - function get_option ($option) {
203 - return get_settings($option);
204 - }
205 -}
206 -if (!function_exists('current_user_can')) {
207 - $legacy_capability_hack = true;
208 - function current_user_can ($task) {
209 - global $user_level;
254 +function is_syndicated () { return (strlen(get_syndication_feed_id()) > 0); }
210 255
211 - $can = false;
256 +function get_syndication_source_link ($original = NULL) {
257 + if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
258 + endif;
212 259
213 - // This is **not** a full replacement for current_user_can. It
214 - // is only for checking the capabilities we care about via the
215 - // WordPress 1.5 user levels.
216 - switch ($task) {
217 - case 'manage_options':
218 - $can = ($user_level >= 6);
219 - break;
220 - case 'manage_links':
221 - $can = ($user_level >= 5);
222 - break;
223 - } /* switch */
224 - return $can;
225 - }
226 -} else {
227 - $legacy_capability_hack = false;
228 -}
229 -if (!function_exists('sanitize_user')) {
230 - function sanitize_user ($text, $strict) {
231 - return $text; // Don't munge it if it wasn't munged going in...
232 - }
233 -}
260 + if ($original) : $vals = get_post_custom_values('syndication_source_uri_original');
261 + else : $vals = array();
262 + endif;
263 +
264 + if (count($vals) == 0) : $vals = get_post_custom_values('syndication_source_uri');
265 + endif;
266 +
267 + if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
234 268
235 -################################################################################
236 -## TEMPLATE API: functions to make your templates syndication-aware ############
237 -################################################################################
269 + return $ret;
270 +} /* function get_syndication_source_link() */
238 271
239 -function is_syndicated () { return (strlen(get_syndication_feed_id()) > 0); }
272 +function the_syndication_source_link ($original = NULL) { echo get_syndication_source_link($original); }
240 273
241 -function the_syndication_source_link () { echo get_syndication_source_link(); }
242 -function get_syndication_source_link () { list($n) = get_post_custom_values('syndication_source_uri'); return $n; }
274 +function get_syndication_source ($original = NULL) {
275 + if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
276 + endif;
243 277
244 -function get_syndication_source () { list($n) = get_post_custom_values('syndication_source'); return $n; }
245 -function the_syndication_source () { echo get_syndication_source(); }
278 + if ($original) : $vals = get_post_custom_values('syndication_source_original');
279 + else : $vals = array();
280 + endif;
281 +
282 + if (count($vals) == 0) : $vals = get_post_custom_values('syndication_source');
283 + endif;
284 +
285 + if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
246 286
247 -function get_syndication_feed () { list($u) = get_post_custom_values('syndication_feed'); return $u; }
248 -function the_syndication_feed () { echo get_syndication_feed (); }
287 + return $ret;
288 +} /* function get_syndication_source() */
249 289
290 +function the_syndication_source ($original = NULL) { echo get_syndication_source($original); }
291 +
292 +function get_syndication_feed ($original = NULL) {
293 + if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
294 + endif;
295 +
296 + if ($original) : $vals = get_post_custom_values('syndication_feed_original');
297 + else : $vals = array();
298 + endif;
299 +
300 + if (count($vals) == 0) : $vals = get_post_custom_values('syndication_feed');
301 + endif;
302 +
303 + if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
304 +
305 + return $ret;
306 +} /* function get_syndication_feed() */
307 +
308 +function the_syndication_feed ($original = NULL) { echo get_syndication_feed ($original); }
309 +
310 +function get_syndication_feed_guid ($original = NULL) {
311 + if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
312 + endif;
313 +
314 + if ($original) : $vals = get_post_custom_values('syndication_source_id_original');
315 + else : $vals = array();
316 + endif;
317 +
318 + if (count($vals) == 0) : $vals = array(get_feed_meta('feed/id'));
319 + endif;
320 +
321 + if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
322 +
323 + return $ret;
324 +} /* function get_syndication_feed_guid () */
325 +
326 +function the_syndication_feed_guid ($original = NULL) { echo get_syndication_feed_guid($original); }
327 +
250 328 function get_syndication_feed_id () { list($u) = get_post_custom_values('syndication_feed_id'); return $u; }
251 329 function the_syndication_feed_id () { echo get_syndication_feed_id(); }
252 330
253 331 $feedwordpress_linkcache = array (); // only load links from database once
@@ -285,9 +363,9 @@
285 363
286 364 function feedwordpress_preserve_syndicated_content ($text) {
287 365 global $feedwordpress_the_syndicated_content;
288 366
289 - if ( is_syndicated() ) :
367 + if ( is_syndicated() and get_option('feedwordpress_formatting_filters') != 'yes' ) :
290 368 $feedwordpress_the_syndicated_content = $text;
291 369 else :
292 370 $feedwordpress_the_syndicated_content = NULL;
293 371 endif;
@@ -303,1060 +381,72 @@
303 381
304 382 return $text;
305 383 }
306 384
307 -function syndication_permalink ($permalink = '') {
308 - if (get_option('feedwordpress_munge_permalink') != 'no'):
309 - $uri = get_syndication_permalink();
310 - return ((strlen($uri) > 0) ? $uri : $permalink);
311 - else:
312 - return $permalink;
313 - endif;
314 -} // function syndication_permalink ()
315 -
316 -################################################################################
317 -## UPGRADE INTERFACE: Have users upgrade DB from older versions of FWP #########
318 -################################################################################
319 -
320 -function fwp_upgrade_page () {
321 - if (isset($GLOBALS['fwp_post']['action']) and $GLOBALS['fwp_post']['action']=='Upgrade') :
322 - $ver = get_option('feedwordpress_version');
323 - if (get_option('feedwordpress_version') != FEEDWORDPRESS_VERSION) :
324 - echo "<div class=\"wrap\">\n";
325 - echo "<h2>Upgrading FeedWordPress...</h2>";
326 -
327 - $feedwordpress =& new FeedWordPress;
328 - $feedwordpress->upgrade_database();
329 - echo "<p><strong>Done!</strong> Upgraded database to version ".FEEDWORDPRESS_VERSION.".</p>\n";
330 - echo "<form action=\"\" method=\"get\">\n";
331 - echo "<div class=\"submit\"><input type=\"hidden\" name=\"page\" value=\"".basename(__FILE__)."\" />";
332 - echo "<input type=\"submit\" value=\"Continue &raquo;\" /></form></div>\n";
333 - echo "</div>\n";
334 - return;
335 - else :
336 - echo "<div class=\"updated\"><p>Already at version ".FEEDWORDPRESS_VERSION."!</p></div>";
337 - endif;
338 - endif;
385 +function feedwordpress_item_feed_data () {
386 + // In a post context....
387 + if (is_syndicated()) :
339 388 ?>
340 -<div class="wrap">
341 -<h2>Upgrade FeedWordPress</h2>
342 -
343 -<p>It appears that you have installed FeedWordPress
344 -<?php echo FEEDWORDPRESS_VERSION; ?> as an upgrade to an existing installation of
345 -FeedWordPress. That's no problem, but you will need to take a minute out first
346 -to upgrade your database: some necessary changes in how the software keeps
347 -track of posts and feeds will cause problems such as duplicate posts and broken
348 -templates if we were to continue without the upgrade.</p>
349 -
350 -<p>Note that most of FeedWordPress's functionality is temporarily disabled
351 -until we have successfully completed the upgrade. Everything should begin
352 -working as normal again once the upgrade is complete. There's extraordinarily
353 -little chance of any damage as the result of the upgrade, but if you're paranoid
354 -like me you may want to back up your database before you proceed.</p>
355 -
356 -<p>This may take several minutes for a large installation.</p>
357 -
358 -<form action="" method="post">
359 -<div class="submit"><input type="submit" name="action" value="Upgrade" /></div>
360 -</form>
361 -</div>
389 +<source>
390 + <title><?php the_syndication_source(); ?></title>
391 + <link rel="alternate" type="text/html" href="<?php the_syndication_source_link(); ?>" />
392 + <link rel="self" href="<?php the_syndication_feed(); ?>" />
362 393 <?php
363 -} // function fwp_upgrade_page ()
364 -
365 -################################################################################
366 -## ADMIN MENU ADD-ONS: implement Dashboard management pages ####################
367 -################################################################################
368 -
369 -function fwp_add_pages () {
370 - global $legacy_capability_hack;
371 -
372 - if ($legacy_capability_hack) :
373 - // old & busted: numeric user levels
374 - $manage_links = 5;
375 - $manage_options = 6;
376 - else :
377 - // new hotness: named capabilities
378 - $manage_links = 'manage_links';
379 - $manage_options = 'manage_options';
380 - endif;
381 -
382 - //add_submenu_page('plugins.php', 'Akismet Configuration', 'Akismet Configuration', 'manage_options', 'syndication-manage-page', 'fwp_syndication_manage_page');
383 - add_menu_page('Syndicated Sites', 'Syndication', $manage_links, 'feedwordpress/'.basename(__FILE__), 'fwp_syndication_manage_page');
384 - add_submenu_page('feedwordpress/'.basename(__FILE__), 'Syndication Options', 'Options', $manage_options, 'feedwordpress/syndication-options.php');
385 - add_options_page('Syndication Options', 'Syndication', $manage_options, 'feedwordpress/syndication-options.php');
386 -} // function fwp_add_pages () */
387 -
388 -function fwp_category_box ($checked, $object) {
389 - global $wp_db_version;
390 -
391 - if (isset($wp_db_version) and $wp_db_version >= FWP_SCHEMA_20) : // WordPress 2.x
394 + $id = get_syndication_feed_guid();
395 + if (strlen($id) > 0) :
392 396 ?>
393 - <div id="poststuff">
394 -
395 - <div id="moremeta">
396 - <div id="grabit" class="dbx-group">
397 - <fieldset id="categorydiv" class="dbx-box">
398 - <h3 class="dbx-handle"><?php _e('Categories') ?></h3>
399 - <div class="dbx-content">
400 - <p style="font-size:smaller;font-style:bold;margin:0">Place <?php print $object; ?> under...</p>
401 - <p id="jaxcat"></p>
402 - <ul id="categorychecklist"><?php write_nested_categories($checked); ?></ul></div>
403 - </fieldset>
404 - </div>
405 - </div>
406 - </div>
397 + <id><?php print $id; ?></id>
407 398 <?php
408 - else : // WordPress 1.5
409 -?>
410 - <fieldset id="categorydiv" style="width: 20%; margin-right: 2em">
411 - <legend><?php _e('Categories') ?></legend>
412 - <p style="font-size:smaller;font-style:bold;margin:0">Place <?php print $object; ?> under...</p>
413 - <div style="height: 20em"><?php write_nested_categories($checked); ?></div>
414 - </fieldset>
399 + endif;
400 + $updated = get_feed_meta('feed/updated');
401 + if (strlen($updated) > 0) : ?>
402 + <updated><?php print $updated; ?></updated>
415 403 <?php
416 404 endif;
417 -}
418 -
419 -function update_feeds_mention ($feed) {
420 - echo "<li>Updating <cite>".$feed['link/name']."</cite> from &lt;<a href=\""
421 - .$feed['link/uri']."\">".$feed['link/uri']."</a>&gt; ...</li>\n";
422 - flush();
423 -}
424 -
425 -function fwp_syndication_manage_page () {
426 - global $wpdb;
427 -
428 - if (FeedWordPress::needs_upgrade()) :
429 - fwp_upgrade_page();
430 - return;
431 - endif;
432 -
433 405 ?>
434 -<?php $cont = true;
435 -if (isset($_REQUEST['action'])):
436 - if ($_REQUEST['action'] == 'feedfinder') : $cont = fwp_feedfinder_page();
437 - elseif ($_REQUEST['action'] == 'switchfeed') : $cont = fwp_switchfeed_page();
438 - elseif ($_REQUEST['action'] == 'linkedit') : $cont = fwp_linkedit_page();
439 - elseif ($_REQUEST['action'] == 'Unsubscribe from Checked Links' or $_REQUEST['action'] == 'Unsubscribe') : $cont = fwp_multidelete_page();
440 - endif;
441 -endif;
442 -
443 -if ($cont):
444 -?>
406 +</source>
445 407 <?php
446 - $links = FeedWordPress::syndicated_links();
447 -
448 - if (isset($_POST['update']) or isset($_POST['action']) or isset($_POST['update_uri'])) :
449 - $fwp_update_invoke = 'post';
450 - else :
451 - $fwp_update_invoke = 'get';
452 408 endif;
453 -
454 - $update_set = array();
455 - if (isset($_POST['link_ids']) and is_array($_POST['link_ids']) and ($_POST['action']=='Update Checked Links')) :
456 - $targets = $wpdb->get_results("
457 - SELECT * FROM $wpdb->links
458 - WHERE link_id IN (".implode(",",$_POST['link_ids']).")
459 - ");
460 - if (is_array($targets)) :
461 - foreach ($targets as $target) :
462 - $update_set[] = $target->link_rss;
463 - endforeach;
464 - else : // This should never happen
465 - FeedWordPress::critical_bug('fwp_syndication_manage_page::targets', $targets, __LINE__);
466 - endif;
467 - elseif (isset($_POST['update_uri'])) :
468 - $update_set[] = $_POST['update_uri'];
469 - endif;
470 -
471 - if ($fwp_update_invoke != 'get' and count($update_set) > 0) : // Only do things with side-effects for HTTP POST or command line
472 - $feedwordpress =& new FeedWordPress;
473 - add_action('feedwordpress_check_feed', 'update_feeds_mention');
474 -
475 - echo "<div class=\"updated\">\n";
476 - echo "<ul>\n";
477 - $tdelta = NULL;
478 - foreach ($update_set as $uri) :
479 - if ($uri == '*') : $uri = NULL; endif;
480 - $delta = $feedwordpress->update($uri);
481 - if (!is_null($delta)) :
482 - if (is_null($tdelta)) :
483 - $tdelta = $delta;
484 - else :
485 - $tdelta['new'] += $delta['new'];
486 - $tdelta['updated'] += $delta['updated'];
487 - endif;
488 - else :
489 - echo "<li><p><strong>Error:</strong> There was a problem updating <a href=\"$uri\">$uri</a></p></li>\n";
490 - endif;
491 - endforeach;
492 - echo "</ul>\n";
493 -
494 - if (!is_null($tdelta)) :
495 - $mesg = array();
496 - if (isset($delta['new'])) : $mesg[] = ' '.$tdelta['new'].' new posts were syndicated'; endif;
497 - if (isset($delta['updated'])) : $mesg[] = ' '.$tdelta['updated'].' existing posts were updated'; endif;
498 - echo "<p>Update complete.".implode(' and', $mesg)."</p>";
499 - echo "\n"; flush();
500 - endif;
501 - echo "</div> <!-- class=\"updated\" -->\n";
502 - endif;
503 -
504 - ?>
505 - <div class="wrap">
506 - <form action="" method="POST">
507 - <h2>Update feeds now</h2>
508 - <p>Check currently scheduled feeds for new and updated posts.</p>
509 -
510 -<?php if (!get_option('feedwordpress_automatic_updates')) : ?>
511 - <p><strong>Note:</strong> Automatic updates are currently turned
512 - <strong>off</strong>. New posts from your feeds will not be syndicated
513 - until you manually check for them here. You can turn on automatic
514 - updates under <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication
515 - Options</a>.</p>
516 -<?php endif; ?>
517 -
518 -
519 - <div class="submit"><input type="hidden" name="update_uri" value="*" /><input type="submit" name="update" value="Update" /></div>
520 - </form>
521 - </div> <!-- class="wrap" -->
522 -
523 - <form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
524 - <div class="wrap">
525 - <h2>Syndicated Sites</h2>
526 -<?php $alt_row = true;
527 - if ($links): ?>
528 -
529 -<table width="100%" cellpadding="3" cellspacing="3">
530 -<tr>
531 -<th width="20%"><?php _e('Name'); ?></th>
532 -<th width="40%"><?php _e('Feed'); ?></th>
533 -<th colspan="4"><?php _e('Action'); ?></th>
534 -</tr>
535 -
536 -<?php foreach ($links as $link):
537 - $alt_row = !$alt_row; ?>
538 -<tr<?php echo ($alt_row?' class="alternate"':''); ?>>
539 -<td><a href="<?php echo wp_specialchars($link->link_url, 'both'); ?>"><?php echo wp_specialchars($link->link_name, 'both'); ?></a></td>
540 -<?php
541 - if (strlen($link->link_rss) > 0):
542 - $caption='Switch Feed';
543 - $uri_bits = parse_url($link->link_rss);
544 - $uri_bits['host'] = preg_replace('/^www\./i', '', $uri_bits['host']);
545 - $display_uri =
546 - (isset($uri_bits['user'])?$uri_bits['user'].'@':'')
547 - .(isset($uri_bits['host'])?$uri_bits['host']:'')
548 - .(isset($uri_bits['port'])?':'.$uri_bits['port']:'')
549 - .(isset($uri_bits['path'])?$uri_bits['path']:'')
550 - .(isset($uri_bits['query'])?'?'.$uri_bits['query']:'');
551 - if (strlen($display_uri) > 32) : $display_uri = substr($display_uri, 0, 32).'&#8230;'; endif;
552 -?>
553 - <td>
554 - <strong><a href="<?php echo $link->link_rss; ?>"><?php echo wp_specialchars($display_uri, 'both'); ?></a></strong></td>
555 -<?php
556 - else:
557 - $caption='Find Feed';
558 -?>
559 - <td style="background-color:#FFFFD0"><p><strong>no
560 - feed assigned</strong></p></td>
561 -<?php
562 - endif;
563 -?>
564 - <td><a href="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>&amp;link_id=<?php echo $link->link_id; ?>&amp;action=linkedit" class="edit"><?php _e('Edit')?></a></td>
565 - <td><a href="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>&amp;link_id=<?php echo $link->link_id; ?>&amp;action=feedfinder" class="edit"><?php echo $caption; ?></a></td>
566 - <td><a href="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>&amp;link_id=<?php echo $link->link_id; ?>&amp;action=Unsubscribe" class="delete"><?php _e('Unsubscribe'); ?></a></td>
567 - <td><input type="checkbox" name="link_ids[]" value="<?php echo $link->link_id; ?>" /></td>
568 -<?php
569 - echo "\n\t</tr>";
570 - endforeach;
571 - else:
572 -?>
573 -
574 -<p>There are no websites currently listed for syndication.</p>
575 -
576 -<?php endif; ?>
577 - </table>
578 -
579 - <br/><hr/>
580 - <div class="submit"><input type="submit" class="delete" name="action" value="Unsubscribe from Checked Links" />
581 - <input type="submit" name="action" value="Update Checked Links" /></div>
582 - </div> <!-- class="wrap" -->
583 - </form>
584 -
585 - <div class="wrap">
586 - <form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
587 - <h2>Add a new syndicated site:</h2>
588 - <div>
589 - <label for="add-uri">Website or newsfeed:</label>
590 - <input type="text" name="lookup" id="add-uri" value="URI" size="64" />
591 - <input type="hidden" name="action" value="feedfinder" />
592 - </div>
593 - <div class="submit"><input type="submit" value="Syndicate &raquo;" /></div>
594 - </form>
595 - </div> <!-- class="wrap" -->
596 -<?php
597 -endif;
598 409 }
599 410
600 -function fwp_feedfinder_page () {
601 - global $wpdb;
602 -
603 - $lookup = (isset($_REQUEST['lookup'])?$_REQUEST['lookup']:NULL);
604 -
605 - if (isset($_REQUEST['link_id']) and ($_REQUEST['link_id']!=0)):
606 - $link_id = $_REQUEST['link_id'];
607 - if (!is_numeric($link_id)) : FeedWordPress::critical_bug('fwp_feedfinder_page::link_id', $link_id, __LINE__); endif;
608 -
609 - $link = $wpdb->get_row("SELECT * FROM $wpdb->links WHERE link_id='".$wpdb->escape($link_id)."'");
610 - if (is_object($link)):
611 - if (is_null($lookup)) $lookup = $link->link_url;
612 - $name = wp_specialchars($link->link_name, 'both');
613 - else:
614 - die (__("Cheatin' uh ?"));
615 - endif;
411 +function syndication_permalink ($permalink = '') {
412 + if (get_option('feedwordpress_munge_permalink') != 'no'):
413 + $uri = get_syndication_permalink();
414 + return ((strlen($uri) > 0) ? $uri : $permalink);
616 415 else:
617 - $name = "New Syndicated Feed";
618 - $link_id = 0;
416 + return $permalink;
619 417 endif;
620 -?>
621 - <div class="wrap">
622 - <h2>Feed Finder: <?php echo $name; ?></h2>
623 -<?php
624 - $f =& new FeedFinder($lookup);
625 - $feeds = $f->find();
626 - if (count($feeds) > 0):
627 - foreach ($feeds as $key => $f):
628 - $rss = fetch_rss($f);
629 - if ($rss):
630 - $feed_title = isset($rss->channel['title'])?$rss->channel['title']:$rss->channel['link'];
631 - $feed_link = isset($rss->channel['link'])?$rss->channel['link']:'';
632 -?>
633 - <form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
634 - <fieldset style="clear: both">
635 - <legend><?php echo $rss->feed_type; ?> <?php echo $rss->feed_version; ?> feed</legend>
418 +} // function syndication_permalink ()
636 419
637 - <?php if ($link_id===0): ?>
638 - <input type="hidden" name="feed_title" value="<?php echo wp_specialchars($feed_title, 'both'); ?>" />
639 - <input type="hidden" name="feed_link" value="<?php echo wp_specialchars($feed_link, 'both'); ?>" />
640 - <?php endif; ?>
420 +################################################################################
421 +## ADMIN MENU ADD-ONS: register Dashboard management pages #####################
422 +################################################################################
641 423
642 - <input type="hidden" name="link_id" value="<?php echo $link_id; ?>" />
643 - <input type="hidden" name="feed" value="<?php echo wp_specialchars($f, 'both'); ?>" />
644 - <input type="hidden" name="action" value="switchfeed" />
424 +function fwp_add_pages () {
425 + global $fwp_capability;
426 + global $fwp_path;
645 427
646 - <div>
647 - <div style="float:right; background-color:#D0D0D0; color: black; width:45%; font-size:70%; border-left: 1px dotted #A0A0A0; padding-left: 0.5em; margin-left: 1.0em">
648 -<?php if (count($rss->items) > 0): ?>
649 - <?php $item = $rss->items[0]; ?>
650 - <h3>Sample Item</h3>
651 - <ul>
652 - <li><strong>Title:</strong> <a href="<?php echo $item['link']; ?>"><?php echo $item['title']; ?></a></li>
653 - <li><strong>Date:</strong> <?php echo isset($item['date_timestamp']) ? date('d-M-y g:i:s a', $item['date_timestamp']) : 'unknown'; ?></li>
654 - </ul>
655 - <div class="entry">
656 - <?php echo (isset($item['content']['encoded'])?$item['content']['encoded']:$item['description']); ?>
657 - </div>
658 -<?php else: ?>
659 - <h3>No Items</h3>
660 - <p>FeedWordPress found no posts on this feed.</p>
661 -<?php endif; ?>
662 - </div>
663 -
664 - <div>
665 - <h3>Feed Information</h3>
666 - <ul>
667 - <li><strong>Website:</strong> <a href="<?php echo $feed_link; ?>"><?php echo is_null($feed_title)?'<em>Unknown</em>':$feed_title; ?></a></li>
668 - <li><strong>Feed URI:</strong> <a href="<?php echo wp_specialchars($f, 'both'); ?>"><?php echo wp_specialchars($f, 'both'); ?></a> <a title="Check feed &lt;<?php echo wp_specialchars($f, 'both'); ?>&gt; for validity" href="http://feedvalidator.org/check.cgi?url=<?php echo urlencode($f); ?>"><img src="../wp-images/smilies/icon_arrow.gif" alt="(&rarr;)" /></a></li>
669 - <li><strong>Encoding:</strong> <?php echo isset($rss->encoding)?wp_specialchars($rss->encoding, 'both'):"<em>Unknown</em>"; ?></li>
670 - <li><strong>Description:</strong> <?php echo isset($rss->channel['description'])?wp_specialchars($rss->channel['description'], 'both'):"<em>Unknown</em>"; ?></li>
671 - </ul>
672 - <div class="submit"><input type="submit" name="Use" value="&laquo; Use this feed" /></div>
673 - <div class="submit"><input type="submit" name="Cancel" value="&laquo; Cancel" /></div>
674 - </div>
675 - </div>
676 - </fieldset>
677 - </form>
678 -<?php endif;
679 - endforeach;
680 - else:
681 - echo "<p><strong>no feed found</strong></p>";
428 + $menu = array('Syndicated Sites', 'Syndication', $fwp_capability['manage_links'], $fwp_path.'/syndication.php', NULL);
429 + if (fwp_test_wp_version(FWP_SCHEMA_27)) :
430 + // add icon parameter
431 + $menu[] = WP_PLUGIN_URL.'/'.$fwp_path.'/feedwordpress-tiny.png';
682 432 endif;
683 -?>
684 - </div>
685 433
686 - <form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
687 - <div class="wrap">
688 - <h2>Use another feed</h2>
689 - <div><label>Feed:</label>
690 - <input type="text" name="lookup" value="URI" />
691 - <input type="hidden" name="link_id" value="<?php echo $link_id; ?>" />
692 - <input type="hidden" name="action" value="feedfinder" /></div>
693 - <div class="submit"><input type="submit" value="Use this feed &raquo;" /></div>
694 - </div>
695 - </form>
696 -<?php
697 - return false; // Don't continue
698 -}
699 -
700 -function fwp_switchfeed_page () {
701 - global $wpdb, $wp_db_version;
702 -
703 - check_admin_referer();
704 - if (!isset($_REQUEST['Cancel'])):
705 - if (!current_user_can('manage_links')):
706 - die (__("Cheatin' uh ?"));
707 - elseif (isset($_REQUEST['link_id']) and ($_REQUEST['link_id']==0)):
708 - $link_id = FeedWordPress::syndicate_link($_REQUEST['feed_title'], $_REQUEST['feed_link'], $_REQUEST['feed']);
709 - if ($link_id): ?>
710 -<div class="updated"><p><a href="<?php echo $_REQUEST['feed_link']; ?>"><?php echo wp_specialchars($_REQUEST['feed_title'], 'both'); ?></a>
711 -has been added as a contributing site, using the newsfeed at &lt;<a href="<?php echo $_REQUEST['feed']; ?>"><?php echo wp_specialchars($_REQUEST['feed'], 'both'); ?></a>&gt;.</p></div>
712 -<?php else: ?>
713 -<div class="updated"><p>There was a problem adding the newsfeed. [SQL: <?php echo wp_specialchars(mysql_error(), 'both'); ?>]</p></div>
714 -<?php endif;
715 - elseif (isset($_REQUEST['link_id'])):
716 - // Update link_rss
717 - $result = $wpdb->query("
718 - UPDATE $wpdb->links
719 - SET
720 - link_rss = '".$wpdb->escape($_REQUEST['feed'])."'
721 - WHERE link_id = '".$wpdb->escape($_REQUEST['link_id'])."'
722 - ");
723 -
724 - if ($result):
725 - $result = $wpdb->get_row("
726 - SELECT link_name, link_url FROM $wpdb->links
727 - WHERE link_id = '".$wpdb->escape($_REQUEST['link_id'])."'
728 - ");
729 - ?>
730 -<div class="updated"><p>Feed for <a href="<?php echo $result->link_url; ?>"><?php echo wp_specialchars($result->link_name, 'both'); ?></a>
731 -updated to &lt;<a href="<?php echo $_REQUEST['feed']; ?>"><?php echo wp_specialchars($_REQUEST['feed'], 'both'); ?></a>&gt;.</p></div>
732 - <?php else: ?>
733 -<div class="updated"><p>Nothing was changed.</p></div>
734 - <?php endif;
735 - endif;
736 - endif;
737 - return true; // Continue
738 -}
739 -
740 -function fwp_linkedit_page () {
741 - global $wpdb;
742 -
743 - check_admin_referer(); // Make sure we arrived here from the Dashboard
744 -
745 - $special_settings = array ( /* Regular expression syntax is OK here */
746 - 'cats',
747 - 'cat_split',
748 - 'hardcode name',
749 - 'hardcode url',
750 - 'hardcode description',
751 - 'hardcode categories', /* Deprecated */
752 - 'post status',
753 - 'comment status',
754 - 'ping status',
755 - 'unfamiliar author',
756 - 'unfamliar categories',
757 - 'update/.*',
758 - 'feed/.*',
759 - 'link/.*',
760 - );
761 -
762 - if (!current_user_can('manage_links')) :
763 - die (__("Cheatin' uh ?"));
764 - elseif (isset($_REQUEST['feedfinder'])) :
765 - return fwp_feedfinder_page(); // re-route to Feed Finder page
434 + if (fwp_test_wp_version(FWP_SCHEMA_26)) :
435 + $options = __('Settings');
436 + $longoptions = __('Syndication Settings');
766 437 else :
767 - $link_id = (int) $_REQUEST['link_id'];
768 - $link =& new SyndicatedLink($link_id);
769 -
770 - if ($link->found()) :
771 - if (isset($GLOBALS['fwp_post']['save'])) :
772 - $alter = array ();
773 -
774 - $meta = $link->settings;
775 - if (isset($meta['cats'])):
776 - $meta['cats'] = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, $meta['cats']);
777 - endif;
778 -
779 - // custom feed settings first
780 - foreach ($GLOBALS['fwp_post']['notes'] as $mn) :
781 - $mn['key0'] = trim($mn['key0']);
782 - $mn['key1'] = trim($mn['key1']);
783 - if (preg_match("\007^(("
784 - .implode(')|(',$special_settings)
785 - ."))$\007i",
786 - $mn['key1'])) :
787 - $mn['key1'] = 'user/'.$mn['key1'];
788 - endif;
789 -
790 - if (strlen($mn['key0']) > 0) :
791 - unset($meta[$mn['key0']]); // out with the old
792 - endif;
793 -
794 - if (($mn['action']=='update') and (strlen($mn['key1']) > 0)) :
795 - $meta[$mn['key1']] = $mn['value']; // in with the new
796 - endif;
797 - endforeach;
798 -
799 - // now stuff through the web form
800 - // hardcoded feed info
801 - if (isset($GLOBALS['fwp_post']['hardcode_name'])) :
802 - $meta['hardcode name'] = $GLOBALS['fwp_post']['hardcode_name'];
803 - if (FeedWordPress::affirmative($meta, 'hardcode name')) :
804 - $alter[] = "link_name = '".$wpdb->escape($GLOBALS['fwp_post']['name'])."'";
805 - endif;
806 - endif;
807 - if (isset($GLOBALS['fwp_post']['hardcode_description'])) :
808 - $meta['hardcode description'] = $GLOBALS['fwp_post']['hardcode_description'];
809 - if (FeedWordPress::affirmative($meta, 'hardcode description')) :
810 - $alter[] = "link_description = '".$wpdb->escape($GLOBALS['fwp_post']['description'])."'";
811 - endif;
812 - endif;
813 - if (isset($GLOBALS['fwp_post']['hardcode_url'])) :
814 - $meta['hardcode url'] = $GLOBALS['fwp_post']['hardcode_url'];
815 - if (FeedWordPress::affirmative($meta, 'hardcode url')) :
816 - $alter[] = "link_url = '".$wpdb->escape($GLOBALS['fwp_post']['linkurl'])."'";
817 - endif;
818 - endif;
819 -
820 - // Update scheduling
821 - if (isset($GLOBALS['fwp_post']['update_schedule'])) :
822 - $meta['update/hold'] = $GLOBALS['fwp_post']['update_schedule'];
823 - endif;
824 -
825 - // Categories
826 - if (isset($GLOBALS['fwp_post']['post_category'])) :
827 - $meta['cats'] = array();
828 - foreach ($GLOBALS['fwp_post']['post_category'] as $cat_id) :
829 - $meta['cats'][] = '{#'.$cat_id.'}';
830 - endforeach;
831 - else :
832 - unset($meta['cats']);
833 - endif;
834 -
835 - // Post status, comment status, ping status
836 - foreach (array('post', 'comment', 'ping') as $what) :
837 - $sfield = "feed_{$what}_status";
838 - if (isset($GLOBALS['fwp_post'][$sfield])) :
839 - if ($GLOBALS['fwp_post'][$sfield]=='site-default') :
840 - unset($meta["{$what} status"]);
841 - else :
842 - $meta["{$what} status"] = $GLOBALS['fwp_post'][$sfield];
843 - endif;
844 - endif;
845 - endforeach;
846 -
847 - // Unfamiliar author, unfamiliar categories
848 - foreach (array("author", "category") as $what) :
849 - $sfield = "unfamiliar_{$what}";
850 - if (isset($GLOBALS['fwp_post'][$sfield])) :
851 - if ($GLOBALS['fwp_post'][$sfield]=='site-default') :
852 - unset($meta["unfamiliar {$what}"]);
853 - else :
854 - $meta["unfamiliar {$what}"] = $GLOBALS['fwp_post'][$sfield];
855 - endif;
856 - endif;
857 - endforeach;
858 -
859 - if (isset($GLOBALS['fwp_post']['cat_split'])) :
860 - if (strlen(trim($GLOBALS['fwp_post']['cat_split'])) > 0) :
861 - $meta['cat_split'] = trim($GLOBALS['fwp_post']['cat_split']);
862 - else :
863 - unset($meta['cat_split']);
864 - endif;
865 - endif;
866 -
867 - if (is_array($meta['cats'])) :
868 - $meta['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $meta['cats']);
869 - endif;
870 -
871 - $notes = '';
872 - foreach ($meta as $key => $value) :
873 - $notes .= $key . ": ". addcslashes($value, "\0..\37".'\\') . "\n";
874 - endforeach;
875 - $alter[] = "link_notes = '".$wpdb->escape($notes)."'";
876 -
877 - $alter_set = implode(", ", $alter);
878 -
879 - // issue update query
880 - $result = $wpdb->query("
881 - UPDATE $wpdb->links
882 - SET $alter_set
883 - WHERE link_id='$link_id'
884 - ");
885 - $updated_link = true;
886 -
887 - // reload link information from DB
888 - $link =& new SyndicatedLink($link_id);
889 - else :
890 - $updated_link = false;
891 - endif;
892 -
893 - $db_link = $link->link;
894 - $link_url = wp_specialchars($db_link->link_url, 1);
895 - $link_name = wp_specialchars($db_link->link_name, 1);
896 - $link_description = wp_specialchars($db_link->link_description, 'both');
897 - $link_notes = wp_specialchars($db_link->link_notes, 'both');
898 - $link_rss_uri = wp_specialchars($db_link->link_rss, 'both');
899 -
900 - $meta = $link->settings;
901 - $post_status_global = get_option('feedwordpress_syndicated_post_status');
902 - $comment_status_global = get_option('feedwordpress_syndicated_comment_status');
903 - $ping_status_global = get_option('feedwordpress_syndicated_ping_status');
904 -
905 - $status['post'] = array('publish' => '', 'private' => '', 'draft' => '', 'site-default' => '');
906 - $status['comment'] = array('open' => '', 'closed' => '', 'site-default' => '');
907 - $status['ping'] = array('open' => '', 'closed' => '', 'site-default' => '');
908 -
909 - foreach (array('post', 'comment', 'ping') as $what) :
910 - if (isset($meta["{$what} status"])) :
911 - $status[$what][$meta["{$what} status"]] = ' checked="checked"';
912 - else :
913 - $status[$what]['site-default'] = ' checked="checked"';
914 - endif;
915 - endforeach;
916 -
917 - $unfamiliar['author'] = array ('create' => '','default' => '','filter' => '');
918 - $unfamiliar['category'] = array ('create'=>'','default'=>'','filter'=>'');
919 -
920 - foreach (array('author', 'category') as $what) :
921 - if (is_string($meta["unfamiliar {$what}"]) and
922 - array_key_exists($meta["unfamiliar {$what}"], $unfamiliar[$what])) :
923 - $key = $meta["unfamiliar {$what}"];
924 - else:
925 - $key = 'site-default';
926 - endif;
927 - $unfamiliar[$what][$key] = ' checked="checked"';
928 - endforeach;
929 -
930 - $dogs = get_nested_categories(-1, 0);
931 - if (is_array($meta['cats'])) :
932 - $cats = array_map('strtolower',
933 - array_map('trim',
934 - $meta['cats']
935 - ));
936 - else:
937 - $cats = array();
938 - endif;
939 -
940 - foreach ($dogs as $tag => $dog) :
941 - $found_by_name = in_array(strtolower(trim($dog['cat_name'])), $cats);
942 -
943 - if (isset($dog['cat_ID'])) : $dog['cat_id'] = $dog['cat_ID']; endif;
944 - $found_by_id = in_array('{#'.trim($dog['cat_id']).'}', $cats);
945 -
946 - if ($found_by_name or $found_by_id) :
947 - $dogs[$tag]['checked'] = true;
948 - endif;
949 - endforeach;
950 - else :
951 - die( __('Link not found.') );
952 - endif;
953 -
954 - ?>
955 -<script type="text/javascript">
956 - function flip_hardcode (item) {
957 - ed=document.getElementById('basics-'+item+'-edit');
958 - view=document.getElementById('basics-'+item+'-view');
959 -
960 - o = document.getElementById('basics-hardcode-'+item);
961 - if (o.value=='yes') { ed.style.display='inline'; view.style.display='none'; }
962 - else { ed.style.display='none'; view.style.display='inline'; }
963 - }
964 -</script>
965 -
966 -<?php if ($updated_link) : ?>
967 -<div class="updated"><p>Syndicated feed settings updated.</p></div>
968 -<?php endif; ?>
969 -
970 -<form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
971 -<div class="wrap">
972 -<input type="hidden" name="link_id" value="<?php echo $link_id; ?>" />
973 -<input type="hidden" name="action" value="linkedit" />
974 -<input type="hidden" name="save" value="link" />
975 -
976 -<h2>Edit a syndicated feed:</h2>
977 -<fieldset><legend>Basics</legend>
978 -<table class="editform" width="100%" cellspacing="2" cellpadding="5">
979 -<tr>
980 -<th scope="row" width="20%"><?php _e('Feed URI:') ?></th>
981 -<td width="60%"><a href="<?php echo wp_specialchars($link_rss_uri, 'both'); ?>"><?php echo $link_rss_uri; ?></a>
982 -<a href="<?php echo FEEDVALIDATOR_URI; ?>?url=<?php echo urlencode($link_rss_uri); ?>"
983 -title="Check feed &lt;<?php echo wp_specialchars($link_rss_uri, 'both'); ?>&gt; for validity"><img src="../wp-images/smilies/icon_arrow.gif" alt="&rarr;" /></a>
984 -</td>
985 -<td width="20%"><input type="submit" name="feedfinder" value="switch &rarr;" style="font-size:smaller" /></td>
986 -</tr>
987 -<tr>
988 -<th scope="row" width="20%"><?php _e('Link Name:') ?></th>
989 -<td width="60%"><input type="text" id="basics-name-edit" name="name"
990 -value="<?php echo $link_name; ?>" style="width: 95%" />
991 -<span id="basics-name-view"><strong><?php echo $link_name; ?></strong></span>
992 -</td>
993 -<td>
994 -<select id="basics-hardcode-name" onchange="flip_hardcode('name')" name="hardcode_name">
995 -<option value="no" <?php echo $link->hardcode('name')?'':'selected="selected"'; ?>>update automatically</option>
996 -<option value="yes" <?php echo $link->hardcode('name')?'selected="selected"':''; ?>>edit manually</option>
997 -</select>
998 -</td>
999 -</tr>
1000 -<tr>
1001 -<th scope="row" width="20%"><?php _e('Short description:') ?></th>
1002 -<td width="60%">
1003 -<input id="basics-description-edit" type="text" name="description" value="<?php echo $link_description; ?>" style="width: 95%" />
1004 -<span id="basics-description-view"><strong><?php echo $link_description; ?></strong></span>
1005 -</td>
1006 -<td>
1007 -<select id="basics-hardcode-description" onchange="flip_hardcode('description')"
1008 -name="hardcode_description">
1009 -<option value="no" <?php echo $link->hardcode('description')?'':'selected="selected"'; ?>>update automatically</option>
1010 -<option value="yes" <?php echo $link->hardcode('description')?'selected="selected"':''; ?>>edit manually</option>
1011 -</select></td>
1012 -</tr>
1013 -<tr>
1014 -<th width="20%" scope="row"><?php _e('Homepage:') ?></th>
1015 -<td width="60%">
1016 -<input id="basics-url-edit" type="text" name="linkurl" value="<?php echo $link_url; ?>" style="width: 95%;" />
1017 -<a id="basics-url-view" href="<?php echo $link_url; ?>"><?php echo $link_url; ?></a></td>
1018 -<td>
1019 -<select id="basics-hardcode-url" onchange="flip_hardcode('url')" name="hardcode_url">
1020 -<option value="no"<?php echo $link->hardcode('url')?'':' selected="selected"'; ?>>update automatically</option>
1021 -<option value="yes"<?php echo $link->hardcode('url')?' selected="selected"':''; ?>>edit manually</option>
1022 -</select></td></tr>
1023 -
1024 -<tr>
1025 -<th width="20%"><?php _e('Last update') ?>:</th>
1026 -<td colspan="2"><?php
1027 - if (isset($meta['update/last'])) :
1028 - echo strftime('%x %X', $meta['update/last'])." ";
1029 - else :
1030 - echo " none yet";
438 + $options = __('Options');
439 + $longoptions = __('Syndication Options');
1031 440 endif;
1032 -?></td></tr>
1033 -<tr><th width="20%">Next update:</th>
1034 -<td colspan="2"><?php
1035 - $holdem = (isset($meta['update/hold']) ? $meta['update/hold'] : 'scheduled');
1036 -?>
1037 -<select name="update_schedule">
1038 -<option value="scheduled"<?php echo ($holdem=='scheduled')?' selected="selected"':''; ?>>update on schedule <?php
1039 - echo " (";
1040 - if (isset($meta['update/ttl']) and is_numeric($meta['update/ttl'])) :
1041 - if (isset($meta['update/timed']) and $meta['update/timed']=='automatically') :
1042 - echo 'next: ';
1043 - $next = $meta['update/last'] + ((int) $meta['update/ttl'] * 60);
1044 - if (strftime('%x', time()) != strftime('%x', $next)) :
1045 - echo strftime('%x', $next)." ";
1046 - endif;
1047 - echo strftime('%X', $meta['update/last']+((int) $meta['update/ttl']*60));
1048 - else :
1049 - echo "every ".$meta['update/ttl']." minute".(($meta['update/ttl']!=1)?"s":"");
1050 - endif;
1051 - else:
1052 - echo "next scheduled update";
1053 - endif;
1054 - echo ")";
1055 -?></option>
1056 -<option value="next"<?php echo ($holdem=='next')?' selected="selected"':''; ?>>update ASAP</option>
1057 -<option value="ping"<?php echo ($holdem=='ping')?' selected="selected"':''; ?>>update only when pinged</option>
1058 -</select></tr>
1059 -</table>
1060 -</fieldset>
1061 441
1062 -<script type="text/javascript">
1063 -flip_hardcode('name');
1064 -flip_hardcode('description');
1065 -flip_hardcode('url');
1066 -</script>
442 + call_user_func_array('add_menu_page', $menu);
443 + add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Authors', 'Authors', $fwp_capability['manage_options'], $fwp_path.'/authors.php');
444 + add_submenu_page($fwp_path.'/syndication.php', $longoptions, $options, $fwp_capability['manage_options'], $fwp_path.'/syndication-options.php');
1067 445
1068 -<p class="submit">
1069 -<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1070 -</p>
446 + add_options_page($longoptions, 'Syndication', $fwp_capability['manage_options'], $fwp_path.'/syndication-options.php');
447 +} // function fwp_add_pages () */
1071 448
1072 -<fieldset>
1073 -<legend>Syndicated Posts</legend>
1074 -
1075 -<?php fwp_category_box($dogs, 'all syndicated posts from this feed'); ?>
1076 -
1077 -<table class="editform" width="75%" cellspacing="2" cellpadding="5">
1078 -<tr><th width="27%" scope="row" style="vertical-align:top">Publication:</th>
1079 -<td width="73%" style="vertical-align:top"><ul style="margin:0; list-style:none">
1080 -<li><label><input type="radio" name="feed_post_status" value="site-default"
1081 -<?php echo $status['post']['site-default']; ?> /> Use site-wide setting from <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a>
1082 -(currently: <strong><?php echo ($post_status_global ? $post_status_global : 'publish'); ?></strong>)</label></li>
1083 -<li><label><input type="radio" name="feed_post_status" value="publish"
1084 -<?php echo $status['post']['publish']; ?> /> Publish posts from this feed immediately</label></li>
1085 -<li><label><input type="radio" name="feed_post_status" value="private"
1086 -<?php echo $status['post']['private']; ?> /> Hold posts from this feed as private posts</label></li>
1087 -<li><label><input type="radio" name="feed_post_status" value="draft"
1088 -<?php echo $status['post']['draft']; ?> /> Hold posts from this feed as drafts</label></li>
1089 -</ul></td>
1090 -</tr>
1091 -
1092 -<tr><th width="27%" scope="row" style="vertical-align:top">Comments:</th>
1093 -<td width="73%"><ul style="margin:0; list-style:none">
1094 -<li><label><input type="radio" name="feed_comment_status" value="site-default"
1095 -<?php echo $status['comment']['site-default']; ?> /> Use site-wide setting from <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a>
1096 -(currently: <strong><?php echo ($comment_status_global ? $comment_status_global : 'closed'); ?>)</strong></label></li>
1097 -<li><label><input type="radio" name="feed_comment_status" value="open"
1098 -<?php echo $status['comment']['open']; ?> /> Allow comments on syndicated posts from this feed</label></li>
1099 -<li><label><input type="radio" name="feed_comment_status" value="closed"
1100 -<?php echo $status['comment']['closed']; ?> /> Don't allow comments on syndicated posts from this feed</label></li>
1101 -</ul></td>
1102 -</tr>
1103 -
1104 -<tr><th width="27%" scope="row" style="vertical-align:top">Trackback and Pingback:</th>
1105 -<td width="73%"><ul style="margin:0; list-style:none">
1106 -<li><label><input type="radio" name="feed_ping_status" value="site-default"
1107 -<?php echo $status['ping']['site-default']; ?> /> Use site-wide setting from <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a>
1108 -(currently: <strong><?php echo ($ping_status_global ? $ping_status_global : 'closed'); ?>)</strong></label></li>
1109 -<li><label><input type="radio" name="feed_ping_status" value="open"
1110 -<?php echo $status['ping']['open']; ?> /> Accept pings on syndicated posts from this feed</label></li>
1111 -<li><label><input type="radio" name="feed_ping_status" value="closed"
1112 -<?php echo $status['ping']['closed']; ?> /> Don't accept pings on syndicated posts from this feed</label></li>
1113 -</ul></td>
1114 -</tr>
1115 -</table>
1116 -</fieldset>
1117 -
1118 -<p class="submit">
1119 -<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1120 -</p>
1121 -
1122 -<fieldset>
1123 -<legend>Advanced Feed Options</legend>
1124 -<table class="editform" width="100%" cellspacing="2" cellpadding="5">
1125 -<tr>
1126 -<th width="20%" scope="row" style="vertical-align:top">Unfamiliar authors:</th>
1127 -<td width="80%"><ul style="margin: 0; list-style:none">
1128 -<li><label><input type="radio" name="unfamiliar_author" value="site-default"<?php echo $unfamiliar['author']['site-default']; ?> /> use site-wide setting from <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a>
1129 -(currently <strong><?php echo FeedWordPress::on_unfamiliar('author');; ?></strong>)</label></li>
1130 -<li><label><input type="radio" name="unfamiliar_author" value="create"<?php echo $unfamiliar['author']['create']; ?>/> create a new author account</label></li>
1131 -<li><label><input type="radio" name="unfamiliar_author" value="default"<?php echo $unfamiliar['author']['default']; ?> /> attribute the post to the default author</label></li>
1132 -<li><label><input type="radio" name="unfamiliar_author" value="filter"<?php echo $unfamiliar['author']['filter']; ?> /> don't syndicate the post</label></li>
1133 -</ul></td>
1134 -</tr>
1135 -
1136 -<tr>
1137 -<th width="20%" scope="row" style="vertical-align:top">Unfamiliar categories:</th>
1138 -<td width="80%"><ul style="margin: 0; list-style:none">
1139 -<li><label><input type="radio" name="unfamiliar_category" value="site-default"<?php echo $unfamiliar['category']['site-default']; ?> /> use site-wide setting from <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a>
1140 -(currently <strong><?php echo FeedWordPress::on_unfamiliar('category');; ?></strong>)</label></li>
1141 -<li><label><input type="radio" name="unfamiliar_category" value="create"<?php echo $unfamiliar['category']['create']; ?> /> create any categories the post is in</label></li>
1142 -<li><label><input type="radio" name="unfamiliar_category" value="default"<?php echo $unfamiliar['category']['default']; ?> /> don't create new categories</label></li>
1143 -<li><label><input type="radio" name="unfamiliar_category" value="filter"<?php echo $unfamiliar['category']['filter']; ?> /> don't create new categories and don't syndicate posts unless they match at least one familiar category</label></li>
1144 -</ul></td>
1145 -</tr>
1146 -
1147 -<tr>
1148 -<th width="20%" scope="row" style="vertical-align:top">Multiple categories:</th>
1149 -<td width="80%">
1150 -<input type="text" size="20" id="cat_split" name="cat_split" value="<?php if (isset($meta['cat_split'])) : echo htmlspecialchars($meta['cat_split']); endif; ?>" /><br/>
1151 -Enter a <a href="http://us.php.net/manual/en/reference.pcre.pattern.syntax.php">Perl-compatible regular expression</a> here if the feed provides multiple
1152 -categories in a single category element. The regular expression should match
1153 -the characters used to separate one category from the next. If the feed uses
1154 -spaces (like <a href="http://del.icio.us/">del.icio.us</a>), use the pattern "\s".
1155 -If the feed does not provide multiple categories in a single element, leave this
1156 -blank.</td>
1157 -</tr>
1158 -</table>
1159 -</fieldset>
1160 -
1161 -<p class="submit">
1162 -<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1163 -</p>
1164 -
1165 -<fieldset id="postcustom">
1166 -<legend>Custom Settings (for use in templates)</legend>
1167 -<div id="postcustomstuff">
1168 -<table id="meta-list" cellpadding="3">
1169 - <tr>
1170 - <th>Key</th>
1171 - <th>Value</th>
1172 - <th>Action</th>
1173 - </tr>
1174 -
1175 -<?php
1176 - $i = 0;
1177 - foreach ($meta as $key => $value) :
1178 - if (!preg_match("\007^((".implode(')|(', $special_settings)."))$\007i", $key)) :
1179 -?>
1180 - <tr style="vertical-align:top">
1181 - <th width="30%" scope="row"><input type="hidden" name="notes[<?php echo $i; ?>][key0]" value="<?php echo wp_specialchars($key, 'both'); ?>" />
1182 - <input id="notes-<?php echo $i; ?>-key" name="notes[<?php echo $i; ?>][key1]" value="<?php echo wp_specialchars($key, 'both'); ?>" /></th>
1183 - <td width="60%"><textarea rows="2" cols="40" id="notes-<?php echo $i; ?>-value" name="notes[<?php echo $i; ?>][value]"><?php echo wp_specialchars($value, 'both'); ?></textarea></td>
1184 - <td width="10%"><select name="notes[<?php echo $i; ?>][action]">
1185 - <option value="update">save changes</option>
1186 - <option value="delete">delete this setting</option>
1187 - </select></td>
1188 - </tr>
1189 -<?php
1190 - $i++;
1191 - endif;
1192 - endforeach;
1193 -?>
1194 - <tr>
1195 - <th scope="row"><input type="text" size="10" name="notes[<?php echo $i; ?>][key1]" value="" /></th>
1196 - <td><textarea name="notes[<?php echo $i; ?>][value]" rows="2" cols="40"></textarea></td>
1197 - <td><em>add new setting...</em><input type="hidden" name="notes[<?php echo $i; ?>][action]" value="update" /></td>
1198 - </tr>
1199 -</table>
1200 -</fieldset>
1201 -
1202 -<p class="submit">
1203 -<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1204 -</p>
1205 -
1206 -</div>
1207 - <?php
1208 - endif;
1209 - return false; // Don't continue
1210 -}
1211 -
1212 -function fwp_multidelete_page () {
1213 - global $wpdb;
1214 -
1215 - check_admin_referer(); // Make sure the referers are kosher
1216 -
1217 - $link_ids = (isset($_REQUEST['link_ids']) ? $_REQUEST['link_ids'] : array());
1218 - if (isset($_REQUEST['link_id'])) : array_push($link_ids, $_REQUEST['link_id']); endif;
1219 -
1220 - if (!current_user_can('manage_links')):
1221 - die (__("Cheatin' uh ?"));
1222 - elseif (isset($GLOBALS['fwp_post']['confirm']) and $GLOBALS['fwp_post']['confirm']=='Delete'):
1223 - foreach ($GLOBALS['fwp_post']['link_action'] as $link_id => $what) :
1224 - $do_it[$what][] = $link_id;
1225 - endforeach;
1226 -
1227 - $alter = array();
1228 - if (count($do_it['hide']) > 0) :
1229 - $hidem = "(".implode(', ', $do_it['hide']).")";
1230 - $alter[] = "
1231 - UPDATE $wpdb->links
1232 - SET link_visible = 'N'
1233 - WHERE link_id IN {$hidem}
1234 - ";
1235 - endif;
1236 -
1237 - if (count($do_it['nuke']) > 0) :
1238 - $nukem = "(".implode(', ', $do_it['nuke']).")";
1239 -
1240 - // Make a list of the items syndicated from this feed...
1241 - $post_ids = $wpdb->get_col("
1242 - SELECT post_id FROM $wpdb->postmeta
1243 - WHERE meta_key = 'syndication_feed_id'
1244 - AND meta_value IN {$nukem}
1245 - ");
1246 -
1247 - // ... and kill them all
1248 - if (count($post_ids) > 0) :
1249 - foreach ($post_ids as $post_id) :
1250 - wp_delete_post($post_id);
1251 - endforeach;
1252 - endif;
1253 -
1254 - $alter[] = "
1255 - DELETE FROM $wpdb->links
1256 - WHERE link_id IN {$nukem}
1257 - ";
1258 - endif;
1259 -
1260 - if (count($do_it['delete']) > 0) :
1261 - $deletem = "(".implode(', ', $do_it['delete']).")";
1262 -
1263 - // Make the items syndicated from this feed appear to be locally-authored
1264 - $alter[] = "
1265 - DELETE FROM $wpdb->postmeta
1266 - WHERE meta_key = 'syndication_feed_id'
1267 - AND meta_value IN {$deletem}
1268 - ";
1269 -
1270 - // ... and delete the links themselves.
1271 - $alter[] = "
1272 - DELETE FROM $wpdb->links
1273 - WHERE link_id IN {$deletem}
1274 - ";
1275 - endif;
1276 -
1277 - $errs = array(); $success = array ();
1278 - foreach ($alter as $sql) :
1279 - $result = $wpdb->query($sql);
1280 - if (!$result):
1281 - $errs[] = mysql_error();
1282 - endif;
1283 - endforeach;
1284 -
1285 - if (count($alter) > 0) :
1286 - echo "<div class=\"updated\">\n";
1287 - if (count($errs) > 0) :
1288 - echo "There were some problems processing your ";
1289 - echo "unsubscribe request. [SQL: ".implode('; ', $errs)."]";
1290 - else :
1291 - echo "Your unsubscribe request(s) have been processed.";
1292 - endif;
1293 - echo "</div>\n";
1294 - endif;
1295 -
1296 - return true; // Continue on to Syndicated Sites listing
1297 - else :
1298 - $targets = $wpdb->get_results("
1299 - SELECT * FROM $wpdb->links
1300 - WHERE link_id IN (".implode(",",$link_ids).")
1301 - ");
1302 -?>
1303 -<form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
1304 -<div class="wrap">
1305 -<input type="hidden" name="action" value="Unsubscribe" />
1306 -<input type="hidden" name="confirm" value="Delete" />
1307 -
1308 -<h2>Unsubscribe from Syndicated Links:</h2>
1309 -<?php foreach ($targets as $link) :
1310 - $link_url = wp_specialchars($link->link_url, 1);
1311 - $link_name = wp_specialchars($link->link_name, 1);
1312 - $link_description = wp_specialchars($link->link_description, 'both');
1313 - $link_rss = wp_specialchars($link->link_rss, 'both');
1314 -?>
1315 -<fieldset>
1316 -<legend><?php echo $link_name; ?></legend>
1317 -<table class="editform" width="100%" cellspacing="2" cellpadding="5">
1318 -<tr><th scope="row" width="20%"><?php _e('Feed URI:') ?></th>
1319 -<td width="80%"><a href="<?php echo $link_rss; ?>"><?php echo $link_rss; ?></a></td></tr>
1320 -<tr><th scope="row" width="20%"><?php _e('Short description:') ?></th>
1321 -<td width="80%"><?php echo $link_description; ?></span></td></tr>
1322 -<tr><th width="20%" scope="row"><?php _e('Homepage:') ?></th>
1323 -<td width="80%"><a href="<?php echo $link_url; ?>"><?php echo $link_url; ?></a></td></tr>
1324 -<tr style="vertical-align:top"><th width="20%" scope="row">Subscription <?php _e('Options') ?>:</th>
1325 -<td width="80%"><ul style="margin:0; padding: 0; list-style: none">
1326 -<li><input type="radio" id="hide-<?php echo $link->link_id; ?>"
1327 -name="link_action[<?php echo $link->link_id; ?>]" value="hide" />
1328 -<label for="hide-<?php echo $link->link_id; ?>">Turn off the subscription for this
1329 -syndicated link<br/><span style="font-size:smaller">(Keep the feed information
1330 -and all the posts from this feed in the database, but don't syndicate any
1331 -new posts from the feed.)</span></label></li>
1332 -<li><input type="radio" id="nuke-<?php echo $link->link_id; ?>"
1333 -name="link_action[<?php echo $link->link_id; ?>]" value="nuke" />
1334 -<label for="nuke-<?php echo $link->link_id; ?>">Delete this syndicated link and all the
1335 -posts that were syndicated from it</label></li>
1336 -<li><input type="radio" id="delete-<?php echo $link->link_id; ?>"
1337 -name="link_action[<?php echo $link->link_id; ?>]" value="delete" />
1338 -<label for="delete-<?php echo $link->link_id; ?>">Delete this syndicated link, but
1339 -<em>keep</em> posts that were syndicated from it (as if they were authored
1340 -locally).</label></li>
1341 -<li><input type="radio" id="nothing-<?php echo $link->link_id; ?>"
1342 -name="link_action[<?php echo $link->link_id; ?>]" value="nothing" />
1343 -<label for="nothing-<?php echo $link->link_id; ?>">Keep this feed as it is. I changed
1344 -my mind.</label></li>
1345 -</ul>
1346 -</table>
1347 -</fieldset>
1348 -<?php endforeach; ?>
1349 -
1350 -<div class="submit">
1351 -<input class="delete" type="submit" name="submit" value="<?php _e('Unsubscribe from selected feeds &raquo;') ?>" />
1352 -</div>
1353 -</div>
1354 -<?php
1355 - return false; // Don't continue on to Syndicated Sites listing
1356 - endif;
1357 -}
1358 -
1359 449 ################################################################################
1360 450 ## fwp_hold_pings() and fwp_release_pings(): Outbound XML-RPC ping reform ####
1361 451 ## ... 'coz it's rude to send 500 pings the first time your aggregator runs ####
1362 452 ################################################################################
@@ -1510,9 +600,9 @@
1510 600 #
1511 601 # * Updates to existing posts since the last poll are mirrored in the
1512 602 # WordPress store.
1513 603 #
1514 - function update ($uri = null) {
604 + function update ($uri = null, $crash_ts = null) {
1515 605 global $wpdb;
1516 606
1517 607 if (FeedWordPress::needs_upgrade()) : // Will make duplicate posts if we don't hold off
1518 608 return NULL;
@@ -1525,11 +615,28 @@
1525 615 endif;
1526 616
1527 617 do_action('feedwordpress_update', $uri);
1528 618
619 + if (is_null($crash_ts)) :
620 + $crash_dt = (int) get_option('feedwordpress_update_time_limit');
621 + if ($crash_dt > 0) :
622 + $crash_ts = time() + $crash_dt;
623 + else :
624 + $crash_ts = NULL;
625 + endif;
626 + endif;
627 +
628 + // Randomize order for load balancing purposes
629 + $feed_set = $this->feeds;
630 + shuffle($feed_set);
631 +
1529 632 // Loop through and check for new posts
1530 633 $delta = NULL;
1531 - foreach ($this->feeds as $feed) :
634 + foreach ($feed_set as $feed) :
635 + if (!is_null($crash_ts) and (time() > $crash_ts)) : // Check whether we've exceeded the time limit
636 + break;
637 + endif;
638 +
1532 639 $pinged_that = (is_null($uri) or in_array($uri, array($feed->uri(), $feed->homepage())));
1533 640
1534 641 if (!is_null($uri)) : // A site-specific ping always updates
1535 642 $timely = true;
@@ -1542,9 +649,12 @@
1542 649 endif;
1543 650
1544 651 if ($pinged_that and $timely) :
1545 652 do_action('feedwordpress_check_feed', $feed->settings);
1546 - $added = $feed->poll();
653 + $start_ts = time();
654 + $added = $feed->poll($crash_ts);
655 + do_action('feedwordpress_check_feed_complete', $feed->settings, $added, time() - $start_ts);
656 +
1547 657 if (isset($added['new'])) : $delta['new'] += $added['new']; endif;
1548 658 if (isset($added['updated'])) : $delta['updated'] += $added['updated']; endif;
1549 659 endif;
1550 660 endforeach;
@@ -1602,9 +712,9 @@
1602 712 if (function_exists('wp_insert_link')) { // WordPress 2.x
1603 713 $link_id = wp_insert_link(array(
1604 714 "link_name" => $name,
1605 715 "link_url" => $uri,
1606 - "link_category" => array($cat_id),
716 + "link_category" => (fwp_test_wp_version(0, FWP_SCHEMA_21) ? $cat_id : array($cat_id)),
1607 717 "link_rss" => $rss
1608 718 ));
1609 719 } else { // WordPress 1.5.x
1610 720 $result = $wpdb->query("
@@ -1620,14 +730,20 @@
1620 730 return $link_id;
1621 731 } // function FeedWordPress::syndicate_link()
1622 732
1623 733 function on_unfamiliar ($what = 'author', $override = NULL) {
1624 - $set = array('create', 'default', 'filter');
734 + $set = array(
735 + 'author' => array('create', 'default', 'filter'),
736 + 'category' => array('create', 'tag', 'default', 'filter'),
737 + );
738 +
739 + if (is_string($override)) :
740 + $ret = strtolower($override);
741 + endif;
1625 742
1626 - $ret = strtolower($override);
1627 - if (!in_array($ret, $set)) :
743 + if (!is_numeric($override) and !in_array($ret, $set[$what])) :
1628 744 $ret = get_option('feedwordpress_unfamiliar_'.$what);
1629 - if (!in_array($ret, $set)) :
745 + if (!is_numeric($ret) and !in_array($ret, $set[$what])) :
1630 746 $ret = 'create';
1631 747 endif;
1632 748 endif;
1633 749
@@ -1633,8 +749,33 @@
1633 749
1634 750 return $ret;
1635 751 } // function FeedWordPress::on_unfamiliar()
1636 752
753 + function null_email_set () {
754 + $base = get_option('feedwordpress_null_email_set');
755 +
756 + if ($base===false) :
757 + $ret = array('noreply@blogger.com'); // default
758 + else :
759 + $ret = array_map('strtolower',
760 + array_map('trim', explode("\n", $base)));
761 + endif;
762 + $ret = apply_filters('syndicated_item_author_null_email_set', $ret);
763 + return $ret;
764 +
765 + } /* FeedWordPress::null_email_set () */
766 +
767 + function is_null_email ($email) {
768 + $ret = in_array(strtolower(trim($email)), FeedWordPress::null_email_set());
769 + $ret = apply_filters('syndicated_item_author_is_null_email', $ret, $email);
770 + return $ret;
771 + } /* FeedWordPress::is_null_email () */
772 +
773 + function use_aggregator_source_data () {
774 + $ret = get_option('feedwordpress_use_aggregator_source_data');
775 + return apply_filters('syndicated_post_use_aggregator_source_data', ($ret=='yes'));
776 + }
777 +
1637 778 function syndicated_links () {
1638 779 $contributors = FeedWordPress::link_category_id();
1639 780 if (function_exists('get_bookmarks')) :
1640 781 $links = get_bookmarks(array("category" => $contributors));
@@ -1677,12 +818,12 @@
1677 818 if (function_exists('wp_insert_term')) :
1678 819 $term = wp_insert_term($cat, 'link_category');
1679 820 $cat_id = $term['term_id'];
1680 821 // WordPress 2.1, 2.2 category API. By the way, why the fuck is this API function only available in a wp-admin module?
1681 - elseif (function_exists('wp_insert_category')) :
822 + elseif (function_exists('wp_insert_category') and !fwp_test_wp_version(FWP_SCHEMA_20, FWP_SCHEMA_21)) :
1682 823 $cat_id = wp_insert_category(array('cat_name' => $cat));
1683 824 // WordPress 1.5 and 2.0.x
1684 - elseif (!isset($wp_db_version) or $wp_db_version < FWP_SCHEMA_21) :
825 + elseif (fwp_test_wp_version(0, FWP_SCHEMA_21)) :
1685 826 $result = $wpdb->query("
1686 827 INSERT INTO $wpdb->linkcategories
1687 828 SET
1688 829 cat_id = 0,
@@ -1792,8 +933,16 @@
1792 933 endswitch;
1793 934 echo "<p>Upgrade complete. FeedWordPress is now ready to use again.</p>";
1794 935 } /* FeedWordPress::upgrade_database() */
1795 936
937 + function create_guid_index () {
938 + global $wpdb;
939 +
940 + $wpdb->query("
941 + CREATE INDEX {$wpdb->posts}_guid_idx ON {$wpdb->posts}(guid)
942 + ");
943 + } /* FeedWordPress::create_guid_index () */
944 +
1796 945 # Utility functions for handling text settings
1797 946 function negative ($f, $setting) {
1798 947 $nego = array ('n', 'no', 'f', 'false');
1799 948 return (isset($f[$setting]) and in_array(strtolower($f[$setting]), $nego));
@@ -1818,8 +967,14 @@
1818 967 echo "\n";
1819 968 echo $varname.": "; var_dump($var); echo "\n";
1820 969 die;
1821 970 }
971 +
972 + function noncritical_bug ($varname, $var, $line) {
973 + if (FEEDWORDPRESS_DEBUG) : // halt only when we are doing debugging
974 + FeedWordPress::critical_bug($varname, $var, $line);
975 + endif;
976 + }
1822 977 } // class FeedWordPress
1823 978
1824 979 class SyndicatedPost {
1825 980 var $item = null;
@@ -1833,13 +988,8 @@
1833 988
1834 989 var $_freshness = null;
1835 990 var $_wp_id = null;
1836 991
1837 - var $strip_attrs = array (
1838 - array('[a-z]+', 'style'),
1839 - array('[a-z]+', 'target'),
1840 - );
1841 -
1842 992 function SyndicatedPost ($item, $link) {
1843 993 global $wpdb;
1844 994
1845 995 $this->link = $link;
@@ -1870,14 +1020,14 @@
1870 1020 # That's deliberate. The escaping is done at the point
1871 1021 # of insertion, not here, to avoid double-escaping and
1872 1022 # to avoid screwing with syndicated_post filters
1873 1023
1874 - $this->post['post_title'] = $this->item['title'];
1024 + $this->post['post_title'] = apply_filters('syndicated_item_title', $this->item['title'], $this);
1875 1025
1876 - // This just gives usan alphanumeric representation of
1026 + // This just gives us an alphanumeric representation of
1877 1027 // the author. We will look up (or create) the numeric
1878 1028 // ID for the author in SyndicatedPost::add()
1879 - $this->post['named']['author'] = $this->author();
1029 + $this->post['named']['author'] = apply_filters('syndicated_item_author', $this->author(), $this);
1880 1030
1881 1031 # Identify content and sanitize it.
1882 1032 # ---------------------------------
1883 1033 if (isset($this->item['xhtml']['body'])) :
@@ -1888,24 +1038,9 @@
1888 1038 $content = $this->item['content']['encoded'];
1889 1039 else:
1890 1040 $content = $this->item['description'];
1891 1041 endif;
1892 -
1893 - # FeedWordPress used to resolve URIs relative to the
1894 - # feed URI. It now relies on the xml:base support
1895 - # baked in to the MagpieRSS upgrade. So all we do here
1896 - # now is to sanitize problematic attributes.
1897 - #
1898 - # This kind of sucks. I intend to replace it with
1899 - # lib_filter sometime soon.
1900 - foreach ($this->strip_attrs as $pair):
1901 - list($tag,$attr) = $pair;
1902 - $content = preg_replace (
1903 - ":(<$tag [^>]*)($attr=(\"[^\">]*\"|[^>\\s]+))([^>]*>):i",
1904 - "\\1\\4",
1905 - $content
1906 - );
1907 - endforeach;
1042 + $this->post['post_content'] = apply_filters('syndicated_item_content', $content, $this);
1908 1043
1909 1044 # Identify and sanitize excerpt
1910 1045 $excerpt = NULL;
1911 1046 if ( isset($this->item['description']) and $this->item['description'] ) :
@@ -1915,11 +1050,10 @@
1915 1050 if (strlen($excerpt) > 255) :
1916 1051 $excerpt = substr($excerpt,0,252).'...';
1917 1052 endif;
1918 1053 endif;
1054 + $excerpt = apply_filters('syndicated_item_excerpt', $excerpt, $this);
1919 1055
1920 - $this->post['post_content'] = $content;
1921 -
1922 1056 if (!is_null($excerpt)):
1923 1057 $this->post['post_excerpt'] = $excerpt;
1924 1058 endif;
1925 1059
@@ -1927,11 +1061,11 @@
1927 1061 if (!$this->use_api('wp_insert_post')) :
1928 1062 $this->post['post_name'] = sanitize_title($this->post['post_title']);
1929 1063 endif;
1930 1064
1931 - $this->post['epoch']['issued'] = $this->published();
1932 - $this->post['epoch']['created'] = $this->created();
1933 - $this->post['epoch']['modified'] = $this->updated();
1065 + $this->post['epoch']['issued'] = apply_filters('syndicated_item_published', $this->published(), $this);
1066 + $this->post['epoch']['created'] = apply_filters('syndicated_item_created', $this->created(), $this);
1067 + $this->post['epoch']['modified'] = apply_filters('syndicated_item_updated', $this->updated(), $this);
1934 1068
1935 1069 // Dealing with timestamps in WordPress is so fucking fucked.
1936 1070 $offset = (int) get_option('gmt_offset') * 60 * 60;
1937 1071 $this->post['post_date'] = gmdate('Y-m-d H:i:s', $this->published() + $offset);
@@ -1944,9 +1078,9 @@
1944 1078 $this->post['comment_status'] = $this->link->syndicated_status('comment', 'closed');
1945 1079 $this->post['ping_status'] = $this->link->syndicated_status('ping', 'closed');
1946 1080
1947 1081 // Unique ID (hopefully a unique tag: URI); failing that, the permalink
1948 - $this->post['guid'] = $this->guid();
1082 + $this->post['guid'] = apply_filters('syndicated_item_guid', $this->guid(), $this);
1949 1083
1950 1084 // RSS 2.0 / Atom 1.0 enclosure support
1951 1085 if ( isset($this->item['enclosure#']) ) :
1952 1086 for ($i = 1; $i <= $this->item['enclosure#']; $i++) :
@@ -1951,28 +1085,42 @@
1951 1085 if ( isset($this->item['enclosure#']) ) :
1952 1086 for ($i = 1; $i <= $this->item['enclosure#']; $i++) :
1953 1087 $eid = (($i > 1) ? "#{$id}" : "");
1954 1088 $this->post['meta']['enclosure'][] =
1955 - $this->item["enclosure{$eid}@url"]."\n".
1956 - $this->item["enclosure{$eid}@length"]."\n".
1957 - $this->item["enclosure{$eid}@type"];
1089 + apply_filters('syndicated_item_enclosure_url', $this->item["enclosure{$eid}@url"], $this)."\n".
1090 + apply_filters('syndicated_item_enclosure_length', $this->item["enclosure{$eid}@length"], $this)."\n".
1091 + apply_filters('syndicated_item_enclosure_type', $this->item["enclosure{$eid}@type"], $this);
1958 1092 endfor;
1959 1093 endif;
1960 1094
1961 1095 // In case you want to point back to the blog this was syndicated from
1962 1096 if (isset($this->feed->channel['title'])) :
1963 - $this->post['meta']['syndication_source'] = $this->feed->channel['title'];
1097 + $this->post['meta']['syndication_source'] = apply_filters('syndicated_item_source_title', $this->feed->channel['title'], $this);
1964 1098 endif;
1099 +
1965 1100 if (isset($this->feed->channel['link'])) :
1966 - $this->post['meta']['syndication_source_uri'] = $this->feed->channel['link'];
1101 + $this->post['meta']['syndication_source_uri'] = apply_filters('syndicated_item_source_link', $this->feed->channel['link'], $this);
1967 1102 endif;
1968 1103
1104 + // Make use of atom:source data, if present in an aggregated feed
1105 + if (isset($this->item['source_title'])) :
1106 + $this->post['meta']['syndication_source_original'] = $this->item['source_title'];
1107 + endif;
1108 +
1109 + if (isset($this->item['source_link'])) :
1110 + $this->post['meta']['syndication_source_uri_original'] = $this->item['source_link'];
1111 + endif;
1112 +
1113 + if (isset($this->item['source_id'])) :
1114 + $this->post['meta']['syndication_source_id_original'] = $this->item['source_id'];
1115 + endif;
1116 +
1969 1117 // Store information on human-readable and machine-readable comment URIs
1970 1118 if (isset($this->item['comments'])) :
1971 - $this->post['meta']['rss:comments'] = $this->item['comments'];
1119 + $this->post['meta']['rss:comments'] = apply_filters('syndicated_item_comments', $this->item['comments']);
1972 1120 endif;
1973 1121 if (isset($this->item['wfw']['commentrss'])) :
1974 - $this->post['meta']['wfw:commentRSS'] = $this->item['wfw']['commentrss'];
1122 + $this->post['meta']['wfw:commentRSS'] = apply_filters('syndicated_item_commentrss', $this->item['wfw']['commentrss']);
1975 1123 endif;
1976 1124
1977 1125 // Store information to identify the feed that this came from
1978 1126 $this->post['meta']['syndication_feed'] = $this->feedmeta['link/uri'];
@@ -1977,14 +1125,21 @@
1977 1125 // Store information to identify the feed that this came from
1978 1126 $this->post['meta']['syndication_feed'] = $this->feedmeta['link/uri'];
1979 1127 $this->post['meta']['syndication_feed_id'] = $this->feedmeta['link/id'];
1980 1128
1129 + if (isset($this->item['source_link_self'])) :
1130 + $this->post['meta']['syndication_feed_original'] = $this->item['source_link_self'];
1131 + endif;
1132 +
1981 1133 // In case you want to know the external permalink...
1982 - $this->post['meta']['syndication_permalink'] = $this->item['link'];
1134 + $this->post['meta']['syndication_permalink'] = apply_filters('syndicated_item_link', $this->item['link']);
1983 1135
1136 + // Store a hash of the post content for checking whether something needs to be updated
1137 + $this->post['meta']['syndication_item_hash'] = $this->update_hash();
1138 +
1984 1139 // Feed-by-feed options for author and category creation
1985 1140 $this->post['named']['unfamiliar']['author'] = $this->feedmeta['unfamiliar author'];
1986 - $this->post['named']['unfamiliar']['category'] = $this->feedmeta['unfamiliar categories'];
1141 + $this->post['named']['unfamiliar']['category'] = $this->feedmeta['unfamiliar category'];
1987 1142
1988 1143 // Categories: start with default categories, if any
1989 1144 $fc = get_option("feedwordpress_syndication_cats");
1990 1145 if ($fc) :
@@ -2011,8 +1166,22 @@
2011 1166 $this->post['named']['category'][] = $cat;
2012 1167 endif;
2013 1168 endfor;
2014 1169 endif;
1170 + $this->post['named']['category'] = apply_filters('syndicated_item_categories', $this->post['named']['category'], $this);
1171 +
1172 + // Tags: start with default tags, if any
1173 + $ft = get_option("feedwordpress_syndication_tags");
1174 + if ($ft) :
1175 + $this->post['tags_input'] = explode(FEEDWORDPRESS_CAT_SEPARATOR, $ft);
1176 + else :
1177 + $this->post['tags_input'] = array();
1178 + endif;
1179 +
1180 + if (is_array($this->feedmeta['tags'])) :
1181 + $this->post['tags_input'] = array_merge($this->post['tags_input'], $this->feedmeta['tags']);
1182 + endif;
1183 +
2015 1184 endif;
2016 1185 } // SyndicatedPost::SyndicatedPost()
2017 1186
2018 1187 function filtered () {
@@ -2033,18 +1202,35 @@
2033 1202 SELECT id, guid, post_modified_gmt
2034 1203 FROM $wpdb->posts WHERE guid='$guid'
2035 1204 ");
2036 1205
2037 - preg_match('/([0-9]+)-([0-9]+)-([0-9]+) ([0-9]+):([0-9]+):([0-9]+)/', $result->post_modified_gmt, $backref);
2038 - $updated = gmmktime($backref[4], $backref[5], $backref[6], $backref[2], $backref[3], $backref[1]);
2039 1206 if (!$result) :
2040 1207 $this->_freshness = 2; // New content
2041 - elseif ($this->updated() > $updated) :
2042 - $this->_freshness = 1; // Updated content
2043 - $this->_wp_id = $result->id;
2044 - else :
2045 - $this->_freshness = 0; // Same old, same old
2046 - $this->_wp_id = $result->id;
1208 + else:
1209 + $stored_update_hashes = get_post_custom_values('syndication_item_hash', $result->id);
1210 + if (count($stored_update_hashes) > 0) :
1211 + $stored_update_hash = $stored_update_hashes[0];
1212 + $update_hash_changed = ($stored_update_hash != $this->update_hash());
1213 + else :
1214 + $update_hash_changed = false;
1215 + endif;
1216 +
1217 + preg_match('/([0-9]+)-([0-9]+)-([0-9]+) ([0-9]+):([0-9]+):([0-9]+)/', $result->post_modified_gmt, $backref);
1218 +
1219 + $last_rev_ts = gmmktime($backref[4], $backref[5], $backref[6], $backref[2], $backref[3], $backref[1]);
1220 + $updated_ts = $this->updated(/*fallback=*/ true, /*default=*/ NULL);
1221 + $updated = ((
1222 + !is_null($updated_ts)
1223 + and ($updated_ts > $last_rev_ts)
1224 + ) or $update_hash_changed);
1225 +
1226 + if ($updated) :
1227 + $this->_freshness = 1; // Updated content
1228 + $this->_wp_id = $result->id;
1229 + else :
1230 + $this->_freshness = 0; // Same old, same old
1231 + $this->_wp_id = $result->id;
1232 + endif;
2047 1233 endif;
2048 1234 endif;
2049 1235 return $this->_freshness;
2050 1236 }
@@ -2080,13 +1266,17 @@
2080 1266 endif;
2081 1267
2082 1268 if (!$this->filtered() and $freshness > 0) :
2083 1269 # -- Look up, or create, numeric ID for categories
2084 - $this->post['post_category'] = $this->category_ids (
1270 + list($pcats, $ptags) = $this->category_ids (
2085 1271 $this->post['named']['category'],
2086 - FeedWordPress::on_unfamiliar('category', $this->post['named']['unfamiliar']['category'])
1272 + FeedWordPress::on_unfamiliar('category', $this->post['named']['unfamiliar']['category']),
1273 + /*tags_too=*/ true
2087 1274 );
2088 -
1275 +
1276 + $this->post['post_category'] = $pcats;
1277 + $this->post['tags_input'] = array_merge($this->post['tags_input'], $ptags);
1278 +
2089 1279 if (is_null($this->post['post_category'])) :
2090 1280 // filter mode on, no matching categories; drop the post
2091 1281 $this->post = NULL;
2092 1282 else :
@@ -2142,15 +1332,37 @@
2142 1332 $dbpost[$key] = $value;
2143 1333 endif;
2144 1334 endforeach;
2145 1335
1336 + if (strlen($dbpost['post_title'].$dbpost['post_content'].$dbpost['post_excerpt']) == 0) :
1337 + // FIXME: Option for filtering out empty posts
1338 + endif;
1339 + if (strlen($dbpost['post_title'])==0) :
1340 + $dbpost['post_title'] = $this->post['meta']['syndication_source']
1341 + .' '.gmdate('Y-m-d H:i:s', $this->published() + $offset);
1342 + // FIXME: Option for what to fill a blank title with...
1343 + endif;
1344 +
2146 1345 if ($this->use_api('wp_insert_post')) :
2147 1346 $dbpost['post_pingback'] = false; // Tell WP 2.1 and 2.2 not to process for pingbacks
1347 +
1348 + // This is a ridiculous fucking kludge necessitated by WordPress 2.6 munging authorship meta-data
1349 + add_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1350 +
1351 + // Kludge to prevent kses filters from stripping the
1352 + // content of posts when updating without a logged in
1353 + // user who has `unfiltered_html` capability.
1354 + add_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1355 +
2148 1356 $this->_wp_id = wp_insert_post($dbpost);
2149 -
1357 +
1358 + // Turn off ridiculous fucking kludges #1 and #2
1359 + remove_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1360 + remove_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1361 +
2150 1362 // This should never happen.
2151 1363 if (!is_numeric($this->_wp_id) or ($this->_wp_id == 0)) :
2152 - FeedWordPress::critical_bug('SyndicatedPost (_wp_id problem)', $this, __LINE__);
1364 + FeedWordPress::critical_bug('SyndicatedPost (_wp_id problem)', array("dbpost" => $dbpost, "this" => $this), __LINE__);
2153 1365 endif;
2154 1366
2155 1367 // Unfortunately, as of WordPress 2.3, wp_insert_post()
2156 1368 // *still* offers no way to use a guid of your choice,
@@ -2193,9 +1405,9 @@
2193 1405 $this->_wp_id = $wpdb->insert_id;
2194 1406
2195 1407 // This should never happen.
2196 1408 if (!is_numeric($this->_wp_id) or ($this->_wp_id == 0)) :
2197 - FeedWordPress::critical_bug('SyndicatedPost::_wp_id', $this->_wp_id, __LINE__);
1409 + FeedWordPress::critical_bug('SyndicatedPost (_wp_id problem)', array("dbpost" => $dbpost, "this" => $this), __LINE__);
2198 1410 endif;
2199 1411
2200 1412 // WordPress 1.5.x - 2.0.x
2201 1413 wp_set_post_cats('1', $this->wp_id(), $this->post['post_category']);
@@ -2224,13 +1436,26 @@
2224 1436 endforeach;
2225 1437
2226 1438 if ($this->use_api('wp_insert_post')) :
2227 1439 $dbpost['post_pingback'] = false; // Tell WP 2.1 and 2.2 not to process for pingbacks
1440 +
1441 + // This is a ridiculous fucking kludge necessitated by WordPress 2.6 munging authorship meta-data
1442 + add_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1443 +
1444 + // Kludge to prevent kses filters from stripping the
1445 + // content of posts when updating without a logged in
1446 + // user who has `unfiltered_html` capability.
1447 + add_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1448 +
2228 1449 $this->_wp_id = wp_insert_post($dbpost);
2229 1450
1451 + // Turn off ridiculous fucking kludges #1 and #2
1452 + remove_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1453 + remove_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1454 +
2230 1455 // This should never happen.
2231 1456 if (!is_numeric($this->_wp_id) or ($this->_wp_id == 0)) :
2232 - FeedWordPress::critical_bug('SyndicatedPost::_wp_id', $this->_wp_id, __LINE__);
1457 + FeedWordPress::critical_bug('SyndicatedPost (_wp_id problem)', array("dbpost" => $dbpost, "this" => $this), __LINE__);
2233 1458 endif;
2234 1459
2235 1460 // Unfortunately, as of WordPress 2.3, wp_insert_post()
2236 1461 // munges your post modified timestamp.
@@ -2263,9 +1488,9 @@
2263 1488 elseif (function_exists('wp_set_post_cats')) :
2264 1489 wp_set_post_cats('1', $this->wp_id(), $this->post['post_category']);
2265 1490 // This should never happen.
2266 1491 else :
2267 - FeedWordPress::critical_bug('SyndicatedPost::insert_new::wp_version', $GLOBALS['wp_version'], __LINE__);
1492 + FeedWordPress::critical_bug('SyndicatedPost (_wp_id problem)', array("dbpost" => $dbpost, "this" => $this), __LINE__);
2268 1493 endif;
2269 1494
2270 1495 // Since we are not going through official channels, we need to
2271 1496 // manually tell WordPress that we've published a new post.
@@ -2276,8 +1501,63 @@
2276 1501 do_action('edit_post', $this->post['ID']);
2277 1502 endif;
2278 1503 } /* SyndicatedPost::update_existing() */
2279 1504
1505 + /**
1506 + * SyndicatedPost::fix_revision_meta() - Fixes the way WP 2.6+ fucks up
1507 + * meta-data (authorship, etc.) when storing revisions of an updated
1508 + * syndicated post.
1509 + *
1510 + * In their infinite wisdom, the WordPress coders have made it completely
1511 + * impossible for a plugin that uses wp_insert_post() to set certain
1512 + * meta-data (such as the author) when you store an old revision of an
1513 + * updated post. Instead, it uses the WordPress defaults (= currently
1514 + * active user ID if the process is running with a user logged in, or
1515 + * = #0 if there is no user logged in). This results in bogus authorship
1516 + * data for revisions that are syndicated from off the feed, unless we
1517 + * use a ridiculous kludge like this to end-run the munging of meta-data
1518 + * by _wp_put_post_revision.
1519 + *
1520 + * @param int $revision_id The revision ID to fix up meta-data
1521 + */
1522 + function fix_revision_meta ($revision_id) {
1523 + global $wpdb;
1524 +
1525 + $post_author = (int) $this->post['post_author'];
1526 +
1527 + $revision_id = (int) $revision_id;
1528 + $wpdb->query("
1529 + UPDATE $wpdb->posts
1530 + SET post_author={$this->post['post_author']}
1531 + WHERE post_type = 'revision' AND ID='$revision_id'
1532 + ");
1533 + } /* SyndicatedPost::fix_revision_meta () */
1534 +
1535 + /**
1536 + * SyndicatedPost::avoid_kses_munge() -- If FeedWordPress is processing
1537 + * an automatic update, that generally means that wp_insert_post() is
1538 + * being called under the user credentials of whoever is viewing the
1539 + * blog at the time -- usually meaning no user at all. But if WordPress
1540 + * gets a wp_insert_post() when current_user_can('unfiltered_html') is
1541 + * false, it will run the content of the post through a kses function
1542 + * that strips out lots of HTML tags -- notably <object> and some others.
1543 + * This causes problems for syndicating (for example) feeds that contain
1544 + * YouTube videos. It also produces an unexpected asymmetry between
1545 + * automatically-initiated updates and updates initiated manually from
1546 + * the WordPress Dashboard (which are usually initiated under the
1547 + * credentials of a logged-in admin, and so don't get run through the
1548 + * kses function). So, to avoid the whole mess, what we do here is
1549 + * just forcibly disable the kses munging for a single syndicated post,
1550 + * by restoring the contents of the `post_content` field.
1551 + *
1552 + * @param string $content The content of the post, after other filters have gotten to it
1553 + * @return string The original content of the post, before other filters had a chance to munge it.
1554 + */
1555 + function avoid_kses_munge ($content) {
1556 + global $wpdb;
1557 + return $wpdb->escape($this->post['post_content']);
1558 + }
1559 +
2280 1560 // SyndicatedPost::add_rss_meta: adds interesting meta-data to each entry
2281 1561 // using the space for custom keys. The set of keys and values to add is
2282 1562 // specified by the keys and values of $post['meta']. This is used to
2283 1563 // store anything that the WordPress user might want to access from a
@@ -2329,9 +1609,9 @@
2329 1609
2330 1610 // SyndicatedPost::author_id (): get the ID for an author name from
2331 1611 // the feed. Create the author if necessary.
2332 1612 function author_id ($unfamiliar_author = 'create') {
2333 - global $wpdb, $wp_db_version; // test for WordPress 2.0 database schema
1613 + global $wpdb;
2334 1614
2335 1615 $a = $this->author();
2336 1616 $author = $a['name'];
2337 1617 $email = $a['email'];
@@ -2336,8 +1616,15 @@
2336 1616 $author = $a['name'];
2337 1617 $email = $a['email'];
2338 1618 $url = $a['uri'];
2339 1619
1620 + $match_author_by_email = !('yes' == get_option("feedwordpress_do_not_match_author_by_email"));
1621 + if ($match_author_by_email and !FeedWordPress::is_null_email($email)) :
1622 + $test_email = $email;
1623 + else :
1624 + $test_email = NULL;
1625 + endif;
1626 +
2340 1627 // Never can be too careful...
2341 1628 $login = sanitize_user($author, /*strict=*/ true);
2342 1629 $login = apply_filters('pre_user_login', $login);
2343 1630
@@ -2346,88 +1633,93 @@
2346 1633
2347 1634 $reg_author = $wpdb->escape(preg_quote($author));
2348 1635 $author = $wpdb->escape($author);
2349 1636 $email = $wpdb->escape($email);
1637 + $test_email = $wpdb->escape($test_email);
2350 1638 $url = $wpdb->escape($url);
2351 1639
2352 - // Look for an existing author record that fits...
2353 - if (!isset($wp_db_version)) :
2354 - #-- WordPress 1.5.x
2355 - $id = $wpdb->get_var(
2356 - "SELECT ID from $wpdb->users
2357 - WHERE
2358 - TRIM(LCASE(user_login)) = TRIM(LCASE('$login')) OR
2359 - (
2360 - LENGTH(TRIM(LCASE(user_email))) > 0
2361 - AND TRIM(LCASE(user_email)) = TRIM(LCASE('$email'))
2362 - ) OR
2363 - TRIM(LCASE(user_firstname)) = TRIM(LCASE('$author')) OR
2364 - TRIM(LCASE(user_nickname)) = TRIM(LCASE('$author')) OR
2365 - TRIM(LCASE(user_nicename)) = TRIM(LCASE('$nice_author')) OR
2366 - TRIM(LCASE(user_description)) = TRIM(LCASE('$author')) OR
2367 - (
2368 - LOWER(user_description)
2369 - RLIKE CONCAT(
2370 - '(^|\\n)a\\.?k\\.?a\\.?( |\\t)*:?( |\\t)*',
2371 - LCASE('$reg_author'),
2372 - '( |\\t|\\r)*(\\n|\$)'
2373 - )
2374 - )
2375 - ");
2376 - elseif ($wp_db_version >= 2966) :
1640 + // Check for an existing author rule....
1641 + if (isset($this->link->settings['map authors']['name'][strtolower(trim($author))])) :
1642 + $author_rule = $this->link->settings['map authors']['name'][strtolower(trim($author))];
1643 + else :
1644 + $author_rule = NULL;
1645 + endif;
1646 +
1647 + // User name is mapped to a particular author. If that author ID exists, use it.
1648 + if (is_numeric($author_rule) and get_userdata((int) $author_rule)) :
1649 + $id = (int) $author_rule;
1650 +
1651 + // User name is filtered out
1652 + elseif ('filter' == $author_rule) :
1653 + $id = NULL;
1654 +
1655 + else :
1656 + // Check the database for an existing author record that might fit
1657 +
2377 1658 #-- WordPress 2.0+
2378 -
2379 - # First try the user core data table.
2380 - $id = $wpdb->get_var(
2381 - "SELECT ID FROM $wpdb->users
2382 - WHERE
2383 - TRIM(LCASE(user_login)) = TRIM(LCASE('$login'))
2384 - OR (
2385 - LENGTH(TRIM(LCASE(user_email))) > 0
2386 - AND TRIM(LCASE(user_email)) = TRIM(LCASE('$email'))
2387 - )
2388 - OR TRIM(LCASE(user_nicename)) = TRIM(LCASE('$nice_author'))
2389 - ");
1659 + if (fwp_test_wp_version(FWP_SCHEMA_HAS_USERMETA)) :
2390 1660
2391 - if (is_null($id)) : # Then look for aliases in the user meta data table
1661 + // First try the user core data table.
2392 1662 $id = $wpdb->get_var(
2393 - "SELECT user_id FROM $wpdb->usermeta
1663 + "SELECT ID FROM $wpdb->users
2394 1664 WHERE
2395 - (meta_key = 'description' AND TRIM(LCASE(meta_value)) = TRIM(LCASE('$author')))
1665 + TRIM(LCASE(user_login)) = TRIM(LCASE('$login'))
2396 1666 OR (
2397 - meta_key = 'description'
2398 - AND TRIM(LCASE(meta_value))
1667 + LENGTH(TRIM(LCASE(user_email))) > 0
1668 + AND TRIM(LCASE(user_email)) = TRIM(LCASE('$test_email'))
1669 + )
1670 + OR TRIM(LCASE(user_nicename)) = TRIM(LCASE('$nice_author'))
1671 + ");
1672 +
1673 + // If that fails, look for aliases in the user meta data table
1674 + if (is_null($id)) :
1675 + $id = $wpdb->get_var(
1676 + "SELECT user_id FROM $wpdb->usermeta
1677 + WHERE
1678 + (meta_key = 'description' AND TRIM(LCASE(meta_value)) = TRIM(LCASE('$author')))
1679 + OR (
1680 + meta_key = 'description'
1681 + AND TRIM(LCASE(meta_value))
1682 + RLIKE CONCAT(
1683 + '(^|\\n)a\\.?k\\.?a\\.?( |\\t)*:?( |\\t)*',
1684 + TRIM(LCASE('$reg_author')),
1685 + '( |\\t|\\r)*(\\n|\$)'
1686 + )
1687 + )
1688 + ");
1689 + endif;
1690 +
1691 + #-- WordPress 1.5.x
1692 + else :
1693 + $id = $wpdb->get_var(
1694 + "SELECT ID from $wpdb->users
1695 + WHERE
1696 + TRIM(LCASE(user_login)) = TRIM(LCASE('$login')) OR
1697 + (
1698 + LENGTH(TRIM(LCASE(user_email))) > 0
1699 + AND TRIM(LCASE(user_email)) = TRIM(LCASE('$test_email'))
1700 + ) OR
1701 + TRIM(LCASE(user_firstname)) = TRIM(LCASE('$author')) OR
1702 + TRIM(LCASE(user_nickname)) = TRIM(LCASE('$author')) OR
1703 + TRIM(LCASE(user_nicename)) = TRIM(LCASE('$nice_author')) OR
1704 + TRIM(LCASE(user_description)) = TRIM(LCASE('$author')) OR
1705 + (
1706 + LOWER(user_description)
2399 1707 RLIKE CONCAT(
2400 1708 '(^|\\n)a\\.?k\\.?a\\.?( |\\t)*:?( |\\t)*',
2401 - TRIM(LCASE('$reg_author')),
1709 + LCASE('$reg_author'),
2402 1710 '( |\\t|\\r)*(\\n|\$)'
2403 1711 )
2404 1712 )
2405 1713 ");
1714 +
2406 1715 endif;
2407 - endif;
2408 1716
2409 - // ... if you don't find one, then do what you need to do
2410 - if (is_null($id)) :
2411 - if ($unfamiliar_author === 'create') :
2412 - if (!isset($wp_db_version)) :
2413 - #-- WordPress 1.5.x
2414 - $wpdb->query (
2415 - "INSERT INTO $wpdb->users
2416 - SET
2417 - ID='0',
2418 - user_login='$login',
2419 - user_firstname='$author',
2420 - user_nickname='$author',
2421 - user_nicename='$nice_author',
2422 - user_description='$author',
2423 - user_email='$email',
2424 - user_url='$url'");
2425 - $id = $wpdb->insert_id;
2426 - elseif ($wp_db_version >= 2966) :
2427 - #-- WordPress 2.0+
1717 + // ... if you don't find one, then do what you need to do
1718 + if (is_null($id)) :
1719 + if ($unfamiliar_author === 'create') :
2428 1720 $userdata = array();
2429 -
1721 +
2430 1722 #-- user table data
2431 1723 $userdata['ID'] = NULL; // new user
2432 1724 $userdata['user_login'] = $login;
2433 1725 $userdata['user_nicename'] = $nice_author;
@@ -2434,20 +1726,26 @@
2434 1726 $userdata['user_pass'] = substr(md5(uniqid(microtime())), 0, 6); // just something random to lock it up
2435 1727 $userdata['user_email'] = $email;
2436 1728 $userdata['user_url'] = $url;
2437 1729 $userdata['display_name'] = $author;
2438 -
1730 +
2439 1731 $id = wp_insert_user($userdata);
1732 + elseif (is_numeric($unfamiliar_author) and get_userdata((int) $unfamiliar_author)) :
1733 + $id = (int) $unfamiliar_author;
1734 + elseif ($unfamiliar_author === 'default') :
1735 + $id = 1;
2440 1736 endif;
2441 - elseif ($unfamiliar_author === 'default') :
2442 - $id = 1;
2443 1737 endif;
2444 1738 endif;
1739 +
1740 + if ($id) :
1741 + $this->link->settings['map authors']['name'][strtolower(trim($author))] = $id;
1742 + endif;
2445 1743 return $id;
2446 1744 } // function SyndicatedPost::author_id ()
2447 1745
2448 1746 // look up (and create) category ids from a list of categories
2449 - function category_ids ($cats, $unfamiliar_category = 'create') {
1747 + function category_ids ($cats, $unfamiliar_category = 'create', $tags_too = false) {
2450 1748 global $wpdb;
2451 1749
2452 1750 // We need to normalize whitespace because (1) trailing
2453 1751 // whitespace can cause PHP and MySQL not to see eye to eye on
@@ -2456,8 +1754,10 @@
2456 1754 // because I doubt most people want to make a semantic
2457 1755 // distinction between 'Computers' and 'Computers '
2458 1756 $cats = array_map('trim', $cats);
2459 1757
1758 + $tags = array();
1759 +
2460 1760 $cat_ids = array ();
2461 1761 foreach ($cats as $cat_name) :
2462 1762 if (preg_match('/^{#([0-9]+)}$/', $cat_name, $backref)) :
2463 1763 $cat_id = (int) $backref[1];
@@ -2465,9 +1765,9 @@
2465 1765 $cat_ids[] = $cat_id;
2466 1766 elseif (get_category($cat_id)) :
2467 1767 $cat_ids[] = $cat_id;
2468 1768 endif;
2469 - else :
1769 + elseif (strlen($cat_name) > 0) :
2470 1770 $esc = $wpdb->escape($cat_name);
2471 1771 $resc = $wpdb->escape(preg_quote($cat_name));
2472 1772
2473 1773 // WordPress 2.3+
@@ -2485,11 +1785,17 @@
2485 1785 )) :
2486 1786 foreach ($results AS $term) :
2487 1787 $cat_ids[] = (int) $term->term_id;
2488 1788 endforeach;
1789 + elseif ('tag'==$unfamiliar_category) :
1790 + $tags[] = $cat_name;
2489 1791 elseif ('create'===$unfamiliar_category) :
2490 1792 $term = wp_insert_term($cat_name, 'category');
2491 - $cat_ids[] = $term['term_id'];
1793 + if (is_wp_error($term)) :
1794 + FeedWordPress::noncritical_bug('term insertion problem', array('cat_name' => $cat_name, 'term' => $term, 'this' => $this), __LINE__);
1795 + else :
1796 + $cat_ids[] = $term['term_id'];
1797 + endif;
2492 1798 endif;
2493 1799
2494 1800 // WordPress 1.5.x - 2.2.x
2495 1801 else :
@@ -2530,18 +1836,28 @@
2530 1836 $cat_ids = NULL; // Drop the post
2531 1837 else :
2532 1838 $cat_ids = array_unique($cat_ids);
2533 1839 endif;
2534 - return $cat_ids;
1840 +
1841 + if ($tags_too) : $ret = array($cat_ids, $tags);
1842 + else : $ret = $cat_ids;
1843 + endif;
1844 +
1845 + return $ret;
2535 1846 } // function SyndicatedPost::category_ids ()
2536 1847
2537 1848 function use_api ($tag) {
2538 1849 global $wp_db_version;
2539 - if ('wp_insert_post'==$tag) :
1850 + switch ($tag) :
1851 + case 'wp_insert_post':
2540 1852 // Before 2.2, wp_insert_post does too much of the wrong stuff to use it
2541 1853 // In 1.5 it was such a resource hog it would make PHP segfault on big updates
2542 1854 $ret = (isset($wp_db_version) and $wp_db_version > FWP_SCHEMA_21);
2543 - endif;
1855 + break;
1856 + case 'post_status_pending':
1857 + $ret = (isset($wp_db_version) and $wp_db_version > FWP_SCHEMA_23);
1858 + break;
1859 + endswitch;
2544 1860 return $ret;
2545 1861 } // function SyndicatedPost::use_api ()
2546 1862
2547 1863 #### EXTRACT DATA FROM FEED ITEM ####
@@ -2579,14 +1895,18 @@
2579 1895 endif;
2580 1896
2581 1897 # If everything failed, then default to the current time.
2582 1898 if (is_null($epoch)) :
2583 - $epoch = time();
1899 + if (-1 == $default) :
1900 + $epoch = time();
1901 + else :
1902 + $epoch = $default;
1903 + endif;
2584 1904 endif;
2585 1905
2586 1906 return $epoch;
2587 1907 }
2588 - function updated ($fallback = true) {
1908 + function updated ($fallback = true, $default = -1) {
2589 1909 $epoch = null;
2590 1910
2591 1911 # As far as I know, only dcterms and Atom have reliable ways to
2592 1912 # specify when something was *modified* last. If neither is
@@ -2599,19 +1919,27 @@
2599 1919 $epoch = @parse_w3cdtf($this->item['modified']);
2600 1920 elseif (isset($this->item['updated'])): // Atom 1.0
2601 1921 $epoch = @parse_w3cdtf($this->item['updated']);
2602 1922 elseif ($fallback) : // Fall back to issued / dc:date
2603 - $epoch = $this->published(/*fallback=*/ false);
1923 + $epoch = $this->published(/*fallback=*/ false, /*default=*/ $default);
2604 1924 endif;
2605 1925
2606 1926 # If everything failed, then default to the current time.
2607 1927 if (is_null($epoch)) :
2608 - $epoch = time();
1928 + if (-1 == $default) :
1929 + $epoch = time();
1930 + else :
1931 + $epoch = $default;
1932 + endif;
2609 1933 endif;
2610 1934
2611 1935 return $epoch;
2612 1936 }
2613 1937
1938 + function update_hash () {
1939 + return md5(serialize($this->item));
1940 + }
1941 +
2614 1942 function guid () {
2615 1943 $guid = null;
2616 1944 if (isset($this->item['id'])): // Atom 0.3 / 1.0
2617 1945 $guid = $this->item['id'];
@@ -2698,8 +2026,31 @@
2698 2026 endif;
2699 2027
2700 2028 return $author;
2701 2029 } // SyndicatedPost::author()
2030 +
2031 + var $strip_attrs = array (
2032 + array('[a-z]+', 'style'),
2033 + array('[a-z]+', 'target'),
2034 + );
2035 + function sanitize_content ($content, $obj) {
2036 + # FeedWordPress used to resolve URIs relative to the
2037 + # feed URI. It now relies on the xml:base support
2038 + # baked in to the MagpieRSS upgrade. So all we do here
2039 + # now is to sanitize problematic attributes.
2040 + #
2041 + # This kind of sucks. I intend to replace it with
2042 + # lib_filter sometime soon.
2043 + foreach ($obj->strip_attrs as $pair):
2044 + list($tag,$attr) = $pair;
2045 + $content = preg_replace (
2046 + ":(<$tag [^>]*)($attr=(\"[^\">]*\"|[^>\\s]+))([^>]*>):i",
2047 + "\\1\\4",
2048 + $content
2049 + );
2050 + endforeach;
2051 + return $content;
2052 + }
2702 2053 } // class SyndicatedPost
2703 2054
2704 2055 # class SyndicatedLink: represents a syndication feed stored within the
2705 2056 # WordPress database
@@ -2777,18 +2128,26 @@
2777 2128 $this->settings['link/uri'] = $this->link->link_rss;
2778 2129 $this->settings['link/name'] = $this->link->link_name;
2779 2130 $this->settings['link/id'] = $this->link->link_id;
2780 2131
2781 - // `hardcode categories` is deprecated in favor of `unfamiliar categories`
2132 + // `hardcode categories` and `unfamiliar categories` are deprecated in favor of `unfamiliar category`
2782 2133 if (
2134 + isset($this->settings['unfamiliar categories'])
2135 + and !isset($this->settings['unfamiliar category'])
2136 + ) :
2137 + $this->settings['unfamiliar category'] = $this->settings['unfamiliar categories'];
2138 + endif;
2139 + if (
2783 2140 FeedWordPress::affirmative($this->settings, 'hardcode categories')
2784 - and !isset($this->settings['unfamiliar categories'])
2141 + and !isset($this->settings['unfamiliar category'])
2785 2142 ) :
2786 - $this->settings['unfamiliar categories'] = 'default';
2143 + $this->settings['unfamiliar category'] = 'default';
2787 2144 endif;
2788 -
2145 +
2789 2146 // Set this up automagically for del.icio.us
2790 - if (!isset($this->settings['cat_split']) and false !== strpos($this->link->link_rss, 'del.icio.us')) :
2147 + $bits = parse_url($this->link->link_rss);
2148 + $tagspacers = array('del.icio.us', 'feeds.delicious.com');
2149 + if (!isset($this->settings['cat_split']) and in_array($bits['host'], $tagspacers)) :
2791 2150 $this->settings['cat_split'] = '\s'; // Whitespace separates multiple tags in del.icio.us RSS feeds
2792 2151 endif;
2793 2152
2794 2153 if (isset($this->settings['cats'])):
@@ -2793,14 +2152,33 @@
2793 2152
2794 2153 if (isset($this->settings['cats'])):
2795 2154 $this->settings['cats'] = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, $this->settings['cats']);
2796 2155 endif;
2156 + if (isset($this->settings['tags'])):
2157 + $this->settings['tags'] = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, $this->settings['tags']);
2158 + endif;
2159 +
2160 + if (isset($this->settings['map authors'])) :
2161 + $author_rules = explode("\n\n", $this->settings['map authors']);
2162 + $ma = array();
2163 + foreach ($author_rules as $rule) :
2164 + list($rule_type, $author_name, $author_action) = explode("\n", $rule);
2165 +
2166 + // Normalize for case and whitespace
2167 + $rule_type = strtolower(trim($rule_type));
2168 + $author_name = strtolower(trim($author_name));
2169 + $author_action = strtolower(trim($author_action));
2170 +
2171 + $ma[$rule_type][$author_name] = $author_action;
2172 + endforeach;
2173 + $this->settings['map authors'] = $ma;
2174 + endif;
2797 2175 endif;
2798 - } // SyndicatedLink::SyndicatedLink ()
2176 + } /* SyndicatedLink::SyndicatedLink () */
2799 2177
2800 2178 function found () {
2801 2179 return is_object($this->link);
2802 - }
2180 + } /* SyndicatedLink::found () */
2803 2181
2804 2182 function stale () {
2805 2183 $stale = true;
2806 2184 if (isset($this->settings['update/hold']) and ($this->settings['update/hold']=='ping')) :
@@ -2814,16 +2192,25 @@
2814 2192 +((int) $this->settings['update/ttl'] * 60);
2815 2193 $stale = (time() >= $after);
2816 2194 endif;
2817 2195 return $stale;
2818 - }
2196 + } /* SyndicatedLink::stale () */
2819 2197
2820 - function poll () {
2198 + function poll ($crash_ts = NULL) {
2821 2199 global $wpdb;
2822 2200
2823 2201 $this->magpie = fetch_rss($this->link->link_rss);
2824 2202 $new_count = NULL;
2825 2203
2204 + $resume = FeedWordPress::affirmative($this->settings, 'update/unfinished');
2205 + if ($resume) :
2206 + // pick up where we left off
2207 + $processed = array_map('trim', explode("\n", $this->settings['update/processed']));
2208 + else :
2209 + // begin at the beginning
2210 + $processed = array();
2211 + endif;
2212 +
2826 2213 if (is_object($this->magpie)) :
2827 2214 $new_count = array('new' => 0, 'updated' => 0);
2828 2215
2829 2216 # -- Update Link metadata live from feed
@@ -2859,29 +2246,17 @@
2859 2246 else :
2860 2247 $this->settings['update/ttl'] = rand(30, 120); // spread over time interval for staggered updates
2861 2248 $this->settings['update/timed'] = 'automatically';
2862 2249 endif;
2863 -
2250 +
2864 2251 if (!isset($this->settings['update/hold']) or $this->settings['update/hold']!='ping') :
2865 2252 $this->settings['update/hold'] = 'scheduled';
2866 2253 endif;
2867 -
2868 - // Copy back without a few things that we don't want to save in the notes
2869 - $to_notes = $this->settings;
2870 2254
2871 - if (is_array($to_notes['cats'])) :
2872 - $to_notes['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['cats']);
2873 - endif;
2874 - unset($to_notes['link/id']); unset($to_notes['link/uri']);
2875 - unset($to_notes['link/name']);
2876 - unset($to_notes['hardcode categories']); // Deprecated
2877 -
2878 - $notes = '';
2879 - foreach ($to_notes as $key => $value) :
2880 - $notes .= $key . ": ". addcslashes($value, "\0..\37".'\\') . "\n";
2881 - endforeach;
2882 - $update[] = "link_notes = '".$wpdb->escape($notes)."'";
2883 -
2255 + $this->settings['update/unfinished'] = 'yes';
2256 +
2257 + $update[] = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
2258 +
2884 2259 $update_set = implode(',', $update);
2885 2260
2886 2261 // Update the properties of the link from the feed information
2887 2262 $result = $wpdb->query("
@@ -2890,27 +2265,125 @@
2890 2265 WHERE link_id='$this->id'
2891 2266 ");
2892 2267
2893 2268 # -- Add new posts from feed and update any updated posts
2269 + $crashed = false;
2270 +
2894 2271 if (is_array($this->magpie->items)) :
2895 2272 foreach ($this->magpie->items as $item) :
2896 2273 $post =& new SyndicatedPost($item, $this);
2897 - if (!$post->filtered()) :
2898 - $new = $post->store();
2899 - if ( $new !== false ) $new_count[$new]++;
2274 + if (!$resume or !in_array(trim($post->guid()), $processed)) :
2275 + $processed[] = $post->guid();
2276 + if (!$post->filtered()) :
2277 + $new = $post->store();
2278 + if ( $new !== false ) $new_count[$new]++;
2279 + endif;
2280 +
2281 + if (!is_null($crash_ts) and (time() > $crash_ts)) :
2282 + $crashed = true;
2283 + break;
2284 + endif;
2900 2285 endif;
2901 2286 endforeach;
2902 2287 endif;
2288 +
2289 + // Copy back any changes to feed settings made in the course of updating (e.g. new author rules)
2290 + $to_notes = $this->settings;
2291 +
2292 + $this->settings['update/processed'] = $processed;
2293 + if (!$crashed) :
2294 + $this->settings['update/unfinished'] = 'no';
2295 + endif;
2296 +
2297 + $update_set = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
2298 +
2299 + // Update the properties of the link from the feed information
2300 + $result = $wpdb->query("
2301 + UPDATE $wpdb->links
2302 + SET $update_set
2303 + WHERE link_id='$this->id'
2304 + ");
2903 2305 endif;
2306 +
2904 2307 return $new_count;
2905 2308 } /* SyndicatedLink::poll() */
2906 -
2309 +
2310 + function map_name_to_new_user ($name, $newuser_name) {
2311 + global $wpdb;
2312 +
2313 + if (strlen($newuser_name) > 0) :
2314 + $userdata = array();
2315 + $userdata['ID'] = NULL;
2316 +
2317 + $userdata['user_login'] = sanitize_user($newuser_name);
2318 + $userdata['user_login'] = apply_filters('pre_user_login', $userdata['user_login']);
2319 +
2320 + $userdata['user_nicename'] = sanitize_title($newuser_name);
2321 + $userdata['user_nicename'] = apply_filters('pre_user_nicename', $userdata['user_nicename']);
2322 +
2323 + $userdata['display_name'] = $wpdb->escape($newuser_name);
2324 +
2325 + $newuser_id = wp_insert_user($userdata);
2326 + if (is_numeric($newuser_id)) :
2327 + if (is_null($name)) : // Unfamiliar author
2328 + $this->settings['unfamiliar author'] = $newuser_id;
2329 + else :
2330 + $this->settings['map authors']['name'][$name] = $newuser_id;
2331 + endif;
2332 + else :
2333 + // TODO: Add some error detection and reporting
2334 + endif;
2335 + else :
2336 + // TODO: Add some error reporting
2337 + endif;
2338 + } /* SyndicatedLink::map_name_to_new_user () */
2339 +
2340 + function settings_to_notes () {
2341 + $to_notes = $this->settings;
2342 +
2343 + unset($to_notes['link/id']); // Magic setting; don't save
2344 + unset($to_notes['link/uri']); // Magic setting; don't save
2345 + unset($to_notes['link/name']); // Magic setting; don't save
2346 + unset($to_notes['hardcode categories']); // Deprecated
2347 + unset($to_notes['unfamiliar categories']); // Deprecated
2348 +
2349 + // Collapse array settings
2350 + if (isset($to_notes['update/processed']) and (is_array($to_notes['update/processed']))) :
2351 + $to_notes['update/processed'] = implode("\n", $to_notes['update/processed']);
2352 + endif;
2353 +
2354 + if (is_array($to_notes['cats'])) :
2355 + $to_notes['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['cats']);
2356 + endif;
2357 + if (is_array($to_notes['tags'])) :
2358 + $to_notes['tags'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['tags']);
2359 + endif;
2360 +
2361 + // Collapse the author mapping rule structure back into a flat string
2362 + if (isset($to_notes['map authors'])) :
2363 + $ma = array();
2364 + foreach ($to_notes['map authors'] as $rule_type => $author_rules) :
2365 + foreach ($author_rules as $author_name => $author_action) :
2366 + $ma[] = $rule_type."\n".$author_name."\n".$author_action;
2367 + endforeach;
2368 + endforeach;
2369 + $to_notes['map authors'] = implode("\n\n", $ma);
2370 + endif;
2371 +
2372 + $notes = '';
2373 + foreach ($to_notes as $key => $value) :
2374 + $notes .= $key . ": ". addcslashes($value, "\0..\37".'\\') . "\n";
2375 + endforeach;
2376 + return $notes;
2377 + } /* SyndicatedLink::settings_to_notes () */
2378 +
2907 2379 function uri () {
2908 2380 return (is_object($this->link) ? $this->link->link_rss : NULL);
2909 - }
2381 + } /* SyndicatedLink::uri () */
2382 +
2910 2383 function homepage () {
2911 2384 return (isset($this->settings['feed/link']) ? $this->settings['feed/link'] : NULL);
2912 - }
2385 + } /* SyndicatedLink::homepage () */
2913 2386
2914 2387 function ttl () {
2915 2388 if (is_object($this->magpie)) :
2916 2389 $channel = $this->magpie->channel;
@@ -2956,9 +2429,9 @@
2956 2429 endif;
2957 2430 return $ret;
2958 2431 } /* SyndicatedLink::ttl() */
2959 2432
2960 - // SyndicatedLink:flatten_array (): flatten an array. Useful for
2433 + // SyndicatedLink::flatten_array (): flatten an array. Useful for
2961 2434 // hierarchical and namespaced elements.
2962 2435 //
2963 2436 // Given an array which may contain array or object elements in it,
2964 2437 // return a "flattened" array: a one-dimensional array of scalars
@@ -2977,9 +2450,9 @@
2977 2450 endif;
2978 2451 endforeach;
2979 2452 endif;
2980 2453 return $ret;
2981 - } // function SyndicatedLink::flatten_array ()
2454 + } /* SyndicatedLink::flatten_array () */
2982 2455
2983 2456 function hardcode ($what) {
2984 2457 $default = get_option("feedwordpress_hardcode_$what");
2985 2458 if ( $default === 'yes' ) :
@@ -2993,9 +2466,9 @@
2993 2466 // setting is explicitly "yes"
2994 2467 $ret = FeedWordPress::affirmative($this->settings, "hardcode $what");
2995 2468 endif;
2996 2469 return $ret;
2997 - } // function SyndicatedLink::hardcode ()
2470 + } /* SyndicatedLink::hardcode () */
2998 2471
2999 2472 function syndicated_status ($what, $default) {
3000 2473 global $wpdb;
3001 2474
@@ -3005,9 +2478,9 @@
3005 2478 elseif (!$ret) :
3006 2479 $ret = $default;
3007 2480 endif;
3008 2481 return $wpdb->escape(trim(strtolower($ret)));
3009 - } // function SyndicatedLink:syndicated_status ()
2482 + } /* SyndicatedLink:syndicated_status () */
3010 2483 } // class SyndicatedLink
3011 2484
3012 2485 ################################################################################
3013 2486 ## XML-RPC HOOKS: accept XML-RPC update pings from Contributors ################
@@ -3042,8 +2515,9 @@
3042 2515
3043 2516 var $verify = FALSE;
3044 2517
3045 2518 var $_data = NULL;
2519 + var $_error = NULL;
3046 2520 var $_head = NULL;
3047 2521
3048 2522 # -- Recognition patterns
3049 2523 var $_feed_types = array(
@@ -3098,8 +2572,12 @@
3098 2572 $this->_get($uri);
3099 2573 return $this->_data;
3100 2574 }
3101 2575
2576 + function error () {
2577 + return $this->_error;
2578 + }
2579 +
3102 2580 function is_feed ($uri = NULL) {
3103 2581 $data = $this->data($uri);
3104 2582
3105 2583 return (
@@ -3118,23 +2596,23 @@
3118 2596 if ($uri) $this->uri = $uri;
3119 2597
3120 2598 // Is the result not yet cached?
3121 2599 if ($this->_cache_uri !== $this->uri) :
3122 - // Snoopy is an HTTP client in PHP
3123 - $client = new Snoopy();
3124 -
3125 - // Prepare headers and internal settings
3126 - $client->rawheaders['Connection'] = 'close';
3127 - $client->accept = 'application/atom+xml application/rdf+xml application/rss+xml application/xml text/html */*';
3128 - $client->agent = 'feedfinder/1.2 (compatible; PHP FeedFinder) +http://projects.radgeek.com/feedwordpress';
3129 - $client->read_timeout = 25;
3130 -
3131 - // Fetch the HTML or feed
3132 - @$client->fetch($this->uri);
3133 - $this->_data = $client->results;
2600 + $headers['Connection'] = 'close';
2601 + $headers['Accept'] = 'application/atom+xml application/rdf+xml application/rss+xml application/xml text/html */*';
2602 + $headers['User-Agent'] = 'feedfinder/1.2 (compatible; PHP FeedFinder) +http://projects.radgeek.com/feedwordpress';
3134 2603
3135 - // Kilroy was here
3136 - $this->_cache_uri = $this->uri;
2604 + // Use function provided by MagpieRSS package
2605 + $client = _fetch_remote_file($this->uri, $headers);
2606 + if (isset($client->error)) :
2607 + $this->_error = $client->error;
2608 + else :
2609 + $this->_error = NULL;
2610 + endif;
2611 + $this->_data = $client->results;
2612 +
2613 + // Kilroy was here
2614 + $this->_cache_uri = $this->uri;
3137 2615 endif;
3138 2616 } /* FeedFinder::_get () */
3139 2617
3140 2618 function _link_rel_feeds () {
@@ -3395,5 +2873,5 @@
3395 2873 $ret['name'] = NULL; $ret['email'] = NULL;
3396 2874 endif;
3397 2875 return $ret;
3398 2876 }
3399 -?>
2877 +