PluginProbe
FeedWordPress / 0.992
FeedWordPress v0.992
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 +2028 -885 2009.06130.992 View file →
@@ -2,12 +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: 2009.0613
6 +Version: 0.992
7 7 Author: Charles Johnson
8 8 Author URI: http://radgeek.com/
9 9 License: GPL
10 +Last modified: 2008-01-04 18:03 PDT
10 11 */
11 12
12 13 # This uses code derived from:
13 14 # - wp-rss-aggregate.php by Kellan Elliot-McCrea <kellan@protest.net>
@@ -14,30 +15,24 @@
14 15 # - HTTP Navigator 2 by Keyvan Minoukadeh <keyvan@k1m.com>
15 16 # - Ultra-Liberal Feed Finder by Mark Pilgrim <mark@diveintomark.org>
16 17 # according to the terms of the GNU General Public License.
17 18 #
18 -# INSTALLATION: see readme.txt or <http://projects.radgeek.com/install>
19 +# INSTALLATION: see README.text or <http://projects.radgeek.com/install>
19 20 #
20 21 # USAGE: once FeedWordPress is installed, you manage just about everything from
21 -# the WordPress Dashboard, under the Syndication menu. To ensure that fresh
22 -# content is added as it becomes available, you can convince your contributors
23 -# to put your XML-RPC URI (if WordPress is installed at
22 +# the WordPress Dashboard, under Options --> Syndication or Links --> Syndicated
23 +# To ensure that fresh content is added as it becomes available, get your
24 +# contributors to put your XML-RPC URI (if WordPress is installed at
24 25 # <http://www.zyx.com/blog>, XML-RPC requests should be sent to
25 -# <http://www.zyx.com/blog/xmlrpc.php>), or update manually under the
26 -# Syndication menu, or set up automatic updates under Syndication --> Settings,
27 -# or use a cron job.
26 +# <http://www.zyx.com/blog/xmlrpc.php>), or see `update-feeds.php`
28 27
29 28 # -- Don't change these unless you know what you're doing...
30 29
31 -define ('FEEDWORDPRESS_VERSION', '2009.0612');
30 +define ('FEEDWORDPRESS_VERSION', '0.992');
32 31 define ('FEEDWORDPRESS_AUTHOR_CONTACT', 'http://radgeek.com/contact');
33 32 define ('DEFAULT_SYNDICATION_CATEGORY', 'Contributors');
34 33
35 -$feedwordpress_debug = get_option('feedwordpress_debug');
36 -if (is_string($feedwordpress_debug)) :
37 - $feedwordpress_debug = ($feedwordpress_debug == 'yes');
38 -endif;
39 -define ('FEEDWORDPRESS_DEBUG', $feedwordpress_debug);
34 +define ('FEEDWORDPRESS_DEBUG', false);
40 35
41 36 define ('FEEDWORDPRESS_CAT_SEPARATOR_PATTERN', '/[:\n]/');
42 37 define ('FEEDWORDPRESS_CAT_SEPARATOR', "\n");
43 38
@@ -44,15 +39,11 @@
44 39 define ('FEEDVALIDATOR_URI', 'http://feedvalidator.org/check.cgi');
45 40
46 41 define ('FEEDWORDPRESS_FRESHNESS_INTERVAL', 10*60); // Every ten minutes
47 42
48 -define ('FWP_SCHEMA_HAS_USERMETA', 2966);
49 43 define ('FWP_SCHEMA_20', 3308); // Database schema # for WP 2.0
50 44 define ('FWP_SCHEMA_21', 4772); // Database schema # for WP 2.1
51 45 define ('FWP_SCHEMA_23', 5495); // Database schema # for WP 2.3
52 -define ('FWP_SCHEMA_25', 7558); // Database schema # for WP 2.5
53 -define ('FWP_SCHEMA_26', 8201); // Database schema # for WP 2.6
54 -define ('FWP_SCHEMA_27', 9872); // Database schema # for WP 2.7
55 46
56 47 if (FEEDWORDPRESS_DEBUG) :
57 48 // Help us to pick out errors, if any.
58 49 ini_set('error_reporting', E_ALL & ~E_NOTICE);
@@ -90,10 +81,11 @@
90 81 require_once (ABSPATH . 'wp-admin/admin-db.php'); // for wp_insert_category
91 82 endif;
92 83 endif;
93 84
94 -require_once(dirname(__FILE__) . '/compatability.php'); // LEGACY API: Replicate or mock up functions for legacy support purposes
95 -require_once(dirname(__FILE__) . '/feedwordpresshtml.class.php');
85 +if (function_exists('wp_enqueue_script')) :
86 + wp_enqueue_script( 'ajaxcat' ); // Provides the handy-dandy new category text box
87 +endif;
96 88
97 89 // Magic quotes are just about the stupidest thing ever.
98 90 if (is_array($_POST)) :
99 91 $fwp_post = stripslashes_deep($_POST);
@@ -98,45 +90,9 @@
98 90 if (is_array($_POST)) :
99 91 $fwp_post = stripslashes_deep($_POST);
100 92 endif;
101 93
102 -// Get the path relative to the plugins directory in which FWP is stored
103 -preg_match (
104 - '|/wp-content/plugins/(.+)$|',
105 - dirname(__FILE__),
106 - $ref
107 -);
108 94
109 -if (isset($ref[1])) :
110 - $fwp_path = $ref[1];
111 -else : // Something went wrong. Let's just guess.
112 - $fwp_path = 'feedwordpress';
113 -endif;
114 -
115 -// If this is a FeedWordPress admin page, queue up scripts for AJAX functions that FWP uses
116 -// If it is a display page or a non-FeedWordPress admin page, don't.
117 -if (is_admin() and isset($_REQUEST['page']) and preg_match("|^{$fwp_path}/|", $_REQUEST['page'])) :
118 - if (function_exists('wp_enqueue_script')) :
119 - if (isset($wp_db_version) and $wp_db_version >= FWP_SCHEMA_25) :
120 - wp_enqueue_script('post'); // for magic tag and category boxes
121 - wp_enqueue_script('thickbox'); // for fold-up boxes
122 - wp_enqueue_script('admin-forms'); // for checkbox selection
123 - else :
124 - wp_enqueue_script( 'ajaxcat' ); // Provides the handy-dandy new category text box
125 - endif;
126 - endif;
127 - if (function_exists('wp_enqueue_style')) :
128 - if (fwp_test_wp_version(FWP_SCHEMA_25)) :
129 - wp_enqueue_style('dashboard');
130 - endif;
131 - endif;
132 - if (function_exists('wp_admin_css')) :
133 - if (fwp_test_wp_version(FWP_SCHEMA_25)) :
134 - wp_admin_css('css/dashboard');
135 - endif;
136 - endif;
137 -endif;
138 -
139 95 if (!FeedWordPress::needs_upgrade()) : // only work if the conditions are safe!
140 96
141 97 # Syndicated items are generally received in output-ready (X)HTML and
142 98 # should not be folded, crumpled, mutilated, or spindled by WordPress
@@ -153,10 +109,8 @@
153 109
154 110 add_filter('the_content', 'feedwordpress_preserve_syndicated_content', -10000);
155 111 add_filter('the_content', 'feedwordpress_restore_syndicated_content', 10000);
156 112
157 - add_action('atom_entry', 'feedwordpress_item_feed_data');
158 -
159 113 # Filter in original permalinks if the user wants that
160 114 add_filter('post_link', 'syndication_permalink', 1);
161 115
162 116 # WTF? By default, wp_insert_link runs incoming link_url and link_rss
@@ -167,11 +121,9 @@
167 121 remove_filter('pre_link_url', 'wp_filter_kses');
168 122
169 123 # Admin menu
170 124 add_action('admin_menu', 'fwp_add_pages');
171 - add_action('admin_notices', 'fwp_check_debug');
172 - add_action('admin_notices', 'fwp_check_magpie');
173 -
125 +
174 126 # Inbound XML-RPC update methods
175 127 add_filter('xmlrpc_methods', 'feedwordpress_xmlrpc_hook');
176 128
177 129 # Outbound XML-RPC ping reform
@@ -195,44 +147,13 @@
195 147 endif;
196 148
197 149 # Cron-less auto-update. Hooray!
198 150 add_action('init', 'feedwordpress_auto_update');
199 - add_action('init', 'feedwordpress_check_for_magpie_fix');
200 -
201 - # Default sanitizers
202 - add_filter('syndicated_item_content', array('SyndicatedPost', 'resolve_relative_uris'), 0, 2);
203 - add_filter('syndicated_item_content', array('SyndicatedPost', 'sanitize_content'), 0, 2);
204 -
205 151 else :
206 152 # Hook in the menus, which will just point to the upgrade interface
207 153 add_action('admin_menu', 'fwp_add_pages');
208 154 endif; // if (!FeedWordPress::needs_upgrade())
209 155
210 -function feedwordpress_check_for_magpie_fix () {
211 - if (isset($_POST['action']) and $_POST['action']=='fix_magpie_version') :
212 - FeedWordPressCompatibility::validate_http_request(/*action=*/ 'feedwordpress_fix_magpie', /*capability=*/ 'edit_files');
213 -
214 - $back_to = $_SERVER['REQUEST_URI'];
215 - if (isset($_POST['ignore'])) :
216 - // kill error message by telling it we ignored the upgrade request for this version
217 - update_option('feedwordpress_magpie_ignored_upgrade_to', EXPECTED_MAGPIE_VERSION);
218 - $ret = 'ignored';
219 - elseif (isset($_POST['upgrade'])) :
220 - $source = dirname(__FILE__)."/MagpieRSS-upgrade/rss.php";
221 - $destination = ABSPATH . WPINC . '/rss.php';
222 - $success = @copy($source, $destination);
223 - $ret = (int) $success;
224 - endif;
225 -
226 - if (strpos($back_to, '?')===false) : $sep = '?';
227 - else : $sep = '&';
228 - endif;
229 -
230 - header("Location: {$back_to}{$sep}feedwordpress_magpie_fix=".$ret);
231 - exit;
232 - endif;
233 -} /* feedwordpress_check_for_magpie_fix() */
234 -
235 156 function feedwordpress_auto_update () {
236 157 if (FeedWordPress::stale()) :
237 158 $feedwordpress =& new FeedWordPress;
238 159 $feedwordpress->update();
@@ -280,85 +201,84 @@
280 201 : implode(' and ', $mesg)));
281 202 }
282 203
283 204 ################################################################################
284 -## TEMPLATE API: functions to make your templates syndication-aware ############
205 +## LEGACY API: Replicate or mock up functions for legacy support purposes ######
285 206 ################################################################################
286 207
287 -function is_syndicated () { return (strlen(get_syndication_feed_id()) > 0); }
208 +if (!function_exists('get_option')) {
209 + function get_option ($option) {
210 + return get_settings($option);
211 + }
212 +}
213 +if (!function_exists('current_user_can')) {
214 + $legacy_capability_hack = true;
215 + function current_user_can ($task) {
216 + global $user_level;
288 217
289 -function get_syndication_source_link ($original = NULL) {
290 - if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
291 - endif;
218 + $can = false;
292 219
293 - if ($original) : $vals = get_post_custom_values('syndication_source_uri_original');
294 - else : $vals = array();
295 - endif;
296 -
297 - if (count($vals) == 0) : $vals = get_post_custom_values('syndication_source_uri');
298 - endif;
299 -
300 - if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
220 + // This is **not** a full replacement for current_user_can. It
221 + // is only for checking the capabilities we care about via the
222 + // WordPress 1.5 user levels.
223 + switch ($task) {
224 + case 'manage_options':
225 + $can = ($user_level >= 6);
226 + break;
227 + case 'manage_links':
228 + $can = ($user_level >= 5);
229 + break;
230 + } /* switch */
231 + return $can;
232 + }
233 +} else {
234 + $legacy_capability_hack = false;
235 +}
236 +if (!function_exists('sanitize_user')) {
237 + function sanitize_user ($text, $strict) {
238 + return $text; // Don't munge it if it wasn't munged going in...
239 + }
240 +}
241 +if (!function_exists('wp_insert_user')) {
242 + function wp_insert_user ($userdata) {
243 + #-- Help WordPress 1.5.x quack like a duck
244 + $login = $userdata['user_login'];
245 + $author = $userdata['display_name'];
246 + $nice_author = $userdata['user_nicename'];
247 + $email = $userdata['user_email'];
248 + $url = $userdata['user_url'];
301 249
302 - return $ret;
303 -} /* function get_syndication_source_link() */
250 + $wpdb->query (
251 + "INSERT INTO $wpdb->users
252 + SET
253 + ID='0',
254 + user_login='$login',
255 + user_firstname='$author',
256 + user_nickname='$author',
257 + user_nicename='$nice_author',
258 + user_description='$author',
259 + user_email='$email',
260 + user_url='$url'");
261 + $id = $wpdb->insert_id;
262 +
263 + return $id;
264 + }
265 +}
266 +################################################################################
267 +## TEMPLATE API: functions to make your templates syndication-aware ############
268 +################################################################################
304 269
305 -function the_syndication_source_link ($original = NULL) { echo get_syndication_source_link($original); }
270 +function is_syndicated () { return (strlen(get_syndication_feed_id()) > 0); }
306 271
307 -function get_syndication_source ($original = NULL) {
308 - if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
309 - endif;
272 +function the_syndication_source_link () { echo get_syndication_source_link(); }
273 +function get_syndication_source_link () { list($n) = get_post_custom_values('syndication_source_uri'); return $n; }
310 274
311 - if ($original) : $vals = get_post_custom_values('syndication_source_original');
312 - else : $vals = array();
313 - endif;
314 -
315 - if (count($vals) == 0) : $vals = get_post_custom_values('syndication_source');
316 - endif;
317 -
318 - if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
275 +function get_syndication_source () { list($n) = get_post_custom_values('syndication_source'); return $n; }
276 +function the_syndication_source () { echo get_syndication_source(); }
319 277
320 - return $ret;
321 -} /* function get_syndication_source() */
278 +function get_syndication_feed () { list($u) = get_post_custom_values('syndication_feed'); return $u; }
279 +function the_syndication_feed () { echo get_syndication_feed (); }
322 280
323 -function the_syndication_source ($original = NULL) { echo get_syndication_source($original); }
324 -
325 -function get_syndication_feed ($original = NULL) {
326 - if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
327 - endif;
328 -
329 - if ($original) : $vals = get_post_custom_values('syndication_feed_original');
330 - else : $vals = array();
331 - endif;
332 -
333 - if (count($vals) == 0) : $vals = get_post_custom_values('syndication_feed');
334 - endif;
335 -
336 - if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
337 -
338 - return $ret;
339 -} /* function get_syndication_feed() */
340 -
341 -function the_syndication_feed ($original = NULL) { echo get_syndication_feed ($original); }
342 -
343 -function get_syndication_feed_guid ($original = NULL) {
344 - if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
345 - endif;
346 -
347 - if ($original) : $vals = get_post_custom_values('syndication_source_id_original');
348 - else : $vals = array();
349 - endif;
350 -
351 - if (count($vals) == 0) : $vals = array(get_feed_meta('feed/id'));
352 - endif;
353 -
354 - if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
355 -
356 - return $ret;
357 -} /* function get_syndication_feed_guid () */
358 -
359 -function the_syndication_feed_guid ($original = NULL) { echo get_syndication_feed_guid($original); }
360 -
361 281 function get_syndication_feed_id () { list($u) = get_post_custom_values('syndication_feed_id'); return $u; }
362 282 function the_syndication_feed_id () { echo get_syndication_feed_id(); }
363 283
364 284 $feedwordpress_linkcache = array (); // only load links from database once
@@ -396,13 +316,9 @@
396 316
397 317 function feedwordpress_preserve_syndicated_content ($text) {
398 318 global $feedwordpress_the_syndicated_content;
399 319
400 - $globalExpose = (get_option('feedwordpress_formatting_filters') == 'yes');
401 - $localExpose = get_post_custom_values('_feedwordpress_formatting_filters');
402 - $expose = ($globalExpose or ((count($localExpose) > 0) and $localExpose[0]));
403 -
404 - if ( is_syndicated() and !$expose ) :
320 + if ( is_syndicated() ) :
405 321 $feedwordpress_the_syndicated_content = $text;
406 322 else :
407 323 $feedwordpress_the_syndicated_content = NULL;
408 324 endif;
@@ -418,34 +334,8 @@
418 334
419 335 return $text;
420 336 }
421 337
422 -function feedwordpress_item_feed_data () {
423 - // In a post context....
424 - if (is_syndicated()) :
425 -?>
426 -<source>
427 - <title><?php the_syndication_source(); ?></title>
428 - <link rel="alternate" type="text/html" href="<?php the_syndication_source_link(); ?>" />
429 - <link rel="self" href="<?php the_syndication_feed(); ?>" />
430 -<?php
431 - $id = get_syndication_feed_guid();
432 - if (strlen($id) > 0) :
433 -?>
434 - <id><?php print $id; ?></id>
435 -<?php
436 - endif;
437 - $updated = get_feed_meta('feed/updated');
438 - if (strlen($updated) > 0) : ?>
439 - <updated><?php print $updated; ?></updated>
440 -<?php
441 - endif;
442 -?>
443 -</source>
444 -<?php
445 - endif;
446 -}
447 -
448 338 function syndication_permalink ($permalink = '') {
449 339 if (get_option('feedwordpress_munge_permalink') != 'no'):
450 340 $uri = get_syndication_permalink();
451 341 return ((strlen($uri) > 0) ? $uri : $permalink);
@@ -454,146 +344,1248 @@
454 344 endif;
455 345 } // function syndication_permalink ()
456 346
457 347 ################################################################################
458 -## ADMIN MENU ADD-ONS: register Dashboard management pages #####################
348 +## UPGRADE INTERFACE: Have users upgrade DB from older versions of FWP #########
459 349 ################################################################################
460 350
351 +function fwp_upgrade_page () {
352 + if (isset($GLOBALS['fwp_post']['action']) and $GLOBALS['fwp_post']['action']=='Upgrade') :
353 + $ver = get_option('feedwordpress_version');
354 + if (get_option('feedwordpress_version') != FEEDWORDPRESS_VERSION) :
355 + echo "<div class=\"wrap\">\n";
356 + echo "<h2>Upgrading FeedWordPress...</h2>";
357 +
358 + $feedwordpress =& new FeedWordPress;
359 + $feedwordpress->upgrade_database();
360 + echo "<p><strong>Done!</strong> Upgraded database to version ".FEEDWORDPRESS_VERSION.".</p>\n";
361 + echo "<form action=\"\" method=\"get\">\n";
362 + echo "<div class=\"submit\"><input type=\"hidden\" name=\"page\" value=\"".basename(__FILE__)."\" />";
363 + echo "<input type=\"submit\" value=\"Continue &raquo;\" /></form></div>\n";
364 + echo "</div>\n";
365 + return;
366 + else :
367 + echo "<div class=\"updated\"><p>Already at version ".FEEDWORDPRESS_VERSION."!</p></div>";
368 + endif;
369 + endif;
370 +?>
371 +<div class="wrap">
372 +<h2>Upgrade FeedWordPress</h2>
373 +
374 +<p>It appears that you have installed FeedWordPress
375 +<?php echo FEEDWORDPRESS_VERSION; ?> as an upgrade to an existing installation of
376 +FeedWordPress. That's no problem, but you will need to take a minute out first
377 +to upgrade your database: some necessary changes in how the software keeps
378 +track of posts and feeds will cause problems such as duplicate posts and broken
379 +templates if we were to continue without the upgrade.</p>
380 +
381 +<p>Note that most of FeedWordPress's functionality is temporarily disabled
382 +until we have successfully completed the upgrade. Everything should begin
383 +working as normal again once the upgrade is complete. There's extraordinarily
384 +little chance of any damage as the result of the upgrade, but if you're paranoid
385 +like me you may want to back up your database before you proceed.</p>
386 +
387 +<p>This may take several minutes for a large installation.</p>
388 +
389 +<form action="" method="post">
390 +<div class="submit"><input type="submit" name="action" value="Upgrade" /></div>
391 +</form>
392 +</div>
393 +<?php
394 +} // function fwp_upgrade_page ()
395 +
396 +################################################################################
397 +## ADMIN MENU ADD-ONS: implement Dashboard management pages ####################
398 +################################################################################
399 +
461 400 function fwp_add_pages () {
462 - global $fwp_capability;
463 - global $fwp_path;
401 + global $legacy_capability_hack;
464 402
465 - $menu = array('Syndicated Sites', 'Syndication', $fwp_capability['manage_links'], $fwp_path.'/syndication.php', NULL);
466 - if (fwp_test_wp_version(FWP_SCHEMA_27)) :
467 - // add icon parameter
468 - $menu[] = WP_PLUGIN_URL.'/'.$fwp_path.'/feedwordpress-tiny.png';
403 + if ($legacy_capability_hack) :
404 + // old & busted: numeric user levels
405 + $manage_links = 5;
406 + $manage_options = 6;
407 + else :
408 + // new hotness: named capabilities
409 + $manage_links = 'manage_links';
410 + $manage_options = 'manage_options';
469 411 endif;
470 412
471 - if (fwp_test_wp_version(FWP_SCHEMA_26)) :
472 - $options = __('Settings');
473 - $longoptions = __('Syndication Settings');
474 - else :
475 - $options = __('Options');
476 - $longoptions = __('Syndication Options');
413 + //add_submenu_page('plugins.php', 'Akismet Configuration', 'Akismet Configuration', 'manage_options', 'syndication-manage-page', 'fwp_syndication_manage_page');
414 + add_menu_page('Syndicated Sites', 'Syndication', $manage_links, 'feedwordpress/'.basename(__FILE__), 'fwp_syndication_manage_page');
415 + add_submenu_page('feedwordpress/'.basename(__FILE__), 'Syndication Options', 'Options', $manage_options, 'feedwordpress/syndication-options.php');
416 + add_options_page('Syndication Options', 'Syndication', $manage_options, 'feedwordpress/syndication-options.php');
417 +} // function fwp_add_pages () */
418 +
419 +function fwp_category_box ($checked, $object) {
420 + global $wp_db_version;
421 +
422 + if (isset($wp_db_version) and $wp_db_version >= FWP_SCHEMA_20) : // WordPress 2.x
423 +?>
424 + <div id="poststuff">
425 +
426 + <div id="moremeta">
427 + <div id="grabit" class="dbx-group">
428 + <fieldset id="categorydiv" class="dbx-box">
429 + <h3 class="dbx-handle"><?php _e('Categories') ?></h3>
430 + <div class="dbx-content">
431 + <p style="font-size:smaller;font-style:bold;margin:0">Place <?php print $object; ?> under...</p>
432 + <p id="jaxcat"></p>
433 + <ul id="categorychecklist"><?php write_nested_categories($checked); ?></ul></div>
434 + </fieldset>
435 + </div>
436 + </div>
437 + </div>
438 +<?php
439 + else : // WordPress 1.5
440 +?>
441 + <fieldset id="categorydiv" style="width: 20%; margin-right: 2em">
442 + <legend><?php _e('Categories') ?></legend>
443 + <p style="font-size:smaller;font-style:bold;margin:0">Place <?php print $object; ?> under...</p>
444 + <div style="height: 20em"><?php write_nested_categories($checked); ?></div>
445 + </fieldset>
446 +<?php
477 447 endif;
448 +}
478 449
479 - call_user_func_array('add_menu_page', $menu);
480 - add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Posts', 'Posts', $fwp_capability['manage_options'], $fwp_path.'/posts-page.php');
481 - add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Authors', 'Authors', $fwp_capability['manage_options'], $fwp_path.'/authors-page.php');
482 - add_submenu_page($fwp_path.'/syndication.php', 'Categories & Tags', 'Categories & Tags', $fwp_capability['manage_options'], $fwp_path.'/categories-page.php');
483 - add_submenu_page($fwp_path.'/syndication.php', $longoptions, $options, $fwp_capability['manage_options'], $fwp_path.'/syndication-options.php');
450 +function update_feeds_mention ($feed) {
451 + echo "<li>Updating <cite>".$feed['link/name']."</cite> from &lt;<a href=\""
452 + .$feed['link/uri']."\">".$feed['link/uri']."</a>&gt; ...</li>\n";
453 + flush();
454 +}
484 455
485 - add_options_page($longoptions, 'Syndication', $fwp_capability['manage_options'], $fwp_path.'/syndication-options.php');
486 -} /* function fwp_add_pages () */
456 +function fwp_syndication_manage_page () {
457 + global $wpdb;
487 458
488 -function fwp_check_debug () {
489 - // This is a horrible fucking kludge that I have to do because the
490 - // admin notice code is triggered before the code that updates the
491 - // setting.
492 - if (isset($_POST['feedwordpress_debug'])) :
493 - $feedwordpress_debug = $_POST['feedwordpress_debug'];
494 - else :
495 - $feedwordpress_debug = get_option('feedwordpress_debug');
459 + if (FeedWordPress::needs_upgrade()) :
460 + fwp_upgrade_page();
461 + return;
496 462 endif;
497 - if ($feedwordpress_debug==='yes') :
463 +
498 464 ?>
499 - <div class="error">
500 -<p><strong>FeedWordPress warning.</strong> Debugging mode is <strong>ON</strong>.
501 -While it remains on, FeedWordPress displays many diagnostic error messages,
502 -warnings, and notices that are ordinarily suppressed, and also turns off all
503 -caching of feeds. Use with caution: this setting is absolutely inappropriate
504 -for a production server.</p>
505 - </div>
465 +<?php $cont = true;
466 +if (isset($_REQUEST['action'])):
467 + if ($_REQUEST['action'] == 'feedfinder') : $cont = fwp_feedfinder_page();
468 + elseif ($_REQUEST['action'] == 'switchfeed') : $cont = fwp_switchfeed_page();
469 + elseif ($_REQUEST['action'] == 'linkedit') : $cont = fwp_linkedit_page();
470 + elseif ($_REQUEST['action'] == 'Unsubscribe from Checked Links' or $_REQUEST['action'] == 'Unsubscribe') : $cont = fwp_multidelete_page();
471 + endif;
472 +endif;
473 +
474 +if ($cont):
475 +?>
506 476 <?php
477 + $links = FeedWordPress::syndicated_links();
478 +
479 + if (isset($_POST['update']) or isset($_POST['action']) or isset($_POST['update_uri'])) :
480 + $fwp_update_invoke = 'post';
481 + else :
482 + $fwp_update_invoke = 'get';
507 483 endif;
508 -} /* function fwp_check_debug () */
509 484
510 -define('EXPECTED_MAGPIE_VERSION', '2009.0613');
511 -function fwp_check_magpie () {
512 - if (isset($_REQUEST['feedwordpress_magpie_fix'])) :
513 - if ($_REQUEST['feedwordpress_magpie_fix']=='ignored') :
485 + $update_set = array();
486 + if (isset($_POST['link_ids']) and is_array($_POST['link_ids']) and ($_POST['action']=='Update Checked Links')) :
487 + $targets = $wpdb->get_results("
488 + SELECT * FROM $wpdb->links
489 + WHERE link_id IN (".implode(",",$_POST['link_ids']).")
490 + ");
491 + if (is_array($targets)) :
492 + foreach ($targets as $target) :
493 + $update_set[] = $target->link_rss;
494 + endforeach;
495 + else : // This should never happen
496 + FeedWordPress::critical_bug('fwp_syndication_manage_page::targets', $targets, __LINE__);
497 + endif;
498 + elseif (isset($_POST['update_uri'])) :
499 + $update_set[] = $_POST['update_uri'];
500 + endif;
501 +
502 + if ($fwp_update_invoke != 'get' and count($update_set) > 0) : // Only do things with side-effects for HTTP POST or command line
503 + $feedwordpress =& new FeedWordPress;
504 + add_action('feedwordpress_check_feed', 'update_feeds_mention');
505 +
506 + echo "<div class=\"updated\">\n";
507 + echo "<ul>\n";
508 + $tdelta = NULL;
509 + foreach ($update_set as $uri) :
510 + if ($uri == '*') : $uri = NULL; endif;
511 + $delta = $feedwordpress->update($uri);
512 + if (!is_null($delta)) :
513 + if (is_null($tdelta)) :
514 + $tdelta = $delta;
515 + else :
516 + $tdelta['new'] += $delta['new'];
517 + $tdelta['updated'] += $delta['updated'];
518 + endif;
519 + else :
520 + echo "<li><p><strong>Error:</strong> There was a problem updating <a href=\"$uri\">$uri</a></p></li>\n";
521 + endif;
522 + endforeach;
523 + echo "</ul>\n";
524 +
525 + if (!is_null($tdelta)) :
526 + $mesg = array();
527 + if (isset($delta['new'])) : $mesg[] = ' '.$tdelta['new'].' new posts were syndicated'; endif;
528 + if (isset($delta['updated'])) : $mesg[] = ' '.$tdelta['updated'].' existing posts were updated'; endif;
529 + echo "<p>Update complete.".implode(' and', $mesg)."</p>";
530 + echo "\n"; flush();
531 + endif;
532 + echo "</div> <!-- class=\"updated\" -->\n";
533 + endif;
534 +
535 + ?>
536 + <div class="wrap">
537 + <form action="" method="POST">
538 + <h2>Update feeds now</h2>
539 + <p>Check currently scheduled feeds for new and updated posts.</p>
540 +
541 +<?php if (!get_option('feedwordpress_automatic_updates')) : ?>
542 + <p><strong>Note:</strong> Automatic updates are currently turned
543 + <strong>off</strong>. New posts from your feeds will not be syndicated
544 + until you manually check for them here. You can turn on automatic
545 + updates under <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication
546 + Options</a>.</p>
547 +<?php endif; ?>
548 +
549 +
550 + <div class="submit"><input type="hidden" name="update_uri" value="*" /><input type="submit" name="update" value="Update" /></div>
551 + </form>
552 + </div> <!-- class="wrap" -->
553 +
554 + <form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
555 + <div class="wrap">
556 + <h2>Syndicated Sites</h2>
557 +<?php $alt_row = true;
558 + if ($links): ?>
559 +
560 +<table width="100%" cellpadding="3" cellspacing="3">
561 +<tr>
562 +<th width="20%"><?php _e('Name'); ?></th>
563 +<th width="40%"><?php _e('Feed'); ?></th>
564 +<th colspan="4"><?php _e('Action'); ?></th>
565 +</tr>
566 +
567 +<?php foreach ($links as $link):
568 + $alt_row = !$alt_row; ?>
569 +<tr<?php echo ($alt_row?' class="alternate"':''); ?>>
570 +<td><a href="<?php echo wp_specialchars($link->link_url, 'both'); ?>"><?php echo wp_specialchars($link->link_name, 'both'); ?></a></td>
571 +<?php
572 + if (strlen($link->link_rss) > 0):
573 + $caption='Switch Feed';
574 + $uri_bits = parse_url($link->link_rss);
575 + $uri_bits['host'] = preg_replace('/^www\./i', '', $uri_bits['host']);
576 + $display_uri =
577 + (isset($uri_bits['user'])?$uri_bits['user'].'@':'')
578 + .(isset($uri_bits['host'])?$uri_bits['host']:'')
579 + .(isset($uri_bits['port'])?':'.$uri_bits['port']:'')
580 + .(isset($uri_bits['path'])?$uri_bits['path']:'')
581 + .(isset($uri_bits['query'])?'?'.$uri_bits['query']:'');
582 + if (strlen($display_uri) > 32) : $display_uri = substr($display_uri, 0, 32).'&#8230;'; endif;
514 583 ?>
515 -<div class="updated fade">
516 -<p>O.K., we'll ignore the problem for now. FeedWordPress will not display any
517 -more error messages.</p>
518 -</div>
584 + <td>
585 + <strong><a href="<?php echo wp_specialchars($link->link_rss, 'both'); ?>"><?php echo wp_specialchars($display_uri, 'both'); ?></a></strong></td>
519 586 <?php
520 - elseif ((bool) $_REQUEST['feedwordpress_magpie_fix']) :
587 + else:
588 + $caption='Find Feed';
521 589 ?>
522 -<div class="updated fade">
523 -<p>Congratulations! Your MagpieRSS has been successfully upgraded to the version
524 -shipped with FeedWordPress.</p>
525 -</div>
590 + <td style="background-color:#FFFFD0"><p><strong>no
591 + feed assigned</strong></p></td>
526 592 <?php
527 - else :
528 - $source = dirname(__FILE__)."/MagpieRSS-upgrade/rss.php";
529 - $destination = ABSPATH . WPINC . '/rss.php';
530 - $cmd = "cp '".htmlspecialchars(addslashes($source))."' '".htmlspecialchars(addslashes($destination))."'";
531 - $cmd = wordwrap($cmd, /*width=*/ 75, /*break=*/ " \\\n\t");
593 + endif;
594 +?>
595 + <td><a href="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>&amp;link_id=<?php echo $link->link_id; ?>&amp;action=linkedit" class="edit"><?php _e('Edit')?></a></td>
596 + <td><a href="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>&amp;link_id=<?php echo $link->link_id; ?>&amp;action=feedfinder" class="edit"><?php echo $caption; ?></a></td>
597 + <td><a href="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>&amp;link_id=<?php echo $link->link_id; ?>&amp;action=Unsubscribe" class="delete"><?php _e('Unsubscribe'); ?></a></td>
598 + <td><input type="checkbox" name="link_ids[]" value="<?php echo $link->link_id; ?>" /></td>
599 +<?php
600 + echo "\n\t</tr>";
601 + endforeach;
602 + else:
603 +?>
532 604
605 +<p>There are no websites currently listed for syndication.</p>
606 +
607 +<?php endif; ?>
608 + </table>
609 +
610 + <br/><hr/>
611 + <div class="submit"><input type="submit" class="delete" name="action" value="Unsubscribe from Checked Links" />
612 + <input type="submit" name="action" value="Update Checked Links" /></div>
613 + </div> <!-- class="wrap" -->
614 + </form>
615 +
616 + <div class="wrap">
617 + <form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
618 + <h2>Add a new syndicated site:</h2>
619 + <div>
620 + <label for="add-uri">Website or newsfeed:</label>
621 + <input type="text" name="lookup" id="add-uri" value="URI" size="64" />
622 + <input type="hidden" name="action" value="feedfinder" />
623 + </div>
624 + <div class="submit"><input type="submit" value="Syndicate &raquo;" /></div>
625 + </form>
626 + </div> <!-- class="wrap" -->
627 +<?php
628 +endif;
629 +}
630 +
631 +function fwp_feedfinder_page () {
632 + global $wpdb;
633 +
634 + $lookup = (isset($_REQUEST['lookup'])?$_REQUEST['lookup']:NULL);
635 +
636 + if (isset($_REQUEST['link_id']) and ($_REQUEST['link_id']!=0)):
637 + $link_id = $_REQUEST['link_id'];
638 + if (!is_numeric($link_id)) : FeedWordPress::critical_bug('fwp_feedfinder_page::link_id', $link_id, __LINE__); endif;
639 +
640 + $link = $wpdb->get_row("SELECT * FROM $wpdb->links WHERE link_id='".$wpdb->escape($link_id)."'");
641 + if (is_object($link)):
642 + if (is_null($lookup)) $lookup = $link->link_url;
643 + $name = wp_specialchars($link->link_name, 'both');
644 + else:
645 + die (__("Cheatin' uh ?"));
646 + endif;
647 + else:
648 + $name = "New Syndicated Feed";
649 + $link_id = 0;
650 + endif;
533 651 ?>
534 -<div class="error">
535 -<p><strong>FeedWordPress was unable to automatically upgrade your copy of MagpieRSS.</strong></p>
536 -<p>It's likely that you need to change the file permissions on <code><?php print htmlspecialchars($source); ?></code>
537 -to allow FeedWordPress to overwrite it.</p>
538 -<p><strong>To perform the upgrade manually,</strong> you can
539 -use a SFTP or FTP client to upload a copy of <code>rss.php</code> from the
540 -<code>MagpieRSS-upgrades/</code> directory of your FeedWordPress archive so that
541 -it overwrites <code><?php print htmlspecialchars($destination); ?></code>. Or,
542 -if your web host provides shell access, you can issue the following command from
543 -a command prompt to perform the upgrade:</p>
544 -<pre>
545 -<samp>$</samp> <kbd><?php print $cmd; ?></kbd>
546 -</pre>
547 -<p><strong>If you've fixed the file permissions,</strong> you can try the
548 -automatic upgrade again.</p>
652 + <div class="wrap">
653 + <h2>Feed Finder: <?php echo $name; ?></h2>
654 +<?php
655 + $f =& new FeedFinder($lookup);
656 + $feeds = $f->find();
657 + if (count($feeds) > 0):
658 + foreach ($feeds as $key => $f):
659 + $rss = fetch_rss($f);
660 + if ($rss):
661 + $feed_title = isset($rss->channel['title'])?$rss->channel['title']:$rss->channel['link'];
662 + $feed_link = isset($rss->channel['link'])?$rss->channel['link']:'';
663 +?>
664 + <form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
665 + <fieldset style="clear: both">
666 + <legend><?php echo $rss->feed_type; ?> <?php echo $rss->feed_version; ?> feed</legend>
549 667
550 -<?php feedwordpress_upgrade_old_and_busted_buttons(); ?>
551 -</div>
668 + <?php if ($link_id===0): ?>
669 + <input type="hidden" name="feed_title" value="<?php echo wp_specialchars($feed_title, 'both'); ?>" />
670 + <input type="hidden" name="feed_link" value="<?php echo wp_specialchars($feed_link, 'both'); ?>" />
671 + <?php endif; ?>
672 +
673 + <input type="hidden" name="link_id" value="<?php echo $link_id; ?>" />
674 + <input type="hidden" name="feed" value="<?php echo wp_specialchars($f, 'both'); ?>" />
675 + <input type="hidden" name="action" value="switchfeed" />
676 +
677 + <div>
678 + <div style="float:right; background-color:#D0D0D0; color: black; width:45%; font-size:70%; border-left: 1px dotted #A0A0A0; padding-left: 0.5em; margin-left: 1.0em">
679 +<?php if (count($rss->items) > 0): ?>
680 + <?php $item = $rss->items[0]; ?>
681 + <h3>Sample Item</h3>
682 + <ul>
683 + <li><strong>Title:</strong> <a href="<?php echo $item['link']; ?>"><?php echo $item['title']; ?></a></li>
684 + <li><strong>Date:</strong> <?php echo isset($item['date_timestamp']) ? date('d-M-y g:i:s a', $item['date_timestamp']) : 'unknown'; ?></li>
685 + </ul>
686 + <div class="entry">
687 + <?php echo (isset($item['content']['encoded'])?$item['content']['encoded']:$item['description']); ?>
688 + </div>
689 +<?php else: ?>
690 + <h3>No Items</h3>
691 + <p>FeedWordPress found no posts on this feed.</p>
692 +<?php endif; ?>
693 + </div>
694 +
695 + <div>
696 + <h3>Feed Information</h3>
697 + <ul>
698 + <li><strong>Website:</strong> <a href="<?php echo $feed_link; ?>"><?php echo is_null($feed_title)?'<em>Unknown</em>':$feed_title; ?></a></li>
699 + <li><strong>Feed URI:</strong> <a href="<?php echo wp_specialchars($f, 'both'); ?>"><?php echo wp_specialchars($f, 'both'); ?></a> (<a title="Check feed &lt;<?php echo wp_specialchars($f, 'both'); ?>&gt; for validity" href="http://feedvalidator.org/check.cgi?url=<?php echo urlencode($f); ?>">validate</a>)</li>
700 + <li><strong>Encoding:</strong> <?php echo isset($rss->encoding)?wp_specialchars($rss->encoding, 'both'):"<em>Unknown</em>"; ?></li>
701 + <li><strong>Description:</strong> <?php echo isset($rss->channel['description'])?wp_specialchars($rss->channel['description'], 'both'):"<em>Unknown</em>"; ?></li>
702 + </ul>
703 + <div class="submit"><input type="submit" name="Use" value="&laquo; Use this feed" /></div>
704 + <div class="submit"><input type="submit" name="Cancel" value="&laquo; Cancel" /></div>
705 + </div>
706 + </div>
707 + </fieldset>
708 + </form>
709 +<?php endif;
710 + endforeach;
711 + else:
712 + echo "<p><strong>no feed found</strong></p>";
713 + endif;
714 +?>
715 + </div>
716 +
717 + <form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
718 + <div class="wrap">
719 + <h2>Use another feed</h2>
720 + <div><label>Feed:</label>
721 + <input type="text" name="lookup" value="URI" />
722 + <input type="hidden" name="link_id" value="<?php echo $link_id; ?>" />
723 + <input type="hidden" name="action" value="feedfinder" /></div>
724 + <div class="submit"><input type="submit" value="Use this feed &raquo;" /></div>
725 + </div>
726 + </form>
552 727 <?php
728 + return false; // Don't continue
729 +}
730 +
731 +function fwp_switchfeed_page () {
732 + global $wpdb, $wp_db_version;
733 +
734 + check_admin_referer();
735 + if (!isset($_REQUEST['Cancel'])):
736 + if (!current_user_can('manage_links')):
737 + die (__("Cheatin' uh ?"));
738 + elseif (isset($_REQUEST['link_id']) and ($_REQUEST['link_id']==0)):
739 + $link_id = FeedWordPress::syndicate_link($_REQUEST['feed_title'], $_REQUEST['feed_link'], $_REQUEST['feed']);
740 + if ($link_id): ?>
741 +<div class="updated"><p><a href="<?php echo $_REQUEST['feed_link']; ?>"><?php echo wp_specialchars($_REQUEST['feed_title'], 'both'); ?></a>
742 +has been added as a contributing site, using the newsfeed at &lt;<a href="<?php echo $_REQUEST['feed']; ?>"><?php echo wp_specialchars($_REQUEST['feed'], 'both'); ?></a>&gt;.</p></div>
743 +<?php else: ?>
744 +<div class="updated"><p>There was a problem adding the newsfeed. [SQL: <?php echo wp_specialchars(mysql_error(), 'both'); ?>]</p></div>
745 +<?php endif;
746 + elseif (isset($_REQUEST['link_id'])):
747 + // Update link_rss
748 + $result = $wpdb->query("
749 + UPDATE $wpdb->links
750 + SET
751 + link_rss = '".$wpdb->escape($_REQUEST['feed'])."'
752 + WHERE link_id = '".$wpdb->escape($_REQUEST['link_id'])."'
753 + ");
754 +
755 + if ($result):
756 + $result = $wpdb->get_row("
757 + SELECT link_name, link_url FROM $wpdb->links
758 + WHERE link_id = '".$wpdb->escape($_REQUEST['link_id'])."'
759 + ");
760 + ?>
761 +<div class="updated"><p>Feed for <a href="<?php echo $result->link_url; ?>"><?php echo wp_specialchars($result->link_name, 'both'); ?></a>
762 +updated to &lt;<a href="<?php echo $_REQUEST['feed']; ?>"><?php echo wp_specialchars($_REQUEST['feed'], 'both'); ?></a>&gt;.</p></div>
763 + <?php else: ?>
764 +<div class="updated"><p>Nothing was changed.</p></div>
765 + <?php endif;
553 766 endif;
767 + endif;
768 + return true; // Continue
769 +}
770 +
771 +function fwp_linkedit_page () {
772 + global $wpdb;
773 +
774 + check_admin_referer(); // Make sure we arrived here from the Dashboard
775 +
776 + $special_settings = array ( /* Regular expression syntax is OK here */
777 + 'cats',
778 + 'cat_split',
779 + 'hardcode name',
780 + 'hardcode url',
781 + 'hardcode description',
782 + 'hardcode categories', /* Deprecated */
783 + 'post status',
784 + 'comment status',
785 + 'ping status',
786 + 'unfamiliar author',
787 + 'unfamliar categories',
788 + 'map authors',
789 + 'update/.*',
790 + 'feed/.*',
791 + 'link/.*',
792 + );
793 +
794 + if (!current_user_can('manage_links')) :
795 + die (__("Cheatin' uh ?"));
796 + elseif (isset($_REQUEST['feedfinder'])) :
797 + return fwp_feedfinder_page(); // re-route to Feed Finder page
554 798 else :
555 - $magpie_version = FeedWordPress::magpie_version();
799 + $link_id = (int) $_REQUEST['link_id'];
800 + $link =& new SyndicatedLink($link_id);
556 801
557 - $ignored = get_option('feedwordpress_magpie_ignored_upgrade_to');
558 - if (EXPECTED_MAGPIE_VERSION != $magpie_version and EXPECTED_MAGPIE_VERSION != $ignored) :
559 - if (current_user_can('edit_files')) :
560 - $youAre = 'you are';
561 - $itIsRecommendedThatYou = 'It is <strong>strongly recommended</strong> that you';
802 + if ($link->found()) :
803 + if (isset($GLOBALS['fwp_post']['save'])) :
804 + $alter = array ();
805 +
806 + $meta = $link->settings;
807 + //if (isset($meta['cats'])):
808 + // $meta['cats'] = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, $meta['cats']);
809 + //endif;
810 +
811 + // custom feed settings first
812 + foreach ($GLOBALS['fwp_post']['notes'] as $mn) :
813 + $mn['key0'] = trim($mn['key0']);
814 + $mn['key1'] = trim($mn['key1']);
815 + if (preg_match("\007^(("
816 + .implode(')|(',$special_settings)
817 + ."))$\007i",
818 + $mn['key1'])) :
819 + $mn['key1'] = 'user/'.$mn['key1'];
820 + endif;
821 +
822 + if (strlen($mn['key0']) > 0) :
823 + unset($meta[$mn['key0']]); // out with the old
824 + endif;
825 +
826 + if (($mn['action']=='update') and (strlen($mn['key1']) > 0)) :
827 + $meta[$mn['key1']] = $mn['value']; // in with the new
828 + endif;
829 + endforeach;
830 +
831 + // now stuff through the web form
832 + // hardcoded feed info
833 + if (isset($GLOBALS['fwp_post']['hardcode_name'])) :
834 + $meta['hardcode name'] = $GLOBALS['fwp_post']['hardcode_name'];
835 + if (FeedWordPress::affirmative($meta, 'hardcode name')) :
836 + $alter[] = "link_name = '".$wpdb->escape($GLOBALS['fwp_post']['name'])."'";
837 + endif;
838 + endif;
839 + if (isset($GLOBALS['fwp_post']['hardcode_description'])) :
840 + $meta['hardcode description'] = $GLOBALS['fwp_post']['hardcode_description'];
841 + if (FeedWordPress::affirmative($meta, 'hardcode description')) :
842 + $alter[] = "link_description = '".$wpdb->escape($GLOBALS['fwp_post']['description'])."'";
843 + endif;
844 + endif;
845 + if (isset($GLOBALS['fwp_post']['hardcode_url'])) :
846 + $meta['hardcode url'] = $GLOBALS['fwp_post']['hardcode_url'];
847 + if (FeedWordPress::affirmative($meta, 'hardcode url')) :
848 + $alter[] = "link_url = '".$wpdb->escape($GLOBALS['fwp_post']['linkurl'])."'";
849 + endif;
850 + endif;
851 +
852 + // Update scheduling
853 + if (isset($GLOBALS['fwp_post']['update_schedule'])) :
854 + $meta['update/hold'] = $GLOBALS['fwp_post']['update_schedule'];
855 + endif;
856 +
857 + // Categories
858 + if (isset($GLOBALS['fwp_post']['post_category'])) :
859 + $meta['cats'] = array();
860 + foreach ($GLOBALS['fwp_post']['post_category'] as $cat_id) :
861 + $meta['cats'][] = '{#'.$cat_id.'}';
862 + endforeach;
863 + else :
864 + unset($meta['cats']);
865 + endif;
866 +
867 + // Post status, comment status, ping status
868 + foreach (array('post', 'comment', 'ping') as $what) :
869 + $sfield = "feed_{$what}_status";
870 + if (isset($GLOBALS['fwp_post'][$sfield])) :
871 + if ($GLOBALS['fwp_post'][$sfield]=='site-default') :
872 + unset($meta["{$what} status"]);
873 + else :
874 + $meta["{$what} status"] = $GLOBALS['fwp_post'][$sfield];
875 + endif;
876 + endif;
877 + endforeach;
878 +
879 + // Unfamiliar author, unfamiliar categories
880 + foreach (array("author", "category") as $what) :
881 + $sfield = "unfamiliar_{$what}";
882 + if (isset($GLOBALS['fwp_post'][$sfield])) :
883 + if ('site-default'==$GLOBALS['fwp_post'][$sfield]) :
884 + unset($meta["unfamiliar {$what}"]);
885 + elseif ('newuser'==$GLOBALS['fwp_post'][$sfield]) :
886 + $newuser_name = trim($GLOBALS['fwp_post']["{$sfield}_newuser"]);
887 + if (strlen($newuser_name) > 0) :
888 + $userdata = array();
889 + $userdata['ID'] = NULL;
890 +
891 + $userdata['user_login'] = sanitize_user($newuser_name);
892 + $userdata['user_login'] = apply_filters('pre_user_login', $userdata['user_login']);
893 +
894 + $userdata['user_nicename'] = sanitize_title($newuser_name);
895 + $userdata['user_nicename'] = apply_filters('pre_user_nicename', $userdata['user_nicename']);
896 +
897 + $userdata['display_name'] = $wpdb->escape($newuser_name);
898 +
899 + $newuser_id = wp_insert_user($userdata);
900 + if (is_numeric($newuser_id)) :
901 + $meta["unfamiliar {$what}"] = $newuser_id;
902 + else :
903 + // TODO: Add some error detection and reporting
904 + endif;
905 + else :
906 + // TODO: Add some error reporting
907 + endif;
908 + else :
909 + $meta["unfamiliar {$what}"] = $GLOBALS['fwp_post'][$sfield];
910 + endif;
911 + endif;
912 + endforeach;
913 +
914 + // Handle author mapping rules
915 + if (isset($GLOBALS['fwp_post']['author_rules_name']) and isset($GLOBALS['fwp_post']['author_rules_action'])) :
916 + unset($meta['map authors']);
917 + foreach ($GLOBALS['fwp_post']['author_rules_name'] as $key => $name) :
918 + // Normalize for case and whitespace
919 + $name = strtolower(trim($name));
920 + $author_action = strtolower(trim($GLOBALS['fwp_post']['author_rules_action'][$key]));
921 +
922 + if (strlen($name) > 0) :
923 + if ('newuser' == $author_action) :
924 + $newuser_name = trim($GLOBALS['fwp_post']['author_rules_newuser'][$key]);
925 + if (strlen($newuser_name) > 0) :
926 + $userdata = array();
927 + $userdata['ID'] = NULL;
928 +
929 + $userdata['user_login'] = sanitize_user($newuser_name);
930 + $userdata['user_login'] = apply_filters('pre_user_login', $userdata['user_login']);
931 +
932 + $userdata['user_nicename'] = sanitize_title($newuser_name);
933 + $userdata['user_nicename'] = apply_filters('pre_user_nicename', $userdata['user_nicename']);
934 +
935 + $userdata['display_name'] = $wpdb->escape($newuser_name);
936 +
937 + $newuser_id = wp_insert_user($userdata);
938 + if (is_numeric($newuser_id)) :
939 + $meta['map authors']['name'][$name] = $newuser_id;
940 + else :
941 + // TODO: Add some error detection and reporting
942 + endif;
943 + else :
944 + // TODO: Add some error reporting
945 + endif;
946 + else :
947 + $meta['map authors']['name'][$name] = $author_action;
948 + endif;
949 + endif;
950 + endforeach;
951 + endif;
952 +
953 + if (isset($GLOBALS['fwp_post']['add_author_rule_name']) and isset($GLOBALS['fwp_post']['add_author_rule_action'])) :
954 + $name = strtolower(trim($GLOBALS['fwp_post']['add_author_rule_name']));
955 + $author_action = strtolower(trim($GLOBALS['fwp_post']['add_author_rule_action']));
956 + if (strlen($name) > 0) :
957 + if ('newuser' == $author_action) :
958 + $newuser_name = trim($GLOBALS['fwp_post']['add_author_rule_newuser']);
959 + if (strlen($newuser_name) > 0) :
960 + $userdata = array();
961 + $userdata['ID'] = NULL;
962 +
963 + $userdata['user_login'] = sanitize_user($newuser_name);
964 + $userdata['user_login'] = apply_filters('pre_user_login', $userdata['user_login']);
965 +
966 + $userdata['user_nicename'] = sanitize_title($newuser_name);
967 + $userdata['user_nicename'] = apply_filters('pre_user_nicename', $userdata['user_nicename']);
968 +
969 + $userdata['display_name'] = $wpdb->escape($newuser_name);
970 +
971 + $newuser_id = wp_insert_user($userdata);
972 + if (is_numeric($newuser_id)) :
973 + $meta['map authors']['name'][$name] = $newuser_id;
974 + else :
975 + // TODO: Add some error detection and reporting
976 + endif;
977 + else :
978 + // TODO: Add some error reporting
979 + endif;
980 + else :
981 + $meta['map authors']['name'][$name] = $author_action;
982 + endif;
983 + endif;
984 + endif;
985 +
986 + if (isset($GLOBALS['fwp_post']['cat_split'])) :
987 + if (strlen(trim($GLOBALS['fwp_post']['cat_split'])) > 0) :
988 + $meta['cat_split'] = trim($GLOBALS['fwp_post']['cat_split']);
989 + else :
990 + unset($meta['cat_split']);
991 + endif;
992 + endif;
993 +
994 + if (is_array($meta['cats'])) :
995 + $meta['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $meta['cats']);
996 + endif;
997 +
998 + // Collapse the author mapping rule structure back into a flat string
999 + if (isset($meta['map authors'])) :
1000 + $ma = array();
1001 + foreach ($meta['map authors'] as $rule_type => $author_rules) :
1002 + foreach ($author_rules as $author_name => $author_action) :
1003 + $ma[] = $rule_type."\n".$author_name."\n".$author_action;
1004 + endforeach;
1005 + endforeach;
1006 + $meta['map authors'] = implode("\n\n", $ma);
1007 + endif;
1008 +
1009 + $notes = '';
1010 + foreach ($meta as $key => $value) :
1011 + $notes .= $key . ": ". addcslashes($value, "\0..\37".'\\') . "\n";
1012 + endforeach;
1013 + $alter[] = "link_notes = '".$wpdb->escape($notes)."'";
1014 +
1015 + $alter_set = implode(", ", $alter);
1016 +
1017 + // issue update query
1018 + $result = $wpdb->query("
1019 + UPDATE $wpdb->links
1020 + SET $alter_set
1021 + WHERE link_id='$link_id'
1022 + ");
1023 + $updated_link = true;
1024 +
1025 + // reload link information from DB
1026 + $link =& new SyndicatedLink($link_id);
562 1027 else :
563 - $youAre = 'this site is';
564 - $itIsRecommendedThatYou = 'You may want to contact the administrator of the site; it is <strong>strongly recommended</strong> that they';
1028 + $updated_link = false;
565 1029 endif;
566 - print '<div class="error">';
1030 +
1031 + $db_link = $link->link;
1032 + $link_url = wp_specialchars($db_link->link_url, 1);
1033 + $link_name = wp_specialchars($db_link->link_name, 1);
1034 + $link_description = wp_specialchars($db_link->link_description, 'both');
1035 + $link_notes = wp_specialchars($db_link->link_notes, 'both');
1036 + $link_rss_uri = wp_specialchars($db_link->link_rss, 'both');
1037 +
1038 + $meta = $link->settings;
1039 + $post_status_global = get_option('feedwordpress_syndicated_post_status');
1040 + $comment_status_global = get_option('feedwordpress_syndicated_comment_status');
1041 + $ping_status_global = get_option('feedwordpress_syndicated_ping_status');
1042 +
1043 + $status['post'] = array('publish' => '', 'private' => '', 'draft' => '', 'site-default' => '');
1044 + $status['comment'] = array('open' => '', 'closed' => '', 'site-default' => '');
1045 + $status['ping'] = array('open' => '', 'closed' => '', 'site-default' => '');
1046 +
1047 + foreach (array('post', 'comment', 'ping') as $what) :
1048 + if (isset($meta["{$what} status"])) :
1049 + $status[$what][$meta["{$what} status"]] = ' checked="checked"';
1050 + else :
1051 + $status[$what]['site-default'] = ' checked="checked"';
1052 + endif;
1053 + endforeach;
1054 +
1055 + $unfamiliar['author'] = array ('create' => '','default' => '','filter' => '');
1056 + $unfamiliar['category'] = array ('create'=>'','default'=>'','filter'=>'');
1057 +
1058 + foreach (array('author', 'category') as $what) :
1059 + if (is_string($meta["unfamiliar {$what}"]) and
1060 + array_key_exists($meta["unfamiliar {$what}"], $unfamiliar[$what])) :
1061 + $key = $meta["unfamiliar {$what}"];
1062 + else:
1063 + $key = 'site-default';
1064 + endif;
1065 + $unfamiliar[$what][$key] = ' checked="checked"';
1066 + endforeach;
1067 +
1068 + $dogs = get_nested_categories(-1, 0);
1069 + if (is_array($meta['cats'])) :
1070 + $cats = array_map('strtolower',
1071 + array_map('trim',
1072 + $meta['cats']
1073 + ));
1074 + else:
1075 + $cats = array();
1076 + endif;
1077 +
1078 + foreach ($dogs as $tag => $dog) :
1079 + $found_by_name = in_array(strtolower(trim($dog['cat_name'])), $cats);
1080 +
1081 + if (isset($dog['cat_ID'])) : $dog['cat_id'] = $dog['cat_ID']; endif;
1082 + $found_by_id = in_array('{#'.trim($dog['cat_id']).'}', $cats);
1083 +
1084 + if ($found_by_name or $found_by_id) :
1085 + $dogs[$tag]['checked'] = true;
1086 + endif;
1087 + endforeach;
1088 + else :
1089 + die( __('Link not found.') );
1090 + endif;
1091 +
1092 + ?>
1093 +<script type="text/javascript">
1094 + function flip_hardcode (item) {
1095 + ed=document.getElementById('basics-'+item+'-edit');
1096 + view=document.getElementById('basics-'+item+'-view');
1097 +
1098 + o = document.getElementById('basics-hardcode-'+item);
1099 + if (o.value=='yes') { ed.style.display='inline'; view.style.display='none'; }
1100 + else { ed.style.display='none'; view.style.display='inline'; }
1101 + }
1102 + function flip_newuser (item) {
1103 + rollup=document.getElementById(item);
1104 + newuser=document.getElementById(item+'-newuser');
1105 + sitewide=document.getElementById(item+'-default');
1106 + if (rollup) {
1107 + if ('newuser'==rollup.value) {
1108 + if (newuser) newuser.style.display='block';
1109 + if (sitewide) sitewide.style.display='none';
1110 + } else if ('site-default'==rollup.value) {
1111 + if (newuser) newuser.style.display='none';
1112 + if (sitewide) sitewide.style.display='block';
1113 + } else {
1114 + if (newuser) newuser.style.display='none';
1115 + if (sitewide) sitewide.style.display='none';
1116 + }
1117 + }
1118 + }
1119 +</script>
1120 +
1121 +<?php if ($updated_link) : ?>
1122 +<div class="updated"><p>Syndicated feed settings updated.</p></div>
1123 +<?php endif; ?>
1124 +
1125 +<form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
1126 +<div class="wrap">
1127 +<input type="hidden" name="link_id" value="<?php echo $link_id; ?>" />
1128 +<input type="hidden" name="action" value="linkedit" />
1129 +<input type="hidden" name="save" value="link" />
1130 +
1131 +<h2>Edit a syndicated feed:</h2>
1132 +<fieldset class="options"><legend>Basics</legend>
1133 +<table class="editform" width="100%" cellspacing="2" cellpadding="5">
1134 +<tr>
1135 +<th scope="row" width="20%"><?php _e('Feed URI:') ?></th>
1136 +<td width="60%"><a href="<?php echo wp_specialchars($link_rss_uri, 'both'); ?>"><?php echo $link_rss_uri; ?></a>
1137 +(<a href="<?php echo FEEDVALIDATOR_URI; ?>?url=<?php echo urlencode($link_rss_uri); ?>"
1138 +title="Check feed &lt;<?php echo wp_specialchars($link_rss_uri, 'both'); ?>&gt; for validity">validate</a>)
1139 +</td>
1140 +<td width="20%"><input type="submit" name="feedfinder" value="switch &rarr;" style="font-size:smaller" /></td>
1141 +</tr>
1142 +<tr>
1143 +<th scope="row" width="20%"><?php _e('Link Name:') ?></th>
1144 +<td width="60%"><input type="text" id="basics-name-edit" name="name"
1145 +value="<?php echo $link_name; ?>" style="width: 95%" />
1146 +<span id="basics-name-view"><strong><?php echo $link_name; ?></strong></span>
1147 +</td>
1148 +<td>
1149 +<select id="basics-hardcode-name" onchange="flip_hardcode('name')" name="hardcode_name">
1150 +<option value="no" <?php echo $link->hardcode('name')?'':'selected="selected"'; ?>>update automatically</option>
1151 +<option value="yes" <?php echo $link->hardcode('name')?'selected="selected"':''; ?>>edit manually</option>
1152 +</select>
1153 +</td>
1154 +</tr>
1155 +<tr>
1156 +<th scope="row" width="20%"><?php _e('Short description:') ?></th>
1157 +<td width="60%">
1158 +<input id="basics-description-edit" type="text" name="description" value="<?php echo $link_description; ?>" style="width: 95%" />
1159 +<span id="basics-description-view"><strong><?php echo $link_description; ?></strong></span>
1160 +</td>
1161 +<td>
1162 +<select id="basics-hardcode-description" onchange="flip_hardcode('description')"
1163 +name="hardcode_description">
1164 +<option value="no" <?php echo $link->hardcode('description')?'':'selected="selected"'; ?>>update automatically</option>
1165 +<option value="yes" <?php echo $link->hardcode('description')?'selected="selected"':''; ?>>edit manually</option>
1166 +</select></td>
1167 +</tr>
1168 +<tr>
1169 +<th width="20%" scope="row"><?php _e('Homepage:') ?></th>
1170 +<td width="60%">
1171 +<input id="basics-url-edit" type="text" name="linkurl" value="<?php echo $link_url; ?>" style="width: 95%;" />
1172 +<a id="basics-url-view" href="<?php echo $link_url; ?>"><?php echo $link_url; ?></a></td>
1173 +<td>
1174 +<select id="basics-hardcode-url" onchange="flip_hardcode('url')" name="hardcode_url">
1175 +<option value="no"<?php echo $link->hardcode('url')?'':' selected="selected"'; ?>>update automatically</option>
1176 +<option value="yes"<?php echo $link->hardcode('url')?' selected="selected"':''; ?>>edit manually</option>
1177 +</select></td></tr>
1178 +
1179 +<tr>
1180 +<th width="20%"><?php _e('Last update') ?>:</th>
1181 +<td colspan="2"><?php
1182 + if (isset($meta['update/last'])) :
1183 + echo strftime('%x %X', $meta['update/last'])." ";
1184 + else :
1185 + echo " none yet";
1186 + endif;
1187 +?></td></tr>
1188 +<tr><th width="20%">Next update:</th>
1189 +<td colspan="2"><?php
1190 + $holdem = (isset($meta['update/hold']) ? $meta['update/hold'] : 'scheduled');
567 1191 ?>
568 -<p style="font-style: italic"><strong>FeedWordPress has detected that <?php print $youAre; ?> currently using a version of
569 -MagpieRSS other than the upgraded version that ships with this version of FeedWordPress.</strong></p>
570 -<ul>
571 -<li><strong>Currently running:</strong> MagpieRSS <?php print $magpie_version; ?></li>
572 -<li><strong>Version included with FeedWordPress <?php print FEEDWORDPRESS_VERSION; ?>:</strong> MagpieRSS <?php print EXPECTED_MAGPIE_VERSION; ?></li>
573 -</ul>
574 -<p><?php print $itIsRecommendedThatYou; ?> install the upgraded
575 -version of MagpieRSS supplied with FeedWordPress. The version of
576 -MagpieRSS that ships with WordPress is very old and buggy, and
577 -encounters a number of errors when trying to parse modern Atom
578 -and RSS feeds.</p>
1192 +<select name="update_schedule">
1193 +<option value="scheduled"<?php echo ($holdem=='scheduled')?' selected="selected"':''; ?>>update on schedule <?php
1194 + echo " (";
1195 + if (isset($meta['update/ttl']) and is_numeric($meta['update/ttl'])) :
1196 + if (isset($meta['update/timed']) and $meta['update/timed']=='automatically') :
1197 + echo 'next: ';
1198 + $next = $meta['update/last'] + ((int) $meta['update/ttl'] * 60);
1199 + if (strftime('%x', time()) != strftime('%x', $next)) :
1200 + echo strftime('%x', $next)." ";
1201 + endif;
1202 + echo strftime('%X', $meta['update/last']+((int) $meta['update/ttl']*60));
1203 + else :
1204 + echo "every ".$meta['update/ttl']." minute".(($meta['update/ttl']!=1)?"s":"");
1205 + endif;
1206 + else:
1207 + echo "next scheduled update";
1208 + endif;
1209 + echo ")";
1210 +?></option>
1211 +<option value="next"<?php echo ($holdem=='next')?' selected="selected"':''; ?>>update ASAP</option>
1212 +<option value="ping"<?php echo ($holdem=='ping')?' selected="selected"':''; ?>>update only when pinged</option>
1213 +</select></tr>
1214 +</table>
1215 +</fieldset>
1216 +
1217 +<script type="text/javascript">
1218 +flip_hardcode('name');
1219 +flip_hardcode('description');
1220 +flip_hardcode('url');
1221 +</script>
1222 +
1223 +<p class="submit">
1224 +<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1225 +</p>
1226 +
1227 +<fieldset class="options">
1228 +<legend>Syndicated Posts</legend>
1229 +
1230 +<?php fwp_category_box($dogs, 'all syndicated posts from this feed'); ?>
1231 +
1232 +<table class="editform" width="75%" cellspacing="2" cellpadding="5">
1233 +<tr><th width="27%" scope="row" style="vertical-align:top">Publication:</th>
1234 +<td width="73%" style="vertical-align:top"><ul style="margin:0; list-style:none">
1235 +<li><label><input type="radio" name="feed_post_status" value="site-default"
1236 +<?php echo $status['post']['site-default']; ?> /> Use site-wide setting from <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a>
1237 +(currently: <strong><?php echo ($post_status_global ? $post_status_global : 'publish'); ?></strong>)</label></li>
1238 +<li><label><input type="radio" name="feed_post_status" value="publish"
1239 +<?php echo $status['post']['publish']; ?> /> Publish posts from this feed immediately</label></li>
1240 +<li><label><input type="radio" name="feed_post_status" value="private"
1241 +<?php echo $status['post']['private']; ?> /> Hold posts from this feed as private posts</label></li>
1242 +<li><label><input type="radio" name="feed_post_status" value="draft"
1243 +<?php echo $status['post']['draft']; ?> /> Hold posts from this feed as drafts</label></li>
1244 +</ul></td>
1245 +</tr>
1246 +
1247 +<tr><th width="27%" scope="row" style="vertical-align:top">Comments:</th>
1248 +<td width="73%"><ul style="margin:0; list-style:none">
1249 +<li><label><input type="radio" name="feed_comment_status" value="site-default"
1250 +<?php echo $status['comment']['site-default']; ?> /> Use site-wide setting from <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a>
1251 +(currently: <strong><?php echo ($comment_status_global ? $comment_status_global : 'closed'); ?>)</strong></label></li>
1252 +<li><label><input type="radio" name="feed_comment_status" value="open"
1253 +<?php echo $status['comment']['open']; ?> /> Allow comments on syndicated posts from this feed</label></li>
1254 +<li><label><input type="radio" name="feed_comment_status" value="closed"
1255 +<?php echo $status['comment']['closed']; ?> /> Don't allow comments on syndicated posts from this feed</label></li>
1256 +</ul></td>
1257 +</tr>
1258 +
1259 +<tr><th width="27%" scope="row" style="vertical-align:top">Trackback and Pingback:</th>
1260 +<td width="73%"><ul style="margin:0; list-style:none">
1261 +<li><label><input type="radio" name="feed_ping_status" value="site-default"
1262 +<?php echo $status['ping']['site-default']; ?> /> Use site-wide setting from <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a>
1263 +(currently: <strong><?php echo ($ping_status_global ? $ping_status_global : 'closed'); ?>)</strong></label></li>
1264 +<li><label><input type="radio" name="feed_ping_status" value="open"
1265 +<?php echo $status['ping']['open']; ?> /> Accept pings on syndicated posts from this feed</label></li>
1266 +<li><label><input type="radio" name="feed_ping_status" value="closed"
1267 +<?php echo $status['ping']['closed']; ?> /> Don't accept pings on syndicated posts from this feed</label></li>
1268 +</ul></td>
1269 +</tr>
1270 +</table>
1271 +</fieldset>
1272 +
1273 +<p class="submit">
1274 +<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1275 +</p>
1276 +
1277 +<fieldset class="options">
1278 +<legend>Syndicated Authors</legend>
1279 +<?php $authorlist = fwp_author_list(); ?>
1280 +
1281 +<table>
1282 +<tr><th colspan="3" style="text-align: left; padding-top: 1.0em; border-bottom: 1px dotted black;">For posts by specific authors. Blank out a name to delete the rule.</th></tr>
1283 +
1284 +<?php if (isset($meta['map authors'])) : $i=0; foreach ($meta['map authors'] as $author_rules) : foreach ($author_rules as $author_name => $author_action) : $i++; ?>
1285 +<tr>
1286 + <th style="text-align: left">Posts by <input type="text" name="author_rules_name[]" value="<?php echo htmlspecialchars($author_name); ?>" /></th>
1287 + <td>
1288 + <select id="author-rules-<?php echo $i; ?>" name="author_rules_action[]" onchange="flip_newuser('author-rules-<?php echo $i; ?>');">
1289 + <?php foreach ($authorlist as $local_author_id => $local_author_name) : ?>
1290 + <option value="<?php echo $local_author_id; ?>"<?php if ($local_author_id==$author_action) : echo ' selected="selected"'; endif; ?>>are assigned to <?php echo $local_author_name; ?></option>
1291 + <?php endforeach; ?>
1292 + <option value="newuser">will be assigned to a new user...</option>
1293 + <option value="filter"<?php if ('filter'==$author_action) : echo ' selected="selected"'; endif; ?>>get filtered out</option>
1294 + </select>
1295 + </td>
1296 + <td><div id="author-rules-<?php echo $i; ?>-newuser">named <input type="text" name="author_rules_newuser[]" value="" /></div></td>
1297 +</tr>
1298 +<?php endforeach; endforeach; endif; ?>
1299 +
1300 +<tr><th colspan="3" style="text-align: left; padding-top: 1.0em; border-bottom: 1px dotted black;">Fill in to set up a new rule:</th></tr>
1301 +
1302 +<tr>
1303 + <th style="text-align: left">Posts by <input type="text" name="add_author_rule_name" /></th>
1304 + <td>
1305 + <select id="add-author-rule" name="add_author_rule_action" onchange="flip_newuser('add-author-rule');">
1306 + <?php foreach ($authorlist as $author_id => $author_name) : ?>
1307 + <option value="<?php echo $author_id; ?>">are assigned to <?php echo $author_name; ?></option>
1308 + <?php endforeach; ?>
1309 + <option value="newuser">will be assigned to a new user...</option>
1310 + <option value="filter">get filtered out</option>
1311 + </select>
1312 + </td>
1313 + <td><div id="add-author-rule-newuser">named <input type="text" name="add_author_rule_newuser" value="" /></div></td>
1314 +</tr>
1315 +
1316 +<tr><th colspan="3" style="text-align: left; padding-top: 1.0em; border-bottom: 1px dotted black;">For posts by authors that haven't been syndicated before:</th></tr>
1317 +<tr>
1318 + <th style="text-align: left">Posts by new authors</th>
1319 + <td>
1320 + <select id="unfamiliar-author" name="unfamiliar_author" onchange="flip_newuser('unfamiliar-author');">
1321 + <option value="site-default"<?php if (!isset($meta['unfamiliar author'])) : ?>selected="selected"<?php endif; ?>>are handled using site-wide settings</option>
1322 + <option value="create"<?php if ('create'==$meta['unfamiliar author']) : ?>selected="selected"<?php endif; ?>>create a new author account</option>
1323 + <?php foreach ($authorlist as $author_id => $author_name) : ?>
1324 + <option value="<?php echo $author_id; ?>"<?php if ($author_id==$meta['unfamiliar author']) : ?>selected="selected"<?php endif; ?>>are assigned to <?php echo $author_name; ?></option>
1325 + <?php endforeach; ?>
1326 + <option value="newuser">will be assigned to a new user...</option>
1327 + <option value="filter"<?php if ('filter'==$meta['unfamiliar author']) : ?>selected="selected"<?php endif; ?>>get filtered out</option>
1328 + </select>
1329 + </td>
1330 + <td>
1331 + <div id="unfamiliar-author-default">Site-wide settings can be set in <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a></div>
1332 + <div id="unfamiliar-author-newuser">named <input type="text" name="unfamiliar_author_newuser" value="" /></div>
1333 + </td>
1334 +</tr>
1335 +
1336 +</table>
1337 +</fieldset>
1338 +
1339 +<script>
1340 + flip_newuser('unfamiliar-author');
1341 +<?php for ($j=1; $j<=$i; $j++) : ?>
1342 + flip_newuser('author-rules-<?php echo $j; ?>');
1343 +<?php endfor; ?>
1344 + flip_newuser('add-author-rule');
1345 +</script>
1346 +
1347 +<p class="submit">
1348 +<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1349 +</p>
1350 +
1351 +<fieldset>
1352 +<legend>Advanced Feed Options</legend>
1353 +<table class="editform" width="100%" cellspacing="2" cellpadding="5">
1354 +
1355 +<tr>
1356 +<th width="20%" scope="row" style="vertical-align:top">Unfamiliar categories:</th>
1357 +<td width="80%"><ul style="margin: 0; list-style:none">
1358 +<li><label><input type="radio" name="unfamiliar_category" value="site-default"<?php echo $unfamiliar['category']['site-default']; ?> /> use site-wide setting from <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a>
1359 +(currently <strong><?php echo FeedWordPress::on_unfamiliar('category'); ?></strong>)</label></li>
1360 +<li><label><input type="radio" name="unfamiliar_category" value="create"<?php echo $unfamiliar['category']['create']; ?> /> create any categories the post is in</label></li>
1361 +<li><label><input type="radio" name="unfamiliar_category" value="default"<?php echo $unfamiliar['category']['default']; ?> /> don't create new categories</label></li>
1362 +<li><label><input type="radio" name="unfamiliar_category" value="filter"<?php echo $unfamiliar['category']['filter']; ?> /> don't create new categories and don't syndicate posts unless they match at least one familiar category</label></li>
1363 +</ul></td>
1364 +</tr>
1365 +
1366 +<tr>
1367 +<th width="20%" scope="row" style="vertical-align:top">Multiple categories:</th>
1368 +<td width="80%">
1369 +<input type="text" size="20" id="cat_split" name="cat_split" value="<?php if (isset($meta['cat_split'])) : echo htmlspecialchars($meta['cat_split']); endif; ?>" /><br/>
1370 +Enter a <a href="http://us.php.net/manual/en/reference.pcre.pattern.syntax.php">Perl-compatible regular expression</a> here if the feed provides multiple
1371 +categories in a single category element. The regular expression should match
1372 +the characters used to separate one category from the next. If the feed uses
1373 +spaces (like <a href="http://del.icio.us/">del.icio.us</a>), use the pattern "\s".
1374 +If the feed does not provide multiple categories in a single element, leave this
1375 +blank.</td>
1376 +</tr>
1377 +</table>
1378 +</fieldset>
1379 +
1380 +<p class="submit">
1381 +<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1382 +</p>
1383 +
1384 +<fieldset id="postcustom">
1385 +<legend>Custom Settings (for use in templates)</legend>
1386 +<div id="postcustomstuff">
1387 +<table id="meta-list" cellpadding="3">
1388 + <tr>
1389 + <th>Key</th>
1390 + <th>Value</th>
1391 + <th>Action</th>
1392 + </tr>
1393 +
579 1394 <?php
580 - feedwordpress_upgrade_old_and_busted_buttons();
581 - print '</div>';
1395 + $i = 0;
1396 + foreach ($meta as $key => $value) :
1397 + if (!preg_match("\007^((".implode(')|(', $special_settings)."))$\007i", $key)) :
1398 +?>
1399 + <tr style="vertical-align:top">
1400 + <th width="30%" scope="row"><input type="hidden" name="notes[<?php echo $i; ?>][key0]" value="<?php echo wp_specialchars($key, 'both'); ?>" />
1401 + <input id="notes-<?php echo $i; ?>-key" name="notes[<?php echo $i; ?>][key1]" value="<?php echo wp_specialchars($key, 'both'); ?>" /></th>
1402 + <td width="60%"><textarea rows="2" cols="40" id="notes-<?php echo $i; ?>-value" name="notes[<?php echo $i; ?>][value]"><?php echo wp_specialchars($value, 'both'); ?></textarea></td>
1403 + <td width="10%"><select name="notes[<?php echo $i; ?>][action]">
1404 + <option value="update">save changes</option>
1405 + <option value="delete">delete this setting</option>
1406 + </select></td>
1407 + </tr>
1408 +<?php
1409 + $i++;
582 1410 endif;
1411 + endforeach;
1412 +?>
1413 + <tr>
1414 + <th scope="row"><input type="text" size="10" name="notes[<?php echo $i; ?>][key1]" value="" /></th>
1415 + <td><textarea name="notes[<?php echo $i; ?>][value]" rows="2" cols="40"></textarea></td>
1416 + <td><em>add new setting...</em><input type="hidden" name="notes[<?php echo $i; ?>][action]" value="update" /></td>
1417 + </tr>
1418 +</table>
1419 +</fieldset>
1420 +
1421 +<p class="submit">
1422 +<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1423 +</p>
1424 +
1425 +</div>
1426 + <?php
583 1427 endif;
1428 + return false; // Don't continue
584 1429 }
585 1430
586 -function feedwordpress_upgrade_old_and_busted_buttons() {
587 - if (current_user_can('edit_files')) :
1431 +function fwp_author_list () {
1432 + global $wpdb;
1433 + $ret = array();
1434 + $users = $wpdb->get_results("SELECT * FROM $wpdb->users ORDER BY display_name");
1435 + if (is_array($users)) :
1436 + foreach ($users as $user) :
1437 + $id = (int) $user->ID;
1438 + $ret[$id] = $user->display_name;
1439 + endforeach;
1440 + endif;
1441 + return $ret;
1442 +}
1443 +
1444 +function fwp_multidelete_page () {
1445 + global $wpdb;
1446 +
1447 + check_admin_referer(); // Make sure the referers are kosher
1448 +
1449 + $link_ids = (isset($_REQUEST['link_ids']) ? $_REQUEST['link_ids'] : array());
1450 + if (isset($_REQUEST['link_id'])) : array_push($link_ids, $_REQUEST['link_id']); endif;
1451 +
1452 + if (!current_user_can('manage_links')):
1453 + die (__("Cheatin' uh ?"));
1454 + elseif (isset($GLOBALS['fwp_post']['confirm']) and $GLOBALS['fwp_post']['confirm']=='Delete'):
1455 + foreach ($GLOBALS['fwp_post']['link_action'] as $link_id => $what) :
1456 + $do_it[$what][] = $link_id;
1457 + endforeach;
1458 +
1459 + $alter = array();
1460 + if (count($do_it['hide']) > 0) :
1461 + $hidem = "(".implode(', ', $do_it['hide']).")";
1462 + $alter[] = "
1463 + UPDATE $wpdb->links
1464 + SET link_visible = 'N'
1465 + WHERE link_id IN {$hidem}
1466 + ";
1467 + endif;
1468 +
1469 + if (count($do_it['nuke']) > 0) :
1470 + $nukem = "(".implode(', ', $do_it['nuke']).")";
1471 +
1472 + // Make a list of the items syndicated from this feed...
1473 + $post_ids = $wpdb->get_col("
1474 + SELECT post_id FROM $wpdb->postmeta
1475 + WHERE meta_key = 'syndication_feed_id'
1476 + AND meta_value IN {$nukem}
1477 + ");
1478 +
1479 + // ... and kill them all
1480 + if (count($post_ids) > 0) :
1481 + foreach ($post_ids as $post_id) :
1482 + wp_delete_post($post_id);
1483 + endforeach;
1484 + endif;
1485 +
1486 + $alter[] = "
1487 + DELETE FROM $wpdb->links
1488 + WHERE link_id IN {$nukem}
1489 + ";
1490 + endif;
1491 +
1492 + if (count($do_it['delete']) > 0) :
1493 + $deletem = "(".implode(', ', $do_it['delete']).")";
1494 +
1495 + // Make the items syndicated from this feed appear to be locally-authored
1496 + $alter[] = "
1497 + DELETE FROM $wpdb->postmeta
1498 + WHERE meta_key = 'syndication_feed_id'
1499 + AND meta_value IN {$deletem}
1500 + ";
1501 +
1502 + // ... and delete the links themselves.
1503 + $alter[] = "
1504 + DELETE FROM $wpdb->links
1505 + WHERE link_id IN {$deletem}
1506 + ";
1507 + endif;
1508 +
1509 + $errs = array(); $success = array ();
1510 + foreach ($alter as $sql) :
1511 + $result = $wpdb->query($sql);
1512 + if (!$result):
1513 + $errs[] = mysql_error();
1514 + endif;
1515 + endforeach;
1516 +
1517 + if (count($alter) > 0) :
1518 + echo "<div class=\"updated\">\n";
1519 + if (count($errs) > 0) :
1520 + echo "There were some problems processing your ";
1521 + echo "unsubscribe request. [SQL: ".implode('; ', $errs)."]";
1522 + else :
1523 + echo "Your unsubscribe request(s) have been processed.";
1524 + endif;
1525 + echo "</div>\n";
1526 + endif;
1527 +
1528 + return true; // Continue on to Syndicated Sites listing
1529 + else :
1530 + $targets = $wpdb->get_results("
1531 + SELECT * FROM $wpdb->links
1532 + WHERE link_id IN (".implode(",",$link_ids).")
1533 + ");
588 1534 ?>
589 -<form action="" method="post"><div>
590 -<?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_fix_magpie'); ?>
591 -<input type="hidden" name="action" value="fix_magpie_version" />
592 -<input class="button-secondary" type="submit" name="ignore" value="<?php _e('Ignore this problem'); ?>" />
593 -<input class="button-primary" type="submit" name="upgrade" value="<?php _e('Upgrade'); ?>" />
594 -</div></form>
1535 +<form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
1536 +<div class="wrap">
1537 +<input type="hidden" name="action" value="Unsubscribe" />
1538 +<input type="hidden" name="confirm" value="Delete" />
1539 +
1540 +<h2>Unsubscribe from Syndicated Links:</h2>
1541 +<?php foreach ($targets as $link) :
1542 + $link_url = wp_specialchars($link->link_url, 1);
1543 + $link_name = wp_specialchars($link->link_name, 1);
1544 + $link_description = wp_specialchars($link->link_description, 'both');
1545 + $link_rss = wp_specialchars($link->link_rss, 'both');
1546 +?>
1547 +<fieldset>
1548 +<legend><?php echo $link_name; ?></legend>
1549 +<table class="editform" width="100%" cellspacing="2" cellpadding="5">
1550 +<tr><th scope="row" width="20%"><?php _e('Feed URI:') ?></th>
1551 +<td width="80%"><a href="<?php echo $link_rss; ?>"><?php echo $link_rss; ?></a></td></tr>
1552 +<tr><th scope="row" width="20%"><?php _e('Short description:') ?></th>
1553 +<td width="80%"><?php echo $link_description; ?></span></td></tr>
1554 +<tr><th width="20%" scope="row"><?php _e('Homepage:') ?></th>
1555 +<td width="80%"><a href="<?php echo $link_url; ?>"><?php echo $link_url; ?></a></td></tr>
1556 +<tr style="vertical-align:top"><th width="20%" scope="row">Subscription <?php _e('Options') ?>:</th>
1557 +<td width="80%"><ul style="margin:0; padding: 0; list-style: none">
1558 +<li><input type="radio" id="hide-<?php echo $link->link_id; ?>"
1559 +name="link_action[<?php echo $link->link_id; ?>]" value="hide" />
1560 +<label for="hide-<?php echo $link->link_id; ?>">Turn off the subscription for this
1561 +syndicated link<br/><span style="font-size:smaller">(Keep the feed information
1562 +and all the posts from this feed in the database, but don't syndicate any
1563 +new posts from the feed.)</span></label></li>
1564 +<li><input type="radio" id="nuke-<?php echo $link->link_id; ?>"
1565 +name="link_action[<?php echo $link->link_id; ?>]" value="nuke" />
1566 +<label for="nuke-<?php echo $link->link_id; ?>">Delete this syndicated link and all the
1567 +posts that were syndicated from it</label></li>
1568 +<li><input type="radio" id="delete-<?php echo $link->link_id; ?>"
1569 +name="link_action[<?php echo $link->link_id; ?>]" value="delete" />
1570 +<label for="delete-<?php echo $link->link_id; ?>">Delete this syndicated link, but
1571 +<em>keep</em> posts that were syndicated from it (as if they were authored
1572 +locally).</label></li>
1573 +<li><input type="radio" id="nothing-<?php echo $link->link_id; ?>"
1574 +name="link_action[<?php echo $link->link_id; ?>]" value="nothing" />
1575 +<label for="nothing-<?php echo $link->link_id; ?>">Keep this feed as it is. I changed
1576 +my mind.</label></li>
1577 +</ul>
1578 +</table>
1579 +</fieldset>
1580 +<?php endforeach; ?>
1581 +
1582 +<div class="submit">
1583 +<input class="delete" type="submit" name="submit" value="<?php _e('Unsubscribe from selected feeds &raquo;') ?>" />
1584 +</div>
1585 +</div>
595 1586 <?php
1587 + return false; // Don't continue on to Syndicated Sites listing
596 1588 endif;
597 1589 }
598 1590
599 1591 ################################################################################
@@ -750,9 +1742,9 @@
750 1742 #
751 1743 # * Updates to existing posts since the last poll are mirrored in the
752 1744 # WordPress store.
753 1745 #
754 - function update ($uri = null, $crash_ts = null) {
1746 + function update ($uri = null) {
755 1747 global $wpdb;
756 1748
757 1749 if (FeedWordPress::needs_upgrade()) : // Will make duplicate posts if we don't hold off
758 1750 return NULL;
@@ -765,28 +1757,11 @@
765 1757 endif;
766 1758
767 1759 do_action('feedwordpress_update', $uri);
768 1760
769 - if (is_null($crash_ts)) :
770 - $crash_dt = (int) get_option('feedwordpress_update_time_limit');
771 - if ($crash_dt > 0) :
772 - $crash_ts = time() + $crash_dt;
773 - else :
774 - $crash_ts = NULL;
775 - endif;
776 - endif;
777 -
778 - // Randomize order for load balancing purposes
779 - $feed_set = $this->feeds;
780 - shuffle($feed_set);
781 -
782 1761 // Loop through and check for new posts
783 1762 $delta = NULL;
784 - foreach ($feed_set as $feed) :
785 - if (!is_null($crash_ts) and (time() > $crash_ts)) : // Check whether we've exceeded the time limit
786 - break;
787 - endif;
788 -
1763 + foreach ($this->feeds as $feed) :
789 1764 $pinged_that = (is_null($uri) or in_array($uri, array($feed->uri(), $feed->homepage())));
790 1765
791 1766 if (!is_null($uri)) : // A site-specific ping always updates
792 1767 $timely = true;
@@ -799,12 +1774,9 @@
799 1774 endif;
800 1775
801 1776 if ($pinged_that and $timely) :
802 1777 do_action('feedwordpress_check_feed', $feed->settings);
803 - $start_ts = time();
804 - $added = $feed->poll($crash_ts);
805 - do_action('feedwordpress_check_feed_complete', $feed->settings, $added, time() - $start_ts);
806 -
1778 + $added = $feed->poll();
807 1779 if (isset($added['new'])) : $delta['new'] += $added['new']; endif;
808 1780 if (isset($added['updated'])) : $delta['updated'] += $added['updated']; endif;
809 1781 endif;
810 1782 endforeach;
@@ -862,9 +1834,9 @@
862 1834 if (function_exists('wp_insert_link')) { // WordPress 2.x
863 1835 $link_id = wp_insert_link(array(
864 1836 "link_name" => $name,
865 1837 "link_url" => $uri,
866 - "link_category" => (fwp_test_wp_version(0, FWP_SCHEMA_21) ? $cat_id : array($cat_id)),
1838 + "link_category" => array($cat_id),
867 1839 "link_rss" => $rss
868 1840 ));
869 1841 } else { // WordPress 1.5.x
870 1842 $result = $wpdb->query("
@@ -880,20 +1852,17 @@
880 1852 return $link_id;
881 1853 } // function FeedWordPress::syndicate_link()
882 1854
883 1855 function on_unfamiliar ($what = 'author', $override = NULL) {
884 - $set = array(
885 - 'author' => array('create', 'default', 'filter'),
886 - 'category' => array('create', 'tag', 'default', 'filter'),
887 - );
888 -
1856 + $set = array('create', 'default', 'filter');
1857 +
889 1858 if (is_string($override)) :
890 1859 $ret = strtolower($override);
891 1860 endif;
892 1861
893 - if (!is_numeric($override) and !in_array($ret, $set[$what])) :
1862 + if (!is_numeric($override) and !in_array($ret, $set)) :
894 1863 $ret = get_option('feedwordpress_unfamiliar_'.$what);
895 - if (!is_numeric($ret) and !in_array($ret, $set[$what])) :
1864 + if (!is_numeric($ret) and !in_array($ret, $set)) :
896 1865 $ret = 'create';
897 1866 endif;
898 1867 endif;
899 1868
@@ -899,33 +1868,8 @@
899 1868
900 1869 return $ret;
901 1870 } // function FeedWordPress::on_unfamiliar()
902 1871
903 - function null_email_set () {
904 - $base = get_option('feedwordpress_null_email_set');
905 -
906 - if ($base===false) :
907 - $ret = array('noreply@blogger.com'); // default
908 - else :
909 - $ret = array_map('strtolower',
910 - array_map('trim', explode("\n", $base)));
911 - endif;
912 - $ret = apply_filters('syndicated_item_author_null_email_set', $ret);
913 - return $ret;
914 -
915 - } /* FeedWordPress::null_email_set () */
916 -
917 - function is_null_email ($email) {
918 - $ret = in_array(strtolower(trim($email)), FeedWordPress::null_email_set());
919 - $ret = apply_filters('syndicated_item_author_is_null_email', $ret, $email);
920 - return $ret;
921 - } /* FeedWordPress::is_null_email () */
922 -
923 - function use_aggregator_source_data () {
924 - $ret = get_option('feedwordpress_use_aggregator_source_data');
925 - return apply_filters('syndicated_post_use_aggregator_source_data', ($ret=='yes'));
926 - }
927 -
928 1872 function syndicated_links () {
929 1873 $contributors = FeedWordPress::link_category_id();
930 1874 if (function_exists('get_bookmarks')) :
931 1875 $links = get_bookmarks(array("category" => $contributors));
@@ -950,12 +1894,12 @@
950 1894 // WordPress 2.3 introduces a new taxonomy/term API
951 1895 if (function_exists('is_term')) :
952 1896 $cat_id = is_term($cat, 'link_category');
953 1897 // WordPress 2.1 and 2.2 use a common table for both link and post categories
954 - elseif (fwp_test_wp_version(FWP_SCHEMA_21, FWP_SCHEMA_23)) :
1898 + elseif (isset($wp_db_version) and ($wp_db_version >= FWP_SCHEMA_21 and $wp_db_version < FWP_SCHEMA_23) ) :
955 1899 $cat_id = $wpdb->get_var("SELECT cat_id FROM {$wpdb->categories} WHERE cat_name='$cat'");
956 1900 // WordPress 1.5 and 2.0.x have a separate table for link categories
957 - elseif (fwp_test_wp_version(0, FWP_SCHEMA_21)):
1901 + elseif (!isset($wp_db_version) or $wp_db_version < FWP_SCHEMA_21) :
958 1902 $cat_id = $wpdb->get_var("SELECT cat_id FROM {$wpdb->linkcategories} WHERE cat_name='$cat'");
959 1903 // This should never happen.
960 1904 else :
961 1905 FeedWordPress::critical_bug('FeedWordPress::link_category_id::wp_db_version', $wp_db_version, __LINE__);
@@ -968,12 +1912,12 @@
968 1912 if (function_exists('wp_insert_term')) :
969 1913 $term = wp_insert_term($cat, 'link_category');
970 1914 $cat_id = $term['term_id'];
971 1915 // WordPress 2.1, 2.2 category API. By the way, why the fuck is this API function only available in a wp-admin module?
972 - elseif (function_exists('wp_insert_category') and !fwp_test_wp_version(FWP_SCHEMA_20, FWP_SCHEMA_21)) :
1916 + elseif (function_exists('wp_insert_category')) :
973 1917 $cat_id = wp_insert_category(array('cat_name' => $cat));
974 1918 // WordPress 1.5 and 2.0.x
975 - elseif (fwp_test_wp_version(0, FWP_SCHEMA_21)) :
1919 + elseif (!isset($wp_db_version) or $wp_db_version < FWP_SCHEMA_21) :
976 1920 $result = $wpdb->query("
977 1921 INSERT INTO $wpdb->linkcategories
978 1922 SET
979 1923 cat_id = 0,
@@ -1083,23 +2027,8 @@
1083 2027 endswitch;
1084 2028 echo "<p>Upgrade complete. FeedWordPress is now ready to use again.</p>";
1085 2029 } /* FeedWordPress::upgrade_database() */
1086 2030
1087 - function create_guid_index () {
1088 - global $wpdb;
1089 -
1090 - $wpdb->query("
1091 - CREATE INDEX {$wpdb->posts}_guid_idx ON {$wpdb->posts}(guid)
1092 - ");
1093 - } /* FeedWordPress::create_guid_index () */
1094 -
1095 - function magpie_version () {
1096 - if (!defined('MAGPIE_VERSION')) : $magpie_version = $GLOBALS['wp_version'].'-default';
1097 - else : $magpie_version = MAGPIE_VERSION;
1098 - endif;
1099 - return $magpie_version;
1100 - }
1101 -
1102 2031 # Utility functions for handling text settings
1103 2032 function negative ($f, $setting) {
1104 2033 $nego = array ('n', 'no', 'f', 'false');
1105 2034 return (isset($f[$setting]) and in_array(strtolower($f[$setting]), $nego));
@@ -1114,29 +2043,18 @@
1114 2043 # Internal debugging functions
1115 2044 function critical_bug ($varname, $var, $line) {
1116 2045 global $wp_version;
1117 2046
1118 - if (defined('MAGPIE_VERSION')) : $mv = MAGPIE_VERSION;
1119 - else : $mv = 'WordPress '.$wp_version.' default.';
1120 - endif;
1121 -
1122 2047 echo '<p>There may be a bug in FeedWordPress. Please <a href="'.FEEDWORDPRESS_AUTHOR_CONTACT.'">contact the author</a> and paste the following information into your e-mail:</p>';
1123 2048 echo "\n<plaintext>";
1124 2049 echo "Triggered at line # ".$line."\n";
1125 2050 echo "FeedWordPress version: ".FEEDWORDPRESS_VERSION."\n";
1126 - echo "MagpieRSS version: {$mv}\n";
1127 - echo "WordPress version: {$wp_version}\n";
2051 + echo "WordPress version: $wp_version\n";
1128 2052 echo "PHP version: ".phpversion()."\n";
1129 2053 echo "\n";
1130 2054 echo $varname.": "; var_dump($var); echo "\n";
1131 2055 die;
1132 2056 }
1133 -
1134 - function noncritical_bug ($varname, $var, $line) {
1135 - if (FEEDWORDPRESS_DEBUG) : // halt only when we are doing debugging
1136 - FeedWordPress::critical_bug($varname, $var, $line);
1137 - endif;
1138 - }
1139 2057 } // class FeedWordPress
1140 2058
1141 2059 class SyndicatedPost {
1142 2060 var $item = null;
@@ -1145,12 +2063,18 @@
1145 2063 var $feed = null;
1146 2064 var $feedmeta = null;
1147 2065
1148 2066 var $post = array ();
2067 + var $_base = null;
1149 2068
1150 2069 var $_freshness = null;
1151 2070 var $_wp_id = null;
1152 2071
2072 + var $strip_attrs = array (
2073 + array('[a-z]+', 'style'),
2074 + array('[a-z]+', 'target'),
2075 + );
2076 +
1153 2077 function SyndicatedPost ($item, $link) {
1154 2078 global $wpdb;
1155 2079
1156 2080 $this->link = $link;
@@ -1181,20 +2105,18 @@
1181 2105 # That's deliberate. The escaping is done at the point
1182 2106 # of insertion, not here, to avoid double-escaping and
1183 2107 # to avoid screwing with syndicated_post filters
1184 2108
1185 - $this->post['post_title'] = apply_filters('syndicated_item_title', $this->item['title'], $this);
2109 + $this->post['post_title'] = $this->item['title'];
1186 2110
1187 - // This just gives us an alphanumeric representation of
2111 + // This just gives usan alphanumeric representation of
1188 2112 // the author. We will look up (or create) the numeric
1189 2113 // ID for the author in SyndicatedPost::add()
1190 - $this->post['named']['author'] = apply_filters('syndicated_item_author', $this->author(), $this);
2114 + $this->post['named']['author'] = $this->author();
1191 2115
1192 2116 # Identify content and sanitize it.
1193 2117 # ---------------------------------
1194 - if (isset($this->item['atom_content'])) :
1195 - $content = $this->item['atom_content'];
1196 - elseif (isset($this->item['xhtml']['body'])) :
2118 + if (isset($this->item['xhtml']['body'])) :
1197 2119 $content = $this->item['xhtml']['body'];
1198 2120 elseif (isset($this->item['xhtml']['div'])) :
1199 2121 $content = $this->item['xhtml']['div'];
1200 2122 elseif (isset($this->item['content']['encoded']) and $this->item['content']['encoded']):
@@ -1201,9 +2123,24 @@
1201 2123 $content = $this->item['content']['encoded'];
1202 2124 else:
1203 2125 $content = $this->item['description'];
1204 2126 endif;
1205 - $this->post['post_content'] = apply_filters('syndicated_item_content', $content, $this);
2127 +
2128 + # FeedWordPress used to resolve URIs relative to the
2129 + # feed URI. It now relies on the xml:base support
2130 + # baked in to the MagpieRSS upgrade. So all we do here
2131 + # now is to sanitize problematic attributes.
2132 + #
2133 + # This kind of sucks. I intend to replace it with
2134 + # lib_filter sometime soon.
2135 + foreach ($this->strip_attrs as $pair):
2136 + list($tag,$attr) = $pair;
2137 + $content = preg_replace (
2138 + ":(<$tag [^>]*)($attr=(\"[^\">]*\"|[^>\\s]+))([^>]*>):i",
2139 + "\\1\\4",
2140 + $content
2141 + );
2142 + endforeach;
1206 2143
1207 2144 # Identify and sanitize excerpt
1208 2145 $excerpt = NULL;
1209 2146 if ( isset($this->item['description']) and $this->item['description'] ) :
@@ -1213,10 +2150,11 @@
1213 2150 if (strlen($excerpt) > 255) :
1214 2151 $excerpt = substr($excerpt,0,252).'...';
1215 2152 endif;
1216 2153 endif;
1217 - $excerpt = apply_filters('syndicated_item_excerpt', $excerpt, $this);
1218 2154
2155 + $this->post['post_content'] = $content;
2156 +
1219 2157 if (!is_null($excerpt)):
1220 2158 $this->post['post_excerpt'] = $excerpt;
1221 2159 endif;
1222 2160
@@ -1224,11 +2162,11 @@
1224 2162 if (!$this->use_api('wp_insert_post')) :
1225 2163 $this->post['post_name'] = sanitize_title($this->post['post_title']);
1226 2164 endif;
1227 2165
1228 - $this->post['epoch']['issued'] = apply_filters('syndicated_item_published', $this->published(), $this);
1229 - $this->post['epoch']['created'] = apply_filters('syndicated_item_created', $this->created(), $this);
1230 - $this->post['epoch']['modified'] = apply_filters('syndicated_item_updated', $this->updated(), $this);
2166 + $this->post['epoch']['issued'] = $this->published();
2167 + $this->post['epoch']['created'] = $this->created();
2168 + $this->post['epoch']['modified'] = $this->updated();
1231 2169
1232 2170 // Dealing with timestamps in WordPress is so fucking fucked.
1233 2171 $offset = (int) get_option('gmt_offset') * 60 * 60;
1234 2172 $this->post['post_date'] = gmdate('Y-m-d H:i:s', $this->published() + $offset);
@@ -1241,67 +2179,35 @@
1241 2179 $this->post['comment_status'] = $this->link->syndicated_status('comment', 'closed');
1242 2180 $this->post['ping_status'] = $this->link->syndicated_status('ping', 'closed');
1243 2181
1244 2182 // Unique ID (hopefully a unique tag: URI); failing that, the permalink
1245 - $this->post['guid'] = apply_filters('syndicated_item_guid', $this->guid(), $this);
2183 + $this->post['guid'] = $this->guid();
1246 2184
1247 - // User-supplied custom settings to apply to each post. Do first so that FWP-generated custom settings will overwrite if necessary; thus preventing any munging
1248 - $default_custom_settings = get_option('feedwordpress_custom_settings');
1249 - if ($default_custom_settings) :
1250 - $default_custom_settings = unserialize($default_custom_settings);
1251 - endif;
1252 - if (!is_array($default_custom_settings)) :
1253 - $default_custom_settings = array();
1254 - endif;
1255 -
1256 - $custom_settings = $this->link->settings['postmeta'];
1257 - if ($custom_settings) :
1258 - $custom_settings = unserialize($custom_settings);
1259 - endif;
1260 - if (!is_array($custom_settings)) :
1261 - $custom_settings = array();
1262 - endif;
1263 - $this->post['meta'] = array_merge($default_custom_settings, $custom_settings);
1264 -
1265 2185 // RSS 2.0 / Atom 1.0 enclosure support
1266 2186 if ( isset($this->item['enclosure#']) ) :
1267 2187 for ($i = 1; $i <= $this->item['enclosure#']; $i++) :
1268 2188 $eid = (($i > 1) ? "#{$id}" : "");
1269 2189 $this->post['meta']['enclosure'][] =
1270 - apply_filters('syndicated_item_enclosure_url', $this->item["enclosure{$eid}@url"], $this)."\n".
1271 - apply_filters('syndicated_item_enclosure_length', $this->item["enclosure{$eid}@length"], $this)."\n".
1272 - apply_filters('syndicated_item_enclosure_type', $this->item["enclosure{$eid}@type"], $this);
2190 + $this->item["enclosure{$eid}@url"]."\n".
2191 + $this->item["enclosure{$eid}@length"]."\n".
2192 + $this->item["enclosure{$eid}@type"];
1273 2193 endfor;
1274 2194 endif;
1275 2195
1276 2196 // In case you want to point back to the blog this was syndicated from
1277 2197 if (isset($this->feed->channel['title'])) :
1278 - $this->post['meta']['syndication_source'] = apply_filters('syndicated_item_source_title', $this->feed->channel['title'], $this);
2198 + $this->post['meta']['syndication_source'] = $this->feed->channel['title'];
1279 2199 endif;
1280 -
1281 2200 if (isset($this->feed->channel['link'])) :
1282 - $this->post['meta']['syndication_source_uri'] = apply_filters('syndicated_item_source_link', $this->feed->channel['link'], $this);
2201 + $this->post['meta']['syndication_source_uri'] = $this->feed->channel['link'];
1283 2202 endif;
1284 2203
1285 - // Make use of atom:source data, if present in an aggregated feed
1286 - if (isset($this->item['source_title'])) :
1287 - $this->post['meta']['syndication_source_original'] = $this->item['source_title'];
1288 - endif;
1289 -
1290 - if (isset($this->item['source_link'])) :
1291 - $this->post['meta']['syndication_source_uri_original'] = $this->item['source_link'];
1292 - endif;
1293 -
1294 - if (isset($this->item['source_id'])) :
1295 - $this->post['meta']['syndication_source_id_original'] = $this->item['source_id'];
1296 - endif;
1297 -
1298 2204 // Store information on human-readable and machine-readable comment URIs
1299 2205 if (isset($this->item['comments'])) :
1300 - $this->post['meta']['rss:comments'] = apply_filters('syndicated_item_comments', $this->item['comments']);
2206 + $this->post['meta']['rss:comments'] = $this->item['comments'];
1301 2207 endif;
1302 2208 if (isset($this->item['wfw']['commentrss'])) :
1303 - $this->post['meta']['wfw:commentRSS'] = apply_filters('syndicated_item_commentrss', $this->item['wfw']['commentrss']);
2209 + $this->post['meta']['wfw:commentRSS'] = $this->item['wfw']['commentrss'];
1304 2210 endif;
1305 2211
1306 2212 // Store information to identify the feed that this came from
1307 2213 $this->post['meta']['syndication_feed'] = $this->feedmeta['link/uri'];
@@ -1306,21 +2212,14 @@
1306 2212 // Store information to identify the feed that this came from
1307 2213 $this->post['meta']['syndication_feed'] = $this->feedmeta['link/uri'];
1308 2214 $this->post['meta']['syndication_feed_id'] = $this->feedmeta['link/id'];
1309 2215
1310 - if (isset($this->item['source_link_self'])) :
1311 - $this->post['meta']['syndication_feed_original'] = $this->item['source_link_self'];
1312 - endif;
1313 -
1314 2216 // In case you want to know the external permalink...
1315 - $this->post['meta']['syndication_permalink'] = apply_filters('syndicated_item_link', $this->item['link']);
2217 + $this->post['meta']['syndication_permalink'] = $this->item['link'];
1316 2218
1317 - // Store a hash of the post content for checking whether something needs to be updated
1318 - $this->post['meta']['syndication_item_hash'] = $this->update_hash();
1319 -
1320 2219 // Feed-by-feed options for author and category creation
1321 2220 $this->post['named']['unfamiliar']['author'] = $this->feedmeta['unfamiliar author'];
1322 - $this->post['named']['unfamiliar']['category'] = $this->feedmeta['unfamiliar category'];
2221 + $this->post['named']['unfamiliar']['category'] = $this->feedmeta['unfamiliar categories'];
1323 2222
1324 2223 // Categories: start with default categories, if any
1325 2224 $fc = get_option("feedwordpress_syndication_cats");
1326 2225 if ($fc) :
@@ -1347,22 +2246,8 @@
1347 2246 $this->post['named']['category'][] = $cat;
1348 2247 endif;
1349 2248 endfor;
1350 2249 endif;
1351 - $this->post['named']['category'] = apply_filters('syndicated_item_categories', $this->post['named']['category'], $this);
1352 -
1353 - // Tags: start with default tags, if any
1354 - $ft = get_option("feedwordpress_syndication_tags");
1355 - if ($ft) :
1356 - $this->post['tags_input'] = explode(FEEDWORDPRESS_CAT_SEPARATOR, $ft);
1357 - else :
1358 - $this->post['tags_input'] = array();
1359 - endif;
1360 -
1361 - if (is_array($this->feedmeta['tags'])) :
1362 - $this->post['tags_input'] = array_merge($this->post['tags_input'], $this->feedmeta['tags']);
1363 - endif;
1364 -
1365 2250 endif;
1366 2251 } // SyndicatedPost::SyndicatedPost()
1367 2252
1368 2253 function filtered () {
@@ -1383,35 +2268,18 @@
1383 2268 SELECT id, guid, post_modified_gmt
1384 2269 FROM $wpdb->posts WHERE guid='$guid'
1385 2270 ");
1386 2271
2272 + preg_match('/([0-9]+)-([0-9]+)-([0-9]+) ([0-9]+):([0-9]+):([0-9]+)/', $result->post_modified_gmt, $backref);
2273 + $updated = gmmktime($backref[4], $backref[5], $backref[6], $backref[2], $backref[3], $backref[1]);
1387 2274 if (!$result) :
1388 2275 $this->_freshness = 2; // New content
1389 - else:
1390 - $stored_update_hashes = get_post_custom_values('syndication_item_hash', $result->id);
1391 - if (count($stored_update_hashes) > 0) :
1392 - $stored_update_hash = $stored_update_hashes[0];
1393 - $update_hash_changed = ($stored_update_hash != $this->update_hash());
1394 - else :
1395 - $update_hash_changed = false;
1396 - endif;
1397 -
1398 - preg_match('/([0-9]+)-([0-9]+)-([0-9]+) ([0-9]+):([0-9]+):([0-9]+)/', $result->post_modified_gmt, $backref);
1399 -
1400 - $last_rev_ts = gmmktime($backref[4], $backref[5], $backref[6], $backref[2], $backref[3], $backref[1]);
1401 - $updated_ts = $this->updated(/*fallback=*/ true, /*default=*/ NULL);
1402 - $updated = ((
1403 - !is_null($updated_ts)
1404 - and ($updated_ts > $last_rev_ts)
1405 - ) or $update_hash_changed);
1406 -
1407 - if ($updated) :
1408 - $this->_freshness = 1; // Updated content
1409 - $this->_wp_id = $result->id;
1410 - else :
1411 - $this->_freshness = 0; // Same old, same old
1412 - $this->_wp_id = $result->id;
1413 - endif;
2276 + elseif ($this->updated() > $updated) :
2277 + $this->_freshness = 1; // Updated content
2278 + $this->_wp_id = $result->id;
2279 + else :
2280 + $this->_freshness = 0; // Same old, same old
2281 + $this->_wp_id = $result->id;
1414 2282 endif;
1415 2283 endif;
1416 2284 return $this->_freshness;
1417 2285 }
@@ -1447,17 +2315,13 @@
1447 2315 endif;
1448 2316
1449 2317 if (!$this->filtered() and $freshness > 0) :
1450 2318 # -- Look up, or create, numeric ID for categories
1451 - list($pcats, $ptags) = $this->category_ids (
2319 + $this->post['post_category'] = $this->category_ids (
1452 2320 $this->post['named']['category'],
1453 - FeedWordPress::on_unfamiliar('category', $this->post['named']['unfamiliar']['category']),
1454 - /*tags_too=*/ true
2321 + FeedWordPress::on_unfamiliar('category', $this->post['named']['unfamiliar']['category'])
1455 2322 );
1456 -
1457 - $this->post['post_category'] = $pcats;
1458 - $this->post['tags_input'] = array_merge($this->post['tags_input'], $ptags);
1459 -
2323 +
1460 2324 if (is_null($this->post['post_category'])) :
1461 2325 // filter mode on, no matching categories; drop the post
1462 2326 $this->post = NULL;
1463 2327 else :
@@ -1503,278 +2367,152 @@
1503 2367 } // function SyndicatedPost::store ()
1504 2368
1505 2369 function insert_new () {
1506 2370 global $wpdb, $wp_db_version;
2371 +
2372 + // Why the fuck doesn't wp_insert_post already do this?
2373 + foreach ($this->post as $key => $value) :
2374 + if (is_string($value)) :
2375 + $dbpost[$key] = $wpdb->escape($value);
2376 + else :
2377 + $dbpost[$key] = $value;
2378 + endif;
2379 + endforeach;
1507 2380
1508 - $dbpost = $this->normalize_post(/*new=*/ true);
1509 - if (!is_null($dbpost)) :
1510 - if ($this->use_api('wp_insert_post')) :
1511 - $dbpost['post_pingback'] = false; // Tell WP 2.1 and 2.2 not to process for pingbacks
2381 + if ($this->use_api('wp_insert_post')) :
2382 + $dbpost['post_pingback'] = false; // Tell WP 2.1 and 2.2 not to process for pingbacks
2383 + $this->_wp_id = wp_insert_post($dbpost);
2384 +
2385 + // This should never happen.
2386 + if (!is_numeric($this->_wp_id) or ($this->_wp_id == 0)) :
2387 + FeedWordPress::critical_bug('SyndicatedPost (_wp_id problem)', $this, __LINE__);
2388 + endif;
1512 2389
1513 - // This is a ridiculous fucking kludge necessitated by WordPress 2.6 munging authorship meta-data
1514 - add_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1515 -
1516 - // Kludge to prevent kses filters from stripping the
1517 - // content of posts when updating without a logged in
1518 - // user who has `unfiltered_html` capability.
1519 - add_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1520 -
1521 - $this->_wp_id = wp_insert_post($dbpost);
1522 -
1523 - // Turn off ridiculous fucking kludges #1 and #2
1524 - remove_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1525 - remove_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1526 -
1527 - $this->validate_post_id($dbpost, array(__CLASS__, __FUNCTION__));
1528 -
1529 - // Unfortunately, as of WordPress 2.3, wp_insert_post()
1530 - // *still* offers no way to use a guid of your choice,
1531 - // and munges your post modified timestamp, too.
1532 - $result = $wpdb->query("
1533 - UPDATE $wpdb->posts
1534 - SET
1535 - guid='{$dbpost['guid']}',
1536 - post_modified='{$dbpost['post_modified']}',
1537 - post_modified_gmt='{$dbpost['post_modified_gmt']}'
1538 - WHERE ID='{$this->_wp_id}'
1539 - ");
1540 - else :
1541 - # The right way to do this is the above. But, alas,
1542 - # in earlier versions of WordPress, wp_insert_post has
1543 - # too much behavior (mainly related to pings) that can't
1544 - # be overridden. In WordPress 1.5, it's enough of a
1545 - # resource hog to make PHP segfault after inserting
1546 - # 50-100 posts. This can get pretty annoying, especially
1547 - # if you are trying to update your feeds for the first
1548 - # time.
1549 -
1550 - $result = $wpdb->query("
1551 - INSERT INTO $wpdb->posts
2390 + // Unfortunately, as of WordPress 2.3, wp_insert_post()
2391 + // *still* offers no way to use a guid of your choice,
2392 + // and munges your post modified timestamp, too.
2393 + $result = $wpdb->query("
2394 + UPDATE $wpdb->posts
1552 2395 SET
1553 - guid = '{$dbpost['guid']}',
1554 - post_author = '{$dbpost['post_author']}',
1555 - post_date = '{$dbpost['post_date']}',
1556 - post_date_gmt = '{$dbpost['post_date_gmt']}',
1557 - post_content = '{$dbpost['post_content']}',"
1558 - .(isset($dbpost['post_excerpt']) ? "post_excerpt = '{$dbpost['post_excerpt']}'," : "")."
1559 - post_title = '{$dbpost['post_title']}',
1560 - post_name = '{$dbpost['post_name']}',
1561 - post_modified = '{$dbpost['post_modified']}',
1562 - post_modified_gmt = '{$dbpost['post_modified_gmt']}',
1563 - comment_status = '{$dbpost['comment_status']}',
1564 - ping_status = '{$dbpost['ping_status']}',
1565 - post_status = '{$dbpost['post_status']}'
1566 - ");
1567 - $this->_wp_id = $wpdb->insert_id;
1568 -
1569 - $this->validate_post_id($dbpost, array(__CLASS__, __FUNCTION__));
1570 -
1571 - // WordPress 1.5.x - 2.0.x
1572 - wp_set_post_cats('1', $this->wp_id(), $this->post['post_category']);
1573 -
1574 - // Since we are not going through official channels, we need to
1575 - // manually tell WordPress that we've published a new post.
1576 - // We need to make sure to do this in order for FeedWordPress
1577 - // to play well with the staticize-reloaded plugin (something
1578 - // that a large aggregator website is going to *want* to be
1579 - // able to use).
1580 - do_action('publish_post', $this->_wp_id);
1581 - endif;
1582 - endif;
1583 - } /* SyndicatedPost::insert_new() */
2396 + guid='{$dbpost['guid']}',
2397 + post_modified='{$dbpost['post_modified']}',
2398 + post_modified_gmt='{$dbpost['post_modified_gmt']}'
2399 + WHERE ID='{$this->_wp_id}'
2400 + ");
2401 + else :
2402 + # The right way to do this is the above. But, alas,
2403 + # in earlier versions of WordPress, wp_insert_post has
2404 + # too much behavior (mainly related to pings) that can't
2405 + # be overridden. In WordPress 1.5, it's enough of a
2406 + # resource hog to make PHP segfault after inserting
2407 + # 50-100 posts. This can get pretty annoying, especially
2408 + # if you are trying to update your feeds for the first
2409 + # time.
1584 2410
1585 - function update_existing () {
1586 - global $wpdb;
2411 + $result = $wpdb->query("
2412 + INSERT INTO $wpdb->posts
2413 + SET
2414 + guid = '{$dbpost['guid']}',
2415 + post_author = '{$dbpost['post_author']}',
2416 + post_date = '{$dbpost['post_date']}',
2417 + post_date_gmt = '{$dbpost['post_date_gmt']}',
2418 + post_content = '{$dbpost['post_content']}',"
2419 + .(isset($dbpost['post_excerpt']) ? "post_excerpt = '{$dbpost['post_excerpt']}'," : "")."
2420 + post_title = '{$dbpost['post_title']}',
2421 + post_name = '{$dbpost['post_name']}',
2422 + post_modified = '{$dbpost['post_modified']}',
2423 + post_modified_gmt = '{$dbpost['post_modified_gmt']}',
2424 + comment_status = '{$dbpost['comment_status']}',
2425 + ping_status = '{$dbpost['ping_status']}',
2426 + post_status = '{$dbpost['post_status']}'
2427 + ");
2428 + $this->_wp_id = $wpdb->insert_id;
1587 2429
1588 - // Why the fuck doesn't wp_insert_post already do this?
1589 - $dbpost = $this->normalize_post(/*new=*/ false);
1590 - if (!is_null($dbpost)) :
1591 - if ($this->use_api('wp_insert_post')) :
1592 - $dbpost['post_pingback'] = false; // Tell WP 2.1 and 2.2 not to process for pingbacks
1593 -
1594 - // This is a ridiculous fucking kludge necessitated by WordPress 2.6 munging authorship meta-data
1595 - add_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1596 -
1597 - // Kludge to prevent kses filters from stripping the
1598 - // content of posts when updating without a logged in
1599 - // user who has `unfiltered_html` capability.
1600 - add_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
2430 + // This should never happen.
2431 + if (!is_numeric($this->_wp_id) or ($this->_wp_id == 0)) :
2432 + FeedWordPress::critical_bug('SyndicatedPost::_wp_id', $this->_wp_id, __LINE__);
2433 + endif;
1601 2434
1602 - // Don't munge status fields that the user may have reset manually
1603 - if (function_exists('get_post_field')) :
1604 - $doNotMunge = array('post_status', 'comment_status', 'ping_status');
1605 - foreach ($doNotMunge as $field) :
1606 - $dbpost[$field] = get_post_field($field, $this->wp_id());
1607 - endforeach;
1608 - endif;
1609 -
1610 - $this->_wp_id = wp_insert_post($dbpost);
2435 + // WordPress 1.5.x - 2.0.x
2436 + wp_set_post_cats('1', $this->wp_id(), $this->post['post_category']);
1611 2437
1612 - // Turn off ridiculous fucking kludges #1 and #2
1613 - remove_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1614 - remove_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1615 -
1616 - $this->validate_post_id($dbpost, array(__CLASS__, __FUNCTION__));
1617 -
1618 - // Unfortunately, as of WordPress 2.3, wp_insert_post()
1619 - // munges your post modified timestamp.
1620 - $result = $wpdb->query("
1621 - UPDATE $wpdb->posts
1622 - SET
1623 - post_modified='{$dbpost['post_modified']}',
1624 - post_modified_gmt='{$dbpost['post_modified_gmt']}'
1625 - WHERE ID='{$this->_wp_id}'
1626 - ");
1627 - else :
1628 -
1629 - $result = $wpdb->query("
1630 - UPDATE $wpdb->posts
1631 - SET
1632 - post_author = '{$dbpost['post_author']}',
1633 - post_content = '{$dbpost['post_content']}',"
1634 - .(isset($dbpost['post_excerpt']) ? "post_excerpt = '{$dbpost['post_excerpt']}'," : "")."
1635 - post_title = '{$dbpost['post_title']}',
1636 - post_name = '{$dbpost['post_name']}',
1637 - post_modified = '{$dbpost['post_modified']}',
1638 - post_modified_gmt = '{$dbpost['post_modified_gmt']}'
1639 - WHERE guid='{$dbpost['guid']}'
1640 - ");
1641 -
1642 - // WordPress 2.1.x and up
1643 - if (function_exists('wp_set_post_categories')) :
1644 - wp_set_post_categories($this->wp_id(), $this->post['post_category']);
1645 - // WordPress 1.5.x - 2.0.x
1646 - elseif (function_exists('wp_set_post_cats')) :
1647 - wp_set_post_cats('1', $this->wp_id(), $this->post['post_category']);
1648 - // This should never happen.
1649 - else :
1650 - FeedWordPress::critical_bug(__CLASS__.'::'.__FUNCTION.'(): no post categorizing function', array("dbpost" => $dbpost, "this" => $this), __LINE__);
1651 - endif;
1652 -
1653 - // Since we are not going through official channels, we need to
1654 - // manually tell WordPress that we've published a new post.
1655 - // We need to make sure to do this in order for FeedWordPress
1656 - // to play well with the staticize-reloaded plugin (something
1657 - // that a large aggregator website is going to *want* to be
1658 - // able to use).
1659 - do_action('edit_post', $this->post['ID']);
1660 - endif;
2438 + // Since we are not going through official channels, we need to
2439 + // manually tell WordPress that we've published a new post.
2440 + // We need to make sure to do this in order for FeedWordPress
2441 + // to play well with the staticize-reloaded plugin (something
2442 + // that a large aggregator website is going to *want* to be
2443 + // able to use).
2444 + do_action('publish_post', $this->_wp_id);
1661 2445 endif;
1662 - } /* SyndicatedPost::update_existing() */
2446 + } /* SyndicatedPost::insert_new() */
1663 2447
1664 - /**
1665 - * SyndicatedPost::normalize_post()
1666 - *
1667 - * @param bool $new If true, this post is to be inserted anew. If false, it is an update of an existing post.
1668 - * @return array A normalized representation of the post ready to be inserted into the database or sent to the WordPress API functions
1669 - */
1670 - function normalize_post ($new = true) {
2448 + function update_existing () {
1671 2449 global $wpdb;
1672 2450
1673 - $out = array();
1674 -
1675 2451 // Why the fuck doesn't wp_insert_post already do this?
2452 + $dbpost = array();
1676 2453 foreach ($this->post as $key => $value) :
1677 2454 if (is_string($value)) :
1678 - $out[$key] = $wpdb->escape($value);
2455 + $dbpost[$key] = $wpdb->escape($value);
1679 2456 else :
1680 - $out[$key] = $value;
2457 + $dbpost[$key] = $value;
1681 2458 endif;
1682 2459 endforeach;
1683 2460
1684 - if (strlen($out['post_title'].$out['post_content'].$out['post_excerpt']) == 0) :
1685 - // FIXME: Option for filtering out empty posts
1686 - endif;
1687 - if (strlen($out['post_title'])==0) :
1688 - $offset = (int) get_option('gmt_offset') * 60 * 60;
1689 - $out['post_title'] =
1690 - $this->post['meta']['syndication_source']
1691 - .' '.gmdate('Y-m-d H:i:s', $this->published() + $offset);
1692 - // FIXME: Option for what to fill a blank title with...
1693 - endif;
2461 + if ($this->use_api('wp_insert_post')) :
2462 + $dbpost['post_pingback'] = false; // Tell WP 2.1 and 2.2 not to process for pingbacks
2463 + $this->_wp_id = wp_insert_post($dbpost);
1694 2464
1695 - return $out;
1696 - }
2465 + // This should never happen.
2466 + if (!is_numeric($this->_wp_id) or ($this->_wp_id == 0)) :
2467 + FeedWordPress::critical_bug('SyndicatedPost::_wp_id', $this->_wp_id, __LINE__);
2468 + endif;
1697 2469
1698 - /**
1699 - * SyndicatedPost::validate_post_id()
1700 - *
1701 - * @param array $dbpost An array representing the post we attempted to insert or update
1702 - * @param mixed $ns A string or array representing the namespace (class, method) whence this method was called.
1703 - */
1704 - function validate_post_id ($dbpost, $ns) {
1705 - if (is_array($ns)) : $ns = implode('::', $ns);
1706 - else : $ns = (string) $ns; endif;
1707 -
1708 - // This should never happen.
1709 - if (!is_numeric($this->_wp_id) or ($this->_wp_id == 0)) :
1710 - FeedWordPress::critical_bug(
1711 - /*name=*/ $ns.'::_wp_id',
1712 - /*var =*/ array(
1713 - "\$this->_wp_id" => $this->_wp_id,
1714 - "\$dbpost" => $dbpost,
1715 - "\$this" => $this
1716 - ),
1717 - /*line # =*/ __LINE__
1718 - );
2470 + // Unfortunately, as of WordPress 2.3, wp_insert_post()
2471 + // munges your post modified timestamp.
2472 + $result = $wpdb->query("
2473 + UPDATE $wpdb->posts
2474 + SET
2475 + post_modified='{$dbpost['post_modified']}',
2476 + post_modified_gmt='{$dbpost['post_modified_gmt']}'
2477 + WHERE ID='{$this->_wp_id}'
2478 + ");
2479 + else :
2480 +
2481 + $result = $wpdb->query("
2482 + UPDATE $wpdb->posts
2483 + SET
2484 + post_author = '{$dbpost['post_author']}',
2485 + post_content = '{$dbpost['post_content']}',"
2486 + .(isset($dbpost['post_excerpt']) ? "post_excerpt = '{$dbpost['post_excerpt']}'," : "")."
2487 + post_title = '{$dbpost['post_title']}',
2488 + post_name = '{$dbpost['post_name']}',
2489 + post_modified = '{$dbpost['post_modified']}',
2490 + post_modified_gmt = '{$dbpost['post_modified_gmt']}'
2491 + WHERE guid='{$dbpost['guid']}'
2492 + ");
2493 +
2494 + // WordPress 2.1.x and up
2495 + if (function_exists('wp_set_post_categories')) :
2496 + wp_set_post_categories($this->wp_id(), $this->post['post_category']);
2497 + // WordPress 1.5.x - 2.0.x
2498 + elseif (function_exists('wp_set_post_cats')) :
2499 + wp_set_post_cats('1', $this->wp_id(), $this->post['post_category']);
2500 + // This should never happen.
2501 + else :
2502 + FeedWordPress::critical_bug('SyndicatedPost::insert_new::wp_version', $GLOBALS['wp_version'], __LINE__);
2503 + endif;
2504 +
2505 + // Since we are not going through official channels, we need to
2506 + // manually tell WordPress that we've published a new post.
2507 + // We need to make sure to do this in order for FeedWordPress
2508 + // to play well with the staticize-reloaded plugin (something
2509 + // that a large aggregator website is going to *want* to be
2510 + // able to use).
2511 + do_action('edit_post', $this->post['ID']);
1719 2512 endif;
1720 - } /* SyndicatedPost::validate_post_id() */
1721 -
1722 - /**
1723 - * SyndicatedPost::fix_revision_meta() - Fixes the way WP 2.6+ fucks up
1724 - * meta-data (authorship, etc.) when storing revisions of an updated
1725 - * syndicated post.
1726 - *
1727 - * In their infinite wisdom, the WordPress coders have made it completely
1728 - * impossible for a plugin that uses wp_insert_post() to set certain
1729 - * meta-data (such as the author) when you store an old revision of an
1730 - * updated post. Instead, it uses the WordPress defaults (= currently
1731 - * active user ID if the process is running with a user logged in, or
1732 - * = #0 if there is no user logged in). This results in bogus authorship
1733 - * data for revisions that are syndicated from off the feed, unless we
1734 - * use a ridiculous kludge like this to end-run the munging of meta-data
1735 - * by _wp_put_post_revision.
1736 - *
1737 - * @param int $revision_id The revision ID to fix up meta-data
1738 - */
1739 - function fix_revision_meta ($revision_id) {
1740 - global $wpdb;
1741 -
1742 - $post_author = (int) $this->post['post_author'];
1743 -
1744 - $revision_id = (int) $revision_id;
1745 - $wpdb->query("
1746 - UPDATE $wpdb->posts
1747 - SET post_author={$this->post['post_author']}
1748 - WHERE post_type = 'revision' AND ID='$revision_id'
1749 - ");
1750 - } /* SyndicatedPost::fix_revision_meta () */
2513 + } /* SyndicatedPost::update_existing() */
1751 2514
1752 - /**
1753 - * SyndicatedPost::avoid_kses_munge() -- If FeedWordPress is processing
1754 - * an automatic update, that generally means that wp_insert_post() is
1755 - * being called under the user credentials of whoever is viewing the
1756 - * blog at the time -- usually meaning no user at all. But if WordPress
1757 - * gets a wp_insert_post() when current_user_can('unfiltered_html') is
1758 - * false, it will run the content of the post through a kses function
1759 - * that strips out lots of HTML tags -- notably <object> and some others.
1760 - * This causes problems for syndicating (for example) feeds that contain
1761 - * YouTube videos. It also produces an unexpected asymmetry between
1762 - * automatically-initiated updates and updates initiated manually from
1763 - * the WordPress Dashboard (which are usually initiated under the
1764 - * credentials of a logged-in admin, and so don't get run through the
1765 - * kses function). So, to avoid the whole mess, what we do here is
1766 - * just forcibly disable the kses munging for a single syndicated post,
1767 - * by restoring the contents of the `post_content` field.
1768 - *
1769 - * @param string $content The content of the post, after other filters have gotten to it
1770 - * @return string The original content of the post, before other filters had a chance to munge it.
1771 - */
1772 - function avoid_kses_munge ($content) {
1773 - global $wpdb;
1774 - return $wpdb->escape($this->post['post_content']);
1775 - }
1776 -
1777 2515 // SyndicatedPost::add_rss_meta: adds interesting meta-data to each entry
1778 2516 // using the space for custom keys. The set of keys and values to add is
1779 2517 // specified by the keys and values of $post['meta']. This is used to
1780 2518 // store anything that the WordPress user might want to access from a
@@ -1826,9 +2564,9 @@
1826 2564
1827 2565 // SyndicatedPost::author_id (): get the ID for an author name from
1828 2566 // the feed. Create the author if necessary.
1829 2567 function author_id ($unfamiliar_author = 'create') {
1830 - global $wpdb;
2568 + global $wpdb, $wp_db_version; // test for WordPress 2.0 database schema
1831 2569
1832 2570 $a = $this->author();
1833 2571 $author = $a['name'];
1834 2572 $email = $a['email'];
@@ -1833,15 +2571,8 @@
1833 2571 $author = $a['name'];
1834 2572 $email = $a['email'];
1835 2573 $url = $a['uri'];
1836 2574
1837 - $match_author_by_email = !('yes' == get_option("feedwordpress_do_not_match_author_by_email"));
1838 - if ($match_author_by_email and !FeedWordPress::is_null_email($email)) :
1839 - $test_email = $email;
1840 - else :
1841 - $test_email = NULL;
1842 - endif;
1843 -
1844 2575 // Never can be too careful...
1845 2576 $login = sanitize_user($author, /*strict=*/ true);
1846 2577 $login = apply_filters('pre_user_login', $login);
1847 2578
@@ -1850,9 +2581,8 @@
1850 2581
1851 2582 $reg_author = $wpdb->escape(preg_quote($author));
1852 2583 $author = $wpdb->escape($author);
1853 2584 $email = $wpdb->escape($email);
1854 - $test_email = $wpdb->escape($test_email);
1855 2585 $url = $wpdb->escape($url);
1856 2586
1857 2587 // Check for an existing author rule....
1858 2588 if (isset($this->link->settings['map authors']['name'][strtolower(trim($author))])) :
@@ -1871,10 +2601,34 @@
1871 2601
1872 2602 else :
1873 2603 // Check the database for an existing author record that might fit
1874 2604
2605 + #-- WordPress 1.5.x
2606 + if (!isset($wp_db_version)) :
2607 + $id = $wpdb->get_var(
2608 + "SELECT ID from $wpdb->users
2609 + WHERE
2610 + TRIM(LCASE(user_login)) = TRIM(LCASE('$login')) OR
2611 + (
2612 + LENGTH(TRIM(LCASE(user_email))) > 0
2613 + AND TRIM(LCASE(user_email)) = TRIM(LCASE('$email'))
2614 + ) OR
2615 + TRIM(LCASE(user_firstname)) = TRIM(LCASE('$author')) OR
2616 + TRIM(LCASE(user_nickname)) = TRIM(LCASE('$author')) OR
2617 + TRIM(LCASE(user_nicename)) = TRIM(LCASE('$nice_author')) OR
2618 + TRIM(LCASE(user_description)) = TRIM(LCASE('$author')) OR
2619 + (
2620 + LOWER(user_description)
2621 + RLIKE CONCAT(
2622 + '(^|\\n)a\\.?k\\.?a\\.?( |\\t)*:?( |\\t)*',
2623 + LCASE('$reg_author'),
2624 + '( |\\t|\\r)*(\\n|\$)'
2625 + )
2626 + )
2627 + ");
2628 +
1875 2629 #-- WordPress 2.0+
1876 - if (fwp_test_wp_version(FWP_SCHEMA_HAS_USERMETA)) :
2630 + elseif ($wp_db_version >= 2966) :
1877 2631
1878 2632 // First try the user core data table.
1879 2633 $id = $wpdb->get_var(
1880 2634 "SELECT ID FROM $wpdb->users
@@ -1881,9 +2635,9 @@
1881 2635 WHERE
1882 2636 TRIM(LCASE(user_login)) = TRIM(LCASE('$login'))
1883 2637 OR (
1884 2638 LENGTH(TRIM(LCASE(user_email))) > 0
1885 - AND TRIM(LCASE(user_email)) = TRIM(LCASE('$test_email'))
2639 + AND TRIM(LCASE(user_email)) = TRIM(LCASE('$email'))
1886 2640 )
1887 2641 OR TRIM(LCASE(user_nicename)) = TRIM(LCASE('$nice_author'))
1888 2642 ");
1889 2643
@@ -1903,33 +2657,8 @@
1903 2657 )
1904 2658 )
1905 2659 ");
1906 2660 endif;
1907 -
1908 - #-- WordPress 1.5.x
1909 - else :
1910 - $id = $wpdb->get_var(
1911 - "SELECT ID from $wpdb->users
1912 - WHERE
1913 - TRIM(LCASE(user_login)) = TRIM(LCASE('$login')) OR
1914 - (
1915 - LENGTH(TRIM(LCASE(user_email))) > 0
1916 - AND TRIM(LCASE(user_email)) = TRIM(LCASE('$test_email'))
1917 - ) OR
1918 - TRIM(LCASE(user_firstname)) = TRIM(LCASE('$author')) OR
1919 - TRIM(LCASE(user_nickname)) = TRIM(LCASE('$author')) OR
1920 - TRIM(LCASE(user_nicename)) = TRIM(LCASE('$nice_author')) OR
1921 - TRIM(LCASE(user_description)) = TRIM(LCASE('$author')) OR
1922 - (
1923 - LOWER(user_description)
1924 - RLIKE CONCAT(
1925 - '(^|\\n)a\\.?k\\.?a\\.?( |\\t)*:?( |\\t)*',
1926 - LCASE('$reg_author'),
1927 - '( |\\t|\\r)*(\\n|\$)'
1928 - )
1929 - )
1930 - ");
1931 -
1932 2661 endif;
1933 2662
1934 2663 // ... if you don't find one, then do what you need to do
1935 2664 if (is_null($id)) :
@@ -1960,9 +2689,9 @@
1960 2689 return $id;
1961 2690 } // function SyndicatedPost::author_id ()
1962 2691
1963 2692 // look up (and create) category ids from a list of categories
1964 - function category_ids ($cats, $unfamiliar_category = 'create', $tags_too = false) {
2693 + function category_ids ($cats, $unfamiliar_category = 'create') {
1965 2694 global $wpdb;
1966 2695
1967 2696 // We need to normalize whitespace because (1) trailing
1968 2697 // whitespace can cause PHP and MySQL not to see eye to eye on
@@ -1971,10 +2700,8 @@
1971 2700 // because I doubt most people want to make a semantic
1972 2701 // distinction between 'Computers' and 'Computers '
1973 2702 $cats = array_map('trim', $cats);
1974 2703
1975 - $tags = array();
1976 -
1977 2704 $cat_ids = array ();
1978 2705 foreach ($cats as $cat_name) :
1979 2706 if (preg_match('/^{#([0-9]+)}$/', $cat_name, $backref)) :
1980 2707 $cat_id = (int) $backref[1];
@@ -1982,9 +2709,9 @@
1982 2709 $cat_ids[] = $cat_id;
1983 2710 elseif (get_category($cat_id)) :
1984 2711 $cat_ids[] = $cat_id;
1985 2712 endif;
1986 - elseif (strlen($cat_name) > 0) :
2713 + else :
1987 2714 $esc = $wpdb->escape($cat_name);
1988 2715 $resc = $wpdb->escape(preg_quote($cat_name));
1989 2716
1990 2717 // WordPress 2.3+
@@ -2002,17 +2729,11 @@
2002 2729 )) :
2003 2730 foreach ($results AS $term) :
2004 2731 $cat_ids[] = (int) $term->term_id;
2005 2732 endforeach;
2006 - elseif ('tag'==$unfamiliar_category) :
2007 - $tags[] = $cat_name;
2008 2733 elseif ('create'===$unfamiliar_category) :
2009 2734 $term = wp_insert_term($cat_name, 'category');
2010 - if (is_wp_error($term)) :
2011 - FeedWordPress::noncritical_bug('term insertion problem', array('cat_name' => $cat_name, 'term' => $term, 'this' => $this), __LINE__);
2012 - else :
2013 - $cat_ids[] = $term['term_id'];
2014 - endif;
2735 + $cat_ids[] = $term['term_id'];
2015 2736 endif;
2016 2737
2017 2738 // WordPress 1.5.x - 2.2.x
2018 2739 else :
@@ -2053,28 +2774,18 @@
2053 2774 $cat_ids = NULL; // Drop the post
2054 2775 else :
2055 2776 $cat_ids = array_unique($cat_ids);
2056 2777 endif;
2057 -
2058 - if ($tags_too) : $ret = array($cat_ids, $tags);
2059 - else : $ret = $cat_ids;
2060 - endif;
2061 -
2062 - return $ret;
2778 + return $cat_ids;
2063 2779 } // function SyndicatedPost::category_ids ()
2064 2780
2065 2781 function use_api ($tag) {
2066 2782 global $wp_db_version;
2067 - switch ($tag) :
2068 - case 'wp_insert_post':
2783 + if ('wp_insert_post'==$tag) :
2069 2784 // Before 2.2, wp_insert_post does too much of the wrong stuff to use it
2070 2785 // In 1.5 it was such a resource hog it would make PHP segfault on big updates
2071 2786 $ret = (isset($wp_db_version) and $wp_db_version > FWP_SCHEMA_21);
2072 - break;
2073 - case 'post_status_pending':
2074 - $ret = (isset($wp_db_version) and $wp_db_version > FWP_SCHEMA_23);
2075 - break;
2076 - endswitch;
2787 + endif;
2077 2788 return $ret;
2078 2789 } // function SyndicatedPost::use_api ()
2079 2790
2080 2791 #### EXTRACT DATA FROM FEED ITEM ####
@@ -2112,18 +2823,14 @@
2112 2823 endif;
2113 2824
2114 2825 # If everything failed, then default to the current time.
2115 2826 if (is_null($epoch)) :
2116 - if (-1 == $default) :
2117 - $epoch = time();
2118 - else :
2119 - $epoch = $default;
2120 - endif;
2827 + $epoch = time();
2121 2828 endif;
2122 2829
2123 2830 return $epoch;
2124 2831 }
2125 - function updated ($fallback = true, $default = -1) {
2832 + function updated ($fallback = true) {
2126 2833 $epoch = null;
2127 2834
2128 2835 # As far as I know, only dcterms and Atom have reliable ways to
2129 2836 # specify when something was *modified* last. If neither is
@@ -2136,27 +2843,19 @@
2136 2843 $epoch = @parse_w3cdtf($this->item['modified']);
2137 2844 elseif (isset($this->item['updated'])): // Atom 1.0
2138 2845 $epoch = @parse_w3cdtf($this->item['updated']);
2139 2846 elseif ($fallback) : // Fall back to issued / dc:date
2140 - $epoch = $this->published(/*fallback=*/ false, /*default=*/ $default);
2847 + $epoch = $this->published(/*fallback=*/ false);
2141 2848 endif;
2142 2849
2143 2850 # If everything failed, then default to the current time.
2144 2851 if (is_null($epoch)) :
2145 - if (-1 == $default) :
2146 - $epoch = time();
2147 - else :
2148 - $epoch = $default;
2149 - endif;
2852 + $epoch = time();
2150 2853 endif;
2151 2854
2152 2855 return $epoch;
2153 2856 }
2154 2857
2155 - function update_hash () {
2156 - return md5(serialize($this->item));
2157 - }
2158 -
2159 2858 function guid () {
2160 2859 $guid = null;
2161 2860 if (isset($this->item['id'])): // Atom 0.3 / 1.0
2162 2861 $guid = $this->item['id'];
@@ -2243,97 +2942,380 @@
2243 2942 endif;
2244 2943
2245 2944 return $author;
2246 2945 } // SyndicatedPost::author()
2946 +} // class SyndicatedPost
2947 +
2948 +# class SyndicatedLink: represents a syndication feed stored within the
2949 +# WordPress database
2950 +#
2951 +# To keep things compact and editable from within WordPress, we use all the
2952 +# links under a particular category in the WordPress "Blogroll" for the list of
2953 +# feeds to syndicate. "Contributors" is the category used by default; you can
2954 +# configure that under Options --> Syndication.
2955 +#
2956 +# Fields used are:
2957 +#
2958 +# * link_rss: the URI of the Atom/RSS feed to syndicate
2959 +#
2960 +# * link_notes: user-configurable options, with keys and values
2961 +# like so:
2962 +#
2963 +# key: value
2964 +# cats: computers\nweb
2965 +# feed/key: value
2966 +#
2967 +# Keys that start with "feed/" are gleaned from the data supplied
2968 +# by the feed itself, and will be overwritten with each update.
2969 +#
2970 +# Values have linebreak characters escaped with C-style
2971 +# backslashes (so, for example, a newline becomes "\n").
2972 +#
2973 +# The value of `cats` is used as a newline-separated list of
2974 +# default categories for any post coming from a particular feed.
2975 +# (In the example above, any posts from this feed will be placed
2976 +# in the "computers" and "web" categories--*in addition to* any
2977 +# categories that may already be applied to the posts.)
2978 +#
2979 +# Values of keys in link_notes are accessible from templates using
2980 +# the function `get_feed_meta($key)` if this plugin is activated.
2981 +
2982 +class SyndicatedLink {
2983 + var $id = null;
2984 + var $link = null;
2985 + var $settings = array ();
2986 + var $magpie = null;
2987 +
2988 + function SyndicatedLink ($link) {
2989 + global $wpdb;
2990 +
2991 + if (is_object($link)) :
2992 + $this->link = $link;
2993 + $this->id = $link->link_id;
2994 + else :
2995 + $this->id = $link;
2996 + if (function_exists('get_bookmark')) : // WP 2.1+
2997 + $this->link = get_bookmark($link);
2998 + else :
2999 + $this->link = $wpdb->get_row("
3000 + SELECT * FROM $wpdb->links
3001 + WHERE (link_id = '".$wpdb->escape($link)."')"
3002 + );
3003 + endif;
3004 + endif;
3005 +
3006 + if (strlen($this->link->link_rss) > 0) :
3007 + // Read off feed settings from link_notes
3008 + $notes = explode("\n", $this->link->link_notes);
3009 + foreach ($notes as $note):
3010 + list($key, $value) = explode(": ", $note, 2);
2247 3011
2248 - var $uri_attrs = array (
2249 - array('a', 'href'),
2250 - array('applet', 'codebase'),
2251 - array('area', 'href'),
2252 - array('blockquote', 'cite'),
2253 - array('body', 'background'),
2254 - array('del', 'cite'),
2255 - array('form', 'action'),
2256 - array('frame', 'longdesc'),
2257 - array('frame', 'src'),
2258 - array('iframe', 'longdesc'),
2259 - array('iframe', 'src'),
2260 - array('head', 'profile'),
2261 - array('img', 'longdesc'),
2262 - array('img', 'src'),
2263 - array('img', 'usemap'),
2264 - array('input', 'src'),
2265 - array('input', 'usemap'),
2266 - array('ins', 'cite'),
2267 - array('link', 'href'),
2268 - array('object', 'classid'),
2269 - array('object', 'codebase'),
2270 - array('object', 'data'),
2271 - array('object', 'usemap'),
2272 - array('q', 'cite'),
2273 - array('script', 'src')
2274 - ); /* var SyndicatedPost::$uri_attrs */
3012 + if (strlen($key) > 0) :
3013 + // Unescape and trim() off the whitespace.
3014 + // Thanks to Ray Lischner for pointing out the
3015 + // need to trim off whitespace.
3016 + $this->settings[$key] = stripcslashes (trim($value));
3017 + endif;
3018 + endforeach;
2275 3019
2276 - var $_base = null;
3020 + // "Magic" feed settings
3021 + $this->settings['link/uri'] = $this->link->link_rss;
3022 + $this->settings['link/name'] = $this->link->link_name;
3023 + $this->settings['link/id'] = $this->link->link_id;
3024 +
3025 + // `hardcode categories` is deprecated in favor of `unfamiliar categories`
3026 + if (
3027 + FeedWordPress::affirmative($this->settings, 'hardcode categories')
3028 + and !isset($this->settings['unfamiliar categories'])
3029 + ) :
3030 + $this->settings['unfamiliar categories'] = 'default';
3031 + endif;
3032 +
3033 + // Set this up automagically for del.icio.us
3034 + if (!isset($this->settings['cat_split']) and false !== strpos($this->link->link_rss, 'del.icio.us')) :
3035 + $this->settings['cat_split'] = '\s'; // Whitespace separates multiple tags in del.icio.us RSS feeds
3036 + endif;
2277 3037
2278 - function resolve_single_relative_uri ($refs) {
2279 - $tag = FeedWordPressHTML::attributeMatch($refs);
2280 - $url = Relative_URI::resolve($tag['value'], $this->_base);
2281 - return $tag['prefix'] . $url . $tag['suffix'];
2282 - } /* function SyndicatedPost::resolve_single_relative_uri() */
3038 + if (isset($this->settings['cats'])):
3039 + $this->settings['cats'] = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, $this->settings['cats']);
3040 + endif;
3041 +
3042 + if (isset($this->settings['map authors'])) :
3043 + $author_rules = explode("\n\n", $this->settings['map authors']);
3044 + $ma = array();
3045 + foreach ($author_rules as $rule) :
3046 + list($rule_type, $author_name, $author_action) = explode("\n", $rule);
3047 +
3048 + // Normalize for case and whitespace
3049 + $rule_type = strtolower(trim($rule_type));
3050 + $author_name = strtolower(trim($author_name));
3051 + $author_action = strtolower(trim($author_action));
3052 +
3053 + $ma[$rule_type][$author_name] = $author_action;
3054 + endforeach;
3055 + $this->settings['map authors'] = $ma;
3056 + endif;
3057 + endif;
3058 + } // SyndicatedLink::SyndicatedLink ()
3059 +
3060 + function found () {
3061 + return is_object($this->link);
3062 + }
2283 3063
2284 - function resolve_relative_uris ($content, $obj) {
2285 - # The MagpieRSS upgrade has some `xml:base` support baked in.
2286 - # However, sometimes people do silly things, like putting
2287 - # relative URIs out on a production RSS 2.0 feed or other feeds
2288 - # with no good support for `xml:base`. So we'll do our best to
2289 - # try to catch any remaining relative URIs and resolve them as
2290 - # best we can.
2291 - $obj->_base = $obj->item['link']; // Reset the base for resolving relative URIs
3064 + function stale () {
3065 + $stale = true;
3066 + if (isset($this->settings['update/hold']) and ($this->settings['update/hold']=='ping')) :
3067 + $stale = false; // don't update on any timed updates; pings only
3068 + elseif (isset($this->settings['update/hold']) and ($this->settings['update/hold']=='next')) :
3069 + $stale = true; // update on the next timed update
3070 + elseif (!isset($this->settings['update/ttl']) or !isset($this->settings['update/last'])) :
3071 + $stale = true; // initial update
3072 + else :
3073 + $after = ((int) $this->settings['update/last'])
3074 + +((int) $this->settings['update/ttl'] * 60);
3075 + $stale = (time() >= $after);
3076 + endif;
3077 + return $stale;
3078 + }
2292 3079
2293 - foreach ($obj->uri_attrs as $pair) :
2294 - list($tag, $attr) = $pair;
2295 - $pattern = FeedWordPressHTML::attributeRegex($tag, $attr);
2296 - $content = preg_replace_callback (
2297 - $pattern,
2298 - array(&$obj, 'resolve_single_relative_uri'),
2299 - $content
2300 - );
2301 - endforeach;
3080 + function poll () {
3081 + global $wpdb;
2302 3082
2303 - return $content;
2304 - } /* function SyndicatedPost::resolve_relative_uris () */
3083 + $this->magpie = fetch_rss($this->link->link_rss);
3084 + $new_count = NULL;
2305 3085
2306 - var $strip_attrs = array (
2307 - array('[a-z]+', 'target'),
2308 -// array('[a-z]+', 'style'),
2309 -// array('[a-z]+', 'on[a-z]+'),
2310 - );
3086 + if (is_object($this->magpie)) :
3087 + $new_count = array('new' => 0, 'updated' => 0);
2311 3088
2312 - function strip_attribute_from_tag ($refs) {
2313 - $tag = FeedWordPressHTML::attributeMatch($refs);
2314 - return $tag['before_attribute'].$tag['after_attribute'];
3089 + # -- Update Link metadata live from feed
3090 + $channel = $this->magpie->channel;
3091 +
3092 + if (!isset($channel['id'])) :
3093 + $channel['id'] = $this->link->link_rss;
3094 + endif;
3095 +
3096 + $update = array();
3097 + if (!$this->hardcode('url') and isset($channel['link'])) :
3098 + $update[] = "link_url = '".$wpdb->escape($channel['link'])."'";
3099 + endif;
3100 +
3101 + if (!$this->hardcode('name') and isset($channel['title'])) :
3102 + $update[] = "link_name = '".$wpdb->escape($channel['title'])."'";
3103 + endif;
3104 +
3105 + if (!$this->hardcode('description')) :
3106 + if (isset($channel['tagline'])) :
3107 + $update[] = "link_description = '".$wpdb->escape($channel['tagline'])."'";
3108 + elseif (isset($channel['description'])) :
3109 + $update[] = "link_description = '".$wpdb->escape($channel['description'])."'";
3110 + endif;
3111 + endif;
3112 +
3113 + $this->settings = array_merge($this->settings, $this->flatten_array($channel));
3114 +
3115 + $this->settings['update/last'] = time(); $ttl = $this->ttl();
3116 + if (!is_null($ttl)) :
3117 + $this->settings['update/ttl'] = $ttl;
3118 + $this->settings['update/timed'] = 'feed';
3119 + else :
3120 + $this->settings['update/ttl'] = rand(30, 120); // spread over time interval for staggered updates
3121 + $this->settings['update/timed'] = 'automatically';
3122 + endif;
3123 +
3124 + if (!isset($this->settings['update/hold']) or $this->settings['update/hold']!='ping') :
3125 + $this->settings['update/hold'] = 'scheduled';
3126 + endif;
3127 +
3128 + // Copy back without a few things that we don't want to save in the notes
3129 + $to_notes = $this->settings;
3130 +
3131 + if (is_array($to_notes['cats'])) :
3132 + $to_notes['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['cats']);
3133 + endif;
3134 +
3135 + if (isset($to_notes['map authors'])) :
3136 + $ma = array();
3137 + foreach ($to_notes['map authors'] as $rule_type => $author_rules) :
3138 + foreach ($author_rules as $author_name => $author_action) :
3139 + $ma[] = $rule_type."\n".$author_name."\n".$author_action;
3140 + endforeach;
3141 + endforeach;
3142 + $to_notes['map authors'] = implode("\n\n", $ma);
3143 + endif;
3144 +
3145 + unset($to_notes['link/id']); unset($to_notes['link/uri']);
3146 + unset($to_notes['link/name']);
3147 + unset($to_notes['hardcode categories']); // Deprecated
3148 +
3149 + $notes = '';
3150 + foreach ($to_notes as $key => $value) :
3151 + $notes .= $key . ": ". addcslashes($value, "\0..\37".'\\') . "\n";
3152 + endforeach;
3153 + $update[] = "link_notes = '".$wpdb->escape($notes)."'";
3154 +
3155 + $update_set = implode(',', $update);
3156 +
3157 + // Update the properties of the link from the feed information
3158 + $result = $wpdb->query("
3159 + UPDATE $wpdb->links
3160 + SET $update_set
3161 + WHERE link_id='$this->id'
3162 + ");
3163 +
3164 + # -- Add new posts from feed and update any updated posts
3165 + if (is_array($this->magpie->items)) :
3166 + foreach ($this->magpie->items as $item) :
3167 + $post =& new SyndicatedPost($item, $this);
3168 + if (!$post->filtered()) :
3169 + $new = $post->store();
3170 + if ( $new !== false ) $new_count[$new]++;
3171 + endif;
3172 + endforeach;
3173 + endif;
3174 +
3175 + // Copy back any changes to feed settings made in the course of updating (e.g. new author rules)
3176 + $to_notes = $this->settings;
3177 +
3178 + if (is_array($to_notes['cats'])) :
3179 + $to_notes['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['cats']);
3180 + endif;
3181 +
3182 + if (isset($to_notes['map authors'])) :
3183 + $ma = array();
3184 + foreach ($to_notes['map authors'] as $rule_type => $author_rules) :
3185 + foreach ($author_rules as $author_name => $author_action) :
3186 + $ma[] = $rule_type."\n".$author_name."\n".$author_action;
3187 + endforeach;
3188 + endforeach;
3189 + $to_notes['map authors'] = implode("\n\n", $ma);
3190 + endif;
3191 +
3192 + unset($to_notes['link/id']); unset($to_notes['link/uri']);
3193 + unset($to_notes['link/name']);
3194 + unset($to_notes['hardcode categories']); // Deprecated
3195 +
3196 + $notes = '';
3197 + foreach ($to_notes as $key => $value) :
3198 + $notes .= $key . ": ". addcslashes($value, "\0..\37".'\\') . "\n";
3199 + endforeach;
3200 +
3201 + $update_set = "link_notes = '".$wpdb->escape($notes)."'";
3202 +
3203 + // Update the properties of the link from the feed information
3204 + $result = $wpdb->query("
3205 + UPDATE $wpdb->links
3206 + SET $update_set
3207 + WHERE link_id='$this->id'
3208 + ");
3209 + endif;
3210 + return $new_count;
3211 + } /* SyndicatedLink::poll() */
3212 +
3213 + function uri () {
3214 + return (is_object($this->link) ? $this->link->link_rss : NULL);
2315 3215 }
3216 + function homepage () {
3217 + return (isset($this->settings['feed/link']) ? $this->settings['feed/link'] : NULL);
3218 + }
2316 3219
2317 - function sanitize_content ($content, $obj) {
2318 - # This kind of sucks. I intend to replace it with
2319 - # lib_filter sometime soon.
2320 - foreach ($obj->strip_attrs as $pair):
2321 - list($tag,$attr) = $pair;
2322 - $pattern = FeedWordPressHTML::attributeRegex($tag, $attr);
3220 + function ttl () {
3221 + if (is_object($this->magpie)) :
3222 + $channel = $this->magpie->channel;
3223 + else :
3224 + $channel = array();
3225 + endif;
2323 3226
2324 - $content = preg_replace_callback (
2325 - $pattern,
2326 - array(&$obj, 'strip_attribute_from_tag'),
2327 - $content
3227 + if (isset($channel['ttl'])) :
3228 + // "ttl stands for time to live. It's a number of
3229 + // minutes that indicates how long a channel can be
3230 + // cached before refreshing from the source."
3231 + // <http://blogs.law.harvard.edu/tech/rss#ltttlgtSubelementOfLtchannelgt>
3232 + $ret = $channel['ttl'];
3233 + elseif (isset($channel['sy']['updatefrequency']) or isset($channel['sy']['updateperiod'])) :
3234 + $period_minutes = array (
3235 + 'hourly' => 60, /* minutes in an hour */
3236 + 'daily' => 1440, /* minutes in a day */
3237 + 'weekly' => 10080, /* minutes in a week */
3238 + 'monthly' => 43200, /* minutes in a month */
3239 + 'yearly' => 525600, /* minutes in a year */
2328 3240 );
2329 - endforeach;
2330 - return $content;
2331 - }
2332 -} // class SyndicatedPost
2333 3241
2334 -require_once(dirname(__FILE__) . '/syndicatedlink.class.php');
3242 + // "sy:updatePeriod: Describes the period over which the
3243 + // channel format is updated. Acceptable values are:
3244 + // hourly, daily, weekly, monthly, yearly. If omitted,
3245 + // daily is assumed." <http://web.resource.org/rss/1.0/modules/syndication/>
3246 + if (isset($channel['sy']['updateperiod'])) : $period = $channel['sy']['updateperiod'];
3247 + else : $period = 'daily';
3248 + endif;
3249 +
3250 + // "sy:updateFrequency: Used to describe the frequency
3251 + // of updates in relation to the update period. A
3252 + // positive integer indicates how many times in that
3253 + // period the channel is updated. ... If omitted a value
3254 + // of 1 is assumed." <http://web.resource.org/rss/1.0/modules/syndication/>
3255 + if (isset($channel['sy']['updatefrequency'])) : $freq = (int) $channel['sy']['updatefrequency'];
3256 + else : $freq = 1;
3257 + endif;
3258 +
3259 + $ret = (int) ($period_minutes[$period] / $freq);
3260 + else :
3261 + $ret = NULL;
3262 + endif;
3263 + return $ret;
3264 + } /* SyndicatedLink::ttl() */
2335 3265
3266 + // SyndicatedLink::flatten_array (): flatten an array. Useful for
3267 + // hierarchical and namespaced elements.
3268 + //
3269 + // Given an array which may contain array or object elements in it,
3270 + // return a "flattened" array: a one-dimensional array of scalars
3271 + // containing each of the scalar elements contained within the array
3272 + // structure. Thus, for example, if $a['b']['c']['d'] == 'e', then the
3273 + // returned array for FeedWordPress::flatten_array($a) will contain a key
3274 + // $a['feed/b/c/d'] with value 'e'.
3275 + function flatten_array ($arr, $prefix = 'feed/', $separator = '/') {
3276 + $ret = array ();
3277 + if (is_array($arr)) :
3278 + foreach ($arr as $key => $value) :
3279 + if (is_scalar($value)) :
3280 + $ret[$prefix.$key] = $value;
3281 + else :
3282 + $ret = array_merge($ret, $this->flatten_array($value, $prefix.$key.$separator, $separator));
3283 + endif;
3284 + endforeach;
3285 + endif;
3286 + return $ret;
3287 + } // function SyndicatedLink::flatten_array ()
3288 +
3289 + function hardcode ($what) {
3290 + $default = get_option("feedwordpress_hardcode_$what");
3291 + if ( $default === 'yes' ) :
3292 + // If the default is to hardcode, then we want the
3293 + // negation of negative(): TRUE by default and FALSE if
3294 + // the setting is explicitly "no"
3295 + $ret = !FeedWordPress::negative($this->settings, "hardcode $what");
3296 + else :
3297 + // If the default is NOT to hardcode, then we want
3298 + // affirmative(): FALSE by default and TRUE if the
3299 + // setting is explicitly "yes"
3300 + $ret = FeedWordPress::affirmative($this->settings, "hardcode $what");
3301 + endif;
3302 + return $ret;
3303 + } // function SyndicatedLink::hardcode ()
3304 +
3305 + function syndicated_status ($what, $default) {
3306 + global $wpdb;
3307 +
3308 + $ret = get_option("feedwordpress_syndicated_{$what}_status");
3309 + if ( isset($this->settings["$what status"]) ) :
3310 + $ret = $this->settings["$what status"];
3311 + elseif (!$ret) :
3312 + $ret = $default;
3313 + endif;
3314 + return $wpdb->escape(trim(strtolower($ret)));
3315 + } // function SyndicatedLink:syndicated_status ()
3316 +} // class SyndicatedLink
3317 +
2336 3318 ################################################################################
2337 3319 ## XML-RPC HOOKS: accept XML-RPC update pings from Contributors ################
2338 3320 ################################################################################
2339 3321
@@ -2355,8 +3337,169 @@
2355 3337 return array('flerror' => false, 'message' => "Thanks for the ping.".implode(' and', $mesg));
2356 3338 endif;
2357 3339 }
2358 3340
3341 +################################################################################
3342 +## class FeedFinder: find likely feeds using autodetection and/or guesswork ####
3343 +################################################################################
3344 +
3345 +class FeedFinder {
3346 + var $uri = NULL;
3347 + var $_cache_uri = NULL;
3348 +
3349 + var $verify = FALSE;
3350 +
3351 + var $_data = NULL;
3352 + var $_head = NULL;
3353 +
3354 + # -- Recognition patterns
3355 + var $_feed_types = array(
3356 + 'application/rss+xml',
3357 + 'text/xml',
3358 + 'application/atom+xml',
3359 + 'application/x.atom+xml',
3360 + 'application/x-atom+xml'
3361 + );
3362 + var $_feed_markers = array('\\<feed', '\\<rss', 'xmlns="http://purl.org/rss/1.0');
3363 + var $_html_markers = array('\\<html');
3364 + var $_obvious_feed_url = array('[./]rss', '[./]rdf', '[./]atom', '[./]feed', '\.xml');
3365 + var $_maybe_feed_url = array ('rss', 'rdf', 'atom', 'feed', 'xml');
3366 +
3367 + function FeedFinder ($uri = NULL, $verify = TRUE) {
3368 + $this->uri = $uri; $this->verify = $verify;
3369 + } /* FeedFinder::FeedFinder () */
3370 +
3371 + function find ($uri = NULL) {
3372 + $ret = array ();
3373 + if (!is_null($this->data($uri))) {
3374 + if ($this->is_feed($uri)) {
3375 + $ret = array($this->uri);
3376 + } else {
3377 + // Assume that we have HTML or XHTML (even if we don't, who's it gonna hurt?)
3378 + // Autodiscovery is the preferred method
3379 + $href = $this->_link_rel_feeds();
3380 +
3381 + // ... but we'll also take the little orange buttons
3382 + $href = array_merge($href, $this->_a_href_feeds(TRUE));
3383 +
3384 + // If all that failed, look harder
3385 + if (count($href) == 0) $href = $this->_a_href_feeds(FALSE);
3386 +
3387 + // Verify feeds and resolve relative URIs
3388 + foreach ($href as $u) {
3389 + $the_uri = Relative_URI::resolve($u, $this->uri);
3390 + if ($this->verify) {
3391 + $feed =& new FeedFinder($the_uri);
3392 + if ($feed->is_feed()) $ret[] = $the_uri;
3393 + $feed = NULL;
3394 + } else {
3395 + $ret[] = $the_uri;
3396 + }
3397 + } /* foreach */
3398 + } /* if */
3399 + } /* if */
3400 + return array_unique($ret);
3401 + } /* FeedFinder::find () */
3402 +
3403 + function data ($uri = NULL) {
3404 + $this->_get($uri);
3405 + return $this->_data;
3406 + }
3407 +
3408 + function is_feed ($uri = NULL) {
3409 + $data = $this->data($uri);
3410 +
3411 + return (
3412 + preg_match (
3413 + "\007(".implode('|',$this->_feed_markers).")\007i",
3414 + $data
3415 + ) and !preg_match (
3416 + "\007(".implode('|',$this->_html_markers).")\007i",
3417 + $data
3418 + )
3419 + );
3420 + } /* FeedFinder::is_feed () */
3421 +
3422 + # --- Private methods ---
3423 + function _get ($uri = NULL) {
3424 + if ($uri) $this->uri = $uri;
3425 +
3426 + // Is the result not yet cached?
3427 + if ($this->_cache_uri !== $this->uri) :
3428 + // Snoopy is an HTTP client in PHP
3429 + $client = new Snoopy();
3430 +
3431 + // Prepare headers and internal settings
3432 + $client->rawheaders['Connection'] = 'close';
3433 + $client->accept = 'application/atom+xml application/rdf+xml application/rss+xml application/xml text/html */*';
3434 + $client->agent = 'feedfinder/1.2 (compatible; PHP FeedFinder) +http://projects.radgeek.com/feedwordpress';
3435 + $client->read_timeout = 25;
3436 +
3437 + // Fetch the HTML or feed
3438 + @$client->fetch($this->uri);
3439 + $this->_data = $client->results;
3440 +
3441 + // Kilroy was here
3442 + $this->_cache_uri = $this->uri;
3443 + endif;
3444 + } /* FeedFinder::_get () */
3445 +
3446 + function _link_rel_feeds () {
3447 + $links = $this->_tags('link');
3448 + $link_count = count($links);
3449 +
3450 + // now figure out which one points to the RSS file
3451 + $href = array ();
3452 + for ($n=0; $n<$link_count; $n++) {
3453 + if (strtolower($links[$n]['rel']) == 'alternate') {
3454 + if (in_array(strtolower($links[$n]['type']), $this->_feed_types)) {
3455 + $href[] = $links[$n]['href'];
3456 + } /* if */
3457 + } /* if */
3458 + } /* for */
3459 + return $href;
3460 + }
3461 +
3462 + function _a_href_feeds ($obvious = TRUE) {
3463 + $pattern = ($obvious ? $this->_obvious_feed_url : $this->_maybe_feed_url);
3464 +
3465 + $links = $this->_tags('a');
3466 + $link_count = count($links);
3467 +
3468 + // now figure out which one points to the RSS file
3469 + $href = array ();
3470 + for ($n=0; $n<$link_count; $n++) {
3471 + if (preg_match("\007(".implode('|',$pattern).")\007i", $links[$n]['href'])) {
3472 + $href[] = $links[$n]['href'];
3473 + } /* if */
3474 + } /* for */
3475 + return $href;
3476 + }
3477 +
3478 + function _tags ($tag) {
3479 + $html = $this->data();
3480 +
3481 + // search through the HTML, save all <link> tags
3482 + // and store each link's attributes in an associative array
3483 + preg_match_all('/<'.$tag.'\s+(.*?)\s*\/?>/si', $html, $matches);
3484 + $links = $matches[1];
3485 + $ret = array();
3486 + $link_count = count($links);
3487 + for ($n=0; $n<$link_count; $n++) {
3488 + $attributes = preg_split('/\s+/s', $links[$n]);
3489 + foreach($attributes as $attribute) {
3490 + $att = preg_split('/\s*=\s*/s', $attribute, 2);
3491 + if (isset($att[1])) {
3492 + $att[1] = preg_replace('/([\'"]?)(.*)\1/', '$2', $att[1]);
3493 + $final_link[strtolower($att[0])] = $att[1];
3494 + } /* if */
3495 + } /* foreach */
3496 + $ret[$n] = $final_link;
3497 + } /* for */
3498 + return $ret;
3499 + }
3500 +} /* class FeedFinder */
3501 +
2359 3502 # Relative URI static class: PHP class for resolving relative URLs
2360 3503 #
2361 3504 # This class is derived (under the terms of the GPL) from URL Class 0.3 by
2362 3505 # Keyvan Minoukadeh <keyvan@k1m.com>, which is great but more than we need
@@ -2558,5 +3701,5 @@
2558 3701 $ret['name'] = NULL; $ret['email'] = NULL;
2559 3702 endif;
2560 3703 return $ret;
2561 3704 }
2562 -
3705 +?>