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 +666 -1494 0.9922008.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.992
6 +Version: 2008.1214
7 7 Author: Charles Johnson
8 8 Author URI: http://radgeek.com/
9 9 License: GPL
10 -Last modified: 2008-01-04 18:03 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.992');
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,8 +149,10 @@
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);
115 157
116 158 # WTF? By default, wp_insert_link runs incoming link_url and link_rss
@@ -147,8 +189,12 @@
147 189 endif;
148 190
149 191 # Cron-less auto-update. Hooray!
150 192 add_action('init', 'feedwordpress_auto_update');
193 +
194 + # Default sanitizers
195 + add_filter('syndicated_item_content', array('SyndicatedPost', 'sanitize_content'), 0, 2);
196 +
151 197 else :
152 198 # Hook in the menus, which will just point to the upgrade interface
153 199 add_action('admin_menu', 'fwp_add_pages');
154 200 endif; // if (!FeedWordPress::needs_upgrade())
@@ -201,84 +247,85 @@
201 247 : implode(' and ', $mesg)));
202 248 }
203 249
204 250 ################################################################################
205 -## LEGACY API: Replicate or mock up functions for legacy support purposes ######
251 +## TEMPLATE API: functions to make your templates syndication-aware ############
206 252 ################################################################################
207 253
208 -if (!function_exists('get_option')) {
209 - function get_option ($option) {
210 - return get_settings($option);
211 - }
212 -}
213 -if (!function_exists('current_user_can')) {
214 - $legacy_capability_hack = true;
215 - function current_user_can ($task) {
216 - global $user_level;
254 +function is_syndicated () { return (strlen(get_syndication_feed_id()) > 0); }
217 255
218 - $can = false;
256 +function get_syndication_source_link ($original = NULL) {
257 + if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
258 + endif;
219 259
220 - // This is **not** a full replacement for current_user_can. It
221 - // is only for checking the capabilities we care about via the
222 - // WordPress 1.5 user levels.
223 - switch ($task) {
224 - case 'manage_options':
225 - $can = ($user_level >= 6);
226 - break;
227 - case 'manage_links':
228 - $can = ($user_level >= 5);
229 - break;
230 - } /* switch */
231 - return $can;
232 - }
233 -} else {
234 - $legacy_capability_hack = false;
235 -}
236 -if (!function_exists('sanitize_user')) {
237 - function sanitize_user ($text, $strict) {
238 - return $text; // Don't munge it if it wasn't munged going in...
239 - }
240 -}
241 -if (!function_exists('wp_insert_user')) {
242 - function wp_insert_user ($userdata) {
243 - #-- Help WordPress 1.5.x quack like a duck
244 - $login = $userdata['user_login'];
245 - $author = $userdata['display_name'];
246 - $nice_author = $userdata['user_nicename'];
247 - $email = $userdata['user_email'];
248 - $url = $userdata['user_url'];
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;
249 268
250 - $wpdb->query (
251 - "INSERT INTO $wpdb->users
252 - SET
253 - ID='0',
254 - user_login='$login',
255 - user_firstname='$author',
256 - user_nickname='$author',
257 - user_nicename='$nice_author',
258 - user_description='$author',
259 - user_email='$email',
260 - user_url='$url'");
261 - $id = $wpdb->insert_id;
262 -
263 - return $id;
264 - }
265 -}
266 -################################################################################
267 -## TEMPLATE API: functions to make your templates syndication-aware ############
268 -################################################################################
269 + return $ret;
270 +} /* function get_syndication_source_link() */
269 271
270 -function is_syndicated () { return (strlen(get_syndication_feed_id()) > 0); }
272 +function the_syndication_source_link ($original = NULL) { echo get_syndication_source_link($original); }
271 273
272 -function the_syndication_source_link () { echo get_syndication_source_link(); }
273 -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;
274 277
275 -function get_syndication_source () { list($n) = get_post_custom_values('syndication_source'); return $n; }
276 -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;
277 286
278 -function get_syndication_feed () { list($u) = get_post_custom_values('syndication_feed'); return $u; }
279 -function the_syndication_feed () { echo get_syndication_feed (); }
287 + return $ret;
288 +} /* function get_syndication_source() */
280 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 +
281 328 function get_syndication_feed_id () { list($u) = get_post_custom_values('syndication_feed_id'); return $u; }
282 329 function the_syndication_feed_id () { echo get_syndication_feed_id(); }
283 330
284 331 $feedwordpress_linkcache = array (); // only load links from database once
@@ -316,9 +363,9 @@
316 363
317 364 function feedwordpress_preserve_syndicated_content ($text) {
318 365 global $feedwordpress_the_syndicated_content;
319 366
320 - if ( is_syndicated() ) :
367 + if ( is_syndicated() and get_option('feedwordpress_formatting_filters') != 'yes' ) :
321 368 $feedwordpress_the_syndicated_content = $text;
322 369 else :
323 370 $feedwordpress_the_syndicated_content = NULL;
324 371 endif;
@@ -334,1261 +381,72 @@
334 381
335 382 return $text;
336 383 }
337 384
338 -function syndication_permalink ($permalink = '') {
339 - if (get_option('feedwordpress_munge_permalink') != 'no'):
340 - $uri = get_syndication_permalink();
341 - return ((strlen($uri) > 0) ? $uri : $permalink);
342 - else:
343 - return $permalink;
344 - endif;
345 -} // function syndication_permalink ()
346 -
347 -################################################################################
348 -## UPGRADE INTERFACE: Have users upgrade DB from older versions of FWP #########
349 -################################################################################
350 -
351 -function fwp_upgrade_page () {
352 - if (isset($GLOBALS['fwp_post']['action']) and $GLOBALS['fwp_post']['action']=='Upgrade') :
353 - $ver = get_option('feedwordpress_version');
354 - if (get_option('feedwordpress_version') != FEEDWORDPRESS_VERSION) :
355 - echo "<div class=\"wrap\">\n";
356 - echo "<h2>Upgrading FeedWordPress...</h2>";
357 -
358 - $feedwordpress =& new FeedWordPress;
359 - $feedwordpress->upgrade_database();
360 - echo "<p><strong>Done!</strong> Upgraded database to version ".FEEDWORDPRESS_VERSION.".</p>\n";
361 - echo "<form action=\"\" method=\"get\">\n";
362 - echo "<div class=\"submit\"><input type=\"hidden\" name=\"page\" value=\"".basename(__FILE__)."\" />";
363 - echo "<input type=\"submit\" value=\"Continue &raquo;\" /></form></div>\n";
364 - echo "</div>\n";
365 - return;
366 - else :
367 - echo "<div class=\"updated\"><p>Already at version ".FEEDWORDPRESS_VERSION."!</p></div>";
368 - endif;
369 - endif;
385 +function feedwordpress_item_feed_data () {
386 + // In a post context....
387 + if (is_syndicated()) :
370 388 ?>
371 -<div class="wrap">
372 -<h2>Upgrade FeedWordPress</h2>
373 -
374 -<p>It appears that you have installed FeedWordPress
375 -<?php echo FEEDWORDPRESS_VERSION; ?> as an upgrade to an existing installation of
376 -FeedWordPress. That's no problem, but you will need to take a minute out first
377 -to upgrade your database: some necessary changes in how the software keeps
378 -track of posts and feeds will cause problems such as duplicate posts and broken
379 -templates if we were to continue without the upgrade.</p>
380 -
381 -<p>Note that most of FeedWordPress's functionality is temporarily disabled
382 -until we have successfully completed the upgrade. Everything should begin
383 -working as normal again once the upgrade is complete. There's extraordinarily
384 -little chance of any damage as the result of the upgrade, but if you're paranoid
385 -like me you may want to back up your database before you proceed.</p>
386 -
387 -<p>This may take several minutes for a large installation.</p>
388 -
389 -<form action="" method="post">
390 -<div class="submit"><input type="submit" name="action" value="Upgrade" /></div>
391 -</form>
392 -</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(); ?>" />
393 393 <?php
394 -} // function fwp_upgrade_page ()
395 -
396 -################################################################################
397 -## ADMIN MENU ADD-ONS: implement Dashboard management pages ####################
398 -################################################################################
399 -
400 -function fwp_add_pages () {
401 - global $legacy_capability_hack;
402 -
403 - if ($legacy_capability_hack) :
404 - // old & busted: numeric user levels
405 - $manage_links = 5;
406 - $manage_options = 6;
407 - else :
408 - // new hotness: named capabilities
409 - $manage_links = 'manage_links';
410 - $manage_options = 'manage_options';
411 - endif;
412 -
413 - //add_submenu_page('plugins.php', 'Akismet Configuration', 'Akismet Configuration', 'manage_options', 'syndication-manage-page', 'fwp_syndication_manage_page');
414 - add_menu_page('Syndicated Sites', 'Syndication', $manage_links, 'feedwordpress/'.basename(__FILE__), 'fwp_syndication_manage_page');
415 - add_submenu_page('feedwordpress/'.basename(__FILE__), 'Syndication Options', 'Options', $manage_options, 'feedwordpress/syndication-options.php');
416 - add_options_page('Syndication Options', 'Syndication', $manage_options, 'feedwordpress/syndication-options.php');
417 -} // function fwp_add_pages () */
418 -
419 -function fwp_category_box ($checked, $object) {
420 - global $wp_db_version;
421 -
422 - 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) :
423 396 ?>
424 - <div id="poststuff">
425 -
426 - <div id="moremeta">
427 - <div id="grabit" class="dbx-group">
428 - <fieldset id="categorydiv" class="dbx-box">
429 - <h3 class="dbx-handle"><?php _e('Categories') ?></h3>
430 - <div class="dbx-content">
431 - <p style="font-size:smaller;font-style:bold;margin:0">Place <?php print $object; ?> under...</p>
432 - <p id="jaxcat"></p>
433 - <ul id="categorychecklist"><?php write_nested_categories($checked); ?></ul></div>
434 - </fieldset>
435 - </div>
436 - </div>
437 - </div>
397 + <id><?php print $id; ?></id>
438 398 <?php
439 - else : // WordPress 1.5
440 -?>
441 - <fieldset id="categorydiv" style="width: 20%; margin-right: 2em">
442 - <legend><?php _e('Categories') ?></legend>
443 - <p style="font-size:smaller;font-style:bold;margin:0">Place <?php print $object; ?> under...</p>
444 - <div style="height: 20em"><?php write_nested_categories($checked); ?></div>
445 - </fieldset>
399 + endif;
400 + $updated = get_feed_meta('feed/updated');
401 + if (strlen($updated) > 0) : ?>
402 + <updated><?php print $updated; ?></updated>
446 403 <?php
447 404 endif;
448 -}
449 -
450 -function update_feeds_mention ($feed) {
451 - echo "<li>Updating <cite>".$feed['link/name']."</cite> from &lt;<a href=\""
452 - .$feed['link/uri']."\">".$feed['link/uri']."</a>&gt; ...</li>\n";
453 - flush();
454 -}
455 -
456 -function fwp_syndication_manage_page () {
457 - global $wpdb;
458 -
459 - if (FeedWordPress::needs_upgrade()) :
460 - fwp_upgrade_page();
461 - return;
462 - endif;
463 -
464 405 ?>
465 -<?php $cont = true;
466 -if (isset($_REQUEST['action'])):
467 - if ($_REQUEST['action'] == 'feedfinder') : $cont = fwp_feedfinder_page();
468 - elseif ($_REQUEST['action'] == 'switchfeed') : $cont = fwp_switchfeed_page();
469 - elseif ($_REQUEST['action'] == 'linkedit') : $cont = fwp_linkedit_page();
470 - elseif ($_REQUEST['action'] == 'Unsubscribe from Checked Links' or $_REQUEST['action'] == 'Unsubscribe') : $cont = fwp_multidelete_page();
471 - endif;
472 -endif;
473 -
474 -if ($cont):
475 -?>
406 +</source>
476 407 <?php
477 - $links = FeedWordPress::syndicated_links();
478 -
479 - if (isset($_POST['update']) or isset($_POST['action']) or isset($_POST['update_uri'])) :
480 - $fwp_update_invoke = 'post';
481 - else :
482 - $fwp_update_invoke = 'get';
483 408 endif;
484 -
485 - $update_set = array();
486 - if (isset($_POST['link_ids']) and is_array($_POST['link_ids']) and ($_POST['action']=='Update Checked Links')) :
487 - $targets = $wpdb->get_results("
488 - SELECT * FROM $wpdb->links
489 - WHERE link_id IN (".implode(",",$_POST['link_ids']).")
490 - ");
491 - if (is_array($targets)) :
492 - foreach ($targets as $target) :
493 - $update_set[] = $target->link_rss;
494 - endforeach;
495 - else : // This should never happen
496 - FeedWordPress::critical_bug('fwp_syndication_manage_page::targets', $targets, __LINE__);
497 - endif;
498 - elseif (isset($_POST['update_uri'])) :
499 - $update_set[] = $_POST['update_uri'];
500 - endif;
501 -
502 - if ($fwp_update_invoke != 'get' and count($update_set) > 0) : // Only do things with side-effects for HTTP POST or command line
503 - $feedwordpress =& new FeedWordPress;
504 - add_action('feedwordpress_check_feed', 'update_feeds_mention');
505 -
506 - echo "<div class=\"updated\">\n";
507 - echo "<ul>\n";
508 - $tdelta = NULL;
509 - foreach ($update_set as $uri) :
510 - if ($uri == '*') : $uri = NULL; endif;
511 - $delta = $feedwordpress->update($uri);
512 - if (!is_null($delta)) :
513 - if (is_null($tdelta)) :
514 - $tdelta = $delta;
515 - else :
516 - $tdelta['new'] += $delta['new'];
517 - $tdelta['updated'] += $delta['updated'];
518 - endif;
519 - else :
520 - echo "<li><p><strong>Error:</strong> There was a problem updating <a href=\"$uri\">$uri</a></p></li>\n";
521 - endif;
522 - endforeach;
523 - echo "</ul>\n";
524 -
525 - if (!is_null($tdelta)) :
526 - $mesg = array();
527 - if (isset($delta['new'])) : $mesg[] = ' '.$tdelta['new'].' new posts were syndicated'; endif;
528 - if (isset($delta['updated'])) : $mesg[] = ' '.$tdelta['updated'].' existing posts were updated'; endif;
529 - echo "<p>Update complete.".implode(' and', $mesg)."</p>";
530 - echo "\n"; flush();
531 - endif;
532 - echo "</div> <!-- class=\"updated\" -->\n";
533 - endif;
534 -
535 - ?>
536 - <div class="wrap">
537 - <form action="" method="POST">
538 - <h2>Update feeds now</h2>
539 - <p>Check currently scheduled feeds for new and updated posts.</p>
540 -
541 -<?php if (!get_option('feedwordpress_automatic_updates')) : ?>
542 - <p><strong>Note:</strong> Automatic updates are currently turned
543 - <strong>off</strong>. New posts from your feeds will not be syndicated
544 - until you manually check for them here. You can turn on automatic
545 - updates under <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication
546 - Options</a>.</p>
547 -<?php endif; ?>
548 -
549 -
550 - <div class="submit"><input type="hidden" name="update_uri" value="*" /><input type="submit" name="update" value="Update" /></div>
551 - </form>
552 - </div> <!-- class="wrap" -->
553 -
554 - <form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
555 - <div class="wrap">
556 - <h2>Syndicated Sites</h2>
557 -<?php $alt_row = true;
558 - if ($links): ?>
559 -
560 -<table width="100%" cellpadding="3" cellspacing="3">
561 -<tr>
562 -<th width="20%"><?php _e('Name'); ?></th>
563 -<th width="40%"><?php _e('Feed'); ?></th>
564 -<th colspan="4"><?php _e('Action'); ?></th>
565 -</tr>
566 -
567 -<?php foreach ($links as $link):
568 - $alt_row = !$alt_row; ?>
569 -<tr<?php echo ($alt_row?' class="alternate"':''); ?>>
570 -<td><a href="<?php echo wp_specialchars($link->link_url, 'both'); ?>"><?php echo wp_specialchars($link->link_name, 'both'); ?></a></td>
571 -<?php
572 - if (strlen($link->link_rss) > 0):
573 - $caption='Switch Feed';
574 - $uri_bits = parse_url($link->link_rss);
575 - $uri_bits['host'] = preg_replace('/^www\./i', '', $uri_bits['host']);
576 - $display_uri =
577 - (isset($uri_bits['user'])?$uri_bits['user'].'@':'')
578 - .(isset($uri_bits['host'])?$uri_bits['host']:'')
579 - .(isset($uri_bits['port'])?':'.$uri_bits['port']:'')
580 - .(isset($uri_bits['path'])?$uri_bits['path']:'')
581 - .(isset($uri_bits['query'])?'?'.$uri_bits['query']:'');
582 - if (strlen($display_uri) > 32) : $display_uri = substr($display_uri, 0, 32).'&#8230;'; endif;
583 -?>
584 - <td>
585 - <strong><a href="<?php echo wp_specialchars($link->link_rss, 'both'); ?>"><?php echo wp_specialchars($display_uri, 'both'); ?></a></strong></td>
586 -<?php
587 - else:
588 - $caption='Find Feed';
589 -?>
590 - <td style="background-color:#FFFFD0"><p><strong>no
591 - feed assigned</strong></p></td>
592 -<?php
593 - endif;
594 -?>
595 - <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>
596 - <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>
597 - <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>
598 - <td><input type="checkbox" name="link_ids[]" value="<?php echo $link->link_id; ?>" /></td>
599 -<?php
600 - echo "\n\t</tr>";
601 - endforeach;
602 - else:
603 -?>
604 -
605 -<p>There are no websites currently listed for syndication.</p>
606 -
607 -<?php endif; ?>
608 - </table>
609 -
610 - <br/><hr/>
611 - <div class="submit"><input type="submit" class="delete" name="action" value="Unsubscribe from Checked Links" />
612 - <input type="submit" name="action" value="Update Checked Links" /></div>
613 - </div> <!-- class="wrap" -->
614 - </form>
615 -
616 - <div class="wrap">
617 - <form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
618 - <h2>Add a new syndicated site:</h2>
619 - <div>
620 - <label for="add-uri">Website or newsfeed:</label>
621 - <input type="text" name="lookup" id="add-uri" value="URI" size="64" />
622 - <input type="hidden" name="action" value="feedfinder" />
623 - </div>
624 - <div class="submit"><input type="submit" value="Syndicate &raquo;" /></div>
625 - </form>
626 - </div> <!-- class="wrap" -->
627 -<?php
628 -endif;
629 409 }
630 410
631 -function fwp_feedfinder_page () {
632 - global $wpdb;
633 -
634 - $lookup = (isset($_REQUEST['lookup'])?$_REQUEST['lookup']:NULL);
635 -
636 - if (isset($_REQUEST['link_id']) and ($_REQUEST['link_id']!=0)):
637 - $link_id = $_REQUEST['link_id'];
638 - if (!is_numeric($link_id)) : FeedWordPress::critical_bug('fwp_feedfinder_page::link_id', $link_id, __LINE__); endif;
639 -
640 - $link = $wpdb->get_row("SELECT * FROM $wpdb->links WHERE link_id='".$wpdb->escape($link_id)."'");
641 - if (is_object($link)):
642 - if (is_null($lookup)) $lookup = $link->link_url;
643 - $name = wp_specialchars($link->link_name, 'both');
644 - else:
645 - die (__("Cheatin' uh ?"));
646 - 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);
647 415 else:
648 - $name = "New Syndicated Feed";
649 - $link_id = 0;
416 + return $permalink;
650 417 endif;
651 -?>
652 - <div class="wrap">
653 - <h2>Feed Finder: <?php echo $name; ?></h2>
654 -<?php
655 - $f =& new FeedFinder($lookup);
656 - $feeds = $f->find();
657 - if (count($feeds) > 0):
658 - foreach ($feeds as $key => $f):
659 - $rss = fetch_rss($f);
660 - if ($rss):
661 - $feed_title = isset($rss->channel['title'])?$rss->channel['title']:$rss->channel['link'];
662 - $feed_link = isset($rss->channel['link'])?$rss->channel['link']:'';
663 -?>
664 - <form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
665 - <fieldset style="clear: both">
666 - <legend><?php echo $rss->feed_type; ?> <?php echo $rss->feed_version; ?> feed</legend>
418 +} // function syndication_permalink ()
667 419
668 - <?php if ($link_id===0): ?>
669 - <input type="hidden" name="feed_title" value="<?php echo wp_specialchars($feed_title, 'both'); ?>" />
670 - <input type="hidden" name="feed_link" value="<?php echo wp_specialchars($feed_link, 'both'); ?>" />
671 - <?php endif; ?>
420 +################################################################################
421 +## ADMIN MENU ADD-ONS: register Dashboard management pages #####################
422 +################################################################################
672 423
673 - <input type="hidden" name="link_id" value="<?php echo $link_id; ?>" />
674 - <input type="hidden" name="feed" value="<?php echo wp_specialchars($f, 'both'); ?>" />
675 - <input type="hidden" name="action" value="switchfeed" />
424 +function fwp_add_pages () {
425 + global $fwp_capability;
426 + global $fwp_path;
676 427
677 - <div>
678 - <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">
679 -<?php if (count($rss->items) > 0): ?>
680 - <?php $item = $rss->items[0]; ?>
681 - <h3>Sample Item</h3>
682 - <ul>
683 - <li><strong>Title:</strong> <a href="<?php echo $item['link']; ?>"><?php echo $item['title']; ?></a></li>
684 - <li><strong>Date:</strong> <?php echo isset($item['date_timestamp']) ? date('d-M-y g:i:s a', $item['date_timestamp']) : 'unknown'; ?></li>
685 - </ul>
686 - <div class="entry">
687 - <?php echo (isset($item['content']['encoded'])?$item['content']['encoded']:$item['description']); ?>
688 - </div>
689 -<?php else: ?>
690 - <h3>No Items</h3>
691 - <p>FeedWordPress found no posts on this feed.</p>
692 -<?php endif; ?>
693 - </div>
694 -
695 - <div>
696 - <h3>Feed Information</h3>
697 - <ul>
698 - <li><strong>Website:</strong> <a href="<?php echo $feed_link; ?>"><?php echo is_null($feed_title)?'<em>Unknown</em>':$feed_title; ?></a></li>
699 - <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); ?>">validate</a>)</li>
700 - <li><strong>Encoding:</strong> <?php echo isset($rss->encoding)?wp_specialchars($rss->encoding, 'both'):"<em>Unknown</em>"; ?></li>
701 - <li><strong>Description:</strong> <?php echo isset($rss->channel['description'])?wp_specialchars($rss->channel['description'], 'both'):"<em>Unknown</em>"; ?></li>
702 - </ul>
703 - <div class="submit"><input type="submit" name="Use" value="&laquo; Use this feed" /></div>
704 - <div class="submit"><input type="submit" name="Cancel" value="&laquo; Cancel" /></div>
705 - </div>
706 - </div>
707 - </fieldset>
708 - </form>
709 -<?php endif;
710 - endforeach;
711 - else:
712 - 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';
713 432 endif;
714 -?>
715 - </div>
716 433
717 - <form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
718 - <div class="wrap">
719 - <h2>Use another feed</h2>
720 - <div><label>Feed:</label>
721 - <input type="text" name="lookup" value="URI" />
722 - <input type="hidden" name="link_id" value="<?php echo $link_id; ?>" />
723 - <input type="hidden" name="action" value="feedfinder" /></div>
724 - <div class="submit"><input type="submit" value="Use this feed &raquo;" /></div>
725 - </div>
726 - </form>
727 -<?php
728 - return false; // Don't continue
729 -}
730 -
731 -function fwp_switchfeed_page () {
732 - global $wpdb, $wp_db_version;
733 -
734 - check_admin_referer();
735 - if (!isset($_REQUEST['Cancel'])):
736 - if (!current_user_can('manage_links')):
737 - die (__("Cheatin' uh ?"));
738 - elseif (isset($_REQUEST['link_id']) and ($_REQUEST['link_id']==0)):
739 - $link_id = FeedWordPress::syndicate_link($_REQUEST['feed_title'], $_REQUEST['feed_link'], $_REQUEST['feed']);
740 - if ($link_id): ?>
741 -<div class="updated"><p><a href="<?php echo $_REQUEST['feed_link']; ?>"><?php echo wp_specialchars($_REQUEST['feed_title'], 'both'); ?></a>
742 -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>
743 -<?php else: ?>
744 -<div class="updated"><p>There was a problem adding the newsfeed. [SQL: <?php echo wp_specialchars(mysql_error(), 'both'); ?>]</p></div>
745 -<?php endif;
746 - elseif (isset($_REQUEST['link_id'])):
747 - // Update link_rss
748 - $result = $wpdb->query("
749 - UPDATE $wpdb->links
750 - SET
751 - link_rss = '".$wpdb->escape($_REQUEST['feed'])."'
752 - WHERE link_id = '".$wpdb->escape($_REQUEST['link_id'])."'
753 - ");
754 -
755 - if ($result):
756 - $result = $wpdb->get_row("
757 - SELECT link_name, link_url FROM $wpdb->links
758 - WHERE link_id = '".$wpdb->escape($_REQUEST['link_id'])."'
759 - ");
760 - ?>
761 -<div class="updated"><p>Feed for <a href="<?php echo $result->link_url; ?>"><?php echo wp_specialchars($result->link_name, 'both'); ?></a>
762 -updated to &lt;<a href="<?php echo $_REQUEST['feed']; ?>"><?php echo wp_specialchars($_REQUEST['feed'], 'both'); ?></a>&gt;.</p></div>
763 - <?php else: ?>
764 -<div class="updated"><p>Nothing was changed.</p></div>
765 - <?php endif;
766 - endif;
767 - endif;
768 - return true; // Continue
769 -}
770 -
771 -function fwp_linkedit_page () {
772 - global $wpdb;
773 -
774 - check_admin_referer(); // Make sure we arrived here from the Dashboard
775 -
776 - $special_settings = array ( /* Regular expression syntax is OK here */
777 - 'cats',
778 - 'cat_split',
779 - 'hardcode name',
780 - 'hardcode url',
781 - 'hardcode description',
782 - 'hardcode categories', /* Deprecated */
783 - 'post status',
784 - 'comment status',
785 - 'ping status',
786 - 'unfamiliar author',
787 - 'unfamliar categories',
788 - 'map authors',
789 - 'update/.*',
790 - 'feed/.*',
791 - 'link/.*',
792 - );
793 -
794 - if (!current_user_can('manage_links')) :
795 - die (__("Cheatin' uh ?"));
796 - elseif (isset($_REQUEST['feedfinder'])) :
797 - 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');
798 437 else :
799 - $link_id = (int) $_REQUEST['link_id'];
800 - $link =& new SyndicatedLink($link_id);
801 -
802 - if ($link->found()) :
803 - if (isset($GLOBALS['fwp_post']['save'])) :
804 - $alter = array ();
805 -
806 - $meta = $link->settings;
807 - //if (isset($meta['cats'])):
808 - // $meta['cats'] = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, $meta['cats']);
809 - //endif;
810 -
811 - // custom feed settings first
812 - foreach ($GLOBALS['fwp_post']['notes'] as $mn) :
813 - $mn['key0'] = trim($mn['key0']);
814 - $mn['key1'] = trim($mn['key1']);
815 - if (preg_match("\007^(("
816 - .implode(')|(',$special_settings)
817 - ."))$\007i",
818 - $mn['key1'])) :
819 - $mn['key1'] = 'user/'.$mn['key1'];
820 - endif;
821 -
822 - if (strlen($mn['key0']) > 0) :
823 - unset($meta[$mn['key0']]); // out with the old
824 - endif;
825 -
826 - if (($mn['action']=='update') and (strlen($mn['key1']) > 0)) :
827 - $meta[$mn['key1']] = $mn['value']; // in with the new
828 - endif;
829 - endforeach;
830 -
831 - // now stuff through the web form
832 - // hardcoded feed info
833 - if (isset($GLOBALS['fwp_post']['hardcode_name'])) :
834 - $meta['hardcode name'] = $GLOBALS['fwp_post']['hardcode_name'];
835 - if (FeedWordPress::affirmative($meta, 'hardcode name')) :
836 - $alter[] = "link_name = '".$wpdb->escape($GLOBALS['fwp_post']['name'])."'";
837 - endif;
838 - endif;
839 - if (isset($GLOBALS['fwp_post']['hardcode_description'])) :
840 - $meta['hardcode description'] = $GLOBALS['fwp_post']['hardcode_description'];
841 - if (FeedWordPress::affirmative($meta, 'hardcode description')) :
842 - $alter[] = "link_description = '".$wpdb->escape($GLOBALS['fwp_post']['description'])."'";
843 - endif;
844 - endif;
845 - if (isset($GLOBALS['fwp_post']['hardcode_url'])) :
846 - $meta['hardcode url'] = $GLOBALS['fwp_post']['hardcode_url'];
847 - if (FeedWordPress::affirmative($meta, 'hardcode url')) :
848 - $alter[] = "link_url = '".$wpdb->escape($GLOBALS['fwp_post']['linkurl'])."'";
849 - endif;
850 - endif;
851 -
852 - // Update scheduling
853 - if (isset($GLOBALS['fwp_post']['update_schedule'])) :
854 - $meta['update/hold'] = $GLOBALS['fwp_post']['update_schedule'];
855 - endif;
856 -
857 - // Categories
858 - if (isset($GLOBALS['fwp_post']['post_category'])) :
859 - $meta['cats'] = array();
860 - foreach ($GLOBALS['fwp_post']['post_category'] as $cat_id) :
861 - $meta['cats'][] = '{#'.$cat_id.'}';
862 - endforeach;
863 - else :
864 - unset($meta['cats']);
865 - endif;
866 -
867 - // Post status, comment status, ping status
868 - foreach (array('post', 'comment', 'ping') as $what) :
869 - $sfield = "feed_{$what}_status";
870 - if (isset($GLOBALS['fwp_post'][$sfield])) :
871 - if ($GLOBALS['fwp_post'][$sfield]=='site-default') :
872 - unset($meta["{$what} status"]);
873 - else :
874 - $meta["{$what} status"] = $GLOBALS['fwp_post'][$sfield];
875 - endif;
876 - endif;
877 - endforeach;
878 -
879 - // Unfamiliar author, unfamiliar categories
880 - foreach (array("author", "category") as $what) :
881 - $sfield = "unfamiliar_{$what}";
882 - if (isset($GLOBALS['fwp_post'][$sfield])) :
883 - if ('site-default'==$GLOBALS['fwp_post'][$sfield]) :
884 - unset($meta["unfamiliar {$what}"]);
885 - elseif ('newuser'==$GLOBALS['fwp_post'][$sfield]) :
886 - $newuser_name = trim($GLOBALS['fwp_post']["{$sfield}_newuser"]);
887 - if (strlen($newuser_name) > 0) :
888 - $userdata = array();
889 - $userdata['ID'] = NULL;
890 -
891 - $userdata['user_login'] = sanitize_user($newuser_name);
892 - $userdata['user_login'] = apply_filters('pre_user_login', $userdata['user_login']);
893 -
894 - $userdata['user_nicename'] = sanitize_title($newuser_name);
895 - $userdata['user_nicename'] = apply_filters('pre_user_nicename', $userdata['user_nicename']);
896 -
897 - $userdata['display_name'] = $wpdb->escape($newuser_name);
898 -
899 - $newuser_id = wp_insert_user($userdata);
900 - if (is_numeric($newuser_id)) :
901 - $meta["unfamiliar {$what}"] = $newuser_id;
902 - else :
903 - // TODO: Add some error detection and reporting
904 - endif;
905 - else :
906 - // TODO: Add some error reporting
907 - endif;
908 - else :
909 - $meta["unfamiliar {$what}"] = $GLOBALS['fwp_post'][$sfield];
910 - endif;
911 - endif;
912 - endforeach;
913 -
914 - // Handle author mapping rules
915 - if (isset($GLOBALS['fwp_post']['author_rules_name']) and isset($GLOBALS['fwp_post']['author_rules_action'])) :
916 - unset($meta['map authors']);
917 - foreach ($GLOBALS['fwp_post']['author_rules_name'] as $key => $name) :
918 - // Normalize for case and whitespace
919 - $name = strtolower(trim($name));
920 - $author_action = strtolower(trim($GLOBALS['fwp_post']['author_rules_action'][$key]));
921 -
922 - if (strlen($name) > 0) :
923 - if ('newuser' == $author_action) :
924 - $newuser_name = trim($GLOBALS['fwp_post']['author_rules_newuser'][$key]);
925 - if (strlen($newuser_name) > 0) :
926 - $userdata = array();
927 - $userdata['ID'] = NULL;
928 -
929 - $userdata['user_login'] = sanitize_user($newuser_name);
930 - $userdata['user_login'] = apply_filters('pre_user_login', $userdata['user_login']);
931 -
932 - $userdata['user_nicename'] = sanitize_title($newuser_name);
933 - $userdata['user_nicename'] = apply_filters('pre_user_nicename', $userdata['user_nicename']);
934 -
935 - $userdata['display_name'] = $wpdb->escape($newuser_name);
936 -
937 - $newuser_id = wp_insert_user($userdata);
938 - if (is_numeric($newuser_id)) :
939 - $meta['map authors']['name'][$name] = $newuser_id;
940 - else :
941 - // TODO: Add some error detection and reporting
942 - endif;
943 - else :
944 - // TODO: Add some error reporting
945 - endif;
946 - else :
947 - $meta['map authors']['name'][$name] = $author_action;
948 - endif;
949 - endif;
950 - endforeach;
951 - endif;
952 -
953 - if (isset($GLOBALS['fwp_post']['add_author_rule_name']) and isset($GLOBALS['fwp_post']['add_author_rule_action'])) :
954 - $name = strtolower(trim($GLOBALS['fwp_post']['add_author_rule_name']));
955 - $author_action = strtolower(trim($GLOBALS['fwp_post']['add_author_rule_action']));
956 - if (strlen($name) > 0) :
957 - if ('newuser' == $author_action) :
958 - $newuser_name = trim($GLOBALS['fwp_post']['add_author_rule_newuser']);
959 - if (strlen($newuser_name) > 0) :
960 - $userdata = array();
961 - $userdata['ID'] = NULL;
962 -
963 - $userdata['user_login'] = sanitize_user($newuser_name);
964 - $userdata['user_login'] = apply_filters('pre_user_login', $userdata['user_login']);
965 -
966 - $userdata['user_nicename'] = sanitize_title($newuser_name);
967 - $userdata['user_nicename'] = apply_filters('pre_user_nicename', $userdata['user_nicename']);
968 -
969 - $userdata['display_name'] = $wpdb->escape($newuser_name);
970 -
971 - $newuser_id = wp_insert_user($userdata);
972 - if (is_numeric($newuser_id)) :
973 - $meta['map authors']['name'][$name] = $newuser_id;
974 - else :
975 - // TODO: Add some error detection and reporting
976 - endif;
977 - else :
978 - // TODO: Add some error reporting
979 - endif;
980 - else :
981 - $meta['map authors']['name'][$name] = $author_action;
982 - endif;
983 - endif;
984 - endif;
985 -
986 - if (isset($GLOBALS['fwp_post']['cat_split'])) :
987 - if (strlen(trim($GLOBALS['fwp_post']['cat_split'])) > 0) :
988 - $meta['cat_split'] = trim($GLOBALS['fwp_post']['cat_split']);
989 - else :
990 - unset($meta['cat_split']);
991 - endif;
992 - endif;
993 -
994 - if (is_array($meta['cats'])) :
995 - $meta['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $meta['cats']);
996 - endif;
997 -
998 - // Collapse the author mapping rule structure back into a flat string
999 - if (isset($meta['map authors'])) :
1000 - $ma = array();
1001 - foreach ($meta['map authors'] as $rule_type => $author_rules) :
1002 - foreach ($author_rules as $author_name => $author_action) :
1003 - $ma[] = $rule_type."\n".$author_name."\n".$author_action;
1004 - endforeach;
1005 - endforeach;
1006 - $meta['map authors'] = implode("\n\n", $ma);
1007 - endif;
1008 -
1009 - $notes = '';
1010 - foreach ($meta as $key => $value) :
1011 - $notes .= $key . ": ". addcslashes($value, "\0..\37".'\\') . "\n";
1012 - endforeach;
1013 - $alter[] = "link_notes = '".$wpdb->escape($notes)."'";
1014 -
1015 - $alter_set = implode(", ", $alter);
1016 -
1017 - // issue update query
1018 - $result = $wpdb->query("
1019 - UPDATE $wpdb->links
1020 - SET $alter_set
1021 - WHERE link_id='$link_id'
1022 - ");
1023 - $updated_link = true;
1024 -
1025 - // reload link information from DB
1026 - $link =& new SyndicatedLink($link_id);
1027 - else :
1028 - $updated_link = false;
1029 - endif;
1030 -
1031 - $db_link = $link->link;
1032 - $link_url = wp_specialchars($db_link->link_url, 1);
1033 - $link_name = wp_specialchars($db_link->link_name, 1);
1034 - $link_description = wp_specialchars($db_link->link_description, 'both');
1035 - $link_notes = wp_specialchars($db_link->link_notes, 'both');
1036 - $link_rss_uri = wp_specialchars($db_link->link_rss, 'both');
1037 -
1038 - $meta = $link->settings;
1039 - $post_status_global = get_option('feedwordpress_syndicated_post_status');
1040 - $comment_status_global = get_option('feedwordpress_syndicated_comment_status');
1041 - $ping_status_global = get_option('feedwordpress_syndicated_ping_status');
1042 -
1043 - $status['post'] = array('publish' => '', 'private' => '', 'draft' => '', 'site-default' => '');
1044 - $status['comment'] = array('open' => '', 'closed' => '', 'site-default' => '');
1045 - $status['ping'] = array('open' => '', 'closed' => '', 'site-default' => '');
1046 -
1047 - foreach (array('post', 'comment', 'ping') as $what) :
1048 - if (isset($meta["{$what} status"])) :
1049 - $status[$what][$meta["{$what} status"]] = ' checked="checked"';
1050 - else :
1051 - $status[$what]['site-default'] = ' checked="checked"';
1052 - endif;
1053 - endforeach;
1054 -
1055 - $unfamiliar['author'] = array ('create' => '','default' => '','filter' => '');
1056 - $unfamiliar['category'] = array ('create'=>'','default'=>'','filter'=>'');
1057 -
1058 - foreach (array('author', 'category') as $what) :
1059 - if (is_string($meta["unfamiliar {$what}"]) and
1060 - array_key_exists($meta["unfamiliar {$what}"], $unfamiliar[$what])) :
1061 - $key = $meta["unfamiliar {$what}"];
1062 - else:
1063 - $key = 'site-default';
1064 - endif;
1065 - $unfamiliar[$what][$key] = ' checked="checked"';
1066 - endforeach;
1067 -
1068 - $dogs = get_nested_categories(-1, 0);
1069 - if (is_array($meta['cats'])) :
1070 - $cats = array_map('strtolower',
1071 - array_map('trim',
1072 - $meta['cats']
1073 - ));
1074 - else:
1075 - $cats = array();
1076 - endif;
1077 -
1078 - foreach ($dogs as $tag => $dog) :
1079 - $found_by_name = in_array(strtolower(trim($dog['cat_name'])), $cats);
1080 -
1081 - if (isset($dog['cat_ID'])) : $dog['cat_id'] = $dog['cat_ID']; endif;
1082 - $found_by_id = in_array('{#'.trim($dog['cat_id']).'}', $cats);
1083 -
1084 - if ($found_by_name or $found_by_id) :
1085 - $dogs[$tag]['checked'] = true;
1086 - endif;
1087 - endforeach;
1088 - else :
1089 - die( __('Link not found.') );
1090 - endif;
1091 -
1092 - ?>
1093 -<script type="text/javascript">
1094 - function flip_hardcode (item) {
1095 - ed=document.getElementById('basics-'+item+'-edit');
1096 - view=document.getElementById('basics-'+item+'-view');
1097 -
1098 - o = document.getElementById('basics-hardcode-'+item);
1099 - if (o.value=='yes') { ed.style.display='inline'; view.style.display='none'; }
1100 - else { ed.style.display='none'; view.style.display='inline'; }
1101 - }
1102 - function flip_newuser (item) {
1103 - rollup=document.getElementById(item);
1104 - newuser=document.getElementById(item+'-newuser');
1105 - sitewide=document.getElementById(item+'-default');
1106 - if (rollup) {
1107 - if ('newuser'==rollup.value) {
1108 - if (newuser) newuser.style.display='block';
1109 - if (sitewide) sitewide.style.display='none';
1110 - } else if ('site-default'==rollup.value) {
1111 - if (newuser) newuser.style.display='none';
1112 - if (sitewide) sitewide.style.display='block';
1113 - } else {
1114 - if (newuser) newuser.style.display='none';
1115 - if (sitewide) sitewide.style.display='none';
1116 - }
1117 - }
1118 - }
1119 -</script>
1120 -
1121 -<?php if ($updated_link) : ?>
1122 -<div class="updated"><p>Syndicated feed settings updated.</p></div>
1123 -<?php endif; ?>
1124 -
1125 -<form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
1126 -<div class="wrap">
1127 -<input type="hidden" name="link_id" value="<?php echo $link_id; ?>" />
1128 -<input type="hidden" name="action" value="linkedit" />
1129 -<input type="hidden" name="save" value="link" />
1130 -
1131 -<h2>Edit a syndicated feed:</h2>
1132 -<fieldset class="options"><legend>Basics</legend>
1133 -<table class="editform" width="100%" cellspacing="2" cellpadding="5">
1134 -<tr>
1135 -<th scope="row" width="20%"><?php _e('Feed URI:') ?></th>
1136 -<td width="60%"><a href="<?php echo wp_specialchars($link_rss_uri, 'both'); ?>"><?php echo $link_rss_uri; ?></a>
1137 -(<a href="<?php echo FEEDVALIDATOR_URI; ?>?url=<?php echo urlencode($link_rss_uri); ?>"
1138 -title="Check feed &lt;<?php echo wp_specialchars($link_rss_uri, 'both'); ?>&gt; for validity">validate</a>)
1139 -</td>
1140 -<td width="20%"><input type="submit" name="feedfinder" value="switch &rarr;" style="font-size:smaller" /></td>
1141 -</tr>
1142 -<tr>
1143 -<th scope="row" width="20%"><?php _e('Link Name:') ?></th>
1144 -<td width="60%"><input type="text" id="basics-name-edit" name="name"
1145 -value="<?php echo $link_name; ?>" style="width: 95%" />
1146 -<span id="basics-name-view"><strong><?php echo $link_name; ?></strong></span>
1147 -</td>
1148 -<td>
1149 -<select id="basics-hardcode-name" onchange="flip_hardcode('name')" name="hardcode_name">
1150 -<option value="no" <?php echo $link->hardcode('name')?'':'selected="selected"'; ?>>update automatically</option>
1151 -<option value="yes" <?php echo $link->hardcode('name')?'selected="selected"':''; ?>>edit manually</option>
1152 -</select>
1153 -</td>
1154 -</tr>
1155 -<tr>
1156 -<th scope="row" width="20%"><?php _e('Short description:') ?></th>
1157 -<td width="60%">
1158 -<input id="basics-description-edit" type="text" name="description" value="<?php echo $link_description; ?>" style="width: 95%" />
1159 -<span id="basics-description-view"><strong><?php echo $link_description; ?></strong></span>
1160 -</td>
1161 -<td>
1162 -<select id="basics-hardcode-description" onchange="flip_hardcode('description')"
1163 -name="hardcode_description">
1164 -<option value="no" <?php echo $link->hardcode('description')?'':'selected="selected"'; ?>>update automatically</option>
1165 -<option value="yes" <?php echo $link->hardcode('description')?'selected="selected"':''; ?>>edit manually</option>
1166 -</select></td>
1167 -</tr>
1168 -<tr>
1169 -<th width="20%" scope="row"><?php _e('Homepage:') ?></th>
1170 -<td width="60%">
1171 -<input id="basics-url-edit" type="text" name="linkurl" value="<?php echo $link_url; ?>" style="width: 95%;" />
1172 -<a id="basics-url-view" href="<?php echo $link_url; ?>"><?php echo $link_url; ?></a></td>
1173 -<td>
1174 -<select id="basics-hardcode-url" onchange="flip_hardcode('url')" name="hardcode_url">
1175 -<option value="no"<?php echo $link->hardcode('url')?'':' selected="selected"'; ?>>update automatically</option>
1176 -<option value="yes"<?php echo $link->hardcode('url')?' selected="selected"':''; ?>>edit manually</option>
1177 -</select></td></tr>
1178 -
1179 -<tr>
1180 -<th width="20%"><?php _e('Last update') ?>:</th>
1181 -<td colspan="2"><?php
1182 - if (isset($meta['update/last'])) :
1183 - echo strftime('%x %X', $meta['update/last'])." ";
1184 - else :
1185 - echo " none yet";
438 + $options = __('Options');
439 + $longoptions = __('Syndication Options');
1186 440 endif;
1187 -?></td></tr>
1188 -<tr><th width="20%">Next update:</th>
1189 -<td colspan="2"><?php
1190 - $holdem = (isset($meta['update/hold']) ? $meta['update/hold'] : 'scheduled');
1191 -?>
1192 -<select name="update_schedule">
1193 -<option value="scheduled"<?php echo ($holdem=='scheduled')?' selected="selected"':''; ?>>update on schedule <?php
1194 - echo " (";
1195 - if (isset($meta['update/ttl']) and is_numeric($meta['update/ttl'])) :
1196 - if (isset($meta['update/timed']) and $meta['update/timed']=='automatically') :
1197 - echo 'next: ';
1198 - $next = $meta['update/last'] + ((int) $meta['update/ttl'] * 60);
1199 - if (strftime('%x', time()) != strftime('%x', $next)) :
1200 - echo strftime('%x', $next)." ";
1201 - endif;
1202 - echo strftime('%X', $meta['update/last']+((int) $meta['update/ttl']*60));
1203 - else :
1204 - echo "every ".$meta['update/ttl']." minute".(($meta['update/ttl']!=1)?"s":"");
1205 - endif;
1206 - else:
1207 - echo "next scheduled update";
1208 - endif;
1209 - echo ")";
1210 -?></option>
1211 -<option value="next"<?php echo ($holdem=='next')?' selected="selected"':''; ?>>update ASAP</option>
1212 -<option value="ping"<?php echo ($holdem=='ping')?' selected="selected"':''; ?>>update only when pinged</option>
1213 -</select></tr>
1214 -</table>
1215 -</fieldset>
1216 441
1217 -<script type="text/javascript">
1218 -flip_hardcode('name');
1219 -flip_hardcode('description');
1220 -flip_hardcode('url');
1221 -</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');
1222 445
1223 -<p class="submit">
1224 -<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1225 -</p>
446 + add_options_page($longoptions, 'Syndication', $fwp_capability['manage_options'], $fwp_path.'/syndication-options.php');
447 +} // function fwp_add_pages () */
1226 448
1227 -<fieldset class="options">
1228 -<legend>Syndicated Posts</legend>
1229 -
1230 -<?php fwp_category_box($dogs, 'all syndicated posts from this feed'); ?>
1231 -
1232 -<table class="editform" width="75%" cellspacing="2" cellpadding="5">
1233 -<tr><th width="27%" scope="row" style="vertical-align:top">Publication:</th>
1234 -<td width="73%" style="vertical-align:top"><ul style="margin:0; list-style:none">
1235 -<li><label><input type="radio" name="feed_post_status" value="site-default"
1236 -<?php echo $status['post']['site-default']; ?> /> Use site-wide setting from <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a>
1237 -(currently: <strong><?php echo ($post_status_global ? $post_status_global : 'publish'); ?></strong>)</label></li>
1238 -<li><label><input type="radio" name="feed_post_status" value="publish"
1239 -<?php echo $status['post']['publish']; ?> /> Publish posts from this feed immediately</label></li>
1240 -<li><label><input type="radio" name="feed_post_status" value="private"
1241 -<?php echo $status['post']['private']; ?> /> Hold posts from this feed as private posts</label></li>
1242 -<li><label><input type="radio" name="feed_post_status" value="draft"
1243 -<?php echo $status['post']['draft']; ?> /> Hold posts from this feed as drafts</label></li>
1244 -</ul></td>
1245 -</tr>
1246 -
1247 -<tr><th width="27%" scope="row" style="vertical-align:top">Comments:</th>
1248 -<td width="73%"><ul style="margin:0; list-style:none">
1249 -<li><label><input type="radio" name="feed_comment_status" value="site-default"
1250 -<?php echo $status['comment']['site-default']; ?> /> Use site-wide setting from <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a>
1251 -(currently: <strong><?php echo ($comment_status_global ? $comment_status_global : 'closed'); ?>)</strong></label></li>
1252 -<li><label><input type="radio" name="feed_comment_status" value="open"
1253 -<?php echo $status['comment']['open']; ?> /> Allow comments on syndicated posts from this feed</label></li>
1254 -<li><label><input type="radio" name="feed_comment_status" value="closed"
1255 -<?php echo $status['comment']['closed']; ?> /> Don't allow comments on syndicated posts from this feed</label></li>
1256 -</ul></td>
1257 -</tr>
1258 -
1259 -<tr><th width="27%" scope="row" style="vertical-align:top">Trackback and Pingback:</th>
1260 -<td width="73%"><ul style="margin:0; list-style:none">
1261 -<li><label><input type="radio" name="feed_ping_status" value="site-default"
1262 -<?php echo $status['ping']['site-default']; ?> /> Use site-wide setting from <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a>
1263 -(currently: <strong><?php echo ($ping_status_global ? $ping_status_global : 'closed'); ?>)</strong></label></li>
1264 -<li><label><input type="radio" name="feed_ping_status" value="open"
1265 -<?php echo $status['ping']['open']; ?> /> Accept pings on syndicated posts from this feed</label></li>
1266 -<li><label><input type="radio" name="feed_ping_status" value="closed"
1267 -<?php echo $status['ping']['closed']; ?> /> Don't accept pings on syndicated posts from this feed</label></li>
1268 -</ul></td>
1269 -</tr>
1270 -</table>
1271 -</fieldset>
1272 -
1273 -<p class="submit">
1274 -<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1275 -</p>
1276 -
1277 -<fieldset class="options">
1278 -<legend>Syndicated Authors</legend>
1279 -<?php $authorlist = fwp_author_list(); ?>
1280 -
1281 -<table>
1282 -<tr><th colspan="3" style="text-align: left; padding-top: 1.0em; border-bottom: 1px dotted black;">For posts by specific authors. Blank out a name to delete the rule.</th></tr>
1283 -
1284 -<?php if (isset($meta['map authors'])) : $i=0; foreach ($meta['map authors'] as $author_rules) : foreach ($author_rules as $author_name => $author_action) : $i++; ?>
1285 -<tr>
1286 - <th style="text-align: left">Posts by <input type="text" name="author_rules_name[]" value="<?php echo htmlspecialchars($author_name); ?>" /></th>
1287 - <td>
1288 - <select id="author-rules-<?php echo $i; ?>" name="author_rules_action[]" onchange="flip_newuser('author-rules-<?php echo $i; ?>');">
1289 - <?php foreach ($authorlist as $local_author_id => $local_author_name) : ?>
1290 - <option value="<?php echo $local_author_id; ?>"<?php if ($local_author_id==$author_action) : echo ' selected="selected"'; endif; ?>>are assigned to <?php echo $local_author_name; ?></option>
1291 - <?php endforeach; ?>
1292 - <option value="newuser">will be assigned to a new user...</option>
1293 - <option value="filter"<?php if ('filter'==$author_action) : echo ' selected="selected"'; endif; ?>>get filtered out</option>
1294 - </select>
1295 - </td>
1296 - <td><div id="author-rules-<?php echo $i; ?>-newuser">named <input type="text" name="author_rules_newuser[]" value="" /></div></td>
1297 -</tr>
1298 -<?php endforeach; endforeach; endif; ?>
1299 -
1300 -<tr><th colspan="3" style="text-align: left; padding-top: 1.0em; border-bottom: 1px dotted black;">Fill in to set up a new rule:</th></tr>
1301 -
1302 -<tr>
1303 - <th style="text-align: left">Posts by <input type="text" name="add_author_rule_name" /></th>
1304 - <td>
1305 - <select id="add-author-rule" name="add_author_rule_action" onchange="flip_newuser('add-author-rule');">
1306 - <?php foreach ($authorlist as $author_id => $author_name) : ?>
1307 - <option value="<?php echo $author_id; ?>">are assigned to <?php echo $author_name; ?></option>
1308 - <?php endforeach; ?>
1309 - <option value="newuser">will be assigned to a new user...</option>
1310 - <option value="filter">get filtered out</option>
1311 - </select>
1312 - </td>
1313 - <td><div id="add-author-rule-newuser">named <input type="text" name="add_author_rule_newuser" value="" /></div></td>
1314 -</tr>
1315 -
1316 -<tr><th colspan="3" style="text-align: left; padding-top: 1.0em; border-bottom: 1px dotted black;">For posts by authors that haven't been syndicated before:</th></tr>
1317 -<tr>
1318 - <th style="text-align: left">Posts by new authors</th>
1319 - <td>
1320 - <select id="unfamiliar-author" name="unfamiliar_author" onchange="flip_newuser('unfamiliar-author');">
1321 - <option value="site-default"<?php if (!isset($meta['unfamiliar author'])) : ?>selected="selected"<?php endif; ?>>are handled using site-wide settings</option>
1322 - <option value="create"<?php if ('create'==$meta['unfamiliar author']) : ?>selected="selected"<?php endif; ?>>create a new author account</option>
1323 - <?php foreach ($authorlist as $author_id => $author_name) : ?>
1324 - <option value="<?php echo $author_id; ?>"<?php if ($author_id==$meta['unfamiliar author']) : ?>selected="selected"<?php endif; ?>>are assigned to <?php echo $author_name; ?></option>
1325 - <?php endforeach; ?>
1326 - <option value="newuser">will be assigned to a new user...</option>
1327 - <option value="filter"<?php if ('filter'==$meta['unfamiliar author']) : ?>selected="selected"<?php endif; ?>>get filtered out</option>
1328 - </select>
1329 - </td>
1330 - <td>
1331 - <div id="unfamiliar-author-default">Site-wide settings can be set in <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a></div>
1332 - <div id="unfamiliar-author-newuser">named <input type="text" name="unfamiliar_author_newuser" value="" /></div>
1333 - </td>
1334 -</tr>
1335 -
1336 -</table>
1337 -</fieldset>
1338 -
1339 -<script>
1340 - flip_newuser('unfamiliar-author');
1341 -<?php for ($j=1; $j<=$i; $j++) : ?>
1342 - flip_newuser('author-rules-<?php echo $j; ?>');
1343 -<?php endfor; ?>
1344 - flip_newuser('add-author-rule');
1345 -</script>
1346 -
1347 -<p class="submit">
1348 -<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1349 -</p>
1350 -
1351 -<fieldset>
1352 -<legend>Advanced Feed Options</legend>
1353 -<table class="editform" width="100%" cellspacing="2" cellpadding="5">
1354 -
1355 -<tr>
1356 -<th width="20%" scope="row" style="vertical-align:top">Unfamiliar categories:</th>
1357 -<td width="80%"><ul style="margin: 0; list-style:none">
1358 -<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>
1359 -(currently <strong><?php echo FeedWordPress::on_unfamiliar('category'); ?></strong>)</label></li>
1360 -<li><label><input type="radio" name="unfamiliar_category" value="create"<?php echo $unfamiliar['category']['create']; ?> /> create any categories the post is in</label></li>
1361 -<li><label><input type="radio" name="unfamiliar_category" value="default"<?php echo $unfamiliar['category']['default']; ?> /> don't create new categories</label></li>
1362 -<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>
1363 -</ul></td>
1364 -</tr>
1365 -
1366 -<tr>
1367 -<th width="20%" scope="row" style="vertical-align:top">Multiple categories:</th>
1368 -<td width="80%">
1369 -<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/>
1370 -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
1371 -categories in a single category element. The regular expression should match
1372 -the characters used to separate one category from the next. If the feed uses
1373 -spaces (like <a href="http://del.icio.us/">del.icio.us</a>), use the pattern "\s".
1374 -If the feed does not provide multiple categories in a single element, leave this
1375 -blank.</td>
1376 -</tr>
1377 -</table>
1378 -</fieldset>
1379 -
1380 -<p class="submit">
1381 -<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1382 -</p>
1383 -
1384 -<fieldset id="postcustom">
1385 -<legend>Custom Settings (for use in templates)</legend>
1386 -<div id="postcustomstuff">
1387 -<table id="meta-list" cellpadding="3">
1388 - <tr>
1389 - <th>Key</th>
1390 - <th>Value</th>
1391 - <th>Action</th>
1392 - </tr>
1393 -
1394 -<?php
1395 - $i = 0;
1396 - foreach ($meta as $key => $value) :
1397 - if (!preg_match("\007^((".implode(')|(', $special_settings)."))$\007i", $key)) :
1398 -?>
1399 - <tr style="vertical-align:top">
1400 - <th width="30%" scope="row"><input type="hidden" name="notes[<?php echo $i; ?>][key0]" value="<?php echo wp_specialchars($key, 'both'); ?>" />
1401 - <input id="notes-<?php echo $i; ?>-key" name="notes[<?php echo $i; ?>][key1]" value="<?php echo wp_specialchars($key, 'both'); ?>" /></th>
1402 - <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>
1403 - <td width="10%"><select name="notes[<?php echo $i; ?>][action]">
1404 - <option value="update">save changes</option>
1405 - <option value="delete">delete this setting</option>
1406 - </select></td>
1407 - </tr>
1408 -<?php
1409 - $i++;
1410 - endif;
1411 - endforeach;
1412 -?>
1413 - <tr>
1414 - <th scope="row"><input type="text" size="10" name="notes[<?php echo $i; ?>][key1]" value="" /></th>
1415 - <td><textarea name="notes[<?php echo $i; ?>][value]" rows="2" cols="40"></textarea></td>
1416 - <td><em>add new setting...</em><input type="hidden" name="notes[<?php echo $i; ?>][action]" value="update" /></td>
1417 - </tr>
1418 -</table>
1419 -</fieldset>
1420 -
1421 -<p class="submit">
1422 -<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1423 -</p>
1424 -
1425 -</div>
1426 - <?php
1427 - endif;
1428 - return false; // Don't continue
1429 -}
1430 -
1431 -function fwp_author_list () {
1432 - global $wpdb;
1433 - $ret = array();
1434 - $users = $wpdb->get_results("SELECT * FROM $wpdb->users ORDER BY display_name");
1435 - if (is_array($users)) :
1436 - foreach ($users as $user) :
1437 - $id = (int) $user->ID;
1438 - $ret[$id] = $user->display_name;
1439 - endforeach;
1440 - endif;
1441 - return $ret;
1442 -}
1443 -
1444 -function fwp_multidelete_page () {
1445 - global $wpdb;
1446 -
1447 - check_admin_referer(); // Make sure the referers are kosher
1448 -
1449 - $link_ids = (isset($_REQUEST['link_ids']) ? $_REQUEST['link_ids'] : array());
1450 - if (isset($_REQUEST['link_id'])) : array_push($link_ids, $_REQUEST['link_id']); endif;
1451 -
1452 - if (!current_user_can('manage_links')):
1453 - die (__("Cheatin' uh ?"));
1454 - elseif (isset($GLOBALS['fwp_post']['confirm']) and $GLOBALS['fwp_post']['confirm']=='Delete'):
1455 - foreach ($GLOBALS['fwp_post']['link_action'] as $link_id => $what) :
1456 - $do_it[$what][] = $link_id;
1457 - endforeach;
1458 -
1459 - $alter = array();
1460 - if (count($do_it['hide']) > 0) :
1461 - $hidem = "(".implode(', ', $do_it['hide']).")";
1462 - $alter[] = "
1463 - UPDATE $wpdb->links
1464 - SET link_visible = 'N'
1465 - WHERE link_id IN {$hidem}
1466 - ";
1467 - endif;
1468 -
1469 - if (count($do_it['nuke']) > 0) :
1470 - $nukem = "(".implode(', ', $do_it['nuke']).")";
1471 -
1472 - // Make a list of the items syndicated from this feed...
1473 - $post_ids = $wpdb->get_col("
1474 - SELECT post_id FROM $wpdb->postmeta
1475 - WHERE meta_key = 'syndication_feed_id'
1476 - AND meta_value IN {$nukem}
1477 - ");
1478 -
1479 - // ... and kill them all
1480 - if (count($post_ids) > 0) :
1481 - foreach ($post_ids as $post_id) :
1482 - wp_delete_post($post_id);
1483 - endforeach;
1484 - endif;
1485 -
1486 - $alter[] = "
1487 - DELETE FROM $wpdb->links
1488 - WHERE link_id IN {$nukem}
1489 - ";
1490 - endif;
1491 -
1492 - if (count($do_it['delete']) > 0) :
1493 - $deletem = "(".implode(', ', $do_it['delete']).")";
1494 -
1495 - // Make the items syndicated from this feed appear to be locally-authored
1496 - $alter[] = "
1497 - DELETE FROM $wpdb->postmeta
1498 - WHERE meta_key = 'syndication_feed_id'
1499 - AND meta_value IN {$deletem}
1500 - ";
1501 -
1502 - // ... and delete the links themselves.
1503 - $alter[] = "
1504 - DELETE FROM $wpdb->links
1505 - WHERE link_id IN {$deletem}
1506 - ";
1507 - endif;
1508 -
1509 - $errs = array(); $success = array ();
1510 - foreach ($alter as $sql) :
1511 - $result = $wpdb->query($sql);
1512 - if (!$result):
1513 - $errs[] = mysql_error();
1514 - endif;
1515 - endforeach;
1516 -
1517 - if (count($alter) > 0) :
1518 - echo "<div class=\"updated\">\n";
1519 - if (count($errs) > 0) :
1520 - echo "There were some problems processing your ";
1521 - echo "unsubscribe request. [SQL: ".implode('; ', $errs)."]";
1522 - else :
1523 - echo "Your unsubscribe request(s) have been processed.";
1524 - endif;
1525 - echo "</div>\n";
1526 - endif;
1527 -
1528 - return true; // Continue on to Syndicated Sites listing
1529 - else :
1530 - $targets = $wpdb->get_results("
1531 - SELECT * FROM $wpdb->links
1532 - WHERE link_id IN (".implode(",",$link_ids).")
1533 - ");
1534 -?>
1535 -<form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
1536 -<div class="wrap">
1537 -<input type="hidden" name="action" value="Unsubscribe" />
1538 -<input type="hidden" name="confirm" value="Delete" />
1539 -
1540 -<h2>Unsubscribe from Syndicated Links:</h2>
1541 -<?php foreach ($targets as $link) :
1542 - $link_url = wp_specialchars($link->link_url, 1);
1543 - $link_name = wp_specialchars($link->link_name, 1);
1544 - $link_description = wp_specialchars($link->link_description, 'both');
1545 - $link_rss = wp_specialchars($link->link_rss, 'both');
1546 -?>
1547 -<fieldset>
1548 -<legend><?php echo $link_name; ?></legend>
1549 -<table class="editform" width="100%" cellspacing="2" cellpadding="5">
1550 -<tr><th scope="row" width="20%"><?php _e('Feed URI:') ?></th>
1551 -<td width="80%"><a href="<?php echo $link_rss; ?>"><?php echo $link_rss; ?></a></td></tr>
1552 -<tr><th scope="row" width="20%"><?php _e('Short description:') ?></th>
1553 -<td width="80%"><?php echo $link_description; ?></span></td></tr>
1554 -<tr><th width="20%" scope="row"><?php _e('Homepage:') ?></th>
1555 -<td width="80%"><a href="<?php echo $link_url; ?>"><?php echo $link_url; ?></a></td></tr>
1556 -<tr style="vertical-align:top"><th width="20%" scope="row">Subscription <?php _e('Options') ?>:</th>
1557 -<td width="80%"><ul style="margin:0; padding: 0; list-style: none">
1558 -<li><input type="radio" id="hide-<?php echo $link->link_id; ?>"
1559 -name="link_action[<?php echo $link->link_id; ?>]" value="hide" />
1560 -<label for="hide-<?php echo $link->link_id; ?>">Turn off the subscription for this
1561 -syndicated link<br/><span style="font-size:smaller">(Keep the feed information
1562 -and all the posts from this feed in the database, but don't syndicate any
1563 -new posts from the feed.)</span></label></li>
1564 -<li><input type="radio" id="nuke-<?php echo $link->link_id; ?>"
1565 -name="link_action[<?php echo $link->link_id; ?>]" value="nuke" />
1566 -<label for="nuke-<?php echo $link->link_id; ?>">Delete this syndicated link and all the
1567 -posts that were syndicated from it</label></li>
1568 -<li><input type="radio" id="delete-<?php echo $link->link_id; ?>"
1569 -name="link_action[<?php echo $link->link_id; ?>]" value="delete" />
1570 -<label for="delete-<?php echo $link->link_id; ?>">Delete this syndicated link, but
1571 -<em>keep</em> posts that were syndicated from it (as if they were authored
1572 -locally).</label></li>
1573 -<li><input type="radio" id="nothing-<?php echo $link->link_id; ?>"
1574 -name="link_action[<?php echo $link->link_id; ?>]" value="nothing" />
1575 -<label for="nothing-<?php echo $link->link_id; ?>">Keep this feed as it is. I changed
1576 -my mind.</label></li>
1577 -</ul>
1578 -</table>
1579 -</fieldset>
1580 -<?php endforeach; ?>
1581 -
1582 -<div class="submit">
1583 -<input class="delete" type="submit" name="submit" value="<?php _e('Unsubscribe from selected feeds &raquo;') ?>" />
1584 -</div>
1585 -</div>
1586 -<?php
1587 - return false; // Don't continue on to Syndicated Sites listing
1588 - endif;
1589 -}
1590 -
1591 449 ################################################################################
1592 450 ## fwp_hold_pings() and fwp_release_pings(): Outbound XML-RPC ping reform ####
1593 451 ## ... 'coz it's rude to send 500 pings the first time your aggregator runs ####
1594 452 ################################################################################
@@ -1742,9 +600,9 @@
1742 600 #
1743 601 # * Updates to existing posts since the last poll are mirrored in the
1744 602 # WordPress store.
1745 603 #
1746 - function update ($uri = null) {
604 + function update ($uri = null, $crash_ts = null) {
1747 605 global $wpdb;
1748 606
1749 607 if (FeedWordPress::needs_upgrade()) : // Will make duplicate posts if we don't hold off
1750 608 return NULL;
@@ -1757,11 +615,28 @@
1757 615 endif;
1758 616
1759 617 do_action('feedwordpress_update', $uri);
1760 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 +
1761 632 // Loop through and check for new posts
1762 633 $delta = NULL;
1763 - 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 +
1764 639 $pinged_that = (is_null($uri) or in_array($uri, array($feed->uri(), $feed->homepage())));
1765 640
1766 641 if (!is_null($uri)) : // A site-specific ping always updates
1767 642 $timely = true;
@@ -1774,9 +649,12 @@
1774 649 endif;
1775 650
1776 651 if ($pinged_that and $timely) :
1777 652 do_action('feedwordpress_check_feed', $feed->settings);
1778 - $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 +
1779 657 if (isset($added['new'])) : $delta['new'] += $added['new']; endif;
1780 658 if (isset($added['updated'])) : $delta['updated'] += $added['updated']; endif;
1781 659 endif;
1782 660 endforeach;
@@ -1834,9 +712,9 @@
1834 712 if (function_exists('wp_insert_link')) { // WordPress 2.x
1835 713 $link_id = wp_insert_link(array(
1836 714 "link_name" => $name,
1837 715 "link_url" => $uri,
1838 - "link_category" => array($cat_id),
716 + "link_category" => (fwp_test_wp_version(0, FWP_SCHEMA_21) ? $cat_id : array($cat_id)),
1839 717 "link_rss" => $rss
1840 718 ));
1841 719 } else { // WordPress 1.5.x
1842 720 $result = $wpdb->query("
@@ -1852,17 +730,20 @@
1852 730 return $link_id;
1853 731 } // function FeedWordPress::syndicate_link()
1854 732
1855 733 function on_unfamiliar ($what = 'author', $override = NULL) {
1856 - $set = array('create', 'default', 'filter');
1857 -
734 + $set = array(
735 + 'author' => array('create', 'default', 'filter'),
736 + 'category' => array('create', 'tag', 'default', 'filter'),
737 + );
738 +
1858 739 if (is_string($override)) :
1859 740 $ret = strtolower($override);
1860 741 endif;
1861 742
1862 - if (!is_numeric($override) and !in_array($ret, $set)) :
743 + if (!is_numeric($override) and !in_array($ret, $set[$what])) :
1863 744 $ret = get_option('feedwordpress_unfamiliar_'.$what);
1864 - if (!is_numeric($ret) and !in_array($ret, $set)) :
745 + if (!is_numeric($ret) and !in_array($ret, $set[$what])) :
1865 746 $ret = 'create';
1866 747 endif;
1867 748 endif;
1868 749
@@ -1868,8 +749,33 @@
1868 749
1869 750 return $ret;
1870 751 } // function FeedWordPress::on_unfamiliar()
1871 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 +
1872 778 function syndicated_links () {
1873 779 $contributors = FeedWordPress::link_category_id();
1874 780 if (function_exists('get_bookmarks')) :
1875 781 $links = get_bookmarks(array("category" => $contributors));
@@ -1912,12 +818,12 @@
1912 818 if (function_exists('wp_insert_term')) :
1913 819 $term = wp_insert_term($cat, 'link_category');
1914 820 $cat_id = $term['term_id'];
1915 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?
1916 - elseif (function_exists('wp_insert_category')) :
822 + elseif (function_exists('wp_insert_category') and !fwp_test_wp_version(FWP_SCHEMA_20, FWP_SCHEMA_21)) :
1917 823 $cat_id = wp_insert_category(array('cat_name' => $cat));
1918 824 // WordPress 1.5 and 2.0.x
1919 - elseif (!isset($wp_db_version) or $wp_db_version < FWP_SCHEMA_21) :
825 + elseif (fwp_test_wp_version(0, FWP_SCHEMA_21)) :
1920 826 $result = $wpdb->query("
1921 827 INSERT INTO $wpdb->linkcategories
1922 828 SET
1923 829 cat_id = 0,
@@ -2027,8 +933,16 @@
2027 933 endswitch;
2028 934 echo "<p>Upgrade complete. FeedWordPress is now ready to use again.</p>";
2029 935 } /* FeedWordPress::upgrade_database() */
2030 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 +
2031 945 # Utility functions for handling text settings
2032 946 function negative ($f, $setting) {
2033 947 $nego = array ('n', 'no', 'f', 'false');
2034 948 return (isset($f[$setting]) and in_array(strtolower($f[$setting]), $nego));
@@ -2053,8 +967,14 @@
2053 967 echo "\n";
2054 968 echo $varname.": "; var_dump($var); echo "\n";
2055 969 die;
2056 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 + }
2057 977 } // class FeedWordPress
2058 978
2059 979 class SyndicatedPost {
2060 980 var $item = null;
@@ -2068,13 +988,8 @@
2068 988
2069 989 var $_freshness = null;
2070 990 var $_wp_id = null;
2071 991
2072 - var $strip_attrs = array (
2073 - array('[a-z]+', 'style'),
2074 - array('[a-z]+', 'target'),
2075 - );
2076 -
2077 992 function SyndicatedPost ($item, $link) {
2078 993 global $wpdb;
2079 994
2080 995 $this->link = $link;
@@ -2105,14 +1020,14 @@
2105 1020 # That's deliberate. The escaping is done at the point
2106 1021 # of insertion, not here, to avoid double-escaping and
2107 1022 # to avoid screwing with syndicated_post filters
2108 1023
2109 - $this->post['post_title'] = $this->item['title'];
1024 + $this->post['post_title'] = apply_filters('syndicated_item_title', $this->item['title'], $this);
2110 1025
2111 - // This just gives usan alphanumeric representation of
1026 + // This just gives us an alphanumeric representation of
2112 1027 // the author. We will look up (or create) the numeric
2113 1028 // ID for the author in SyndicatedPost::add()
2114 - $this->post['named']['author'] = $this->author();
1029 + $this->post['named']['author'] = apply_filters('syndicated_item_author', $this->author(), $this);
2115 1030
2116 1031 # Identify content and sanitize it.
2117 1032 # ---------------------------------
2118 1033 if (isset($this->item['xhtml']['body'])) :
@@ -2123,24 +1038,9 @@
2123 1038 $content = $this->item['content']['encoded'];
2124 1039 else:
2125 1040 $content = $this->item['description'];
2126 1041 endif;
2127 -
2128 - # FeedWordPress used to resolve URIs relative to the
2129 - # feed URI. It now relies on the xml:base support
2130 - # baked in to the MagpieRSS upgrade. So all we do here
2131 - # now is to sanitize problematic attributes.
2132 - #
2133 - # This kind of sucks. I intend to replace it with
2134 - # lib_filter sometime soon.
2135 - foreach ($this->strip_attrs as $pair):
2136 - list($tag,$attr) = $pair;
2137 - $content = preg_replace (
2138 - ":(<$tag [^>]*)($attr=(\"[^\">]*\"|[^>\\s]+))([^>]*>):i",
2139 - "\\1\\4",
2140 - $content
2141 - );
2142 - endforeach;
1042 + $this->post['post_content'] = apply_filters('syndicated_item_content', $content, $this);
2143 1043
2144 1044 # Identify and sanitize excerpt
2145 1045 $excerpt = NULL;
2146 1046 if ( isset($this->item['description']) and $this->item['description'] ) :
@@ -2150,11 +1050,10 @@
2150 1050 if (strlen($excerpt) > 255) :
2151 1051 $excerpt = substr($excerpt,0,252).'...';
2152 1052 endif;
2153 1053 endif;
1054 + $excerpt = apply_filters('syndicated_item_excerpt', $excerpt, $this);
2154 1055
2155 - $this->post['post_content'] = $content;
2156 -
2157 1056 if (!is_null($excerpt)):
2158 1057 $this->post['post_excerpt'] = $excerpt;
2159 1058 endif;
2160 1059
@@ -2162,11 +1061,11 @@
2162 1061 if (!$this->use_api('wp_insert_post')) :
2163 1062 $this->post['post_name'] = sanitize_title($this->post['post_title']);
2164 1063 endif;
2165 1064
2166 - $this->post['epoch']['issued'] = $this->published();
2167 - $this->post['epoch']['created'] = $this->created();
2168 - $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);
2169 1068
2170 1069 // Dealing with timestamps in WordPress is so fucking fucked.
2171 1070 $offset = (int) get_option('gmt_offset') * 60 * 60;
2172 1071 $this->post['post_date'] = gmdate('Y-m-d H:i:s', $this->published() + $offset);
@@ -2179,9 +1078,9 @@
2179 1078 $this->post['comment_status'] = $this->link->syndicated_status('comment', 'closed');
2180 1079 $this->post['ping_status'] = $this->link->syndicated_status('ping', 'closed');
2181 1080
2182 1081 // Unique ID (hopefully a unique tag: URI); failing that, the permalink
2183 - $this->post['guid'] = $this->guid();
1082 + $this->post['guid'] = apply_filters('syndicated_item_guid', $this->guid(), $this);
2184 1083
2185 1084 // RSS 2.0 / Atom 1.0 enclosure support
2186 1085 if ( isset($this->item['enclosure#']) ) :
2187 1086 for ($i = 1; $i <= $this->item['enclosure#']; $i++) :
@@ -2186,28 +1085,42 @@
2186 1085 if ( isset($this->item['enclosure#']) ) :
2187 1086 for ($i = 1; $i <= $this->item['enclosure#']; $i++) :
2188 1087 $eid = (($i > 1) ? "#{$id}" : "");
2189 1088 $this->post['meta']['enclosure'][] =
2190 - $this->item["enclosure{$eid}@url"]."\n".
2191 - $this->item["enclosure{$eid}@length"]."\n".
2192 - $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);
2193 1092 endfor;
2194 1093 endif;
2195 1094
2196 1095 // In case you want to point back to the blog this was syndicated from
2197 1096 if (isset($this->feed->channel['title'])) :
2198 - $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);
2199 1098 endif;
1099 +
2200 1100 if (isset($this->feed->channel['link'])) :
2201 - $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);
2202 1102 endif;
2203 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 +
2204 1117 // Store information on human-readable and machine-readable comment URIs
2205 1118 if (isset($this->item['comments'])) :
2206 - $this->post['meta']['rss:comments'] = $this->item['comments'];
1119 + $this->post['meta']['rss:comments'] = apply_filters('syndicated_item_comments', $this->item['comments']);
2207 1120 endif;
2208 1121 if (isset($this->item['wfw']['commentrss'])) :
2209 - $this->post['meta']['wfw:commentRSS'] = $this->item['wfw']['commentrss'];
1122 + $this->post['meta']['wfw:commentRSS'] = apply_filters('syndicated_item_commentrss', $this->item['wfw']['commentrss']);
2210 1123 endif;
2211 1124
2212 1125 // Store information to identify the feed that this came from
2213 1126 $this->post['meta']['syndication_feed'] = $this->feedmeta['link/uri'];
@@ -2212,14 +1125,21 @@
2212 1125 // Store information to identify the feed that this came from
2213 1126 $this->post['meta']['syndication_feed'] = $this->feedmeta['link/uri'];
2214 1127 $this->post['meta']['syndication_feed_id'] = $this->feedmeta['link/id'];
2215 1128
1129 + if (isset($this->item['source_link_self'])) :
1130 + $this->post['meta']['syndication_feed_original'] = $this->item['source_link_self'];
1131 + endif;
1132 +
2216 1133 // In case you want to know the external permalink...
2217 - $this->post['meta']['syndication_permalink'] = $this->item['link'];
1134 + $this->post['meta']['syndication_permalink'] = apply_filters('syndicated_item_link', $this->item['link']);
2218 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 +
2219 1139 // Feed-by-feed options for author and category creation
2220 1140 $this->post['named']['unfamiliar']['author'] = $this->feedmeta['unfamiliar author'];
2221 - $this->post['named']['unfamiliar']['category'] = $this->feedmeta['unfamiliar categories'];
1141 + $this->post['named']['unfamiliar']['category'] = $this->feedmeta['unfamiliar category'];
2222 1142
2223 1143 // Categories: start with default categories, if any
2224 1144 $fc = get_option("feedwordpress_syndication_cats");
2225 1145 if ($fc) :
@@ -2246,8 +1166,22 @@
2246 1166 $this->post['named']['category'][] = $cat;
2247 1167 endif;
2248 1168 endfor;
2249 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 +
2250 1184 endif;
2251 1185 } // SyndicatedPost::SyndicatedPost()
2252 1186
2253 1187 function filtered () {
@@ -2268,18 +1202,35 @@
2268 1202 SELECT id, guid, post_modified_gmt
2269 1203 FROM $wpdb->posts WHERE guid='$guid'
2270 1204 ");
2271 1205
2272 - preg_match('/([0-9]+)-([0-9]+)-([0-9]+) ([0-9]+):([0-9]+):([0-9]+)/', $result->post_modified_gmt, $backref);
2273 - $updated = gmmktime($backref[4], $backref[5], $backref[6], $backref[2], $backref[3], $backref[1]);
2274 1206 if (!$result) :
2275 1207 $this->_freshness = 2; // New content
2276 - elseif ($this->updated() > $updated) :
2277 - $this->_freshness = 1; // Updated content
2278 - $this->_wp_id = $result->id;
2279 - else :
2280 - $this->_freshness = 0; // Same old, same old
2281 - $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;
2282 1233 endif;
2283 1234 endif;
2284 1235 return $this->_freshness;
2285 1236 }
@@ -2315,13 +1266,17 @@
2315 1266 endif;
2316 1267
2317 1268 if (!$this->filtered() and $freshness > 0) :
2318 1269 # -- Look up, or create, numeric ID for categories
2319 - $this->post['post_category'] = $this->category_ids (
1270 + list($pcats, $ptags) = $this->category_ids (
2320 1271 $this->post['named']['category'],
2321 - FeedWordPress::on_unfamiliar('category', $this->post['named']['unfamiliar']['category'])
1272 + FeedWordPress::on_unfamiliar('category', $this->post['named']['unfamiliar']['category']),
1273 + /*tags_too=*/ true
2322 1274 );
2323 -
1275 +
1276 + $this->post['post_category'] = $pcats;
1277 + $this->post['tags_input'] = array_merge($this->post['tags_input'], $ptags);
1278 +
2324 1279 if (is_null($this->post['post_category'])) :
2325 1280 // filter mode on, no matching categories; drop the post
2326 1281 $this->post = NULL;
2327 1282 else :
@@ -2377,15 +1332,37 @@
2377 1332 $dbpost[$key] = $value;
2378 1333 endif;
2379 1334 endforeach;
2380 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 +
2381 1345 if ($this->use_api('wp_insert_post')) :
2382 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 +
2383 1356 $this->_wp_id = wp_insert_post($dbpost);
2384 -
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 +
2385 1362 // This should never happen.
2386 1363 if (!is_numeric($this->_wp_id) or ($this->_wp_id == 0)) :
2387 - FeedWordPress::critical_bug('SyndicatedPost (_wp_id problem)', $this, __LINE__);
1364 + FeedWordPress::critical_bug('SyndicatedPost (_wp_id problem)', array("dbpost" => $dbpost, "this" => $this), __LINE__);
2388 1365 endif;
2389 1366
2390 1367 // Unfortunately, as of WordPress 2.3, wp_insert_post()
2391 1368 // *still* offers no way to use a guid of your choice,
@@ -2428,9 +1405,9 @@
2428 1405 $this->_wp_id = $wpdb->insert_id;
2429 1406
2430 1407 // This should never happen.
2431 1408 if (!is_numeric($this->_wp_id) or ($this->_wp_id == 0)) :
2432 - FeedWordPress::critical_bug('SyndicatedPost::_wp_id', $this->_wp_id, __LINE__);
1409 + FeedWordPress::critical_bug('SyndicatedPost (_wp_id problem)', array("dbpost" => $dbpost, "this" => $this), __LINE__);
2433 1410 endif;
2434 1411
2435 1412 // WordPress 1.5.x - 2.0.x
2436 1413 wp_set_post_cats('1', $this->wp_id(), $this->post['post_category']);
@@ -2459,13 +1436,26 @@
2459 1436 endforeach;
2460 1437
2461 1438 if ($this->use_api('wp_insert_post')) :
2462 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 +
2463 1449 $this->_wp_id = wp_insert_post($dbpost);
2464 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 +
2465 1455 // This should never happen.
2466 1456 if (!is_numeric($this->_wp_id) or ($this->_wp_id == 0)) :
2467 - FeedWordPress::critical_bug('SyndicatedPost::_wp_id', $this->_wp_id, __LINE__);
1457 + FeedWordPress::critical_bug('SyndicatedPost (_wp_id problem)', array("dbpost" => $dbpost, "this" => $this), __LINE__);
2468 1458 endif;
2469 1459
2470 1460 // Unfortunately, as of WordPress 2.3, wp_insert_post()
2471 1461 // munges your post modified timestamp.
@@ -2498,9 +1488,9 @@
2498 1488 elseif (function_exists('wp_set_post_cats')) :
2499 1489 wp_set_post_cats('1', $this->wp_id(), $this->post['post_category']);
2500 1490 // This should never happen.
2501 1491 else :
2502 - 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__);
2503 1493 endif;
2504 1494
2505 1495 // Since we are not going through official channels, we need to
2506 1496 // manually tell WordPress that we've published a new post.
@@ -2511,8 +1501,63 @@
2511 1501 do_action('edit_post', $this->post['ID']);
2512 1502 endif;
2513 1503 } /* SyndicatedPost::update_existing() */
2514 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 +
2515 1560 // SyndicatedPost::add_rss_meta: adds interesting meta-data to each entry
2516 1561 // using the space for custom keys. The set of keys and values to add is
2517 1562 // specified by the keys and values of $post['meta']. This is used to
2518 1563 // store anything that the WordPress user might want to access from a
@@ -2564,9 +1609,9 @@
2564 1609
2565 1610 // SyndicatedPost::author_id (): get the ID for an author name from
2566 1611 // the feed. Create the author if necessary.
2567 1612 function author_id ($unfamiliar_author = 'create') {
2568 - global $wpdb, $wp_db_version; // test for WordPress 2.0 database schema
1613 + global $wpdb;
2569 1614
2570 1615 $a = $this->author();
2571 1616 $author = $a['name'];
2572 1617 $email = $a['email'];
@@ -2571,8 +1616,15 @@
2571 1616 $author = $a['name'];
2572 1617 $email = $a['email'];
2573 1618 $url = $a['uri'];
2574 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 +
2575 1627 // Never can be too careful...
2576 1628 $login = sanitize_user($author, /*strict=*/ true);
2577 1629 $login = apply_filters('pre_user_login', $login);
2578 1630
@@ -2581,8 +1633,9 @@
2581 1633
2582 1634 $reg_author = $wpdb->escape(preg_quote($author));
2583 1635 $author = $wpdb->escape($author);
2584 1636 $email = $wpdb->escape($email);
1637 + $test_email = $wpdb->escape($test_email);
2585 1638 $url = $wpdb->escape($url);
2586 1639
2587 1640 // Check for an existing author rule....
2588 1641 if (isset($this->link->settings['map authors']['name'][strtolower(trim($author))])) :
@@ -2601,34 +1654,10 @@
2601 1654
2602 1655 else :
2603 1656 // Check the database for an existing author record that might fit
2604 1657
2605 - #-- WordPress 1.5.x
2606 - if (!isset($wp_db_version)) :
2607 - $id = $wpdb->get_var(
2608 - "SELECT ID from $wpdb->users
2609 - WHERE
2610 - TRIM(LCASE(user_login)) = TRIM(LCASE('$login')) OR
2611 - (
2612 - LENGTH(TRIM(LCASE(user_email))) > 0
2613 - AND TRIM(LCASE(user_email)) = TRIM(LCASE('$email'))
2614 - ) OR
2615 - TRIM(LCASE(user_firstname)) = TRIM(LCASE('$author')) OR
2616 - TRIM(LCASE(user_nickname)) = TRIM(LCASE('$author')) OR
2617 - TRIM(LCASE(user_nicename)) = TRIM(LCASE('$nice_author')) OR
2618 - TRIM(LCASE(user_description)) = TRIM(LCASE('$author')) OR
2619 - (
2620 - LOWER(user_description)
2621 - RLIKE CONCAT(
2622 - '(^|\\n)a\\.?k\\.?a\\.?( |\\t)*:?( |\\t)*',
2623 - LCASE('$reg_author'),
2624 - '( |\\t|\\r)*(\\n|\$)'
2625 - )
2626 - )
2627 - ");
2628 -
2629 1658 #-- WordPress 2.0+
2630 - elseif ($wp_db_version >= 2966) :
1659 + if (fwp_test_wp_version(FWP_SCHEMA_HAS_USERMETA)) :
2631 1660
2632 1661 // First try the user core data table.
2633 1662 $id = $wpdb->get_var(
2634 1663 "SELECT ID FROM $wpdb->users
@@ -2635,9 +1664,9 @@
2635 1664 WHERE
2636 1665 TRIM(LCASE(user_login)) = TRIM(LCASE('$login'))
2637 1666 OR (
2638 1667 LENGTH(TRIM(LCASE(user_email))) > 0
2639 - AND TRIM(LCASE(user_email)) = TRIM(LCASE('$email'))
1668 + AND TRIM(LCASE(user_email)) = TRIM(LCASE('$test_email'))
2640 1669 )
2641 1670 OR TRIM(LCASE(user_nicename)) = TRIM(LCASE('$nice_author'))
2642 1671 ");
2643 1672
@@ -2657,8 +1686,33 @@
2657 1686 )
2658 1687 )
2659 1688 ");
2660 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)
1707 + RLIKE CONCAT(
1708 + '(^|\\n)a\\.?k\\.?a\\.?( |\\t)*:?( |\\t)*',
1709 + LCASE('$reg_author'),
1710 + '( |\\t|\\r)*(\\n|\$)'
1711 + )
1712 + )
1713 + ");
1714 +
2661 1715 endif;
2662 1716
2663 1717 // ... if you don't find one, then do what you need to do
2664 1718 if (is_null($id)) :
@@ -2689,9 +1743,9 @@
2689 1743 return $id;
2690 1744 } // function SyndicatedPost::author_id ()
2691 1745
2692 1746 // look up (and create) category ids from a list of categories
2693 - function category_ids ($cats, $unfamiliar_category = 'create') {
1747 + function category_ids ($cats, $unfamiliar_category = 'create', $tags_too = false) {
2694 1748 global $wpdb;
2695 1749
2696 1750 // We need to normalize whitespace because (1) trailing
2697 1751 // whitespace can cause PHP and MySQL not to see eye to eye on
@@ -2700,8 +1754,10 @@
2700 1754 // because I doubt most people want to make a semantic
2701 1755 // distinction between 'Computers' and 'Computers '
2702 1756 $cats = array_map('trim', $cats);
2703 1757
1758 + $tags = array();
1759 +
2704 1760 $cat_ids = array ();
2705 1761 foreach ($cats as $cat_name) :
2706 1762 if (preg_match('/^{#([0-9]+)}$/', $cat_name, $backref)) :
2707 1763 $cat_id = (int) $backref[1];
@@ -2709,9 +1765,9 @@
2709 1765 $cat_ids[] = $cat_id;
2710 1766 elseif (get_category($cat_id)) :
2711 1767 $cat_ids[] = $cat_id;
2712 1768 endif;
2713 - else :
1769 + elseif (strlen($cat_name) > 0) :
2714 1770 $esc = $wpdb->escape($cat_name);
2715 1771 $resc = $wpdb->escape(preg_quote($cat_name));
2716 1772
2717 1773 // WordPress 2.3+
@@ -2729,11 +1785,17 @@
2729 1785 )) :
2730 1786 foreach ($results AS $term) :
2731 1787 $cat_ids[] = (int) $term->term_id;
2732 1788 endforeach;
1789 + elseif ('tag'==$unfamiliar_category) :
1790 + $tags[] = $cat_name;
2733 1791 elseif ('create'===$unfamiliar_category) :
2734 1792 $term = wp_insert_term($cat_name, 'category');
2735 - $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;
2736 1798 endif;
2737 1799
2738 1800 // WordPress 1.5.x - 2.2.x
2739 1801 else :
@@ -2774,18 +1836,28 @@
2774 1836 $cat_ids = NULL; // Drop the post
2775 1837 else :
2776 1838 $cat_ids = array_unique($cat_ids);
2777 1839 endif;
2778 - return $cat_ids;
1840 +
1841 + if ($tags_too) : $ret = array($cat_ids, $tags);
1842 + else : $ret = $cat_ids;
1843 + endif;
1844 +
1845 + return $ret;
2779 1846 } // function SyndicatedPost::category_ids ()
2780 1847
2781 1848 function use_api ($tag) {
2782 1849 global $wp_db_version;
2783 - if ('wp_insert_post'==$tag) :
1850 + switch ($tag) :
1851 + case 'wp_insert_post':
2784 1852 // Before 2.2, wp_insert_post does too much of the wrong stuff to use it
2785 1853 // In 1.5 it was such a resource hog it would make PHP segfault on big updates
2786 1854 $ret = (isset($wp_db_version) and $wp_db_version > FWP_SCHEMA_21);
2787 - 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;
2788 1860 return $ret;
2789 1861 } // function SyndicatedPost::use_api ()
2790 1862
2791 1863 #### EXTRACT DATA FROM FEED ITEM ####
@@ -2823,14 +1895,18 @@
2823 1895 endif;
2824 1896
2825 1897 # If everything failed, then default to the current time.
2826 1898 if (is_null($epoch)) :
2827 - $epoch = time();
1899 + if (-1 == $default) :
1900 + $epoch = time();
1901 + else :
1902 + $epoch = $default;
1903 + endif;
2828 1904 endif;
2829 1905
2830 1906 return $epoch;
2831 1907 }
2832 - function updated ($fallback = true) {
1908 + function updated ($fallback = true, $default = -1) {
2833 1909 $epoch = null;
2834 1910
2835 1911 # As far as I know, only dcterms and Atom have reliable ways to
2836 1912 # specify when something was *modified* last. If neither is
@@ -2843,19 +1919,27 @@
2843 1919 $epoch = @parse_w3cdtf($this->item['modified']);
2844 1920 elseif (isset($this->item['updated'])): // Atom 1.0
2845 1921 $epoch = @parse_w3cdtf($this->item['updated']);
2846 1922 elseif ($fallback) : // Fall back to issued / dc:date
2847 - $epoch = $this->published(/*fallback=*/ false);
1923 + $epoch = $this->published(/*fallback=*/ false, /*default=*/ $default);
2848 1924 endif;
2849 1925
2850 1926 # If everything failed, then default to the current time.
2851 1927 if (is_null($epoch)) :
2852 - $epoch = time();
1928 + if (-1 == $default) :
1929 + $epoch = time();
1930 + else :
1931 + $epoch = $default;
1932 + endif;
2853 1933 endif;
2854 1934
2855 1935 return $epoch;
2856 1936 }
2857 1937
1938 + function update_hash () {
1939 + return md5(serialize($this->item));
1940 + }
1941 +
2858 1942 function guid () {
2859 1943 $guid = null;
2860 1944 if (isset($this->item['id'])): // Atom 0.3 / 1.0
2861 1945 $guid = $this->item['id'];
@@ -2942,8 +2026,31 @@
2942 2026 endif;
2943 2027
2944 2028 return $author;
2945 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 + }
2946 2053 } // class SyndicatedPost
2947 2054
2948 2055 # class SyndicatedLink: represents a syndication feed stored within the
2949 2056 # WordPress database
@@ -3021,18 +2128,26 @@
3021 2128 $this->settings['link/uri'] = $this->link->link_rss;
3022 2129 $this->settings['link/name'] = $this->link->link_name;
3023 2130 $this->settings['link/id'] = $this->link->link_id;
3024 2131
3025 - // `hardcode categories` is deprecated in favor of `unfamiliar categories`
2132 + // `hardcode categories` and `unfamiliar categories` are deprecated in favor of `unfamiliar category`
3026 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 (
3027 2140 FeedWordPress::affirmative($this->settings, 'hardcode categories')
3028 - and !isset($this->settings['unfamiliar categories'])
2141 + and !isset($this->settings['unfamiliar category'])
3029 2142 ) :
3030 - $this->settings['unfamiliar categories'] = 'default';
2143 + $this->settings['unfamiliar category'] = 'default';
3031 2144 endif;
3032 -
2145 +
3033 2146 // Set this up automagically for del.icio.us
3034 - 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)) :
3035 2150 $this->settings['cat_split'] = '\s'; // Whitespace separates multiple tags in del.icio.us RSS feeds
3036 2151 endif;
3037 2152
3038 2153 if (isset($this->settings['cats'])):
@@ -3037,8 +2152,11 @@
3037 2152
3038 2153 if (isset($this->settings['cats'])):
3039 2154 $this->settings['cats'] = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, $this->settings['cats']);
3040 2155 endif;
2156 + if (isset($this->settings['tags'])):
2157 + $this->settings['tags'] = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, $this->settings['tags']);
2158 + endif;
3041 2159
3042 2160 if (isset($this->settings['map authors'])) :
3043 2161 $author_rules = explode("\n\n", $this->settings['map authors']);
3044 2162 $ma = array();
@@ -3054,13 +2172,13 @@
3054 2172 endforeach;
3055 2173 $this->settings['map authors'] = $ma;
3056 2174 endif;
3057 2175 endif;
3058 - } // SyndicatedLink::SyndicatedLink ()
2176 + } /* SyndicatedLink::SyndicatedLink () */
3059 2177
3060 2178 function found () {
3061 2179 return is_object($this->link);
3062 - }
2180 + } /* SyndicatedLink::found () */
3063 2181
3064 2182 function stale () {
3065 2183 $stale = true;
3066 2184 if (isset($this->settings['update/hold']) and ($this->settings['update/hold']=='ping')) :
@@ -3074,16 +2192,25 @@
3074 2192 +((int) $this->settings['update/ttl'] * 60);
3075 2193 $stale = (time() >= $after);
3076 2194 endif;
3077 2195 return $stale;
3078 - }
2196 + } /* SyndicatedLink::stale () */
3079 2197
3080 - function poll () {
2198 + function poll ($crash_ts = NULL) {
3081 2199 global $wpdb;
3082 2200
3083 2201 $this->magpie = fetch_rss($this->link->link_rss);
3084 2202 $new_count = NULL;
3085 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 +
3086 2213 if (is_object($this->magpie)) :
3087 2214 $new_count = array('new' => 0, 'updated' => 0);
3088 2215
3089 2216 # -- Update Link metadata live from feed
@@ -3119,40 +2246,17 @@
3119 2246 else :
3120 2247 $this->settings['update/ttl'] = rand(30, 120); // spread over time interval for staggered updates
3121 2248 $this->settings['update/timed'] = 'automatically';
3122 2249 endif;
3123 -
2250 +
3124 2251 if (!isset($this->settings['update/hold']) or $this->settings['update/hold']!='ping') :
3125 2252 $this->settings['update/hold'] = 'scheduled';
3126 2253 endif;
3127 -
3128 - // Copy back without a few things that we don't want to save in the notes
3129 - $to_notes = $this->settings;
3130 2254
3131 - if (is_array($to_notes['cats'])) :
3132 - $to_notes['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['cats']);
3133 - endif;
2255 + $this->settings['update/unfinished'] = 'yes';
3134 2256
3135 - if (isset($to_notes['map authors'])) :
3136 - $ma = array();
3137 - foreach ($to_notes['map authors'] as $rule_type => $author_rules) :
3138 - foreach ($author_rules as $author_name => $author_action) :
3139 - $ma[] = $rule_type."\n".$author_name."\n".$author_action;
3140 - endforeach;
3141 - endforeach;
3142 - $to_notes['map authors'] = implode("\n\n", $ma);
3143 - endif;
2257 + $update[] = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
3144 2258
3145 - unset($to_notes['link/id']); unset($to_notes['link/uri']);
3146 - unset($to_notes['link/name']);
3147 - unset($to_notes['hardcode categories']); // Deprecated
3148 -
3149 - $notes = '';
3150 - foreach ($to_notes as $key => $value) :
3151 - $notes .= $key . ": ". addcslashes($value, "\0..\37".'\\') . "\n";
3152 - endforeach;
3153 - $update[] = "link_notes = '".$wpdb->escape($notes)."'";
3154 -
3155 2259 $update_set = implode(',', $update);
3156 2260
3157 2261 // Update the properties of the link from the feed information
3158 2262 $result = $wpdb->query("
@@ -3161,14 +2265,24 @@
3161 2265 WHERE link_id='$this->id'
3162 2266 ");
3163 2267
3164 2268 # -- Add new posts from feed and update any updated posts
2269 + $crashed = false;
2270 +
3165 2271 if (is_array($this->magpie->items)) :
3166 2272 foreach ($this->magpie->items as $item) :
3167 2273 $post =& new SyndicatedPost($item, $this);
3168 - if (!$post->filtered()) :
3169 - $new = $post->store();
3170 - 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;
3171 2285 endif;
3172 2286 endforeach;
3173 2287 endif;
3174 2288
@@ -3174,49 +2288,102 @@
3174 2288
3175 2289 // Copy back any changes to feed settings made in the course of updating (e.g. new author rules)
3176 2290 $to_notes = $this->settings;
3177 2291
3178 - if (is_array($to_notes['cats'])) :
3179 - $to_notes['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['cats']);
2292 + $this->settings['update/processed'] = $processed;
2293 + if (!$crashed) :
2294 + $this->settings['update/unfinished'] = 'no';
3180 2295 endif;
3181 2296
3182 - if (isset($to_notes['map authors'])) :
3183 - $ma = array();
3184 - foreach ($to_notes['map authors'] as $rule_type => $author_rules) :
3185 - foreach ($author_rules as $author_name => $author_action) :
3186 - $ma[] = $rule_type."\n".$author_name."\n".$author_action;
3187 - endforeach;
3188 - endforeach;
3189 - $to_notes['map authors'] = implode("\n\n", $ma);
3190 - endif;
3191 -
3192 - unset($to_notes['link/id']); unset($to_notes['link/uri']);
3193 - unset($to_notes['link/name']);
3194 - unset($to_notes['hardcode categories']); // Deprecated
3195 -
3196 - $notes = '';
3197 - foreach ($to_notes as $key => $value) :
3198 - $notes .= $key . ": ". addcslashes($value, "\0..\37".'\\') . "\n";
3199 - endforeach;
3200 -
3201 - $update_set = "link_notes = '".$wpdb->escape($notes)."'";
2297 + $update_set = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
3202 2298
3203 2299 // Update the properties of the link from the feed information
3204 2300 $result = $wpdb->query("
3205 - UPDATE $wpdb->links
3206 - SET $update_set
3207 - WHERE link_id='$this->id'
2301 + UPDATE $wpdb->links
2302 + SET $update_set
2303 + WHERE link_id='$this->id'
3208 2304 ");
3209 2305 endif;
2306 +
3210 2307 return $new_count;
3211 2308 } /* SyndicatedLink::poll() */
3212 -
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 +
3213 2379 function uri () {
3214 2380 return (is_object($this->link) ? $this->link->link_rss : NULL);
3215 - }
2381 + } /* SyndicatedLink::uri () */
2382 +
3216 2383 function homepage () {
3217 2384 return (isset($this->settings['feed/link']) ? $this->settings['feed/link'] : NULL);
3218 - }
2385 + } /* SyndicatedLink::homepage () */
3219 2386
3220 2387 function ttl () {
3221 2388 if (is_object($this->magpie)) :
3222 2389 $channel = $this->magpie->channel;
@@ -3283,9 +2450,9 @@
3283 2450 endif;
3284 2451 endforeach;
3285 2452 endif;
3286 2453 return $ret;
3287 - } // function SyndicatedLink::flatten_array ()
2454 + } /* SyndicatedLink::flatten_array () */
3288 2455
3289 2456 function hardcode ($what) {
3290 2457 $default = get_option("feedwordpress_hardcode_$what");
3291 2458 if ( $default === 'yes' ) :
@@ -3299,9 +2466,9 @@
3299 2466 // setting is explicitly "yes"
3300 2467 $ret = FeedWordPress::affirmative($this->settings, "hardcode $what");
3301 2468 endif;
3302 2469 return $ret;
3303 - } // function SyndicatedLink::hardcode ()
2470 + } /* SyndicatedLink::hardcode () */
3304 2471
3305 2472 function syndicated_status ($what, $default) {
3306 2473 global $wpdb;
3307 2474
@@ -3311,9 +2478,9 @@
3311 2478 elseif (!$ret) :
3312 2479 $ret = $default;
3313 2480 endif;
3314 2481 return $wpdb->escape(trim(strtolower($ret)));
3315 - } // function SyndicatedLink:syndicated_status ()
2482 + } /* SyndicatedLink:syndicated_status () */
3316 2483 } // class SyndicatedLink
3317 2484
3318 2485 ################################################################################
3319 2486 ## XML-RPC HOOKS: accept XML-RPC update pings from Contributors ################
@@ -3348,8 +2515,9 @@
3348 2515
3349 2516 var $verify = FALSE;
3350 2517
3351 2518 var $_data = NULL;
2519 + var $_error = NULL;
3352 2520 var $_head = NULL;
3353 2521
3354 2522 # -- Recognition patterns
3355 2523 var $_feed_types = array(
@@ -3404,8 +2572,12 @@
3404 2572 $this->_get($uri);
3405 2573 return $this->_data;
3406 2574 }
3407 2575
2576 + function error () {
2577 + return $this->_error;
2578 + }
2579 +
3408 2580 function is_feed ($uri = NULL) {
3409 2581 $data = $this->data($uri);
3410 2582
3411 2583 return (
@@ -3424,23 +2596,23 @@
3424 2596 if ($uri) $this->uri = $uri;
3425 2597
3426 2598 // Is the result not yet cached?
3427 2599 if ($this->_cache_uri !== $this->uri) :
3428 - // Snoopy is an HTTP client in PHP
3429 - $client = new Snoopy();
3430 -
3431 - // Prepare headers and internal settings
3432 - $client->rawheaders['Connection'] = 'close';
3433 - $client->accept = 'application/atom+xml application/rdf+xml application/rss+xml application/xml text/html */*';
3434 - $client->agent = 'feedfinder/1.2 (compatible; PHP FeedFinder) +http://projects.radgeek.com/feedwordpress';
3435 - $client->read_timeout = 25;
3436 -
3437 - // Fetch the HTML or feed
3438 - @$client->fetch($this->uri);
3439 - $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';
3440 2603
3441 - // Kilroy was here
3442 - $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;
3443 2615 endif;
3444 2616 } /* FeedFinder::_get () */
3445 2617
3446 2618 function _link_rel_feeds () {
@@ -3701,5 +2873,5 @@
3701 2873 $ret['name'] = NULL; $ret['email'] = NULL;
3702 2874 endif;
3703 2875 return $ret;
3704 2876 }
3705 -?>
2877 +