From 29cb62af3dba0a6a2891800cfe97578c1a2819ae Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 28 Feb 2019 17:51:13 -0800 Subject: [PATCH 01/33] translate name of content filter (addon) app. --- Zotlabs/Lib/Apps.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 56283ff76..7541c68a4 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -327,6 +327,7 @@ class Apps { 'Report Bug' => t('Report Bug'), 'Bookmarks' => t('Bookmarks'), 'Chatrooms' => t('Chatrooms'), + 'Content Filter' => t('Content Filter'), 'Connections' => t('Connections'), 'Remote Diagnostics' => t('Remote Diagnostics'), 'Suggest Channels' => t('Suggest Channels'), From 2244bf2ba2e8611017de51fbeb3c449efef906f0 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 1 Mar 2019 14:16:19 +0100 Subject: [PATCH 02/33] iron out some kinks with scrollToItem() in combination with collapsed content and images --- view/js/main.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/view/js/main.js b/view/js/main.js index b1af29846..1322c2112 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -770,7 +770,7 @@ function updateConvItems(mode,data) { mediaPlaying = false; }); - var bimgs = ((preloadImages) ? false : $(".wall-item-body img, .wall-photo-item img").not(function() { return this.complete; })); + var bimgs = $(".wall-item-body img, .wall-photo-item img").not(function() { return this.complete; }); var bimgcount = bimgs.length; if (bimgcount) { @@ -778,16 +778,22 @@ function updateConvItems(mode,data) { bimgcount--; if (! bimgcount) { collapseHeight(); + + if(bParam_mid && mode === 'replace') + scrollToItem(); + + $(document.body).trigger("sticky_kit:recalc"); } }); } else { collapseHeight(); + + if(bParam_mid && mode === 'replace') + scrollToItem(); + + $(document.body).trigger("sticky_kit:recalc"); } - if(bParam_mid && mode === 'replace') - scrollToItem(); - - $(document.body).trigger("sticky_kit:recalc"); } function scrollToItem() { From 5febc3e07dd1c1aeda68c09b4092d5d4219f39b5 Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Fri, 1 Mar 2019 10:50:10 -0500 Subject: [PATCH 03/33] Use sender hash --- include/zot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zot.php b/include/zot.php index 3b089831b..c9c01103c 100644 --- a/include/zot.php +++ b/include/zot.php @@ -1840,7 +1840,7 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ intval($channel['channel_id']) ); if ($parent) { - $allowed = can_comment_on_post($d['hash'],$parent[0]); + $allowed = can_comment_on_post($sender['hash'],$parent[0]); } } From 747ce9b1f15d3f656ed8ca816c1790c351decec9 Mon Sep 17 00:00:00 2001 From: mike Date: Sat, 2 Mar 2019 12:21:59 +0300 Subject: [PATCH 04/33] Mention php-zip module dependency in administrator guide --- doc/admin/administrator_guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/admin/administrator_guide.md b/doc/admin/administrator_guide.md index 5f1d40428..2b1c84180 100644 --- a/doc/admin/administrator_guide.md +++ b/doc/admin/administrator_guide.md @@ -95,7 +95,7 @@ PHP might differ from the _webserver_ version php.ini file * and with no hosting provider restrictions on the use of exec() and proc_open(). -* curl, gd (with at least jpeg and png support), mysqli, mbstring, mcrypt, +* curl, gd (with at least jpeg and png support), mysqli, mbstring, mcrypt, zip, and openssl extensions. The imagick extension is not required but desirable. * xml extension is required if you want webdav to work. From 117a8cafca6982e7d976fe00f32ecb0df66b2899 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 2 Mar 2019 15:50:53 +0100 Subject: [PATCH 05/33] while in legacy zot $sender is expected to be an array, in zot6 $sender is expected to be a string (xchan_hash) --- Zotlabs/Lib/Libzot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index 019237568..6190c9970 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -1385,7 +1385,7 @@ class Libzot { /** * @brief * - * @param array $sender + * @param string $sender * @param array $arr * @param array $deliveries * @param boolean $relay From e26de9c1d11dc8175ea520be091f0437d99ea5e0 Mon Sep 17 00:00:00 2001 From: mike Date: Sun, 3 Mar 2019 18:24:36 +0300 Subject: [PATCH 06/33] Addressing new 'support@zotadel.net' support forum instead of old 'support@gravizot.de' --- doc/bugs.bb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/bugs.bb b/doc/bugs.bb index f773da025..3bf2a0e29 100644 --- a/doc/bugs.bb +++ b/doc/bugs.bb @@ -21,7 +21,7 @@ If you get a blank white screen when doing something, this is almost always a co [h3]I'm stumped. I can't figure out what is wrong.[/h3] -At this point it might be worthwhile discussing the issue on one of the online forums. There may be several of these and some may be more suited to your spoken language. At this time, the 'Hubzilla Support' channel (support@gravizot.de) is the recommended forum for discussing bugs. +At this point it might be worthwhile discussing the issue on one of the online forums. There may be several of these and some may be more suited to your spoken language. At this time, the 'Hubzilla Support' channel (support@zotadel.net) is the recommended forum for discussing bugs. If community members with software engineering training/expertise can't help you right away, understand that they are volunteers and may have a lot of other work and demands on their time. At this point you need to file a bug report. You will need an account on framagit.org to do this. So register, and then visit https://framagit.org/hubzilla/core/issues . Create an issue here and provide all the same information that you provided online. Don't leave out anything. @@ -29,4 +29,4 @@ Then you wait. If it's a high profile issue, it may get fixed quickly. But nobod Other people working to fix the problem may need to find out more, so do your homework and document what is happening and everything you've tried. Don't say "I did xyz and it didn't work." That doesn't tell us anything. Tell us precisely what steps you took and what you expected the result to be, and precisely what happened as a result. What page/URL were you looking at or what form were you filling in? If there were any error messages, don't say "there was an error message". Tell us exactly what the message said. Also tell us what hub you are using, what software version you're running and any other details that may be unique about your site configuration. It is understood that you might wish to keep some information and your connections private, however if you aren't willing to share the information other people need to reproduce/fix the problem, it may not get fixed. - \ No newline at end of file + From 938fcdd1a6e8db47d2e66d68f8face9925bb7963 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 4 Mar 2019 20:07:01 -0800 Subject: [PATCH 07/33] mod_oep: photos/album/xxxxx is no longer hex2bin/bin2hex but the album hash and is throwing php warnings when trying to decode --- Zotlabs/Module/Oep.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Module/Oep.php b/Zotlabs/Module/Oep.php index c0d8e15e5..3977ac8dd 100644 --- a/Zotlabs/Module/Oep.php +++ b/Zotlabs/Module/Oep.php @@ -456,7 +456,7 @@ class Oep extends \Zotlabs\Web\Controller { if(preg_match('|//(.*?)/(.*?)/(.*?)/album/|',$url,$matches)) { $chn = $matches[3]; - $res = hex2bin(basename($url)); + $res = basename($url); } if(! ($chn && $res)) From 8e50fecccca5dd72a49869502e541db03632cd86 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 4 Mar 2019 20:09:47 -0800 Subject: [PATCH 08/33] remove clones from delivery recipients for top-level posts - they will get the post via clone sync --- Zotlabs/Daemon/Notifier.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php index df73d977d..4e0c0d49c 100644 --- a/Zotlabs/Daemon/Notifier.php +++ b/Zotlabs/Daemon/Notifier.php @@ -412,6 +412,12 @@ class Notifier { $private = false; $recipients = collect_recipients($parent_item,$private); + + if ($top_level_post) { + // remove clones who will receive the post via sync + $recipients = array_diff($recipients, [ $target_item['owner_xchan'] ]); + } + // FIXME add any additional recipients such as mentions, etc. // don't send deletions onward for other people's stuff From 47001c33039e6915f12b95a3e948caae6cf21d41 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 4 Mar 2019 20:11:43 -0800 Subject: [PATCH 09/33] api_router - allow parameters as final path argument --- Zotlabs/Lib/Api_router.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Zotlabs/Lib/Api_router.php b/Zotlabs/Lib/Api_router.php index 404678bd9..6e3f231a9 100644 --- a/Zotlabs/Lib/Api_router.php +++ b/Zotlabs/Lib/Api_router.php @@ -12,8 +12,16 @@ class Api_router { } static function find($path) { - if(array_key_exists($path,self::$routes)) + if (array_key_exists($path,self::$routes)) { return self::$routes[$path]; + } + + $with_params = dirname($path) . '/[id]'; + + if (array_key_exists($with_params,self::$routes)) { + return self::$routes[$with_params]; + } + return null; } From 98b1c7a38c3f3ef8ba7d36b77d9366691c3fbf15 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 5 Mar 2019 16:57:32 -0800 Subject: [PATCH 10/33] maintain compatibility with recent zot6 changes --- Zotlabs/Lib/Libzot.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index 6190c9970..7dca2e78a 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -685,8 +685,14 @@ class Libzot { $adult_changed = 1; if(intval($r[0]['xchan_deleted']) != intval($arr['deleted'])) $deleted_changed = 1; + // old style if(intval($r[0]['xchan_pubforum']) != intval($arr['public_forum'])) $pubforum_changed = 1; + // new style 6-MAR-2019 + if(array_key_exists('channel_type',$arr) && intval($arr['channel_type']) < 2 && intval($r[0]['xchan_pubforum']) !== intval($arr['channel_type'])) { + $pubforum_changed = 1; + $arr['public_forum'] = $arr['channel_type']; + } if($arr['protocols']) { $protocols = implode(',',$arr['protocols']); From 26e7da0b969c834cc6c2ff7c00713c7be05cb5c4 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 5 Mar 2019 17:06:42 -0800 Subject: [PATCH 11/33] channel_type is not integer --- Zotlabs/Lib/Libzot.php | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index 7dca2e78a..4efd869f3 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -685,14 +685,26 @@ class Libzot { $adult_changed = 1; if(intval($r[0]['xchan_deleted']) != intval($arr['deleted'])) $deleted_changed = 1; + + // new style 6-MAR-2019 + + if(array_key_exists('channel_type',$arr)) { + if($arr['channel_type'] === 'collection') { + // do nothing at this time. + } + elseif($arr['channel_type'] === 'group') { + $arr['public_forum'] = 1; + } + else { + $arr['public_forum'] = 0; + } + } + // old style + if(intval($r[0]['xchan_pubforum']) != intval($arr['public_forum'])) $pubforum_changed = 1; - // new style 6-MAR-2019 - if(array_key_exists('channel_type',$arr) && intval($arr['channel_type']) < 2 && intval($r[0]['xchan_pubforum']) !== intval($arr['channel_type'])) { - $pubforum_changed = 1; - $arr['public_forum'] = $arr['channel_type']; - } + if($arr['protocols']) { $protocols = implode(',',$arr['protocols']); From 0c05e6593e020180ca678dff6d60c095e23b34cd Mon Sep 17 00:00:00 2001 From: "M. Dent" Date: Wed, 6 Mar 2019 09:52:26 +0100 Subject: [PATCH 12/33] Add CURLOPT_CONNECTTIMEOUT --- include/network.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/network.php b/include/network.php index 8ac71011e..12f2ad4e9 100644 --- a/include/network.php +++ b/include/network.php @@ -114,6 +114,13 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { @curl_setopt($ch, CURLOPT_TIMEOUT, (($curl_time !== false) ? $curl_time : 60)); } + if(x($opts,'connecttimeout') && intval($opts['connecttimeout'])) { + @curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, intval($opts['connecttimeout'])); + } + else { + $curl_contime = intval(@get_config('system','curl_connecttimeout')); + @curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, (($curl_contime !== false) ? $curl_contime : 30)); + } if(x($opts,'http_auth')) { // "username" . ':' . "password" From 08725c44c6874bdbbb46649645a9ac818f0abe36 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 6 Mar 2019 21:08:56 +0100 Subject: [PATCH 13/33] changelog --- CHANGELOG | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 0e3e89a9e..4c9385b24 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,107 @@ +Hubzilla 4.0 (2019-??-??) + - Add CURLOPT_CONNECTTIMEOUT option + - Allow parameters as final path argument in API router + - Remove clones from delivery recipients for top-level posts in favor of clone sync + - Mention php-zip module dependency in administrator guide + - Iron out some kinks with scrollToItem() in combination with collapsed content and images + - Zot API changes to support combined content (items+files) import addon + - Update PHP Version check during setup - min version is now 7.1 + - Urlencode links in category widget + - Implement ability for channel visitors to be able to delete their own content + - Support zot location independent urls + - MySQL 8 admin summary compatibility + - Improved gitlab-ci environment + - Deprecate and remove addon settings in favour of per app settings + - Refactor PhotoDriver class and add tests + - Convert affinity tool to app + - Refactor linkify_tags() so it works with xchans across multiple protocols + - Add the actual mid to viewsrc for debuging reasons + - Add filter hooks and the ability to add buttons to the default status editor + - Prevent Hubzilla usage for SEO backlinks + - Implement privacy warning for forum posts via !-tag + - Set document title when title changes on a page update + - Cache embeds in the background on initial storage rather than on first access + - Custom sessionhandler support + - Update nginx and lighttpd sample server configs to explicit disallow access to util + - Introduce command line tool for managing site admins + - Various doxygen improvements + - Add privacygroup_extras_post/drop hooks + - Add collect_public_recipients hook + - Prevent memory exhaustion on zot message pickup with large message queue + - Remove experimental worker queue from core + - Add get_base_apps hook + - Improve handling of notification updates while commenting + - Add warning if upload_filesize < 4MB + - Add ITEM_TYPE_CUSTOM and hooks for processing custom item types + - Set min/maxversion for plugins to STD_VERSION unless otherwise specified + - Add option to make affinity slider 'sticky' across page loads + - Add photo_view_filter hook + - Reset page title if article has no title + - Implement the zot6 protocol + - Add PHOTO_CACHE photo type + - Basic support for HTTP3 + - Add native summary support + - Disable image caching if personal or group permissions enabled + + Bugfixes + - Fix regression where mod oep was still using hex2bin/bin2hex instead of album hash + - Fix regression when selecting multiple images in embed images + - Fix broken sync_an_item() + - Fix page jumping on like if comments are expanded (show all x comments) + - Fix regression in mod display where an page update could display items from multiple channels + - Fix starring and filing allowed for other unsupported item types + - Fix wrong variable in z_get_temp_dir() + - Fix page jumping when liking a collapsed/expanded post + - Fix tags detection in URL + - Fix warnings in mod embedphotos + - Fix wrong variable in can_comment_on_post() + - Fix mod new_channel counting removed channels + - Fix regression where not all content variables were sslified + - Fix default values for affinity tool and other information which could be lost when approving a connection + - Fix regression in linkdropper() + - Fix issue with unset auto_save_draft variable which resultet in a javascript error + - Fix home notifications won't expand if there are more than 300 unseen network notifications ahead of them + - Fix total_identities count + - Fix delayed items propagate before publication on cloned channels + + Addons + - twitter_api: fedilab needs profile_image_url_https + - New addon: content_import - imports items and files to cloned channels (this obsoletes hzfiles) + - Diaspora: prevent processing of incomplete messages in various places + - hzfiles: fix add missing load/unload functions + - chess: do not look for games if we have no game_id - improves initial pageload performance + - chess: convert to app + - channelreputation: convert to app + - irc: convert to per app + - Provide the addon_common directory for common addon libraries + - fuzzloc: convert to app + - flattrwidget: convert to app + - jappixmini: convert to app + - xmpp: convert to app + - visage: convert to app + - diaspora: reflect linkify_tags() rewrite + - twitter: convert to app + - smileybutton: convert to app + - skeleton: convert to app + - planets: convert to app + - pumpio: convert to app + - pageheader: convert to app + - nsabait: convert to app + - dwpost: convert to app + - diaspora: set the preserve_lf option in various places + - diaspora: fix comments from unknown persons are not accpted + - nofed: convert to app + - ljpost: convert to app + - diaspora: call update_queue_item() if delivery failed + - pubcrawl: call update_queue_item() if delivery failed + - libertree: convert to app + - New addon: queueworker advanced - queue handling (experimental) + - gallery: extended functionality: implements stream image viewer, converts images at the beginning of a post to a gallery + - authchoose: correction to query, add affinity setting + - New addon: photocache - local caching for public photos + - New addon: totp - two factor authentication using time-based one-time passwords + + Hubzilla 3.8.9 (2018-02-03) - Fix typos in mod oep - Fix page jumping when liking collapsed/expanded post From 0b2213dd41a7ef275766725c070e16f8ba94d5a5 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 6 Mar 2019 19:01:28 -0800 Subject: [PATCH 14/33] guest access tokens: xchan record not created on URL login --- include/channel.php | 1 + 1 file changed, 1 insertion(+) diff --git a/include/channel.php b/include/channel.php index 466d2eab9..f705ba4d2 100644 --- a/include/channel.php +++ b/include/channel.php @@ -1836,6 +1836,7 @@ function zat_init() { ); if($r) { $xchan = atoken_xchan($r[0]); + atoken_create_xchan($xchan); atoken_login($xchan); } } From 04fe7e61deb19b9b05c87bff037b7bbf1d7bc662 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 7 Mar 2019 09:32:12 +0100 Subject: [PATCH 15/33] update changelog --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 4c9385b24..cc6880f6c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -44,6 +44,7 @@ Hubzilla 4.0 (2019-??-??) - Disable image caching if personal or group permissions enabled Bugfixes + - Fix guest access token xchan record not created on URL login - Fix regression where mod oep was still using hex2bin/bin2hex instead of album hash - Fix regression when selecting multiple images in embed images - Fix broken sync_an_item() From 1f7622e4c42bf71d1d38dd88c40c903d83a8d6c0 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 7 Mar 2019 15:45:42 -0800 Subject: [PATCH 16/33] fetch private objects using delivery channel credentials --- Zotlabs/Lib/Libzot.php | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index 4efd869f3..bc0826189 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -1125,9 +1125,14 @@ class Libzot { logger('Activity rejected: ' . print_r($data,true)); return; } - $arr = Activity::decode_note($AS); + if (is_array($AS->obj)) { + $arr = Activity::decode_note($AS); + } + else { + $arr = []; + } - logger($AS->debug()); + logger($AS->debug(),LOGGER_DATA); } @@ -1230,7 +1235,7 @@ class Libzot { $relay = (($env['type'] === 'response') ? true : false ); - $result = self::process_delivery($env['sender'],$arr,$deliveries,$relay,false,$message_request); + $result = self::process_delivery($env['sender'],$AS,$arr,$deliveries,$relay,false,$message_request); } elseif($env['type'] === 'sync') { // $arr = get_channelsync_elements($data); @@ -1412,7 +1417,7 @@ class Libzot { * @return array */ - static function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $request = false) { + static function process_delivery($sender, $act, $arr, $deliveries, $relay, $public = false, $request = false) { $result = []; @@ -1441,6 +1446,24 @@ class Libzot { $DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>'); + if(($act) && ($act->obj) && (! is_array($act->obj))) { + // The initial object fetch failed using the sys channel credentials. + // Try again using the delivery channel credentials. + // We will also need to re-parse the $item array, + // but preserve any values that were set during anonymous parsing. + + $o = Activity::fetch($act->obj,$channel); + if($o) { + $act->obj = $o; + $arr = array_merge(Activity::decode_note($act),$arr); + } + else { + $DR->update('Incomplete or corrupt activity'); + $result[] = $DR->get(); + continue; + } + } + /** * We need to block normal top-level message delivery from our clones, as the delivered * message doesn't have ACL information in it as the cloned copy does. That copy @@ -1859,7 +1882,7 @@ class Libzot { logger('FOF Activity received: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG); logger('FOF Activity recipient: ' . $channel['channel_portable_id'], LOGGER_DATA, LOG_DEBUG); - $result = self::process_delivery($arr['owner_xchan'],$arr, [ $channel['channel_portable_id'] ],false,false,true); + $result = self::process_delivery($arr['owner_xchan'],$AS, $arr, [ $channel['channel_portable_id'] ],false,false,true); if ($result) { $ret = array_merge($ret, $result); } From ce0067d8ebf1f7363bfb238bb73fb24078783261 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 7 Mar 2019 20:01:41 -0800 Subject: [PATCH 17/33] It is in fact the 'Content Import' app string that needs to be translated. A previous commit errantly included the string 'Content Filter'. But don't remove 'Content Filter'. That is actually a thing in Zap and will eventually make its way to Hubzilla. --- Zotlabs/Lib/Apps.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 7541c68a4..fefc6639d 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -328,6 +328,7 @@ class Apps { 'Bookmarks' => t('Bookmarks'), 'Chatrooms' => t('Chatrooms'), 'Content Filter' => t('Content Filter'), + 'Content Import' => t('Content Import'), 'Connections' => t('Connections'), 'Remote Diagnostics' => t('Remote Diagnostics'), 'Suggest Channels' => t('Suggest Channels'), From 507c71f64c68cc0de0f090f1abdd024866e91068 Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 8 Mar 2019 05:45:02 +0100 Subject: [PATCH 18/33] $sender is supposed to be string in libzot --- Zotlabs/Lib/Libzot.php | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index bc0826189..fd1538f0b 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -1895,8 +1895,7 @@ class Libzot { /** * @brief Remove community tag. * - * @param array $sender an associative array with - * * \e string \b hash a xchan_hash + * @param string $sender * @param array $arr an associative array * * \e int \b verb * * \e int \b obj_type @@ -1969,7 +1968,7 @@ class Libzot { * * @see item_store_update() * - * @param array $sender + * @param string $sender * @param array $item * @param array $orig * @param int $uid @@ -2020,7 +2019,7 @@ class Libzot { /** * @brief Deletes an imported item. * - * @param array $sender + * @param string $sender * * \e string \b hash a xchan_hash * @param array $item * @param int $uid @@ -2038,9 +2037,9 @@ class Libzot { $r = q("select id, author_xchan, owner_xchan, source_xchan, item_deleted from item where ( author_xchan = '%s' or owner_xchan = '%s' or source_xchan = '%s' ) and mid = '%s' and uid = %d limit 1", - dbesc($sender['hash']), - dbesc($sender['hash']), - dbesc($sender['hash']), + dbesc($sender), + dbesc($sender), + dbesc($sender), dbesc($item['mid']), intval($uid) ); @@ -2195,8 +2194,7 @@ class Libzot { * * @see import_directory_profile() * - * @param array $sender an associative array - * * \e string \b hash a xchan_hash + * @param string $sender * @param array $arr * @param array $deliveries (unused) * @return void @@ -2206,7 +2204,7 @@ class Libzot { logger('process_profile_delivery', LOGGER_DEBUG); $r = q("select xchan_addr from xchan where xchan_hash = '%s' limit 1", - dbesc($sender['hash']) + dbesc($sender) ); if($r) { Libzotdir::import_directory_profile($sender, $arr, $r[0]['xchan_addr'], UPDATE_FLAGS_UPDATED, 0); @@ -2217,8 +2215,7 @@ class Libzot { /** * @brief * - * @param array $sender an associative array - * * \e string \b hash a xchan_hash + * @param string $sender * @param array $arr * @param array $deliveries (unused) deliveries is irrelevant * @return void From 73c96f35c1b1e50518179f430ceaa3ebc0a7d643 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 8 Mar 2019 10:48:01 +0000 Subject: [PATCH 19/33] update changelog (cherry picked from commit 5b3824917d591b27c4797971c8253ed67b41dc5a) --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index cc6880f6c..0a57efa9d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -Hubzilla 4.0 (2019-??-??) +Hubzilla 4.0 (2019-03-08) - Add CURLOPT_CONNECTTIMEOUT option - Allow parameters as final path argument in API router - Remove clones from delivery recipients for top-level posts in favor of clone sync From b5ed3edc8f3e2a442d836ddef8ffa9114b49e523 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Fri, 8 Mar 2019 14:51:30 -0800 Subject: [PATCH 20/33] port zot_record_preferred --- Zotlabs/Lib/Libzot.php | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index bc0826189..50053a2fd 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -1197,12 +1197,14 @@ class Libzot { //logger($AS->debug()); - $r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1", + $r = q("select hubloc_hash, hubloc_network from hubloc where hubloc_id_url = '%s' ", dbesc($AS->actor['id']) ); if($r) { - $arr['author_xchan'] = $r[0]['hubloc_hash']; + // selects a zot6 hash if available, otherwise use whatever we have + $r = self::zot_record_preferred($r); + $arr['author_xchan'] = $r['hubloc_hash']; } @@ -3099,4 +3101,22 @@ class Libzot { return(($x) ? true : false); } + + static public function zot_record_preferred($arr, $check = 'hubloc_network') { + + if(! $arr) { + return $arr; + } + + foreach($arr as $v) { + if($v[$check] === 'zot6') { + + return $v; + } + } + + return $arr[0]; + + } + } From 51024d382172c5e2e62bacc6d9103a1caa40e4a5 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sat, 9 Mar 2019 12:58:03 -0800 Subject: [PATCH 21/33] authenticated fetch fixes --- Zotlabs/Lib/ActivityStreams.php | 5 +++- Zotlabs/Module/Item.php | 1 + include/zid.php | 48 +++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/Zotlabs/Lib/ActivityStreams.php b/Zotlabs/Lib/ActivityStreams.php index a357b6d69..006744aff 100644 --- a/Zotlabs/Lib/ActivityStreams.php +++ b/Zotlabs/Lib/ActivityStreams.php @@ -319,7 +319,10 @@ class ActivityStreams { function get_compound_property($property, $base = '', $namespace = '', $first = false) { $x = $this->get_property_obj($property, $base, $namespace); if($this->is_url($x)) { - $x = $this->fetch_property($x); + $y = $this->fetch_property($x); + if (is_array($y)) { + $x = $y; + } } // verify and unpack JSalmon signature if present diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index ebcf632ef..b247df0fd 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -55,6 +55,7 @@ class Item extends Controller { $sigdata = HTTPSig::verify(EMPTY_STR); if($sigdata['portable_id'] && $sigdata['header_valid']) { $portable_id = $sigdata['portable_id']; + observer_auth($portable_id); } $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 "; diff --git a/include/zid.php b/include/zid.php index a37ebe1f6..0b12689ef 100644 --- a/include/zid.php +++ b/include/zid.php @@ -352,3 +352,51 @@ function owt_init($token) { logger('OpenWebAuth: auth success from ' . $hubloc['xchan_addr']); } + + +function observer_auth($ob_hash) { + + if($ob_hash === false) { + return; + } + + $r = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash + where hubloc_addr = '%s' or hubloc_id_url = '%s' or hubloc_hash = '%s' order by hubloc_id desc", + dbesc($ob_hash), + dbesc($ob_hash), + dbesc($ob_hash) + ); + + if(! $r) { + // finger them if they can't be found. + $wf = discover_by_webbie($ob_hash); + if($wf) { + $r = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash + where hubloc_addr = '%s' or hubloc_id_url = '%s' or hubloc_hash = '%s' order by hubloc_id desc", + dbesc($ob_hash), + dbesc($ob_hash), + dbesc($ob_hash) + ); + } + } + if(! $r) { + logger('unable to finger ' . $ob_hash); + return; + } + + $hubloc = $r[0]; + + $_SESSION['authenticated'] = 1; + + // normal visitor (remote_channel) login session credentials + $_SESSION['visitor_id'] = $hubloc['xchan_hash']; + $_SESSION['my_url'] = $hubloc['xchan_url']; + $_SESSION['my_address'] = $hubloc['hubloc_addr']; + $_SESSION['remote_hub'] = $hubloc['hubloc_url']; + $_SESSION['DNT'] = 1; + + \App::set_observer($hubloc); + require_once('include/security.php'); + \App::set_groups(init_groups_visitor($_SESSION['visitor_id'])); + +} From cada0b6df12dab6e91aa7b560eccdf9f334f2b98 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 10 Mar 2019 15:50:45 -0700 Subject: [PATCH 22/33] init_groups_visitor: include xchans from all zot-like networks --- include/security.php | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/include/security.php b/include/security.php index 493d34699..4af46c257 100644 --- a/include/security.php +++ b/include/security.php @@ -575,11 +575,29 @@ function init_groups_visitor($contact_id) { } } - // physical groups this channel is a member of - - $r = q("SELECT hash FROM pgrp left join pgrp_member on pgrp.id = pgrp_member.gid WHERE xchan = '%s' ", + $x = q("select * from xchan where xchan_hash = '%s'", dbesc($contact_id) ); + + if (! $x) { + return $groups; + } + + // include xchans for all zot-like networks + + $xchans = q("select xchan_hash from xchan where xchan_hash = '%s' OR ( xchan_guid = '%s' AND xchan_pubkey = '%s' ) ", + dbesc($contact_id), + dbesc($x[0]['xchan_guid']), + dbesc($x[0]['xchan_pubkey']) + ); + + if($xchans) { + $hashes = ids_to_querystr($xchans,'xchan_hash',true); + } + + // physical groups this identity is a member of + + $r = q("SELECT hash FROM pgrp left join pgrp_member on pgrp.id = pgrp_member.gid WHERE xchan in ( " . protect_sprintf($hashes) . " ) " ); if($r) { foreach($r as $rr) $groups[] = $rr['hash']; From 4e97fb0e587eed6875b1d3a2615b0997a7f13c63 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 10 Mar 2019 22:32:37 -0700 Subject: [PATCH 23/33] testing init_groups_visitor changes - also add virtual groups for both zot identities --- include/security.php | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/include/security.php b/include/security.php index 4af46c257..44cd605dc 100644 --- a/include/security.php +++ b/include/security.php @@ -564,17 +564,6 @@ function check_form_security_token_ForbiddenOnErr($typename = '', $formname = 'f function init_groups_visitor($contact_id) { $groups = []; - // private profiles are treated as a virtual group - - $r = q("SELECT abook_profile from abook where abook_xchan = '%s' and abook_profile != '' ", - dbesc($contact_id) - ); - if($r) { - foreach($r as $rv) { - $groups[] = 'vp.' . $rv['abook_profile']; - } - } - $x = q("select * from xchan where xchan_hash = '%s'", dbesc($contact_id) ); @@ -594,10 +583,19 @@ function init_groups_visitor($contact_id) { if($xchans) { $hashes = ids_to_querystr($xchans,'xchan_hash',true); } - + + // private profiles are treated as a virtual group + + $r = q("SELECT abook_profile from abook where abook_xchan in ( " . protect_sprintf($hashes) . " ) and abook_profile != '' "); + if($r) { + foreach($r as $rv) { + $groups[] = 'vp.' . $rv['abook_profile']; + } + } + // physical groups this identity is a member of - $r = q("SELECT hash FROM pgrp left join pgrp_member on pgrp.id = pgrp_member.gid WHERE xchan in ( " . protect_sprintf($hashes) . " ) " ); + $r = q("SELECT hash FROM pgrp left join pgrp_member on pgrp.id = pgrp_member.gid WHERE xchan in ( " . protect_sprintf($hashes) . " ) "); if($r) { foreach($r as $rr) $groups[] = $rr['hash']; From 5fb0d38ad8b59bef92655b56cf7145cc979b6dea Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 11 Mar 2019 16:29:12 -0700 Subject: [PATCH 24/33] security updates for multiple xchans --- include/security.php | 248 +++++++++++++++++++++++++++++++++---------- 1 file changed, 189 insertions(+), 59 deletions(-) diff --git a/include/security.php b/include/security.php index 44cd605dc..b9705a0e4 100644 --- a/include/security.php +++ b/include/security.php @@ -306,6 +306,7 @@ function change_channel($change_channel) { * * @return string additional SQL where statement */ + function permissions_sql($owner_id, $remote_observer = null, $table = '') { $local_channel = local_channel(); @@ -316,7 +317,7 @@ function permissions_sql($owner_id, $remote_observer = null, $table = '') { * default permissions - anonymous user */ - if($table) + if ($table) $table .= '.'; $sql = " AND {$table}allow_cid = '' @@ -329,38 +330,63 @@ function permissions_sql($owner_id, $remote_observer = null, $table = '') { * Profile owner - everything is visible */ - if(($local_channel) && ($local_channel == $owner_id)) { - $sql = ''; + if (($local_channel) && ($local_channel == $owner_id)) { + return EMPTY_STR; } /** - * Authenticated visitor. Unless pre-verified, - * check that the contact belongs to this $owner_id - * and load the groups the visitor belongs to. - * If pre-verified, the caller is expected to have already - * done this and passed the groups into this function. + * Authenticated visitor. */ else { + $observer = ((! is_null($remote_observer)) ? $remote_observer : get_observer_hash()); - if($observer) { - $groups = init_groups_visitor($observer); - $gs = '<<>>'; // should be impossible to match + if ($observer) { - if(is_array($groups) && count($groups)) { - foreach($groups as $g) - $gs .= '|<' . $g . '>'; + $sec = get_security_ids($owner_id,$observer); + + // always allow the channel owner, even if authenticated as a visitor + + if ($sec['channel_id']) { + foreach ($sec['channel_id'] as $ch) { + if ($observer === $ch) { + return EMPTY_STR; + } + } + } + + if (is_array($sec['allow_cid']) && count($sec['allow_cid'])) { + $ca = []; + foreach ($sec['allow_cid'] as $c) { + $ca[] = '<' . $c . '>'; + } + $cs = implode('|',$ca); } + else { + $cs = '<<>>'; // should be impossible to match + } + + if (is_array($sec['allow_gid']) && count($sec['allow_gid'])) { + $ga = []; + foreach ($sec['allow_gid'] as $g) { + $ga[] = '<' . $g . '>'; + } + $gs = implode('|',$ga); + } + else { + $gs = '<<>>'; // should be impossible to match + } + $regexop = db_getfunc('REGEXP'); $sql = sprintf( - " AND ( NOT ({$table}deny_cid like '%s' OR {$table}deny_gid $regexop '%s') - AND ( {$table}allow_cid like '%s' OR {$table}allow_gid $regexop '%s' OR ( {$table}allow_cid = '' AND {$table}allow_gid = '') ) + " AND ( NOT ({$table}deny_cid regexop '%s' OR {$table}deny_gid $regexop '%s') + AND ( {$table}allow_cid regexop '%s' OR {$table}allow_gid $regexop '%s' OR ( {$table}allow_cid = '' AND {$table}allow_gid = '') ) ) ", - dbesc(protect_sprintf( '%<' . $observer . '>%')), + dbesc($cs), dbesc($gs), - dbesc(protect_sprintf( '%<' . $observer . '>%')), + dbesc($cs), dbesc($gs) ); } @@ -377,6 +403,7 @@ function permissions_sql($owner_id, $remote_observer = null, $table = '') { * * @return string additional SQL where statement */ + function item_permissions_sql($owner_id, $remote_observer = null) { $local_channel = local_channel(); @@ -398,37 +425,59 @@ function item_permissions_sql($owner_id, $remote_observer = null) { } /** - * Authenticated visitor. Unless pre-verified, - * check that the contact belongs to this $owner_id - * and load the groups the visitor belongs to. - * If pre-verified, the caller is expected to have already - * done this and passed the groups into this function. + * Authenticated visitor. */ else { - $observer = (($remote_observer) ? $remote_observer : get_observer_hash()); - if($observer) { + $observer = (($remote_observer) ? $remote_observer : get_observer_hash()); - $s = scopes_sql($owner_id,$observer); + if($observer) { - $groups = init_groups_visitor($observer); + $scope = scopes_sql($owner_id,$observer); + $sec = get_security_ids($owner_id,$observer); - $gs = '<<>>'; // should be impossible to match + // always allow the channel owner, even if authenticated as a visitor - if(is_array($groups) && count($groups)) { - foreach($groups as $g) - $gs .= '|<' . $g . '>'; + if($sec['channel_id']) { + foreach($sec['channel_id'] as $ch) { + if($observer === $ch) { + return EMPTY_STR; + } + } + } + + if (is_array($sec['allow_cid']) && count($sec['allow_cid'])) { + $ca = []; + foreach ($sec['allow_cid'] as $c) { + $ca[] = '<' . $c . '>'; + } + $cs = implode('|',$ca); } + else { + $cs = '<<>>'; // should be impossible to match + } + + if (is_array($sec['allow_gid']) && count($sec['allow_gid'])) { + $ga = []; + foreach ($sec['allow_gid'] as $g) { + $ga[] = '<' . $g . '>'; + } + $gs = implode('|',$ga); + } + else { + $gs = '<<>>'; // should be impossible to match + } + $regexop = db_getfunc('REGEXP'); $sql = sprintf( - " AND (( NOT (deny_cid like '%s' OR deny_gid $regexop '%s') - AND ( allow_cid like '%s' OR allow_gid $regexop '%s' OR ( allow_cid = '' AND allow_gid = '' AND item_private = 0 )) - ) OR ( item_private = 1 $s )) + " AND (( NOT (deny_cid regexop '%s' OR deny_gid $regexop '%s') + AND ( allow_cid regexop '%s' OR allow_gid $regexop '%s' OR ( allow_cid = '' AND allow_gid = '' AND item_private = 0 )) + ) OR ( item_private = 1 $scope )) ", - dbesc(protect_sprintf( '%<' . $observer . '>%')), + dbesc($cs), dbesc($gs), - dbesc(protect_sprintf( '%<' . $observer . '>%')), + dbesc($cs), dbesc($gs) ); } @@ -465,40 +514,57 @@ function scopes_sql($uid,$observer) { } - - - - - /** * @param string $observer_hash * * @return string additional SQL where statement */ + function public_permissions_sql($observer_hash) { - $groups = init_groups_visitor($observer_hash); + $owner_id = 0; - $gs = '<<>>'; // should be impossible to match + if ($observer_hash) { + + $sec = get_security_ids($owner_id,$observer_hash); + + if (is_array($sec['allow_cid']) && count($sec['allow_cid'])) { + $ca = []; + foreach ($sec['allow_cid'] as $c) { + $ca[] = '<' . $c . '>'; + } + $cs = implode('|',$ca); + } + else { + $cs = '<<>>'; // should be impossible to match + } + + if (is_array($sec['allow_gid']) && count($sec['allow_gid'])) { + $ga = []; + foreach ($sec['allow_gid'] as $g) { + $ga[] = '<' . $g . '>'; + } + $gs = implode('|',$ga); + } + else { + $gs = '<<>>'; // should be impossible to match + } - if(is_array($groups) && count($groups)) { - foreach($groups as $g) - $gs .= '|<' . $g . '>'; - } - $sql = ''; - if($observer_hash) { $regexop = db_getfunc('REGEXP'); $sql = sprintf( - " OR (( NOT (deny_cid like '%s' OR deny_gid $regexop '%s') - AND ( allow_cid like '%s' OR allow_gid $regexop '%s' OR ( allow_cid = '' AND allow_gid = '' AND item_private = 0 ) ) - )) + " AND ( NOT (deny_cid regexop '%s' OR deny_gid $regexop '%s') + AND ( allow_cid regexop '%s' OR allow_gid $regexop '%s' OR ( allow_cid = '' AND allow_gid = '' AND item_private = 0) ) + ) ", - dbesc(protect_sprintf( '%<' . $observer_hash . '>%')), + dbesc($cs), dbesc($gs), - dbesc(protect_sprintf( '%<' . $observer_hash . '>%')), + dbesc($cs), dbesc($gs) ); } + else { + $sql = EMPTY_STR; + } return $sql; } @@ -510,7 +576,7 @@ function public_permissions_sql($observer_hash) { * In this implementation, a security token is reusable (if the user submits a form, goes back and resubmits the form, maybe with small changes; * or if the security token is used for ajax-calls that happen several times), but only valid for a certain amout of time (3hours). * The "typename" seperates the security tokens of different types of forms. This could be relevant in the following case: - * A security token is used to protekt a link from CSRF (e.g. the "delete this profile"-link). + * A security token is used to protect a link from CSRF (e.g. the "delete this profile"-link). * If the new page contains by any chance external elements, then the used security token is exposed by the referrer. * Actually, important actions should not be triggered by Links / GET-Requests at all, but somethimes they still are, * so this mechanism brings in some damage control (the attacker would be able to forge a request to a form of this type, but not to forms of other types). @@ -587,8 +653,8 @@ function init_groups_visitor($contact_id) { // private profiles are treated as a virtual group $r = q("SELECT abook_profile from abook where abook_xchan in ( " . protect_sprintf($hashes) . " ) and abook_profile != '' "); - if($r) { - foreach($r as $rv) { + if ($r) { + foreach ($r as $rv) { $groups[] = 'vp.' . $rv['abook_profile']; } } @@ -596,8 +662,8 @@ function init_groups_visitor($contact_id) { // physical groups this identity is a member of $r = q("SELECT hash FROM pgrp left join pgrp_member on pgrp.id = pgrp_member.gid WHERE xchan in ( " . protect_sprintf($hashes) . " ) "); - if($r) { - foreach($r as $rr) + if ($r) { + foreach ($r as $rr) $groups[] = $rr['hash']; } return $groups; @@ -605,6 +671,70 @@ function init_groups_visitor($contact_id) { + +function get_security_ids($channel_id, $ob_hash) { + + $ret = [ + 'channel_id' => [], + 'allow_cid' => [], + 'allow_gid' => [] + ]; + + if($channel_id) { + $ch = q("select channel_hash, portable_id from channel where channel_id = %d", + intval($channel_id) + ); + if($ch) { + $ret['channel_id'][] = $ch[0]['channel_hash']; + $ret['channel_id'][] = $ch[0]['portable_id']; + } + } + + $groups = []; + + $x = q("select * from xchan where xchan_hash = '%s'", + dbesc($ob_hash) + ); + + if ($x) { + + // include xchans for all zot-like networks + + $xchans = q("select xchan_hash from xchan where xchan_hash = '%s' OR ( xchan_guid = '%s' AND xchan_pubkey = '%s' ) ", + dbesc($ob_hash), + dbesc($x[0]['xchan_guid']), + dbesc($x[0]['xchan_pubkey']) + ); + + if ($xchans) { + $ret['allow_cid'] = ids_to_array($xchans,'xchan_hash'); + $hashes = ids_to_querystr($xchans,'xchan_hash',true); + + // private profiles are treated as a virtual group + + $r = q("SELECT abook_profile from abook where abook_xchan in ( " . protect_sprintf($hashes) . " ) and abook_profile != '' "); + if($r) { + foreach ($r as $rv) { + $groups[] = 'vp.' . $rv['abook_profile']; + } + } + + // physical groups this identity is a member of + + $r = q("SELECT hash FROM pgrp left join pgrp_member on pgrp.id = pgrp_member.gid WHERE xchan in ( " . protect_sprintf($hashes) . " ) "); + if($r) { + foreach ($r as $rv) { + $groups[] = $rv['hash']; + } + } + $ret['allow_gid'] = $groups; + } + } + + return $ret; +} + + // This is used to determine which uid have posts which are visible to the logged in user (from the API) for the // public_timeline, and we can use this in a community page by making // $perms = (PERMS_NETWORK|PERMS_PUBLIC) unless logged in. From 3ec06705caed8459045875d03b8906e72405d6bb Mon Sep 17 00:00:00 2001 From: Mike Macgirvin Date: Tue, 12 Mar 2019 16:12:29 +1100 Subject: [PATCH 25/33] perform zot6 discovery in import_author_xchan --- include/items.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/items.php b/include/items.php index 51aa81017..c6dcd32c6 100755 --- a/include/items.php +++ b/include/items.php @@ -914,6 +914,15 @@ function import_author_xchan($x) { if(array_key_exists('network',$x) && $x['network'] === 'zot') return $y; + // perform zot6 discovery + + if($x['url']) { + $y = discover_by_webbie($x['url'],'zot6'); + if($y) { + return $y; + } + } + if($x['network'] === 'rss') { $y = import_author_rss($x); } From a9172129d2f537eddcd273255895712718fe9543 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 11 Mar 2019 22:17:36 -0700 Subject: [PATCH 26/33] check zot6 in import_author_xchan --- include/items.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/items.php b/include/items.php index 51aa81017..9287c81db 100755 --- a/include/items.php +++ b/include/items.php @@ -914,6 +914,15 @@ function import_author_xchan($x) { if(array_key_exists('network',$x) && $x['network'] === 'zot') return $y; + // perform zot6 discovery + + if($x['url']) { + $y = discover_by_webbie($x['url'],'zot6'); + if($y) { + return $y; + } + } + if($x['network'] === 'rss') { $y = import_author_rss($x); } From 11116bdcb77eb9fc62db92fdf87cf2cc1d8e5708 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 12 Mar 2019 03:40:43 -0700 Subject: [PATCH 27/33] typos --- include/security.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/security.php b/include/security.php index b9705a0e4..38cb72263 100644 --- a/include/security.php +++ b/include/security.php @@ -380,8 +380,8 @@ function permissions_sql($owner_id, $remote_observer = null, $table = '') { $regexop = db_getfunc('REGEXP'); $sql = sprintf( - " AND ( NOT ({$table}deny_cid regexop '%s' OR {$table}deny_gid $regexop '%s') - AND ( {$table}allow_cid regexop '%s' OR {$table}allow_gid $regexop '%s' OR ( {$table}allow_cid = '' AND {$table}allow_gid = '') ) + " AND ( NOT ({$table}deny_cid $regexop '%s' OR {$table}deny_gid $regexop '%s') + AND ( {$table}allow_cid $regexop '%s' OR {$table}allow_gid $regexop '%s' OR ( {$table}allow_cid = '' AND {$table}allow_gid = '') ) ) ", dbesc($cs), @@ -471,8 +471,8 @@ function item_permissions_sql($owner_id, $remote_observer = null) { $regexop = db_getfunc('REGEXP'); $sql = sprintf( - " AND (( NOT (deny_cid regexop '%s' OR deny_gid $regexop '%s') - AND ( allow_cid regexop '%s' OR allow_gid $regexop '%s' OR ( allow_cid = '' AND allow_gid = '' AND item_private = 0 )) + " AND (( NOT (deny_cid $regexop '%s' OR deny_gid $regexop '%s') + AND ( allow_cid $regexop '%s' OR allow_gid $regexop '%s' OR ( allow_cid = '' AND allow_gid = '' AND item_private = 0 )) ) OR ( item_private = 1 $scope )) ", dbesc($cs), @@ -552,8 +552,8 @@ function public_permissions_sql($observer_hash) { $regexop = db_getfunc('REGEXP'); $sql = sprintf( - " AND ( NOT (deny_cid regexop '%s' OR deny_gid $regexop '%s') - AND ( allow_cid regexop '%s' OR allow_gid $regexop '%s' OR ( allow_cid = '' AND allow_gid = '' AND item_private = 0) ) + " AND ( NOT (deny_cid $regexop '%s' OR deny_gid $regexop '%s') + AND ( allow_cid $regexop '%s' OR allow_gid $regexop '%s' OR ( allow_cid = '' AND allow_gid = '' AND item_private = 0) ) ) ", dbesc($cs), @@ -681,12 +681,12 @@ function get_security_ids($channel_id, $ob_hash) { ]; if($channel_id) { - $ch = q("select channel_hash, portable_id from channel where channel_id = %d", + $ch = q("select channel_hash, channel_portable_id from channel where channel_id = %d", intval($channel_id) ); if($ch) { $ret['channel_id'][] = $ch[0]['channel_hash']; - $ret['channel_id'][] = $ch[0]['portable_id']; + $ret['channel_id'][] = $ch[0]['channel_portable_id']; } } From 72384ff2cb28afa74f93a15738fdbd95efe1443b Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 12 Mar 2019 15:17:25 -0700 Subject: [PATCH 28/33] add owner permission checks to AS item fetch --- Zotlabs/Module/Item.php | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index b247df0fd..980d7308d 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -62,9 +62,44 @@ class Item extends Controller { $sql_extra = item_permissions_sql(0); - $r = q("select * from item where mid = '%s' $item_normal $sql_extra limit 1", - dbesc(z_root() . '/item/' . $item_id) + $r = null; + + + // first see if we have this item owned by the current signer + + $x = q("select * from xchan where xchan_hash = '%s'", + dbesc($sigdata['portable_id']) ); + + if ($x) { + + // include xchans for all zot-like networks - these will have the same guid and public key + + $xchans = q("select xchan_hash from xchan where xchan_hash = '%s' OR ( xchan_guid = '%s' AND xchan_pubkey = '%s' ) ", + dbesc($sigdata['portable_id']), + dbesc($x[0]['xchan_guid']), + dbesc($x[0]['xchan_pubkey']) + ); + + if ($xchans) { + $hashes = ids_to_querystr($xchans,'xchan_hash',true); + $r = q("select * from item where mid = '%s' $item_normal and owner_xchan in ( " . protect_sprintf($hashes) . " ) ", + dbesc(z_root() . '/item/' . $item_id) + ); + } + } + + // then see if we can access it as a visitor + + if (! $r) { + + $r = q("select * from item where mid = '%s' $item_normal $sql_extra limit 1", + dbesc(z_root() . '/item/' . $item_id) + ); + } + + // fetch once more with no extra conditions to see what error condition applies + if(! $r) { From cf5a310286079b22ac3d716c28feae115a59539d Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 12 Mar 2019 16:17:34 -0700 Subject: [PATCH 29/33] rework authenticated item fetches (check ACL on the parent, not on the requested item) --- Zotlabs/Module/Item.php | 115 +++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 65 deletions(-) diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index 980d7308d..df9a80583 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -40,92 +40,78 @@ class Item extends Controller { function init() { - if(Libzot::is_zot_request()) { + if (Libzot::is_zot_request()) { $conversation = false; $item_id = argv(1); - if(! $item_id) + if (! $item_id) http_status_exit(404, 'Not found'); - $portable_id = EMPTY_STR; + $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 "; + + $i = null; + + // do we have the item (at all)? + + $r = q("select * from item where mid = '%s' $item_normal limit 1", + dbesc(z_root() . '/item/' . $item_id) + ); + + if (! $r) { + http_status_exit(404,'Not found'); + } + + // process an authenticated fetch + $sigdata = HTTPSig::verify(EMPTY_STR); if($sigdata['portable_id'] && $sigdata['header_valid']) { $portable_id = $sigdata['portable_id']; observer_auth($portable_id); + + // first see if we have a copy of this item's parent owned by the current signer + // include xchans for all zot-like networks - these will have the same guid and public key + + $x = q("select * from xchan where xchan_hash = '%s'", + dbesc($sigdata['portable_id']) + ); + + if ($x) { + $xchans = q("select xchan_hash from xchan where xchan_hash = '%s' OR ( xchan_guid = '%s' AND xchan_pubkey = '%s' ) ", + dbesc($sigdata['portable_id']), + dbesc($x[0]['xchan_guid']), + dbesc($x[0]['xchan_pubkey']) + ); + + if ($xchans) { + $hashes = ids_to_querystr($xchans,'xchan_hash',true); + $i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan in ( " . protect_sprintf($hashes) . " ) ", + dbesc($r[0]['parent_mid']) + ); + } + } } - $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 "; + // if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access $sql_extra = item_permissions_sql(0); - $r = null; - - - // first see if we have this item owned by the current signer - - $x = q("select * from xchan where xchan_hash = '%s'", - dbesc($sigdata['portable_id']) - ); - - if ($x) { - - // include xchans for all zot-like networks - these will have the same guid and public key - - $xchans = q("select xchan_hash from xchan where xchan_hash = '%s' OR ( xchan_guid = '%s' AND xchan_pubkey = '%s' ) ", - dbesc($sigdata['portable_id']), - dbesc($x[0]['xchan_guid']), - dbesc($x[0]['xchan_pubkey']) - ); - - if ($xchans) { - $hashes = ids_to_querystr($xchans,'xchan_hash',true); - $r = q("select * from item where mid = '%s' $item_normal and owner_xchan in ( " . protect_sprintf($hashes) . " ) ", - dbesc(z_root() . '/item/' . $item_id) - ); - } - } - - // then see if we can access it as a visitor - - if (! $r) { - - $r = q("select * from item where mid = '%s' $item_normal $sql_extra limit 1", - dbesc(z_root() . '/item/' . $item_id) + if (! $i) { + $i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra limit 1", + dbesc($r[0]['parent_mid']) ); } - // fetch once more with no extra conditions to see what error condition applies - - if(! $r) { - - - $r = q("select * from item where mid = '%s' $item_normal limit 1", - dbesc(z_root() . '/item/' . $item_id) - ); - if($r) { - http_status_exit(403, 'Forbidden'); - } - http_status_exit(404, 'Not found'); + if(! $i) { + http_status_exit(403,'Forbidden'); } - - $items = q("select parent as item_id from item where mid = '%s' and uid = %d $item_normal $sql_extra ", - dbesc($r[0]['parent_mid']), - intval($r[0]['uid']) - ); - if(! $items) { - http_status_exit(404, 'Not found'); - } - - $r = $items; - - $parents_str = ids_to_querystr($r,'item_id'); + $parents_str = ids_to_querystr($i,'item_id'); - $items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent IN ( %s ) $item_normal $sql_extra ", + $items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent IN ( %s ) $item_normal ", dbesc($parents_str) ); @@ -133,9 +119,8 @@ class Item extends Controller { http_status_exit(404, 'Not found'); } - $r = $items; - xchan_query($r,true); - $items = fetch_post_tags($r,true); + xchan_query($items,true); + $items = fetch_post_tags($items,true); $observer = App::get_observer(); $parent = $items[0]; From 088a93e023aa23d089dad2a06d61b540d3ea47a1 Mon Sep 17 00:00:00 2001 From: Mike Macgirvin Date: Wed, 13 Mar 2019 13:21:04 +1100 Subject: [PATCH 30/33] limit 1 --- Zotlabs/Module/Item.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index df9a80583..c466e7c82 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -88,7 +88,7 @@ class Item extends Controller { if ($xchans) { $hashes = ids_to_querystr($xchans,'xchan_hash',true); - $i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan in ( " . protect_sprintf($hashes) . " ) ", + $i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan in ( " . protect_sprintf($hashes) . " ) limit 1", dbesc($r[0]['parent_mid']) ); } From a3e94855f91c1c66fbd4c9ca5ca77386b944febd Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 13 Mar 2019 17:48:00 +0100 Subject: [PATCH 31/33] add zot6 to clonable networks --- Zotlabs/Module/Connedit.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php index a587324df..acd7cb769 100644 --- a/Zotlabs/Module/Connedit.php +++ b/Zotlabs/Module/Connedit.php @@ -848,7 +848,7 @@ class Connedit extends \Zotlabs\Web\Controller { $locstr = unpunify($contact['xchan_url']); $clone_warn = ''; - $clonable = (in_array($contact['xchan_network'],['zot','rss']) ? true : false); + $clonable = (in_array($contact['xchan_network'],['zot', 'zot6', 'rss']) ? true : false); if(! $clonable) { $clone_warn = ''; $clone_warn .= ((intval($contact['abook_not_here'])) From a5a5ac60ba626b0d863627e5f0144afbbaeb8e66 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 13 Mar 2019 16:27:52 -0700 Subject: [PATCH 32/33] find unregistered z6 clones on hubzilla sites (does not happen automatically since z6 is not the default protocol on hubzilla). This will need to be pushed to master for the next point release. --- Zotlabs/Daemon/Cron_daily.php | 1 + Zotlabs/Daemon/Poller.php | 1 + include/hubloc.php | 36 +++++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/Zotlabs/Daemon/Cron_daily.php b/Zotlabs/Daemon/Cron_daily.php index f0351fcdd..dbfcff439 100644 --- a/Zotlabs/Daemon/Cron_daily.php +++ b/Zotlabs/Daemon/Cron_daily.php @@ -85,6 +85,7 @@ class Cron_daily { Master::Summon(array('Cli_suggest')); remove_obsolete_hublocs(); + z6_discover(); call_hooks('cron_daily',datetime_convert()); diff --git a/Zotlabs/Daemon/Poller.php b/Zotlabs/Daemon/Poller.php index a8cf34ce2..84bf7e923 100644 --- a/Zotlabs/Daemon/Poller.php +++ b/Zotlabs/Daemon/Poller.php @@ -199,6 +199,7 @@ class Poller { set_config('system','lastpoll',datetime_convert()); //All done - clear the lockfile + @unlink($lockfile); return; diff --git a/include/hubloc.php b/include/hubloc.php index b2903b0ee..7cb00f788 100644 --- a/include/hubloc.php +++ b/include/hubloc.php @@ -305,3 +305,39 @@ function ping_site($url) { return $ret; } + + +function z6_discover() { + + // find unregistered zot6 clone hublocs + + $c = q("select channel_hash, portable_id from channel where channel_deleted = 0"); + 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'", + dbesc($entry['channel_hash']), + dbesc(z_root()) + ); + if (! $q1) { + // channel has no zot clones + continue; + } + // 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($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) { + // probe and store results - only for zot6 (over-ride the zot default) + discover_by_webbie($entry['hubloc_addr'],'zot6'); + } + } + } + } + +} \ No newline at end of file From 05bcbfa28cafae0febcfb63bd39fdcb249f7def0 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 13 Mar 2019 16:31:37 -0700 Subject: [PATCH 33/33] signature issue for zot6 content imported from zotfeeds to hubzilla --- include/items.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/items.php b/include/items.php index 6bb453bc8..c9c2e2d48 100755 --- a/include/items.php +++ b/include/items.php @@ -763,11 +763,11 @@ function get_item_elements($x,$allow_code = false) { // check the supplied signature against the supplied content. // Note that we will purify the content which could change it. - $r = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1", + $r = q("select xchan_pubkey, xchan_network from xchan where xchan_hash = '%s' limit 1", dbesc($arr['author_xchan']) ); if($r) { - if($r[0]['xchan_pubkey']) { + if($r[0]['xchan_pubkey'] && $r[0]['xchan_network'] === 'zot') { if(rsa_verify($x['body'],base64url_decode($arr['sig']),$r[0]['xchan_pubkey'])) { $arr['item_verified'] = 1; }