From 9d51318c53e1adc2e4d4c8586f8783819516991e Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 19 Oct 2017 17:24:11 -0700 Subject: table structure for pseudo or proxy channels (pchan) --- include/channel.php | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'include') diff --git a/include/channel.php b/include/channel.php index d7116ce28..399dff87e 100644 --- a/include/channel.php +++ b/include/channel.php @@ -2604,3 +2604,12 @@ function anon_identity_init($reqvars) { } +function pchan_to_chan($pchan) { + $chan = $pchan; + $chan['channel_address'] = $pchan['pchan_guid']; + $chan['channel_hash'] = $pchan['pchan_hash']; + $chan['channel_pubkey'] = $pchan['pchan_pubkey']; + $chan['channel_prvkey'] = $pchan['pchan_prvkey']; + $chan['channel_name'] = $pchan['xchan_name']; + return $chan; +} \ No newline at end of file -- cgit v1.2.3 From c7d9a5ac91b3d256f31ebada4b38875905addb1f Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 22 Oct 2017 12:35:17 -0700 Subject: wrong key --- include/zot.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/zot.php b/include/zot.php index 55632fc31..dad30dbb0 100644 --- a/include/zot.php +++ b/include/zot.php @@ -361,8 +361,6 @@ function zot_refresh($them, $channel = null, $force = false) { else $permissions = $j['permissions']; - $connected_set = false; - if($permissions && is_array($permissions)) { $old_read_stream_perm = get_abconfig($channel['channel_id'],$x['hash'],'their_perms','view_stream'); @@ -4177,7 +4175,7 @@ function zotinfo($arr) { if($ztarget_hash) { $permissions['connected'] = false; - $b = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1", + $b = q("select * from abook where abook_xchan = '%s' and abook_channel = %d and abook_pending = 0 limit 1", dbesc($ztarget_hash), intval($e['channel_id']) ); @@ -4201,7 +4199,7 @@ function zotinfo($arr) { if($x) $ret['locations'] = $x; - $ret['site'] = zot_site_info($e['xchan_pubkey']); + $ret['site'] = zot_site_info($e['channel_prvkey']); check_zotinfo($e,$x,$ret); -- cgit v1.2.3 From 812d904c98d6fb3a4124f6e2415de5a139f954ce Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 22 Oct 2017 18:23:37 -0700 Subject: bring back the markdown post feature (after investing some effort to make it work) --- include/features.php | 9 +++++++++ include/markdown.php | 11 +++++++---- include/network.php | 4 ++++ 3 files changed, 20 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/features.php b/include/features.php index f84c9cb05..d8d98dbaa 100644 --- a/include/features.php +++ b/include/features.php @@ -363,6 +363,15 @@ function get_features($filtered = true) { t('Post/Comment Tools'), + [ + 'markdown', + t('Markdown'), + t('Use markdown for editing posts'), + false, + get_config('feature_lock','markdown'), + feature_level('markdown',2), + ], + [ 'commtag', t('Community Tagging'), diff --git a/include/markdown.php b/include/markdown.php index 0cd9ab237..0464cf71a 100644 --- a/include/markdown.php +++ b/include/markdown.php @@ -49,14 +49,17 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) { $s = $x['text']; - // Escaping the hash tags - doesn't always seem to work - // $s = preg_replace('/\#([^\s\#])/','\\#$1',$s); - // This seems to work + // Escaping the hash tags $s = preg_replace('/\#([^\s\#])/','#$1',$s); $s = MarkdownExtra::defaultTransform($s); - $s = str_replace("\r","",$s); + if($options && $options['preserve_lf']) { + $s = str_replace(["\r","\n"],["",'
'],$s); + } + else { + $s = str_replace("\r","",$s); + } $s = str_replace('#','#',$s); diff --git a/include/network.php b/include/network.php index 7e2dbf4cf..2f29a70c4 100644 --- a/include/network.php +++ b/include/network.php @@ -716,6 +716,10 @@ function scale_external_images($s, $include_link = true, $scale_replace = false) $scaled = str_replace($scale_replace[0], $scale_replace[1], $mtch[3]); else $scaled = $mtch[3]; + + if(! strpbrk(substr($scaled,0,1),'zhfmt')) + continue; + $i = z_fetch_url($scaled,true); -- cgit v1.2.3 From e67ff5c122087f878111ad99d1c3b2328b967ab2 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 23 Oct 2017 12:35:46 -0700 Subject: hubzilla issue #885 --- include/contact_widgets.php | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include') diff --git a/include/contact_widgets.php b/include/contact_widgets.php index a13f87573..9cc9f0baf 100644 --- a/include/contact_widgets.php +++ b/include/contact_widgets.php @@ -65,6 +65,10 @@ function categories_widget($baseurl,$selected = '') { if(! feature_enabled(App::$profile['profile_uid'],'categories')) return ''; + require_once('include/security.php'); + + $sql_extra = item_permissions_sql(App::$profile['profile_uid']); + $item_normal = item_normal(); $terms = array(); @@ -77,6 +81,7 @@ function categories_widget($baseurl,$selected = '') { and item.owner_xchan = '%s' and item.item_wall = 1 $item_normal + $sql_extra order by term.term asc", intval(App::$profile['profile_uid']), intval(TERM_CATEGORY), @@ -105,6 +110,8 @@ function cardcategories_widget($baseurl,$selected = '') { if(! feature_enabled(App::$profile['profile_uid'],'categories')) return ''; + $sql_extra = item_permissions_sql(App::$profile['profile_uid']); + $item_normal = "and item.item_hidden = 0 and item.item_type = 6 and item.item_deleted = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0 and item.item_blocked = 0 "; @@ -118,6 +125,7 @@ function cardcategories_widget($baseurl,$selected = '') { and term.otype = %d and item.owner_xchan = '%s' $item_normal + $sql_extra order by term.term asc", intval(App::$profile['profile_uid']), intval(TERM_CATEGORY), -- cgit v1.2.3 From 52c1f79f2ec2ac4c417e8cca2008565891a5a0f6 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 23 Oct 2017 17:52:17 -0700 Subject: acl encoding issues --- include/text.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/text.php b/include/text.php index 8a65be0d5..d81b59d75 100644 --- a/include/text.php +++ b/include/text.php @@ -2846,7 +2846,7 @@ function item_url_replace($channel,&$item,$old,$new,$oldnick = '') { */ function sanitise_acl(&$item) { if (strlen($item)) - $item = '<' . notags(trim($item)) . '>'; + $item = '<' . notags(trim(urldecode($item))) . '>'; else unset($item); } -- cgit v1.2.3 From fe5f1e4d67d999ed3c6ef78dc4d49f5dd1a93056 Mon Sep 17 00:00:00 2001 From: Klaus Weidenbach Date: Tue, 24 Oct 2017 16:33:58 +0200 Subject: :white_check_mark: Some unit test for include/language.php Unfortunately not so much unit testable, but added in preparation to update LanguageDetect and Intl library. --- include/language.php | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/language.php b/include/language.php index efe9397fb..a59823757 100644 --- a/include/language.php +++ b/include/language.php @@ -322,6 +322,8 @@ function get_language_name($s, $l = null) { $language = $languageRepository->get($s, $l); } catch (CommerceGuys\Intl\Exception\UnknownLanguageException $e) { return $s; // Give up + } catch (CommerceGuys\Intl\Exception\UnknownLocaleException $e) { + return $s; // Give up } } -- cgit v1.2.3 From 8e4c5db766ce23d05b8507991b04fece743147de Mon Sep 17 00:00:00 2001 From: Klaus Weidenbach Date: Wed, 25 Oct 2017 01:57:18 +0200 Subject: :arrow_up: Update Text_LanguageDetect. Update from v0.3.0 (2012) to v1.0.0 (2017) which should remove some warnings and improve PHP7 support. Using composer to handle this PEAR library now. Fix a problem in FeedutilsTest. --- include/help.php | 28 +++++++++++++++++----------- include/language.php | 16 +++++++--------- 2 files changed, 24 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/include/help.php b/include/help.php index 02c3cb8e4..0dc37e517 100644 --- a/include/help.php +++ b/include/help.php @@ -28,7 +28,7 @@ function get_help_content($tocpath = false) { } if($path) { - + $title = basename($path); if(! $tocpath) \App::$page['title'] = t('Help:') . ' ' . ucwords(str_replace('-',' ',notags($title))); @@ -38,10 +38,10 @@ function get_help_content($tocpath = false) { // available and so default back to the English TOC at /doc/toc.{html,bb,md} // TODO: This is incompatible with the hierarchical TOC construction // defined in /Zotlabs/Widget/Helpindex.php. - if($tocpath !== false && - load_doc_file('doc/' . $path . '.md') === '' && - load_doc_file('doc/' . $path . '.bb') === '' && - load_doc_file('doc/' . $path . '.html') === '' + if($tocpath !== false && + load_doc_file('doc/' . $path . '.md') === '' && + load_doc_file('doc/' . $path . '.bb') === '' && + load_doc_file('doc/' . $path . '.html') === '' ) { $path = $title; } @@ -120,22 +120,28 @@ function preg_callback_help_include($matches) { } +/** + * @brief + * + * @return boolean|array + */ function determine_help_language() { - require_once('Text/LanguageDetect.php'); $lang_detect = new Text_LanguageDetect(); // Set this mode to recognize language by the short code like "en", "ru", etc. $lang_detect->setNameMode(2); - // If the language was specified in the URL, override the language preference + // If the language was specified in the URL, override the language preference // of the browser. Default to English if both of these are absent. if($lang_detect->languageExists(argv(1))) { $lang = argv(1); $from_url = true; } else { $lang = \App::$language; - if(! isset($lang)) + if(! isset($lang)) $lang = 'en'; + $from_url = false; } + return array('language' => $lang, 'from_url' => $from_url); } @@ -145,14 +151,14 @@ function load_doc_file($s) { $x = determine_help_language(); $lang = $x['language']; $url_idx = ($x['from_url'] ? 1 : 0); - // The English translation is at the root of /doc/. Other languages are in + // The English translation is at the root of /doc/. Other languages are in // subfolders named by the language code such as "de", "es", etc. if($lang !== 'en') { - $path .= '/' . $lang; + $path .= '/' . $lang; } $b = basename($s); - + for($i=1+$url_idx; $i t('Select an alternate language'), '$langs' => array($lang_options, $selected), - + )); return $o; -- cgit v1.2.3 From 66832c41e9fff481c20ca219b3cc0a4e53b8b551 Mon Sep 17 00:00:00 2001 From: Klaus Weidenbach Date: Wed, 25 Oct 2017 23:21:07 +0200 Subject: :arrow_up: Update intl library. Update intl library from v0.4? (2014) to v0.7.4 (2016). Use global composer autoloader now. --- include/language.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'include') diff --git a/include/language.php b/include/language.php index eb286231a..f6f266685 100644 --- a/include/language.php +++ b/include/language.php @@ -8,6 +8,7 @@ * language related tasks. */ +use CommerceGuys\Intl\Language\LanguageRepository; /** * @brief Get the browser's submitted preferred languages. @@ -298,11 +299,7 @@ function detect_language($s) { * @param string $s Language code to look up * @param string $l (optional) In which language to return the name * @return string with the language name, or $s if unrecognized - * - * @todo include CommerceGuys\Intl through composer like SabreDAV. */ -require_once(__DIR__ . '/../library/intl/vendor/autoload.php'); -use CommerceGuys\Intl\Language\LanguageRepository; function get_language_name($s, $l = null) { // get() expects the second part to be in upper case if (strpos($s, '-') !== false) $s = substr($s, 0, 2) . strtoupper(substr($s, 2)); -- cgit v1.2.3 From 1be98d7b7fea30a929d27e7aa0b1412da3276b2c Mon Sep 17 00:00:00 2001 From: Klaus Weidenbach Date: Sat, 28 Oct 2017 01:22:59 +0200 Subject: :white_check_mark: Some more work on unit tests. Some small improvements for coverage report. Add more functions from include/text.php Update composer dev libraries for phpunit. --- include/feedutils.php | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/feedutils.php b/include/feedutils.php index 217da8188..62fa4849a 100644 --- a/include/feedutils.php +++ b/include/feedutils.php @@ -1662,8 +1662,6 @@ function handle_feed($uid, $abook_id, $url) { /** * @brief Return a XML tag with author information. * - * @hooks \b atom_author Possibility to add further tags to returned XML string - * * \e string The created XML tag as a string without closing tag * @param string $tag The XML tag to create * @param string $nick preferred username * @param string $name displayed name of the author @@ -1672,7 +1670,7 @@ function handle_feed($uid, $abook_id, $url) { * @param int $w image width * @param string $type profile photo mime type * @param string $photo Fully qualified URL to a profile/avator photo - * @return string + * @return string XML tag */ function atom_author($tag, $nick, $name, $uri, $h, $w, $type, $photo) { $o = ''; @@ -1695,6 +1693,11 @@ function atom_author($tag, $nick, $name, $uri, $h, $w, $type, $photo) { $o .= ' ' . $nick . '' . "\r\n"; $o .= ' ' . $name . '' . "\r\n"; + /** + * @hooks atom_author + * Possibility to add further tags to returned XML string. + * * \e string The created XML tag as a string without closing tag + */ call_hooks('atom_author', $o); $o .= "\r\n"; @@ -1703,17 +1706,23 @@ function atom_author($tag, $nick, $name, $uri, $h, $w, $type, $photo) { } -function atom_render_author($tag,$xchan) { +/** + * @brief Return an atom tag with author information from an xchan. + * + * @param string $tag + * @param array $xchan + * @return string + */ +function atom_render_author($tag, $xchan) { - - $nick = xmlify(substr($xchan['xchan_addr'],0,strpos($xchan['xchan_addr'],'@'))); + $nick = xmlify(substr($xchan['xchan_addr'], 0, strpos($xchan['xchan_addr'], '@'))); $id = xmlify($xchan['xchan_url']); $name = xmlify($xchan['xchan_name']); $photo = xmlify($xchan['xchan_photo_l']); $type = xmlify($xchan['xchan_photo_mimetype']); $w = $h = 300; - $o .= "<$tag>\r\n"; + $o = "<$tag>\r\n"; $o .= " http://activitystrea.ms/schema/1.0/person\r\n"; $o .= " $id\r\n"; $o .= " $nick\r\n"; @@ -1724,13 +1733,16 @@ function atom_render_author($tag,$xchan) { $o .= ' ' . $nick . '' . "\r\n"; $o .= ' ' . $name . '' . "\r\n"; + /** + * @hooks atom_render_author + * Possibility to add further tags to returned XML string. + * * \e string The created XML tag as a string without closing tag + */ call_hooks('atom_render_author', $o); $o .= "\r\n"; return $o; - - } function compat_photos_list($s) { -- cgit v1.2.3 From 4fef29e61c32b129f0090a4962d91607337a9406 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 29 Oct 2017 22:21:52 -0700 Subject: memory overflow trying to delete a connection with a very high noise to signal ratio --- include/connections.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/connections.php b/include/connections.php index 60bce018e..e9d7daa2d 100644 --- a/include/connections.php +++ b/include/connections.php @@ -369,7 +369,7 @@ function contact_remove($channel_id, $abook_id) { return false; - $r = q("select * from item where (owner_xchan = '%s' or author_xchan = '%s') and uid = %d", + $r = q("select id from item where (owner_xchan = '%s' or author_xchan = '%s') and uid = %d", dbesc($abook['abook_xchan']), dbesc($abook['abook_xchan']), intval($channel_id) -- cgit v1.2.3 From 60da235efb53b4e38c91489b500dac75facc4a9b Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 30 Oct 2017 20:43:24 -0700 Subject: use 1) personal setting, 2) site setting, 3) default false - for system.channel_menu --- include/nav.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/nav.php b/include/nav.php index 89947e270..af0ebbae2 100644 --- a/include/nav.php +++ b/include/nav.php @@ -312,7 +312,7 @@ EOT; '$pleasewait' => t('Please wait...'), '$nav_apps' => $nav_apps, '$navbar_apps' => $navbar_apps, - '$channel_menu' => get_config('system','channel_menu'), + '$channel_menu' => get_pconfig(App::$profile_uid,'system','channel_menu',get_config('system','channel_menu')), '$channel_thumb' => ((App::$profile) ? App::$profile['thumb'] : ''), '$channel_apps' => $channel_apps, '$addapps' => t('Add Apps'), -- cgit v1.2.3 From 6efef3922b9fe6864c0855e6407b77ca54af70c5 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 31 Oct 2017 15:41:44 -0700 Subject: add another delivery control parameter (force queue threshold) --- include/queue_fn.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/queue_fn.php b/include/queue_fn.php index c9179b953..c09033d0a 100644 --- a/include/queue_fn.php +++ b/include/queue_fn.php @@ -158,6 +158,16 @@ function queue_deliver($outq, $immediate = false) { } } + if($immediate) { + $x = q("select count(outq_hash) as total from outq where outq_delivered = 0"); + if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',300))) { + logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO); + update_queue_item($outq['outq_hash']); + return; + } + } + + $arr = array('outq' => $outq, 'base' => $base, 'handled' => false, 'immediate' => $immediate); call_hooks('queue_deliver',$arr); if($arr['handled']) @@ -205,7 +215,7 @@ function queue_deliver($outq, $immediate = false) { else { logger('deliver: queue post returned ' . $result['return_code'] . ' from ' . $outq['outq_posturl'],LOGGER_DEBUG); - update_queue_item($outq['outq_posturl']); + update_queue_item($outq['outq_hash']); } return; } -- cgit v1.2.3 From 7d9d1e0cdb21e47aec20b64148a0714323383914 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 1 Nov 2017 02:15:40 -0700 Subject: Maria's profile photo issue, please push to master. --- include/zot.php | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/zot.php b/include/zot.php index dad30dbb0..5270ed8b8 100644 --- a/include/zot.php +++ b/include/zot.php @@ -3649,6 +3649,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { $disallowed = array('id','aid','uid','guid'); foreach($arr['profile'] as $profile) { + $x = q("select * from profile where profile_guid = '%s' and uid = %d limit 1", dbesc($profile['profile_guid']), intval($channel['channel_id']) @@ -3671,6 +3672,9 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { if(in_array($k,$disallowed)) continue; + if($profile['is_default'] && in_array($k,['photo','thumb'])) + continue; + if($k === 'name') $clean['fullname'] = $v; elseif($k === 'with') -- cgit v1.2.3 From 28cd2759d76c9227c474c8c1da073a4f91cf5523 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 1 Nov 2017 17:50:57 -0700 Subject: do not send message_list responses to dead sites (this delivery method bypassed the notifier) --- include/zot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/zot.php b/include/zot.php index 5270ed8b8..6647daa0a 100644 --- a/include/zot.php +++ b/include/zot.php @@ -3872,7 +3872,7 @@ function zot_reply_message_request($data) { if ($messages) { $env_recips = null; - $r = q("select hubloc.*, site.site_crypto from hubloc left join site on hubloc_url = site_url where hubloc_hash = '%s' and hubloc_error = 0 and hubloc_deleted = 0", + $r = q("select hubloc.*, site.site_crypto from hubloc left join site on hubloc_url = site_url where hubloc_hash = '%s' and hubloc_error = 0 and hubloc_deleted = 0 and site.site_dead = 0 ", dbesc($sender_hash) ); if (! $r) { -- cgit v1.2.3 From 52657b6215b3b7104a89c8c3fea09a7f37ebf71e Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 1 Nov 2017 19:24:29 -0700 Subject: don't perform zot_refresh on dead sites unless $force is set --- include/zot.php | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'include') diff --git a/include/zot.php b/include/zot.php index 6647daa0a..bb87a234c 100644 --- a/include/zot.php +++ b/include/zot.php @@ -285,6 +285,16 @@ function zot_refresh($them, $channel = null, $force = false) { return false; } + $s = q("select site_dead from site where site_url = '%s' limit 1", + dbesc($url) + ); + + if($s && intval($s[0]['site_dead']) && (! $force)) { + logger('zot_refresh: site ' . $url . ' is marked dead and force flag is not set. Cancelling operation.'); + return false; + } + + $token = random_string(); $postvars = []; -- cgit v1.2.3 From cdaf5f3fc0756157863008df185f6b344241c147 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 2 Nov 2017 08:44:46 +0100 Subject: fix issues with diaspora xchans --- include/message.php | 6 +++--- include/text.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/message.php b/include/message.php index 3f003e020..477c7172c 100644 --- a/include/message.php +++ b/include/message.php @@ -381,7 +381,7 @@ function private_messages_list($uid, $mailbox = '', $start = 0, $numitems = 0) { $chans[] = $s; } - $c = q("select * from xchan where xchan_hash in (" . implode(',',$chans) . ")"); + $c = q("select * from xchan where xchan_hash in (" . protect_sprintf(implode(',',$chans)) . ")"); foreach($r as $k => $rr) { $r[$k]['from'] = find_xchan_in_array($rr['from_xchan'],$c); @@ -420,7 +420,7 @@ function private_messages_fetch_message($channel_id, $messageitem_id, $updatesee $chans[] = $s; } - $c = q("select * from xchan where xchan_hash in (" . implode(',',$chans) . ")"); + $c = q("select * from xchan where xchan_hash in (" . protect_sprintf(implode(',',$chans)) . ")"); foreach($messages as $k => $message) { $messages[$k]['from'] = find_xchan_in_array($message['from_xchan'],$c); @@ -545,7 +545,7 @@ function private_messages_fetch_conversation($channel_id, $messageitem_id, $upda } - $c = q("select * from xchan where xchan_hash in (" . implode(',',$chans) . ")"); + $c = q("select * from xchan where xchan_hash in (" . protect_sprintf(implode(',',$chans)) . ")"); foreach($messages as $k => $message) { $messages[$k]['from'] = find_xchan_in_array($message['from_xchan'],$c); diff --git a/include/text.php b/include/text.php index d81b59d75..746c35679 100644 --- a/include/text.php +++ b/include/text.php @@ -2160,7 +2160,7 @@ function xchan_mail_query(&$item) { if(count($arr)) { $chans = q("select xchan.*,hubloc.* from xchan left join hubloc on hubloc_hash = xchan_hash - where xchan_hash in (" . implode(',', $arr) . ") and hubloc_primary = 1"); + where xchan_hash in (" . protect_sprintf(implode(',', $arr)) . ") and hubloc_primary = 1"); } if($chans) { $item['from'] = find_xchan_in_array($item['from_xchan'],$chans); -- cgit v1.2.3 From 1b290f573acdd4f003b6ffcce6c0705ea461bd9d Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 2 Nov 2017 03:13:30 -0700 Subject: put deferred queue logic every place we create a delivery process (except for protocol 'friend requests' which aren't likely to swamp the delivery system). Remove it from the queue_delivery function which was too late to do anything. --- include/network.php | 11 +++++++++++ include/queue_fn.php | 8 -------- include/zot.php | 17 +++++++++++++++++ 3 files changed, 28 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/network.php b/include/network.php index 2f29a70c4..73a6aeff2 100644 --- a/include/network.php +++ b/include/network.php @@ -1438,6 +1438,17 @@ function do_delivery($deliveries) { if(! (is_array($deliveries) && count($deliveries))) return; + + $x = q("select count(outq_hash) as total from outq where outq_delivered = 0"); + if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',300))) { + logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO); + foreach($deliveries as $d) { + update_queue_item($d); + } + return; + } + + $interval = ((get_config('system','delivery_interval') !== false) ? intval(get_config('system','delivery_interval')) : 2 ); diff --git a/include/queue_fn.php b/include/queue_fn.php index c09033d0a..0d98e1e21 100644 --- a/include/queue_fn.php +++ b/include/queue_fn.php @@ -158,14 +158,6 @@ function queue_deliver($outq, $immediate = false) { } } - if($immediate) { - $x = q("select count(outq_hash) as total from outq where outq_delivered = 0"); - if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',300))) { - logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO); - update_queue_item($outq['outq_hash']); - return; - } - } $arr = array('outq' => $outq, 'base' => $base, 'handled' => false, 'immediate' => $immediate); diff --git a/include/zot.php b/include/zot.php index bb87a234c..5764bb99a 100644 --- a/include/zot.php +++ b/include/zot.php @@ -3148,6 +3148,15 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { 'msg' => json_encode($info) )); + + $x = q("select count(outq_hash) as total from outq where outq_delivered = 0"); + if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',300))) { + logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO); + update_queue_item($hash); + continue; + } + + Zotlabs\Daemon\Master::Summon(array('Deliver', $hash)); $total = $total - 1; @@ -3915,6 +3924,14 @@ function zot_reply_message_request($data) { 'msg' => $data_packet )); + + $x = q("select count(outq_hash) as total from outq where outq_delivered = 0"); + if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',300))) { + logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO); + update_queue_item($hash); + continue; + } + /* * invoke delivery to send out the notify packet */ -- cgit v1.2.3 From 0d7062ffdf018287c14f09666cc0e0f82997ccca Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 2 Nov 2017 15:43:14 -0700 Subject: more queue work --- include/network.php | 9 +++++++-- include/queue_fn.php | 7 ++++--- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/network.php b/include/network.php index 73a6aeff2..2caf29ab5 100644 --- a/include/network.php +++ b/include/network.php @@ -1433,14 +1433,19 @@ function scrape_feed($url) { -function do_delivery($deliveries) { + + +function do_delivery($deliveries, $force = false) { + + // $force is set if a site that wasn't responding suddenly returns to life. + // Try and shove through everything going to that site while it's responding. if(! (is_array($deliveries) && count($deliveries))) return; $x = q("select count(outq_hash) as total from outq where outq_delivered = 0"); - if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',300))) { + if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',300)) && (! $force)) { logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO); foreach($deliveries as $d) { update_queue_item($d); diff --git a/include/queue_fn.php b/include/queue_fn.php index 0d98e1e21..5fb0d5f1e 100644 --- a/include/queue_fn.php +++ b/include/queue_fn.php @@ -42,7 +42,7 @@ function update_queue_item($id, $add_priority = 0) { $next = datetime_convert('UTC','UTC','now + 1 hour'); } else { - $next = datetime_convert('UTC','UTC','now + 15 minutes'); + $next = datetime_convert('UTC','UTC','now + ' . intval($add_priority) . ' minutes'); } q("UPDATE outq SET outq_updated = '%s', @@ -200,14 +200,15 @@ function queue_deliver($outq, $immediate = false) { } } if($piled_up) { - do_delivery($piled_up); + // call do_delivery() with the force flag + do_delivery($piled_up, true); } } } else { logger('deliver: queue post returned ' . $result['return_code'] . ' from ' . $outq['outq_posturl'],LOGGER_DEBUG); - update_queue_item($outq['outq_hash']); + update_queue_item($outq['outq_hash'],10); } return; } -- cgit v1.2.3 From 0ce7358f0f00cb000562dc34be13459eb5779c18 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 3 Nov 2017 13:49:58 +0100 Subject: update item_normal() to not include ACTIVITY_OBJ_FILE obj_type --- include/items.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/items.php b/include/items.php index dd8b394d3..08e53553b 100755 --- a/include/items.php +++ b/include/items.php @@ -173,19 +173,19 @@ function comments_are_now_closed($item) { function item_normal() { return " and item.item_hidden = 0 and item.item_type = 0 and item.item_deleted = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0 - and item.item_blocked = 0 "; + and item.item_blocked = 0 and item.obj_type != '" . ACTIVITY_OBJ_FILE . "' "; } function item_normal_search() { return " and item.item_hidden = 0 and item.item_type in (0,3,6) and item.item_deleted = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0 - and item.item_blocked = 0 "; + and item.item_blocked = 0 and item.obj_type != '" . ACTIVITY_OBJ_FILE . "' "; } function item_normal_update() { return " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0 - and item.item_blocked = 0 "; + and item.item_blocked = 0 and item.obj_type != '" . ACTIVITY_OBJ_FILE . "' "; } @@ -201,7 +201,7 @@ function is_item_normal($item) { if(intval($item['item_hidden']) || intval($item['item_type']) || intval($item['item_deleted']) || intval($item['item_unpublished']) || intval($item['item_delayed']) || intval($item['item_pending_remove']) - || intval($item['item_blocked'])) + || intval($item['item_blocked']) || ($item['obj_type'] == ACTIVITY_OBJ_FILE)) return false; return true; -- cgit v1.2.3 From 1159dd59edc40b753b9f4fe55165b4ee3c22285d Mon Sep 17 00:00:00 2001 From: zotlabs Date: Fri, 3 Nov 2017 14:07:00 -0700 Subject: fix cloud redirects with owt tokens --- include/zid.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'include') diff --git a/include/zid.php b/include/zid.php index ce9f70385..5ade6b0f8 100644 --- a/include/zid.php +++ b/include/zid.php @@ -89,10 +89,35 @@ function strip_zids($s) { return preg_replace('/[\?&]zid=(.*?)(&|$)/ism','$2',$s); } +function strip_owt($s) { + return preg_replace('/[\?&]owt=(.*?)(&|$)/ism','$2',$s); +} + function strip_zats($s) { return preg_replace('/[\?&]zat=(.*?)(&|$)/ism','$2',$s); } +function strip_auth_query_params() { + + $_SERVER['QUERY_STRING'] = str_replace(array('?f=', '&f='), array('', ''), $_SERVER['QUERY_STRING']); + $_SERVER['QUERY_STRING'] = strip_zids($_SERVER['QUERY_STRING']); + $_SERVER['QUERY_STRING'] = strip_owt($_SERVER['QUERY_STRING']); + + $_SERVER['REQUEST_URI'] = str_replace(array('?f=', '&f='), array('', ''), $_SERVER['REQUEST_URI']); + $_SERVER['REQUEST_URI'] = strip_zids($_SERVER['REQUEST_URI']); + $_SERVER['REQUEST_URI'] = strip_owt($_SERVER['REQUEST_URI']); + + + $_ENV['QUERY_STRING'] = str_replace(array('?f=', '&f='), array('', ''), $_ENV['QUERY_STRING']); + $_ENV['QUERY_STRING'] = strip_zids($_ENV['QUERY_STRING']); + $_ENV['QUERY_STRING'] = strip_owt($_ENV['QUERY_STRING']); + + $_ENV['REQUEST_URI'] = str_replace(array('?f=', '&f='), array('', ''), $_ENV['REQUEST_URI']); + $_ENV['REQUEST_URI'] = strip_zids($_ENV['REQUEST_URI']); + $_ENV['REQUEST_URI'] = strip_owt($_ENV['REQUEST_URI']); + +} + /** * zidify_callback() and zidify_links() work together to turn any HTML a tags with class="zrl" into zid links -- cgit v1.2.3 From fae9c236371ba70b2ac7624d6020c76a77c1944d Mon Sep 17 00:00:00 2001 From: zotlabs Date: Fri, 3 Nov 2017 14:20:49 -0700 Subject: imagedata not set correctly if large photo AND imagick is not installed --- include/photos.php | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/photos.php b/include/photos.php index 5de68f162..503a725cd 100644 --- a/include/photos.php +++ b/include/photos.php @@ -75,6 +75,9 @@ function photo_upload($channel, $observer, $args) { $imagedata = @file_get_contents($tmp_name); @unlink($tmp_name); } + else { + $imagedata = @file_get_contents($args['os_syspath']); + } } else { $imagedata = @file_get_contents($args['os_syspath']); -- cgit v1.2.3 From 1a737be2b408135177a9e94dcffd0f68c0aca90b Mon Sep 17 00:00:00 2001 From: Klaus Weidenbach Date: Tue, 5 Sep 2017 00:23:42 +0200 Subject: :bulb: Improving Doxygen documentation. Fix some Doxygen parsing errors. Improve hooks documentation. --- include/acl_selectors.php | 4 +- include/attach.php | 130 +++++++++---- include/channel.php | 428 +++++++++++++++++++++++++--------------- include/datetime.php | 87 +++++---- include/event.php | 139 +++++++------ include/feedutils.php | 151 ++++++++++----- include/items.php | 439 +++++++++++++++++++++++++++-------------- include/markdown.php | 71 ++++--- include/network.php | 214 +++++++++++++------- include/photos.php | 227 +++++++++++----------- include/plugin.php | 70 ++++--- include/zid.php | 76 +++++--- include/zot.php | 485 ++++++++++++++++++++++++++++------------------ 13 files changed, 1573 insertions(+), 948 deletions(-) (limited to 'include') diff --git a/include/acl_selectors.php b/include/acl_selectors.php index 09c24f82c..4e203074b 100644 --- a/include/acl_selectors.php +++ b/include/acl_selectors.php @@ -110,7 +110,7 @@ function fixacl(&$item) { * * @param array $defaults Optional access control list for the initial state of the dialog. * @param boolean $show_jotnets Whether plugins for federated networks should be included in the permissions dialog -* @param PermissionDescription $emptyACL_description - An optional description for the permission implied by selecting an empty ACL. Preferably an instance of PermissionDescription. +* @param \Zotlabs\Lib\PermissionDescription $emptyACL_description - An optional description for the permission implied by selecting an empty ACL. Preferably an instance of PermissionDescription. * @param string $dialog_description Optional message to include at the top of the dialog. E.g. "Warning: Post permissions cannot be changed once sent". * @param string $context_help Allows the dialog to present a help icon. E.g. "acl_dialog_post" * @param boolean $readonly Not implemented yet. When implemented, the dialog will use acl_readonly.tpl instead, so that permissions may be viewed for posts that can no longer have their permissions changed. @@ -172,7 +172,7 @@ function populate_acl($defaults = null,$show_jotnets = true, $emptyACL_descripti if(count($allow_cid) === 1 && $channel && $allow_cid[0] = $channel['channel_hash'] && (! $allow_gid) && (! $deny_gid) && (! $deny_cid)) { $just_me = true; $custom = false; - } + } $r = q("SELECT id, profile_guid, profile_name from profile where is_default = 0 and uid = %d order by profile_name", intval(local_channel()) diff --git a/include/attach.php b/include/attach.php index 78e133b03..bfe3d5d46 100644 --- a/include/attach.php +++ b/include/attach.php @@ -21,7 +21,7 @@ require_once('include/group.php'); * This function takes a file name and guess the mimetype from the * filename extension. * - * @param $filename a string filename + * @param string $filename a string filename * @return string The mimetype according to a file ending. */ function z_mime_content_type($filename) { @@ -412,6 +412,10 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { require_once('include/photos.php'); + /** + * @hooks photo_upload_begin + * Called when attempting to upload a photo. + */ call_hooks('photo_upload_begin', $arr); $ret = array('success' => false); @@ -486,14 +490,36 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $x = attach_mkdir($channel,$observer_hash,$arr); if($x['message']) logger('import_directory: ' . $x['message']); + return; } } elseif($options !== 'update') { - $f = array('src' => '', 'filename' => '', 'filesize' => 0, 'type' => ''); - - call_hooks('photo_upload_file',$f); - call_hooks('attach_upload_file',$f); + $f = [ + 'src' => '', + 'filename' => '', + 'filesize' => 0, + 'type' => '' + ]; + + /** + * @hooks photo_upload_file + * Called to generate alternate filenames for an upload. + * * \e string \b src - return value, default empty + * * \e string \b filename - return value, default empty + * * \e number \b filesize - return value, default 0 + * * \e string \b type - return value, default empty + */ + call_hooks('photo_upload_file', $f); + /** + * @hooks attach_upload_file + * Called when uploading a file. + * * \e string \b src - return value, default empty + * * \e string \b filename - return value, default empty + * * \e number \b filesize - return value, default 0 + * * \e string \b type - return value, default empty + */ + call_hooks('attach_upload_file', $f); if (x($f,'src') && x($f,'filesize')) { $src = $f['src']; @@ -680,7 +706,13 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $ret['message'] = sprintf( t('File exceeds size limit of %d'), $maxfilesize); if($remove_when_processed) @unlink($src); - call_hooks('photo_upload_end',$ret); + + /** + * @hooks photo_upload_end + * Called when a photo upload has been processed. + */ + call_hooks('photo_upload_end', $ret); + return $ret; } @@ -695,7 +727,12 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { if($remove_when_processed) @unlink($src); - call_hooks('photo_upload_end',$ret); + /** + * @hooks photo_upload_end + * Called when a photo upload has been processed. + */ + call_hooks('photo_upload_end', $ret); + return $ret; } } @@ -773,7 +810,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { ); } elseif($options === 'update') { - $r = q("update attach set filename = '%s', filetype = '%s', folder = '%s', edited = '%s', os_storage = %d, is_photo = %d, os_path = '%s', + $r = q("update attach set filename = '%s', filetype = '%s', folder = '%s', edited = '%s', os_storage = %d, is_photo = %d, os_path = '%s', display_path = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where id = %d and uid = %d", dbesc((array_key_exists('filename',$arr)) ? $arr['filename'] : $x[0]['filename']), dbesc((array_key_exists('filetype',$arr)) ? $arr['filetype'] : $x[0]['filetype']), @@ -862,7 +899,13 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { if(! $r) { $ret['message'] = t('File upload failed. Possible system limit or action terminated.'); - call_hooks('photo_upload_end',$ret); + + /** + * @hooks photo_upload_end + * Called when a photo upload has been processed. + */ + call_hooks('photo_upload_end', $ret); + return $ret; } @@ -875,15 +918,25 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { if(! $r) { $ret['message'] = t('Stored file could not be verified. Upload failed.'); - call_hooks('photo_upload_end',$ret); + + /** + * @hooks photo_upload_end + * Called when a photo upload has been processed. + */ + call_hooks('photo_upload_end', $ret); + return $ret; } $ret['success'] = true; $ret['data'] = $r[0]; if(! $is_photo) { - // This would've been called already with a success result in photos_upload() if it was a photo. - call_hooks('photo_upload_end',$ret); + /** + * @hooks photo_upload_end + * Called when a photo upload has been processed. + * This would've been called already with a success result in photos_upload() if it was a photo. + */ + call_hooks('photo_upload_end', $ret); } if($dosync) { @@ -986,7 +1039,7 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { $os_basepath = 'store/' . $channel['channel_address']; - logger('attach_mkdir: basepath: ' . $os_basepath); + logger('basepath: ' . $os_basepath); if(! is_dir($os_basepath)) os_mkdir($os_basepath,STORAGE_DEFAULT_PERMISSIONS, true); @@ -1055,7 +1108,7 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { return $ret; } - $dpath = $r[0]['filename'] . (($dpath) ? '/' . $dpath : ''); + $dpath = $r[0]['filename'] . (($dpath) ? '/' . $dpath : ''); if($lfile) $lpath = $r[0]['hash'] . (($lpath) ? '/' . $lpath : ''); @@ -1154,7 +1207,7 @@ function attach_mkdirp($channel, $observer_hash, $arr = null) { $basepath = 'store/' . $channel['channel_address']; - logger('attach_mkdirp: basepath: ' . $basepath); + logger('basepath: ' . $basepath); if(! is_dir($basepath)) os_mkdir($basepath,STORAGE_DEFAULT_PERMISSIONS, true); @@ -1180,6 +1233,7 @@ function attach_mkdirp($channel, $observer_hash, $arr = null) { foreach($paths as $p) { if(! $p) continue; + $arx = array( 'filename' => $p, 'folder' => $current_parent, @@ -1308,7 +1362,7 @@ function attach_delete($channel_id, $resource, $is_photo = 0) { ); if(! $r) { - attach_drop_photo($channel_id,$resource); + attach_drop_photo($channel_id,$resource); return; } @@ -1501,6 +1555,13 @@ function find_folder_hash_by_attach_hash($channel_id, $attachHash, $recurse = fa return $hash; } +/** + * @brief Return the hash of an attachment's folder. + * + * @param int $channel_id + * @param string $path + * @return string + */ function find_folder_hash_by_path($channel_id, $path) { if(! $path) @@ -1530,7 +1591,6 @@ function find_folder_hash_by_path($channel_id, $path) { return ''; return $parent_hash; - } /** @@ -1557,9 +1617,11 @@ function find_filename_by_hash($channel_id, $attachHash) { } /** + * @brief Pipes $in to $out in 16MB chunks. * - * @param $in - * @param $out + * @param resource $in File pointer of input + * @param resource $out File pointer of output + * @return number with the size */ function pipe_streams($in, $out) { $size = 0; @@ -1726,11 +1788,12 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, } /** - * @brief Create file activity object + * @brief Create file activity object. * * @param int $channel_id * @param string $hash - * @param string $cloudpath + * @param string $url + * @return array An associative array for the specified file. */ function get_file_activity_object($channel_id, $hash, $url) { @@ -2257,7 +2320,7 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) { if($r[0]['is_photo']) { - $t = q("update photo set album = '%s', filename = '%s', os_path = '%s', display_path = '%s' + $t = q("update photo set album = '%s', filename = '%s', os_path = '%s', display_path = '%s' where resource_id = '%s' and uid = %d", dbesc($newdirname), dbesc($filename), @@ -2349,8 +2412,6 @@ function attach_syspaths($channel_id,$attach_hash) { while($attach_hash); return [ 'os_path' => $os_path, 'path' => $path ]; - - } @@ -2386,7 +2447,7 @@ function save_chunk($channel,$start,$end,$len) { $tmp_path = $_FILES['files']['tmp_name']; $new_base = 'store/[data]/' . $channel['channel_address'] . '/tmp'; os_mkdir($new_base,STORAGE_DEFAULT_PERMISSIONS,true); - + $new_path = $new_base . '/' . $_FILES['files']['name']; if(! file_exists($new_path)) { @@ -2417,20 +2478,19 @@ function save_chunk($channel,$start,$end,$len) { } -/* - * chunkloader - * Submit handler for chunked uploads - * +/** + * @brief Submit handler for chunked uploads. + * + * @param array $channel + * @param array $arr + * @return array */ - -function chunkloader($channel,$arr) { +function chunkloader($channel, $arr) { logger('request: ' . print_r($arr,true), LOGGER_DEBUG); logger('files: ' . print_r($_FILES,true), LOGGER_DEBUG); - $result = []; - $tmp_path = $_FILES['file']['tmp_name']; $new_base = 'store/[data]/' . $channel['channel_address'] . '/tmp'; @@ -2439,7 +2499,7 @@ function chunkloader($channel,$arr) { $new_path = $new_base . '/' . $arr['resumableFilename']; rename($tmp_path,$new_path . '.' . intval($arr['resumableChunkNumber'])); - + $missing_parts = false; for($x = 1; $x <= intval($arr['resumableTotalChunks']); $x ++) { if(! file_exists($new_path . '.' . $x)) { @@ -2475,7 +2535,7 @@ function chunkloader($channel,$arr) { $result['error'] = 0; $result['size'] = $arr['resumableTotalSize']; $result['complete'] = true; - return $result; + return $result; } diff --git a/include/channel.php b/include/channel.php index 399dff87e..6a6022aba 100644 --- a/include/channel.php +++ b/include/channel.php @@ -1,6 +1,7 @@ $name]; + /** + * @hooks validate_channelname + * Used to validate the names used by a channel. + * * \e string \b name + * * \e string \b message - return error message + */ call_hooks('validate_channelname', $arr); if (x($arr, 'message')) @@ -259,7 +264,6 @@ function create_identity($arr) { 'channel_system' => intval($system), 'channel_expire_days' => intval($expire), 'channel_timezone' => App::$timezone - ] ); @@ -280,9 +284,19 @@ function create_identity($arr) { $photo_type = null; - $z = [ 'account' => $a[0], 'channel' => $r[0], 'photo_url' => '' ]; - call_hooks('create_channel_photo',$z); - + $z = [ + 'account' => $a[0], + 'channel' => $r[0], + 'photo_url' => '' + ]; + /** + * @hooks create_channel_photo + * * \e array \b account + * * \e array \b channel + * * \e string \b photo_url - Return value + */ + call_hooks('create_channel_photo', $z); + if($z['photo_url']) { $photo_type = import_channel_photo_from_url($z['photo_url'],$arr['account_id'],$r[0]['channel_id']); } @@ -322,7 +336,7 @@ function create_identity($arr) { ] ); if(! $r) - logger('create_identity: Unable to store hub location'); + logger('Unable to store hub location'); $newuid = $ret['channel']['channel_id']; @@ -454,12 +468,18 @@ function create_identity($arr) { require_once('include/follow.php'); if(! is_array($accts)) $accts = array($accts); + foreach($accts as $acct) { if(trim($acct)) new_contact($newuid,trim($acct),$ret['channel'],false); } } + /** + * @hooks create_identity + * Called when creating a channel. + * * \e int - The UID of the created identity + */ call_hooks('create_identity', $newuid); Zotlabs\Daemon\Master::Summon(array('Directory', $ret['channel']['channel_id'])); @@ -576,14 +596,14 @@ function channel_change_address($channel,$new_address) { $old_address = $channel['channel_address']; if($new_address === 'sys') { - $ret['message'] = t('Reserved nickname. Please choose another.'); - return $ret; - } + $ret['message'] = t('Reserved nickname. Please choose another.'); + return $ret; + } - if(check_webbie(array($new_address)) !== $new_address) { - $ret['message'] = t('Nickname has unsupported characters or is already being used on this site.'); - return $ret; - } + if(check_webbie(array($new_address)) !== $new_address) { + $ret['message'] = t('Nickname has unsupported characters or is already being used on this site.'); + return $ret; + } $r = q("update channel set channel_address = '%s' where channel_id = %d", dbesc($new_address), @@ -644,7 +664,7 @@ function channel_change_address($channel,$new_address) { ); } } - } + } Zotlabs\Daemon\Master::Summon(array('Notifier', 'refresh_all', $channel['channel_id'])); @@ -653,10 +673,6 @@ function channel_change_address($channel,$new_address) { } - - - - /** * @brief Set default channel to be used on login. * @@ -664,9 +680,9 @@ function channel_change_address($channel,$new_address) { * login account * @param int $channel_id * channel id to set as default for this account - * @param boolean $force - * if true, set this default unconditionally - * if $force is false only do this if there is no existing default + * @param boolean $force (optional) default true + * - if true, set this default unconditionally + * - if $force is false only do this if there is no existing default */ function set_default_login_identity($account_id, $channel_id, $force = true) { $r = q("select account_default_channel from account where account_id = %d limit 1", @@ -685,8 +701,6 @@ function set_default_login_identity($account_id, $channel_id, $force = true) { /** * @brief Return an array with default list of sections to export. * - * @hooks get_default_export_sections - * * \e array \b sections * @return array with default section names to export */ function get_default_export_sections() { @@ -703,6 +717,11 @@ function get_default_export_sections() { ]; $cb = [ 'sections' => $sections ]; + /** + * @hooks get_default_export_sections + * Called to get the default list of functional data groups to export in identity_basic_export(). + * * \e array \b sections - return value + */ call_hooks('get_default_export_sections', $cb); return $cb['sections']; @@ -714,15 +733,11 @@ function get_default_export_sections() { * which would be necessary to create a nomadic identity clone. This includes * most channel resources and connection information with the exception of content. * - * @hooks identity_basic_export - * * \e int \b channel_id - * * \e array \b sections - * * \e array \b data * @param int $channel_id * Channel_id to export * @param array $sections (optional) * Which sections to include in the export, default see get_default_export_sections() - * @returns array + * @return array * See function for details */ function identity_basic_export($channel_id, $sections = null) { @@ -967,7 +982,7 @@ function identity_basic_export($channel_id, $sections = null) { } } - if(in_array('items',$sections)) { + if(in_array('items', $sections)) { /** @warning this may run into memory limits on smaller systems */ /** export three months of posts. If you want to export and import all posts you have to start with @@ -991,22 +1006,42 @@ function identity_basic_export($channel_id, $sections = null) { } } - $addon = [ 'channel_id' => $channel_id, 'sections' => $sections, 'data' => $ret]; - call_hooks('identity_basic_export',$addon); + $addon = [ + 'channel_id' => $channel_id, + 'sections' => $sections, + 'data' => $ret + ]; + /** + * @hooks identity_basic_export + * Called when exporting a channel's basic information for backup or transfer. + * * \e number \b channel_id - The channel ID + * * \e array \b sections + * * \e array \b data - The data will get returned + */ + call_hooks('identity_basic_export', $addon); $ret = $addon['data']; return $ret; } - -function identity_export_year($channel_id,$year,$month = 0) { +/** + * @brief Export items for a year, or a month of a year. + * + * @param int $channel_id The channel ID + * @param number $year YYYY + * @param number $month (optional) 0-12, default 0 complete year + * @return array An associative array + * * \e array \b relocate - (optional) + * * \e array \b item - array with items encoded_item() + */ +function identity_export_year($channel_id, $year, $month = 0) { if(! $year) return array(); if($month && $month <= 12) { - $target_month = sprintf('%02d',$month); - $target_month_plus = sprintf('%02d',$month+1); + $target_month = sprintf('%02d', $month); + $target_month_plus = sprintf('%02d', $month+1); } else $target_month = '01'; @@ -1017,13 +1052,13 @@ function identity_export_year($channel_id,$year,$month = 0) { if($ch) { $ret['relocate'] = [ 'channel_address' => $ch['channel_address'], 'url' => z_root()]; } - $mindate = datetime_convert('UTC','UTC',$year . '-' . $target_month . '-01 00:00:00'); + $mindate = datetime_convert('UTC', 'UTC', $year . '-' . $target_month . '-01 00:00:00'); if($month && $month < 12) - $maxdate = datetime_convert('UTC','UTC',$year . '-' . $target_month_plus . '-01 00:00:00'); + $maxdate = datetime_convert('UTC', 'UTC', $year . '-' . $target_month_plus . '-01 00:00:00'); else - $maxdate = datetime_convert('UTC','UTC',$year+1 . '-01-01 00:00:00'); + $maxdate = datetime_convert('UTC', 'UTC', $year+1 . '-01-01 00:00:00'); - $r = q("select * from item where ( item_wall = 1 or item_type != %d ) and item_deleted = 0 and uid = %d and created >= '%s' and created < '%s' and resource_type = '' order by created", + $r = q("select * from item where ( item_wall = 1 or item_type != %d ) and item_deleted = 0 and uid = %d and created >= '%s' and created < '%s' and resource_type = '' order by created", intval(ITEM_TYPE_POST), intval($channel_id), dbesc($mindate), @@ -1033,9 +1068,9 @@ function identity_export_year($channel_id,$year,$month = 0) { if($r) { $ret['item'] = array(); xchan_query($r); - $r = fetch_post_tags($r,true); + $r = fetch_post_tags($r, true); foreach($r as $rr) - $ret['item'][] = encode_item($rr,true); + $ret['item'][] = encode_item($rr, true); } return $ret; @@ -1274,6 +1309,7 @@ function profile_edit_menu($uid) { foreach($r as $rr) { if(!($multi_profiles || $rr['is_default'])) continue; + $ret['menu']['entries'][] = array( 'photo' => $rr['thumb'], 'id' => $rr['id'], @@ -1298,8 +1334,8 @@ function profile_edit_menu($uid) { * * @param array $profile * @param int $block - * @param boolean $show_connect - * @param mixed $zcard + * @param boolean $show_connect (optional) default true + * @param mixed $zcard (optional) default false * * @return HTML string suitable for sidebar inclusion * Exceptions: Returns empty string if passed $profile is wrong type or not populated @@ -1327,6 +1363,10 @@ function profile_sidebar($profile, $block = 0, $show_connect = true, $zcard = fa $profile['picdate'] = urlencode($profile['picdate']); + /** + * @hooks profile_sidebar_enter + * Called before generating the 'channel sidebar' or mini-profile. + */ call_hooks('profile_sidebar_enter', $profile); if($show_connect) { @@ -1409,22 +1449,30 @@ function profile_sidebar($profile, $block = 0, $show_connect = true, $zcard = fa '$reddress' => $reddress, '$rating' => '', '$contact_block' => $contact_block, - '$editmenu' => profile_edit_menu($profile['uid']) + '$editmenu' => profile_edit_menu($profile['uid']) )); - $arr = array('profile' => $profile, 'entry' => $o); + $arr = [ + 'profile' => $profile, + 'entry' => $o + ]; + /** + * @hooks profile_sidebar + * Called when generating the 'channel sidebar' or mini-profile. + * * \e array \b profile + * * \e string \b entry - The parsed HTML template + */ call_hooks('profile_sidebar', $arr); return $arr['entry']; - } function gender_icon($gender) { // logger('gender: ' . $gender); - // This can easily get throw off if the observer language is different + // This can easily get throw off if the observer language is different // than the channel owner language. if(strpos(strtolower($gender),strtolower(t('Female'))) !== false) @@ -1622,16 +1670,21 @@ function get_my_address() { * If somebody arrives at our site using a zid, add their xchan to our DB if we * don't have it already. * And if they aren't already authenticated here, attempt reverse magic auth. - * - * @hooks zid_init - * * \e string \b zid - their zid - * * \e string \b url - the destination url */ function zid_init() { $tmp_str = get_my_address(); if(validate_email($tmp_str)) { - $arr = array('zid' => $tmp_str, 'url' => App::$cmd); - call_hooks('zid_init',$arr); + $arr = [ + 'zid' => $tmp_str, + 'url' => App::$cmd + ]; + /** + * @hooks zid_init + * * \e string \b zid - their zid + * * \e string \b url - the destination url + */ + call_hooks('zid_init', $arr); + if(! local_channel()) { $r = q("select * from hubloc where hubloc_addr = '%s' order by hubloc_connected desc limit 1", dbesc($tmp_str) @@ -1641,7 +1694,8 @@ function zid_init() { } if($r && remote_channel() && remote_channel() === $r[0]['hubloc_hash']) return; - logger('zid_init: not authenticated. Invoking reverse magic-auth for ' . $tmp_str); + + logger('Not authenticated. Invoking reverse magic-auth for ' . $tmp_str); // try to avoid recursion - but send them home to do a proper magic auth $query = App::$query_string; $query = str_replace(array('?zid=','&zid='),array('?rzid=','&rzid='),$query); @@ -1650,7 +1704,7 @@ function zid_init() { goaway($r[0]['hubloc_url'] . '/magic' . '?f=&rev=1&owa=1&dest=' . z_root() . $dest); } else - logger('zid_init: no hubloc found.'); + logger('No hubloc found.'); } } } @@ -1673,21 +1727,23 @@ function zat_init() { } - - -// Used from within PCSS themes to set theme parameters. If there's a -// puid request variable, that is the "page owner" and normally their theme -// settings take precedence; unless a local user sets the "always_my_theme" -// system pconfig, which means they don't want to see anybody else's theme -// settings except their own while on this site. - +/** + * @brief Used from within PCSS themes to set theme parameters. + * + * If there's a puid request variable, that is the "page owner" and normally + * their theme settings take precedence; unless a local user sets the "always_my_theme" + * system pconfig, which means they don't want to see anybody else's theme + * settings except their own while on this site. + * + * @return int + */ function get_theme_uid() { $uid = (($_REQUEST['puid']) ? intval($_REQUEST['puid']) : 0); if(local_channel()) { if((get_pconfig(local_channel(),'system','always_my_theme')) || (! $uid)) return local_channel(); } - if(! $uid) { + if(! $uierd) { $x = get_sys_channel(); if($x) return $x['channel_id']; @@ -1700,9 +1756,9 @@ function get_theme_uid() { * @brief Retrieves the path of the default_profile_photo for this system * with the specified size. * -* @param int $size -* one of (300, 80, 48) -* @returns string with path to profile photo +* @param int $size (optional) default 300 +* one of (300, 80, 48) +* @return string with path to profile photo */ function get_default_profile_photo($size = 300) { $scheme = get_config('system','default_profile_photo'); @@ -1715,9 +1771,9 @@ function get_default_profile_photo($size = 300) { /** * @brief Test whether a given identity is NOT a member of the Hubzilla. * - * @param string $s; + * @param string $s * xchan_hash of the identity in question - * @returns boolean true or false + * @return boolean true or false */ function is_foreigner($s) { return((strpbrk($s, '.:@')) ? true : false); @@ -1726,14 +1782,21 @@ function is_foreigner($s) { /** * @brief Test whether a given identity is a member of the Hubzilla. * - * @param string $s; + * @param string $s * xchan_hash of the identity in question - * @returns boolean true or false + * @return boolean true or false */ function is_member($s) { return((is_foreigner($s)) ? false : true); } +/** + * @brief Get chatpresence status for nick. + * + * @param string $nick + * @return array An associative array with + * * \e bool \b result + */ function get_online_status($nick) { $ret = array('result' => false); @@ -1748,6 +1811,7 @@ function get_online_status($nick) { $hide = get_pconfig($r[0]['channel_id'],'system','hide_online_status'); if($hide) return $ret; + $x = q("select cp_status from chatpresence where cp_xchan = '%s' and cp_room = 0 limit 1", dbesc($r[0]['channel_hash']) ); @@ -1759,6 +1823,12 @@ function get_online_status($nick) { } +/** + * @brief + * + * @param string $webbie + * @return array|boolean|string + */ function remote_online_status($webbie) { $result = false; @@ -1782,11 +1852,10 @@ function remote_online_status($webbie) { /** - * @brief + * @brief Return the parsed identity selector HTML template. * - * @return string + * @return string with parsed HTML channel_id_selet template */ - function identity_selector() { if(local_channel()) { $r = q("select channel.*, xchan.* from channel left join xchan on channel.channel_hash = xchan.xchan_hash where channel.channel_account_id = %d and channel_removed = 0 order by channel_name ", @@ -1798,6 +1867,7 @@ function identity_selector() { '$channels' => $r, '$selected' => local_channel() )); + return $o; } } @@ -1809,14 +1879,17 @@ function identity_selector() { function is_public_profile() { if(! local_channel()) return false; + if(intval(get_config('system','block_public'))) return false; + $channel = App::get_channel(); if($channel) { $perm = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_profile'); if($perm == PERMS_PUBLIC) return true; } + return false; } @@ -1861,7 +1934,7 @@ function get_profile_fields_advanced($filter = 0) { * * @param int $channel_id * The channel to disable notifications for - * @returns int + * @return int * Current notification flag value. Send this to notifications_on() to restore the channel settings when finished * with the activity requiring notifications_off(); */ @@ -1993,13 +2066,14 @@ function get_cover_photo($channel_id,$format = 'bbcode', $res = PHOTO_RES_COVER_ return $output; } + /** - * @brief + * @brief Return parsed HTML zcard template. * * @param array $channel - * @param string $observer_hash - * @param array $args - * @return string + * @param string $observer_hash (optional) + * @param array $args (optional) + * @return string parsed HTML from \e zcard template */ function get_zcard($channel, $observer_hash = '', $args = array()) { @@ -2067,6 +2141,14 @@ function get_zcard($channel, $observer_hash = '', $args = array()) { } +/** + * @brief Return parsed HTML embed zcard template. + * + * @param array $channel + * @param string $observer_hash (optional) + * @param array $args (optional) + * @return string parsed HTML from \e zcard_embed template + */ function get_zcard_embed($channel, $observer_hash = '', $args = array()) { logger('get_zcard_embed'); @@ -2133,10 +2215,12 @@ function get_zcard_embed($channel, $observer_hash = '', $args = array()) { } /** - * @brief + * @brief Get a channel array from a channel nickname. * - * @param string $nick - * @return mixed + * @param string $nick - A channel_address nickname + * @return array|boolean + * - array with channel entry + * - false if no channel with $nick was found */ function channelx_by_nick($nick) { $r = q("SELECT * FROM channel left join xchan on channel_hash = xchan_hash WHERE channel_address = '%s' and channel_removed = 0 LIMIT 1", @@ -2147,10 +2231,10 @@ function channelx_by_nick($nick) { } /** - * @brief + * @brief Get a channel array by a channel_hash. * * @param string $hash - * @return mixed + * @return array|boolean false if channel ID not found, otherwise the channel array */ function channelx_by_hash($hash) { $r = q("SELECT * FROM channel left join xchan on channel_hash = xchan_hash WHERE channel_hash = '%s' and channel_removed = 0 LIMIT 1", @@ -2161,13 +2245,13 @@ function channelx_by_hash($hash) { } /** - * @brief + * @brief Get a channel array by a channel ID. * - * @param int $id - * @return mixed + * @param int $id A channel ID + * @return array|boolean false if channel ID not found, otherwise the channel array */ function channelx_by_n($id) { - $r = q("SELECT * FROM channel left join xchan on channel_hash = xchan_hash WHERE channel_id = %d and channel_removed = 0 LIMIT 1", + $r = q("SELECT * FROM channel LEFT JOIN xchan ON channel_hash = xchan_hash WHERE channel_id = %d AND channel_removed = 0 LIMIT 1", dbesc($id) ); @@ -2177,7 +2261,7 @@ function channelx_by_n($id) { /** * @brief * - * @param string $channel + * @param array $channel * @return string */ function channel_reddress($channel) { @@ -2188,67 +2272,77 @@ function channel_reddress($channel) { } +/** + * @brief Get manual channel conversation update config. + * + * Check the channel config \e manual_conversation_update, if not set fall back + * to global system config, defaults to 1 if nothing set. + * + * @param int $channel_id + * @return int + */ function channel_manual_conv_update($channel_id) { - $x = get_pconfig($channel_id, 'system','manual_conversation_update'); + $x = get_pconfig($channel_id, 'system', 'manual_conversation_update'); if($x === false) - $x = get_config('system','manual_conversation_update', 1); + $x = get_config('system', 'manual_conversation_update', 1); return intval($x); } +/** + * @brief Return parsed HTML remote_login template. + * + * @return string with parsed HTML from \e remote_login template + */ function remote_login() { + $o = replace_macros(get_markup_template('remote_login.tpl'),array( + '$title' => t('Remote Authentication'), + '$desc' => t('Enter your channel address (e.g. channel@example.com)'), + '$submit' => t('Authenticate') + )); - $o = replace_macros(get_markup_template('remote_login.tpl'),array( - '$title' => t('Remote Authentication'), - '$desc' => t('Enter your channel address (e.g. channel@example.com)'), - '$submit' => t('Authenticate') - )); - return $o; - + return $o; } function channel_store_lowlevel($arr) { - $store = [ - 'channel_account_id' => ((array_key_exists('channel_account_id',$arr)) ? $arr['channel_account_id'] : '0'), - 'channel_primary' => ((array_key_exists('channel_primary',$arr)) ? $arr['channel_primary'] : '0'), - 'channel_name' => ((array_key_exists('channel_name',$arr)) ? $arr['channel_name'] : ''), - 'channel_address' => ((array_key_exists('channel_address',$arr)) ? $arr['channel_address'] : ''), - 'channel_guid' => ((array_key_exists('channel_guid',$arr)) ? $arr['channel_guid'] : ''), - 'channel_guid_sig' => ((array_key_exists('channel_guid_sig',$arr)) ? $arr['channel_guid_sig'] : ''), - 'channel_hash' => ((array_key_exists('channel_hash',$arr)) ? $arr['channel_hash'] : ''), - 'channel_timezone' => ((array_key_exists('channel_timezone',$arr)) ? $arr['channel_timezone'] : 'UTC'), - 'channel_location' => ((array_key_exists('channel_location',$arr)) ? $arr['channel_location'] : ''), - 'channel_theme' => ((array_key_exists('channel_theme',$arr)) ? $arr['channel_theme'] : ''), - 'channel_startpage' => ((array_key_exists('channel_startpage',$arr)) ? $arr['channel_startpage'] : ''), - 'channel_pubkey' => ((array_key_exists('channel_pubkey',$arr)) ? $arr['channel_pubkey'] : ''), - 'channel_prvkey' => ((array_key_exists('channel_prvkey',$arr)) ? $arr['channel_prvkey'] : ''), - 'channel_notifyflags' => ((array_key_exists('channel_notifyflags',$arr)) ? $arr['channel_notifyflags'] : '65535'), - 'channel_pageflags' => ((array_key_exists('channel_pageflags',$arr)) ? $arr['channel_pageflags'] : '0'), - 'channel_dirdate' => ((array_key_exists('channel_dirdate',$arr)) ? $arr['channel_dirdate'] : NULL_DATE), - 'channel_lastpost' => ((array_key_exists('channel_lastpost',$arr)) ? $arr['channel_lastpost'] : NULL_DATE), - 'channel_deleted' => ((array_key_exists('channel_deleted',$arr)) ? $arr['channel_deleted'] : NULL_DATE), - 'channel_max_anon_mail' => ((array_key_exists('channel_max_anon_mail',$arr)) ? $arr['channel_max_anon_mail'] : '10'), - 'channel_max_friend_req' => ((array_key_exists('channel_max_friend_req',$arr)) ? $arr['channel_max_friend_req'] : '10'), - 'channel_expire_days' => ((array_key_exists('channel_expire_days',$arr)) ? $arr['channel_expire_days'] : '0'), - 'channel_passwd_reset' => ((array_key_exists('channel_passwd_reset',$arr)) ? $arr['channel_passwd_reset'] : ''), - 'channel_default_group' => ((array_key_exists('channel_default_group',$arr)) ? $arr['channel_default_group'] : ''), - 'channel_allow_cid' => ((array_key_exists('channel_allow_cid',$arr)) ? $arr['channel_allow_cid'] : ''), - 'channel_allow_gid' => ((array_key_exists('channel_allow_gid',$arr)) ? $arr['channel_allow_gid'] : ''), - 'channel_deny_cid' => ((array_key_exists('channel_deny_cid',$arr)) ? $arr['channel_deny_cid'] : ''), - 'channel_deny_gid' => ((array_key_exists('channel_deny_gid',$arr)) ? $arr['channel_deny_gid'] : ''), - 'channel_removed' => ((array_key_exists('channel_removed',$arr)) ? $arr['channel_removed'] : '0'), - 'channel_system' => ((array_key_exists('channel_system',$arr)) ? $arr['channel_system'] : '0'), - + $store = [ + 'channel_account_id' => ((array_key_exists('channel_account_id',$arr)) ? $arr['channel_account_id'] : '0'), + 'channel_primary' => ((array_key_exists('channel_primary',$arr)) ? $arr['channel_primary'] : '0'), + 'channel_name' => ((array_key_exists('channel_name',$arr)) ? $arr['channel_name'] : ''), + 'channel_address' => ((array_key_exists('channel_address',$arr)) ? $arr['channel_address'] : ''), + 'channel_guid' => ((array_key_exists('channel_guid',$arr)) ? $arr['channel_guid'] : ''), + 'channel_guid_sig' => ((array_key_exists('channel_guid_sig',$arr)) ? $arr['channel_guid_sig'] : ''), + 'channel_hash' => ((array_key_exists('channel_hash',$arr)) ? $arr['channel_hash'] : ''), + 'channel_timezone' => ((array_key_exists('channel_timezone',$arr)) ? $arr['channel_timezone'] : 'UTC'), + 'channel_location' => ((array_key_exists('channel_location',$arr)) ? $arr['channel_location'] : ''), + 'channel_theme' => ((array_key_exists('channel_theme',$arr)) ? $arr['channel_theme'] : ''), + 'channel_startpage' => ((array_key_exists('channel_startpage',$arr)) ? $arr['channel_startpage'] : ''), + 'channel_pubkey' => ((array_key_exists('channel_pubkey',$arr)) ? $arr['channel_pubkey'] : ''), + 'channel_prvkey' => ((array_key_exists('channel_prvkey',$arr)) ? $arr['channel_prvkey'] : ''), + 'channel_notifyflags' => ((array_key_exists('channel_notifyflags',$arr)) ? $arr['channel_notifyflags'] : '65535'), + 'channel_pageflags' => ((array_key_exists('channel_pageflags',$arr)) ? $arr['channel_pageflags'] : '0'), + 'channel_dirdate' => ((array_key_exists('channel_dirdate',$arr)) ? $arr['channel_dirdate'] : NULL_DATE), + 'channel_lastpost' => ((array_key_exists('channel_lastpost',$arr)) ? $arr['channel_lastpost'] : NULL_DATE), + 'channel_deleted' => ((array_key_exists('channel_deleted',$arr)) ? $arr['channel_deleted'] : NULL_DATE), + 'channel_max_anon_mail' => ((array_key_exists('channel_max_anon_mail',$arr)) ? $arr['channel_max_anon_mail'] : '10'), + 'channel_max_friend_req' => ((array_key_exists('channel_max_friend_req',$arr)) ? $arr['channel_max_friend_req'] : '10'), + 'channel_expire_days' => ((array_key_exists('channel_expire_days',$arr)) ? $arr['channel_expire_days'] : '0'), + 'channel_passwd_reset' => ((array_key_exists('channel_passwd_reset',$arr)) ? $arr['channel_passwd_reset'] : ''), + 'channel_default_group' => ((array_key_exists('channel_default_group',$arr)) ? $arr['channel_default_group'] : ''), + 'channel_allow_cid' => ((array_key_exists('channel_allow_cid',$arr)) ? $arr['channel_allow_cid'] : ''), + 'channel_allow_gid' => ((array_key_exists('channel_allow_gid',$arr)) ? $arr['channel_allow_gid'] : ''), + 'channel_deny_cid' => ((array_key_exists('channel_deny_cid',$arr)) ? $arr['channel_deny_cid'] : ''), + 'channel_deny_gid' => ((array_key_exists('channel_deny_gid',$arr)) ? $arr['channel_deny_gid'] : ''), + 'channel_removed' => ((array_key_exists('channel_removed',$arr)) ? $arr['channel_removed'] : '0'), + 'channel_system' => ((array_key_exists('channel_system',$arr)) ? $arr['channel_system'] : '0'), 'channel_moved' => ((array_key_exists('channel_moved',$arr)) ? $arr['channel_moved'] : ''), 'channel_password' => ((array_key_exists('channel_password',$arr)) ? $arr['channel_password'] : ''), 'channel_salt' => ((array_key_exists('channel_salt',$arr)) ? $arr['channel_salt'] : '') - ]; - return create_table_from_array('channel',$store); - + return create_table_from_array('channel', $store); } function profile_store_lowlevel($arr) { @@ -2304,16 +2398,22 @@ function profile_store_lowlevel($arr) { } -// Included here for completeness, but this is a very dangerous operation. -// It is the caller's responsibility to confirm the requestor's intent and -// authorisation to do this. - -function account_remove($account_id,$local = true,$unset_session = true) { +/** + * Included here for completeness, but this is a very dangerous operation. + * It is the caller's responsibility to confirm the requestor's intent and + * authorisation to do this. + * + * @param int $account_id + * @param boolean $local (optional) default true + * @param boolean $unset_session (optional) default true + * @return boolean|array + */ +function account_remove($account_id, $local = true, $unset_session = true) { logger('account_remove: ' . $account_id); if(! intval($account_id)) { - logger('account_remove: no account.'); + logger('No account.'); return false; } @@ -2334,7 +2434,7 @@ function account_remove($account_id,$local = true,$unset_session = true) { $account_email=$r[0]['account_email']; if(! $r) { - logger('account_remove: No account with id: ' . $account_id); + logger('No account with id: ' . $account_id); return false; } @@ -2351,7 +2451,6 @@ function account_remove($account_id,$local = true,$unset_session = true) { intval($account_id) ); - if ($unset_session) { App::$session->nuke(); notice( sprintf(t('Account \'%s\' deleted'),$account_email) . EOL); @@ -2364,8 +2463,6 @@ function account_remove($account_id,$local = true,$unset_session = true) { /** * @brief Removes a channel. * - * @hooks channel_remove - * * \e array \b entry from channel tabel for $channel_id * @param int $channel_id * @param boolean $local default true * @param boolean $unset_session default false @@ -2386,6 +2483,11 @@ function channel_remove($channel_id, $local = true, $unset_session = false) { $channel = $r[0]; + /** + * @hooks channel_remove + * Called when removing a channel. + * * \e array with entry from channel tabel for $channel_id + */ call_hooks('channel_remove', $r[0]); if(! $local) { @@ -2457,6 +2559,7 @@ function channel_remove($channel_id, $local = true, $unset_session = false) { $rr = q("update account set account_default_channel = %d where account_id = %d", intval($r[0]['channel_id']), intval(App::$account['account_id'])); + logger("Default channel deleted, changing default to channel_id " . $r[0]['channel_id']); } else { @@ -2531,20 +2634,30 @@ function channel_codeallowed($channel_id) { return true; return false; - } function anon_identity_init($reqvars) { - $x = [ 'request_vars' => $reqvars, 'xchan' => null, 'success' => 'unset' ]; - call_hooks('anon_identity_init',$x); + $x = [ + 'request_vars' => $reqvars, + 'xchan' => null, + 'success' => 'unset' + ]; + /** + * @hooks anon_identity_init + * * \e array \b request_vars + * * \e string \b xchan - return value + * * \e string|int \b success - Must be a number, so xchan return value gets used + */ + call_hooks('anon_identity_init', $x); + if($x['success'] !== 'unset' && intval($x['success']) && $x['xchan']) return $x['xchan']; - // allow a captcha handler to over-ride + // allow a captcha handler to over-ride if($x['success'] !== 'unset' && (intval($x['success']) === 0)) - return false; - + return false; + $anon_name = strip_tags(trim($reqvars['anonname'])); $anon_email = strip_tags(trim($reqvars['anonmail'])); @@ -2571,7 +2684,7 @@ function anon_identity_init($reqvars) { ); if(! $x) { - xchan_store_lowlevel([ + xchan_store_lowlevel([ 'xchan_guid' => $anon_email, 'xchan_hash' => $hash, 'xchan_name' => $anon_name, @@ -2579,7 +2692,7 @@ function anon_identity_init($reqvars) { 'xchan_network' => 'unknown', 'xchan_name_date' => datetime_convert() ]); - + $x = q("select * from xchan where xchan_guid = '%s' and xchan_hash = '%s' and xchan_network = 'unknown' limit 1", dbesc($anon_email), @@ -2597,13 +2710,18 @@ function anon_identity_init($reqvars) { dbesc($anon_email), dbesc($hash) ); - } return $x[0]; } +/** + * @brief Create a channel array from proxy channel (pchan). + * + * @param array $pchan The proxy channel + * @return array channel array + */ function pchan_to_chan($pchan) { $chan = $pchan; $chan['channel_address'] = $pchan['pchan_guid']; @@ -2611,5 +2729,7 @@ function pchan_to_chan($pchan) { $chan['channel_pubkey'] = $pchan['pchan_pubkey']; $chan['channel_prvkey'] = $pchan['pchan_prvkey']; $chan['channel_name'] = $pchan['xchan_name']; + return $chan; -} \ No newline at end of file +} + diff --git a/include/datetime.php b/include/datetime.php index 85e87848b..0fcd957be 100644 --- a/include/datetime.php +++ b/include/datetime.php @@ -8,6 +8,8 @@ /** * @brief Two-level sort for timezones. * + * Can be used in usort() to sort timezones. + * * @param string $a * @param string $b * @return number @@ -27,13 +29,14 @@ function timezone_cmp($a, $b) { function is_null_date($s) { if($s === '0000-00-00 00:00:00' || $s === '0001-01-01 00:00:00') return true; + return false; } - /** * @brief Return timezones grouped (primarily) by continent. * + * @see timezone_cmp() * @return array */ function get_timezones( ){ @@ -54,7 +57,7 @@ function get_timezones( ){ $city = $ex[0]; $continent = t('Miscellaneous'); } - $city = str_replace('_', ' ', t($city)); + $city = str_replace('_', ' ', t($city)); if (!x($continents, $ex[0])) $continents[$ex[0]] = array(); $continents[$continent][$value] = $city; @@ -109,7 +112,7 @@ function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d try { $d = new DateTime($s, $from_obj); } catch(Exception $e) { - logger('datetime_convert: exception: ' . $e->getMessage()); + logger('exception: ' . $e->getMessage()); $d = new DateTime('now', $from_obj); } @@ -128,7 +131,7 @@ function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d * @brief Wrapper for date selector, tailored for use in birthday fields. * * @param string $dob Date of Birth - * @return string + * @return string Parsed HTML with selector */ function dob($dob) { @@ -161,59 +164,62 @@ function dob($dob) { } /** - * returns a date selector - * @param $format - * format string, e.g. 'ymd' or 'mdy'. Not currently supported - * @param $min - * unix timestamp of minimum date - * @param $max - * unix timestap of maximum date - * @param $default - * unix timestamp of default date - * @param $id - * id and name of datetimepicker (defaults to "datetimepicker") + * @brief Returns a date selector. + * + * @see datetimesel() + * @param string $format + * format string, e.g. 'ymd' or 'mdy'. Not currently supported + * @param DateTime $min + * unix timestamp of minimum date + * @param DateTime $max + * unix timestap of maximum date + * @param DateTime $default + * unix timestamp of default date + * @param string $id + * id and name of datetimepicker (defaults to "datetimepicker") */ function datesel($format, $min, $max, $default, $id = 'datepicker') { - return datetimesel($format, $min, $max, $default, '', $id,true, false, '', ''); + return datetimesel($format, $min, $max, $default, '', $id, true, false, '', ''); } /** - * returns a time selector - * @param $format - * format string, e.g. 'ymd' or 'mdy'. Not currently supported - * @param $h - * already selected hour - * @param $m + * @brief Returns a time selector. + * + * @param string $format + * format string, e.g. 'ymd' or 'mdy'. Not currently supported + * @param string $h + * already selected hour + * @param string $m * already selected minute - * @param $id + * @param string $id * id and name of datetimepicker (defaults to "timepicker") */ function timesel($format, $h, $m, $id='timepicker') { - return datetimesel($format,new DateTime(),new DateTime(),new DateTime("$h:$m"),'', $id,false,true); + return datetimesel($format, new DateTime(), new DateTime(), new DateTime("$h:$m"), '', $id, false, true); } /** * @brief Returns a datetime selector. * * @param string $format - * format string, e.g. 'ymd' or 'mdy'. Not currently supported - * @param $min - * unix timestamp of minimum date - * @param $max - * unix timestap of maximum date - * @param $default - * unix timestamp of default date + * format string, e.g. 'ymd' or 'mdy'. Not currently supported + * @param DateTime $min + * unix timestamp of minimum date + * @param DateTime $max + * unix timestap of maximum date + * @param DateTime $default + * unix timestamp of default date * @param string $label * @param string $id - * id and name of datetimepicker (defaults to "datetimepicker") + * id and name of datetimepicker (defaults to "datetimepicker") * @param boolean $pickdate - * true to show date picker (default) + * true to show date picker (default) * @param boolean $picktime - * true to show time picker (default) - * @param $minfrom - * set minimum date from picker with id $minfrom (none by default) - * @param $maxfrom - * set maximum date from picker with id $maxfrom (none by default) + * true to show time picker (default) + * @param DateTime $minfrom + * set minimum date from picker with id $minfrom (none by default) + * @param DateTime $maxfrom + * set maximum date from picker with id $maxfrom (none by default) * @param boolean $required default false * @param int $first_day (optional) default 0 * @return string Parsed HTML output. @@ -343,9 +349,6 @@ function plural_dates($k,$n) { } } - - - /** * @brief Returns timezone correct age in years. * @@ -418,7 +421,7 @@ function get_dim($y, $m) { * * @param int $y Year * @param int $m Month (1=January, 12=December) - * @return day 0 = Sunday through 6 = Saturday + * @return string day 0 = Sunday through 6 = Saturday */ function get_first_dim($y, $m) { $d = sprintf('%04d-%02d-01 00:00', intval($y), intval($m)); diff --git a/include/event.php b/include/event.php index b56a5fb3e..282c1a9d7 100644 --- a/include/event.php +++ b/include/event.php @@ -1,15 +1,16 @@ ' . "\r\n"; @@ -29,27 +30,27 @@ function format_event_html($ev) { $o .= '
' . t('Starts:') . ' ' - . (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(), + . '" >' + . (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(), $ev['dtstart'] , $bd_format )) - : day_translate(datetime_convert('UTC', 'UTC', + : day_translate(datetime_convert('UTC', 'UTC', $ev['dtstart'] , $bd_format))) . '
' . "\r\n"; if(! $ev['nofinish']) $o .= '
' . t('Finishes:') . ' ' - . (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(), + . '" >' + . (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(), $ev['dtend'] , $bd_format )) - : day_translate(datetime_convert('UTC', 'UTC', + : day_translate(datetime_convert('UTC', 'UTC', $ev['dtend'] , $bd_format ))) . '
' . "\r\n"; $o .= '
' . zidify_links(smilies(bbcode($ev['description']))) . '
' . "\r\n"; if(strlen($ev['location'])) - $o .= '
' . t('Location:') . ' ' + $o .= '
' . t('Location:') . ' ' . zidify_links(smilies(bbcode($ev['location']))) . '
' . "\r\n"; @@ -123,9 +124,9 @@ function format_event_ical($ev) { $o .= "\r\nCREATED:" . datetime_convert('UTC','UTC', $ev['created'],'Ymd\\THis\\Z'); $o .= "\r\nLAST-MODIFIED:" . datetime_convert('UTC','UTC', $ev['edited'],'Ymd\\THis\\Z'); $o .= "\r\nDTSTAMP:" . datetime_convert('UTC','UTC', $ev['edited'],'Ymd\\THis\\Z'); - if($ev['dtstart']) + if($ev['dtstart']) $o .= "\r\nDTSTART:" . datetime_convert('UTC','UTC', $ev['dtstart'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : '')); - if($ev['dtend'] && ! $ev['nofinish']) + if($ev['dtend'] && ! $ev['nofinish']) $o .= "\r\nDTEND:" . datetime_convert('UTC','UTC', $ev['dtend'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : '')); if($ev['summary']) { $o .= "\r\nSUMMARY:" . format_ical_text($ev['summary']); @@ -143,7 +144,7 @@ function format_event_ical($ev) { $o .= "\r\nPRIORITY:" . intval($ev['event_priority']); $o .= "\r\nUID:" . $ev['event_hash'] ; $o .= "\r\nEND:VEVENT\r\n"; - + return $o; } @@ -156,9 +157,9 @@ function format_todo_ical($ev) { $o .= "\r\nCREATED:" . datetime_convert('UTC','UTC', $ev['created'],'Ymd\\THis\\Z'); $o .= "\r\nLAST-MODIFIED:" . datetime_convert('UTC','UTC', $ev['edited'],'Ymd\\THis\\Z'); $o .= "\r\nDTSTAMP:" . datetime_convert('UTC','UTC', $ev['edited'],'Ymd\\THis\\Z'); - if($ev['dtstart']) + if($ev['dtstart']) $o .= "\r\nDTSTART:" . datetime_convert('UTC','UTC', $ev['dtstart'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : '')); - if($ev['dtend'] && ! $ev['nofinish']) + if($ev['dtend'] && ! $ev['nofinish']) $o .= "\r\nDUE:" . datetime_convert('UTC','UTC', $ev['dtend'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : '')); if($ev['summary']) { $o .= "\r\nSUMMARY:" . format_ical_text($ev['summary']); @@ -170,8 +171,8 @@ function format_todo_ical($ev) { $o .= "\r\nCOMPLETED:" . datetime_convert('UTC','UTC', $ev['event_status_date'],'Ymd\\THis\\Z'); } if(intval($ev['event_percent'])) - $o .= "\r\nPERCENT-COMPLETE:" . $ev['event_percent']; - if(intval($ev['event_sequence'])) + $o .= "\r\nPERCENT-COMPLETE:" . $ev['event_percent']; + if(intval($ev['event_sequence'])) $o .= "\r\nSEQUENCE:" . $ev['event_sequence']; if($ev['location']) { $o .= "\r\nLOCATION:" . format_ical_text($ev['location']); @@ -196,12 +197,13 @@ function format_ical_text($s) { $s = html2plain(bbcode($s)); $s = str_replace(["\r\n","\n"],["",""],$s); - return(wordwrap(str_replace(['\\',',',';'],['\\\\','\\,','\\;'],$s),72,"\r\n ",true)); + return(wordwrap(str_replace(['\\',',',';'],['\\\\','\\,','\\;'],$s),72,"\r\n ",true)); } function format_ical_sourcetext($s) { $s = base64_encode($s); + return(wordwrap(str_replace(['\\',',',';'],['\\\\','\\,','\\;'],$s),72,"\r\n ",true)); } @@ -225,7 +227,7 @@ function format_event_bbcode($ev) { if(($ev['dtend']) && (! $ev['nofinish'])) $o .= '[event-finish]' . $ev['dtend'] . '[/event-finish]'; - + if($ev['location']) $o .= '[event-location]' . $ev['location'] . '[/event-location]'; @@ -253,7 +255,6 @@ function bbtoevent($s) { $ev = array(); - $match = ''; if(preg_match("/\[event\](.*?)\[\/event\]/is",$s,$match)) { // only parse one object per event tag @@ -306,7 +307,7 @@ function bbtoevent($s) { * * @see ev_compare() * @param array $arr - * @return sorted array + * @return array Date sorted array of events */ function sort_by_date($arr) { if (is_array($arr)) @@ -318,6 +319,8 @@ function sort_by_date($arr) { /** * @brief Compare function for events. * + * This function can be used in usort() to sort events by date. + * * @see sort_by_date() * @param array $a * @param array $b @@ -375,8 +378,19 @@ function event_store_event($arr) { } } - $hook_info = [ 'event' => $arr, 'existing_event' => $existing_event, 'cancel' => false ]; - call_hooks('event_store_event',$hook_info); + $hook_info = [ + 'event' => $arr, + 'existing_event' => $existing_event, + 'cancel' => false + ]; + /** + * @hooks event_store_event + * Called when an event record is created or updated. + * * \e array \b event + * * \e array \b existing_event + * * \e boolean \b cancel - default false + */ + call_hooks('event_store_event', $hook_info); if($hook_info['cancel']) return false; @@ -386,7 +400,7 @@ function event_store_event($arr) { if($existing_event) { if($existing_event['edited'] >= $arr['edited']) { - // Nothing has changed. + // Nothing has changed. return $existing_event; } @@ -444,7 +458,6 @@ function event_store_event($arr) { // New event. Store it. - if(array_key_exists('external_id',$arr)) $hash = $arr['external_id']; elseif(array_key_exists('event_hash',$arr)) @@ -531,7 +544,7 @@ function event_addtocal($item_id, $uid) { } if($ev->private) - $ev['allow_cid'] = '<' . $channel['channel_hash'] . '>'; + $ev['allow_cid'] = '<' . $channel['channel_hash'] . '>'; else { $acl = new Zotlabs\Access\AccessList($channel); $x = $acl->get(); @@ -596,14 +609,12 @@ function ical_to_ev($s) { date_default_timezone_set($saved_timezone); return $ev; - } function parse_vobject($ical, $type) { - $ev = []; if(! isset($ical->DTSTART)) { @@ -698,10 +709,8 @@ function parse_vobject($ical, $type) { - - function parse_ical_file($f,$uid) { -require_once('vendor/autoload.php'); + require_once('vendor/autoload.php'); $s = @file_get_contents($f); @@ -731,6 +740,7 @@ require_once('vendor/autoload.php'); if($ical) return true; + return false; } @@ -779,7 +789,6 @@ function event_import_ical($ical, $uid) { $ev['created'] = datetime_convert('UTC','UTC',$created->format(\DateTime::W3C)); } - if(isset($ical->{'LAST-MODIFIED'})) { $edited = $ical->{'LAST-MODIFIED'}->getDateTime(); $ev['edited'] = datetime_convert('UTC','UTC',$edited->format(\DateTime::W3C)); @@ -814,7 +823,7 @@ function event_import_ical($ical, $uid) { else $ev['external_id'] = $evuid; } - + if($ev['summary'] && $ev['dtstart']) { $ev['event_xchan'] = $channel['channel_hash']; $ev['uid'] = $channel['channel_id']; @@ -822,7 +831,7 @@ function event_import_ical($ical, $uid) { $ev['private'] = 1; $ev['allow_cid'] = '<' . $channel['channel_hash'] . '>'; - logger('storing event: ' . print_r($ev,true), LOGGER_ALL); + logger('storing event: ' . print_r($ev,true), LOGGER_ALL); $event = event_store_event($ev); if($event) { $item_id = event_store_item($ev,$event); @@ -831,7 +840,6 @@ function event_import_ical($ical, $uid) { } return false; - } function event_ical_get_sourcetext($s) { @@ -931,7 +939,7 @@ function event_import_ical_task($ical, $uid) { if(isset($ical->SEQUENCE)) { $ev['event_sequence'] = (string) $ical->SEQUENCE; // see if our stored event is more current than the one we're importing - if((intval($ev['event_sequence']) <= intval($stored_event['event_sequence'])) + if((intval($ev['event_sequence']) <= intval($stored_event['event_sequence'])) && ($ev['edited'] <= $stored_event['edited'])) return false; } @@ -958,7 +966,7 @@ function event_import_ical_task($ical, $uid) { $ev['private'] = 1; $ev['allow_cid'] = '<' . $channel['channel_hash'] . '>'; - logger('storing event: ' . print_r($ev,true), LOGGER_ALL); + logger('storing event: ' . print_r($ev,true), LOGGER_ALL); $event = event_store_event($ev); if($event) { $item_id = event_store_item($ev,$event); @@ -967,14 +975,10 @@ function event_import_ical_task($ical, $uid) { } return false; - } - - - function event_store_item($arr, $event) { require_once('include/datetime.php'); @@ -995,7 +999,6 @@ function event_store_item($arr, $event) { } - $item_arr = array(); $prefix = ''; // $birthday = false; @@ -1008,9 +1011,9 @@ function event_store_item($arr, $event) { $prefix = t('This event has been added to your calendar.'); // $birthday = true; - // The event is created on your own site by the system, but appears to belong + // The event is created on your own site by the system, but appears to belong // to the birthday person. It also isn't propagated - so we need to prevent - // folks from trying to comment on it. If you're looking at this and trying to + // folks from trying to comment on it. If you're looking at this and trying to // fix it, you'll need to completely change the way birthday events are created // and send them out from the source. This has its own issues. @@ -1048,9 +1051,10 @@ function event_store_item($arr, $event) { $private = (($arr['allow_cid'] || $arr['allow_gid'] || $arr['deny_cid'] || $arr['deny_gid']) ? 1 : 0); - // @FIXME can only update sig if we have the author's channel on this site - // Until fixed, set it to nothing so it won't give us signature errors - + /** + * @FIXME can only update sig if we have the author's channel on this site + * Until fixed, set it to nothing so it won't give us signature errors. + */ $sig = ''; q("UPDATE item SET title = '%s', body = '%s', obj = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', edited = '%s', sig = '%s', item_flags = %d, item_private = %d, obj_type = '%s' WHERE id = %d AND uid = %d", @@ -1090,6 +1094,10 @@ function event_store_item($arr, $event) { } $item_id = $r[0]['id']; + /** + * @hooks event_updated + * Called when an event record is modified. + */ call_hooks('event_updated', $event['id']); return $item_id; @@ -1103,7 +1111,7 @@ function event_store_item($arr, $event) { $item_wall = 0; $item_origin = 0; - $item_thread_top = 0; + $item_thread_top = 0; if($item) { $item_arr['id'] = $item['id']; @@ -1196,6 +1204,10 @@ function event_store_item($arr, $event) { $item_id = $res['item_id']; + /** + * @hooks event_created + * Called when an event record is created. + */ call_hooks('event_created', $event['id']); return $item_id; @@ -1216,25 +1228,24 @@ function todo_stat() { function tasks_fetch($arr) { - if(! local_channel()) - return; + if(! local_channel()) + return; - $ret = array(); - $sql_extra = " and event_status != 'COMPLETED' "; - if($arr && $arr['all'] == 1) - $sql_extra = ''; + $ret = array(); + $sql_extra = " and event_status != 'COMPLETED' "; + if($arr && $arr['all'] == 1) + $sql_extra = ''; - $r = q("select * from event where etype = 'task' and uid = %d $sql_extra order by created desc", - intval(local_channel()) - ); + $r = q("select * from event where etype = 'task' and uid = %d $sql_extra order by created desc", + intval(local_channel()) + ); - $ret['success'] = (($r) ? true : false); - if($r) { - $ret['tasks'] = $r; - } + $ret['success'] = (($r) ? true : false); + if($r) { + $ret['tasks'] = $r; + } return $ret; - } function cdav_principal($uri) { diff --git a/include/feedutils.php b/include/feedutils.php index 217da8188..1284c45a3 100644 --- a/include/feedutils.php +++ b/include/feedutils.php @@ -1,5 +1,8 @@ $atom, 'channel' => $channel, 'observer_hash' => $observer_hash, 'params' => $params ]; - call_hooks('atom_feed_top',$x); + $x = [ + 'xml' => $atom, + 'channel' => $channel, + 'observer_hash' => $observer_hash, + 'params' => $params + ]; + /** + * @hooks atom_feed_top + * * \e string \b xml - the generated feed and what will get returned from the hook + * * \e array \b channel + * * \e string \b observer_hash + * * \e array \b params + */ + call_hooks('atom_feed_top', $x); $atom = $x['xml']; - // a much simpler interface + /** + * @hooks atom_feed + * A much simpler interface than atom_feed_top. + * * \e string - the feed after atom_feed_top hook + */ call_hooks('atom_feed', $atom); $items = items_fetch( @@ -135,11 +153,14 @@ function get_feed_for($channel, $observer_hash, $params) { if($item['item_private']) continue; - /** @BUG $owner is undefined in this call */ $atom .= atom_entry($item, $type, null, $owner, true, '', $params['compat']); } } + /** + * @hooks atom_feed_end + * \e string - The created XML feed as a string without closing tag + */ call_hooks('atom_feed_end', $atom); $atom .= '' . "\r\n"; @@ -344,6 +365,7 @@ function get_atom_elements($feed, $item, &$author) { } } + // check for a yahoo media element (github etc.) if(! $author['author_photo']) { @@ -356,7 +378,6 @@ function get_atom_elements($feed, $item, &$author) { // No photo/profile-link on the item - look at the feed level - if((! (x($author,'author_link'))) || (! (x($author,'author_photo')))) { $rawauthor = $feed->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author'); if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) { @@ -396,7 +417,7 @@ function get_atom_elements($feed, $item, &$author) { // new style $ostatus_conversation = normalise_id(unxmlify($rawcnv[0]['attribs']['']['ref'])); if(! $ostatus_conversation) { - // old style + // old style $ostatus_conversation = normalise_id(unxmlify($rawcnv[0]['data'])); } if($ostatus_conversation) { @@ -406,7 +427,7 @@ function get_atom_elements($feed, $item, &$author) { } $ostatus_protocol = (($ostatus_conversation) ? true : false); - + $mastodon = (($item->get_item_tags('http://mastodon.social/schema/1.0','scope')) ? true : false); if($mastodon) { $ostatus_protocol = true; @@ -645,7 +666,7 @@ function get_atom_elements($feed, $item, &$author) { $res['attach'][] = array('href' => $link, 'length' => $len, 'type' => $type, 'title' => $title ); } } - + $rawobj = $item->get_item_tags(NAMESPACE_ACTIVITY, 'object'); @@ -723,7 +744,6 @@ function get_atom_elements($feed, $item, &$author) { $res['target'] = $obj; } - if(array_key_exists('verb',$res) && $res['verb'] === ACTIVITY_SHARE && array_key_exists('obj_type',$res) && in_array($res['obj_type'], [ ACTIVITY_OBJ_NOTE, ACTIVITY_OBJ_COMMENT, ACTIVITY_OBJ_ACTIVITY ] )) { @@ -737,7 +757,13 @@ function get_atom_elements($feed, $item, &$author) { 'author' => $author, 'result' => $res ]; - + /** + * @hooks parse_atom + * * \e SimplePie \b feed - The original SimplePie feed + * * \e array \b item + * * \e array \b author + * * \e array \b result - the result array that will also get returned + */ call_hooks('parse_atom', $arr); logger('author: ' .print_r($arr['author'], true), LOGGER_DATA); @@ -782,7 +808,7 @@ function feed_get_reshare(&$res,$item) { $share['avatar'] = z_root() . '/' . get_default_profile_photo(80); if(! $share['profile']) $share['profile'] = z_root(); - + $child = $rawobj[0]['child']; @@ -809,7 +835,7 @@ function feed_get_reshare(&$res,$item) { $body = html2bbcode($body); } } - + $attach = $share['links']; if($attach) { @@ -845,16 +871,16 @@ function feed_get_reshare(&$res,$item) { } } } - + if((! $body) && ($share['alternate'])) { $body = $share['alternate']; - } + } - $res['body'] = "[share author='" . urlencode($share['author']) . + $res['body'] = "[share author='" . urlencode($share['author']) . "' profile='" . $share['profile'] . "' avatar='" . $share['avatar'] . "' link='" . $share['alternate'] . - "' posted='" . $share['created'] . + "' posted='" . $share['created'] . "' message_id='" . $share['message_id'] . "']"; $res['body'] .= $body; @@ -864,7 +890,6 @@ function feed_get_reshare(&$res,$item) { } - /** * @brief Encodes SimplePie_Item link arrays. * @@ -940,7 +965,7 @@ function process_feed_tombstones($feed,$importer,$contact,$pass) { * * @param string $xml * The (atom) feed to consume - RSS isn't as fully supported but may work for simple feeds. - * @param $importer + * @param array $importer * The contact_record (joined to user_record) of the local user who owns this * relationship. It is this person's stuff that is going to be updated. * @param[in,out] array $contact @@ -1103,7 +1128,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { // Update content if 'updated' changes if($r) { - if(activity_match($datarray['verb'],ACTIVITY_DELETE) + if(activity_match($datarray['verb'],ACTIVITY_DELETE) && $datarray['author_xchan'] === $r[0]['author_xchan']) { if(! intval($r[0]['item_deleted'])) { logger('deleting item ' . $r[0]['id'] . ' mid=' . $datarray['mid'], LOGGER_DEBUG); @@ -1147,6 +1172,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { $datarray['parent_mid'] = $pmid; } } + if(($item_parent_mid) && (! $pmid)) { logger('find_parent: matched in-reply-to: ' . $parent_mid, LOGGER_DEBUG); $pmid = $item_parent_mid[0]['parent_mid']; @@ -1172,7 +1198,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { dbesc($parent_mid), intval($importer['channel_id']) ); - + if($x) { $item_parent_mid = $x; $pmid = $x[0]['parent_mid']; @@ -1205,7 +1231,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { ); if($r) { $parent_item = $r[0]; - if(intval($parent_item['item_nocomment']) || $parent_item['comment_policy'] === 'none' + if(intval($parent_item['item_nocomment']) || $parent_item['comment_policy'] === 'none' || ($parent_item['comments_closed'] > NULL_DATE && $parent_item['comments_closed'] < datetime_convert())) { logger('comments disabled for post ' . $parent_item['mid']); continue; @@ -1215,7 +1241,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { $allowed = false; if($parent_item) { - if($parent_item['owner_xchan'] == $importer['channel_hash']) + if($parent_item['owner_xchan'] == $importer['channel_hash']) $allowed = perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'post_comments'); else $allowed = true; @@ -1230,16 +1256,17 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { // interactive feeds (such as OStatus) downstream to our followers // We do not want to set it for non-interactive feeds or conversations we do not own - if(array_key_exists('send_downstream',$importer) && intval($importer['send_downstream']) + if(array_key_exists('send_downstream',$importer) && intval($importer['send_downstream']) && ($parent_item['owner_xchan'] == $importer['channel_hash'])) { $send_downstream = true; } } else { if((! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'send_stream')) && (! $importer['system'])) { - // @fixme check for and process ostatus autofriend - // otherwise - + /** + * @fixme check for and process ostatus autofriend + * otherwise ignore this author. + */ logger('Ignoring this author.'); continue; } @@ -1249,13 +1276,13 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { // immediate parent wasn't found. Turn into a top-level post if permissions allow // but save the thread_parent in case we need to refer to it later. - + if(! post_is_importable($datarray, $contact)) continue; + $datarray['parent_mid'] = $datarray['mid']; set_iconfig($datarray,'system','parent_mid',$parent_mid,true); } - // allow likes of comments @@ -1306,7 +1333,6 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { } - // if we have everything but a photo, provide the default profile photo if($author['author_name'] && $author['author_link'] && (! $author['author_photo'])) @@ -1364,7 +1390,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { // Update content if 'updated' changes if($r) { - if(activity_match($datarray['verb'],ACTIVITY_DELETE) + if(activity_match($datarray['verb'],ACTIVITY_DELETE) && $datarray['author_xchan'] === $r[0]['author_xchan']) { if(! intval($r[0]['item_deleted'])) { logger('deleting item ' . $r[0]['id'] . ' mid=' . $datarray['mid'], LOGGER_DEBUG); @@ -1426,12 +1452,12 @@ function feed_conversation_fetch($importer,$contact,$parent_link) { // GNU-Social flavoured feeds if(strpos($parent_link,'/notice/')) { $link = str_replace('/notice/','/api/statuses/show/',$parent_link) . '.atom'; - } + } // Mastodon flavoured feeds if(strpos($parent_link,'/users/') && strpos($parent_link,'/updates/')) { $link = $parent_link . '.atom'; - } + } if(! $link) return false; @@ -1446,21 +1472,21 @@ function feed_conversation_fetch($importer,$contact,$parent_link) { $data = $fetch['body']; // We will probably receive an atom 'entry' and not an atom 'feed'. Unfortunately - // our parser is a bit strict about compliance so we'll insert just enough of a feed - // tag to trick it into believing it's a compliant feed. + // our parser is a bit strict about compliance so we'll insert just enough of a feed + // tag to trick it into believing it's a compliant feed. if(! strstr($data,'' . "\r\n"; $o .= ' ' . $name . '' . "\r\n"; + /** + * @hooks atom_author + * Possibility to add further tags to returned XML string + * * \e string - The created XML tag as a string without closing tag + */ call_hooks('atom_author', $o); $o .= "\r\n"; @@ -1703,9 +1735,15 @@ function atom_author($tag, $nick, $name, $uri, $h, $w, $type, $photo) { } -function atom_render_author($tag,$xchan) { +/** + * @brief + * + * @param string $tag + * @param array $xchan + * @return string An xml tag + */ +function atom_render_author($tag, $xchan) { - $nick = xmlify(substr($xchan['xchan_addr'],0,strpos($xchan['xchan_addr'],'@'))); $id = xmlify($xchan['xchan_url']); $name = xmlify($xchan['xchan_name']); @@ -1724,13 +1762,15 @@ function atom_render_author($tag,$xchan) { $o .= ' ' . $nick . '' . "\r\n"; $o .= ' ' . $name . '' . "\r\n"; + /** + * @hooks atom_render_author + * * \e string - The created XML tag as a string without closing tag + */ call_hooks('atom_render_author', $o); $o .= "\r\n"; return $o; - - } function compat_photos_list($s) { @@ -1740,7 +1780,7 @@ function compat_photos_list($s) { $found = preg_match_all('/\[[zi]mg(.*?)\](.*?)\[/ism',$s,$matches,PREG_SET_ORDER); if($found) { - foreach($matches as $match) { + foreach($matches as $match) { $ret[] = [ 'href' => $match[2], 'length' => 0, @@ -1754,7 +1794,6 @@ function compat_photos_list($s) { } - /** * @brief Create an item for the Atom feed. * @@ -1766,11 +1805,11 @@ function compat_photos_list($s) { * @param array $owner * @param string $comment default false * @param number $cid default 0 + * @param boolean $compat default false * @return void|string */ function atom_entry($item, $type, $author, $owner, $comment = false, $cid = 0, $compat = false) { - if(! $item['parent']) return; @@ -1922,9 +1961,17 @@ function atom_entry($item, $type, $author, $owner, $comment = false, $cid = 0, $ 'abook_id' => $cid, 'entry' => $o ]; - + /** + * @hooks atom_entry + * * \e array \b item + * * \e string \b type + * * \e array \b author + * * \e array \b owner + * * \e string \b comment + * * \e number \b abook_id + * * \e string \b entry - The generated entry and what will get returned + */ call_hooks('atom_entry', $x); return $x['entry']; } - diff --git a/include/items.php b/include/items.php index 08e53553b..3934f6194 100755 --- a/include/items.php +++ b/include/items.php @@ -1,6 +1,7 @@ $observer_xchan, 'item' => $item, 'allowed' => 'unset' ]; - call_hooks('can_comment_on_post',$x); +// logger('Comment_policy: ' . $item['comment_policy'], LOGGER_DEBUG); + + $x = [ + 'observer_hash' => $observer_xchan, + 'item' => $item, + ]; + /** + * @hooks can_comment_on_post + * Called when deciding whether or not to present a comment box for a post. + * * \e string \b observer_hash + * * \e array \b item + * * \e boolean \b allowed - return value + */ + call_hooks('can_comment_on_post', $x); if($x['allowed'] !== 'unset') return $x['allowed']; @@ -386,10 +397,14 @@ function post_activity_item($arr, $allow_code = false, $deliver = true) { $_REQUEST['api_source'] = 1; - call_hooks('post_local',$arr); + /** + * @hooks post_local + * Called when an item has been posted on this machine via mod/item.php (also via API). + */ + call_hooks('post_local', $arr); - if(x($arr,'cancel')) { - logger('post_activity_item: post cancelled by plugin.'); + if(x($arr, 'cancel')) { + logger('Post cancelled by plugin.'); return $ret; } @@ -400,6 +415,12 @@ function post_activity_item($arr, $allow_code = false, $deliver = true) { $ret['success'] = true; $ret['item_id'] = $post_id; $ret['activity'] = $post['item']; + + /** + * @hooks post_local_end + * Called after a local post operation has completed. + * * \e array - the item returned from item_store() + */ call_hooks('post_local_end', $ret['activity']); } @@ -407,8 +428,8 @@ function post_activity_item($arr, $allow_code = false, $deliver = true) { Zotlabs\Daemon\Master::Summon(array('Notifier','activity',$post_id)); } - $ret['success'] = true; + return $ret; } @@ -430,7 +451,6 @@ function validate_item_elements($message,$arr) { $result['success'] = true; return $result; - } @@ -469,7 +489,7 @@ function limit_body_size($body) { if( ($textlen + $img_start) > $maxlen ) { if($textlen < $maxlen) { - logger('limit_body_size: the limit happens before an embedded image', LOGGER_DEBUG); + logger('The limit happens before an embedded image', LOGGER_DEBUG); $new_body = $new_body . substr($orig_body, 0, $maxlen - $textlen); $textlen = $maxlen; } @@ -799,8 +819,17 @@ function get_item_elements($x,$allow_code = false) { function import_author_xchan($x) { - $arr = array('xchan' => $x, 'xchan_hash' => ''); - call_hooks('import_author_xchan',$arr); + $arr = [ + 'xchan' => $x, + 'xchan_hash' => '' + ]; + /** + * @hooks import_author_xchan + * Called when looking up an author of a post by xchan_hash to ensure they have an xchan record on our site. + * * \e array \b xchan + * * \e string \b xchan_hash - Thre returned value + */ + call_hooks('import_author_xchan', $arr); if($arr['xchan_hash']) return $arr['xchan_hash']; @@ -823,7 +852,6 @@ function import_author_xchan($x) { } return($y); - } /** @@ -835,7 +863,6 @@ function import_author_xchan($x) { * * \e string \b guid * @return boolean|string */ - function import_author_rss($x) { if(! $x['url']) return false; @@ -844,7 +871,7 @@ function import_author_rss($x) { dbesc($x['url']) ); if($r) { - logger('import_author_rss: in cache' , LOGGER_DEBUG); + logger('In cache' , LOGGER_DEBUG); return $r[0]['xchan_hash']; } $name = trim($x['name']); @@ -883,7 +910,15 @@ function import_author_rss($x) { function import_author_unknown($x) { - $arr = [ 'author' => $x, 'result' => false ]; + $arr = [ + 'author' => $x, + 'result' => false + ]; + /** + * @hooks import_author + * * \e array \b author + * * \e boolean|string \b result - Return value, default false + */ call_hooks('import_author', $arr); if($arr['result']) return $arr['result']; @@ -895,7 +930,7 @@ function import_author_unknown($x) { dbesc($x['url']) ); if($r) { - logger('import_author_unknown: in cache' , LOGGER_DEBUG); + logger('In cache' , LOGGER_DEBUG); return $r[0]['xchan_hash']; } @@ -1469,8 +1504,11 @@ function get_profile_elements($x) { } - - +/** + * @brief Signs an item body. + * + * @param[in,out] array $item + */ function item_sign(&$item) { if(array_key_exists('sig',$item) && $item['sig']) @@ -1483,14 +1521,13 @@ function item_sign(&$item) { if(! $r) return; - $item['sig'] = base64url_encode(rsa_sign($item['body'],$r[0]['channel_prvkey'])); + $item['sig'] = base64url_encode(rsa_sign($item['body'], $r[0]['channel_prvkey'])); $item['item_verified'] = 1; - } /** - * @brief + * @brief Stores an item type record. * * @param array $arr * @param boolean $allow_exec (optional) default false @@ -1502,8 +1539,17 @@ function item_sign(&$item) { */ function item_store($arr, $allow_exec = false, $deliver = true) { - $d = array('item' => $arr, 'allow_exec' => $allow_exec); - call_hooks('item_store', $d ); + $d = [ + 'item' => $arr, + 'allow_exec' => $allow_exec + ]; + /** + * @hooks item_store + * Called when item_store() stores a record of type item. + * * \e array \b item + * * \e boolean \b allow_exec + */ + call_hooks('item_store', $d); $arr = $d['item']; $allow_exec = $d['allow_exec']; @@ -1548,7 +1594,6 @@ function item_store($arr, $allow_exec = false, $deliver = true) { return $ret; } - $arr['title'] = ((array_key_exists('title',$arr) && strlen($arr['title'])) ? trim($arr['title']) : ''); $arr['body'] = ((array_key_exists('body',$arr) && strlen($arr['body'])) ? trim($arr['body']) : ''); @@ -1566,7 +1611,6 @@ function item_store($arr, $allow_exec = false, $deliver = true) { $arr['item_flags'] = ((x($arr,'item_flags')) ? intval($arr['item_flags']) : 0 ); - $arr['lang'] = detect_language($arr['body']); // apply the input filter here @@ -1581,10 +1625,23 @@ function item_store($arr, $allow_exec = false, $deliver = true) { $allowed_languages = get_pconfig($arr['uid'],'system','allowed_languages'); if((is_array($allowed_languages)) && ($arr['lang']) && (! array_key_exists($arr['lang'],$allowed_languages))) { - $translate = array('item' => $arr, 'from' => $arr['lang'], 'to' => $allowed_languages, 'translated' => false); + $translate = [ + 'item' => $arr, + 'from' => $arr['lang'], + 'to' => $allowed_languages, + 'translated' => false + ]; + /** + * @hooks item_translate + * Called from item_store and item_store_update after the post language has been autodetected. + * * \e array \b item + * * \e string \b from + * * \e string \b to + * * \e boolean \b translated + */ call_hooks('item_translate', $translate); if((! $translate['translated']) && (intval(get_pconfig($arr['uid'],'system','reject_disallowed_languages')))) { - logger('item_store: language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']); + logger('language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']); $ret['message'] = 'language not accepted'; return $ret; } @@ -1776,18 +1833,26 @@ function item_store($arr, $allow_exec = false, $deliver = true) { intval($arr['revision']) ); if($r) { - logger('item_store: duplicate item ignored. ' . print_r($arr,true)); + logger('duplicate item ignored. ' . print_r($arr,true)); $ret['message'] = 'duplicate post.'; return $ret; } - call_hooks('item_store',$arr); + /** + * @hooks item_store + * Called when item_store() stores a record of type item. + */ + call_hooks('item_store', $arr); - // This hook remains for backward compatibility. - call_hooks('post_remote',$arr); + /** + * @hooks post_remote + * Called when an activity arrives from another site. + * This hook remains for backward compatibility. + */ + call_hooks('post_remote', $arr); - if(x($arr,'cancel')) { - logger('item_store: post cancelled by plugin.'); + if(x($arr, 'cancel')) { + logger('Post cancelled by plugin.'); $ret['message'] = 'cancelled.'; return $ret; } @@ -1894,7 +1959,11 @@ function item_store($arr, $allow_exec = false, $deliver = true) { $ret['item'] = $arr; - call_hooks('post_remote_end',$arr); + /** + * @hooks post_remote_end + * Called after processing a remote post. + */ + call_hooks('post_remote_end', $arr); // update the commented timestamp on the parent - unless this is potentially a clone of an older item // which we don't wish to bring to the surface. As the queue only holds deliveries for 3 days, it's @@ -1931,11 +2000,28 @@ function item_store($arr, $allow_exec = false, $deliver = true) { } - -function item_store_update($arr,$allow_exec = false, $deliver = true) { - - $d = array('item' => $arr, 'allow_exec' => $allow_exec); - call_hooks('item_store_update', $d ); +/** + * @brief Update a stored item. + * + * @param array $arr an item + * @param boolean $allow_exec (optional) default false + * @param boolean $deliver (optional) default true + * @return array + */ +function item_store_update($arr, $allow_exec = false, $deliver = true) { + + $d = [ + 'item' => $arr, + 'allow_exec' => $allow_exec + ]; + /** + * @hooks item_store_update + * Called when item_store_update() is called to update a stored item. It + * overwrites the function's parameters $arr and $allow_exec. + * * \e array \b item + * * \e boolean \b allow_exec + */ + call_hooks('item_store_update', $d); $arr = $d['item']; $allow_exec = $d['allow_exec']; @@ -1947,12 +2033,12 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) { } if(! intval($arr['uid'])) { - logger('item_store_update: no uid'); + logger('no uid'); $ret['message'] = 'no uid.'; return $ret; } if(! intval($arr['id'])) { - logger('item_store_update: no id'); + logger('no id'); $ret['message'] = 'no id.'; return $ret; } @@ -1965,7 +2051,7 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) { intval($uid) ); if(! $orig) { - logger('item_store_update: original post not found: ' . $orig_post_id); + logger('Original post not found: ' . $orig_post_id); $ret['message'] = 'no original'; return $ret; } @@ -1997,7 +2083,20 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) { $allowed_languages = get_pconfig($arr['uid'],'system','allowed_languages'); if((is_array($allowed_languages)) && ($arr['lang']) && (! array_key_exists($arr['lang'],$allowed_languages))) { - $translate = array('item' => $arr, 'from' => $arr['lang'], 'to' => $allowed_languages, 'translated' => false); + $translate = [ + 'item' => $arr, + 'from' => $arr['lang'], + 'to' => $allowed_languages, + 'translated' => false + ]; + /** + * @hooks item_translate + * Called from item_store() and item_store_update() after the post language has been autodetected. + * * \e array \b item - returned value + * * \e string \b from + * * \e string \b to + * * \e boolean \b translated - default false, set true if hook translated it and provide it in item + */ call_hooks('item_translate', $translate); if((! $translate['translated']) && (intval(get_pconfig($arr['uid'],'system','reject_disallowed_languages')))) { logger('item_store: language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']); @@ -2097,18 +2196,20 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) { $arr['item_pending_remove'] = ((array_key_exists('item_pending_remove',$arr)) ? intval($arr['item_pending_remove']) : $orig[0]['item_pending_remove'] ); $arr['item_blocked'] = ((array_key_exists('item_blocked',$arr)) ? intval($arr['item_blocked']) : $orig[0]['item_blocked'] ); - - $arr['sig'] = ((x($arr,'sig')) ? $arr['sig'] : ''); $arr['layout_mid'] = ((array_key_exists('layout_mid',$arr)) ? dbesc($arr['layout_mid']) : $orig[0]['layout_mid'] ); $arr['public_policy'] = ((x($arr,'public_policy')) ? notags(trim($arr['public_policy'])) : $orig[0]['public_policy'] ); $arr['comment_policy'] = ((x($arr,'comment_policy')) ? notags(trim($arr['comment_policy'])) : $orig[0]['comment_policy'] ); - call_hooks('post_remote_update',$arr); + /** + * @hooks post_remote_update + * Called when processing a remote post that involved an edit or update. + */ + call_hooks('post_remote_update', $arr); - if(x($arr,'cancel')) { - logger('item_store_update: post cancelled by plugin.'); + if(x($arr, 'cancel')) { + logger('Post cancelled by plugin.'); $ret['message'] = 'cancelled.'; return $ret; } @@ -2145,9 +2246,9 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) { $r = dbq("update item set " . $str . " where id = " . $orig_post_id ); if($r) - logger('item_store_update: updated item ' . $orig_post_id, LOGGER_DEBUG); + logger('Updated item ' . $orig_post_id, LOGGER_DEBUG); else { - logger('item_store_update: could not update item'); + logger('Could not update item'); $ret['message'] = 'DB update failed.'; return $ret; } @@ -2194,7 +2295,11 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) { $ret['item'] = $arr; - call_hooks('post_remote_update_end',$arr); + /** + * @hooks post_remote_update_end + * Called after processing a remote post that involved an edit or update. + */ + call_hooks('post_remote_update_end', $arr); if($deliver) { send_status_notifications($orig_post_id,$arr); @@ -2427,7 +2532,7 @@ function tag_deliver($uid, $item_id) { } } else - logger('tag_deliver: tag permission denied for ' . $u[0]['channel_address']); + logger('Tag permission denied for ' . $u[0]['channel_address']); } /* @@ -2463,7 +2568,7 @@ function tag_deliver($uid, $item_id) { $terms = array_merge(get_terms_oftype($item['term'],TERM_MENTION),get_terms_oftype($item['term'],TERM_FORUM)); if($terms) - logger('tag_deliver: post mentions: ' . print_r($terms,true), LOGGER_DATA); + logger('Post mentions: ' . print_r($terms,true), LOGGER_DATA); $link = normalise_link($u[0]['xchan_url']); @@ -2477,7 +2582,7 @@ function tag_deliver($uid, $item_id) { } if($mention) { - logger('tag_deliver: mention found for ' . $u[0]['channel_name']); + logger('Mention found for ' . $u[0]['channel_name']); $r = q("update item set item_mentionsme = 1 where id = %d", intval($item_id) @@ -2543,12 +2648,23 @@ function tag_deliver($uid, $item_id) { } if(! ($tagged || $plustagged)) { - logger('tag_deliver: mention was in a reshare or exceeded max_tagged_forums - ignoring'); + logger('Mention was in a reshare or exceeded max_tagged_forums - ignoring'); return; } - $arr = array('channel_id' => $uid, 'item' => $item, 'body' => $body); - call_hooks('tagged',$arr); + $arr = [ + 'channel_id' => $uid, + 'item' => $item, + 'body' => $body + ]; + /** + * @hooks tagged + * Called when a delivery is processed which results in you being tagged. + * * \e number \b channel_id + * * \e array \b item + * * \e string \b body + */ + call_hooks('tagged', $arr); /* * Kill two birds with one stone. As long as we're here, send a mention notification. @@ -2567,7 +2683,7 @@ function tag_deliver($uid, $item_id) { // Just a normal tag? if(! $plustagged) { - logger('tag_deliver: not a plus tag', LOGGER_DEBUG); + logger('Not a plus tag', LOGGER_DEBUG); return; } @@ -2580,7 +2696,7 @@ function tag_deliver($uid, $item_id) { } if((! $mention) && (! $union)) { - logger('tag_deliver: no mention for ' . $u[0]['channel_name'] . ' and no union.'); + logger('No mention for ' . $u[0]['channel_name'] . ' and no union.'); return; } @@ -2590,11 +2706,11 @@ function tag_deliver($uid, $item_id) { if(intval($item['item_wall']) || intval($item['item_origin']) || (! intval($item['item_thread_top'])) || ($item['id'] != $item['parent'])) { - logger('tag_deliver: item was local or a comment. rejected.'); + logger('Item was local or a comment. rejected.'); return; } - logger('tag_deliver: creating second delivery chain.'); + logger('Creating second delivery chain.'); start_delivery_chain($u[0],$item,$item_id,null); } @@ -2605,8 +2721,12 @@ function tag_deliver($uid, $item_id) { * This is so that the channel with tag_delivery enabled can receive the post even if they turn off * permissions for the sender to send their stream. tag_deliver() can't be called until the post is actually stored. * By then it would be too late to reject it. + * + * @param number $uid A chnnel_id + * @param array $item + * @return boolean */ -function tgroup_check($uid,$item) { +function tgroup_check($uid, $item) { $mention = false; @@ -2731,8 +2851,8 @@ function start_delivery_chain($channel, $item, $item_id, $parent) { if($sourced) { $r = q("select * from source where src_channel_id = %d and ( src_xchan = '%s' or src_xchan = '*' ) limit 1", intval($channel['channel_id']), - dbesc(($item['source_xchan']) ? $item['source_xchan'] : $item['owner_xchan']) - ); + dbesc(($item['source_xchan']) ? $item['source_xchan'] : $item['owner_xchan']) + ); if($r) { $t = trim($r[0]['src_tag']); if($t) { @@ -2741,15 +2861,15 @@ function start_delivery_chain($channel, $item, $item_id, $parent) { foreach($tags as $tt) { $tt = trim($tt); if($tt) { - q("insert into term (uid,oid,otype,ttype,term,url) - values(%d,%d,%d,%d,'%s','%s') ", - intval($channel['channel_id']), - intval($item_id), - intval(TERM_OBJ_POST), - intval(TERM_CATEGORY), - dbesc($tt), + q("insert into term (uid,oid,otype,ttype,term,url) + values(%d,%d,%d,%d,'%s','%s') ", + intval($channel['channel_id']), + intval($item_id), + intval(TERM_OBJ_POST), + intval(TERM_CATEGORY), + dbesc($tt), dbesc(z_root() . '/channel/' . $channel['channel_address'] . '?f=&cat=' . urlencode($tt)) - ); + ); } } } @@ -3014,7 +3134,6 @@ function mail_store($arr) { $arr['mail_flags'] = ((x($arr,'mail_flags')) ? intval($arr['mail_flags']) : 0 ); $arr['mail_raw'] = ((x($arr,'mail_raw')) ? intval($arr['mail_raw']) : 0 ); - if($arr['parent_mid']) { $parent_item = q("select * from mail where mid = '%s' and channel_id = %d limit 1", @@ -3022,7 +3141,7 @@ function mail_store($arr) { intval($arr['channel_id']) ); if(($parent_item) && (! $arr['conv_guid'])) { - $arr['conv_guid'] = $parent_item[0]['conv_guid']; + $arr['conv_guid'] = $parent_item[0]['conv_guid']; } } else { @@ -3048,19 +3167,23 @@ function mail_store($arr) { ); if($r) { - logger('mail_store: duplicate item ignored. ' . print_r($arr,true)); + logger('Duplicate item ignored. ' . print_r($arr,true)); return 0; } if(! $r && $arr['mail_recalled'] == 1) { - logger('mail_store: recalled item not found. ' . print_r($arr,true)); + logger('Recalled item not found. ' . print_r($arr,true)); return 0; } - call_hooks('post_mail',$arr); + /** + * @hooks post_mail + * Called when a mail message has been composed. + */ + call_hooks('post_mail', $arr); if(x($arr,'cancel')) { - logger('mail_store: post cancelled by plugin.'); + logger('Post cancelled by plugin.'); return 0; } @@ -3077,15 +3200,15 @@ function mail_store($arr) { if($r) { $current_post = $r[0]['id']; - logger('mail_store: created item ' . $current_post, LOGGER_DEBUG); + logger('Created item ' . $current_post, LOGGER_DEBUG); $arr['id'] = $current_post; // for notification } else { - logger('mail_store: could not locate created item'); + logger('Could not locate created item'); return 0; } if(count($r) > 1) { - logger('mail_store: duplicated post occurred. Removing duplicates.'); + logger('Duplicated post occurred. Removing duplicates.'); q("DELETE FROM mail WHERE mid = '%s' AND channel_id = %d AND id != %d ", $arr['mid'], intval($arr['channel_id']), @@ -3114,7 +3237,11 @@ function mail_store($arr) { ); } - call_hooks('post_mail_end',$arr); + /** + * @hooks post_mail_end + * Called when a mail message has been delivered. + */ + call_hooks('post_mail_end', $arr); return $current_post; } @@ -3135,7 +3262,7 @@ function fix_private_photos($s, $uid, $item = null, $cid = 0) { $img_st_close++; // make it point to AFTER the closing bracket $image = substr($orig_body, $img_start + $img_st_close, $img_len); - logger('fix_private_photos: found photo ' . $image, LOGGER_DEBUG); + logger('Found photo ' . $image, LOGGER_DEBUG); if(stristr($image , $site . '/photo/')) { // Only embed locally hosted photos @@ -3179,7 +3306,7 @@ function fix_private_photos($s, $uid, $item = null, $cid = 0) { // If a custom width and height were specified, apply before embedding if(preg_match("/\[zmg\=([0-9]*)x([0-9]*)\]/is", substr($orig_body, $img_start, $img_st_close), $match)) { - logger('fix_private_photos: scaling photo', LOGGER_DEBUG); + logger('Scaling photo', LOGGER_DEBUG); $width = intval($match[1]); $height = intval($match[2]); @@ -3192,9 +3319,9 @@ function fix_private_photos($s, $uid, $item = null, $cid = 0) { } } - logger('fix_private_photos: replacing photo', LOGGER_DEBUG); + logger('Replacing photo', LOGGER_DEBUG); $image = 'data:' . $type . ';base64,' . base64_encode($data); - logger('fix_private_photos: replaced: ' . $image, LOGGER_DATA); + logger('Replaced: ' . $image, LOGGER_DATA); } } } @@ -3451,8 +3578,16 @@ function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL,$force = fal ); } - $arr = array('item' => $item, 'interactive' => $interactive, 'stage' => $stage); - call_hooks('drop_item', $arr ); + $arr = [ + 'item' => $item, + 'interactive' => $interactive, + 'stage' => $stage + ]; + /** + * @hooks drop_item + * Called when an 'item' is removed. + */ + call_hooks('drop_item', $arr); $notify_id = intval($item['id']); @@ -3602,8 +3737,14 @@ function delete_item_lowlevel($item, $stage = DROPITEM_NORMAL, $force = false) { return true; } - -function first_post_date($uid,$wall = false) { +/** + * @brief Return the first post date. + * + * @param int $uid + * @param boolean $wall (optional) default false + * @return string|boolean date string, otherwise false + */ +function first_post_date($uid, $wall = false) { $wall_sql = (($wall) ? " and item_wall = 1 " : "" ); $item_normal = item_normal(); @@ -3612,7 +3753,6 @@ function first_post_date($uid,$wall = false) { where uid = %d and id = parent $item_normal $wall_sql order by created asc limit 1", intval($uid) - ); if($r) { // logger('first_post_date: ' . $r[0]['id'] . ' ' . $r[0]['created'], LOGGER_DATA); @@ -3628,8 +3768,8 @@ function first_post_date($uid,$wall = false) { * current flat list of all representative dates. * * @param int $uid - * @param unknown $wall - * @param unknown $mindate + * @param boolean $wall + * @param string $mindate * @return array */ function list_post_dates($uid, $wall, $mindate) { @@ -3700,8 +3840,14 @@ function posted_dates($uid,$wall) { return $ret; } - -function fetch_post_tags($items,$link = false) { +/** + * @brief Extend an item array with the associated tags of the posts. + * + * @param array $items + * @param boolean $link (optional) default false + * @return array Return the provided $items array after extended the posts with tags + */ +function fetch_post_tags($items, $link = false) { $tag_finder = array(); if($items) { @@ -3720,7 +3866,6 @@ function fetch_post_tags($items,$link = false) { } $tag_finder_str = implode(', ', $tag_finder); - if(strlen($tag_finder_str)) { $tags = q("select * from term where oid in ( %s ) and otype = %d", dbesc($tag_finder_str), @@ -3729,7 +3874,6 @@ function fetch_post_tags($items,$link = false) { $imeta = q("select * from iconfig where iid in ( %s )", dbesc($tag_finder_str) ); - } for($x = 0; $x < count($items); $x ++) { @@ -3779,8 +3923,15 @@ function fetch_post_tags($items,$link = false) { } - -function zot_feed($uid,$observer_hash,$arr) { +/** + * @brief + * + * @param int $uid + * @param string $observer_hash + * @param array $arr + * @return array + */ +function zot_feed($uid, $observer_hash, $arr) { $result = array(); $mindate = null; @@ -3990,24 +4141,23 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C } if($arr['search']) { + if(strpos($arr['search'],'#') === 0) + $sql_extra .= term_query('item',substr($arr['search'],1),TERM_HASHTAG,TERM_COMMUNITYTAG); + else + $sql_extra .= sprintf(" AND item.body like '%s' ", + dbesc(protect_sprintf('%' . $arr['search'] . '%')) + ); + } - if(strpos($arr['search'],'#') === 0) - $sql_extra .= term_query('item',substr($arr['search'],1),TERM_HASHTAG,TERM_COMMUNITYTAG); - else - $sql_extra .= sprintf(" AND item.body like '%s' ", - dbesc(protect_sprintf('%' . $arr['search'] . '%')) - ); - } - - if(strlen($arr['file'])) { - $sql_extra .= term_query('item',$arr['files'],TERM_FILE); - } + if(strlen($arr['file'])) { + $sql_extra .= term_query('item',$arr['files'],TERM_FILE); + } - if($arr['conv'] && $channel) { - $sql_extra .= sprintf(" AND parent IN (SELECT distinct parent from item where ( author_xchan like '%s' or item_mentionsme = 1 )) ", - dbesc(protect_sprintf($uidhash)) - ); - } + if($arr['conv'] && $channel) { + $sql_extra .= sprintf(" AND parent IN (SELECT distinct parent from item where ( author_xchan like '%s' or item_mentionsme = 1 )) ", + dbesc(protect_sprintf($uidhash)) + ); + } if (($client_mode & CLIENT_MODE_UPDATE) && (! ($client_mode & CLIENT_MODE_LOAD))) { // only setup pagination on initial page view @@ -4042,9 +4192,9 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C } } - $simple_update = (($client_mode & CLIENT_MODE_UPDATE) ? " and item.item_unseen = 1 " : ''); - if($client_mode & CLIENT_MODE_LOAD) - $simple_update = ''; + $simple_update = (($client_mode & CLIENT_MODE_UPDATE) ? " and item.item_unseen = 1 " : ''); + if($client_mode & CLIENT_MODE_LOAD) + $simple_update = ''; //$start = dba_timer(); @@ -4087,27 +4237,26 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C if(($client_mode & CLIENT_MODE_LOAD) || ($client_mode == CLIENT_MODE_NORMAL)) { - // Fetch a page full of parent items for this page - - $r = q("SELECT distinct item.id AS item_id, item.$ordering FROM item - left join abook on item.author_xchan = abook.abook_xchan - WHERE $item_uids $item_restrict - AND item.parent = item.id - and (abook.abook_blocked = 0 or abook.abook_flags is null) - $sql_extra3 $sql_extra $sql_nets - ORDER BY item.$ordering DESC $pager_sql " - ); - - } - else { - // update - $r = q("SELECT item.parent AS item_id FROM item - left join abook on item.author_xchan = abook.abook_xchan - WHERE $item_uids $item_restrict $simple_update - and (abook.abook_blocked = 0 or abook.abook_flags is null) - $sql_extra3 $sql_extra $sql_nets " - ); - } + // Fetch a page full of parent items for this page + + $r = q("SELECT distinct item.id AS item_id, item.$ordering FROM item + left join abook on item.author_xchan = abook.abook_xchan + WHERE $item_uids $item_restrict + AND item.parent = item.id + and (abook.abook_blocked = 0 or abook.abook_flags is null) + $sql_extra3 $sql_extra $sql_nets + ORDER BY item.$ordering DESC $pager_sql " + ); + } + else { + // update + $r = q("SELECT item.parent AS item_id FROM item + left join abook on item.author_xchan = abook.abook_xchan + WHERE $item_uids $item_restrict $simple_update + and (abook.abook_blocked = 0 or abook.abook_flags is null) + $sql_extra3 $sql_extra $sql_nets " + ); + } //$first = dba_timer(); @@ -4167,12 +4316,11 @@ function webpage_to_namespace($webpage) { $page_type = 'docfile'; else $page_type = 'unknown'; - return $page_type; + return $page_type; } - function update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remote_id,$mid) { if(! $post_id) @@ -4296,7 +4444,6 @@ function comment_local_origin($item) { - function send_profile_photo_activity($channel,$photo,$profile) { // for now only create activities for the default profile @@ -4345,8 +4492,6 @@ function send_profile_photo_activity($channel,$photo,$profile) { $arr['author_xchan'] = $channel['channel_hash']; post_activity_item($arr); - - } @@ -4549,7 +4694,6 @@ function item_create_edit_activity($post) { )); - $x = post_activity_item($new_item); $post_id = $x['id']; @@ -4565,5 +4709,4 @@ function item_create_edit_activity($post) { } \Zotlabs\Daemon\Master::Summon(array('Notifier', 'edit_activity', $post_id)); - } diff --git a/include/markdown.php b/include/markdown.php index 0464cf71a..865727b20 100644 --- a/include/markdown.php +++ b/include/markdown.php @@ -14,27 +14,25 @@ require_once("include/bbcode.php"); /** - * @brief + * @brief Convert Markdown to bbcode. * * We don't want to support a bbcode specific markdown interpreter * and the markdown library we have is pretty good, but provides HTML output. * So we'll use that to convert to HTML, then convert the HTML back to bbcode, * and then clean up a few Diaspora specific constructs. * - * @param string $s + * @param string $s The message as Markdown * @param boolean $use_zrl default false - * @return string + * @param array $options default empty + * @return string The message converted to bbcode */ - function markdown_to_bb($s, $use_zrl = false, $options = []) { - if(is_array($s)) { - btlogger('markdown_to_bb called with array. ' . print_r($s,true), LOGGER_NORMAL, LOG_WARNING); + btlogger('markdown_to_bb called with array. ' . print_r($s, true), LOGGER_NORMAL, LOG_WARNING); return ''; } - $s = str_replace(" ","\r",$s); $s = str_replace(" \n>","",$s); @@ -43,9 +41,18 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) { // if empty link text replace with the url $s = preg_replace("/\[\]\((.*?)\)/ism",'[$1]($1)',$s); - $x = [ 'text' => $s , 'zrl' => $use_zrl, 'options' => $options ]; - - call_hooks('markdown_to_bb_init',$x); + $x = [ + 'text' => $s, + 'zrl' => $use_zrl, + 'options' => $options + ]; + /** + * @hooks markdown_to_bb_init + * * \e string \b text - The message as Markdown and what will get returned + * * \e boolean \b zrl + * * \e array \b options + */ + call_hooks('markdown_to_bb_init', $x); $s = $x['text']; @@ -67,7 +74,7 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) { // Convert everything that looks like a link to a link if($use_zrl) { - $s = str_replace(array('[img','/img]'),array('[zmg','/zmg]'),$s); + $s = str_replace(['[img', '/img]'], ['[zmg', '/zmg]'], $s); $s = preg_replace("/([^\]\=]|^)(https?\:\/\/)([a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)/ism", '$1[zrl=$2$3]$2$3[/zrl]',$s); } else { @@ -80,13 +87,22 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) { // Don't show link to full picture (until it is fixed) $s = scale_external_images($s, false); - call_hooks('markdown_to_bb',$s); + /** + * @hooks markdown_to_bb + * * \e string - The already converted message as bbcode + */ + call_hooks('markdown_to_bb', $s); return $s; } - +/** + * @brief + * + * @param array $match + * @return string + */ function bb_to_markdown_share($match) { $matches = array(); @@ -153,17 +169,22 @@ function bb_to_markdown_share($match) { } - +/** + * @brief Convert bbcode to Markdown. + * + * @param string $Text The message as bbcode + * @param array $options default empty + * @return string The message converted to Markdown + */ function bb_to_markdown($Text, $options = []) { /* * Transform #tags, strip off the [url] and replace spaces with underscore */ - $Text = preg_replace_callback('/#\[([zu])rl\=(.*?)\](.*?)\[\/[(zu)]rl\]/i', + $Text = preg_replace_callback('/#\[([zu])rl\=(.*?)\](.*?)\[\/[(zu)]rl\]/i', create_function('$match', 'return \'#\'. str_replace(\' \', \'_\', $match[3]);'), $Text); - $Text = preg_replace('/#\^\[([zu])rl\=(.*?)\](.*?)\[\/([zu])rl\]/i', '[$1rl=$2]$3[/$4rl]', $Text); // Converting images with size parameters to simple images. Markdown doesn't know it. @@ -173,7 +194,12 @@ function bb_to_markdown($Text, $options = []) { $x = [ 'bbcode' => $Text, 'options' => $options ]; - call_hooks('bb_to_markdown_bb',$x); + /** + * @hooks bb_to_markdown_bb + * * \e string \b bbcode - The message as bbcode and what will get returned + * * \e array \b options + */ + call_hooks('bb_to_markdown_bb', $x); $Text = $x['bbcode']; @@ -202,14 +228,16 @@ function bb_to_markdown($Text, $options = []) { $Text = trim($Text); + /** + * @hooks bb_to_markdown + * * \e string - The already converted message as bbcode and what will get returned + */ call_hooks('bb_to_markdown', $Text); return $Text; - } - /** * @brief Convert a HTML text into Markdown. * @@ -217,8 +245,6 @@ function bb_to_markdown($Text, $options = []) { * * If the HTML text can not get parsed it will return an empty string. * - * @see HTMLToMarkdown - * * @param string $html The HTML code to convert * @return string Markdown representation of the given HTML text, empty on error */ @@ -232,8 +258,5 @@ function html2markdown($html) { logger("Invalid HTML. HTMLToMarkdown library threw an exception."); } - // The old html 2 markdown library "pixel418/markdownify": "^2.2", - //$md = new HtmlConverter(); - //$markdown = $md->convert($Text); return $markdown; } diff --git a/include/network.php b/include/network.php index 2caf29ab5..3569874be 100644 --- a/include/network.php +++ b/include/network.php @@ -1,6 +1,7 @@ content * * \e string \b debug => from curl_info() */ -function z_post_url($url,$params, $redirects = 0, $opts = array()) { +function z_post_url($url, $params, $redirects = 0, $opts = array()) { // logger('url: ' . $url); // logger('params: ' . print_r($params,true)); @@ -276,13 +277,10 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) { @curl_setopt($ch, CURLOPT_USERPWD, $opts['http_auth']); } - if(x($opts,'cookiejar')) @curl_setopt($ch, CURLOPT_COOKIEJAR, $opts['cookiejar']); if(x($opts,'cookiefile')) @curl_setopt($ch, CURLOPT_COOKIEFILE, $opts['cookiefile']); - - if(x($opts,'cookie')) @curl_setopt($ch, CURLOPT_COOKIE, $opts['cookie']); @@ -423,7 +421,7 @@ function http_status($val, $msg = '') { * integer HTTP status result value * @param string $msg * optional message - * @return does not return, process is terminated + * @return void does not return, process is terminated */ function http_status_exit($val, $msg = '') { http_status($val, $msg); @@ -431,10 +429,10 @@ function http_status_exit($val, $msg = '') { } /** - * @brief convert an XML document to a normalised, case-corrected array used by webfinger. + * @brief Convert an XML document to a normalised, case-corrected array used by webfinger. * * @param string|array|SimpleXMLElement $xml_element - * @param int $recursion_depth[in,out] + * @param[in,out] int $recursion_depth * @return NULL|string|array */ function convert_xml_element_to_array($xml_element, &$recursion_depth=0) { @@ -501,14 +499,14 @@ function z_dns_check($h,$check_mx = 0) { } /** - * @brief Validates a given URL + * @brief Validates a given URL. * * Take a URL from the wild, prepend http:// if necessary and check DNS to see * if it's real (or check if is a valid IP address). * * @see z_dns_check() * - * @param string $url[in,out] URL to check + * @param[in,out] string $url URL to check * @return boolean Return true if it's OK, false if something is wrong with it */ function validate_url(&$url) { @@ -593,6 +591,7 @@ function allowed_url($url) { } } } + return $found; } @@ -658,7 +657,7 @@ function allowed_email($email) { -function parse_xml_string($s,$strict = true) { +function parse_xml_string($s, $strict = true) { if($strict) { if(! strstr($s,' $webbie, 'protocol' => $protocol, 'success' => false, 'webfinger' => $x); + $arr = [ + 'address' => $webbie, + 'protocol' => $protocol, + 'success' => false, + 'webfinger' => $x + ]; + /** + * @hooks discover_channel_webfinger + * Called when performing a webfinger lookup. + * * \e string \b address - The webbie + * * \e string \b protocol + * * \e array \b webfinger - The result from webfinger_rfc7033() + * * \e boolean \b success - The return value, default false + */ call_hooks('discover_channel_webfinger', $arr); if($arr['success']) return true; return false; - } -function webfinger_rfc7033($webbie,$zot = false) { +/** + * @brief Fetch and return a webfinger for a webbie. + * + * @param string $webbie - The webbie + * @param boolean $zot (optional) default false + * @return boolean|string false or associative array from result JSON + */ +function webfinger_rfc7033($webbie, $zot = false) { if(strpos($webbie,'@')) { $lhs = substr($webbie,0,strpos($webbie,'@')); @@ -1199,6 +1230,7 @@ function webfinger_rfc7033($webbie,$zot = false) { if($m) { if($m['scheme'] !== 'https') return false; + $rhs = $m['host'] . (($m['port']) ? ':' . $m['port'] : ''); $resource = urlencode($webbie); } @@ -1211,20 +1243,19 @@ function webfinger_rfc7033($webbie,$zot = false) { // and results in a 406 (Not Acceptable) response, and will also incorrectly produce an XML // document if you use 'application/jrd+json, */*'. We could set this to application/jrd+json, // but some test webfinger servers may not explicitly set the content type and they would be - // blocked. The best compromise until Mastodon is fixed is to remove the Accept header which is - // accomplished by setting it to nothing. + // blocked. The best compromise until Mastodon is fixed is to remove the Accept header which is + // accomplished by setting it to nothing. $counter = 0; - $s = z_fetch_url('https://' . $rhs . '/.well-known/webfinger?f=&resource=' . $resource . (($zot) ? '&zot=1' : ''), + $s = z_fetch_url('https://' . $rhs . '/.well-known/webfinger?f=&resource=' . $resource . (($zot) ? '&zot=1' : ''), false, $counter, [ 'headers' => [ 'Accept:' ] ]); if($s['success']) { - $j = json_decode($s['body'],true); + $j = json_decode($s['body'], true); return($j); } return false; - } function old_webfinger($webbie) { @@ -1604,7 +1635,13 @@ function check_siteallowed($url) { $retvalue = true; $arr = array('url' => $url); - call_hooks('check_siteallowed',$arr); + /** + * @hooks check_siteallowed + * Used to over-ride or bypass the site black/white block lists. + * * \e string \b url + * * \e boolean \b allowed - optional return value set in hook + */ + call_hooks('check_siteallowed', $arr); if(array_key_exists('allowed',$arr)) return $arr['allowed']; @@ -1643,7 +1680,13 @@ function check_channelallowed($hash) { $retvalue = true; $arr = array('hash' => $hash); - call_hooks('check_channelallowed',$arr); + /** + * @hooks check_channelallowed + * Used to over-ride or bypass the channel black/white block lists. + * * \e string \b hash + * * \e boolean \b allowed - optional return value set in hook + */ + call_hooks('check_channelallowed', $arr); if(array_key_exists('allowed',$arr)) return $arr['allowed']; @@ -1732,6 +1775,10 @@ function network_to_name($s) { NETWORK_MYSPACE => t('MySpace'), ); + /** + * @hooks network_to_name + * @deprecated + */ call_hooks('network_to_name', $nets); $search = array_keys($nets); @@ -1743,7 +1790,7 @@ function network_to_name($s) { /** * @brief Send a text email message. * - * @param array $params an assoziative array with: + * @param array $params an associative array with: * * \e string \b fromName name of the sender * * \e string \b fromEmail email of the sender * * \e string \b replyTo replyTo address to direct responses @@ -1774,6 +1821,10 @@ function z_mail($params) { $params['sent'] = false; $params['result'] = false; + /** + * @hooks email_send + * * \e params @see z_mail() + */ call_hooks('email_send', $params); if($params['sent']) { @@ -1921,60 +1972,78 @@ function service_plink($contact, $guid) { $plink = $url . '/channel/' . $handle . '?f=&mid=' . $guid; $x = [ 'xchan' => $contact, 'guid' => $guid, 'url' => $url, 'plink' => $plink ]; + /** + * @hooks service_plink + * * \e array \b xchan + * * \e string \b guid + * * \e string \b url + * * \e string \b plink will get returned + */ call_hooks('service_plink', $x); return $x['plink']; } + +/** + * @brief + * + * @param array $mimeTypes + * @param string $acceptedTypes by default false will use $_SERVER['HTTP_ACCEPT'] + * @return array|NULL + */ function getBestSupportedMimeType($mimeTypes = null, $acceptedTypes = false) { - // Values will be stored in this array + // Values will be stored in this array + $AcceptTypes = []; if($acceptedTypes === false) $acceptedTypes = $_SERVER['HTTP_ACCEPT']; - $AcceptTypes = Array (); - - // Accept header is case insensitive, and whitespace isn’t important - $accept = strtolower(str_replace(' ', '', $acceptedTypes)); - // divide it into parts in the place of a "," - $accept = explode(',', $accept); - foreach ($accept as $a) { - // the default quality is 1. - $q = 1; - // check if there is a different quality - if (strpos($a, ';q=')) { - // divide "mime/type;q=X" into two parts: "mime/type" i "X" - list($a, $q) = explode(';q=', $a); - } - // mime-type $a is accepted with the quality $q - // WARNING: $q == 0 means, that mime-type isn’t supported! - $AcceptTypes[$a] = $q; - } - arsort($AcceptTypes); - - // if no parameter was passed, just return parsed data - if (!$mimeTypes) return $AcceptTypes; - - $mimeTypes = array_map('strtolower', (array)$mimeTypes); - - // let’s check our supported types: - foreach ($AcceptTypes as $mime => $q) { - if ($q && in_array($mime, $mimeTypes)) return $mime; - } - // no mime-type found - return null; -} + // Accept header is case insensitive, and whitespace isn’t important + $accept = strtolower(str_replace(' ', '', $acceptedTypes)); + // divide it into parts in the place of a "," + $accept = explode(',', $accept); + foreach ($accept as $a) { + // the default quality is 1. + $q = 1; + // check if there is a different quality + if (strpos($a, ';q=')) { + // divide "mime/type;q=X" into two parts: "mime/type" i "X" + list($a, $q) = explode(';q=', $a); + } + // mime-type $a is accepted with the quality $q + // WARNING: $q == 0 means, that mime-type isn’t supported! + $AcceptTypes[$a] = $q; + } + arsort($AcceptTypes); + // if no parameter was passed, just return parsed data + if (!$mimeTypes) return $AcceptTypes; -function jsonld_document_loader($url) { + $mimeTypes = array_map('strtolower', (array)$mimeTypes); - // perform caching for jsonld normaliser + // let’s check our supported types: + foreach ($AcceptTypes as $mime => $q) { + if ($q && in_array($mime, $mimeTypes)) return $mime; + } + + // no mime-type found + return null; +} + +/** + * @brief Perform caching for jsonld normaliser. + * + * @param string $url + * @return mixed|boolean|array + */ +function jsonld_document_loader($url) { require_once('library/jsonld/jsonld.php'); $cachepath = 'store/[data]/ldcache'; if(! is_dir($cachepath)) - os_mkdir($cachepath,STORAGE_DEFAULT_PERMISSIONS,true); + os_mkdir($cachepath, STORAGE_DEFAULT_PERMISSIONS, true); $filename = $cachepath . '/' . urlencode($url); if(file_exists($filename) && filemtime($filename) > time() - (12 * 60 * 60)) { @@ -1983,7 +2052,7 @@ function jsonld_document_loader($url) { $r = jsonld_default_document_loader($url); if($r) { - file_put_contents($filename,json_encode($r)); + file_put_contents($filename, json_encode($r)); return $r; } @@ -1993,5 +2062,4 @@ function jsonld_document_loader($url) { } return []; - } \ No newline at end of file diff --git a/include/photos.php b/include/photos.php index 5de68f162..508121950 100644 --- a/include/photos.php +++ b/include/photos.php @@ -10,14 +10,13 @@ require_once('include/photo/photo_driver.php'); require_once('include/text.php'); /** - * @brief + * @brief Upload a photo. * * @param array $channel * @param array $observer * @param array $args * @return array */ - function photo_upload($channel, $observer, $args) { $ret = array('success' => false); @@ -115,25 +114,33 @@ function photo_upload($channel, $observer, $args) { if (! $type) $type=guess_image_type($filename); - logger('photo_upload: received file: ' . $filename . ' as ' . $src . ' ('. $type . ') ' . $filesize . ' bytes', LOGGER_DEBUG); + logger('Received file: ' . $filename . ' as ' . $src . ' ('. $type . ') ' . $filesize . ' bytes', LOGGER_DEBUG); $maximagesize = get_config('system','maximagesize'); if (($maximagesize) && ($filesize > $maximagesize)) { $ret['message'] = sprintf ( t('Image exceeds website size limit of %lu bytes'), $maximagesize); @unlink($src); - call_hooks('photo_upload_end',$ret); + /** + * @hooks photo_upload_end + * Called when a photo upload has been processed. + */ + call_hooks('photo_upload_end', $ret); return $ret; } if (! $filesize) { $ret['message'] = t('Image file is empty.'); @unlink($src); - call_hooks('photo_post_end',$ret); + /** + * @hooks photo_post_end + * Called after uploading a photo. + */ + call_hooks('photo_post_end', $ret); return $ret; } - logger('photo_upload: loading the contents of ' . $src , LOGGER_DEBUG); + logger('Loading the contents of ' . $src , LOGGER_DEBUG); $imagedata = @file_get_contents($src); } @@ -146,7 +153,11 @@ function photo_upload($channel, $observer, $args) { if (($r) && ($limit !== false) && (($r[0]['total'] + strlen($imagedata)) > $limit)) { $ret['message'] = upgrade_message(); @unlink($src); - call_hooks('photo_post_end',$ret); + /** + * @hooks photo_post_end + * Called after uploading a photo. + */ + call_hooks('photo_post_end', $ret); return $ret; } @@ -154,9 +165,13 @@ function photo_upload($channel, $observer, $args) { if (! $ph->is_valid()) { $ret['message'] = t('Unable to process image'); - logger('photo_upload: unable to process image'); + logger('unable to process image'); @unlink($src); - call_hooks('photo_upload_end',$ret); + /** + * @hooks photo_upload_end + * Called when a photo upload has been processed. + */ + call_hooks('photo_upload_end', $ret); return $ret; } @@ -266,8 +281,12 @@ function photo_upload($channel, $observer, $args) { intval($channel_id) ); $ret['message'] = t('Photo storage failed.'); - logger('photo_upload: photo store failed.'); - call_hooks('photo_upload_end',$ret); + logger('Photo store failed.'); + /** + * @hooks photo_upload_end + * Called when a photo upload has been processed. + */ + call_hooks('photo_upload_end', $ret); return $ret; } @@ -293,8 +312,6 @@ function photo_upload($channel, $observer, $args) { $width = $link[1]['width']; $height = $link[1]['height']; $tag = (($r1) ? '[zmg=' . $width . 'x' . $height . ']' : '[zmg]'); - - } else { $scale = 2; @@ -352,7 +369,6 @@ function photo_upload($channel, $observer, $args) { $item['target'] = json_encode($target); $force = true; - } $r = q("select id, edited from item where mid = '%s' and uid = %d limit 1", dbesc($item['mid']), @@ -420,7 +436,6 @@ function photo_upload($channel, $observer, $args) { $arr['item_private'] = 1; - $result = item_store($arr,false,$deliver); $item_id = $result['item_id']; @@ -434,7 +449,11 @@ function photo_upload($channel, $observer, $args) { $ret['resource_id'] = $photo_hash; $ret['photoitem_id'] = $item_id; - call_hooks('photo_upload_end',$ret); + /** + * @hooks photo_upload_end + * Called when a photo upload has been processed. + */ + call_hooks('photo_upload_end', $ret); return $ret; } @@ -499,10 +518,8 @@ function photo_calculate_1600_scale($arr) { } return $dest_width . 'x' . $dest_height; - } - /** * @brief Returns a list with all photo albums observer is allowed to see. * @@ -517,7 +534,6 @@ function photo_calculate_1600_scale($arr) { * * \e boolean \b success * * \e array \b albums */ - function photos_albums_list($channel, $observer, $sort_key = 'display_path', $direction = 'asc') { $channel_id = $channel['channel_id']; @@ -610,14 +626,13 @@ function photos_album_widget($channelx,$observer,$sortkey = 'display_path',$dire } /** - * @brief + * @brief Return an array of photos. * * @param array $channel * @param array $observer - * @param string $album default empty + * @param string $album (optional) default empty * @return boolean|array */ - function photos_list_photos($channel, $observer, $album = '') { $channel_id = $channel['channel_id']; @@ -654,21 +669,20 @@ function photos_list_photos($channel, $observer, $album = '') { * @brief Check if given photo album exists in channel. * * @param int $channel_id id of the channel + * @param string $observer_hash * @param string $album name of the album * @return boolean */ - - function photos_album_exists($channel_id, $observer_hash, $album) { - $sql_extra = permissions_sql($channel_id,$observer_hash); + $sql_extra = permissions_sql($channel_id, $observer_hash); $r = q("SELECT folder, hash, is_dir, filename, os_path, display_path FROM attach WHERE hash = '%s' AND is_dir = 1 AND uid = %d $sql_extra limit 1", dbesc($album), intval($channel_id) ); - // partial backward compatibility with Hubzilla < 2.4 when we used the filename only + // partial backward compatibility with Hubzilla < 2.4 when we used the filename only // (ambiguous which would get chosen if you had two albums of the same name in different directories) if(!$r && ctype_xdigit($album)) { $r = q("SELECT folder, hash, is_dir, filename, os_path, display_path FROM attach WHERE filename = '%s' AND is_dir = 1 AND uid = %d $sql_extra limit 1", @@ -690,7 +704,6 @@ function photos_album_exists($channel_id, $observer_hash, $album) { * @param string $newname The new name of the album * @return bool|array */ - function photos_album_rename($channel_id, $oldname, $newname) { return q("UPDATE photo SET album = '%s' WHERE album = '%s' AND uid = %d", dbesc($newname), @@ -699,17 +712,14 @@ function photos_album_rename($channel_id, $oldname, $newname) { ); } - - /** * @brief * * @param int $channel_id * @param string $album - * @param string $remote_xchan + * @param string $remote_xchan (optional) default empty * @return string|boolean */ - function photos_album_get_db_idstr($channel_id, $album, $remote_xchan = '') { if($remote_xchan) { @@ -743,15 +753,13 @@ function photos_album_get_db_idstr($channel_id, $album, $remote_xchan = '') { * @param array $channel * @param string $creator_hash * @param array $photo - * @param boolean $visible default false + * @param boolean $visible (optional) default false * @return int item_id */ - function photos_create_item($channel, $creator_hash, $photo, $visible = false) { // Create item container - $item_hidden = (($visible) ? 0 : 1 ); $mid = item_message_id(); @@ -791,36 +799,36 @@ function photos_create_item($channel, $creator_hash, $photo, $visible = false) { function getGps($exifCoord, $hemi) { - $degrees = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0; - $minutes = count($exifCoord) > 1 ? gps2Num($exifCoord[1]) : 0; - $seconds = count($exifCoord) > 2 ? gps2Num($exifCoord[2]) : 0; + $degrees = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0; + $minutes = count($exifCoord) > 1 ? gps2Num($exifCoord[1]) : 0; + $seconds = count($exifCoord) > 2 ? gps2Num($exifCoord[2]) : 0; - $flip = ($hemi == 'W' or $hemi == 'S') ? -1 : 1; + $flip = ($hemi == 'W' or $hemi == 'S') ? -1 : 1; - return floatval($flip * ($degrees + ($minutes / 60) + ($seconds / 3600))); + return floatval($flip * ($degrees + ($minutes / 60) + ($seconds / 3600))); } function getGpstimestamp($exifCoord) { - $hours = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0; - $minutes = count($exifCoord) > 1 ? gps2Num($exifCoord[1]) : 0; - $seconds = count($exifCoord) > 2 ? gps2Num($exifCoord[2]) : 0; + $hours = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0; + $minutes = count($exifCoord) > 1 ? gps2Num($exifCoord[1]) : 0; + $seconds = count($exifCoord) > 2 ? gps2Num($exifCoord[2]) : 0; - return sprintf('%02d:%02d:%02d',$hours,$minutes,$seconds); + return sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds); } function gps2Num($coordPart) { - $parts = explode('/', $coordPart); + $parts = explode('/', $coordPart); - if (count($parts) <= 0) - return 0; + if (count($parts) <= 0) + return 0; - if (count($parts) == 1) - return $parts[0]; + if (count($parts) == 1) + return $parts[0]; - return floatval($parts[0]) / floatval($parts[1]); + return floatval($parts[0]) / floatval($parts[1]); } @@ -832,7 +840,7 @@ function photo_profile_setperms($channel_id,$resource_id,$profile_id) { $r = q("select profile_guid, is_default from profile where id = %d and uid = %d limit 1", dbesc($profile_id), intval($channel_id) - ); + ); if(! $r) return; @@ -841,26 +849,26 @@ function photo_profile_setperms($channel_id,$resource_id,$profile_id) { $profile_guid = $r[0]['profile_guid']; if($is_default) { - $r = q("update photo set allow_cid = '', allow_gid = '', deny_cid = '', deny_gid = '' + $r = q("update photo set allow_cid = '', allow_gid = '', deny_cid = '', deny_gid = '' where resource_id = '%s' and uid = %d", dbesc($resource_id), intval($channel_id) ); - $r = q("update attach set allow_cid = '', allow_gid = '', deny_cid = '', deny_gid = '' + $r = q("update attach set allow_cid = '', allow_gid = '', deny_cid = '', deny_gid = '' where hash = '%s' and uid = %d", dbesc($resource_id), intval($channel_id) ); } else { - $r = q("update photo set allow_cid = '', allow_gid = '%s', deny_cid = '', deny_gid = '' + $r = q("update photo set allow_cid = '', allow_gid = '%s', deny_cid = '', deny_gid = '' where resource_id = '%s' and uid = %d", dbesc(''), dbesc($resource_id), intval($channel_id) ); - $r = q("update attach set allow_cid = '', allow_gid = '%s', deny_cid = '', deny_gid = '' + $r = q("update attach set allow_cid = '', allow_gid = '%s', deny_cid = '', deny_gid = '' where hash = '%s' and uid = %d", dbesc(''), dbesc($resource_id), @@ -869,71 +877,72 @@ function photo_profile_setperms($channel_id,$resource_id,$profile_id) { } } +/** + * @brief + * + * @param int $uid + * @param int|string $profileid + */ function profile_photo_set_profile_perms($uid, $profileid = 0) { $allowcid = ''; - if($profileid) { + $r = q("SELECT photo, profile_guid, id, is_default, uid + FROM profile WHERE uid = %d and ( profile.id = %d OR profile.profile_guid = '%s') LIMIT 1", + intval($uid), + intval($profileid), + dbesc($profileid) + ); + } + else { + logger('Resetting permissions on default-profile-photo for user'.local_channel()); - $r = q("SELECT photo, profile_guid, id, is_default, uid - FROM profile WHERE uid = %d and ( profile.id = %d OR profile.profile_guid = '%s') LIMIT 1", - intval($uid), - intval($profileid), - dbesc($profileid) - ); - } - else { - logger('Resetting permissions on default-profile-photo for user'.local_channel()); + $r = q("SELECT photo, profile_guid, id, is_default, uid FROM profile + WHERE profile.uid = %d AND is_default = 1 LIMIT 1", + intval($uid) + ); //If no profile is given, we update the default profile + } + if(! $r) + return; - $r = q("SELECT photo, profile_guid, id, is_default, uid FROM profile - WHERE profile.uid = %d AND is_default = 1 LIMIT 1", - intval($uid) - ); //If no profile is given, we update the default profile - } - if(! $r) - return; - - $profile = $r[0]; - - if($profile['id'] && $profile['photo']) { - preg_match("@\w*(?=-\d*$)@i", $profile['photo'], $resource_id); - $resource_id = $resource_id[0]; - - if (! intval($profile['is_default'])) { - $r0 = q("SELECT channel_hash FROM channel WHERE channel_id = %d LIMIT 1", - intval($uid) - ); - //Should not be needed in future. Catches old int-profile-ids. - $r1 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%d' ", - intval($profile['id']) - ); - $r2 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%s'", - dbesc($profile['profile_guid']) - ); - $allowcid = "<" . $r0[0]['channel_hash'] . ">"; - foreach ($r1 as $entry) { - $allowcid .= "<" . $entry['abook_xchan'] . ">"; - } - foreach ($r2 as $entry) { - $allowcid .= "<" . $entry['abook_xchan'] . ">"; - } + $profile = $r[0]; - q("UPDATE photo SET allow_cid = '%s' WHERE resource_id = '%s' AND uid = %d", - dbesc($allowcid), - dbesc($resource_id), - intval($uid) - ); + if($profile['id'] && $profile['photo']) { + preg_match("@\w*(?=-\d*$)@i", $profile['photo'], $resource_id); + $resource_id = $resource_id[0]; + if (! intval($profile['is_default'])) { + $r0 = q("SELECT channel_hash FROM channel WHERE channel_id = %d LIMIT 1", + intval($uid) + ); + //Should not be needed in future. Catches old int-profile-ids. + $r1 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%d' ", + intval($profile['id']) + ); + $r2 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%s'", + dbesc($profile['profile_guid']) + ); + $allowcid = "<" . $r0[0]['channel_hash'] . ">"; + foreach ($r1 as $entry) { + $allowcid .= "<" . $entry['abook_xchan'] . ">"; } - else { - //Reset permissions on default profile picture to public - q("UPDATE photo SET allow_cid = '' WHERE photo_usage = %d AND uid = %d", - intval(PHOTO_PROFILE), - intval($uid) - ); + foreach ($r2 as $entry) { + $allowcid .= "<" . $entry['abook_xchan'] . ">"; } - } - return; + q("UPDATE photo SET allow_cid = '%s' WHERE resource_id = '%s' AND uid = %d", + dbesc($allowcid), + dbesc($resource_id), + intval($uid) + ); + } + else { + //Reset permissions on default profile picture to public + q("UPDATE photo SET allow_cid = '' WHERE photo_usage = %d AND uid = %d", + intval(PHOTO_PROFILE), + intval($uid) + ); + } } +} diff --git a/include/plugin.php b/include/plugin.php index db20152ea..379d8e799 100755 --- a/include/plugin.php +++ b/include/plugin.php @@ -7,7 +7,7 @@ /** - * @brief unloads an addon. + * @brief Unloads an addon. * * @param string $plugin name of the addon */ @@ -22,7 +22,7 @@ function unload_plugin($plugin){ } /** - * @brief uninstalls an addon. + * @brief Uninstalls an addon. * * @param string $plugin name of the addon * @return boolean @@ -110,6 +110,13 @@ function load_plugin($plugin) { } } + +/** + * @brief Check if addon is installed. + * + * @param string $name + * @return boolean + */ function plugin_is_installed($name) { $r = q("select aname from addon where aname = '%s' and installed = 1 limit 1", dbesc($name) @@ -121,8 +128,9 @@ function plugin_is_installed($name) { } -// reload all updated plugins - +/** + * @brief Reload all updated plugins. + */ function reload_plugins() { $plugins = get_config('system', 'addon'); if(strlen($plugins)) { @@ -167,13 +175,18 @@ function reload_plugins() { } } + +/** + * @brief Get a list of non hidden addons. + * + * @return array + */ function visible_plugin_list() { $r = q("select * from addon where hidden = 0 order by aname asc"); return(($r) ? ids_to_array($r,'aname') : array()); } - /** * @brief registers a hook. * @@ -282,7 +295,7 @@ function insert_hook($hook, $fn, $version = 0, $priority = 0) { * the provided data. * * @param string $name of the hook to call - * @param string|array &$data to transmit to the callback handler + * @param[in,out] string|array &$data to transmit to the callback handler */ function call_hooks($name, &$data = null) { $a = 0; @@ -414,8 +427,8 @@ function check_plugin_versions($info) { || stristr($info['serverroles'],'any') || stristr($info['serverroles'],$role))) { logger('serverrole limit: ' . $info['name'],LOGGER_NORMAL,LOG_WARNING); - return false; + return false; } } @@ -447,8 +460,6 @@ function check_plugin_versions($info) { } - - /** * @brief Parse theme comment in search of theme infos. * @@ -532,7 +543,7 @@ function get_theme_info($theme){ * * The screenshot is expected as view/theme/$theme/img/screenshot.[png|jpg]. * - * @param sring $theme The name of the theme + * @param string $theme The name of the theme * @return string */ function get_theme_screenshot($theme) { @@ -626,15 +637,16 @@ function format_css_if_exists($source) { } } -/* +/** * This basically calculates the baseurl. We have other functions to do that, but * there was an issue with script paths and mixed-content whose details are arcane * and perhaps lost in the message archives. The short answer is that we're ignoring * the URL which we are "supposed" to use, and generating script paths relative to * the URL which we are currently using; in order to ensure they are found and aren't * blocked due to mixed content issues. + * + * @return string */ - function script_path() { if(x($_SERVER,'HTTPS') && $_SERVER['HTTPS']) $scheme = 'https'; @@ -659,6 +671,7 @@ function script_path() { else { return z_root(); } + return $scheme . '://' . $hostname; } @@ -675,10 +688,13 @@ function head_remove_js($src, $priority = 0) { unset(App::$js_sources[$priority][$index]); } -// We should probably try to register main.js with a high priority, but currently we handle it -// separately and put it at the end of the html head block in case any other javascript is -// added outside the head_add_js construct. - +/** + * We should probably try to register main.js with a high priority, but currently + * we handle it separately and put it at the end of the html head block in case + * any other javascript is added outside the head_add_js construct. + * + * @return string + */ function head_get_js() { $str = ''; @@ -694,6 +710,7 @@ function head_get_js() { } } } + return $str; } @@ -703,6 +720,7 @@ function head_get_main_js() { if(count($sources)) foreach($sources as $source) $str .= format_js_if_exists($source,true); + return $str; } @@ -716,7 +734,7 @@ function format_js_if_exists($source) { if(substr($source,0,2) === '//') { $path_prefix = ''; } - } + } else { // It's a file from the theme $path = '/' . theme_include($source); @@ -781,12 +799,16 @@ function get_markup_template($s, $root = '') { return $template; } +/** + * @brief + * + * @param string $folder + * @return boolean|string + */ +function folder_exists($folder) { + // Get canonicalized absolute pathname + $path = realpath($folder); -function folder_exists($folder) -{ - // Get canonicalized absolute pathname - $path = realpath($folder); - - // If it exist, check if it's a directory - return (($path !== false) && is_dir($path)) ? $path : false; + // If it exist, check if it's a directory + return (($path !== false) && is_dir($path)) ? $path : false; } diff --git a/include/zid.php b/include/zid.php index ce9f70385..084188770 100644 --- a/include/zid.php +++ b/include/zid.php @@ -21,6 +21,7 @@ function is_matrix_url($url) { } $remembered[$m['host']] = false; } + return false; } @@ -32,14 +33,8 @@ function is_matrix_url($url) { * @param boolean $address * $address to use instead of session environment * @return string - * - * @hooks 'zid' - * string url - url to accept zid - * string zid - urlencoded zid - * string result - the return string we calculated, change it if you want to return something else */ - -function zid($s,$address = '') { +function zid($s, $address = '') { if (! strlen($s) || strpos($s,'zid=')) return $s; @@ -74,7 +69,18 @@ function zid($s,$address = '') { if($fragment) $zurl .= '#' . $fragment; - $arr = array('url' => $s, 'zid' => urlencode($myaddr), 'result' => $zurl); + $arr = [ + 'url' => $s, + 'zid' => urlencode($myaddr), + 'result' => $zurl + ]; + /** + * @hooks zid + * Called when adding the observer's zid to a URL. + * * \e string \b url - url to accept zid + * * \e string \b zid - urlencoded zid + * * \e string \b result - the return string we calculated, change it if you want to return something else + */ call_hooks('zid', $arr); return $arr['result']; @@ -100,25 +106,26 @@ function strip_zats($s) { * because the latter is used for general purpose conversions and the former is used only when preparing text for * immediate display. * - * Issues: Currently the order of HTML parameters in the text is somewhat rigid and inflexible. + * @TODO Issues: Currently the order of HTML parameters in the text is somewhat rigid and inflexible. * We assume it looks like \ and will not work if zrl and href appear in a different order. * * @param array $match * @return string */ function zidify_callback($match) { - $is_zid = ((feature_enabled(local_channel(),'sendzid')) || (strpos($match[1],'zrl')) ? true : false); + $is_zid = ((feature_enabled(local_channel(), 'sendzid')) || (strpos($match[1], 'zrl')) ? true : false); $replace = ' $hubloc, 'url' => \App::$query_string, 'session' => $_SESSION); - call_hooks('magic_auth_success',$arr); + $arr = [ + 'xchan' => $hubloc, + 'url' => \App::$query_string, + 'session' => $_SESSION + ]; + /** + * @hooks magic_auth_success + * Called when a magic-auth was successful. + * * \e array \b xchan + * * \e string \b url + * * \e array \b session + */ + call_hooks('magic_auth_success', $arr); + \App::set_observer($hubloc); require_once('include/security.php'); \App::set_groups(init_groups_visitor($_SESSION['visitor_id'])); - if(! get_config('system','hide_owa_greeting')) + if(! get_config('system', 'hide_owa_greeting')) info(sprintf( t('OpenWebAuth: %1$s welcomes %2$s'),\App::get_hostname(), $hubloc['xchan_name'])); - logger('OpenWebAuth: auth success from ' . $hubloc['xchan_addr']); - + logger('OpenWebAuth: auth success from ' . $hubloc['xchan_addr']); } \ No newline at end of file diff --git a/include/zot.php b/include/zot.php index 5764bb99a..0aa50ab92 100644 --- a/include/zot.php +++ b/include/zot.php @@ -31,7 +31,6 @@ require_once('include/perm_upgrade.php'); * @param string $channel_nick a unique nickname of controlling entity * @returns string */ - function zot_new_uid($channel_nick) { $rawstr = z_root() . '/' . $channel_nick . '.' . mt_rand(); return(base64url_encode(hash('whirlpool', $rawstr, true), true)); @@ -49,7 +48,6 @@ function zot_new_uid($channel_nick) { * @param string $guid * @param string $guid_sig */ - function make_xchan_hash($guid, $guid_sig) { return base64url_encode(hash('whirlpool', $guid . $guid_sig, true)); } @@ -104,6 +102,8 @@ function zot_get_hublocs($hash) { * @param string $remote_key * optional public site key of target hub used to encrypt entire packet * NOTE: remote_key and encrypted packets are required for 'auth_check' packets, optional for all others + * @param string $methods + * optional comma separated list of encryption methods @ref zot_best_algorithm() * @param string $secret * random string, required for packets which require verification/callback * e.g. 'pickup', 'purge', 'notify', 'auth_check'. Packet types 'ping', 'force_refresh', and 'refresh' do not require verification @@ -159,29 +159,38 @@ function zot_build_packet($channel, $type = 'notify', $recipients = null, $remot } /** - * @brief choose best encryption function from those available on both sites - * + * @brief Choose best encryption function from those available on both sites. + * * @param string $methods * comma separated list of encryption methods * @return string first match from our site method preferences crypto_methods() array * of a method which is common to both sites; or 'aes256cbc' if no matches are found. */ - function zot_best_algorithm($methods) { - $x = [ 'methods' => $methods, 'result' => '' ]; - call_hooks('zot_best_algorithm',$x); + $x = [ + 'methods' => $methods, + 'result' => '' + ]; + /** + * @hooks zot_best_algorithm + * Called when negotiating crypto algorithms with remote sites. + * * \e string \b methods - comma separated list of encryption methods + * * \e string \b result - the algorithm to return + */ + call_hooks('zot_best_algorithm', $x); + if($x['result']) return $x['result']; if($methods) { - $x = explode(',',$methods); + $x = explode(',', $methods); if($x) { $y = crypto_methods(); if($y) { foreach($y as $yv) { $yv = trim($yv); - if(in_array($yv,$x)) { + if(in_array($yv, $x)) { return($yv); } } @@ -193,7 +202,6 @@ function zot_best_algorithm($methods) { } - /** * @brief * @@ -210,7 +218,7 @@ function zot_zot($url, $data) { /** * @brief Refreshes after permission changed or friending, etc. * - * The top half of this function is similar to \Zotlabs\Zot\Finger::run() and could potentially be + * The top half of this function is similar to \\Zotlabs\\Zot\\Finger::run() and could potentially be * consolidated. * * zot_refresh is typically invoked when somebody has changed permissions of a channel and they are notified @@ -230,21 +238,22 @@ function zot_zot($url, $data) { * * @param array $them => xchan structure of sender * @param array $channel => local channel structure of target recipient, required for "friending" operations - * @param array $force default false + * @param array $force (optional) default false * - * @returns boolean true if successful, else false + * @return boolean + * * \b true if successful + * * otherwise \b false */ - function zot_refresh($them, $channel = null, $force = false) { if (array_key_exists('xchan_network', $them) && ($them['xchan_network'] !== 'zot')) { - logger('zot_refresh: not got zot. ' . $them['xchan_name']); + logger('not got zot. ' . $them['xchan_name']); return true; } - logger('zot_refresh: them: ' . print_r($them,true), LOGGER_DATA, LOG_DEBUG); + logger('them: ' . print_r($them,true), LOGGER_DATA, LOG_DEBUG); if ($channel) - logger('zot_refresh: channel: ' . print_r($channel,true), LOGGER_DATA, LOG_DEBUG); + logger('channel: ' . print_r($channel,true), LOGGER_DATA, LOG_DEBUG); $url = null; @@ -315,7 +324,6 @@ function zot_refresh($them, $channel = null, $force = false) { && array_key_exists('xchan_guid_sig',$them) && $them['xchan_guid_sig']) { $postvars['guid'] = $them['xchan_guid']; $postvars['guid_sig'] = $them['xchan_guid_sig']; - } $rhs = '/.well-known/zot-info'; @@ -330,7 +338,7 @@ function zot_refresh($them, $channel = null, $force = false) { $j = json_decode($result['body'],true); if (! (($j) && ($j['success']))) { - logger('zot_refresh: result not decodable'); + logger('Result not decodable'); return false; } @@ -484,7 +492,7 @@ function zot_refresh($them, $channel = null, $force = false) { } - /** If there is a default group for this channel, add this connection to it */ + // If there is a default group for this channel, add this connection to it $default_group = $channel['channel_default_group']; if($default_group) { @@ -528,10 +536,10 @@ function zot_refresh($them, $channel = null, $force = false) { * * \e string \b url_sig => URL signed with conversant's private key * @param boolean $multiple (optional) default false * - * @returns array|null null if site is blacklisted or not found, otherwise an - * array with an hubloc record + * @return array|null + * * null if site is blacklisted or not found + * * otherwise an array with an hubloc record */ - function zot_gethub($arr, $multiple = false) { if($arr['guid'] && $arr['guid_sig'] && $arr['url'] && $arr['url_sig']) { @@ -554,11 +562,11 @@ function zot_gethub($arr, $multiple = false) { dbesc($arr['url_sig']) ); if($r) { - logger('zot_gethub: found', LOGGER_DEBUG); + logger('Found', LOGGER_DEBUG); return (($multiple) ? $r : $r[0]); } } - logger('zot_gethub: not found: ' . print_r($arr,true), LOGGER_DEBUG); + logger('Not found: ' . print_r($arr,true), LOGGER_DEBUG); return false; } @@ -577,11 +585,10 @@ function zot_gethub($arr, $multiple = false) { * * \e string \b url => URL of the origination hub of this communication * * \e string \b url_sig => URL signed with conversant's private key * - * @returns array an associative array with + * @return array An associative array with * * \b success boolean true or false * * \b message (optional) error string only if success is false */ - function zot_register_hub($arr) { $result = [ 'success' => false ]; @@ -619,7 +626,7 @@ function zot_register_hub($arr) { $result['success'] = true; } else { - logger('zot_register_hub: failure to verify returned packet using ' . $method); + logger('Failure to verify returned packet using ' . $method); } } } @@ -642,13 +649,17 @@ function zot_register_hub($arr) { * If set [typically by update_directory_entry()] indicates a specific update table row and more particularly * contains a particular address (ud_addr) which needs to be updated in that table. * - * @return associative array + * @return array An associative array with: * * \e boolean \b success boolean true or false * * \e string \b message (optional) error string only if success is false */ +function import_xchan($arr, $ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { -function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { - + /** + * @hooks import_xchan + * Called when processing the result of zot_finger() to store the result + * * \e array + */ call_hooks('import_xchan', $arr); $ret = array('success' => false); @@ -658,13 +669,13 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { $what = ''; if(! (is_array($arr) && array_key_exists('success',$arr) && $arr['success'])) { - logger('import_xchan: invalid data packet: ' . print_r($arr,true)); + logger('Invalid data packet: ' . print_r($arr,true)); $ret['message'] = t('Invalid data packet'); return $ret; } if(! ($arr['guid'] && $arr['guid_sig'])) { - logger('import_xchan: no identity information provided. ' . print_r($arr,true)); + logger('No identity information provided. ' . print_r($arr,true)); return $ret; } @@ -678,7 +689,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { foreach($sig_methods as $method) { if(! rsa_verify($arr['guid'],base64url_decode($arr['guid_sig']),$arr['key'],$method)) { - logger('import_xchan: Unable to verify channel signature for ' . $arr['address'] . ' using ' . $method); + logger('Unable to verify channel signature for ' . $arr['address'] . ' using ' . $method); continue; } else { @@ -761,8 +772,8 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { dbesc($xchan_hash) ); - logger('import_xchan: update: existing: ' . print_r($r[0],true), LOGGER_DATA, LOG_DEBUG); - logger('import_xchan: update: new: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG); + logger('Update: existing: ' . print_r($r[0],true), LOGGER_DATA, LOG_DEBUG); + logger('Update: new: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG); $what .= 'xchan '; $changed = true; } @@ -777,7 +788,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { $x = xchan_store_lowlevel( [ - 'xchan_hash' => $xchan_hash, + 'xchan_hash' => $xchan_hash, 'xchan_guid' => $arr['guid'], 'xchan_guid_sig' => $arr['guid_sig'], 'xchan_pubkey' => $arr['key'], @@ -928,7 +939,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { } } else { - logger('import_xchan: profile not available - hiding'); + logger('Profile not available - hiding'); // they may have made it private $r = q("delete from xprof where xprof_hash = '%s'", dbesc($xchan_hash) @@ -950,7 +961,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { if(($changed) || ($ud_flags == UPDATE_FLAGS_FORCED)) { $guid = random_string() . '@' . App::get_hostname(); update_modtime($xchan_hash,$guid,$address,$ud_flags); - logger('import_xchan: changed: ' . $what,LOGGER_DEBUG); + logger('Changed: ' . $what,LOGGER_DEBUG); } elseif(! $ud_flags) { // nothing changed but we still need to update the updates record @@ -966,7 +977,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { $ret['hash'] = $xchan_hash; } - logger('import_xchan: result: ' . print_r($ret,true), LOGGER_DATA, LOG_DEBUG); + logger('Result: ' . print_r($ret,true), LOGGER_DATA, LOG_DEBUG); return $ret; } @@ -980,19 +991,18 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { * @param array $arr - output of z_post_url() * @param array $outq - The queue structure attached to this request */ - function zot_process_response($hub, $arr, $outq) { if(! $arr['success']) { - logger('zot_process_response: failed: ' . $hub); + logger('Failed: ' . $hub); return; } $x = json_decode($arr['body'], true); if(! $x) { - logger('zot_process_response: No json from ' . $hub); - logger('zot_process_response: headers: ' . print_r($arr['header'],true), LOGGER_DATA, LOG_DEBUG); + logger('No json from ' . $hub); + logger('Headers: ' . print_r($arr['header'], true), LOGGER_DATA, LOG_DEBUG); } if(is_array($x) && array_key_exists('delivery_report',$x) && is_array($x['delivery_report'])) { @@ -1000,7 +1010,7 @@ function zot_process_response($hub, $arr, $outq) { if(array_key_exists('iv',$x['delivery_report'])) { $j = crypto_unencapsulate($x['delivery_report'],get_config('system','prvkey')); if($j) { - $x['delivery_report'] = json_decode($j,true); + $x['delivery_report'] = json_decode($j,true); } if(! (is_array($x['delivery_report']) && count($x['delivery_report']))) { logger('encrypted delivery report could not be decrypted'); @@ -1060,7 +1070,6 @@ function zot_process_response($hub, $arr, $outq) { * decrypted and json decoded notify packet from remote site * @return array from zot_import() */ - function zot_fetch($arr) { logger('zot_fetch: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG); @@ -1073,7 +1082,7 @@ function zot_fetch($arr) { $ret_hubs = zot_gethub($arr['sender'],true); if(! $ret_hubs) { - logger('zot_fetch: no hub: ' . print_r($arr['sender'],true)); + logger('No hub: ' . print_r($arr['sender'],true)); return; } @@ -1105,7 +1114,6 @@ function zot_fetch($arr) { } return; - } /** @@ -1114,7 +1122,7 @@ function zot_fetch($arr) { * Process an incoming array of messages which were obtained via pickup, and * import, update, delete as directed. * - * The message types handled here are 'activity' (e.g. posts), 'mail' , + * The message types handled here are 'activity' (e.g. posts), 'mail', * 'profile', 'location' and 'channel_sync'. * * @param array $arr @@ -1126,18 +1134,17 @@ function zot_fetch($arr) { * currently processing. * * @returns array - * suitable for logging remotely, enumerating the processing results of each message/recipient combination - * * [0] => \e string $channel_hash - * * [1] => \e string $delivery_status - * * [2] => \e string $address + * Suitable for logging remotely, enumerating the processing results of each message/recipient combination + * * [0] => \e string $channel_hash + * * [1] => \e string $delivery_status + * * [2] => \e string $address */ - function zot_import($arr, $sender_url) { $data = json_decode($arr['body'], true); if(! $data) { - logger('zot_import: empty body'); + logger('Empty body'); return array(); } @@ -1173,7 +1180,7 @@ function zot_import($arr, $sender_url) { $i['notify'] = json_decode(crypto_unencapsulate($i['notify'],get_config('system','prvkey')),true); } - logger('zot_import: notify: ' . print_r($i['notify'],true), LOGGER_DATA, LOG_DEBUG); + logger('Notify: ' . print_r($i['notify'],true), LOGGER_DATA, LOG_DEBUG); if(! is_array($i['notify'])) { logger('decode error'); @@ -1183,7 +1190,7 @@ function zot_import($arr, $sender_url) { $hub = zot_gethub($i['notify']['sender']); if((! $hub) || ($hub['hubloc_url'] != $sender_url)) { - logger('zot_import: potential forgery: wrong site for sender: ' . $sender_url . ' != ' . print_r($i['notify'],true)); + logger('Potential forgery: wrong site for sender: ' . $sender_url . ' != ' . print_r($i['notify'],true)); continue; } @@ -1291,7 +1298,7 @@ function zot_import($arr, $sender_url) { } if(! $deliveries) { - logger('zot_import: no deliveries on this site'); + logger('No deliveries on this site'); continue; } @@ -1371,7 +1378,6 @@ function zot_import($arr, $sender_url) { * @param array $msg * @return NULL|array */ - function public_recips($msg) { require_once('include/channel.php'); @@ -1501,9 +1507,8 @@ function public_recips($msg) { } /** - * @brief + * @brief This is the second part of public_recips(). * - * This is the second part of public_recips(). * We'll find all the channels willing to accept public posts from us, then * match them against the sender privacy scope and see who in that list that * the sender is allowing. @@ -1583,7 +1588,6 @@ function allowed_public_recips($msg) { * @param boolean $request (optional) default false * @return array */ - function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $request = false) { $result = array(); @@ -1594,12 +1598,11 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ if(! $public) { if($sender['hash'] != $arr['owner_xchan'] && $sender['hash'] != $arr['author_xchan']) { - logger("process_delivery: sender {$sender['hash']} is not owner {$arr['owner_xchan']} or author {$arr['author_xchan']} - mid {$arr['mid']}"); + logger("Sender {$sender['hash']} is not owner {$arr['owner_xchan']} or author {$arr['author_xchan']} - mid {$arr['mid']}"); return; } } - foreach($deliveries as $d) { $local_public = $public; @@ -1828,7 +1831,6 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ $DR->update('update ignored'); $result[] = $DR->get(); - // We need this line to ensure wall-to-wall comments are relayed (by falling through to the relay bit), // and at the same time not relay any other relayable posts more than once, because to do so is very wasteful. if(! intval($r[0]['item_origin'])) @@ -1842,8 +1844,14 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ // if it's a sourced post, call the post_local hooks as if it were // posted locally so that crosspost connectors will be triggered. - if(check_item_source($arr['uid'], $arr)) + if(check_item_source($arr['uid'], $arr)) { + /** + * @hooks post_local + * Called when an item has been posted on this machine via mod/item.php (also via API). + * * \e array with an item + */ call_hooks('post_local', $arr); + } $item_id = 0; @@ -1855,8 +1863,21 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ $item_result = item_store($arr); if($item_result['success']) { $item_id = $item_result['item_id']; - $parr = array('item_id' => $item_id,'item' => $arr,'sender' => $sender,'channel' => $channel); - call_hooks('activity_received',$parr); + $parr = [ + 'item_id' => $item_id, + 'item' => $arr, + 'sender' => $sender, + 'channel' => $channel + ]; + /** + * @hooks activity_received + * Called when an activity (post, comment, like, etc.) has been received from a zot source. + * * \e int \b item_id + * * \e array \b item + * * \e array \b sender + * * \e array \b channel + */ + call_hooks('activity_received', $parr); // don't add a source route if it's a relay or later recipients will get a route mismatch if(! $relay) add_source_route($item_id,$sender['hash']); @@ -1875,7 +1896,7 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ } if($relay && $item_id) { - logger('process_delivery: invoking relay'); + logger('Invoking relay'); Zotlabs\Daemon\Master::Summon(array('Notifier','relay',intval($item_id))); $DR->addto_update('relayed'); $result[] = $DR->get(); @@ -1885,13 +1906,13 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ if(! $deliveries) $result[] = array('', 'no recipients', '', $arr['mid']); - logger('process_delivery: local results: ' . print_r($result, true), LOGGER_DEBUG); + logger('Local results: ' . print_r($result, true), LOGGER_DEBUG); return $result; } /** - * @brief + * @brief Remove community tag. * * @param array $sender an associative array with * * \e string \b hash a xchan_hash @@ -1901,7 +1922,6 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ * * \e int \b mid * @param int $uid */ - function remove_community_tag($sender, $arr, $uid) { if(! (activity_match($arr['verb'], ACTIVITY_TAG) && ($arr['obj_type'] == ACTIVITY_OBJ_TAGTERM))) @@ -1910,7 +1930,7 @@ function remove_community_tag($sender, $arr, $uid) { logger('remove_community_tag: invoked'); if(! get_pconfig($uid,'system','blocktags')) { - logger('remove_community tag: permission denied.'); + logger('Permission denied.'); return; } @@ -1919,12 +1939,12 @@ function remove_community_tag($sender, $arr, $uid) { intval($uid) ); if(! $r) { - logger('remove_community_tag: no item'); + logger('No item'); return; } if(($sender['hash'] != $r[0]['owner_xchan']) && ($sender['hash'] != $r[0]['author_xchan'])) { - logger('remove_community_tag: sender not authorised.'); + logger('Sender not authorised.'); return; } @@ -1936,7 +1956,7 @@ function remove_community_tag($sender, $arr, $uid) { $i['object'] = json_decode($i['object'],true); if(! ($i['target'] && $i['object'])) { - logger('remove_community_tag: no target/object'); + logger('No target/object'); return; } @@ -1947,7 +1967,7 @@ function remove_community_tag($sender, $arr, $uid) { intval($uid) ); if(! $r) { - logger('remove_community_tag: no parent message'); + logger('No parent message'); return; } @@ -1963,16 +1983,16 @@ function remove_community_tag($sender, $arr, $uid) { } /** - * @brief Just calls item_store_update() and logs result. + * @brief Updates an imported item. * * @see item_store_update() * - * @param array $sender (unused) + * @param array $sender * @param array $item * @param array $orig * @param int $uid + * @param boolean $tag_delivery */ - function update_imported_item($sender, $item, $orig, $uid, $tag_delivery) { // If this is a comment being updated, remove any privacy information @@ -1986,10 +2006,11 @@ function update_imported_item($sender, $item, $orig, $uid, $tag_delivery) { unset($item['item_private']); } - // we need the tag_delivery check for downstream flowing posts as the stored post - // may have a different owner than the one being transmitted. + // we need the tag_delivery check for downstream flowing posts as the stored post + // may have a different owner than the one being transmitted. if(($sender['hash'] != $orig['owner_xchan'] && $sender['hash'] != $orig['author_xchan']) && (! $tag_delivery)) { + /// @fixme shouldn't this be logger? notice('sender is not owner or author'); return; } @@ -2024,10 +2045,9 @@ function update_imported_item($sender, $item, $orig, $uid, $tag_delivery) { * @param boolean $relay * @return boolean|int post_id */ - function delete_imported_item($sender, $item, $uid, $relay) { - logger('delete_imported_item invoked', LOGGER_DEBUG); + logger('invoked', LOGGER_DEBUG); $ownership_valid = false; $item_found = false; @@ -2186,7 +2206,6 @@ function process_mail_delivery($sender, $arr, $deliveries) { * * \e string \b hash a xchan_hash * @param array $arr */ - function process_rating_delivery($sender, $arr) { logger('process_rating_delivery: ' . print_r($arr,true)); @@ -2246,7 +2265,6 @@ function process_rating_delivery($sender, $arr) { * @param array $arr * @param array $deliveries (unused) */ - function process_profile_delivery($sender, $arr, $deliveries) { logger('process_profile_delivery', LOGGER_DEBUG); @@ -2258,7 +2276,16 @@ function process_profile_delivery($sender, $arr, $deliveries) { import_directory_profile($sender['hash'], $arr, $r[0]['xchan_addr'], UPDATE_FLAGS_UPDATED, 0); } -function process_location_delivery($sender,$arr,$deliveries) { + +/** + * @brief + * + * @param array $sender an associative array + * * \e string \b hash a xchan_hash + * @param array $arr + * @param array $deliveries (unused) deliveries is irrelevant + */ +function process_location_delivery($sender, $arr, $deliveries) { // deliveries is irrelevant logger('process_location_delivery', LOGGER_DEBUG); @@ -2271,7 +2298,7 @@ function process_location_delivery($sender,$arr,$deliveries) { if(array_key_exists('locations',$arr) && $arr['locations']) { $x = sync_locations($sender,$arr,true); - logger('process_location_delivery: results: ' . print_r($x,true), LOGGER_DEBUG); + logger('results: ' . print_r($x,true), LOGGER_DEBUG); if($x['changed']) { $guid = random_string() . '@' . App::get_hostname(); update_modtime($sender['hash'],$sender['guid'],$arr['locations'][0]['address'],UPDATE_FLAGS_UPDATED); @@ -2280,7 +2307,7 @@ function process_location_delivery($sender,$arr,$deliveries) { } /** - * @brief checks for a moved UNO channel and sets the channel_moved flag + * @brief Checks for a moved UNO channel and sets the channel_moved flag. * * Currently the effect of this flag is to turn the channel into 'read-only' mode. * New content will not be processed (there was still an issue with blocking the @@ -2294,11 +2321,11 @@ function process_location_delivery($sender,$arr,$deliveries) { * if a new location is reported and there is only one location record. * The rest of the hubloc syncronisation will be handled within * sync_locations + * + * @param string $sender_hash A channel hash + * @param array $locations */ - - - -function check_location_move($sender_hash,$locations) { +function check_location_move($sender_hash, $locations) { if(! $locations) return; @@ -2324,11 +2351,18 @@ function check_location_move($sender_hash,$locations) { // federation plugins may wish to notify connections // of the move on singleton networks - $arr = array('channel' => $r[0],'locations' => $locations); - call_hooks('location_move',$arr); - + $arr = [ + 'channel' => $r[0], + 'locations' => $locations + ]; + /** + * @hooks location_move + * Called when a new location has been provided to a UNO channel (indicating a move rather than a clone). + * * \e array \b channel + * * \e array \b locations + */ + call_hooks('location_move', $arr); } - } @@ -2340,7 +2374,6 @@ function check_location_move($sender_hash,$locations) { * @param boolean $absolute (optional) default false * @return array */ - function sync_locations($sender, $arr, $absolute = false) { $ret = array(); @@ -2350,7 +2383,6 @@ function sync_locations($sender, $arr, $absolute = false) { if($absolute) check_location_move($sender['hash'],$arr['locations']); - $xisting = q("select hubloc_id, hubloc_url, hubloc_sitekey from hubloc where hubloc_hash = '%s'", dbesc($sender['hash']) ); @@ -2372,7 +2404,7 @@ function sync_locations($sender, $arr, $absolute = false) { foreach($arr['locations'] as $location) { if(! rsa_verify($location['url'],base64url_decode($location['url_sig']),$sender['key'])) { - logger('sync_locations: Unable to verify site signature for ' . $location['url']); + logger('Unable to verify site signature for ' . $location['url']); $ret['message'] .= sprintf( t('Unable to verify site signature for %s'), $location['url']) . EOL; continue; } @@ -2385,7 +2417,7 @@ function sync_locations($sender, $arr, $absolute = false) { } if(! $location['sitekey']) { - logger('sync_locations: empty hubloc sitekey. ' . print_r($location,true)); + logger('Empty hubloc sitekey. ' . print_r($location,true)); continue; } @@ -2408,7 +2440,7 @@ function sync_locations($sender, $arr, $absolute = false) { dbesc($location['sitekey']) ); if($r) { - logger('sync_locations: hub exists: ' . $location['url'], LOGGER_DEBUG); + logger('Hub exists: ' . $location['url'], LOGGER_DEBUG); // update connection timestamp if this is the site we're talking to // This only happens when called from import_xchan @@ -2510,7 +2542,7 @@ function sync_locations($sender, $arr, $absolute = false) { dbesc($sender['hash']) ); } - logger('sync_locations: new hub: ' . $location['url']); + logger('New hub: ' . $location['url']); $r = hubloc_store_lowlevel( [ @@ -2548,7 +2580,7 @@ function sync_locations($sender, $arr, $absolute = false) { if($absolute && $xisting) { foreach($xisting as $x) { if(! array_key_exists('updated',$x)) { - logger('sync_locations: deleting unreferenced hub location ' . $x['hubloc_addr']); + logger('Deleting unreferenced hub location ' . $x['hubloc_addr']); $r = q("update hubloc set hubloc_deleted = 1, hubloc_updated = '%s' where hubloc_id = %d", dbesc(datetime_convert()), intval($x['hubloc_id']) @@ -2613,11 +2645,10 @@ function zot_encode_locations($channel) { * @param string $hash * @param array $profile * @param string $addr - * @param number $ud_flags - * @param number $suppress_update default 0 + * @param number $ud_flags (optional) UPDATE_FLAGS_UPDATED + * @param number $suppress_update (optional) default 0 * @return boolean $updated if something changed */ - function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLAGS_UPDATED, $suppress_update = 0) { logger('import_directory_profile', LOGGER_DEBUG); @@ -2717,7 +2748,7 @@ function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLA } } else { $update = true; - logger('import_directory_profile: new profile '); + logger('New profile'); q("insert into xprof (xprof_hash, xprof_desc, xprof_dob, xprof_age, xprof_gender, xprof_marital, xprof_sexual, xprof_locale, xprof_region, xprof_postcode, xprof_country, xprof_about, xprof_homepage, xprof_hometown, xprof_keywords) values ('%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ", dbesc($arr['xprof_hash']), dbesc($arr['xprof_desc']), @@ -2737,7 +2768,18 @@ function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLA ); } - $d = array('xprof' => $arr, 'profile' => $profile, 'update' => $update); + $d = [ + 'xprof' => $arr, + 'profile' => $profile, + 'update' => $update + ]; + /** + * @hooks import_directory_profile + * Called when processing delivery of a profile structure from an external source (usually for directory storage). + * * \e array \b xprof + * * \e array \b profile + * * \e boolean \b update + */ call_hooks('import_directory_profile', $d); if (($d['update']) && (! $suppress_update)) @@ -2749,10 +2791,9 @@ function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLA /** * @brief * - * @param string $hash + * @param string $hash An xtag_hash * @param array $keywords */ - function import_directory_keywords($hash, $keywords) { $existing = array(); @@ -2797,7 +2838,6 @@ function import_directory_keywords($hash, $keywords) { * @param string $addr * @param int $flags (optional) default 0 */ - function update_modtime($hash, $guid, $addr, $flags = 0) { $dirmode = intval(get_config('system', 'directory_mode')); @@ -2830,13 +2870,12 @@ function update_modtime($hash, $guid, $addr, $flags = 0) { * @param string $pubkey * @return boolean true if updated or inserted */ - function import_site($arr, $pubkey) { if( (! is_array($arr)) || (! $arr['url']) || (! $arr['url_sig'])) return false; if(! rsa_verify($arr['url'], base64url_decode($arr['url_sig']), $pubkey)) { - logger('import_site: bad url_sig'); + logger('Bad url_sig'); return false; } @@ -2915,7 +2954,7 @@ function import_site($arr, $pubkey) { if(array_key_exists('zot',$arr)) { set_sconfig($arr['url'],'system','zot_version',$arr['zot']); - } + } if($exists) { if(($siterecord['site_flags'] != $site_flags) @@ -2934,7 +2973,6 @@ function import_site($arr, $pubkey) { // logger('import_site: input: ' . print_r($arr,true)); // logger('import_site: stored: ' . print_r($siterecord,true)); - $r = q("update site set site_dead = 0, site_location = '%s', site_flags = %d, site_access = %d, site_directory = '%s', site_register = %d, site_update = '%s', site_sellpage = '%s', site_realm = '%s', site_type = %d, site_project = '%s', site_version = '%s', site_crypto = '%s' where site_url = '%s'", dbesc($site_location), @@ -2952,7 +2990,7 @@ function import_site($arr, $pubkey) { dbesc($url) ); if(! $r) { - logger('import_site: update failed. ' . print_r($arr,true)); + logger('Update failed. ' . print_r($arr,true)); } } else { @@ -2966,7 +3004,7 @@ function import_site($arr, $pubkey) { else { $update = true; - $r = site_store_lowlevel( + $r = site_store_lowlevel( [ 'site_location' => $site_location, 'site_url' => $url, @@ -2985,7 +3023,7 @@ function import_site($arr, $pubkey) { ); if(! $r) { - logger('import_site: record create failed. ' . print_r($arr,true)); + logger('Record create failed. ' . print_r($arr,true)); } } @@ -2994,20 +3032,19 @@ function import_site($arr, $pubkey) { /** + * @brief Builds and sends a sync packet. + * * Send a zot packet to all hubs where this channel is duplicated, refreshing * such things as personal settings, channel permissions, address book updates, etc. * - * @param int $uid + * @param int $uid (optional) default 0 * @param array $packet (optional) default null * @param boolean $groups_changed (optional) default false */ - function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { - logger('build_sync_packet'); - $keychange = (($packet && array_key_exists('keychange',$packet)) ? true : false); if($keychange) { logger('keychange sync'); @@ -3122,6 +3159,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { ); if($r) $info['collections'] = $r; + $r = q("select groups.hash as collection, group_member.xchan as member from groups left join group_member on groups.id = group_member.gid where group_member.uid = %d", intval($uid) ); @@ -3132,7 +3170,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { $interval = ((get_config('system','delivery_interval') !== false) ? intval(get_config('system','delivery_interval')) : 2 ); - logger('build_sync_packet: packet: ' . print_r($info,true), LOGGER_DATA, LOG_DEBUG); + logger('Packet: ' . print_r($info,true), LOGGER_DATA, LOG_DEBUG); $total = count($synchubs); @@ -3173,7 +3211,6 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { * @param array $deliveries * @return array */ - function process_channel_sync_delivery($sender, $arr, $deliveries) { require_once('include/import.php'); @@ -3201,7 +3238,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { $max_feeds = account_service_class_fetch($channel['channel_account_id'],'total_feeds'); if($channel['channel_hash'] != $sender['hash']) { - logger('process_channel_sync_delivery: possible forgery. Sender ' . $sender['hash'] . ' is not ' . $channel['channel_hash']); + logger('Possible forgery. Sender ' . $sender['hash'] . ' is not ' . $channel['channel_hash']); $result[] = array($d['hash'],'channel mismatch',$channel['channel_name'],''); continue; } @@ -3217,7 +3254,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { $hash = make_xchan_hash($channel['channel_guid'],$sig); - $r = q("update channel set channel_prvkey = '%s', channel_pubkey = '%s', channel_guid_sig = '%s', + $r = q("update channel set channel_prvkey = '%s', channel_pubkey = '%s', channel_guid_sig = '%s', channel_hash = '%s' where channel_id = %d", dbesc($arr['channel']['channel_prvkey']), dbesc($arr['channel']['channel_pubkey']), @@ -3360,7 +3397,6 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { $arr['channel']['channel_pageflags'] = $arr['channel']['channel_pageflags'] - 0x8000; if($arr['channel']['channel_pageflags'] & 0x1000) $arr['channel']['channel_pageflags'] = $arr['channel']['channel_pageflags'] - 0x1000; - } $disallowed = [ @@ -3426,7 +3462,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { $clean = array(); if($abook['abook_xchan'] && $abook['entry_deleted']) { - logger('process_channel_sync_delivery: removing abook entry for ' . $abook['abook_xchan']); + logger('Removing abook entry for ' . $abook['abook_xchan']); $r = q("select abook_id, abook_feed from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1", dbesc($abook['abook_xchan']), @@ -3451,7 +3487,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { if(! $h) { $xhash = import_author_xchan(encode_item_xchan($abook)); if(! $xhash) { - logger('process_channel_sync_delivery: import of ' . $abook['xchan_addr'] . ' failed.'); + logger('Import of ' . $abook['xchan_addr'] . ' failed.'); continue; } } @@ -3468,7 +3504,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { if(array_key_exists('abook_instance',$clean) && $clean['abook_instance'] && strpos($clean['abook_instance'],z_root()) === false) { $clean['abook_not_here'] = 1; - } + } $r = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1", @@ -3480,11 +3516,11 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { if(! $r) { if($max_friends !== false && $total_friends > $max_friends) { - logger('process_channel_sync_delivery: total_channels service class limit exceeded'); + logger('total_channels service class limit exceeded'); continue; } if($max_feeds !== false && intval($clean['abook_feed']) && $total_feeds > $max_feeds) { - logger('process_channel_sync_delivery: total_feeds service class limit exceeded'); + logger('total_feeds service class limit exceeded'); continue; } abook_store_lowlevel( @@ -3503,6 +3539,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { foreach($clean as $k => $v) { if($k == 'abook_dob') $v = dbescdate($v); + $r = dbq("UPDATE abook set " . dbesc($k) . " = '" . dbesc($v) . "' where abook_xchan = '" . dbesc($clean['abook_xchan']) . "' and abook_channel = " . intval($channel['channel_id'])); } @@ -3515,7 +3552,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { translate_abook_perms_inbound($channel,$abook); if($abconfig) { - // @fixme does not handle sync of del_abconfig + /// @fixme does not handle sync of del_abconfig foreach($abconfig as $abc) { set_abconfig($channel['channel_id'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']); } @@ -3712,15 +3749,21 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { if(count($clean)) { foreach($clean as $k => $v) { $r = dbq("UPDATE profile set " . TQUOT . dbesc($k) . TQUOT . " = '" . dbesc($v) - . "' where profile_guid = '" . dbesc($profile['profile_guid']) + . "' where profile_guid = '" . dbesc($profile['profile_guid']) . "' and uid = " . intval($channel['channel_id'])); } } } } - $addon = array('channel' => $channel,'data' => $arr); - call_hooks('process_channel_sync_delivery',$addon); + $addon = ['channel' => $channel, 'data' => $arr]; + /** + * @hooks process_channel_sync_delivery + * Called when accepting delivery of a 'sync packet' containing structure and table updates from a channel clone. + * * \e array \b channel + * * \e array \b data + */ + call_hooks('process_channel_sync_delivery', $addon); // we should probably do this for all items, but usually we only send one. @@ -3732,7 +3775,6 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { $DR = new Zotlabs\Zot\DReport(z_root(),$d['hash'],$d['hash'],'sync packet','channel sync delivered'); $result[] = $DR->get(); - } return $result; @@ -3747,7 +3789,6 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { * * \e string \b xchan_url * @return string */ - function get_rpost_path($observer) { if(! $observer) return ''; @@ -3763,7 +3804,6 @@ function get_rpost_path($observer) { * @param array $x * @return boolean|string return false or a hash */ - function import_author_zot($x) { // Check that we have both a hubloc and xchan record - as occasionally storage calls will fail and @@ -3797,7 +3837,7 @@ function import_author_zot($x) { $site_dead = true; } - // We have valid and somewhat fresh information. + // We have valid and somewhat fresh information. if($r1 && $r2 && $r1[0]['hubloc_updated'] > datetime_convert('UTC','UTC','now - 1 week')) { logger('in cache', LOGGER_DEBUG); @@ -3806,16 +3846,16 @@ function import_author_zot($x) { logger('not in cache or cache stale - probing: ' . print_r($x,true), LOGGER_DEBUG,LOG_INFO); - // The primary hub may be dead. Try to find another one associated with this identity that is - // still alive. If we find one, use that url for the discovery/refresh probe. Otherwise, the dead site - // is all we have and there is no point probing it. Just return the hash indicating we have a - // cached entry and the identity is valid. It's just unreachable until they bring back their - // server from the grave or create another clone elsewhere. + // The primary hub may be dead. Try to find another one associated with this identity that is + // still alive. If we find one, use that url for the discovery/refresh probe. Otherwise, the dead site + // is all we have and there is no point probing it. Just return the hash indicating we have a + // cached entry and the identity is valid. It's just unreachable until they bring back their + // server from the grave or create another clone elsewhere. if($site_dead) { logger('dead site - ignoring', LOGGER_DEBUG,LOG_INFO); - $r = q("select hubloc_url from hubloc left join site on hubloc_url = site_url + $r = q("select hubloc_url from hubloc left join site on hubloc_url = site_url where hubloc_hash = '%s' and site_dead = 0", dbesc($hash) ); @@ -3826,8 +3866,7 @@ function import_author_zot($x) { else { return $hash; } - } - + } $them = array('hubloc_url' => $desturl, 'xchan_guid' => $x['guid'], 'xchan_guid_sig' => $x['guid_sig']); @@ -3854,7 +3893,6 @@ function import_author_zot($x) { * @param array $data * @return array */ - function zot_reply_message_request($data) { $ret = array('success' => false); @@ -3950,9 +3988,9 @@ function zot_rekey_request($sender,$data) { // newsig is newkey signed with oldkey // The original xchan will remain. In Zot/Receiver we will have imported the new xchan and hubloc to verify - // the packet authenticity. What we will do now is verify that the keychange operation was signed by the - // oldkey, and if so change all the abook, abconfig, group, and permission elements which reference the - // old xchan_hash. + // the packet authenticity. What we will do now is verify that the keychange operation was signed by the + // oldkey, and if so change all the abook, abconfig, group, and permission elements which reference the + // old xchan_hash. if((! $data['old_key']) && (! $data['new_key']) && (! $data['new_sig'])) json_return_and_die($ret); @@ -4075,10 +4113,18 @@ function zotinfo($arr) { $id = $e['channel_id']; - $x = [ 'channel_id' => $id, 'protocols' => ['zot'] ]; - call_hooks('channel_protocols',$x); - $protocols = $x['protocols']; + $x = [ + 'channel_id' => $id, + 'protocols' => ['zot'] + ]; + /** + * @hooks channel_protocols + * * \e int \b channel_id + * * \e array \b protocols + */ + call_hooks('channel_protocols', $x); + $protocols = $x['protocols']; $sys_channel = (intval($e['channel_system']) ? true : false); $special_channel = (($e['channel_pageflags'] & PAGE_PREMIUM) ? true : false); @@ -4131,6 +4177,7 @@ function zotinfo($arr) { if($age = age($p[0]['dob'],$e['channel_timezone'],'')) $profile['age'] = $age; + $profile['gender'] = $p[0]['gender']; $profile['marital'] = $p[0]['marital']; $profile['sexual'] = $p[0]['sexual']; @@ -4190,7 +4237,6 @@ function zotinfo($arr) { $ret['deleted_locally'] = true; - // premium or other channel desiring some contact with potential followers before connecting. // This is a template - %s will be replaced with the follow_url we discover for the return channel. @@ -4234,10 +4280,14 @@ function zotinfo($arr) { check_zotinfo($e,$x,$ret); + /** + * @hooks zot_finger + * Called when a zot-info packet has been requested (this is our webfinger discovery mechanism). + * * \e array The final return array + */ + call_hooks('zot_finger', $ret); - call_hooks('zot_finger',$ret); return($ret); - } @@ -4328,11 +4378,17 @@ function zot_site_info($channel_key = '') { } return $ret['site']; - } -function check_zotinfo($channel,$locations,&$ret) { - +/** + * @brief + * + * @param array $channel + * @param array $locations + * @param[out] array $ret + * \e array \b locations result of zot_encode_locations() + */ +function check_zotinfo($channel, $locations, &$ret) { // logger('locations: ' . print_r($locations,true),LOGGER_DATA, LOG_DEBUG); @@ -4340,7 +4396,7 @@ function check_zotinfo($channel,$locations,&$ret) { // 1. Because magic-auth is reliant on it, ensure that the system channel has a valid hubloc // Force this to be the case if anything is found to be wrong with it. - // @FIXME ensure that the system channel exists in the first place and has an xchan + /// @FIXME ensure that the system channel exists in the first place and has an xchan if($channel['channel_system']) { // the sys channel must have a location (hubloc) @@ -4395,12 +4451,23 @@ function check_zotinfo($channel,$locations,&$ret) { } } +/** + * @brief + * + * @param array $dr + * @return boolean + */ function delivery_report_is_storable($dr) { - if(get_config('system','disable_dreport')) + if(get_config('system', 'disable_dreport')) return false; - call_hooks('dreport_is_storable',$dr); + /** + * @hooks dreport_is_storable + * Called before storing a dreport record to determine whether to store it. + * * \e array + */ + call_hooks('dreport_is_storable', $dr); // let plugins accept or reject - if neither, continue on if(array_key_exists('accept',$dr) && intval($dr['accept'])) @@ -4455,12 +4522,18 @@ function delivery_report_is_storable($dr) { return true; return false; - } - -function update_hub_connected($hub,$sitekey = '') { +/** + * @brief + * + * @param array $hub + * @param string $sitekey (optional, default empty) + * + * @return string hubloc_url + */ +function update_hub_connected($hub, $sitekey = '') { if($sitekey) { @@ -4489,7 +4562,7 @@ function update_hub_connected($hub,$sitekey = '') { // Update our DB to show when we last communicated successfully with this hub // This will allow us to prune dead hubs from using up resources - $t = datetime_convert('UTC','UTC','now - 15 minutes'); + $t = datetime_convert('UTC', 'UTC', 'now - 15 minutes'); $r = q("update hubloc set hubloc_connected = '%s' where hubloc_id = %d and hubloc_sitekey = '%s' and hubloc_connected < '%s' ", dbesc(datetime_convert()), @@ -4519,14 +4592,18 @@ function update_hub_connected($hub,$sitekey = '') { return $hub['hubloc_url']; } - +/** + * @brief Useful to get a health check on a remote site. + * + * This will let us know if any important communication details + * that we may have stored are no longer valid, regardless of xchan details. + * + * @return json_return_and_die() + */ function zot_reply_ping() { $ret = array('success'=> false); - // Useful to get a health check on a remote site. - // This will let us know if any important communication details - // that we may have stored are no longer valid, regardless of xchan details. logger('POST: got ping send pong now back: ' . z_root() , LOGGER_DEBUG ); $ret['success'] = true; @@ -4534,6 +4611,7 @@ function zot_reply_ping() { $ret['site']['url'] = z_root(); $ret['site']['url_sig'] = base64url_encode(rsa_sign(z_root(),get_config('system','prvkey'))); $ret['site']['sitekey'] = get_config('system','pubkey'); + json_return_and_die($ret); } @@ -4551,6 +4629,7 @@ function zot_reply_pickup($data) { if((! $data['secret']) || (! $data['secret_sig'])) { $ret['message'] = 'no verification signature'; logger('mod_zot: pickup: ' . $ret['message'], LOGGER_DEBUG); + json_return_and_die($ret); } @@ -4561,6 +4640,7 @@ function zot_reply_pickup($data) { if(! $r) { $ret['message'] = 'site not found'; logger('mod_zot: pickup: ' . $ret['message']); + json_return_and_die($ret); } @@ -4590,12 +4670,14 @@ function zot_reply_pickup($data) { if($forgery) { $ret['message'] = 'possible site forgery'; logger('mod_zot: pickup: ' . $ret['message']); + json_return_and_die($ret); } if($secret_fail) { $ret['message'] = 'secret validation failed'; logger('mod_zot: pickup: ' . $ret['message']); + json_return_and_die($ret); } @@ -4612,6 +4694,7 @@ function zot_reply_pickup($data) { if(! $r) { $ret['message'] = 'nothing to pick up'; logger('mod_zot: pickup: ' . $ret['message']); + json_return_and_die($ret); } @@ -4657,8 +4740,8 @@ function zot_reply_pickup($data) { $algorithm = zot_best_algorithm(($x) ? $x[0]['site_crypto'] : ''); $encrypted = crypto_encapsulate(json_encode($ret),$sitekey,$algorithm); - json_return_and_die($encrypted); + json_return_and_die($encrypted); /* pickup: end */ } @@ -4686,6 +4769,7 @@ function zot_reply_auth_check($data,$encrypted_packet) { if (! $encrypted_packet) { logger('mod_zot: auth_check packet was not encrypted.'); $ret['message'] .= 'no packet encryption' . EOL; + json_return_and_die($ret); } @@ -4694,11 +4778,12 @@ function zot_reply_auth_check($data,$encrypted_packet) { // garbage collect any old unused notifications - // This was and should be 10 minutes but my hosting provider has time lag between the DB and - // the web server. We should probably convert this to webserver time rather than DB time so - // that the different clocks won't affect it and allow us to keep the time short. - - Zotlabs\Zot\Verify::purge('auth','30 MINUTE'); + /** + * @TODO This was and should be 10 minutes but my hosting provider has time lag between the DB and + * the web server. We should probably convert this to webserver time rather than DB time so + * that the different clocks won't affect it and allow us to keep the time short. + */ + Zotlabs\Zot\Verify::purge('auth', '30 MINUTE'); $y = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1", dbesc($sender_hash) @@ -4712,6 +4797,7 @@ function zot_reply_auth_check($data,$encrypted_packet) { if ((! $y) || (! rsa_verify($data['secret'], base64url_decode($data['secret_sig']),$y[0]['xchan_pubkey']))) { logger('mod_zot: auth_check: sender not found or secret_sig invalid.'); $ret['message'] .= 'sender not found or sig invalid ' . print_r($y,true) . EOL; + json_return_and_die($ret); } @@ -4729,6 +4815,7 @@ function zot_reply_auth_check($data,$encrypted_packet) { if (! $c) { logger('mod_zot: auth_check: recipient channel not found.'); $ret['message'] .= 'recipient not found.' . EOL; + json_return_and_die($ret); } @@ -4737,11 +4824,11 @@ function zot_reply_auth_check($data,$encrypted_packet) { // This additionally checks for forged sites since we already stored the expected result in meta // and we've already verified that this is them via zot_gethub() and that their key signed our token - $z = Zotlabs\Zot\Verify::match('auth',$c[0]['channel_id'],$data['secret'],$data['sender']['url']); if (! $z) { logger('mod_zot: auth_check: verification key not found.'); $ret['message'] .= 'verification key not found' . EOL; + json_return_and_die($ret); } @@ -4769,11 +4856,19 @@ function zot_reply_auth_check($data,$encrypted_packet) { json_return_and_die($ret); } + json_return_and_die($ret); } - -function zot_reply_purge($sender,$recipients) { +/** + * @brief + * + * @param array $sender + * @param array $recipients + * + * return json_return_and_die() + */ +function zot_reply_purge($sender, $recipients) { $ret = array('success' => false); @@ -4811,17 +4906,23 @@ function zot_reply_purge($sender,$recipients) { json_return_and_die($ret); } - -function zot_reply_refresh($sender,$recipients) { +/** + * @brief Remote channel info (such as permissions or photo or something) + * has been updated. Grab a fresh copy and sync it. + * + * The difference between refresh and force_refresh is that force_refresh + * unconditionally creates a directory update record, even if no changes were + * detected upon processing. + * + * @param array $sender + * @param array $recipients + * + * @return json_return_and_die() + */ +function zot_reply_refresh($sender, $recipients) { $ret = array('success' => false); - // remote channel info (such as permissions or photo or something) - // has been updated. Grab a fresh copy and sync it. - // The difference between refresh and force_refresh is that - // force_refresh unconditionally creates a directory update record, - // even if no changes were detected upon processing. - if($recipients) { // This would be a permissions update, typically for one connection @@ -4842,7 +4943,7 @@ function zot_reply_refresh($sender,$recipients) { } } else { - // system wide refresh + // system wide refresh $x = zot_refresh(array( 'xchan_guid' => $sender['guid'], @@ -4853,7 +4954,6 @@ function zot_reply_refresh($sender,$recipients) { $ret['success'] = true; json_return_and_die($ret); - } @@ -4876,5 +4976,4 @@ function zot_reply_notify($data) { $ret['success'] = true; json_return_and_die($ret); - } -- cgit v1.2.3 From 9abb061e7185a29cb85ebbad04deba715e1a6a06 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Fri, 3 Nov 2017 16:47:05 -0700 Subject: provide short localised summary for likes that will end up in displayed notifications --- include/conversation.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'include') diff --git a/include/conversation.php b/include/conversation.php index f395b2cbe..5ff8b3864 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -162,6 +162,18 @@ function localize_item(&$item){ elseif(activity_match($item['verb'],ACTIVITY_DISLIKE)) { $bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s'); } + + // short version, in notification strings the author will be displayed separately + + if(activity_match($item['verb'],ACTIVITY_LIKE)) { + $shortbodyverb = t('likes %1$s\'s %2$s'); + } + elseif(activity_match($item['verb'],ACTIVITY_DISLIKE)) { + $shortbodyverb = t('doesn\'t like %1$s\'s %2$s'); + } + + $item['shortlocalize'] = sprintf($bodyverb, $objauthor, $plink); + $item['body'] = $item['localize'] = sprintf($bodyverb, $author, $objauthor, $plink); if($Bphoto != "") $item['body'] .= "\n\n\n" . '[zrl=' . chanlink_url($author_link) . '][zmg=80x80]' . $Bphoto . '[/zmg][/zrl]'; -- cgit v1.2.3 From 6995d54a3cc162d87f881f6e206fa356230fd9e8 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 4 Nov 2017 10:48:24 +0100 Subject: fix wrong variable in sprintf resulting in php warning --- include/conversation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/conversation.php b/include/conversation.php index 5ff8b3864..2ce4dacef 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -172,7 +172,7 @@ function localize_item(&$item){ $shortbodyverb = t('doesn\'t like %1$s\'s %2$s'); } - $item['shortlocalize'] = sprintf($bodyverb, $objauthor, $plink); + $item['shortlocalize'] = sprintf($shortbodyverb, $objauthor, $plink); $item['body'] = $item['localize'] = sprintf($bodyverb, $author, $objauthor, $plink); if($Bphoto != "") -- cgit v1.2.3 From 0e1c628066a48ceb38a56a3b26e1a69e49bd218e Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sat, 4 Nov 2017 18:34:38 -0700 Subject: fix can_comment_on_post() after recent code cleanup (a required array parameter was missing) --- include/items.php | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/items.php b/include/items.php index 3934f6194..5d592c736 100755 --- a/include/items.php +++ b/include/items.php @@ -230,6 +230,7 @@ function can_comment_on_post($observer_xchan, $item) { $x = [ 'observer_hash' => $observer_xchan, 'item' => $item, + 'allowed' => 'unset' ]; /** * @hooks can_comment_on_post -- cgit v1.2.3 From 7efcb3c75f08c8d974f13cd8b5f32f14749d8b6e Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 5 Nov 2017 19:47:44 -0800 Subject: allow cloud filenames to include ampersands without messing up auth tokens (zid, owt, and zat, and the constant placeholder 'f=') --- include/zid.php | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/include/zid.php b/include/zid.php index 359b1721f..d1a0fa88a 100644 --- a/include/zid.php +++ b/include/zid.php @@ -103,25 +103,14 @@ function strip_zats($s) { return preg_replace('/[\?&]zat=(.*?)(&|$)/ism','$2',$s); } -function strip_auth_query_params() { - $_SERVER['QUERY_STRING'] = str_replace(array('?f=', '&f='), array('', ''), $_SERVER['QUERY_STRING']); - $_SERVER['QUERY_STRING'] = strip_zids($_SERVER['QUERY_STRING']); - $_SERVER['QUERY_STRING'] = strip_owt($_SERVER['QUERY_STRING']); - $_SERVER['REQUEST_URI'] = str_replace(array('?f=', '&f='), array('', ''), $_SERVER['REQUEST_URI']); - $_SERVER['REQUEST_URI'] = strip_zids($_SERVER['REQUEST_URI']); - $_SERVER['REQUEST_URI'] = strip_owt($_SERVER['REQUEST_URI']); - - - $_ENV['QUERY_STRING'] = str_replace(array('?f=', '&f='), array('', ''), $_ENV['QUERY_STRING']); - $_ENV['QUERY_STRING'] = strip_zids($_ENV['QUERY_STRING']); - $_ENV['QUERY_STRING'] = strip_owt($_ENV['QUERY_STRING']); - - $_ENV['REQUEST_URI'] = str_replace(array('?f=', '&f='), array('', ''), $_ENV['REQUEST_URI']); - $_ENV['REQUEST_URI'] = strip_zids($_ENV['REQUEST_URI']); - $_ENV['REQUEST_URI'] = strip_owt($_ENV['REQUEST_URI']); +function clean_query_string() { + $x = strip_zids(\App::$query_string); + $x = strip_owt($x); + $x = strip_zats($x); + return strip_query_param($x,'f'); } -- cgit v1.2.3 From 04d66ba7f499e138baf322cd08f973eb6e3f73c9 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 6 Nov 2017 00:17:46 -0800 Subject: attach.php minor cleanup and doc --- include/attach.php | 87 ++++++++++++++++-------------------------------------- 1 file changed, 26 insertions(+), 61 deletions(-) (limited to 'include') diff --git a/include/attach.php b/include/attach.php index bfe3d5d46..ab9a15ec2 100644 --- a/include/attach.php +++ b/include/attach.php @@ -2341,6 +2341,11 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) { } +/** + * Used to generate a select input box of all your folders + */ + + function attach_folder_select_list($channel_id) { $r = q("select * from attach where is_dir = 1 and uid = %d", @@ -2391,6 +2396,10 @@ function attach_folder_rpaths($all_folders,$that_folder) { return (($error) ? false : [ $current_hash , $path ]); } +/** + * @brief Given a channel_id and attach_hash, return an array with the full relative path and os_path + */ + function attach_syspaths($channel_id,$attach_hash) { @@ -2414,6 +2423,17 @@ function attach_syspaths($channel_id,$attach_hash) { return [ 'os_path' => $os_path, 'path' => $path ]; } +/** + * in earlier releases we did not fill in os_path and display_path in the attach DB structure. + * (It was not needed or used). Going forward we intend to make use of these fields. + * A cron task checks for empty values (as older attachments may have arrived at our site + * in a clone operation) and executes attach_syspaths() to generate these field values and correct + * the attach table entry. The operation is limited to 100 DB entries at a time so as not to + * overload the system in any cron run. Eventually it will catch up with old attach structures + * and switch into maintenance mode to correct any that might arrive in clone packets from older + * sites. + */ + function attach_upgrade() { @@ -2440,6 +2460,12 @@ function attach_upgrade() { } +/** + * Chunked uploader for integration with the blueimp jquery-uploader + * This is currently used. + */ + + function save_chunk($channel,$start,$end,$len) { $result = []; @@ -2478,64 +2504,3 @@ function save_chunk($channel,$start,$end,$len) { } -/** - * @brief Submit handler for chunked uploads. - * - * @param array $channel - * @param array $arr - * @return array - */ -function chunkloader($channel, $arr) { - - logger('request: ' . print_r($arr,true), LOGGER_DEBUG); - logger('files: ' . print_r($_FILES,true), LOGGER_DEBUG); - - $result = []; - - $tmp_path = $_FILES['file']['tmp_name']; - $new_base = 'store/[data]/' . $channel['channel_address'] . '/tmp'; - os_mkdir($new_base,STORAGE_DEFAULT_PERMISSIONS,true); - - $new_path = $new_base . '/' . $arr['resumableFilename']; - - rename($tmp_path,$new_path . '.' . intval($arr['resumableChunkNumber'])); - - $missing_parts = false; - for($x = 1; $x <= intval($arr['resumableTotalChunks']); $x ++) { - if(! file_exists($new_path . '.' . $x)) { - $missing_parts = true; - break; - } - } - - if($missing_parts) { - $result['partial'] = true; - return $result; - } - - if(intval($arr['resumableTotalChunks']) === 1) { - rename($new_path . '.' . '1', $new_path); - } - else { - for($x = 1; $x <= intval($arr['resumableTotalChunks']); $x ++) { - $istream = fopen($new_path . '.' . $x,'rb'); - $ostream = fopen($new_path,'ab'); - if($istream && $ostream) { - pipe_streams($istream,$ostream); - fclose($istream); - fclose($ostream); - } - unlink($new_path . '.' . $x); - } - } - - $result['name'] = $arr['resumableFilename']; - $result['type'] = $arr['resumableType']; - $result['tmp_name'] = $new_path; - $result['error'] = 0; - $result['size'] = $arr['resumableTotalSize']; - $result['complete'] = true; - - return $result; -} - -- cgit v1.2.3 From 94e548b07a129fc6a57c38b5d6799e86ca3d34ba Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 6 Nov 2017 11:25:49 +0100 Subject: lets try this in the wild for a while --- include/attach.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/attach.php b/include/attach.php index ab9a15ec2..179a57a90 100644 --- a/include/attach.php +++ b/include/attach.php @@ -947,9 +947,9 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { } if($notify) { - //$cloudPath = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['0']['display_path']; - //$object = get_file_activity_object($channel['channel_id'], $r['0']['hash'], $cloudPath); - //file_activity($channel['channel_id'], $object, $r['0']['allow_cid'], $r['0']['allow_gid'], $r['0']['deny_cid'], $r['0']['deny_gid'], 'post', $notify); + $cloudPath = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['0']['display_path']; + $object = get_file_activity_object($channel['channel_id'], $r['0']['hash'], $cloudPath); + file_activity($channel['channel_id'], $object, $r['0']['allow_cid'], $r['0']['allow_gid'], $r['0']['deny_cid'], $r['0']['deny_gid'], 'post', $notify); } return $ret; @@ -1421,7 +1421,7 @@ function attach_delete($channel_id, $resource, $is_photo = 0) { intval($channel_id) ); - file_activity($channel_id, $object, $object['allow_cid'], $object['allow_gid'], $object['deny_cid'], $object['deny_gid'], 'update', $notify=1); + file_activity($channel_id, $object, $object['allow_cid'], $object['allow_gid'], $object['deny_cid'], $object['deny_gid'], 'update', true); return; } -- cgit v1.2.3 From 549866c0900c1ff550e001323c59a74352920770 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Tue, 7 Nov 2017 10:43:13 +0100 Subject: add location info to the navbar --- include/nav.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/nav.php b/include/nav.php index af0ebbae2..42c42e881 100644 --- a/include/nav.php +++ b/include/nav.php @@ -27,6 +27,8 @@ function nav($template = 'default') { EOT; + $is_owner = (((local_channel()) && ((App::$profile_uid == local_channel()) || (App::$profile_uid == 0))) ? true : false); + if(local_channel()) { $channel = App::get_channel(); $observer = App::get_observer(); @@ -39,17 +41,17 @@ EOT; intval(get_account_id()) ); } + $sitelocation = (($is_owner) ? '' : App::$profile['reddress']); } - elseif(remote_channel()) + elseif(remote_channel()) { $observer = App::get_observer(); + $sitelocation = ((App::$profile['reddress']) ? App::$profile['reddress'] : '@' . App::get_hostname()); + } require_once('include/conversation.php'); - $is_owner = (((local_channel()) && ((App::$profile_uid == local_channel()) || (App::$profile_uid == 0))) ? true : false); + $channel_apps[] = channel_apps($is_owner, App::$profile['channel_address']); - $myident = (($channel) ? $channel['xchan_addr'] : ''); - - $sitelocation = (($myident) ? $myident : App::get_hostname()); /** * -- cgit v1.2.3 From 47fbdda40951be5109c739f63331e2bb95ebd64a Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Tue, 7 Nov 2017 11:22:11 +0100 Subject: rename channel app events to calendar and add nav_set_selected() to /cal --- include/nav.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/nav.php b/include/nav.php index 42c42e881..9df50c9fe 100644 --- a/include/nav.php +++ b/include/nav.php @@ -440,10 +440,10 @@ function channel_apps($is_owner = false, $nickname = null) { if($p['view_stream'] && $cal_link) { $tabs[] = [ - 'label' => t('Events'), + 'label' => t('Calendar'), 'url' => z_root() . $cal_link, - 'sel' => ((argv(0) == 'cal' || argv(0) == 'events') ? 'active' : ''), - 'title' => t('Events'), + 'sel' => ((argv(0) == 'cal') ? 'active' : ''), + 'title' => t('Calendar'), 'id' => 'event-tab', 'icon' => 'calendar' ]; -- cgit v1.2.3 From 92e0c502f76f5a3acc0498f45a0fe836973c554c Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 7 Nov 2017 19:34:00 -0800 Subject: make most recent cloud_tiles setting for local channels persistent across logins --- include/security.php | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/security.php b/include/security.php index 450cc4f69..8b7e7d076 100644 --- a/include/security.php +++ b/include/security.php @@ -264,6 +264,7 @@ function change_channel($change_channel) { App::set_channel($r[0]); $_SESSION['theme'] = $r[0]['channel_theme']; $_SESSION['mobile_theme'] = get_pconfig(local_channel(),'system', 'mobile_theme'); + $_SESSION['cloud_tiles'] = get_pconfig(local_channel(),'system', 'cloud_tiles'); date_default_timezone_set($r[0]['channel_timezone']); $ret = $r[0]; } -- cgit v1.2.3 From 7dad842f35184b3865714bf209c79ad1ef995733 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 8 Nov 2017 19:21:36 -0800 Subject: use logger --- include/zot.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'include') diff --git a/include/zot.php b/include/zot.php index 0aa50ab92..40e303bf1 100644 --- a/include/zot.php +++ b/include/zot.php @@ -2010,8 +2010,7 @@ function update_imported_item($sender, $item, $orig, $uid, $tag_delivery) { // may have a different owner than the one being transmitted. if(($sender['hash'] != $orig['owner_xchan'] && $sender['hash'] != $orig['author_xchan']) && (! $tag_delivery)) { - /// @fixme shouldn't this be logger? - notice('sender is not owner or author'); + logger('sender is not owner or author'); return; } -- cgit v1.2.3 From 9b19e40a74a4a5d641015c04c1765d4bd4502bd1 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 9 Nov 2017 21:26:18 -0800 Subject: hubzilla issue #901 - unicode characters in urls tripping up url regexes - these regexes have been modified to accept unicode "letters" which may preclude emojis and control sequences and symbols in url links; but should suffice for most legal URLs containing language context "text" glyphs. --- include/activities.php | 2 +- include/bbcode.php | 6 +++--- include/markdown.php | 4 ++-- include/text.php | 14 +++++++------- 4 files changed, 13 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/activities.php b/include/activities.php index 2671e668c..9b83f7a5c 100644 --- a/include/activities.php +++ b/include/activities.php @@ -50,7 +50,7 @@ function profile_activity($changed, $value) { if($t == 1 && strlen($value)) { // if it's a url, the HTML quotes will mess it up, so link it and don't try and zidify it because we don't know what it points to. - $value = preg_replace_callback("/([^\]\='".'"'."]|^|\#\^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\+\,]+)/ism", 'red_zrl_callback', $value); + $value = preg_replace_callback("/([^\]\='".'"'."]|^|\#\^)(https?\:\/\/[a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\+\,]+)/ismu", 'red_zrl_callback', $value); // take out the bookmark indicator if(substr($value,0,2) === '#^') $value = str_replace('#^','',$value); diff --git a/include/bbcode.php b/include/bbcode.php index 9a2a6eb9b..050ab2d29 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -838,13 +838,13 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false) // Perform URL Search - $urlchars = '[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]'; + $urlchars = '[a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]'; if (strpos($Text,'http') !== false) { if($tryoembed) { - $Text = preg_replace_callback("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/$urlchars+)/ism", 'tryoembed', $Text); + $Text = preg_replace_callback("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/$urlchars+)/ismu", 'tryoembed', $Text); } - $Text = preg_replace("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/$urlchars+)/ism", '$1$2', $Text); + $Text = preg_replace("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/$urlchars+)/ismu", '$1$2', $Text); } if (strpos($Text,'[/share]') !== false) { diff --git a/include/markdown.php b/include/markdown.php index 865727b20..f398d279e 100644 --- a/include/markdown.php +++ b/include/markdown.php @@ -75,10 +75,10 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) { // Convert everything that looks like a link to a link if($use_zrl) { $s = str_replace(['[img', '/img]'], ['[zmg', '/zmg]'], $s); - $s = preg_replace("/([^\]\=]|^)(https?\:\/\/)([a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)/ism", '$1[zrl=$2$3]$2$3[/zrl]',$s); + $s = preg_replace("/([^\]\=]|^)(https?\:\/\/)([a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)/ismu", '$1[zrl=$2$3]$2$3[/zrl]',$s); } else { - $s = preg_replace("/([^\]\=]|^)(https?\:\/\/)([a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)/ism", '$1[url=$2$3]$2$3[/url]',$s); + $s = preg_replace("/([^\]\=]|^)(https?\:\/\/)([a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)/ismu", '$1[url=$2$3]$2$3[/url]',$s); } // remove duplicate adjacent code tags diff --git a/include/text.php b/include/text.php index 746c35679..c74e515d2 100644 --- a/include/text.php +++ b/include/text.php @@ -819,7 +819,7 @@ function get_tags($s) { // added ; to single word tags to allow emojis and other unicode character constructs in bbcode // (this would actually be &#xnnnnn; but the ampersand will have been escaped to & by the time we see it.) - if(preg_match_all('/(?$1' : ' $1'), $s); + $s = preg_replace("/(https?\:\/\/[a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\@\~\#\'\%\$\!\+\,\@]*)/u", (($me) ? ' $1' : ' $1'), $s); $s = preg_replace("/\<(.*?)(src|href)=(.*?)\&\;(.*?)\>/ism",'<$1$2=$3&$4>',$s); return($s); @@ -3099,10 +3099,10 @@ function cleanup_bbcode($body) { $body = preg_replace_callback('/\[zrl(.*?)\[\/(zrl)\]/ism','\red_escape_codeblock',$body); - $body = preg_replace_callback("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\\ -+\,\(\)]+)/ism", '\nakedoembed', $body); - $body = preg_replace_callback("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\\ -+\,\(\)]+)/ism", '\red_zrl_callback', $body); + $body = preg_replace_callback("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/[a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\\ ++\,\(\)]+)/ismu", '\nakedoembed', $body); + $body = preg_replace_callback("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/[a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\\ ++\,\(\)]+)/ismu", '\red_zrl_callback', $body); $body = preg_replace_callback('/\[\$b64zrl(.*?)\[\/(zrl)\]/ism','\red_unescape_codeblock',$body); $body = preg_replace_callback('/\[\$b64url(.*?)\[\/(url)\]/ism','\red_unescape_codeblock',$body); -- cgit v1.2.3 From 34b38f06e00d929c3004ca7ee961405de0a209e1 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sat, 11 Nov 2017 12:23:20 -0800 Subject: also disable uploading in comments if the channel permissionlimits for view_storage aren't PERMS_PUBLIC. --- include/conversation.php | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/conversation.php b/include/conversation.php index 2ce4dacef..0b9df5acd 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -581,6 +581,9 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa || $owner_channel['channel_deny_cid'] || $owner_channel['channel_deny_gid']) { $uploading = false; } + if(\Zotlabs\Access\PermissionLimits::Get($profile_owner,'view_storage') !== PERMS_PUBLIC) { + $uploading = false; + } } else { $uploading = false; -- cgit v1.2.3 From 458f2e748de22448206ce12c9961e9cce80c796d Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 12 Nov 2017 14:14:20 -0800 Subject: cleanup of upload_to_comments test; we actually don't care about the profile owner. We only care that we're logged in locally and our storage is public by default. --- include/conversation.php | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/include/conversation.php b/include/conversation.php index 0b9df5acd..1cbd9116c 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -573,22 +573,16 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa if (! feature_enabled($profile_owner,'multi_delete')) $page_dropping = false; - $uploading = true; - - if($profile_owner > 0) { - $owner_channel = channelx_by_n($profile_owner); - if($owner_channel['channel_allow_cid'] || $owner_channel['channel_allow_gid'] - || $owner_channel['channel_deny_cid'] || $owner_channel['channel_deny_gid']) { - $uploading = false; - } - if(\Zotlabs\Access\PermissionLimits::Get($profile_owner,'view_storage') !== PERMS_PUBLIC) { - $uploading = false; + $uploading = false; + + if(local_channel()) { + $cur_channel = App::get_channel(); + if($cur_channel['channel_allow_cid'] === '' && $cur_channel['channel_allow_gid'] === '' + && $cur_channel['channel_deny_cid'] === '' && $cur_channel['channel_deny_gid'] === '' + && intval(\Zotlabs\Access\PermissionLimits::Get(local_channel(),'view_storage')) === PERMS_PUBLIC) { + $uploading = true; } } - else { - $uploading = false; - } - $channel = App::get_channel(); $observer = App::get_observer(); -- cgit v1.2.3 From 1ac35dd04748744b22e6fc3dd254f16f7980bd90 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 12 Nov 2017 15:07:12 -0800 Subject: fix some conflicts between private tags and forum tags --- include/items.php | 304 +++++++++++++++++++++++++++--------------------------- 1 file changed, 150 insertions(+), 154 deletions(-) (limited to 'include') diff --git a/include/items.php b/include/items.php index 5d592c736..b1b40e977 100755 --- a/include/items.php +++ b/include/items.php @@ -2571,148 +2571,149 @@ function tag_deliver($uid, $item_id) { if($terms) logger('Post mentions: ' . print_r($terms,true), LOGGER_DATA); + + $max_forums = get_config('system','max_tagged_forums',2); + $matched_forums = 0; + + $link = normalise_link($u[0]['xchan_url']); + if($terms) { foreach($terms as $term) { - if(link_compare($term['url'],$link)) { - $mention = true; - break; + if(! link_compare($term['url'],$link)) { + continue; } - } - } - if($mention) { - logger('Mention found for ' . $u[0]['channel_name']); + $mention = true; - $r = q("update item set item_mentionsme = 1 where id = %d", - intval($item_id) - ); + logger('Mention found for ' . $u[0]['channel_name']); - // At this point we've determined that the person receiving this post was mentioned in it or it is a union. - // Now let's check if this mention was inside a reshare so we don't spam a forum - // If it's private we may have to unobscure it momentarily so that we can parse it. + $r = q("update item set item_mentionsme = 1 where id = %d", + intval($item_id) + ); - $body = $item['body']; + // At this point we've determined that the person receiving this post was mentioned in it or it is a union. + // Now let's check if this mention was inside a reshare so we don't spam a forum + // If it's private we may have to unobscure it momentarily so that we can parse it. - $body = preg_replace('/\[share(.*?)\[\/share\]/','',$body); + $body = preg_replace('/\[share(.*?)\[\/share\]/','',$item['body']); - $tagged = false; - $plustagged = false; - $matches = array(); + $tagged = false; + $plustagged = false; + $matches = array(); - $pattern = '/[\!@]\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($term['term'],'/') . '\[\/zrl\]/'; - if(preg_match($pattern,$body,$matches)) - $tagged = true; + $pattern = '/[\!@]\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($term['term'],'/') . '\[\/zrl\]/'; + if(preg_match($pattern,$body,$matches)) + $tagged = true; - // original red forum tagging sequence @forumname+ - // standard forum tagging sequence !forumname + // original red forum tagging sequence @forumname+ + // standard forum tagging sequence !forumname - $pluspattern = '/@\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\+\[\/zrl\]/'; + $pluspattern = '/@\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\+\[\/zrl\]/'; - $forumpattern = '/\!\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\[\/zrl\]/'; + $forumpattern = '/\!\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\[\/zrl\]/'; - $found = false; + $found = false; - $max_forums = get_config('system','max_tagged_forums'); - if(! $max_forums) - $max_forums = 2; - $matched_forums = 0; - $matches = array(); + $matches = array(); - if(preg_match_all($pluspattern,$body,$matches,PREG_SET_ORDER)) { - foreach($matches as $match) { - $matched_forums ++; - if($term['url'] === $match[1] && $term['term'] === $match[2]) { - if($matched_forums <= $max_forums) { - $plustagged = true; - $found = true; - break; + if(preg_match_all($pluspattern,$body,$matches,PREG_SET_ORDER)) { + foreach($matches as $match) { + $matched_forums ++; + if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_MENTION) { + if($matched_forums <= $max_forums) { + $plustagged = true; + $found = true; + break; + } + logger('forum ' . $term['term'] . ' exceeded max_tagged_forums - ignoring'); } - logger('forum ' . $term['term'] . ' exceeded max_tagged_forums - ignoring'); } } - } - if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) { - foreach($matches as $match) { - $matched_forums ++; - if($term['url'] === $match[1] && $term['term'] === $match[2]) { - if($matched_forums <= $max_forums) { - $plustagged = true; - $found = true; - break; + if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) { + foreach($matches as $match) { + $matched_forums ++; + if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_FORUM) { + if($matched_forums <= $max_forums) { + $plustagged = true; + $found = true; + break; + } + logger('forum ' . $term['term'] . ' exceeded max_tagged_forums - ignoring'); } - logger('forum ' . $term['term'] . ' exceeded max_tagged_forums - ignoring'); } } - } - if(! ($tagged || $plustagged)) { - logger('Mention was in a reshare or exceeded max_tagged_forums - ignoring'); - return; - } + if(! ($tagged || $plustagged)) { + logger('Mention was in a reshare or exceeded max_tagged_forums - ignoring'); + continue; + } - $arr = [ - 'channel_id' => $uid, - 'item' => $item, - 'body' => $body - ]; - /** - * @hooks tagged - * Called when a delivery is processed which results in you being tagged. - * * \e number \b channel_id - * * \e array \b item - * * \e string \b body - */ - call_hooks('tagged', $arr); + $arr = [ + 'channel_id' => $uid, + 'item' => $item, + 'body' => $body + ]; + /** + * @hooks tagged + * Called when a delivery is processed which results in you being tagged. + * * \e number \b channel_id + * * \e array \b item + * * \e string \b body + */ + call_hooks('tagged', $arr); + + /* + * Kill two birds with one stone. As long as we're here, send a mention notification. + */ - /* - * Kill two birds with one stone. As long as we're here, send a mention notification. - */ + Zlib\Enotify::submit(array( + 'to_xchan' => $u[0]['channel_hash'], + 'from_xchan' => $item['author_xchan'], + 'type' => NOTIFY_TAGSELF, + 'item' => $item, + 'link' => $i[0]['llink'], + 'verb' => ACTIVITY_TAG, + 'otype' => 'item' + )); - Zlib\Enotify::submit(array( - 'to_xchan' => $u[0]['channel_hash'], - 'from_xchan' => $item['author_xchan'], - 'type' => NOTIFY_TAGSELF, - 'item' => $item, - 'link' => $i[0]['llink'], - 'verb' => ACTIVITY_TAG, - 'otype' => 'item' - )); - - // Just a normal tag? - - if(! $plustagged) { - logger('Not a plus tag', LOGGER_DEBUG); - return; - } + // Just a normal tag? - // plustagged - keep going, next check permissions + if(! $plustagged) { + logger('Not a plus tag', LOGGER_DEBUG); + continue; + } - if(! perm_is_allowed($uid,$item['author_xchan'],'tag_deliver')) { - logger('tag_delivery denied for uid ' . $uid . ' and xchan ' . $item['author_xchan']); - return; - } - } + // plustagged - keep going, next check permissions + + if(! perm_is_allowed($uid,$item['author_xchan'],'tag_deliver')) { + logger('tag_delivery denied for uid ' . $uid . ' and xchan ' . $item['author_xchan']); + continue; + } - if((! $mention) && (! $union)) { - logger('No mention for ' . $u[0]['channel_name'] . ' and no union.'); - return; - } - // tgroup delivery - setup a second delivery chain - // prevent delivery looping - only proceed - // if the message originated elsewhere and is a top-level post + if((! $mention) && (! $union)) { + logger('No mention for ' . $u[0]['channel_name'] . ' and no union.'); + continue; + } + // tgroup delivery - setup a second delivery chain + // prevent delivery looping - only proceed + // if the message originated elsewhere and is a top-level post - if(intval($item['item_wall']) || intval($item['item_origin']) || (! intval($item['item_thread_top'])) || ($item['id'] != $item['parent'])) { - logger('Item was local or a comment. rejected.'); - return; - } - logger('Creating second delivery chain.'); - start_delivery_chain($u[0],$item,$item_id,null); + if(intval($item['item_wall']) || intval($item['item_origin']) || (! intval($item['item_thread_top'])) || ($item['id'] != $item['parent'])) { + logger('Item was local or a comment. rejected.'); + continue; + } + + logger('Creating second delivery chain.'); + start_delivery_chain($u[0],$item,$item_id,null); + + } + } } /** @@ -2760,78 +2761,73 @@ function tgroup_check($uid, $item) { if($terms) logger('tgroup_check: post mentions: ' . print_r($terms,true), LOGGER_DATA); + $max_forums = get_config('system','max_tagged_forums',2); + $matched_forums = 0; + $link = normalise_link($u[0]['xchan_url']); if($terms) { foreach($terms as $term) { - if(link_compare($term['url'],$link)) { - $mention = true; - break; + if(! link_compare($term['url'],$link)) { + continue; } - } - } - - if($mention) { - logger('tgroup_check: mention found for ' . $u[0]['channel_name']); - } - else - return false; - // At this point we've determined that the person receiving this post was mentioned in it. - // Now let's check if this mention was inside a reshare so we don't spam a forum - // note: $term has been set to the matching term + $mention = true; + logger('tgroup_check: mention found for ' . $u[0]['channel_name']); + // At this point we've determined that the person receiving this post was mentioned in it. + // Now let's check if this mention was inside a reshare so we don't spam a forum + // note: $term has been set to the matching term - $body = $item['body']; - $body = preg_replace('/\[share(.*?)\[\/share\]/','',$body); + $body = preg_replace('/\[share(.*?)\[\/share\]/','',$item['body']); - $pluspattern = '/@\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\+\[\/zrl\]/'; + $pluspattern = '/@\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\+\[\/zrl\]/'; - $forumpattern = '/\!\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\[\/zrl\]/'; + $forumpattern = '/\!\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\[\/zrl\]/'; + $found = false; - $found = false; + $matches = array(); - $max_forums = get_config('system','max_tagged_forums'); - if(! $max_forums) - $max_forums = 2; - $matched_forums = 0; - $matches = array(); - - if(preg_match_all($pluspattern,$body,$matches,PREG_SET_ORDER)) { - foreach($matches as $match) { - $matched_forums ++; - if($term['url'] === $match[1] && $term['term'] === $match[2]) { - if($matched_forums <= $max_forums) { - $found = true; - break; + if(preg_match_all($pluspattern,$body,$matches,PREG_SET_ORDER)) { + foreach($matches as $match) { + $matched_forums ++; + if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_MENTION) { + if($matched_forums <= $max_forums) { + $found = true; + break; + } + logger('forum ' . $term['term'] . ' exceeded max_tagged_forums - ignoring'); + } } - logger('forum ' . $term['term'] . ' exceeded max_tagged_forums - ignoring'); } - } - } - if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) { - foreach($matches as $match) { - $matched_forums ++; - if($term['url'] === $match[1] && $term['term'] === $match[2]) { - if($matched_forums <= $max_forums) { - $found = true; - break; + if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) { + foreach($matches as $match) { + $matched_forums ++; + if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_FORUM) { + if($matched_forums <= $max_forums) { + $found = true; + break; + } + logger('forum ' . $term['term'] . ' exceeded max_tagged_forums - ignoring'); + } } - logger('forum ' . $term['term'] . ' exceeded max_tagged_forums - ignoring'); } + + if(! $found) { + logger('tgroup_check: mention was in a reshare or exceeded max_tagged_forums - ignoring'); + continue; + } + + return true; } } - if(! $found) { - logger('tgroup_check: mention was in a reshare or exceeded max_tagged_forums - ignoring'); - return false; - } + return false; - return true; } /** -- cgit v1.2.3 From b12dc89bb1fbdc29f82fffee3587360d618ef603 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 12 Nov 2017 21:36:25 -0800 Subject: improve removed_channel final cleanup. Hubzilla issue #386 --- include/channel.php | 60 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/include/channel.php b/include/channel.php index 6a6022aba..4f0e8ec6a 100644 --- a/include/channel.php +++ b/include/channel.php @@ -2527,19 +2527,43 @@ function channel_remove($channel_id, $local = true, $unset_session = false) { } } + q("DELETE FROM app WHERE app_channel = %d", intval($channel_id)); + q("DELETE FROM atoken WHERE atoken_uid = %d", intval($channel_id)); + q("DELETE FROM chatroom WHERE cr_uid = %d", intval($channel_id)); + q("DELETE FROM conv WHERE uid = %d", intval($channel_id)); q("DELETE FROM groups WHERE uid = %d", intval($channel_id)); q("DELETE FROM group_member WHERE uid = %d", intval($channel_id)); q("DELETE FROM event WHERE uid = %d", intval($channel_id)); - q("DELETE FROM item WHERE uid = %d", intval($channel_id)); q("DELETE FROM mail WHERE channel_id = %d", intval($channel_id)); + q("DELETE FROM menu WHERE menu_channel_id = %d", intval($channel_id)); + q("DELETE FROM menu_item WHERE mitem_channel_id = %d", intval($channel_id)); + q("DELETE FROM notify WHERE uid = %d", intval($channel_id)); + q("DELETE FROM obj WHERE obj_channel = %d", intval($channel_id)); + + q("DELETE FROM photo WHERE uid = %d", intval($channel_id)); q("DELETE FROM attach WHERE uid = %d", intval($channel_id)); q("DELETE FROM profile WHERE uid = %d", intval($channel_id)); - q("DELETE FROM pconfig WHERE uid = %d", intval($channel_id)); + q("DELETE FROM src WHERE src_channel_id = %d", intval($channel_id)); + + $r = q("select resource_id FROM attach WHERE uid = %d", intval($channel_id)); + if($r) { + foreach($r as $rv) { + attach_delete($channel_id,$rv['resource_id']); + } + } + + + + $r = q("select id from item where uid = %d", intval($channel_id)); + if($r) { + foreach($r as $rv) { + drop_item($rv['id'],false); + } + } - /// @FIXME At this stage we need to remove the file resources located under /store/$nickname q("delete from abook where abook_xchan = '%s' and abook_self = 1 ", dbesc($channel['channel_hash']) @@ -2593,19 +2617,11 @@ function channel_remove($channel_id, $local = true, $unset_session = false) { } //remove from file system - $r = q("select channel_address from channel where channel_id = %d limit 1", - intval($channel_id) - ); - if($r) { - $channel_address = $r[0]['channel_address'] ; - } - if($channel_address) { - $f = 'store/' . $channel_address.'/'; - logger('delete '. $f); - if(is_dir($f)) { - @rrmdir($f); - } + + $f = 'store/' . $channel['channel_address']; + if(is_dir($f)) { + @rrmdir($f); } Zotlabs\Daemon\Master::Summon(array('Directory',$channel_id)); @@ -2616,6 +2632,20 @@ function channel_remove($channel_id, $local = true, $unset_session = false) { } } +// execute this at least a week after removing a channel + +function channel_remove_final($channel_id) { + + q("delete from abook where abook_channel = %d", intval($channel_id)); + q("delete from abconfig where chan = %d", intval($channel_id)); + q("delete from pconfig where uid = %d", intval($channel_id)); + + +} + + + + /** * @brief This checks if a channel is allowed to publish executable code. * -- cgit v1.2.3 From 5dad44402649db9844d735800300d86a8479b3fa Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 13 Nov 2017 19:55:09 +0100 Subject: fix php warnings on photo delete --- include/attach.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/attach.php b/include/attach.php index 179a57a90..2bb57722b 100644 --- a/include/attach.php +++ b/include/attach.php @@ -1366,7 +1366,7 @@ function attach_delete($channel_id, $resource, $is_photo = 0) { return; } - $url = get_cloudpath($channel_id, $channel_address, $resource); + $url = get_cloud_url($channel_id, $channel_address, $resource); $object = get_file_activity_object($channel_id, $resource, $url); // If resource is a directory delete everything in the directory recursive -- cgit v1.2.3 From c8dbcf8a2af7ac3b1a9e26c4c293574f919bd554 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 13 Nov 2017 22:01:37 +0100 Subject: sort combined private mail conversations by latest updated conversation instead of created parent --- include/message.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'include') diff --git a/include/message.php b/include/message.php index 477c7172c..b57d2e068 100644 --- a/include/message.php +++ b/include/message.php @@ -335,12 +335,9 @@ function private_messages_list($uid, $mailbox = '', $start = 0, $numitems = 0) { case 'combined': default: - - $parents = q("SELECT parent_mid FROM mail WHERE mid = parent_mid AND channel_id = %d ORDER BY created DESC", + $parents = q("SELECT mail.parent_mid FROM mail LEFT JOIN conv ON mail.conv_guid = conv.guid WHERE mail.mid = mail.parent_mid AND mail.channel_id = %d ORDER BY conv.updated DESC $limit", dbesc($local_channel) ); - //FIXME: We need the latest mail of a thread here. This query throws errors in postgres. We now look for the latest in php until somebody can fix this... - //$sql = "SELECT * FROM ( SELECT * FROM mail WHERE channel_id = $local_channel ORDER BY created DESC $limit ) AS temp_table GROUP BY parent_mid ORDER BY created DESC"; break; } -- cgit v1.2.3 From d5ff82bbe46fd2b42a6474f645749fc1ef56ceb2 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 13 Nov 2017 14:40:46 -0800 Subject: issue with group_rmv --- include/group.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/group.php b/include/group.php index e0c20b536..03ebf7ee5 100644 --- a/include/group.php +++ b/include/group.php @@ -18,10 +18,6 @@ function group_add($uid,$name,$public = 0) { intval($r) ); if(($z) && $z[0]['deleted']) { - /*$r = q("UPDATE groups SET deleted = 0 WHERE uid = %d AND gname = '%s'", - intval($uid), - dbesc($name) - );*/ q('UPDATE groups SET deleted = 0 WHERE id = %d', intval($z[0]['id'])); notice( t('A deleted group with this name was revived. Existing item permissions may apply to this group and any future members. If this is not what you intended, please create another group with a different name.') . EOL); } @@ -81,11 +77,11 @@ function group_rmv($uid,$name) { $user_info['channel_default_group'] = ''; $change = true; } - if(strpos($user_info['channel_allow_gid'], '<' . $group_id . '>') !== false) { + if(strpos($user_info['channel_allow_gid'], '<' . $group_hash . '>') !== false) { $user_info['channel_allow_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_allow_gid']); $change = true; } - if(strpos($user_info['channel_deny_gid'], '<' . $group_id . '>') !== false) { + if(strpos($user_info['channel_deny_gid'], '<' . $group_hash . '>') !== false) { $user_info['channel_deny_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_deny_gid']); $change = true; } -- cgit v1.2.3 From 8e534918672c2ccf3614623b8bd368d18318f453 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 14 Nov 2017 17:39:33 -0800 Subject: sort out a few more large image upload issues --- include/attach.php | 6 +++++ include/photo/photo_driver.php | 16 ++++++++++---- include/photos.php | 50 +++++++++++++++++++++++++++++++++--------- 3 files changed, 58 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/include/attach.php b/include/attach.php index 2bb57722b..96b9c0b44 100644 --- a/include/attach.php +++ b/include/attach.php @@ -588,6 +588,12 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $def_extension = '.png'; } + // If we know it's a photo, over-ride the type in case the source system could not determine what it was + + if($is_photo) { + $type = $gis['mime']; + } + $pathname = ''; if($is_photo) { diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php index 5eb1f9113..21431e96f 100644 --- a/include/photo/photo_driver.php +++ b/include/photo/photo_driver.php @@ -309,6 +309,11 @@ abstract class photo_driver { public function save($arr) { + if(! $this->is_valid()) { + logger('attempt to store invalid photo.'); + return false; + } + $p = array(); $p['aid'] = ((intval($arr['aid'])) ? intval($arr['aid']) : 0); @@ -331,6 +336,8 @@ abstract class photo_driver { $p['os_path'] = $arr['os_path']; $p['os_syspath'] = ((array_key_exists('os_syspath',$arr)) ? $arr['os_syspath'] : ''); $p['display_path'] = (($arr['display_path']) ? $arr['display_path'] : ''); + $p['width'] = (($arr['width']) ? $arr['width'] : $this->getWidth()); + $p['height'] = (($arr['height']) ? $arr['height'] : $this->getHeight()); if(! intval($p['imgscale'])) logger('save: ' . print_r($arr,true), LOGGER_DATA); @@ -378,8 +385,8 @@ abstract class photo_driver { dbesc(basename($p['filename'])), dbesc($this->getType()), dbesc($p['album']), - intval($this->getHeight()), - intval($this->getWidth()), + intval($p['height']), + intval($p['width']), (intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())), intval($p['os_storage']), intval(strlen($this->imageString())), @@ -409,8 +416,8 @@ abstract class photo_driver { dbesc(basename($p['filename'])), dbesc($this->getType()), dbesc($p['album']), - intval($this->getHeight()), - intval($this->getWidth()), + intval($p['height']), + intval($p['width']), (intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())), intval($p['os_storage']), intval(strlen($this->imageString())), @@ -426,6 +433,7 @@ abstract class photo_driver { dbesc($p['deny_gid']) ); } + logger('photo save ' . $p['imgscale'] . ' returned ' . intval($r)); return $r; } diff --git a/include/photos.php b/include/photos.php index c38e2bed4..41a1d18cb 100644 --- a/include/photos.php +++ b/include/photos.php @@ -62,27 +62,52 @@ function photo_upload($channel, $observer, $args) { $ac = $acl->get(); + $width = $height = 0; + + if($args['getimagesize']) { + $width = $args['getimagesize'][0]; + $height = $args['getimagesize'][1]; + } + + $os_storage = 0; + $max_thumb = get_config('system','max_thumbnail',1600); + if($args['os_syspath'] && $args['getimagesize']) { - if($args['getimagesize'][0] > 1600 || $args['getimagesize'][1] > 1600) { + if($args['getimagesize'][0] > $max_thumb || $args['getimagesize'][1] > $max_thumb) { $imagick_path = get_config('system','imagick_convert_path'); if($imagick_path && @file_exists($imagick_path)) { $tmp_name = $args['os_syspath'] . '-001'; - $newsize = photo_calculate_1600_scale($args['getimagesize']); - exec($imagick_path . ' ' . $args['os_syspath'] . ' -resize ' . $newsize . '^ ' . $tmp_name); + $newsize = photo_calculate_scale(array_merge($args['getimagesize'],['max' => $max_thumb])); + $cmd = $imagick_path . ' ' . escapeshellarg(PROJECT_BASE . '/' . $args['os_syspath']) . ' -thumbnail ' . $newsize . ' ' . escapeshellarg(PROJECT_BASE . '/' . $tmp_name); + // logger('imagick thumbnail command: ' . $cmd); + for($x = 0; $x < 4; $x ++) { + exec($cmd); + if(! file_exists($tmp_name)) { + logger('imagick scale failed. Retrying.'); + continue; + } + } + if(! file_exists($tmp_name)) { + logger('imagick scale failed. Abort.'); + return $ret; + } + $imagedata = @file_get_contents($tmp_name); + $filesize = @filesize($args['os_syspath']); @unlink($tmp_name); } else { $imagedata = @file_get_contents($args['os_syspath']); + $filesize = strlen($imagedata); } } else { $imagedata = @file_get_contents($args['os_syspath']); + $filesize = strlen($imagedata); } $filename = $args['filename']; - $filesize = strlen($imagedata); // this is going to be deleted if it exists $src = '/tmp/deletemenow'; $type = $args['getimagesize']['mime']; @@ -188,8 +213,10 @@ function photo_upload($channel, $observer, $args) { if ($max_length > 0) $ph->scaleImage($max_length); - $width = $ph->getWidth(); - $height = $ph->getHeight(); + if(! $width) + $width = $ph->getWidth(); + if(! $height) + $height = $ph->getHeight(); $smallest = 0; @@ -203,6 +230,7 @@ function photo_upload($channel, $observer, $args) { $p = array('aid' => $account_id, 'uid' => $channel_id, 'xchan' => $visitor, 'resource_id' => $photo_hash, 'filename' => $filename, 'album' => $album, 'imgscale' => 0, 'photo_usage' => PHOTO_NORMAL, + 'width' => $width, 'height' => $height, 'allow_cid' => $ac['allow_cid'], 'allow_gid' => $ac['allow_gid'], 'deny_cid' => $ac['deny_cid'], 'deny_gid' => $ac['deny_gid'], 'os_storage' => $os_storage, 'os_syspath' => $args['os_syspath'], @@ -224,14 +252,16 @@ function photo_upload($channel, $observer, $args) { 'rel' => 'alternate', 'type' => 'text/html', 'href' => z_root() . '/photo/' . $photo_hash . '-0.' . $ph->getExt(), - 'width' => $ph->getWidth(), - 'height' => $ph->getHeight() + 'width' => $width, + 'height' => $height ); if(! $r0) $errors = true; unset($p['os_storage']); unset($p['os_syspath']); + unset($p['width']); + unset($p['height']); if(($width > 1024 || $height > 1024) && (! $errors)) $ph->scaleImage(1024); @@ -462,9 +492,9 @@ function photo_upload($channel, $observer, $args) { } -function photo_calculate_1600_scale($arr) { +function photo_calculate_scale($arr) { - $max = 1600; + $max = $arr['max']; $width = $arr[0]; $height = $arr[1]; -- cgit v1.2.3 From 301b41eaa4f3087624a57d1471f76d903c604a5b Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 15 Nov 2017 09:40:14 +0100 Subject: typo - fixes issue #910 --- include/channel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/channel.php b/include/channel.php index 4f0e8ec6a..b12491936 100644 --- a/include/channel.php +++ b/include/channel.php @@ -1743,7 +1743,7 @@ function get_theme_uid() { if((get_pconfig(local_channel(),'system','always_my_theme')) || (! $uid)) return local_channel(); } - if(! $uierd) { + if(! $uid) { $x = get_sys_channel(); if($x) return $x['channel_id']; -- cgit v1.2.3 From 67b6d41d57b20a223a0cb6f33cbf81473b0936ab Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 15 Nov 2017 11:26:14 -0800 Subject: This should sort out hubzilla issue #826 but requires a bit more testing. It may also sort out some reported issues with commenting and liking items in the public stream. --- include/channel.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/channel.php b/include/channel.php index 4f0e8ec6a..2783dea97 100644 --- a/include/channel.php +++ b/include/channel.php @@ -101,14 +101,14 @@ function create_sys_channel() { set_config('system', 'prvkey', $hostkey['prvkey']); } - create_identity(array( - 'account_id' => 'xxx', // This will create an identity with an (integer) account_id of 0, but account_id is required - 'nickname' => 'sys', - 'name' => 'System', - 'pageflags' => 0, - 'publish' => 0, - 'system' => 1 - )); + create_identity([ + 'account_id' => 'xxx', // Typecast trickery: account_id is required. This will create an identity with an (integer) account_id of 0 + 'nickname' => 'sys', + 'name' => 'System', + 'pageflags' => 0, + 'publish' => 0, + 'system' => 1 + ]); } -- cgit v1.2.3 From 78c9f752af8db5db290a57224fa1d0239a36a34d Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 16 Nov 2017 11:11:06 +0100 Subject: provide ability to pin apps to navbar from /apps. this removes the ability to have per custom navbar pinned apps - this can be added later if desired --- include/nav.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/nav.php b/include/nav.php index 9df50c9fe..8d39d492a 100644 --- a/include/nav.php +++ b/include/nav.php @@ -253,7 +253,7 @@ EOT; } $syslist = array(); - $list = Zlib\Apps::app_list(local_channel(), false, 'nav_featured_app'); + $list = Zlib\Apps::app_list(local_channel(), false, ['nav_featured_app', 'nav_pinned_app']); if($list) { foreach($list as $li) { $syslist[] = Zlib\Apps::app_encode($li); @@ -274,16 +274,20 @@ EOT; $app['active'] = true; if($is_owner) { - $nav_apps[] = Zlib\Apps::app_render($app,'nav'); - if(strpos($app['categories'],'navbar_' . $template)) { + if(strpos($app['categories'],'nav_pinned_app')) { $navbar_apps[] = Zlib\Apps::app_render($app,'navbar'); } + else { + $nav_apps[] = Zlib\Apps::app_render($app,'nav'); + } } elseif(! $is_owner && strpos($app['requires'], 'local_channel') === false) { - $nav_apps[] = Zlib\Apps::app_render($app,'nav'); - if(strpos($app['categories'],'navbar_' . $template)) { + if(strpos($app['categories'],'nav_pinned_app')) { $navbar_apps[] = Zlib\Apps::app_render($app,'navbar'); } + else { + $nav_apps[] = Zlib\Apps::app_render($app,'nav'); + } } } -- cgit v1.2.3 From cba602bf64dd4e9566e5c060c38480128735a60d Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 16 Nov 2017 13:10:08 +0100 Subject: compare strpos result against false --- include/nav.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/nav.php b/include/nav.php index 8d39d492a..2dcf68bc8 100644 --- a/include/nav.php +++ b/include/nav.php @@ -274,7 +274,7 @@ EOT; $app['active'] = true; if($is_owner) { - if(strpos($app['categories'],'nav_pinned_app')) { + if(strpos($app['categories'],'nav_pinned_app') !== false) { $navbar_apps[] = Zlib\Apps::app_render($app,'navbar'); } else { @@ -282,7 +282,7 @@ EOT; } } elseif(! $is_owner && strpos($app['requires'], 'local_channel') === false) { - if(strpos($app['categories'],'nav_pinned_app')) { + if(strpos($app['categories'],'nav_pinned_app') !== false) { $navbar_apps[] = Zlib\Apps::app_render($app,'navbar'); } else { -- cgit v1.2.3 From ab363e31322d699ee53f052d5198c3a7680f8cc8 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 16 Nov 2017 19:58:09 -0800 Subject: improve the icon mappings for cloud tile view --- include/attach.php | 12 +++++++++--- include/text.php | 27 ++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/attach.php b/include/attach.php index 96b9c0b44..0f07fe035 100644 --- a/include/attach.php +++ b/include/attach.php @@ -31,7 +31,6 @@ function z_mime_content_type($filename) { 'txt' => 'text/plain', 'htm' => 'text/html', 'html' => 'text/html', - 'php' => 'text/html', 'css' => 'text/css', 'md' => 'text/markdown', 'bb' => 'text/bbcode', @@ -41,8 +40,17 @@ function z_mime_content_type($filename) { 'swf' => 'application/x-shockwave-flash', 'flv' => 'video/x-flv', 'epub' => 'application/epub+zip', + 'c' => 'text/plain', + 'h' => 'text/plain', + 'sh' => 'text/plain', + 'py' => 'text/plain', + 'php' => 'text/plain', + 'rb' => 'text/plain', + 'pdl' => 'text/plain', + // images + 'png' => 'image/png', 'jpe' => 'image/jpeg', 'jpeg' => 'image/jpeg', @@ -73,9 +81,7 @@ function z_mime_content_type($filename) { 'flac' => 'audio/flac', 'opus' => 'audio/ogg', 'webm' => 'video/webm', -// 'webm' => 'audio/webm', 'mp4' => 'video/mp4', -// 'mp4' => 'audio/mp4', 'mkv' => 'video/x-matroska', // adobe diff --git a/include/text.php b/include/text.php index c74e515d2..ee8318d7c 100644 --- a/include/text.php +++ b/include/text.php @@ -2710,6 +2710,9 @@ function getIconFromType($type) { 'application/octet-stream' => 'fa-file-o', //Text 'text/plain' => 'fa-file-text-o', + 'text/markdown' => 'fa-file-text-o', + 'text/bbcode' => 'fa-file-text-o', + 'text/html' => 'fa-file-text-o', 'application/msword' => 'fa-file-word-o', 'application/pdf' => 'fa-file-pdf-o', 'application/vnd.oasis.opendocument.text' => 'fa-file-word-o', @@ -2739,11 +2742,33 @@ function getIconFromType($type) { 'video/x-matroska' => 'fa-file-video-o' ); - $iconFromType = 'fa-file-o'; + $catMap = [ + 'application' => 'fa-file-code-o', + 'multipart' => 'fa-folder', + 'audio' => 'fa-file-audio-o', + 'video' => 'fa-file-video-o', + 'text' => 'fa-file-text-o', + 'image' => 'fa=file-picture-o', + 'message' => 'fa-file-text-o' + ]; + + + $iconFromType = ''; if (array_key_exists($type, $iconMap)) { $iconFromType = $iconMap[$type]; } + else { + $parts = explode('/',$type); + if($parts[0] && $catMap[$parts[0]]) { + $iconFromType = $catMap[$parts[0]]; + } + } + + if(! $iconFromType) { + $iconFromType = 'fa-file-o'; + } + return $iconFromType; } -- cgit v1.2.3 From 60fcb5f4f2729e6e164abcb515540cc752881b9b Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sat, 18 Nov 2017 12:29:20 -0800 Subject: don't include pending connections in poco --- include/socgraph.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/socgraph.php b/include/socgraph.php index a5b5d1378..3c7a893c6 100644 --- a/include/socgraph.php +++ b/include/socgraph.php @@ -385,7 +385,7 @@ function poco($a,$extended = false) { $sql_extra = " and abook_self = 0 "; if($cid) - $sql_extra = sprintf(" and abook_id = %d and abook_hidden = 0 ",intval($cid)); + $sql_extra = sprintf(" and abook_id = %d and abook_hidden = 0 and abook_pending = 0 ",intval($cid)); if($system_mode) { $r = q("SELECT count(*) as total from abook where abook_self = 1 -- cgit v1.2.3 From 16f584608f8147a58bfe295ff3295aae0f85b38a Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 19 Nov 2017 16:56:59 -0800 Subject: text thumbnails in cloud tile mode --- include/attach.php | 3 ++ include/photo/photo_driver.php | 109 +++++++++++++++++++++++------------------ include/photos.php | 8 ++- 3 files changed, 72 insertions(+), 48 deletions(-) (limited to 'include') diff --git a/include/attach.php b/include/attach.php index 0f07fe035..0f31ed012 100644 --- a/include/attach.php +++ b/include/attach.php @@ -951,6 +951,9 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { call_hooks('photo_upload_end', $ret); } + \Zotlabs\Daemon\Master::Summon([ 'Thumbnail' , $hash ]); + + if($dosync) { $sync = attach_export_data($channel,$hash); diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php index 21431e96f..f75ff2386 100644 --- a/include/photo/photo_driver.php +++ b/include/photo/photo_driver.php @@ -241,69 +241,84 @@ abstract class photo_driver { } + /** + * @brief reads exif data from filename + */ + public function exif($filename) { - public function orient($filename) { - /** - * This function is a bit unusual, because it is operating on a file, but you must - * first create an image from that file to initialise the type and check validity - * of the image. - */ - - if(! $this->is_valid()) + if((! function_exists('exif_read_data')) + || (! in_array($this->getType(), [ 'image/jpeg' , 'image/tiff'] ))) { return false; + } - if((! function_exists('exif_read_data')) || ($this->getType() !== 'image/jpeg')) - return false; - - $exif = @exif_read_data($filename,null,true); - - if($exif) { - $ort = $exif['IFD0']['Orientation']; - - switch($ort) - { - case 1: // nothing - break; + /* + * PHP 7.2 allows you to use a stream resource, which should reduce/avoid + * memory exhaustion on large images. + */ - case 2: // horizontal flip - $this->flip(); - break; + if(version_compare(PHP_VERSION,'7.2.0') >= 0) { + $f = @fopen($filename,'rb'); + } + else { + $f = $filename; + } - case 3: // 180 rotate left - $this->rotate(180); - break; + if($f) { + return @exif_read_data($f); + } - case 4: // vertical flip - $this->flip(false, true); - break; + return false; + } - case 5: // vertical flip + 90 rotate right - $this->flip(false, true); - $this->rotate(-90); - break; + /** + * @brief orients current image based on exif orientation information + */ - case 6: // 90 rotate right - $this->rotate(-90); - break; + public function orient($exif) { - case 7: // horizontal flip + 90 rotate right - $this->flip(); - $this->rotate(-90); - break; + if(! ($this->is_valid() && $exif)) { + return false; + } - case 8: // 90 rotate left - $this->rotate(90); - break; - } + $ort = $exif['IFD0']['Orientation']; - return $exif; + if(! $ort) { + return false; + } + switch($ort) { + case 1: // nothing + break; + case 2: // horizontal flip + $this->flip(); + break; + case 3: // 180 rotate left + $this->rotate(180); + break; + case 4: // vertical flip + $this->flip(false, true); + break; + case 5: // vertical flip + 90 rotate right + $this->flip(false, true); + $this->rotate(-90); + break; + case 6: // 90 rotate right + $this->rotate(-90); + break; + case 7: // horizontal flip + 90 rotate right + $this->flip(); + $this->rotate(-90); + break; + case 8: // 90 rotate left + $this->rotate(90); + break; + default: + break; } - - return false; + return true; } diff --git a/include/photos.php b/include/photos.php index 41a1d18cb..b1391f284 100644 --- a/include/photos.php +++ b/include/photos.php @@ -203,7 +203,13 @@ function photo_upload($channel, $observer, $args) { return $ret; } - $exif = $ph->orient(($args['os_syspath']) ? $args['os_syspath'] : $src); + // obtain exif data from the source file if present + + $exif = $ph->exif(($args['os_syspath']) ? $args['os_syspath'] : $src); + + if($exif) { + $ph->orient($exif); + } @unlink($src); -- cgit v1.2.3 From 250d947667b1500633d80b043ac3760be21446fc Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 19 Nov 2017 21:51:21 -0800 Subject: cloud tiles: use folder-o for folders and set the icon colour to something a bit less harsh than the link colour for system icons. Dark solid blue folders are a bit overwhelming, as is the default text_colour (black) --- include/text.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/text.php b/include/text.php index ee8318d7c..343e3f00b 100644 --- a/include/text.php +++ b/include/text.php @@ -2704,8 +2704,8 @@ function linkify_tags($a, &$body, $uid, $diaspora = false) { function getIconFromType($type) { $iconMap = array( //Folder - t('Collection') => 'fa-folder', - 'multipart/mixed' => 'fa-folder', //dirs in attach use this mime type + t('Collection') => 'fa-folder-o', + 'multipart/mixed' => 'fa-folder-o', //dirs in attach use this mime type //Common file 'application/octet-stream' => 'fa-file-o', //Text -- cgit v1.2.3 From 09f1e4bdfbc7659cfb9f8db9b6c3278a66e08db7 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 21 Nov 2017 15:10:23 -0800 Subject: pdf thumbnails --- include/attach.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/attach.php b/include/attach.php index 0f31ed012..e3c40f68d 100644 --- a/include/attach.php +++ b/include/attach.php @@ -1632,7 +1632,7 @@ function find_filename_by_hash($channel_id, $attachHash) { } /** - * @brief Pipes $in to $out in 16MB chunks. + * @brief Pipes $in to $out in 16KB chunks. * * @param resource $in File pointer of input * @param resource $out File pointer of output -- cgit v1.2.3 From 94d6461568b154d3c228b91912c431474c6ef184 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 21 Nov 2017 16:06:03 -0800 Subject: Video thumbnail generator --- include/attach.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/attach.php b/include/attach.php index e3c40f68d..7988286c9 100644 --- a/include/attach.php +++ b/include/attach.php @@ -1636,12 +1636,13 @@ function find_filename_by_hash($channel_id, $attachHash) { * * @param resource $in File pointer of input * @param resource $out File pointer of output + * @param int $bufsize size of chunk, default 16384 * @return number with the size */ -function pipe_streams($in, $out) { +function pipe_streams($in, $out, $bufize = 16384) { $size = 0; while (!feof($in)) - $size += fwrite($out, fread($in, 16384)); + $size += fwrite($out, fread($in, $bufsize)); return $size; } -- cgit v1.2.3 From b4f8f4df7bc5cc8a74240506cd536224cb31e114 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 21 Nov 2017 19:47:59 -0800 Subject: allow toggle to 'SMBC' scaling mode. 'SMBC' mode is named thusly for Saturday Morning Breakfast Cereal cartoons which are very tall. If you scale the image to constrain both dimensions, the cartoon text is illegible. So we allow the height to float and only constrain the width. The new flag allows you to overide this mode and force both dimensions to always be evaluated and constrained to the provided limit. --- include/photo/photo_driver.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php index f75ff2386..6af753195 100644 --- a/include/photo/photo_driver.php +++ b/include/photo/photo_driver.php @@ -129,7 +129,14 @@ abstract class photo_driver { return $this->types[$this->getType()]; } - public function scaleImage($max) { + /** + * @brief scale image + * int $max maximum pixel size in either dimension + * boolean $float_height - if true allow height to float to any length on tall images, + * constraining only the width + */ + + public function scaleImage($max, $float_height = true) { if(!$this->is_valid()) return FALSE; @@ -146,7 +153,7 @@ abstract class photo_driver { // very tall image (greater than 16:9) // constrain the width - let the height float. - if((($height * 9) / 16) > $width) { + if(((($height * 9) / 16) > $width) && ($float_height)) { $dest_width = $max; $dest_height = intval(( $height * $max ) / $width); } @@ -173,7 +180,7 @@ abstract class photo_driver { // very tall image (greater than 16:9) // but width is OK - don't do anything - if((($height * 9) / 16) > $width) { + if(((($height * 9) / 16) > $width) && ($float_height)) { $dest_width = $width; $dest_height = $height; } -- cgit v1.2.3 From 8bd8af7d16d6b4fb40680bd33b99bbfd582a1208 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 22 Nov 2017 11:49:28 -0800 Subject: initial articles feature --- include/features.php | 9 +++++++++ include/items.php | 2 ++ 2 files changed, 11 insertions(+) (limited to 'include') diff --git a/include/features.php b/include/features.php index d8d98dbaa..ace1b01c3 100644 --- a/include/features.php +++ b/include/features.php @@ -126,6 +126,15 @@ function get_features($filtered = true) { feature_level('cards',1), ], + [ + 'articles', + t('Articles'), + t('Create interactive articles'), + false, + get_config('feature_lock','articles'), + feature_level('articles',1), + ], + [ 'nav_channel_select', t('Navigation Channel Select'), diff --git a/include/items.php b/include/items.php index b1b40e977..654cc5de3 100755 --- a/include/items.php +++ b/include/items.php @@ -4309,6 +4309,8 @@ function webpage_to_namespace($webpage) { $page_type = 'PDL'; elseif($webpage == ITEM_TYPE_CARD) $page_type = 'CARD'; + elseif($webpage == ITEM_TYPE_ARTICLE) + $page_type = 'ARTICLE'; elseif($webpage == ITEM_TYPE_DOC) $page_type = 'docfile'; else -- cgit v1.2.3 From 6c178d44858bbdfd582d09eb4568d32292c0b2c2 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 22 Nov 2017 15:39:06 -0800 Subject: article feature --- include/bbcode.php | 2 ++ include/contact_widgets.php | 48 ++++++++++++++++++++++++++++++ include/conversation.php | 22 +++++++++++++- include/nav.php | 11 +++++++ include/taxonomy.php | 71 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 153 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/bbcode.php b/include/bbcode.php index 050ab2d29..7ebc8d37c 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -329,6 +329,8 @@ function bb_ShareAttributes($match) { if(strpos($link,'/cards/')) $type = t('card'); + elseif(strpos($link,'/articles/')) + $type = t('article'); else $type = t('post'); diff --git a/include/contact_widgets.php b/include/contact_widgets.php index 9cc9f0baf..b36471924 100644 --- a/include/contact_widgets.php +++ b/include/contact_widgets.php @@ -150,6 +150,54 @@ function cardcategories_widget($baseurl,$selected = '') { } +function articlecategories_widget($baseurl,$selected = '') { + + if(! feature_enabled(App::$profile['profile_uid'],'categories')) + return ''; + + $sql_extra = item_permissions_sql(App::$profile['profile_uid']); + + $item_normal = "and item.item_hidden = 0 and item.item_type = 7 and item.item_deleted = 0 + and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0 + and item.item_blocked = 0 "; + + $terms = array(); + $r = q("select distinct(term.term) + from term join item on term.oid = item.id + where item.uid = %d + and term.uid = item.uid + and term.ttype = %d + and term.otype = %d + and item.owner_xchan = '%s' + $item_normal + $sql_extra + order by term.term asc", + intval(App::$profile['profile_uid']), + intval(TERM_CATEGORY), + intval(TERM_OBJ_POST), + dbesc(App::$profile['channel_hash']) + ); + if($r && count($r)) { + foreach($r as $rr) + $terms[] = array('name' => $rr['term'], 'selected' => (($selected == $rr['term']) ? 'selected' : '')); + + return replace_macros(get_markup_template('categories_widget.tpl'),array( + '$title' => t('Categories'), + '$desc' => '', + '$sel_all' => (($selected == '') ? 'selected' : ''), + '$all' => t('Everything'), + '$terms' => $terms, + '$base' => $baseurl, + + )); + } + return ''; +} + + + + + function common_friends_visitor_widget($profile_uid,$cnt = 25) { diff --git a/include/conversation.php b/include/conversation.php index 1cbd9116c..8c75389c4 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -539,6 +539,15 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa $jsreload = $_SESSION['return_url']; } + elseif ($mode === 'articles') { + $profile_owner = App::$profile['profile_uid']; + $page_writeable = ($profile_owner == local_channel()); + $live_update_div = '
' . "\r\n" + . "\r\n"; + $jsreload = $_SESSION['return_url']; + } + elseif ($mode === 'display') { $profile_owner = local_channel(); @@ -714,7 +723,7 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa $conv_link_mid = (($mode == 'moderate') ? $item['parent_mid'] : $item['mid']); - $conv_link = (($item['item_type'] == ITEM_TYPE_CARD) ? $item['plink'] : z_root() . '/display/' . gen_link_id($conv_link_mid)); + $conv_link = ((in_array($item['item_type'],[ ITEM_TYPE_CARD, ITEM_TYPE_ARTICLE] )) ? $item['plink'] : z_root() . '/display/' . gen_link_id($conv_link_mid)); $tmp_item = array( @@ -1887,6 +1896,17 @@ function profile_tabs($a, $is_owner = false, $nickname = null){ 'icon' => 'list' ); } + + if(feature_enabled($uid,'articles')) { + $tabs[] = array( + 'label' => t('articles'), + 'url' => z_root() . '/articles/' . $nickname, + 'sel' => ((argv(0) == 'articles') ? 'active' : ''), + 'title' => t('View Articles'), + 'id' => 'articles-tab', + 'icon' => 'file-text-o' + ); + } if($has_webpages && feature_enabled($uid,'webpages')) { $tabs[] = array( diff --git a/include/nav.php b/include/nav.php index 2dcf68bc8..8ab401c76 100644 --- a/include/nav.php +++ b/include/nav.php @@ -491,6 +491,17 @@ function channel_apps($is_owner = false, $nickname = null) { ]; } + if($p['view_pages'] && feature_enabled($uid,'articles')) { + $tabs[] = [ + 'label' => t('Articles'), + 'url' => z_root() . '/articles/' . $nickname , + 'sel' => ((argv(0) == 'articles') ? 'active' : ''), + 'title' => t('View Articles'), + 'id' => 'articles-tab', + 'icon' => 'file-text-o' + ]; + } + if($has_webpages && feature_enabled($uid,'webpages')) { $tabs[] = [ diff --git a/include/taxonomy.php b/include/taxonomy.php index 23acaa24d..fbd2a18db 100644 --- a/include/taxonomy.php +++ b/include/taxonomy.php @@ -253,6 +253,56 @@ function card_tagadelic($uid, $count = 0, $authors = '', $owner = '', $flags = 0 } +function article_tagadelic($uid, $count = 0, $authors = '', $owner = '', $flags = 0, $restrict = 0, $type = TERM_CATEGORY) { + + require_once('include/security.php'); + + if(! perm_is_allowed($uid,get_observer_hash(),'view_pages')) + return array(); + + + $item_normal = item_normal(); + $sql_options = item_permissions_sql($uid); + $count = intval($count); + + if($flags) { + if($flags === 'wall') + $sql_options .= " and item_wall = 1 "; + } + + if($authors) { + if(! is_array($authors)) + $authors = array($authors); + + stringify_array_elms($authors,true); + $sql_options .= " and author_xchan in (" . implode(',',$authors) . ") "; + } + + if($owner) { + $sql_options .= " and owner_xchan = '" . dbesc($owner) . "' "; + } + + + // Fetch tags + $r = q("select term, count(term) as total from term left join item on term.oid = item.id + where term.uid = %d and term.ttype = %d + and otype = %d and item_type = %d and item_private = 0 + $sql_options $item_normal + group by term order by total desc %s", + intval($uid), + intval($type), + intval(TERM_OBJ_POST), + intval($restrict), + ((intval($count)) ? "limit $count" : '') + ); + + if(! $r) + return array(); + + return Zotlabs\Text\Tagadelic::calc($r); + +} + @@ -395,6 +445,27 @@ function card_catblock($uid,$count = 0,$authors = '',$owner = '', $flags = 0,$re } +function article_catblock($uid,$count = 0,$authors = '',$owner = '', $flags = 0,$restrict = 0,$type = TERM_CATEGORY) { + $o = ''; + + $r = article_tagadelic($uid,$count,$authors,$owner,$flags,$restrict,$type); + + if($r) { + $c = q("select channel_address from channel where channel_id = %d limit 1", + intval($uid) + ); + + $o = '

' . t('Categories') . '

'; + foreach($r as $rr) { + $o .= ''.$rr[0].' ' . "\r\n"; + } + $o .= '
'; + } + + return $o; +} + + function dir_tagblock($link,$r) { $o = ''; -- cgit v1.2.3 From 4fc8416c3cecb3ece3523a1c5e36ab4d8cd8eb73 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 22 Nov 2017 15:41:09 -0800 Subject: disable until completed --- include/features.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/features.php b/include/features.php index ace1b01c3..8601ff79e 100644 --- a/include/features.php +++ b/include/features.php @@ -126,6 +126,7 @@ function get_features($filtered = true) { feature_level('cards',1), ], +/* reserved, work in progress [ 'articles', t('Articles'), @@ -134,7 +135,7 @@ function get_features($filtered = true) { get_config('feature_lock','articles'), feature_level('articles',1), ], - +*/ [ 'nav_channel_select', t('Navigation Channel Select'), -- cgit v1.2.3 From 8fcf16ee63c86667afe5646ea46d56dd1c96aa08 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 22 Nov 2017 18:39:23 -0800 Subject: optional divider between item header and body --- include/conversation.php | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/conversation.php b/include/conversation.php index 8c75389c4..63d503177 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -628,13 +628,14 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa // "New Item View" on network page or search page results // - just loop through the items and format them minimally for display - - //$tpl = get_markup_template('search_item.tpl'); $tpl = 'search_item.tpl'; foreach($items as $item) { - $x = [ 'mode' => $mode, 'item' => $item ]; + $x = [ + 'mode' => $mode, + 'item' => $item + ]; call_hooks('stream_item',$x); if($x['item']['blocked']) @@ -655,14 +656,7 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE))) && ($item['id'] != $item['parent'])) continue; -// $nickname = $item['nickname']; } -// else -// $nickname = App::$user['nickname']; - -// $profile_name = ((strlen($item['author-name'])) ? $item['author-name'] : $item['name']); -// if($item['author-link'] && (! $item['author-name'])) -// $profile_name = $item['author-link']; $sp = false; $profile_link = best_link_url($item,$sp); @@ -671,8 +665,6 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa else $profile_link = zid($profile_link); -// $normalised = normalise_link((strlen($item['author-link'])) ? $item['author-link'] : $item['url']); - $profile_name = $item['author']['xchan_name']; $profile_link = $item['author']['xchan_url']; $profile_avatar = $item['author']['xchan_photo_m']; @@ -768,6 +760,7 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa 'editedtime' => (($item['edited'] != $item['created']) ? sprintf( t('last edited: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['edited'], 'r')) : ''), 'expiretime' => (($item['expires'] > NULL_DATE) ? sprintf( t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r')):''), 'location' => $location, + 'divider' => false, 'indent' => '', 'owner_name' => $owner_name, 'owner_url' => $owner_url, -- cgit v1.2.3 From 14f12927436f71c753127be83f348d89b99401b6 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 23 Nov 2017 20:22:50 +0100 Subject: fix typo in pipe_streams() --- include/attach.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/attach.php b/include/attach.php index 7988286c9..5b4c24f6f 100644 --- a/include/attach.php +++ b/include/attach.php @@ -1639,7 +1639,7 @@ function find_filename_by_hash($channel_id, $attachHash) { * @param int $bufsize size of chunk, default 16384 * @return number with the size */ -function pipe_streams($in, $out, $bufize = 16384) { +function pipe_streams($in, $out, $bufsize = 16384) { $size = 0; while (!feof($in)) $size += fwrite($out, fread($in, $bufsize)); -- cgit v1.2.3 From a99ebd42ec47ea531496f8ca5c07bf2868e21467 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 23 Nov 2017 15:21:50 -0800 Subject: change to bbcode calling parameters: important: will require pulling addons; also some extra checking of server headers in upload functions --- include/bbcode.php | 8 +++++--- include/markdown.php | 2 +- include/text.php | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/bbcode.php b/include/bbcode.php index 7ebc8d37c..fd476766e 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -707,10 +707,12 @@ function parseIdentityAwareHTML($Text) { return $Text; } - // BBcode 2 HTML was written by WAY2WEB.net - // extended to work with Mistpark/Friendica/Redmatrix/Hubzilla - Mike Macgirvin -function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false) { +function bbcode($Text, $options = []) { + + $preserve_nl = ((array_key_exists('preserve_nl',$options)) ? $options['preserve_nl'] : false); + $tryoembed = ((array_key_exists('tryomebed',$options)) ? $options['tryoembed'] : true); + $cache = ((array_key_exists('cache',$options)) ? $options['cache'] : false); call_hooks('bbcode_filter', $Text); diff --git a/include/markdown.php b/include/markdown.php index f398d279e..e4a35e3c3 100644 --- a/include/markdown.php +++ b/include/markdown.php @@ -204,7 +204,7 @@ function bb_to_markdown($Text, $options = []) { $Text = $x['bbcode']; // Convert it to HTML - don't try oembed - $Text = bbcode($Text, $preserve_nl, false); + $Text = bbcode($Text, [ 'tryoembed' => false ]); // Markdownify does not preserve previously escaped html entities such as <> and &. $Text = str_replace(array('<','>','&'),array('&_lt_;','&_gt_;','&_amp_;'),$Text); diff --git a/include/text.php b/include/text.php index 343e3f00b..f3d522e04 100644 --- a/include/text.php +++ b/include/text.php @@ -1679,9 +1679,9 @@ function prepare_text($text, $content_type = 'text/bbcode', $cache = false) { require_once('include/bbcode.php'); if(stristr($text,'[nosmile]')) - $s = bbcode($text,false,true,$cache); + $s = bbcode($text, [ 'cache' => $cache ]); else - $s = smilies(bbcode($text,false,true,$cache)); + $s = smilies(bbcode($text, [ 'cache' => $cache ])); $s = zidify_links($s); -- cgit v1.2.3 From 3bb0efd2cb393decf71fc717ef7e431a9f65d374 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 23 Nov 2017 20:35:34 -0800 Subject: remove deprecated $a argument from advanced_profile() --- include/channel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/channel.php b/include/channel.php index 708e74176..16afd8209 100644 --- a/include/channel.php +++ b/include/channel.php @@ -1490,7 +1490,7 @@ function gender_icon($gender) { } -function advanced_profile(&$a) { +function advanced_profile() { require_once('include/text.php'); if(! perm_is_allowed(App::$profile['profile_uid'],get_observer_hash(),'view_profile')) return ''; -- cgit v1.2.3 From 87eaa6d8e5a5fece531a8ce191f8e89e90f673c2 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 24 Nov 2017 15:01:34 +0100 Subject: some more work on mod hq --- include/conversation.php | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include') diff --git a/include/conversation.php b/include/conversation.php index 63d503177..70a38ee8e 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -513,6 +513,12 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa } } + elseif ($mode === 'hq') { + $profile_owner = local_channel(); + $page_writeable = true; + $live_update_div = '
' . "\r\n"; + } + elseif ($mode === 'channel') { $profile_owner = App::$profile['profile_uid']; $page_writeable = ($profile_owner == local_channel()); -- cgit v1.2.3 From fda5231a719025c0e2d7cc3954ebbab5b0d53586 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Fri, 24 Nov 2017 14:55:39 -0800 Subject: default profile assign --- include/follow.php | 3 +++ include/zot.php | 2 ++ 2 files changed, 5 insertions(+) (limited to 'include') diff --git a/include/follow.php b/include/follow.php index 56d8294c5..0843802c5 100644 --- a/include/follow.php +++ b/include/follow.php @@ -226,6 +226,8 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false) } + $profile_assign = get_pconfig($uid,'system','profile_assign',''); + $r = q("select abook_id, abook_xchan, abook_pending, abook_instance from abook where abook_xchan = '%s' and abook_channel = %d limit 1", @@ -265,6 +267,7 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false) 'abook_channel' => intval($uid), 'abook_closeness' => intval($closeness), 'abook_xchan' => $xchan_hash, + 'abook_profile' => $profile_assign, 'abook_feed' => intval(($xchan['xchan_network'] === 'rss') ? 1 : 0), 'abook_created' => datetime_convert(), 'abook_updated' => datetime_convert(), diff --git a/include/zot.php b/include/zot.php index 40e303bf1..d60494d94 100644 --- a/include/zot.php +++ b/include/zot.php @@ -394,6 +394,7 @@ function zot_refresh($them, $channel = null, $force = false) { $next_birthday = NULL_DATE; } + $profile_assign = get_pconfig($channel['channel_id'],'system','profile_assign',''); // Keep original perms to check if we need to notify them $previous_perms = get_all_perms($channel['channel_id'],$x['hash']); @@ -455,6 +456,7 @@ function zot_refresh($them, $channel = null, $force = false) { 'abook_channel' => intval($channel['channel_id']), 'abook_closeness' => intval($closeness), 'abook_xchan' => $x['hash'], + 'abook_profile' => $profile_assign, 'abook_created' => datetime_convert(), 'abook_updated' => datetime_convert(), 'abook_dob' => $next_birthday, -- cgit v1.2.3 From 9dd545f4205a0f543a883422135e560c4ec74ad1 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Fri, 24 Nov 2017 15:39:00 -0800 Subject: don't include invisible "update activities" in category widget --- include/contact_widgets.php | 61 +++++++++++++++++++++++---------------------- include/taxonomy.php | 10 +++++--- 2 files changed, 37 insertions(+), 34 deletions(-) (limited to 'include') diff --git a/include/contact_widgets.php b/include/contact_widgets.php index b36471924..a105bca19 100644 --- a/include/contact_widgets.php +++ b/include/contact_widgets.php @@ -72,21 +72,22 @@ function categories_widget($baseurl,$selected = '') { $item_normal = item_normal(); $terms = array(); - $r = q("select distinct(term.term) - from term join item on term.oid = item.id - where item.uid = %d - and term.uid = item.uid - and term.ttype = %d - and term.otype = %d - and item.owner_xchan = '%s' - and item.item_wall = 1 - $item_normal - $sql_extra - order by term.term asc", + $r = q("select distinct(term.term) from term join item on term.oid = item.id + where item.uid = %d + and term.uid = item.uid + and term.ttype = %d + and term.otype = %d + and item.owner_xchan = '%s' + and item.item_wall = 1 + and item.verb != '%s' + $item_normal + $sql_extra + order by term.term asc", intval(App::$profile['profile_uid']), - intval(TERM_CATEGORY), - intval(TERM_OBJ_POST), - dbesc(App::$profile['channel_hash']) + intval(TERM_CATEGORY), + intval(TERM_OBJ_POST), + dbesc(App::$profile['channel_hash']), + dbesc(ACTIVITY_UPDATE) ); if($r && count($r)) { foreach($r as $rr) @@ -118,19 +119,19 @@ function cardcategories_widget($baseurl,$selected = '') { $terms = array(); $r = q("select distinct(term.term) - from term join item on term.oid = item.id - where item.uid = %d - and term.uid = item.uid - and term.ttype = %d + from term join item on term.oid = item.id + where item.uid = %d + and term.uid = item.uid + and term.ttype = %d and term.otype = %d - and item.owner_xchan = '%s' + and item.owner_xchan = '%s' $item_normal $sql_extra - order by term.term asc", + order by term.term asc", intval(App::$profile['profile_uid']), - intval(TERM_CATEGORY), + intval(TERM_CATEGORY), intval(TERM_OBJ_POST), - dbesc(App::$profile['channel_hash']) + dbesc(App::$profile['channel_hash']) ); if($r && count($r)) { foreach($r as $rr) @@ -163,19 +164,19 @@ function articlecategories_widget($baseurl,$selected = '') { $terms = array(); $r = q("select distinct(term.term) - from term join item on term.oid = item.id - where item.uid = %d - and term.uid = item.uid - and term.ttype = %d + from term join item on term.oid = item.id + where item.uid = %d + and term.uid = item.uid + and term.ttype = %d and term.otype = %d - and item.owner_xchan = '%s' + and item.owner_xchan = '%s' $item_normal $sql_extra - order by term.term asc", + order by term.term asc", intval(App::$profile['profile_uid']), - intval(TERM_CATEGORY), + intval(TERM_CATEGORY), intval(TERM_OBJ_POST), - dbesc(App::$profile['channel_hash']) + dbesc(App::$profile['channel_hash']) ); if($r && count($r)) { foreach($r as $rr) diff --git a/include/taxonomy.php b/include/taxonomy.php index fbd2a18db..a13a9cf77 100644 --- a/include/taxonomy.php +++ b/include/taxonomy.php @@ -55,18 +55,20 @@ function term_item_parent_query($uid,$table,$s,$type = TERM_UNKNOWN, $type2 = '' $s = str_replace('*','%',$s); if($type2) { - $r = q("select parent from item left join term on term.oid = item.id where term.ttype in (%d, %d) and term.term like '%s' and term.uid = %d and term.otype = 1", + $r = q("select parent from item left join term on term.oid = item.id where term.ttype in (%d, %d) and term.term like '%s' and term.uid = %d and term.otype = 1 and item.verb != '%s'", intval($type), intval($type2), dbesc($s), - intval($uid) + intval($uid), + dbesc(ACTIVITY_UPDATE) ); } else { - $r = q("select parent from item left join term on term.oid = item.id where term.ttype = %d and term.term like '%s' and term.uid = %d and term.otype = 1", + $r = q("select parent from item left join term on term.oid = item.id where term.ttype = %d and term.term like '%s' and term.uid = %d and term.otype = 1 and item.verb != '%s'", intval($type), dbesc($s), - intval($uid) + intval($uid), + dbesc(ACTIVITY_UPDATE) ); } -- cgit v1.2.3 From 08900b730bd39c00e399696472d904c1d5e4ef0b Mon Sep 17 00:00:00 2001 From: zotlabs Date: Fri, 24 Nov 2017 18:23:53 -0800 Subject: this may fix pubstream comments/likes --- include/items.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'include') diff --git a/include/items.php b/include/items.php index 654cc5de3..042deed1b 100755 --- a/include/items.php +++ b/include/items.php @@ -1749,6 +1749,22 @@ function item_store($arr, $allow_exec = false, $deliver = true) { intval($arr['uid']) ); + // perhaps the system channel owns the post and it's a pubstream item + + if(! $r) { + $s = q("select channel_id from channel where channel_system = 1 limit 1"); + if($s) { + $r = q("SELECT * FROM item WHERE mid = '%s' AND uid = %d ORDER BY id ASC LIMIT 1", + dbesc($arr['parent_mid']), + intval($s[0]['channel_id']) + ); + } + if($r) { + $arr['uid'] = $r[0]['uid']; + $arr['aid'] = 0; + } + } + if($r) { // in case item_store was killed before the parent's parent attribute got set, -- cgit v1.2.3 From 0e91810ed6764fbbee54e918711bfb45a1d9fd72 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 26 Nov 2017 18:29:24 -0800 Subject: pubstream comments and a few other bugfixes that were discovered along the way --- include/conversation.php | 4 +-- include/feedutils.php | 31 +++++++++++++++++---- include/items.php | 72 +++++++++++++++++++++++++++++++++++++----------- 3 files changed, 83 insertions(+), 24 deletions(-) (limited to 'include') diff --git a/include/conversation.php b/include/conversation.php index 70a38ee8e..841a00d85 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -482,10 +482,10 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa $previewing = (($preview) ? ' preview ' : ''); $preview_lbl = t('This is an unsaved preview'); - if ($mode === 'network') { + if (in_array($mode, [ 'network', 'pubstream'])) { $profile_owner = local_channel(); - $page_writeable = true; + $page_writeable = ((local_channel()) ? true : false); if (!$update) { // The special div is needed for liveUpdate to kick in for this page. diff --git a/include/feedutils.php b/include/feedutils.php index 50f76b550..8f2c5d988 100644 --- a/include/feedutils.php +++ b/include/feedutils.php @@ -65,15 +65,34 @@ function get_feed_for($channel, $observer_hash, $params) { if(! $channel) http_status_exit(401); + + // logger('params: ' . print_r($params,true)); + + + $interactive = ((is_array($params) && array_key_exists('interactive',$params)) ? intval($params['interactive']) : 0); + + if($params['pages']) { - if(! perm_is_allowed($channel['channel_id'],$observer_hash,'view_pages')) - http_status_exit(403); - } else { - if(! perm_is_allowed($channel['channel_id'],$observer_hash,'view_stream')) - http_status_exit(403); + if(! perm_is_allowed($channel['channel_id'],$observer_hash,'view_pages')) { + if($interactive) { + return ''; + } + else { + http_status_exit(403); + } + } + } + else { + if(! perm_is_allowed($channel['channel_id'],$observer_hash,'view_stream')) { + if($interactive) { + return ''; + } + else { + http_status_exit(403); + } + } } - // logger('params: ' . print_r($params,true)); $feed_template = get_markup_template('atom_feed.tpl'); diff --git a/include/items.php b/include/items.php index 042deed1b..baf11ac69 100755 --- a/include/items.php +++ b/include/items.php @@ -1749,22 +1749,6 @@ function item_store($arr, $allow_exec = false, $deliver = true) { intval($arr['uid']) ); - // perhaps the system channel owns the post and it's a pubstream item - - if(! $r) { - $s = q("select channel_id from channel where channel_system = 1 limit 1"); - if($s) { - $r = q("SELECT * FROM item WHERE mid = '%s' AND uid = %d ORDER BY id ASC LIMIT 1", - dbesc($arr['parent_mid']), - intval($s[0]['channel_id']) - ); - } - if($r) { - $arr['uid'] = $r[0]['uid']; - $arr['aid'] = 0; - } - } - if($r) { // in case item_store was killed before the parent's parent attribute got set, @@ -4725,3 +4709,59 @@ function item_create_edit_activity($post) { \Zotlabs\Daemon\Master::Summon(array('Notifier', 'edit_activity', $post_id)); } + +/** + * @brief copies an entire conversation from the pubstream to this channel's stream + * which will allow you to interact with it. + */ + + + +function copy_of_pubitem($channel,$mid) { + + $result = null; + $syschan = get_sys_channel(); + + // logger('copy_of_pubitem: ' . $channel['channel_id'] . ' mid: ' . $mid); + + $r = q("select * from item where mid = '%s' and uid = %d limit 1", + dbesc($mid), + intval($channel['channel_id']) + ); + + if($r) { + logger('exists'); + $item = fetch_post_tags($r,true); + return $item[0]; + } + + + $r = q("select * from item where parent_mid = (select parent_mid from item where mid = '%s' and uid = %d ) order by id ", + dbesc($mid), + intval($syschan['channel_id']) + ); + + if($r) { + $items = fetch_post_tags($r,true); + foreach($items as $rv) { + $d = q("select id from item where mid = '%s' and uid = %d limit 1", + dbesc($rv['mid']), + intval($channel['channel_id']) + ); + if($d) { + continue; + } + + unset($rv['id']); + unset($rv['parent']); + $rv['aid'] = $channel['channel_account_id']; + $rv['uid'] = $channel['channel_id']; + $x = item_store($rv); + if($x['item_id'] && $x['item']['mid'] === $mid) { + $result = $x['item']; + } + + } + } + return $result; +} -- cgit v1.2.3 From dc53573975361075c62cd7f9721bac2e8eff8ea8 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 27 Nov 2017 02:47:57 -0800 Subject: unset item_wall and item_origin on pubstream to channel copy --- include/items.php | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/items.php b/include/items.php index baf11ac69..e4727e19e 100755 --- a/include/items.php +++ b/include/items.php @@ -4756,6 +4756,9 @@ function copy_of_pubitem($channel,$mid) { unset($rv['parent']); $rv['aid'] = $channel['channel_account_id']; $rv['uid'] = $channel['channel_id']; + $rv['item_wall'] = 0; + $rv['item_origin'] = 0; + $x = item_store($rv); if($x['item_id'] && $x['item']['mid'] === $mid) { $result = $x['item']; -- cgit v1.2.3 From 76703dee8481075a44b254a548bb29b49530d0ad Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 28 Nov 2017 17:37:18 -0800 Subject: more chunk work --- include/attach.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/attach.php b/include/attach.php index 5b4c24f6f..86c792ed9 100644 --- a/include/attach.php +++ b/include/attach.php @@ -2506,7 +2506,7 @@ function save_chunk($channel,$start,$end,$len) { } if(($len - 1) == $end) { unlink($tmp_path); - $result['name'] = $_FILES['files']['tmp_name']; + $result['name'] = $_FILES['files']['name']; $result['type'] = $_FILES['files']['type']; $result['tmp_name'] = $new_path; $result['error'] = 0; -- cgit v1.2.3 From 5abcb8c97813d66b63ca697ca626347a9fd8d95c Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 29 Nov 2017 13:51:54 -0800 Subject: use httpsig auth for getfile --- include/import.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/import.php b/include/import.php index 702fa7e54..8cab16342 100644 --- a/include/import.php +++ b/include/import.php @@ -1199,7 +1199,14 @@ function sync_files($channel, $files) { continue; } $redirects = 0; - $x = z_post_url($fetch_url,$parr,$redirects,array('filep' => $fp)); + + + $headers = []; + $headers['Accept'] = 'application/x-zot+json' ; + $headers['Sigtoken'] = random_string(); + $headers = \Zotlabs\Web\HTTPSig::create_sig('',$headers,$channel['channel_prvkey'], 'acct:' . $channel['channel_address'] . '@' . \App::get_hostname(),false,true,'sha512'); + + $x = z_post_url($fetch_url,$parr,$redirects,[ 'filep' => $fp, 'headers' => $headers]); fclose($fp); if($x['success']) { -- cgit v1.2.3 From dae0107dd0e1caa460866b5debdc6de912bfd819 Mon Sep 17 00:00:00 2001 From: Mario Date: Sun, 3 Dec 2017 12:31:41 +0100 Subject: fix some pubstream on/off weirdness --- include/nav.php | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/nav.php b/include/nav.php index 8ab401c76..66c4c1556 100644 --- a/include/nav.php +++ b/include/nav.php @@ -73,6 +73,11 @@ EOT; // nav links: array of array('href', 'text', 'extra css classes', 'title') $nav = []; + $disable_discover_tab = get_config('system','disable_discover_tab') || get_config('system','disable_discover_tab') === false; + + if(! $disable_discover_tab) + $nav['pubs'] = true; + /** * Display login or logout */ -- cgit v1.2.3 From 91e3c5c34e93004b9641d906c9f512b42f9c4a7a Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 3 Dec 2017 19:30:36 -0800 Subject: render installable elements as buttons instead of links --- include/bbcode.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/bbcode.php b/include/bbcode.php index fd476766e..e38473168 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -246,8 +246,8 @@ function bb_parse_element($match) { $j = json_decode(base64url_decode($match[1]),true); if ($j && local_channel()) { - $text = sprintf( t('Install %s element: '), translate_design_element($j['type'])) . $j['pagetitle']; - $o = EOL . '' . $text . '' . EOL; + $text = sprintf( t('Install %1$s element %2$s'), translate_design_element($j['type']), $j['pagetitle']); + $o = EOL . '' . EOL; } else { $text = sprintf( t('This post contains an installable %s element, however you lack permissions to install it on this site.' ), translate_design_element($j['type'])) . $j['pagetitle']; -- cgit v1.2.3 From 5c12b56e87982be11ae8cb1f10182d354db47fa7 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 4 Dec 2017 08:56:01 +0100 Subject: PHP 7.2 silence some warnings --- include/conversation.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/conversation.php b/include/conversation.php index 841a00d85..fc0942474 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -1473,7 +1473,7 @@ function sort_item_children($items) { $result = $items; usort($result,'sort_thr_created_rev'); foreach($result as $k => $i) { - if(count($result[$k]['children'])) { + if($result[$k]['children']) { $result[$k]['children'] = sort_item_children($result[$k]['children']); } } @@ -1483,7 +1483,7 @@ function sort_item_children($items) { function add_children_to_list($children, &$arr) { foreach($children as $y) { $arr[] = $y; - if(count($y['children'])) + if($y['children']) add_children_to_list($y['children'], $arr); } } -- cgit v1.2.3 From ffaab27e77844c47501b9fd8202a6b94792c3686 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 6 Dec 2017 14:20:17 -0800 Subject: synchronise an attach_move operation to clones --- include/attach.php | 6 ++++-- include/import.php | 9 ++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/attach.php b/include/attach.php index 86c792ed9..b1199507d 100644 --- a/include/attach.php +++ b/include/attach.php @@ -276,6 +276,8 @@ function attach_by_hash($hash, $observer_hash, $rev = 0) { return $ret; } + $r[0]['content'] = dbunescbin($r[0]['content']); + if($r[0]['folder']) { $x = attach_can_view_folder($r[0]['uid'],$observer_hash,$r[0]['folder']); if(! $x) { @@ -2037,6 +2039,7 @@ function attach_export_data($channel, $resource_id, $deleted = false) { if($hash_ptr === $resource_id) { $attach_ptr = $r[0]; } + $r[0]['content'] = dbunescbin($r[0]['content']); $hash_ptr = $r[0]['folder']; $paths[] = $r[0]; @@ -2222,7 +2225,6 @@ function copy_folder_to_cloudfiles($channel, $observer_hash, $srcpath, $cloudpat * the attach.hash of the new parent folder, which must already exist. If $new_folder_hash is blank or empty, * the file is relocated to the root of the channel's storage area. * - * @fixme: this operation is currently not synced to clones !! * * @param int $channel_id * @param int $resource_id @@ -2245,7 +2247,7 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) { $oldstorepath = dbunescbin($r[0]['content']); if($new_folder_hash) { - $n = q("select * from attach where hash = '%s' and uid = %d limit 1", + $n = q("select * from attach where hash = '%s' and uid = %d and is_dir = 1 limit 1", dbesc($new_folder_hash), intval($channel_id) ); diff --git a/include/import.php b/include/import.php index 8cab16342..cd7056497 100644 --- a/include/import.php +++ b/include/import.php @@ -1081,6 +1081,7 @@ function sync_files($channel, $files) { logger('sync_files duplicate check: attach_by_hash() returned ' . print_r($x,true), LOGGER_DEBUG); if($x['success']) { + $orig_attach = $x[0]; $attach_exists = true; $attach_id = $x[0]['id']; } @@ -1145,12 +1146,18 @@ function sync_files($channel, $files) { // If the hash ever contains any escapable chars this could cause // problems. Currently it does not. - /// @TODO implement os_path if(!isset($att['os_path'])) $att['os_path'] = ''; if($attach_exists) { logger('sync_files attach exists: ' . print_r($att,true), LOGGER_DEBUG); + + // process/sync a remote rename/move operation + + if($orig_attach['content'] !== $newfname) { + rename($orig_attach['content'],$newfname); + } + if(! dbesc_array($att)) continue; -- cgit v1.2.3 From d326e7a75c58e49d84d286f89a97573dbc3e870b Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 6 Dec 2017 16:07:40 -0800 Subject: hubzilla issue #680, implement IMoveTarget and recursive file/directory move/rename --- include/attach.php | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/attach.php b/include/attach.php index b1199507d..3a802bd11 100644 --- a/include/attach.php +++ b/include/attach.php @@ -2234,7 +2234,7 @@ function copy_folder_to_cloudfiles($channel, $observer_hash, $srcpath, $cloudpat function attach_move($channel_id, $resource_id, $new_folder_hash) { $c = channelx_by_n($channel_id); - if(! $c) + if(! ($c && $resource_id)) return false; $r = q("select * from attach where hash = '%s' and uid = %d limit 1", @@ -2246,13 +2246,32 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) { $oldstorepath = dbunescbin($r[0]['content']); + if($r[0]['is_dir']) { + $move_success = true; + $x = q("select hash from attach where folder = '%s' and uid = %d", + dbesc($r[0]['hash']), + intval($channel_id) + ); + if($x) { + foreach($x as $xv) { + $rs = attach_move($channel_id,$xv['hash'],$r[0]['hash']); + if(! $rs) { + $move_success = false; + break; + } + } + } + return $move_success; + } + + if($new_folder_hash) { $n = q("select * from attach where hash = '%s' and uid = %d and is_dir = 1 limit 1", dbesc($new_folder_hash), intval($channel_id) ); if(! $n) - return; + return false; $newdirname = $n[0]['filename']; $newstorepath = dbunescbin($n[0]['content']) . '/' . $resource_id; -- cgit v1.2.3 From 85b7c90637b03d4f3093f6a3557d807dbd6dd8b3 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 7 Dec 2017 18:56:26 -0800 Subject: strip acct: from OWA auth to API endpoints --- include/api_auth.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/api_auth.php b/include/api_auth.php index 0818fa54b..5c0bcb317 100644 --- a/include/api_auth.php +++ b/include/api_auth.php @@ -52,6 +52,7 @@ function api_login(&$a){ /* Signature authentication */ if(array_key_exists($head,$_SERVER) && substr(trim($_SERVER[$head]),0,9) === 'Signature') { + if($head !== 'HTTP_AUTHORIZATION') { $_SERVER['HTTP_AUTHORIZATION'] = $_SERVER[$head]; continue; @@ -59,7 +60,7 @@ function api_login(&$a){ $sigblock = \Zotlabs\Web\HTTPSig::parse_sigheader($_SERVER[$head]); if($sigblock) { - $keyId = $sigblock['keyId']; + $keyId = str_replace('acct:','',$sigblock['keyId']); if($keyId) { $r = q("select * from hubloc where hubloc_addr = '%s' limit 1", dbesc($keyId) -- cgit v1.2.3 From adec67d5fa616c23c6265233f2a19d94d09df2e6 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sat, 9 Dec 2017 12:49:28 -0800 Subject: hubzilla-addons issues #73 --- include/bbcode.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/bbcode.php b/include/bbcode.php index e38473168..ed34bc5d6 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -711,7 +711,7 @@ function parseIdentityAwareHTML($Text) { function bbcode($Text, $options = []) { $preserve_nl = ((array_key_exists('preserve_nl',$options)) ? $options['preserve_nl'] : false); - $tryoembed = ((array_key_exists('tryomebed',$options)) ? $options['tryoembed'] : true); + $tryoembed = ((array_key_exists('tryoembed',$options)) ? $options['tryoembed'] : true); $cache = ((array_key_exists('cache',$options)) ? $options['cache'] : false); -- cgit v1.2.3 From ad6cb63e0762a3af3ee0340bd3df80e482c977ef Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sat, 9 Dec 2017 12:56:11 -0800 Subject: xlink_rating_text default value --- include/socgraph.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/socgraph.php b/include/socgraph.php index 3c7a893c6..26446d9c7 100644 --- a/include/socgraph.php +++ b/include/socgraph.php @@ -178,9 +178,11 @@ function poco_load($xchan = '', $url = null) { ); if(! $r) { - q("insert into xlink ( xlink_xchan, xlink_link, xlink_updated, xlink_static ) values ( '%s', '%s', '%s', 0 ) ", + q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_updated, xlink_static ) values ( '%s', '%s', %d, '%s', '%s', 0 ) ", dbesc($xchan), dbesc($hash), + intval(0), + dbesc(''), dbesc(datetime_convert()) ); } -- cgit v1.2.3 From 27bc5fa4b0f66c47f668c6c6efda77f9732bb603 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 10 Dec 2017 15:25:44 -0800 Subject: improvements to file import/export --- include/api_zot.php | 11 +++++++++-- include/attach.php | 22 +++++++++++++++------- include/import.php | 37 +++++++++++++++++++++++++++++++++++-- 3 files changed, 59 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/include/api_zot.php b/include/api_zot.php index aaa9ee497..54f905b4c 100644 --- a/include/api_zot.php +++ b/include/api_zot.php @@ -150,7 +150,11 @@ $start = ((array_key_exists('start',$_REQUEST)) ? intval($_REQUEST['start']) : 0); $records = ((array_key_exists('records',$_REQUEST)) ? intval($_REQUEST['records']) : 0); - $x = attach_list_files(api_user(),get_observer_hash(),$hash,$filename,$filetype,'created asc',$start,$records); + $since = ((array_key_exists('since',$_REQUEST)) ? datetime_convert(date_default_timezone_get(),'UTC',$_REQUEST['since']) : NULL_DATE); + $until = ((array_key_exists('until',$_REQUEST)) ? datetime_convert(date_default_timezone_get(),'UTC',$_REQUEST['until']) : datetime_convert()); + + $x = attach_list_files(api_user(),get_observer_hash(),$hash,$filename,$filetype,'created asc',$start,$records, $since, $until); + if($start || $records) { $x['start'] = $start; $x['records'] = count($x['results']); @@ -226,7 +230,10 @@ if(! $_REQUEST['file_id']) return false; - $ret = attach_export_data(api_user(),$_REQUEST['file_id']); + $channel = channelx_by_n(api_user()); + + $ret = attach_export_data($channel,$_REQUEST['file_id']); + if($ret) { json_return_and_die($ret); } diff --git a/include/attach.php b/include/attach.php index 3a802bd11..4b8841a88 100644 --- a/include/attach.php +++ b/include/attach.php @@ -189,7 +189,7 @@ function attach_count_files($channel_id, $observer, $hash = '', $filename = '', * * \e array|boolean \b results array with results, or false * * \e string \b message with error messages if any */ -function attach_list_files($channel_id, $observer, $hash = '', $filename = '', $filetype = '', $orderby = 'created desc', $start = 0, $entries = 0) { +function attach_list_files($channel_id, $observer, $hash = '', $filename = '', $filetype = '', $orderby = 'created desc', $start = 0, $entries = 0, $since = '', $until = '') { $ret = array('success' => false); @@ -198,6 +198,7 @@ function attach_list_files($channel_id, $observer, $hash = '', $filename = '', $ return $ret; } + require_once('include/security.php'); $sql_extra = permissions_sql($channel_id); @@ -213,14 +214,22 @@ function attach_list_files($channel_id, $observer, $hash = '', $filename = '', $ if($entries) $limit = " limit " . intval($start) . ", " . intval($entries) . " "; - // Retrieve all columns except 'data' + if(! $since) + $since = NULL_DATE; + + if(! $until) + $until = datetime_convert(); + + $sql_extra .= " and created >= '" . dbesc($since) . "' and created <= '" . dbesc($until) . "' "; + + // Retrieve all columns except 'content' $r = q("select id, aid, uid, hash, filename, filetype, filesize, revision, folder, os_path, display_path, os_storage, is_dir, is_photo, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where uid = %d $sql_extra ORDER BY $orderby $limit", intval($channel_id) ); $ret['success'] = ((is_array($r)) ? true : false); - $ret['results'] = ((is_array($r)) ? $r : false); + $ret['results'] = ((is_array($r)) ? $r : []); return $ret; } @@ -2052,14 +2061,13 @@ function attach_export_data($channel, $resource_id, $deleted = false) { if($attach_ptr['is_photo']) { - $r = q("select * from photo where resource_id = '%s' and uid = %d order by imgscale asc", + + $r = q("select aid,uid,xchan,resource_id,created,edited,title,description,album,filename,mimetype,height,width,filesize,imgscale,photo_usage,profile,is_nsfw,os_storage,display_path,photo_flags,allow_cid,allow_gid,deny_cid,deny_gid from photo where resource_id = '%s' and uid = %d order by imgscale asc", dbesc($resource_id), intval($channel['channel_id']) ); + if($r) { - for($x = 0; $x < count($r); $x ++) { - $r[$x]['content'] = base64_encode(dbunescbin($r[$x]['content'])); - } $ret['photo'] = $r; } diff --git a/include/import.php b/include/import.php index cd7056497..a5e8adeb5 100644 --- a/include/import.php +++ b/include/import.php @@ -1263,10 +1263,43 @@ function sync_files($channel, $files) { ); } - if($p['imgscale'] === 0 && $p['os_storage']) + if(intval($p['imgscale']) === 0 && $p['os_storage']) $p['content'] = $store_path; else - $p['content'] = base64_decode($p['content']); + $p['content'] = (($p['content'])? base64_decode($p['content']) : ''); + + if(intval($p['imgscale']) && (! $p['content'])) { + + $time = datetime_convert(); + + $parr = array('hash' => $channel['channel_hash'], + 'time' => $time, + 'resource' => $att['hash'], + 'revision' => 0, + 'signature' => base64url_encode(rsa_sign($channel['channel_hash'] . '.' . $time, $channel['channel_prvkey'])), + 'resolution' => $p['imgscale'] + ); + + $stored_image = $newfname . '-' . intval($p['imgscale']); + + $fp = fopen($stored_image,'w'); + if(! $fp) { + logger('failed to open storage file.',LOGGER_NORMAL,LOG_ERR); + continue; + } + $redirects = 0; + + + $headers = []; + $headers['Accept'] = 'application/x-zot+json' ; + $headers['Sigtoken'] = random_string(); + $headers = \Zotlabs\Web\HTTPSig::create_sig('',$headers,$channel['channel_prvkey'], 'acct:' . $channel['channel_address'] . '@' . \App::get_hostname(),false,true,'sha512'); + + $x = z_post_url($fetch_url,$parr,$redirects,[ 'filep' => $fp, 'headers' => $headers]); + fclose($fp); + $p['content'] = file_get_contents($stored_image); + unlink($stored_image); + } if(!isset($p['display_path'])) $p['display_path'] = ''; -- cgit v1.2.3 From fca1a7506e2f60164ac885f60a6ce1ef03cfa865 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 10 Dec 2017 15:54:40 -0800 Subject: go back to including the photo thumbnail data in the export file. We have the ability to fetch each thumbnail directly if there is a problem with resource consumption, but this is the most efficient way to deal with it and most sites should be able to handle the memory consumption of our thumbnail data. The original full scale photo is a different issue; these can exhaust memory even before base64. --- include/attach.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/attach.php b/include/attach.php index 4b8841a88..88b6fa8e7 100644 --- a/include/attach.php +++ b/include/attach.php @@ -2062,15 +2062,30 @@ function attach_export_data($channel, $resource_id, $deleted = false) { if($attach_ptr['is_photo']) { - $r = q("select aid,uid,xchan,resource_id,created,edited,title,description,album,filename,mimetype,height,width,filesize,imgscale,photo_usage,profile,is_nsfw,os_storage,display_path,photo_flags,allow_cid,allow_gid,deny_cid,deny_gid from photo where resource_id = '%s' and uid = %d order by imgscale asc", + // This query could potentially result in a few megabytes of data use. + + $r = q("select * from photo where resource_id = '%s' and uid = %d order by imgscale asc", dbesc($resource_id), intval($channel['channel_id']) ); - if($r) { + for($x = 0; $x < count($r); $x ++) { + $r[$x]['content'] = base64_encode(dbunescbin($r[$x]['content'])); + } $ret['photo'] = $r; } +// This query can be used instead in memory starved environments. There will be a corresponding +// performance hit during sync because the data will need to be fetched over the network. +// $r = q("select aid,uid,xchan,resource_id,created,edited,title,description,album,filename,mimetype,height,width,filesize,imgscale,photo_usage,profile,is_nsfw,os_storage,display_path,photo_flags,allow_cid,allow_gid,deny_cid,deny_gid from photo where resource_id = '%s' and uid = %d order by imgscale asc", +// dbesc($resource_id), +// intval($channel['channel_id']) +// ); + +// if($r) { +// $ret['photo'] = $r; +// } + $r = q("select * from item where resource_id = '%s' and resource_type = 'photo' and uid = %d ", dbesc($resource_id), intval($channel['channel_id']) -- cgit v1.2.3 From c2990964f07edaae447587e50c28e9a9eeb9bc80 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 10 Dec 2017 18:38:50 -0800 Subject: regression in channel sources delivery --- include/items.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/items.php b/include/items.php index e4727e19e..7948a7c22 100755 --- a/include/items.php +++ b/include/items.php @@ -2694,8 +2694,8 @@ function tag_deliver($uid, $item_id) { } - if((! $mention) && (! $union)) { - logger('No mention for ' . $u[0]['channel_name'] . ' and no union.'); + if(! $mention) { + logger('No mention for ' . $u[0]['channel_name']); continue; } @@ -2714,6 +2714,18 @@ function tag_deliver($uid, $item_id) { } } + + if($union) { + if(intval($item['item_wall']) || intval($item['item_origin']) || (! intval($item['item_thread_top'])) || ($item['id'] != $item['parent'])) { + logger('Item was local or a comment. rejected.'); + return; + } + + logger('Creating second delivery chain.'); + start_delivery_chain($u[0],$item,$item_id,null); + + } + } /** -- cgit v1.2.3 From 4859e6e11a725c345de24749f8600a20ea0a4c2f Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 10 Dec 2017 19:43:54 -0800 Subject: sql compliance issue --- include/channel.php | 2 +- include/zot.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/channel.php b/include/channel.php index 16afd8209..2d40b7db6 100644 --- a/include/channel.php +++ b/include/channel.php @@ -325,7 +325,7 @@ function create_identity($arr) { 'hubloc_guid_sig' => $sig, 'hubloc_hash' => $hash, 'hubloc_addr' => channel_reddress($ret['channel']), - 'hubloc_primary' => $primary, + 'hubloc_primary' => intval($primary), 'hubloc_url' => z_root(), 'hubloc_url_sig' => base64url_encode(rsa_sign(z_root(),$ret['channel']['channel_prvkey'])), 'hubloc_host' => App::get_hostname(), diff --git a/include/zot.php b/include/zot.php index d60494d94..6c0d92a42 100644 --- a/include/zot.php +++ b/include/zot.php @@ -2552,7 +2552,7 @@ function sync_locations($sender, $arr, $absolute = false) { 'hubloc_hash' => $sender['hash'], 'hubloc_addr' => $location['address'], 'hubloc_network' => 'zot', - 'hubloc_primary' => $location['primary'], + 'hubloc_primary' => intval($location['primary']), 'hubloc_url' => $location['url'], 'hubloc_url_sig' => $location['url_sig'], 'hubloc_host' => $location['host'], -- cgit v1.2.3 From 5b1ef760a06dd892a6decf6a621e710b5ae4e7bd Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 11 Dec 2017 16:50:25 +0100 Subject: notification: slight animation for loading... and do not remove public stream items on click (we can not mark them read) --- include/nav.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/nav.php b/include/nav.php index 66c4c1556..2366fe7f1 100644 --- a/include/nav.php +++ b/include/nav.php @@ -313,7 +313,7 @@ EOT; '$sitelocation' => $sitelocation, '$nav' => $x['nav'], '$banner' => $banner, - '$emptynotifications' => t('Loading...'), + '$emptynotifications' => t('Loading'), '$userinfo' => $x['usermenu'], '$localuser' => local_channel(), '$is_owner' => $is_owner, -- cgit v1.2.3 From 494ce9b87230c1745ec9da8cf60fa448cac4f187 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 12 Dec 2017 14:16:34 -0800 Subject: hubzilla #475 continued - show photos in root folder. Part of Andrew's fix for this wasn't in my repository and hopefully won't conflict; as it appears to have been lost somewhere. It also needed a small change to the folder permissions check. --- include/attach.php | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/attach.php b/include/attach.php index 88b6fa8e7..e94454905 100644 --- a/include/attach.php +++ b/include/attach.php @@ -308,6 +308,11 @@ function attach_can_view_folder($uid,$ob_hash,$folder_hash) { $hash = $folder_hash; $result = false; + if(! $folder_hash) { + return perm_is_allowed($uid,$ob_hash,'view_storage'); + } + + do { $r = q("select folder from attach where hash = '%s' and uid = %d $sql_extra", dbesc($hash), -- cgit v1.2.3 From 48be6ad5c4911286e10895a85a405b81f36b222b Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 14 Dec 2017 21:48:30 +0100 Subject: make remote homelink link to the home host and not to the home channel --- include/nav.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/nav.php b/include/nav.php index 2366fe7f1..8566cc58c 100644 --- a/include/nav.php +++ b/include/nav.php @@ -176,13 +176,15 @@ EOT; } - - $homelink = get_my_url(); - if(! $homelink) { + $my_url = get_my_url(); + if(! $my_url) { $observer = App::get_observer(); - $homelink = (($observer) ? $observer['xchan_url'] : ''); + $my_url = (($observer) ? $observer['xchan_url'] : ''); } + $homelink_arr = parse_url($my_url); + $homelink = $homelink_arr['scheme'] . '://' . $homelink_arr['host']; + if(! $is_owner) { $nav['rusermenu'] = array( $homelink, -- cgit v1.2.3 From 814dfcd4ac50a8e0c09bc944f3605eb04e12f9b9 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 14 Dec 2017 22:10:56 +0100 Subject: fix some more PHP7.2 warnings --- include/conversation.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/conversation.php b/include/conversation.php index fc0942474..77694deb3 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -755,8 +755,8 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa 'forged' => $forged, 'txt_cats' => t('Categories:'), 'txt_folders' => t('Filed under:'), - 'has_cats' => ((count($body['categories'])) ? 'true' : ''), - 'has_folders' => ((count($body['folders'])) ? 'true' : ''), + 'has_cats' => (($body['categories']) ? 'true' : ''), + 'has_folders' => (($body['folders']) ? 'true' : ''), 'text' => strip_tags($body['html']), 'ago' => relative_date($item['created']), 'app' => $item['app'], -- cgit v1.2.3 From dc90f103d4ea56d8825d7ae83548b21301ed900a Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 16 Dec 2017 20:30:42 +0100 Subject: fix undefined constant warning --- include/feedutils.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/feedutils.php b/include/feedutils.php index 8f2c5d988..4638ef66a 100644 --- a/include/feedutils.php +++ b/include/feedutils.php @@ -1305,7 +1305,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { // allow likes of comments - if($item_parent_mid && activity_match($datarray['verb'],ACTVITY_LIKE)) { + if($item_parent_mid && activity_match($datarray['verb'],ACTIVITY_LIKE)) { $datarray['thr_parent'] = $item_parent_mid[0]['parent_mid']; } -- cgit v1.2.3 From 01289048a950e4638b6eb23e7bff28d6b88d0894 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 16 Dec 2017 20:33:07 +0100 Subject: silence PHP7.2 warning --- include/message.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/message.php b/include/message.php index b57d2e068..4a673b961 100644 --- a/include/message.php +++ b/include/message.php @@ -215,7 +215,7 @@ function send_message($uid = 0, $recipient = '', $body = '', $subject = '', $rep return $ret; } - if(count($images)) { + if($images) { foreach($images as $image) { if(! stristr($image,z_root() . '/photo/')) continue; -- cgit v1.2.3 From 715847bf748a773b3326e68e94935efdf178f5fe Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sat, 16 Dec 2017 15:10:43 -0800 Subject: don't zidify all permalinks, only zot permalinks --- include/text.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/text.php b/include/text.php index f3d522e04..02e2a10b5 100644 --- a/include/text.php +++ b/include/text.php @@ -1754,9 +1754,14 @@ function get_plink($item,$conversation_mode = true) { else $key = 'llink'; + $zidify = false; + + if(array_key_exists('author',$item) && $item['author']['xchan_network'] === 'zot') + $zidify = true; + if(x($item,$key)) { return array( - 'href' => zid($item[$key]), + 'href' => (($zidify) ? zid($item[$key]) : $item[$key]), 'title' => t('Link to Source'), ); } -- cgit v1.2.3 From fca405741ac0043068ed4d2f4b04c92dc74ff9c9 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sat, 16 Dec 2017 15:14:28 -0800 Subject: reverse the logic so we zidify by default --- include/text.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/text.php b/include/text.php index 02e2a10b5..107efe0cb 100644 --- a/include/text.php +++ b/include/text.php @@ -1754,10 +1754,10 @@ function get_plink($item,$conversation_mode = true) { else $key = 'llink'; - $zidify = false; + $zidify = true; - if(array_key_exists('author',$item) && $item['author']['xchan_network'] === 'zot') - $zidify = true; + if(array_key_exists('author',$item) && $item['author']['xchan_network'] !== 'zot') + $zidify = false; if(x($item,$key)) { return array( -- cgit v1.2.3 From 18349efccc4bb09b33a572bf621f7245ca899671 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 20 Dec 2017 11:11:18 +0100 Subject: html2bbcode: use headings bbcode for headings --- include/html2bbcode.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/html2bbcode.php b/include/html2bbcode.php index d7fbd8660..f67231847 100644 --- a/include/html2bbcode.php +++ b/include/html2bbcode.php @@ -196,12 +196,12 @@ function html2bbcode($message) //node2bbcode($doc, 'tr', array(), "[tr]", "[/tr]"); //node2bbcode($doc, 'td', array(), "[td]", "[/td]"); - node2bbcode($doc, 'h1', array(), "\n\n[size=xx-large][b]", "[/b][/size]\n"); - node2bbcode($doc, 'h2', array(), "\n\n[size=x-large][b]", "[/b][/size]\n"); - node2bbcode($doc, 'h3', array(), "\n\n[size=large][b]", "[/b][/size]\n"); - node2bbcode($doc, 'h4', array(), "\n\n[size=medium][b]", "[/b][/size]\n"); - node2bbcode($doc, 'h5', array(), "\n\n[size=small][b]", "[/b][/size]\n"); - node2bbcode($doc, 'h6', array(), "\n\n[size=x-small][b]", "[/b][/size]\n"); + node2bbcode($doc, 'h1', array(), "\n\n[h1]", "[/h1]\n"); + node2bbcode($doc, 'h2', array(), "\n\n[h2]", "[/h2]\n"); + node2bbcode($doc, 'h3', array(), "\n\n[h3]", "[/h3]\n"); + node2bbcode($doc, 'h4', array(), "\n\n[h4]", "[/h4]\n"); + node2bbcode($doc, 'h5', array(), "\n\n[h5]", "[/h5]\n"); + node2bbcode($doc, 'h6', array(), "\n\n[h6]", "[/h6]\n"); node2bbcode($doc, 'a', array('href'=>'/(.+)/'), '[url=$1]', '[/url]'); -- cgit v1.2.3 From 7766db40f55cb4ae6a470c6c3513d37e1fe00845 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 21 Dec 2017 09:07:37 +0100 Subject: remove additional linebreaks after headings --- include/bbcode.php | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include') diff --git a/include/bbcode.php b/include/bbcode.php index ed34bc5d6..775a91f9a 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -941,27 +941,34 @@ function bbcode($Text, $options = []) { // Check for h1 if (strpos($Text,'[h1]') !== false) { $Text = preg_replace("(\[h1\](.*?)\[\/h1\])ism",'

$1

',$Text); + $Text = str_replace('
', '', $Text); } // Check for h2 if (strpos($Text,'[h2]') !== false) { $Text = preg_replace("(\[h2\](.*?)\[\/h2\])ism",'

$1

',$Text); + $Text = str_replace('
', '', $Text); } // Check for h3 if (strpos($Text,'[h3]') !== false) { $Text = preg_replace("(\[h3\](.*?)\[\/h3\])ism",'

$1

',$Text); + $Text = str_replace('
', '', $Text); } // Check for h4 if (strpos($Text,'[h4]') !== false) { $Text = preg_replace("(\[h4\](.*?)\[\/h4\])ism",'

$1

',$Text); + $Text = str_replace('
', '', $Text); } // Check for h5 if (strpos($Text,'[h5]') !== false) { $Text = preg_replace("(\[h5\](.*?)\[\/h5\])ism",'
$1
',$Text); + $Text = str_replace('
', '', $Text); } // Check for h6 if (strpos($Text,'[h6]') !== false) { $Text = preg_replace("(\[h6\](.*?)\[\/h6\])ism",'
$1
',$Text); + $Text = str_replace('
', '', $Text); } + // Check for table of content without params while(strpos($Text,'[toc]') !== false) { $toc_id = 'toc-' . random_string(10); -- cgit v1.2.3 From 7b77e05f3a5f117d752ab2cd4449ab59dbffb2cf Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 21 Dec 2017 13:33:05 -0800 Subject: hubzilla-addons issue #74 - delayed posts not honoured for GNU-Social There is a very high probability this will also fix hubzilla-addons issue #75 --- include/items.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/items.php b/include/items.php index 7948a7c22..722757f87 100755 --- a/include/items.php +++ b/include/items.php @@ -4139,7 +4139,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C } if($channel && intval($arr['compat']) === 1) { - $sql_extra = " AND author_xchan = '" . $channel['channel_hash'] . "' and item_private = 0 "; + $sql_extra = " AND author_xchan = '" . $channel['channel_hash'] . "' and item_private = 0 $item_normal "; } if ($arr['datequery']) { -- cgit v1.2.3 From 8fc9d87b1b77e44a0fa45707e09c91465ecf261e Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 25 Dec 2017 14:59:08 -0800 Subject: cannot use file_get/put_contents in attach_store, must use pipe_streams --- include/attach.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/attach.php b/include/attach.php index e94454905..39269eb03 100644 --- a/include/attach.php +++ b/include/attach.php @@ -550,6 +550,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $type = $f['type']; } else { if(! x($_FILES,'userfile')) { + logger('No source file'); $ret['message'] = t('No source file.'); return $ret; } @@ -590,6 +591,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { intval($channel_id) ); if(! $x) { + logger('update file source not found'); $ret['message'] = t('Cannot locate file to revise/update'); return $ret; } @@ -731,6 +733,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $maxfilesize = get_config('system','maxfilesize'); if(($maxfilesize) && ($filesize > $maxfilesize)) { + logger('quota_exceeded'); $ret['message'] = sprintf( t('File exceeds size limit of %d'), $maxfilesize); if($remove_when_processed) @unlink($src); @@ -751,6 +754,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { intval($channel['channel_account_id']) ); if(($r) && (($r[0]['total'] + $filesize) > ($limit - $existing_size))) { + logger('service_class limit exceeded'); $ret['message'] = upgrade_message(true) . sprintf(t("You have reached your limit of %1$.0f Mbytes attachment storage."), $limit / 1024000); if($remove_when_processed) @unlink($src); @@ -783,8 +787,15 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $os_path = $os_relpath; $display_path = ltrim($pathname . '/' . $filename,'/'); - if($src) - @file_put_contents($os_basepath . $os_relpath,@file_get_contents($src)); + if($src) { + $istream = @fopen($src,'rb'); + $ostream = @fopen($os_basepath . $os_relpath,'wb'); + if($istream && $ostream) { + pipe_streams($istream,$ostream,65535); + fclose($istream); + fclose($ostream); + } + } if(array_key_exists('created', $arr)) $created = $arr['created']; -- cgit v1.2.3 From 340d437ab28897ad0e5df8d242240a87823f4f8e Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 26 Dec 2017 13:19:27 -0800 Subject: hubzilla issue #945 - directory keywords returned from twkn in standalone mode --- include/taxonomy.php | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/taxonomy.php b/include/taxonomy.php index a13a9cf77..a646df28c 100644 --- a/include/taxonomy.php +++ b/include/taxonomy.php @@ -313,12 +313,25 @@ function dir_tagadelic($count = 0) { $count = intval($count); - // Fetch tags - $r = q("select xtag_term as term, count(xtag_term) as total from xtag where xtag_flags = 0 - group by xtag_term order by total desc %s", - ((intval($count)) ? "limit $count" : '') - ); - + $dirmode = get_config('system','directory_mode'); + + if($dirmode == DIRECTORY_MODE_STANDALONE) { + // Fetch tags + $r = q("select xtag_term as term, count(xtag_term) as total from xtag + left join hubloc on xtag_hash = hubloc_hash + where xtag_flags = 0 and hubloc_url = '%s' + group by xtag_term order by total desc %s", + dbesc(z_root()), + ((intval($count)) ? "limit $count" : '') + ); + } + else { + // Fetch tags + $r = q("select xtag_term as term, count(xtag_term) as total from xtag where xtag_flags = 0 + group by xtag_term order by total desc %s", + ((intval($count)) ? "limit $count" : '') + ); + } if(! $r) return array(); -- cgit v1.2.3 From 94212766cc913f318d7a39cbaa6726da24609207 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sat, 30 Dec 2017 23:15:47 -0800 Subject: update file thumbnails when imported/synced --- include/import.php | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/import.php b/include/import.php index a5e8adeb5..496bcd89e 100644 --- a/include/import.php +++ b/include/import.php @@ -1328,6 +1328,9 @@ function sync_files($channel, $files) { } } } + + \Zotlabs\Daemon\Master::Summon([ 'Thumbnail' , $att['hash'] ]); + if($f['item']) { sync_items($channel,$f['item'], ['channel_address' => $original_channel,'url' => $oldbase] -- cgit v1.2.3 From 301e5383c7d524ca7cbcfd8e65b02f7b3591fc75 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 31 Dec 2017 14:45:42 -0800 Subject: this should finish up hubzilla issue #113 --- include/channel.php | 9 +++++++-- include/import.php | 14 +++++++++----- include/zot.php | 9 +++++++++ 3 files changed, 25 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/channel.php b/include/channel.php index 2d40b7db6..b9adc588b 100644 --- a/include/channel.php +++ b/include/channel.php @@ -1982,12 +1982,17 @@ function get_channel_default_perms($uid) { } -function profiles_build_sync($channel_id) { +function profiles_build_sync($channel_id,$send = true) { $r = q("select * from profile where uid = %d", intval($channel_id) ); if($r) { - build_sync_packet($channel_id,array('profile' => $r)); + if($send) { + build_sync_packet($channel_id,array('profile' => $r)); + } + else { + return $r; + } } } diff --git a/include/import.php b/include/import.php index 496bcd89e..5a655ce4c 100644 --- a/include/import.php +++ b/include/import.php @@ -162,13 +162,17 @@ function import_profiles($channel, $profiles) { convert_oldfields($profile,'work','employment'); /** - * @TODO we are going to reset all profile photos to the original - * somebody will have to fix this later and put all the applicable - * photos into the export. + * @TODO put all the applicable photos into the export. */ - $profile['photo'] = z_root() . '/photo/profile/l/' . $channel['channel_id']; - $profile['thumb'] = z_root() . '/photo/profile/m/' . $channel['channel_id']; + if((strpos($profile['thumb'],'/photo/profile/l/') !== false) || intval($profile['is_default'])) { + $profile['photo'] = z_root() . '/photo/profile/l/' . $channel['channel_id']; + $profile['thumb'] = z_root() . '/photo/profile/m/' . $channel['channel_id']; + } + else { + $profile['photo'] = z_root() . '/photo/' . basename($profile['photo']); + $profile['thumb'] = z_root() . '/photo/' . basename($profile['thumb']); + } create_table_from_array('profile', $profile); } diff --git a/include/zot.php b/include/zot.php index 6c0d92a42..8e3d03ad8 100644 --- a/include/zot.php +++ b/include/zot.php @@ -3745,6 +3745,15 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { * @TODO * We also need to import local photos if a custom photo is selected */ + + if((strpos($profile['thumb'],'/photo/profile/l/') !== false) || intval($profile['is_default'])) { + $profile['photo'] = z_root() . '/photo/profile/l/' . $channel['channel_id']; + $profile['thumb'] = z_root() . '/photo/profile/m/' . $channel['channel_id']; + } + else { + $profile['photo'] = z_root() . '/photo/' . basename($profile['photo']); + $profile['thumb'] = z_root() . '/photo/' . basename($profile['thumb']); + } } if(count($clean)) { -- cgit v1.2.3 From 10a1569c9aa1780344954dc4d01898b29a772aca Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 1 Jan 2018 12:25:43 -0800 Subject: hubzilla issue #947 --- include/network.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/network.php b/include/network.php index 3569874be..79a8c6578 100644 --- a/include/network.php +++ b/include/network.php @@ -752,13 +752,14 @@ function scale_external_images($s, $include_link = true, $scale_replace = false) if($orig_width > 1024 || $orig_height > 1024) { $tag = (($match[1] == 'z') ? 'zmg' : 'img'); + $linktag = (($match[1] == 'z') ? 'zrl' : 'url'); $ph->scaleImage(1024); $new_width = $ph->getWidth(); $new_height = $ph->getHeight(); logger('data: ' . $orig_width . '->' . $new_width . 'w ' . $orig_height . '->' . $new_height . 'h' . ' match: ' . $mtch[0], LOGGER_DEBUG); $s = str_replace($mtch[0],'[' . $tag . '=' . $new_width . 'x' . $new_height. ']' . $scaled . '[/' . $tag . ']' . "\n" . (($include_link) - ? '[zrl=' . $mtch[2] . ']' . t('view full size') . '[/zrl]' . "\n" + ? '[' . $linktag . '=' . $mtch[3] . ']' . t('view full size') . '[/' . $linktag . ']' . "\n" : ''),$s); logger('new string: ' . $s, LOGGER_DEBUG); } -- cgit v1.2.3 From 2f5990962c9f74d354239aea0153700565155232 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 2 Jan 2018 14:04:43 -0800 Subject: issues with feed parameters --- include/items.php | 7 ++++--- include/zid.php | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/items.php b/include/items.php index 722757f87..d0b9cffc9 100755 --- a/include/items.php +++ b/include/items.php @@ -4063,8 +4063,9 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C $item_uids = ' true '; $item_normal = item_normal(); - - if ($arr['uid']) $uid= $arr['uid']; + if($arr['uid']) { + $uid = $arr['uid']; + } if($channel) { $uid = $channel['channel_id']; @@ -4226,7 +4227,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C $items = q("SELECT item.*, item.id AS item_id FROM item WHERE $item_uids $item_restrict $simple_update - $sql_extra $sql_nets + $sql_extra $sql_nets $sql_extra3 ORDER BY item.received DESC $pager_sql" ); diff --git a/include/zid.php b/include/zid.php index d1a0fa88a..6ebc9a6ab 100644 --- a/include/zid.php +++ b/include/zid.php @@ -105,8 +105,8 @@ function strip_zats($s) { -function clean_query_string() { - $x = strip_zids(\App::$query_string); +function clean_query_string($s = '') { + $x = strip_zids(($s) ? $s : \App::$query_string); $x = strip_owt($x); $x = strip_zats($x); -- cgit v1.2.3