From 3ad52463f633b060bee519e8aa4d6e9453fdc2aa Mon Sep 17 00:00:00 2001 From: Mike Macgirvin Date: Mon, 20 Sep 2010 19:34:44 -0700 Subject: [PATCH] more robust feed error handling, at the expense of performance. Pass profile owner through HTML (yuk) to the ajax updater - as browser pre-fetch totally buggers passing it via the server session. --- include/items.php | 13 +- include/main.js | 7 +- include/poller.php | 298 ++++++++++++++++++++--------------------- index.php | 1 + mod/network.php | 4 +- mod/profile.php | 17 ++- mod/update_network.php | 4 +- mod/update_profile.php | 4 +- 8 files changed, 181 insertions(+), 167 deletions(-) diff --git a/include/items.php b/include/items.php index 8ca0eeb16f..c7738c3ed5 100644 --- a/include/items.php +++ b/include/items.php @@ -91,6 +91,7 @@ function get_feed_for(&$a, $dfrn_id, $owner_id, $last_update, $direction = 0) { if(! strlen($last_update)) $last_update = 'now - 30 days'; + $check_date = datetime_convert('UTC','UTC',$last_update,'Y-m-d H:i:s'); $r = q("SELECT `item`.*, `item`.`id` AS `item_id`, @@ -109,8 +110,9 @@ function get_feed_for(&$a, $dfrn_id, $owner_id, $last_update, $direction = 0) { dbesc($check_date), dbesc($sort) ); - if(! count($r)) - killme(); + + // Will check further below if this actually returned results. + // We will provide an empty feed in any case. $items = $r; @@ -135,7 +137,12 @@ function get_feed_for(&$a, $dfrn_id, $owner_id, $last_update, $direction = 0) { '$namdate' => xmlify(datetime_convert('UTC','UTC',$owner['name-date'] . '+00:00' , ATOM_TIME)) )); - + + if(! count($items)) { + $atom .= '' . "\r\n"; + return $atom; + } + foreach($items as $item) { // public feeds get html, our own nodes use bbcode diff --git a/include/main.js b/include/main.js index 645170b41e..1ddab0dc2c 100644 --- a/include/main.js +++ b/include/main.js @@ -37,6 +37,7 @@ var msie = false; var stopped = false; var timer = null; + var pr = 0; $(document).ready(function() { $.ajaxSetup({cache: false}); @@ -64,8 +65,8 @@ function NavUpdate() { - if($('#live-network').length) { src = 'network'; liveUpdate(); } - if($('#live-profile').length) { src = 'profile'; liveUpdate(); } + if($('#live-network').length) { src = 'network'; pr = $('#live-network').attr('profile'); liveUpdate(); } + if($('#live-profile').length) { src = 'profile'; pr = $('#live-profile').attr('profile'); liveUpdate(); } if(! stopped) { $.get("ping",function(data) { @@ -97,7 +98,7 @@ } prev = 'live-' + src; - $.get('update_' + src + '?msie=' + ((msie) ? 1 : 0),function(data) { + $.get('update_' + src + '?p=' + pr + '&msie=' + ((msie) ? 1 : 0),function(data) { $('.wall-item-outside-wrapper',data).each(function() { var ident = $(this).attr('id'); if($('#' + ident).length == 0) { diff --git a/include/poller.php b/include/poller.php index 0980ca1fa5..e0c721f60f 100644 --- a/include/poller.php +++ b/include/poller.php @@ -61,7 +61,6 @@ continue; } - $importer_uid = $contact['uid']; $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1", @@ -96,15 +95,21 @@ echo "XML: " . $xml . "\r\n"; } - if(! $xml) + if(! $xml) { + // dead connection - might be a transient event, or this might + // mean the software was uninstalled or the domain expired. + // Will keep trying for one month. + mark_for_death($contact); continue; - + } $res = simplexml_load_string($xml); - if(intval($res->status) == 1) + if(intval($res->status) == 1) { + // we may not be friends anymore. Will keep trying for one month. mark_for_death($contact); + } else { if($contact['term-date'] != '0000-00-00 00:00:00') unmark_for_death($contact); @@ -113,7 +118,6 @@ if((intval($res->status) != 0) || (! strlen($res->challenge)) || (! strlen($res->dfrn_id))) continue; - $postvars = array(); $sent_dfrn_id = hex2bin($res->dfrn_id); @@ -145,7 +149,6 @@ $postvars['dfrn_id'] = $idtosend; - $xml = post_url($contact['poll'],$postvars); if($debugging) { @@ -153,14 +156,8 @@ echo "Length:" . strlen($xml) . "\r\n"; } - if(! strlen($xml)) { - // an empty response may mean there's nothing new - record the fact that we checked - $r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d LIMIT 1", - dbesc(datetime_convert()), - intval($contact['id']) - ); + if(! strlen($xml)) continue; - } $feed = new SimplePie(); $feed->set_raw_data($xml); @@ -240,157 +237,156 @@ } // Now process the feed - - foreach($feed->get_items() as $item) { + if($feed->get_item_quantity()) { + foreach($feed->get_items() as $item) { - $deleted = false; + $deleted = false; - $rawdelete = $item->get_item_tags( NAMESPACE_TOMB, 'deleted-entry'); - if(isset($rawdelete[0]['attribs']['']['ref'])) { - $uri = $rawthread[0]['attribs']['']['ref']; - $deleted = true; - if(isset($rawdelete[0]['attribs']['']['when'])) { - $when = $rawthread[0]['attribs']['']['when']; - $when = datetime_convert('UTC','UTC', $when, 'Y-m-d H:i:s'); - } - else - $when = datetime_convert('UTC','UTC','now','Y-m-d H:i:s'); - } - if($deleted) { - $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", - dbesc($uri), - intval($importer['uid']) - ); - if(count($r)) { - $item = $r[0]; - if($item['uri'] == $item['parent-uri']) { - $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s', - `body` = '', `title` = '' - WHERE `parent-uri` = '%s' AND `uid` = %d", - dbesc($when), - dbesc(datetime_convert()), - dbesc($item['uri']), - intval($importer['uid']) - ); + $rawdelete = $item->get_item_tags( NAMESPACE_TOMB, 'deleted-entry'); + if(isset($rawdelete[0]['attribs']['']['ref'])) { + $uri = $rawthread[0]['attribs']['']['ref']; + $deleted = true; + if(isset($rawdelete[0]['attribs']['']['when'])) { + $when = $rawthread[0]['attribs']['']['when']; + $when = datetime_convert('UTC','UTC', $when, 'Y-m-d H:i:s'); } - else { - $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s', - `body` = '', `title` = '' - WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", - dbesc($when), - dbesc(datetime_convert()), - dbesc($uri), - intval($importer['uid']) - ); - if($item['last-child']) { - // ensure that last-child is set in case the comment that had it just got wiped. - $q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d ", + else + $when = datetime_convert('UTC','UTC','now','Y-m-d H:i:s'); + } + if($deleted) { + $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", + dbesc($uri), + intval($importer['uid']) + ); + if(count($r)) { + $item = $r[0]; + if($item['uri'] == $item['parent-uri']) { + $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s', + `body` = '', `title` = '' + WHERE `parent-uri` = '%s' AND `uid` = %d", + dbesc($when), dbesc(datetime_convert()), - dbesc($item['parent-uri']), - intval($item['uid']) + dbesc($item['uri']), + intval($importer['uid']) ); - // who is the last child now? - $r = q("SELECT `id` FROM `item` WHERE `parent-uri` = '%s' AND `type` != 'activity' AND `deleted` = 0 AND `uid` = %d - ORDER BY `edited` DESC LIMIT 1", + } + else { + $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s', + `body` = '', `title` = '' + WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", + dbesc($when), + dbesc(datetime_convert()), + dbesc($uri), + intval($importer['uid']) + ); + if($item['last-child']) { + // ensure that last-child is set in case the comment that had it just got wiped. + $q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d ", + dbesc(datetime_convert()), dbesc($item['parent-uri']), - intval($importer['uid']) - ); - if(count($r)) { - q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d LIMIT 1", - intval($r[0]['id']) + intval($item['uid']) ); - } - } - } - } - continue; - } - - - $is_reply = false; - $item_id = $item->get_id(); - $rawthread = $item->get_item_tags( NAMESPACE_THREAD,'in-reply-to'); - if(isset($rawthread[0]['attribs']['']['ref'])) { - $is_reply = true; - $parent_uri = $rawthread[0]['attribs']['']['ref']; - } - - - if($is_reply) { - - // Have we seen it? If not, import it. - - $item_id = $item->get_id(); - - $r = q("SELECT `uid`, `last-child`, `edited` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", - dbesc($item_id), - intval($importer['uid']) - ); - // FIXME update content if 'updated' changes - if(count($r)) { - $allow = $item->get_item_tags( NAMESPACE_DFRN, 'comment-allow'); - if($allow && $allow[0]['data'] != $r[0]['last-child']) { - $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d", - dbesc(datetime_convert()), - dbesc($parent_uri), - intval($importer['uid']) - ); - $r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", - intval($allow[0]['data']), - dbesc(datetime_convert()), - dbesc($item_id), - intval($importer['uid']) - ); - - - } - continue; - } - $datarray = get_atom_elements($item); - $datarray['parent-uri'] = $parent_uri; - $datarray['uid'] = $importer['uid']; - $datarray['contact-id'] = $contact['id']; - if(($datarray['verb'] == ACTIVITY_LIKE) || ($datarray['verb'] == ACTIVITY_DISLIKE)) { - $datarray['type'] = 'activity'; - $datarray['gravity'] = GRAVITY_LIKE; - } - - $r = item_store($datarray); - continue; - } - - else { - // Head post of a conversation. Have we seen it? If not, import it. - - $item_id = $item->get_id(); - $r = q("SELECT `uid`, `last-child`, `edited` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", - dbesc($item_id), - intval($importer['uid']) - ); - if(count($r)) { - $allow = $item->get_item_tags( NAMESPACE_DFRN, 'comment-allow'); - if($allow && $allow[0]['data'] != $r[0]['last-child']) { - $r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", - intval($allow[0]['data']), - dbesc(datetime_convert()), - dbesc($item_id), - intval($importer['uid']) - ); - } + // who is the last child now? + $r = q("SELECT `id` FROM `item` WHERE `parent-uri` = '%s' AND `type` != 'activity' AND `deleted` = 0 AND `uid` = %d + ORDER BY `edited` DESC LIMIT 1", + dbesc($item['parent-uri']), + intval($importer['uid']) + ); + if(count($r)) { + q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d LIMIT 1", + intval($r[0]['id']) + ); + } + } + } + } continue; } - $datarray = get_atom_elements($item); - $datarray['parent-uri'] = $item_id; - $datarray['uid'] = $importer['uid']; - $datarray['contact-id'] = $contact['id']; - $r = item_store($datarray); - continue; + $is_reply = false; + $item_id = $item->get_id(); + $rawthread = $item->get_item_tags( NAMESPACE_THREAD,'in-reply-to'); + if(isset($rawthread[0]['attribs']['']['ref'])) { + $is_reply = true; + $parent_uri = $rawthread[0]['attribs']['']['ref']; + } + + + if($is_reply) { + + // Have we seen it? If not, import it. + + $item_id = $item->get_id(); + + $r = q("SELECT `uid`, `last-child`, `edited` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", + dbesc($item_id), + intval($importer['uid']) + ); + // FIXME update content if 'updated' changes + if(count($r)) { + $allow = $item->get_item_tags( NAMESPACE_DFRN, 'comment-allow'); + if($allow && $allow[0]['data'] != $r[0]['last-child']) { + $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d", + dbesc(datetime_convert()), + dbesc($parent_uri), + intval($importer['uid']) + ); + $r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", + intval($allow[0]['data']), + dbesc(datetime_convert()), + dbesc($item_id), + intval($importer['uid']) + ); + + + } + continue; + } + $datarray = get_atom_elements($item); + $datarray['parent-uri'] = $parent_uri; + $datarray['uid'] = $importer['uid']; + $datarray['contact-id'] = $contact['id']; + if(($datarray['verb'] == ACTIVITY_LIKE) || ($datarray['verb'] == ACTIVITY_DISLIKE)) { + $datarray['type'] = 'activity'; + $datarray['gravity'] = GRAVITY_LIKE; + } + + $r = item_store($datarray); + continue; + } + + else { + // Head post of a conversation. Have we seen it? If not, import it. + + $item_id = $item->get_id(); + $r = q("SELECT `uid`, `last-child`, `edited` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", + dbesc($item_id), + intval($importer['uid']) + ); + if(count($r)) { + $allow = $item->get_item_tags( NAMESPACE_DFRN, 'comment-allow'); + if($allow && $allow[0]['data'] != $r[0]['last-child']) { + $r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", + intval($allow[0]['data']), + dbesc(datetime_convert()), + dbesc($item_id), + intval($importer['uid']) + ); + } + continue; + } + + $datarray = get_atom_elements($item); + $datarray['parent-uri'] = $item_id; + $datarray['uid'] = $importer['uid']; + $datarray['contact-id'] = $contact['id']; + $r = item_store($datarray); + continue; + + } } - } - $r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d LIMIT 1", dbesc(datetime_convert()), intval($contact['id']) diff --git a/index.php b/index.php index 9b9e708f75..0de0afd48d 100644 --- a/index.php +++ b/index.php @@ -89,6 +89,7 @@ $a->page['content'] .= $debug_text; $a->page['content'] .= '
'; // build page + // Navigation (menu) template if($a->module != 'install') require_once("nav.php"); diff --git a/mod/network.php b/mod/network.php index c5845f63c8..e9e730340b 100644 --- a/mod/network.php +++ b/mod/network.php @@ -7,7 +7,7 @@ function network_init(&$a) { } -function network_content(&$a, $update = false) { +function network_content(&$a, $update = 0) { if(! local_user()) return; @@ -59,7 +59,7 @@ function network_content(&$a, $update = false) { // criteria is discovered in javascript). if($a->pager['start'] == 0 && $a->argc == 1) - $o .= '
' . "\r\n"; + $o .= '
' . "\r\n"; } // We aren't going to try and figure out at the item, group, and page level diff --git a/mod/profile.php b/mod/profile.php index 31b634013c..0d9c94eedc 100644 --- a/mod/profile.php +++ b/mod/profile.php @@ -74,7 +74,11 @@ function profile_init(&$a) { } -function profile_content(&$a, $update = false) { +function profile_content(&$a, $update = 0) { + + + file_put_contents('uid.log',"{$_SERVER['QUERY_STRING']} ". session_id() . "\n", FILE_APPEND); + require_once("include/bbcode.php"); require_once('include/security.php'); @@ -86,13 +90,11 @@ function profile_content(&$a, $update = false) { if($update) { // Ensure we've got a profile owner if updating. - $a->profile['profile_uid'] = $_SESSION['profile_uid']; + $a->profile['profile_uid'] = $update; } else { - if($a->profile['uid'] == get_uid()) + if($a->profile['profile_uid'] == get_uid()) $o .= ''; - // set the uid so we can pick it up during update - $_SESSION['profile_uid'] = $a->profile['uid']; } $contact = null; @@ -158,8 +160,11 @@ function profile_content(&$a, $update = false) { )); } + // This is ugly, but we can't pass the profile_uid through the session to the ajax updater, + // because browser prefetching might change it on us. We have to deliver it with the page. + if($tab == 'posts' && (! $a->pager['start'])) - $o .= '
' . "\r\n"; + $o .= '
' . "\r\n"; } // TODO alter registration and settings and profile to update contact table when names and photos change. diff --git a/mod/update_network.php b/mod/update_network.php index 1c790ead16..35e968dba9 100644 --- a/mod/update_network.php +++ b/mod/update_network.php @@ -7,12 +7,14 @@ require_once('mod/network.php'); function update_network_content(&$a) { + $profile_uid = intval($_GET['p']); + header("Content-type: text/html"); echo "\r\n"; echo (($_GET['msie'] == 1) ? '
' : '
'); - $text = network_content($a,true); + $text = network_content($a,$profile_uid); $pattern = "/]*) src=\"([^\"]*)\"/"; $replace = "\r\n"; echo (($_GET['msie'] == 1) ? '
' : '
'); @@ -16,7 +18,7 @@ function update_profile_content(&$a) { // The only ones we need to fetch are those for new page additions, which we'll discover // on the client side and then swap the image back. - $text = profile_content($a,true); + $text = profile_content($a,$profile_uid); $pattern = "/]*) src=\"([^\"]*)\"/"; $replace = "