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