diff --git a/include/hubloc.php b/include/hubloc.php index 6cacf8dc0..02cbbfc4e 100644 --- a/include/hubloc.php +++ b/include/hubloc.php @@ -6,6 +6,8 @@ */ use Code\Lib\Channel; +use Code\Lib\Config; +use Code\Lib\Libzot; use Code\Lib\Time; use Code\Lib\Url; use Code\Daemon\Run; @@ -74,12 +76,17 @@ function site_store_lowlevel($arr) return create_table_from_array('site', $store); } +/** + * @brief Removes foreign location records which are no longer valid + * @return void + */ function prune_hub_reinstalls() { $r = q( - "select site_url from site where site_type = %d", - intval(SITE_TYPE_ZOT) + "select site_url from site where site_type = %d && site_url != '%s'", + intval(SITE_TYPE_ZOT), + dbesc(z_root()) ); if ($r) { foreach ($r as $rr) { @@ -99,10 +106,7 @@ function prune_hub_reinstalls() if (($d1 < $d2) && ($x[0]['hubloc_sitekey'])) { logger('prune_hub_reinstalls: removing dead hublocs at ' . $rr['site_url']); - $y = q( - "delete from hubloc where hubloc_sitekey = '%s'", - dbesc($x[0]['hubloc_sitekey']) - ); + hubloc_delete($x[0]); } } } @@ -111,72 +115,96 @@ function prune_hub_reinstalls() /** - * @brief Remove obsolete hublocs. + * @brief checks and repairs local hubloc records * - * Get rid of any hublocs which are ours but aren't valid anymore - - * e.g. they point to a different and perhaps transient URL that we aren't using. - * - * I need to stress that this shouldn't happen. fix_system_urls() fixes hublocs - * when it discovers the URL has changed. So it's unclear how we could end up - * with URLs pointing to the old site name. But it happens. This may be an artifact - * of an old bug or maybe a regression in some newer code. In any event, they - * mess up communications and we have to take action if we find any. + * This shouldn't happen. But it does. */ -function remove_obsolete_hublocs() +function check_hublocs() { - logger('remove_obsolete_hublocs', LOGGER_DEBUG); + $sitekey = Config::Get('system', 'pubkey'); + $interval = Config::Get('system', 'delivery_interval', 2); - // First make sure we have any hublocs (at all) with this URL and sitekey. - // We don't want to perform this operation while somebody is in the process - // of renaming their hub or installing certs. - - $r = q( - "select hubloc_id from hubloc where hubloc_url = '%s' and hubloc_sitekey = '%s'", - dbesc(z_root()), - dbesc(get_config('system', 'pubkey')) - ); - if ((! $r) || (! count($r))) { - return; - } - - // Good. We have at least one *valid* hubloc. - - // Do we have any invalid ones? - - $r = q( + $wrong_urls = q( "select hubloc_id from hubloc where hubloc_sitekey = '%s' and hubloc_url != '%s'", - dbesc(get_config('system', 'pubkey')), + dbesc($sitekey), dbesc(z_root()) ); - $p = q( + $wrong_keys = q( "select hubloc_id from hubloc where hubloc_sitekey != '%s' and hubloc_url = '%s'", - dbesc(get_config('system', 'pubkey')), + dbesc($sitekey), dbesc(z_root()) ); - if (is_array($r) && is_array($p)) { - $r = array_merge($r, $p); + if (is_array($wrong_urls) && is_array($wrong_keys)) { + $invalids = array_merge($wrong_urls, $wrong_keys); } - if (! $r) { - return; + if ($invalids) { + foreach ($invalids as $hubloc) { + logger('Removing invalid hubloc for ' . $hubloc['hubloc_addr'], LOGGER_DEBUG); + hubloc_delete($hubloc); + $channel = Channel::from_hash($hubloc['hubloc_hash']); + if ($channel) { + Run::Summon(['Notifier', 'refresh_all', $channel['channel_id']]); + if ($interval) { + @time_sleep_until(microtime(true) + (float)$interval); + } + } + } } - // We've got invalid hublocs. Get rid of them. + $channels = q("select * from channel where channel_removed = 0"); - logger('remove_obsolete_hublocs: removing ' . count($r) . ' hublocs.'); - - $interval = ((get_config('system', 'delivery_interval') !== false) - ? intval(get_config('system', 'delivery_interval')) : 2 ); - - // mark the hublocs deleted; spread out the notifications - foreach ($r as $rr) { - hubloc_delete($rr); - $x = Channel::from_hash($rr['hubloc_hash']); - if ($x) { - Run::Summon([ 'Notifier', 'refresh_all', $x['channel_id'] ]); - if ($interval) { - @time_sleep_until(microtime(true) + (float) $interval); + if ($channels) { + foreach ($channels as $channel) { + $hubs = q("select * from hubloc where hubloc_hash = '%s' and + hubloc_url = '%s' and hubloc_sitekey = '%s'", + dbesc($channel['channel_hash']), + dbesc(z_root()), + dbesc($sitekey) + ); + if (!$hubs) { + logger('Repairing hubloc for ' . $channel['channel_address'], LOGGER_DEBUG); + // This channel does not have a valid location (hubloc) + // set for this site. + $hubloc_addr = Channel::get_webfinger($channel); + $primary = 1; // if xchan is missing, make this location the primary + $xchans = q("select * from xchan where xchan_hash = '%s' limit 1", + dbesc($channel['channel_hash']) + ); + if ($xchans) { + $primary = (int)$xchans[0]['xchan_addr'] === $hubloc_addr; + } + $result = hubloc_store_lowlevel( + [ + 'hubloc_guid' => $channel['channel_guid'], + 'hubloc_guid_sig' => $channel['channel_guid_sig'], + 'hubloc_hash' => $channel['channel_hash'], + 'hubloc_id_url' => Channel::url($channel), + 'hubloc_addr' => Channel::get_webfinger($channel), + 'hubloc_primary' => $primary, + 'hubloc_url' => z_root(), + 'hubloc_url_sig' => Libzot::sign(z_root(), $channel['channel_prvkey']), + 'hubloc_site_id' => Libzot::make_xchan_hash(z_root(), $sitekey), + 'hubloc_host' => App::get_hostname(), + 'hubloc_callback' => z_root() . '/nomad', + 'hubloc_sitekey' => $sitekey, + 'hubloc_network' => 'nomad', + 'hubloc_updated' => Time::convert(), + 'hubloc_connected' => Time::convert() + ] + ); + if ($result) { + q("delete from hubloc where hubloc_hash = '%s' and hubloc_url = '%s' and hubloc_sitekey != '%s'", + dbesc($channel['channel_hash']), + dbesc(z_root()), + dbesc($sitekey) + ); + Run::Summon([ 'Notifier', 'refresh_all', $channel['channel_id'] ]); + if ($interval) { + @time_sleep_until(microtime(true) + (float) $interval); + } + } } } } diff --git a/src/Daemon/Cron_daily.php b/src/Daemon/Cron_daily.php index b426b8adb..523f3dfc4 100644 --- a/src/Daemon/Cron_daily.php +++ b/src/Daemon/Cron_daily.php @@ -94,7 +94,7 @@ class Cron_daily implements DaemonInterface Run::Summon([ 'Expire' ]); - remove_obsolete_hublocs(); + check_hublocs(); $data = Time::convert(); Hook::call('cron_daily', $data); diff --git a/src/Lib/Libzot.php b/src/Lib/Libzot.php index 429fa9e0c..3e60eaf71 100644 --- a/src/Lib/Libzot.php +++ b/src/Lib/Libzot.php @@ -868,13 +868,14 @@ class Libzot ) { $rup = q( "update xchan set xchan_updated = '%s', xchan_name = '%s', xchan_name_date = '%s', xchan_connurl = '%s', xchan_follow = '%s', - xchan_connpage = '%s', xchan_hidden = %d, xchan_selfcensored = %d, xchan_deleted = %d, xchan_type = %d, + xchan_epubkey = '%s', xchan_connpage = '%s', xchan_hidden = %d, xchan_selfcensored = %d, xchan_deleted = %d, xchan_type = %d, xchan_addr = '%s', xchan_url = '%s', xchan_network = '%s' where xchan_hash = '%s'", dbesc(Time::convert()), dbesc(($arr['name']) ? unicode_trim(escape_tags($arr['name'])) : '-'), dbesc($arr['name_updated']), dbesc($arr['primary_location']['connections_url']), dbesc($arr['primary_location']['follow_url']), + dbesc($arr['ed25519_key']), dbesc($arr['primary_location']['connect_url']), intval(1 - intval($arr['searchable'])), intval($arr['adult_content']),