Commit 62e466f7 authored by Mario's avatar Mario

Merge branch 'dev'

parents 70777a04 47fd95db
Hubzilla 4.0.2 (2019-04-08)
- Port cdav calendar to fullcalendar version 4
- Fix perms_pending not evaluated correctly
- Fix return wrong profile photo modification date by plugin
- Fix suggestion widget using feature_enabled still
- Fix check service class limits when syncing files
- Remove xchan_instance_url from notifier query - it is not used anymore
- Implement remove cover photo functionality
- Fix z6_discover() and create a zot6 hubloc on import if applicable
- Add backend support for connections ordering
- Deduplicate items in item_store() by uuid if we got one otherwise by mid
- Add ITEM_TYPE_CUSTOM support to mod display
- Fix mod subthread on sys channel items
- Fix "recipient not found" dreport spaming with own xchan
- Fix wrong variables in dirsearch
- Fix 48 hours timeframe check in mod changeaddr
- Fix wrong variable in Libsync
- Pubcrawl: revert adding additional receivers to comments
- Diaspora: fix intro received when being banned
- Pubcrawl: add diaspora:guid from friendica AP posts for deduplication
- Diaspora: fix friendica plink
- Photocache: fix issue with spaces and quotes in original filenames
Hubzilla 4.0.1 (2019-03-21)
- Fix permissions not getting decrypted on follow
- Add option to add a poster to the video bbcode
......
......@@ -452,7 +452,7 @@ class Notifier {
$env_recips = (($private) ? array() : null);
$details = q("select xchan_hash, xchan_instance_url, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . protect_sprintf(implode(',',$recipients)) . ")");
$details = q("select xchan_hash, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . protect_sprintf(implode(',',$recipients)) . ")");
$recip_list = array();
......
......@@ -118,7 +118,7 @@ class DReport {
// So if a remote site says they can't find us, that's no big surprise
// and just creates a lot of extra report noise
if(($dr['location'] !== z_root()) && ($dr['sender'] === $rxchan) && ($dr['status'] === 'recipient_not_found'))
if(($dr['location'] !== z_root()) && ($dr['sender'] === $rxchan) && ($dr['status'] === 'recipient not found'))
return false;
// If you have a private post with a recipient list, every single site is going to report
......
......@@ -336,7 +336,7 @@ class Libsync {
$disallowed = array('abook_id','abook_account','abook_channel','abook_rating','abook_rating_text','abook_not_here');
$fields = db_columns($abook);
$fields = db_columns('abook');
foreach($arr['abook'] as $abook) {
......
......@@ -307,7 +307,7 @@ class Libzotdir {
if ($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) {
$success = false;
$href = \Zotlabs\Lib\Webfinger::zot_url(punify($url));
$href = \Zotlabs\Lib\Webfinger::zot_url(punify($ud['ud_addr']));
if($href) {
$zf = \Zotlabs\Lib\Zotfinger::exec($href);
}
......@@ -651,4 +651,4 @@ class Libzotdir {
}
\ No newline at end of file
}
......@@ -66,7 +66,7 @@ class ZotURL {
}
static public function is_zoturl($s) {
static public function is_zoturl($url) {
if(strpos($url,'x-zot:') === 0) {
return true;
......
......@@ -166,7 +166,7 @@ class Acl extends \Zotlabs\Web\Controller {
if($extra_channels) {
foreach($extra_channels as $channel) {
if(perm_is_allowed(intval($channel), get_observer_hash(),'view_contacts')) {
if($extra_channel_sql)
if($extra_channels_sql)
$extra_channels_sql .= ',';
$extra_channels_sql .= intval($channel);
}
......
......@@ -280,9 +280,12 @@ class Cdav extends Controller {
return;
$title = $_REQUEST['title'];
$dtstart = new \DateTime($_REQUEST['dtstart']);
if($_REQUEST['dtend'])
$dtend = new \DateTime($_REQUEST['dtend']);
$start = datetime_convert(App::$timezone, 'UTC', $_REQUEST['dtstart']);
$dtstart = new \DateTime($start);
if($_REQUEST['dtend']) {
$end = datetime_convert(App::$timezone, 'UTC', $_REQUEST['dtend']);
$dtend = new \DateTime($end);
}
$description = $_REQUEST['description'];
$location = $_REQUEST['location'];
......@@ -306,13 +309,17 @@ class Cdav extends Controller {
'DTSTART' => $dtstart
]
]);
if($dtend)
if($dtend) {
$vcalendar->VEVENT->add('DTEND', $dtend);
$vcalendar->VEVENT->DTEND['TZID'] = App::$timezone;
}
if($description)
$vcalendar->VEVENT->add('DESCRIPTION', $description);
if($location)
$vcalendar->VEVENT->add('LOCATION', $location);
$vcalendar->VEVENT->DTSTART['TZID'] = App::$timezone;
$calendarData = $vcalendar->serialize();
$caldavBackend->createCalendarObject($id, $objectUri, $calendarData);
......@@ -351,8 +358,12 @@ class Cdav extends Controller {
$uri = $_REQUEST['uri'];
$title = $_REQUEST['title'];
$dtstart = new \DateTime($_REQUEST['dtstart']);
$dtend = $_REQUEST['dtend'] ? new \DateTime($_REQUEST['dtend']) : '';
$start = datetime_convert(App::$timezone, 'UTC', $_REQUEST['dtstart']);
$dtstart = new \DateTime($start);
if($_REQUEST['dtend']) {
$end = datetime_convert(App::$timezone, 'UTC', $_REQUEST['dtend']);
$dtend = new \DateTime($end);
}
$description = $_REQUEST['description'];
$location = $_REQUEST['location'];
......@@ -404,8 +415,12 @@ class Cdav extends Controller {
return;
$uri = $_REQUEST['uri'];
$dtstart = new \DateTime($_REQUEST['dtstart']);
$dtend = $_REQUEST['dtend'] ? new \DateTime($_REQUEST['dtend']) : '';
$start = datetime_convert(App::$timezone, 'UTC', $_REQUEST['dtstart']);
$dtstart = new \DateTime($start);
if($_REQUEST['dtend']) {
$end = datetime_convert(App::$timezone, 'UTC', $_REQUEST['dtend']);
$dtend = new \DateTime($end);
}
$object = $caldavBackend->getCalendarObject($id, $uri);
......@@ -877,12 +892,19 @@ class Cdav extends Controller {
//Display calendar(s) here
if(argc() == 2 && argv(1) === 'calendar') {
head_add_css('/library/fullcalendar/fullcalendar.css');
head_add_css('/library/fullcalendar/packages/core/main.min.css');
head_add_css('/library/fullcalendar/packages/daygrid/main.min.css');
head_add_css('/library/fullcalendar/packages/timegrid/main.min.css');
head_add_css('/library/fullcalendar/packages/list/main.min.css');
head_add_css('cdav_calendar.css');
head_add_js('/library/moment/moment.min.js', 1);
head_add_js('/library/fullcalendar/fullcalendar.min.js', 1);
head_add_js('/library/fullcalendar/locale-all.js', 1);
head_add_js('/library/fullcalendar/packages/core/main.min.js');
head_add_js('/library/fullcalendar/packages/interaction/main.min.js');
head_add_js('/library/fullcalendar/packages/daygrid/main.min.js');
head_add_js('/library/fullcalendar/packages/timegrid/main.min.js');
head_add_js('/library/fullcalendar/packages/list/main.min.js');
$sources = '';
foreach($calendars as $calendar) {
$editable = (($calendar['share-access'] == 2) ? 'false' : 'true'); // false/true must be string since we're passing it to javascript
......@@ -891,6 +913,7 @@ class Cdav extends Controller {
$switch = get_pconfig(local_channel(), 'cdav_calendar', $calendar['id'][0]);
if($switch) {
$sources .= '{
id: ' . $calendar['id'][0] . ',
url: \'/cdav/calendar/json/' . $calendar['id'][0] . '/' . $calendar['id'][1] . '\',
color: \'' . $color . '\'
}, ';
......@@ -911,8 +934,8 @@ class Cdav extends Controller {
$first_day = (($first_day) ? $first_day : 0);
$title = ['title', t('Event title')];
$dtstart = ['dtstart', t('Start date and time'), '', t('Example: YYYY-MM-DD HH:mm')];
$dtend = ['dtend', t('End date and time'), '', t('Example: YYYY-MM-DD HH:mm')];
$dtstart = ['dtstart', t('Start date and time')];
$dtend = ['dtend', t('End date and time')];
$description = ['description', t('Description')];
$location = ['location', t('Location')];
......@@ -920,6 +943,7 @@ class Cdav extends Controller {
'$sources' => $sources,
'$color' => $color,
'$lang' => App::$language,
'$timezone' => App::$timezone,
'$first_day' => $first_day,
'$prev' => t('Previous'),
'$next' => t('Next'),
......@@ -952,10 +976,12 @@ class Cdav extends Controller {
//Provide json data for calendar
if(argc() == 5 && argv(1) === 'calendar' && argv(2) === 'json' && intval(argv(3)) && intval(argv(4))) {
$events = [];
$id = [argv(3), argv(4)];
if(! cdav_perms($id[0],$calendars))
killme();
json_return_and_die($events);
if (x($_GET,'start'))
$start = new \DateTime($_GET['start']);
......@@ -969,16 +995,19 @@ class Cdav extends Controller {
$filters['comp-filters'][0]['time-range']['end'] = $end;
$uris = $caldavBackend->calendarQuery($id, $filters);
if($uris) {
if($uris) {
$objects = $caldavBackend->getMultipleCalendarObjects($id, $uris);
foreach($objects as $object) {
$vcalendar = \Sabre\VObject\Reader::read($object['calendardata']);
if(isset($vcalendar->VEVENT->RRULE))
if(isset($vcalendar->VEVENT->RRULE)) {
// expanding recurrent events seems to loose timezone info
// save it here so we can add it later
$recurrent_timezone = (string)$vcalendar->VEVENT->DTSTART['TZID'];
$vcalendar = $vcalendar->expand($start, $end);
}
foreach($vcalendar->VEVENT as $vevent) {
$title = (string)$vevent->SUMMARY;
......@@ -986,14 +1015,15 @@ class Cdav extends Controller {
$dtend = (string)$vevent->DTEND;
$description = (string)$vevent->DESCRIPTION;
$location = (string)$vevent->LOCATION;
$timezone = (string)$vevent->DTSTART['TZID'];
$rw = ((cdav_perms($id[0],$calendars,true)) ? true : false);
$recurrent = ((isset($vevent->{'RECURRENCE-ID'})) ? true : false);
$editable = $rw ? true : false;
$recurrent = ((isset($vevent->{'RECURRENCE-ID'})) ? true : false);
if($recurrent)
if($recurrent) {
$editable = false;
$timezone = $recurrent_timezone;
}
$allDay = false;
......@@ -1007,8 +1037,8 @@ class Cdav extends Controller {
'calendar_id' => $id,
'uri' => $object['uri'],
'title' => $title,
'start' => $dtstart,
'end' => $dtend,
'start' => datetime_convert($timezone, $timezone, $dtstart, 'c'),
'end' => (($dtend) ? datetime_convert($timezone, $timezone, $dtend, 'c') : ''),
'description' => $description,
'location' => $location,
'allDay' => $allDay,
......@@ -1018,11 +1048,8 @@ class Cdav extends Controller {
];
}
}
json_return_and_die($events);
}
else {
killme();
}
json_return_and_die($events);
}
//enable/disable calendars
......
......@@ -31,7 +31,7 @@ class Changeaddr extends \Zotlabs\Web\Controller {
if($account['account_password_changed'] > NULL_DATE) {
$d1 = datetime_convert('UTC','UTC','now - 48 hours');
if($account['account_password_changed'] > d1) {
if($account['account_password_changed'] > $d1) {
notice( t('Channel name changes are not allowed within 48 hours of changing the account password.') . EOL);
return;
}
......@@ -49,7 +49,7 @@ class Changeaddr extends \Zotlabs\Web\Controller {
if(check_webbie(array($new_address)) !== $new_address) {
notice( t('Nickname has unsupported characters or is already being used on this site.') . EOL);
return $ret;
return;
}
channel_change_address($channel,$new_address);
......
......@@ -127,6 +127,20 @@ class Connections extends \Zotlabs\Web\Controller {
$unblocked = true;
}
switch($_REQUEST['order']) {
case 'name_desc':
$sql_order = 'xchan_name DESC';
break;
case 'connected':
$sql_order = 'abook_created';
break;
case 'connected_desc':
$sql_order = 'abook_created DESC';
break;
default:
$sql_order = 'xchan_name';
}
$search = ((x($_REQUEST,'search')) ? notags(trim($_REQUEST['search'])) : '');
$tabs = array(
......@@ -233,7 +247,7 @@ class Connections extends \Zotlabs\Web\Controller {
}
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
WHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra $sql_extra2 ORDER BY xchan_name LIMIT %d OFFSET %d ",
WHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra $sql_extra2 ORDER BY $sql_order LIMIT %d OFFSET %d ",
intval(local_channel()),
intval(App::$pager['itemspage']),
intval(App::$pager['start'])
......@@ -307,7 +321,7 @@ class Connections extends \Zotlabs\Web\Controller {
'ignore_hover' => t('Ignore connection'),
'ignore' => ((! $rr['abook_ignored']) ? t('Ignore') : false),
'recent_label' => t('Recent activity'),
'recentlink' => z_root() . '/network/?f=&cid=' . intval($rr['abook_id']),
'recentlink' => z_root() . '/network/?f=&cid=' . intval($rr['abook_id']) . '&name=' . $rr['xchan_name'],
'oneway' => $oneway
);
}
......
......@@ -48,6 +48,29 @@ class Cover_photo extends \Zotlabs\Web\Controller {
$channel = \App::get_channel();
check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
// Remove cover photo
if(isset($_POST['remove'])) {
$r = q("SELECT resource_id FROM photo WHERE photo_usage = %d AND uid = %d LIMIT 1",
intval(PHOTO_COVER),
intval(local_channel())
);
if($r) {
q("update photo set photo_usage = %d where photo_usage = %d and uid = %d",
intval(PHOTO_NORMAL),
intval(PHOTO_COVER),
intval(local_channel())
);
$sync = attach_export_data($channel,$r[0]['resource_id']);
if($sync)
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
}
goaway(z_root() . '/cover_photo');
}
if((array_key_exists('cropfinal',$_POST)) && ($_POST['cropfinal'] == 1)) {
......@@ -195,10 +218,12 @@ logger('gis: ' . print_r($gis,true));
);
return;
}
$channel = \App::get_channel();
$this->send_cover_photo_activity($channel,$base_image,$profile);
$sync = attach_export_data($channel,$base_image['resource_id']);
if($sync)
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
}
else
......@@ -215,7 +240,7 @@ logger('gis: ' . print_r($gis,true));
require_once('include/attach.php');
$res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Cover Photos'), 'hash' => $hash));
$res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Cover Photos'), 'hash' => $hash, 'nosync' => true));
logger('attach_store: ' . print_r($res,true));
......@@ -393,6 +418,7 @@ logger('gis: ' . print_r($gis,true));
'$lbl_profiles' => t('Select a profile:'),
'$title' => t('Change Cover Photo'),
'$submit' => t('Upload'),
'$remove' => t('Remove'),
'$profiles' => $profiles,
'$embedPhotos' => t('Use a photo from your albums'),
'$embedPhotosModalTitle' => t('Use a photo from your albums'),
......
......@@ -116,12 +116,12 @@ class Dirsearch extends \Zotlabs\Web\Controller {
$sql_extra .= $this->dir_query_build($joiner,'xchan_name',$name);
if($address)
$sql_extra .= $this->dir_query_build($joiner,'xchan_addr',$address);
if($city)
$sql_extra .= $this->dir_query_build($joiner,'xprof_locale',$city);
if($locale)
$sql_extra .= $this->dir_query_build($joiner,'xprof_locale',$locale);
if($region)
$sql_extra .= $this->dir_query_build($joiner,'xprof_region',$region);
if($post)
$sql_extra .= $this->dir_query_build($joiner,'xprof_postcode',$post);
if($postcode)
$sql_extra .= $this->dir_query_build($joiner,'xprof_postcode',$postcode);
if($country)
$sql_extra .= $this->dir_query_build($joiner,'xprof_country',$country);
if($gender)
......
......@@ -175,6 +175,11 @@ class Display extends \Zotlabs\Web\Controller {
return '';
}
}
if ($target_item['item_type'] == ITEM_TYPE_CUSTOM) {
call_hooks('item_custom_display',$target_item);
notice( t('Page not found.') . EOL);
return '';
}
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
......
......@@ -8,6 +8,8 @@ require_once('include/import.php');
require_once('include/perm_upgrade.php');
require_once('library/urlify/URLify.php');
use Zotlabs\Lib\Libzot;
/**
* @brief Module for channel import.
......@@ -228,13 +230,45 @@ class Import extends \Zotlabs\Web\Controller {
);
// reset the original primary hubloc if it is being seized
if($seize) {
$r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ",
dbesc($channel['channel_hash']),
dbesc(z_root())
);
}
// create a new zot6 hubloc if we have got a channel_portable_id
if($channel['channel_portable_id']) {
$r = hubloc_store_lowlevel(
[
'hubloc_guid' => $channel['channel_guid'],
'hubloc_guid_sig' => 'sha256.' . $channel['channel_guid_sig'],
'hubloc_hash' => $channel['channel_portable_id'],
'hubloc_addr' => channel_reddress($channel),
'hubloc_network' => 'zot6',
'hubloc_primary' => (($seize) ? 1 : 0),
'hubloc_url' => z_root(),
'hubloc_url_sig' => 'sha256.' . base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])),
'hubloc_host' => \App::get_hostname(),
'hubloc_callback' => z_root() . '/zot',
'hubloc_sitekey' => get_config('system','pubkey'),
'hubloc_updated' => datetime_convert(),
'hubloc_id_url' => channel_url($channel),
'hubloc_site_id' => Libzot::make_xchan_hash(z_root(),get_config('system','pubkey'))
]
);
// reset the original primary hubloc if it is being seized
if($seize) {
$r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ",
dbesc($channel['channel_portable_id']),
dbesc(z_root())
);
}
}
}
logger('import step 5');
......
......@@ -166,7 +166,7 @@ class Item extends Controller {
if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream'))
http_status_exit(403, 'Forbidden');
$i = Activity::encode_item_collection($nitems,'conversation/' . $item_id,'OrderedCollection',( defined('NOMADIC') ? false : true));
$i = Activity::encode_item_collection($nitems,'conversation/' . $item_id,'OrderedCollection');
if($portable_id) {
ThreadListener::store(z_root() . '/item/' . $item_id,$portable_id);
}
......
......@@ -71,29 +71,32 @@ class Photo extends \Zotlabs\Web\Controller {
$modified = filemtime($default);
$default = z_root() . '/' . $default;
$uid = $person;
$data = '';
$d = [ 'imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '' ];
call_hooks('get_profile_photo',$d);
$resolution = $d['imgscale'];
$uid = $d['channel_id'];
$default = $d['default'];
$data = $d['data'];
$mimetype = $d['mimetype'];
$r = q("SELECT * FROM photo WHERE imgscale = %d AND uid = %d AND photo_usage = %d LIMIT 1",
intval($resolution),
intval($uid),
intval(PHOTO_PROFILE)
);
if($r) {
$modified = strtotime($r[0]['edited'] . "Z");
$mimetype = $r[0]['mimetype'];
if(intval($r[0]['os_storage']))
$data = file_get_contents($data);
else
$data = dbunescbin($r[0]['content']);
}
if(! $data) {
$r = q("SELECT * FROM photo WHERE imgscale = %d AND uid = %d AND photo_usage = %d LIMIT 1",
intval($resolution),
intval($uid),
intval(PHOTO_PROFILE)
);
if($r) {
$modified = strtotime($r[0]['edited'] . "Z");
$data = dbunescbin($r[0]['content']);
$mimetype = $r[0]['mimetype'];
}
if(intval($r[0]['os_storage']))
$data = file_get_contents($data);
$d = [ 'imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '' ];
call_hooks('get_profile_photo',$d);
$resolution = $d['imgscale'];
$uid = $d['channel_id'];
$default = $d['default'];
$data = $d['data'];
$mimetype = $d['mimetype'];
}
if(! $data) {
......
......@@ -33,7 +33,7 @@ class Subthread extends \Zotlabs\Web\Controller {
if(! $i) {
$i = q("select * from item where id = %d and uid = %d",
intval($postid),
intval($item_id),
intval($sys['channel_id'])
);
......
......@@ -69,7 +69,7 @@ class Tagger extends \Zotlabs\Web\Controller {
$post_type = t('photo');
break;
case 'event':
$targgettype = ACTIVITY_OBJ_EVENT;
$targettype = ACTIVITY_OBJ_EVENT;
$post_type = t('event');
break;
default:
......
......@@ -2,6 +2,8 @@
namespace Zotlabs\Widget;
use Zotlabs\Lib\Apps;
require_once('include/socgraph.php');
......@@ -9,9 +11,9 @@ class Suggestions {
function widget($arr) {
if((! local_channel()) || (! feature_enabled(local_channel(),'suggest')))
return '';
if((! local_channel()) || (! Apps::system_app_installed(local_channel(), 'Suggest Channels')))
return EMPTY_STR;
$r = suggestion_query(local_channel(),get_observer_hash(),0,20);
......
......@@ -50,7 +50,7 @@ require_once('include/attach.php');
require_once('include/bbcode.php');
define ( 'PLATFORM_NAME', 'hubzilla' );
define ( 'STD_VERSION', '4.0.1' );
define ( 'STD_VERSION', '4.1.2' );
define ( 'ZOT_REVISION', '6.0a' );
define ( 'DB_UPDATE_VERSION', 1231 );
......
......@@ -360,14 +360,6 @@ function get_features($filtered = true, $level = (-1)) {
get_config('feature_lock','personal_tab')
],
[
'suggest',
t('Suggest Channels'),
t('Show friend and connection suggestions'),
false,
get_config('feature_lock','suggest')
],
[
'network_list_mode',
t('Use blog/list mode'),
......
......@@ -311,7 +311,9 @@ function z6_discover() {
// find unregistered zot6 clone hublocs
$c = q("select channel_hash, portable_id from channel where channel_deleted = 0");
$c = q("select channel_hash, channel_portable_id from channel where channel_deleted = '%s'",
dbesc(NULL_DATE)
);
if ($c) {
foreach ($c as $entry) {
$q1 = q("select * from hubloc left join site on hubloc_url = site_url where hubloc_deleted = 0 and site_dead = 0 and hubloc_hash = '%s' and hubloc_url != '%s'",
......@@ -325,19 +327,19 @@ function z6_discover() {
// does this particular server have a zot6 clone registered on our site for this channel?
foreach ($q1 as $q) {
$q2 = q("select * from hubloc left join site on hubloc_url = site_url where hubloc_deleted = 0 and site_dead = 0 and hubloc_hash = '%s' and hubloc_url = '%s'",
dbesc($entry['portable_id']),
dbesc($entry['channel_portable_id']),
dbesc($q['hubloc_url'])
);
if ($q2) {
continue;
}
// zot6 hubloc not found.
if(strpos($entry['site_project'],'hubzilla') !== false && version_compare($entry['site_version'],'4.0') >= 0) {
if(strpos($q['site_project'],'hubzilla') !== false && version_compare($q['site_version'],'4.0') >= 0) {
// probe and store results - only for zot6 (over-ride the zot default)
discover_by_webbie($entry['hubloc_addr'],'zot6');
discover_by_webbie($q['hubloc_addr'],'zot6');
}
}
}
}
}
\ No newline at end of file
}