From 6464099364f3d4e800137a57d3b9ff9e8f7601e4 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 12 Dec 2018 19:11:30 -0800 Subject: [PATCH 01/93] regression: the ability to order apps messed up since adding pinned apps to the ordering --- Zotlabs/Lib/Apps.php | 38 +++++++++++++++-------- Zotlabs/Module/Appman.php | 6 ++-- Zotlabs/Module/Apporder.php | 33 ++++++++++---------- include/nav.php | 60 +++++++++++++++++++++++++++---------- view/tpl/app.tpl | 4 +-- 5 files changed, 94 insertions(+), 47 deletions(-) diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index b13658be2..8cf62c01a 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -808,12 +808,14 @@ class Apps { return($r); } - static public function app_order($uid,$apps) { + static public function app_order($uid,$apps,$menu) { if(! $apps) return $apps; - $x = (($uid) ? get_pconfig($uid,'system','app_order') : get_config('system','app_order')); + $conf = (($menu === 'nav_featured_app') ? 'app_order' : 'app_pin_order'); + + $x = (($uid) ? get_pconfig($uid,'system',$conf) : get_config('system',$conf)); if(($x) && (! is_array($x))) { $y = explode(',',$x); $y = array_map('trim',$y); @@ -850,19 +852,25 @@ class Apps { return false; } - static function moveup($uid,$guid) { + static function moveup($uid,$guid,$menu) { $syslist = array(); - $list = self::app_list($uid, false, ['nav_featured_app', 'nav_pinned_app']); + + $conf = (($menu === 'nav_featured_app') ? 'app_order' : 'app_pin_order'); + + $list = self::app_list($uid, false, [ $menu ]); if($list) { foreach($list as $li) { - $syslist[] = self::app_encode($li); + $papp = self::app_encode($li); + if($menu !== 'nav_pinned_app' && strpos($papp['categories'],'nav_pinned_app') !== false) + continue; + $syslist[] = $papp; } } self::translate_system_apps($syslist); usort($syslist,'self::app_name_compare'); - $syslist = self::app_order($uid,$syslist); + $syslist = self::app_order($uid,$syslist,$menu); if(! $syslist) return; @@ -887,23 +895,29 @@ class Apps { $narr[] = $x['name']; } - set_pconfig($uid,'system','app_order',implode(',',$narr)); + set_pconfig($uid,'system',$conf,implode(',',$narr)); } - static function movedown($uid,$guid) { + static function movedown($uid,$guid,$menu) { $syslist = array(); - $list = self::app_list($uid, false, ['nav_featured_app', 'nav_pinned_app']); + + $conf = (($menu === 'nav_featured_app') ? 'app_order' : 'app_pin_order'); + + $list = self::app_list($uid, false, [ $menu ]); if($list) { foreach($list as $li) { - $syslist[] = self::app_encode($li); + $papp = self::app_encode($li); + if($menu !== 'nav_pinned_app' && strpos($papp['categories'],'nav_pinned_app') !== false) + continue; + $syslist[] = $papp; } } self::translate_system_apps($syslist); usort($syslist,'self::app_name_compare'); - $syslist = self::app_order($uid,$syslist); + $syslist = self::app_order($uid,$syslist,$menu); if(! $syslist) return; @@ -928,7 +942,7 @@ class Apps { $narr[] = $x['name']; } - set_pconfig($uid,'system','app_order',implode(',',$narr)); + set_pconfig($uid,'system',$conf,implode(',',$narr)); } diff --git a/Zotlabs/Module/Appman.php b/Zotlabs/Module/Appman.php index f50dcc2ab..39689665e 100644 --- a/Zotlabs/Module/Appman.php +++ b/Zotlabs/Module/Appman.php @@ -90,12 +90,12 @@ class Appman extends \Zotlabs\Web\Controller { $channel = \App::get_channel(); - if(argc() > 2) { + if(argc() > 3) { if(argv(2) === 'moveup') { - Zlib\Apps::moveup(local_channel(),argv(1)); + Zlib\Apps::moveup(local_channel(),argv(1),argv(3)); } if(argv(2) === 'movedown') { - Zlib\Apps::movedown(local_channel(),argv(1)); + Zlib\Apps::movedown(local_channel(),argv(1),argv(3)); } goaway(z_root() . '/apporder'); } diff --git a/Zotlabs/Module/Apporder.php b/Zotlabs/Module/Apporder.php index a9f66ba69..eac1abc2d 100644 --- a/Zotlabs/Module/Apporder.php +++ b/Zotlabs/Module/Apporder.php @@ -17,25 +17,28 @@ class Apporder extends \Zotlabs\Web\Controller { nav_set_selected('Order Apps'); - $syslist = array(); - $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); + foreach( [ 'nav_featured_app', 'nav_pinned_app' ] as $l ) { + $syslist = []; + $list = Zlib\Apps::app_list(local_channel(), false, [ $l ]); + if($list) { + foreach($list as $li) { + $syslist[] = Zlib\Apps::app_encode($li); + } } - } - Zlib\Apps::translate_system_apps($syslist); + + Zlib\Apps::translate_system_apps($syslist); - usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare'); + usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare'); - $syslist = Zlib\Apps::app_order(local_channel(),$syslist); + $syslist = Zlib\Apps::app_order(local_channel(),$syslist, $l); - foreach($syslist as $app) { - if(strpos($app['categories'],'nav_pinned_app') !== false) { - $navbar_apps[] = Zlib\Apps::app_render($app,'nav-order'); - } - else { - $nav_apps[] = Zlib\Apps::app_render($app,'nav-order'); + foreach($syslist as $app) { + if($l === 'nav_pinned_app') { + $navbar_apps[] = Zlib\Apps::app_render($app,'nav-order'); + } + elseif(strpos($app['categories'],'nav_pinned_app') === false) { + $nav_apps[] = Zlib\Apps::app_render($app,'nav-order'); + } } } diff --git a/include/nav.php b/include/nav.php index d405b9f06..58e13dd93 100644 --- a/include/nav.php +++ b/include/nav.php @@ -222,6 +222,9 @@ function nav($template = 'default') { if(! $settings_url && isset(App::$nav_sel['settings_url'])) $settings_url = App::$nav_sel['settings_url']; + $pinned_list = []; + $syslist = []; + //app bin if($is_owner) { if(get_pconfig(local_channel(), 'system','import_system_apps') !== datetime_convert('UTC','UTC','now','Y-m-d')) { @@ -234,14 +237,29 @@ function nav($template = 'default') { set_pconfig(local_channel(), 'system','force_import_system_apps', STD_VERSION); } - $syslist = array(); - $list = Apps::app_list(local_channel(), false, ['nav_featured_app', 'nav_pinned_app']); + $list = Apps::app_list(local_channel(), false, [ 'nav_pinned_app' ]); + if($list) { + foreach($list as $li) { + $pinned_list[] = Apps::app_encode($li); + } + } + Apps::translate_system_apps($pinned_list); + + usort($pinned_list,'Zotlabs\\Lib\\Apps::app_name_compare'); + + $pinned_list = Apps::app_order(local_channel(),$pinned_list, 'nav_pinned_app'); + + + $syslist = []; + $list = Apps::app_list(local_channel(), false, [ 'nav_featured_app' ]); + if($list) { foreach($list as $li) { $syslist[] = Apps::app_encode($li); } } Apps::translate_system_apps($syslist); + } else { $syslist = Apps::get_system_apps(true); @@ -249,26 +267,38 @@ function nav($template = 'default') { usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare'); - $syslist = Apps::app_order(local_channel(),$syslist); + $syslist = Apps::app_order(local_channel(),$syslist, 'nav_featured_app'); - foreach($syslist as $app) { - if(\App::$nav_sel['name'] == $app['name']) - $app['active'] = true; - if($is_owner) { - if(strpos($app['categories'],'nav_pinned_app') !== false) { + if($pinned_list) { + foreach($pinned_list as $app) { + if(\App::$nav_sel['name'] == $app['name']) + $app['active'] = true; + + if($is_owner) { $navbar_apps[] = Apps::app_render($app,'navbar'); } - else { - $nav_apps[] = Apps::app_render($app,'nav'); + elseif(! $is_owner && strpos($app['requires'], 'local_channel') === false) { + $navbar_apps[] = Apps::app_render($app,'navbar'); } } - elseif(! $is_owner && strpos($app['requires'], 'local_channel') === false) { - if(strpos($app['categories'],'nav_pinned_app') !== false) { - $navbar_apps[] = Apps::app_render($app,'navbar'); + } + + + if($syslist) { + foreach($syslist as $app) { + if(\App::$nav_sel['name'] == $app['name']) + $app['active'] = true; + + if($is_owner) { + if(strpos($app['categories'],'nav_pinned_app') === false) { + $nav_apps[] = Apps::app_render($app,'nav'); + } } - else { - $nav_apps[] = Apps::app_render($app,'nav'); + elseif(! $is_owner && strpos($app['requires'], 'local_channel') === false) { + if(strpos($app['categories'],'nav_pinned_app') === false) { + $nav_apps[] = Apps::app_render($app,'nav'); + } } } } diff --git a/view/tpl/app.tpl b/view/tpl/app.tpl index 6013f9548..cacbf7e64 100644 --- a/view/tpl/app.tpl +++ b/view/tpl/app.tpl @@ -31,8 +31,8 @@ {{if $icon}}{{else}}{{/if}}{{$app.name}} {{/if}} {{if $order}} - - + + {{if $icon}}{{else}}{{/if}}{{$app.name}}
{{/if}} From f81a3ba45d50c0a0e4da68c17aba73425058e23d Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 14 Dec 2018 11:23:08 +0100 Subject: [PATCH 02/93] fix issue with linkdropper --- view/tpl/jot-header.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/view/tpl/jot-header.tpl b/view/tpl/jot-header.tpl index 2670ba9e7..b286b6071 100755 --- a/view/tpl/jot-header.tpl +++ b/view/tpl/jot-header.tpl @@ -219,7 +219,7 @@ var activeCommentText = ''; } function linkdropper(event) { - var linkFound = event.dataTransfer.types.contains("text/uri-list"); + var linkFound = ((event.dataTransfer.types.indexOf("text/uri-list") > -1) ? true : false); if(linkFound) { event.preventDefault(); var editwin = '#' + event.target.id; @@ -256,7 +256,7 @@ var activeCommentText = ''; commentwin = ((editwin.indexOf('comment') >= 0) ? true : false); if(commentwin) { var commentid = editwin.substring(editwin.lastIndexOf('-') + 1); - commentOpen(document.getElementById(event.target.id),commentid); + $("#comment-edit-text-" + commentid).addClass("expanded"); } } From 3f06a857c27344263d4a361e367738e85fc30af6 Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Fri, 14 Dec 2018 09:55:27 -0500 Subject: [PATCH 03/93] ARTICLES MODULE: Default to local_channel() user when no argv(1) is passed. --- Zotlabs/Module/Articles.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Zotlabs/Module/Articles.php b/Zotlabs/Module/Articles.php index 58c16be45..bc6c00483 100644 --- a/Zotlabs/Module/Articles.php +++ b/Zotlabs/Module/Articles.php @@ -17,8 +17,14 @@ class Articles extends Controller { if(argc() > 1) $which = argv(1); - else - return; + + if(! $which) { + if(local_channel()) { + $channel = App::get_channel(); + if($channel && $channel['channel_address']) + $which = $channel['channel_address']; + } + } profile_load($which); From 03a214c8b9e5bac7d14776286208a153a3edcdf7 Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Fri, 14 Dec 2018 10:05:41 -0500 Subject: [PATCH 04/93] Recreate MR#1419 for dev branch --- util/udall | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/udall b/util/udall index f1d52a1d1..44f37e86e 100755 --- a/util/udall +++ b/util/udall @@ -7,7 +7,7 @@ git pull if [ -d extend ] ; then for a in theme addon widget ; do - if [ -d $a ]; then + if [ -d extend/$a ]; then for b in `ls extend/$a` ; do echo Updating $b 'util/update_'$a'_repo' $b From eb297104debfc42fe6f3afee4eae3c2602627aeb Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Fri, 14 Dec 2018 12:52:58 -0500 Subject: [PATCH 05/93] Make Affinity Slider (optionally) 'sticky' across page loads. (default is current behavior: reset slider with each page load) --- Zotlabs/Module/Network.php | 7 +++++++ Zotlabs/Module/Settings/Featured.php | 8 ++++++++ Zotlabs/Widget/Affinity.php | 9 +++++++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index b93faa612..894e5c8b6 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -132,6 +132,13 @@ class Network extends \Zotlabs\Web\Controller { $deftag = ''; + if (feature_enabled(local_channel(),'affinity')) { + $affinity_locked = int(get_pconfig(local_channel(),'affinity','lock',1)); + if ($affinity_locked) { + set_pconfig(local_channel(),'affinity','cmin',$cmin); + set_pconfig(local_channel(),'affinity','cmax',$cmax); + } + } if(x($_GET,'search') || $file || (!$pf && $cid) || $hashtags || $verb || $category || $conv || $unseen) $nouveau = true; diff --git a/Zotlabs/Module/Settings/Featured.php b/Zotlabs/Module/Settings/Featured.php index 542a05363..1d903fcf7 100644 --- a/Zotlabs/Module/Settings/Featured.php +++ b/Zotlabs/Module/Settings/Featured.php @@ -17,8 +17,12 @@ class Featured { $cmin = intval($_POST['affinity_cmin']); if($cmin < 0 || $cmin > 99) $cmin = 0; + + $lock = ($_POST['affinity_lock']) ? intval($_POST['affinity_lock']) : 1; + set_pconfig(local_channel(),'affinity','cmin',$cmin); set_pconfig(local_channel(),'affinity','cmax',$cmax); + set_pconfig(local_channel(),'affinity','lock',$lock); info( t('Affinity Slider settings updated.') . EOL); @@ -49,6 +53,10 @@ class Featured { $setting_fields .= replace_macros(get_markup_template('field_input.tpl'), array( '$field' => array('affinity_cmin', t('Default minimum affinity level'), $cmin, t('0-99 - default 0')) )); + $lock = intval(get_pconfig(local_channel(),'affinity','lock',1)); + $setting_fields .= replace_macros(get_markup_template('field_checkbox.tpl'), array( + '$field' => array('affinity_lock', t('Always reset on new page visit.'), $lock, t('default: yes'), Array('No','Yes')) + )); $settings_addons .= replace_macros(get_markup_template('generic_addon_settings.tpl'), array( '$addon' => array('affinity_slider', '' . t('Affinity Slider Settings'), '', t('Submit')), diff --git a/Zotlabs/Widget/Affinity.php b/Zotlabs/Widget/Affinity.php index 4fb2874ae..e9dac6b27 100644 --- a/Zotlabs/Widget/Affinity.php +++ b/Zotlabs/Widget/Affinity.php @@ -15,9 +15,14 @@ class Affinity { $cmin = ((x($_REQUEST,'cmin')) ? intval($_REQUEST['cmin']) : $default_cmin); $cmax = ((x($_REQUEST,'cmax')) ? intval($_REQUEST['cmax']) : $default_cmax); - if(feature_enabled(local_channel(),'affinity')) { + $affinity_locked = int(get_pconfig(local_channel(),'affinity','lock',1)); + if ($affinity_locked) { + set_pconfig(local_channel(),'affinity','cmin',$cmin); + set_pconfig(local_channel(),'affinity','cmax',$cmax); + } + $labels = array( t('Me'), t('Family'), @@ -53,4 +58,4 @@ class Affinity { return ''; } } - \ No newline at end of file + From de7cb6d6ad7902f28e63759350613ed4b30a055b Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Fri, 14 Dec 2018 13:59:41 -0500 Subject: [PATCH 06/93] Fix syntax error --- Zotlabs/Module/Network.php | 2 +- Zotlabs/Widget/Affinity.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index 894e5c8b6..d5cc06d09 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -133,7 +133,7 @@ class Network extends \Zotlabs\Web\Controller { $deftag = ''; if (feature_enabled(local_channel(),'affinity')) { - $affinity_locked = int(get_pconfig(local_channel(),'affinity','lock',1)); + $affinity_locked = intval(get_pconfig(local_channel(),'affinity','lock',1)); if ($affinity_locked) { set_pconfig(local_channel(),'affinity','cmin',$cmin); set_pconfig(local_channel(),'affinity','cmax',$cmax); diff --git a/Zotlabs/Widget/Affinity.php b/Zotlabs/Widget/Affinity.php index e9dac6b27..28190e187 100644 --- a/Zotlabs/Widget/Affinity.php +++ b/Zotlabs/Widget/Affinity.php @@ -17,7 +17,7 @@ class Affinity { if(feature_enabled(local_channel(),'affinity')) { - $affinity_locked = int(get_pconfig(local_channel(),'affinity','lock',1)); + $affinity_locked = intval(get_pconfig(local_channel(),'affinity','lock',1)); if ($affinity_locked) { set_pconfig(local_channel(),'affinity','cmin',$cmin); set_pconfig(local_channel(),'affinity','cmax',$cmax); From 3416190e4b8887b91e497529d9e9bb60231beca9 Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Fri, 14 Dec 2018 14:22:28 -0500 Subject: [PATCH 07/93] Set min/maxversion for plugins to STD_VERSION unless otherwise specified --- include/plugin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/plugin.php b/include/plugin.php index 8ceb6417e..7eeb39ce8 100755 --- a/include/plugin.php +++ b/include/plugin.php @@ -736,8 +736,8 @@ function get_theme_info($theme){ 'description' => '', 'author' => array(), 'version' => '', - 'minversion' => '', - 'maxversion' => '', + 'minversion' => STD_VERSION, + 'maxversion' => STD_VERSION, 'compat' => '', 'credits' => '', 'maintainer' => array(), From 4ff3c57976705ce2b7964536d55dabb308cc25dd Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 14 Dec 2018 21:46:48 +0100 Subject: [PATCH 08/93] update changelog --- CHANGELOG | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 444c7b2e4..a3dd1336b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,15 @@ +Hubzilla 3.8.7 (2018-12-14) + - Fix issue with linkdropper in comment area + - Fix regression wit app ordering + - Fix return if readImnageBlob() throws an exception + - Introduce photo_view_filter hook + - Fix home notifications not expanding in certain situations + - Fix for dark schema + - Fix total identities restriction + - Fix article page title not updating if article has no title + - Gallery: the gallery app will now act as the full-size photo viewer in /photos if installed + + Hubzilla 3.8.6 (2018-12-03) - Prevent incompatible export files (osada/zap) from being imported - Catch exception if readImageBlob() receives bogus data From 09b2cdd618217c2dfc0149579ce1780c201a50ea Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Fri, 14 Dec 2018 20:20:26 -0500 Subject: [PATCH 09/93] Add ITEM_TYPE_CUSTOM and hooks for processing custom item types --- boot.php | 2 ++ doc/hook/item_custom.bb | 24 ++++++++++++++++++++++++ doc/hook/item_stored.bb | 18 ++++++++++++++++++ doc/hook/item_stored_update.bb | 15 +++++++++++++++ doc/hooklist.bb | 9 +++++++++ include/items.php | 30 ++++++++++++++++++++++++++++++ 6 files changed, 98 insertions(+) create mode 100644 doc/hook/item_custom.bb create mode 100644 doc/hook/item_stored.bb create mode 100644 doc/hook/item_stored_update.bb diff --git a/boot.php b/boot.php index 4087ec006..1d3897114 100755 --- a/boot.php +++ b/boot.php @@ -576,6 +576,8 @@ define ( 'ITEM_TYPE_BUG', 4 ); define ( 'ITEM_TYPE_DOC', 5 ); define ( 'ITEM_TYPE_CARD', 6 ); define ( 'ITEM_TYPE_ARTICLE', 7 ); +//OSADA ITEM_TYPE_MAIL = 8 +define ( 'ITEM_TYPE_CUSTOM', 9 ); define ( 'ITEM_IS_STICKY', 1000 ); diff --git a/doc/hook/item_custom.bb b/doc/hook/item_custom.bb new file mode 100644 index 000000000..d20c7d76c --- /dev/null +++ b/doc/hook/item_custom.bb @@ -0,0 +1,24 @@ +[h2]item_custom[/h2] + +Allow addons to create and process custom item types. + +Addon authors will need to use iconfig meta data (with sharing on) or some other method +to specify and determine whether the custom item is destined for their addon. + +It is fed an array of ['item' => ${item_array}, 'allow_exec' => {true/false}] + +By default $arr['item']['cancel'] is set to TRUE which will abort storage of the +custom item in the item table unless the addon unsets it or sets it to false. + +[code] + if ($arr['item_type']==ITEM_TYPE_CUSTOM) { + /* Custom items are not stored by default + because they require an addon to process. */ + $d['item']['cancel']=true; + + call_hooks('item_custom',$d); + } + +[/code] + +see: include/items.php diff --git a/doc/hook/item_stored.bb b/doc/hook/item_stored.bb new file mode 100644 index 000000000..8d706cb4e --- /dev/null +++ b/doc/hook/item_stored.bb @@ -0,0 +1,18 @@ +[h2]item_stored[/h2] + +Allow addons to continue processing after an item has been stored in the event +that they need access to the item_id or other data that gets assigned during +the storage process. + +It is fed an array of type item (including terms and iconfig data). + +[code] + /** + * @hooks item_stored + * Called after new item is stored in the database. + * (By this time we have an item_id and other frequently needed info.) + */ + call_hooks('item_stored',$arr); +[/code] + +see: include/items.php diff --git a/doc/hook/item_stored_update.bb b/doc/hook/item_stored_update.bb new file mode 100644 index 000000000..4532a347c --- /dev/null +++ b/doc/hook/item_stored_update.bb @@ -0,0 +1,15 @@ +[h2]item_stored_update[/h2] + +Allow addons to continue processing after an item update has been stored + +It is fed an array of type item (including terms and iconfig data). + +[code] + /** + * @hooks item_stored_update + * Called after updated item is stored in the database. + */ + call_hooks('item_stored_update',$arr); +[/code] + +see: include/items.php diff --git a/doc/hooklist.bb b/doc/hooklist.bb index 5d12a139e..08fc587e2 100644 --- a/doc/hooklist.bb +++ b/doc/hooklist.bb @@ -343,9 +343,18 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the [zrl=[baseurl]/help/hook/item_store]item_store[/zrl] Called when item_store() stores a record of type item +[zrl=[baseurl]/help/hook/item_stored]item_stored[/zrl] + Called after item_store() has stored a record of type item in the database. + +[zrl=[baseurl]/help/hook/item_custom]item_custom[/zrl] + Called before item_store() stores a record of type item (allowing addons to process ITEM_TYPE_CUSTOM items). + [zrl=[baseurl]/help/hook/item_store_update]item_store_update[/zrl] Called when item_store_update() is called to update a stored item. +[zrl=[baseurl]/help/hook/item_stored_update]item_stored_update[/zrl] + Called after item_store_update() has updated a stored item. + [zrl=[baseurl]/help/hook/item_translate]item_translate[/zrl] Called from item_store and item_store_update after the post language has been autodetected diff --git a/include/items.php b/include/items.php index 0cbca23fc..02d31fcb5 100755 --- a/include/items.php +++ b/include/items.php @@ -1591,6 +1591,14 @@ function item_store($arr, $allow_exec = false, $deliver = true) { 'item' => $arr, 'allow_exec' => $allow_exec ]; + + if ($arr['item_type']==ITEM_TYPE_CUSTOM) { + /* Custom items are not stored by default + because they require an addon to process. */ + $d['item']['cancel']=true; + + call_hooks('item_custom',$d); + } /** * @hooks item_store * Called when item_store() stores a record of type item. @@ -2016,6 +2024,13 @@ function item_store($arr, $allow_exec = false, $deliver = true) { */ call_hooks('post_remote_end', $arr); + /** + * @hooks item_stored + * Called after new item is stored in the database. + * (By this time we have an item_id and other frequently needed info.) + */ + call_hooks('item_stored',$arr); + item_update_parent_commented($arr); // If _creating_ a deleted item, don't propagate it further or send out notifications. @@ -2049,6 +2064,15 @@ function item_store_update($arr, $allow_exec = false, $deliver = true) { 'item' => $arr, 'allow_exec' => $allow_exec ]; + + if ($arr['item_type']==ITEM_TYPE_CUSTOM) { + /* Custom items are not stored by default + because they require an addon to process. */ + $d['item']['cancel']=true; + + call_hooks('item_custom_update',$d); + } + /** * @hooks item_store_update * Called when item_store_update() is called to update a stored item. It @@ -2339,6 +2363,12 @@ function item_store_update($arr, $allow_exec = false, $deliver = true) { */ call_hooks('post_remote_update_end', $arr); + /** + * @hooks item_stored_update + * Called after updated item is stored in the database. + */ + call_hooks('item_stored_update',$arr); + if($deliver) { send_status_notifications($orig_post_id,$arr); tag_deliver($uid,$orig_post_id); From 919ea9f750fbb665a655cd26ae86c00e424a4318 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 15 Dec 2018 18:19:29 +0100 Subject: [PATCH 10/93] fix wiki preview issue with hyperlinks --- Zotlabs/Module/Wiki.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index 892810241..502f96a62 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -442,8 +442,8 @@ class Wiki extends Controller { $mimeType = $_POST['mimetype']; if($mimeType === 'text/bbcode') { - $linkconverted = NativeWikiPage::convert_links($content,$wikiURL); - $html = zidify_links(smilies(bbcode($linkconverted))); + $html = zidify_links(smilies(bbcode($content))); + $html = NativeWikiPage::convert_links($html,$wikiURL); } elseif($mimeType === 'text/markdown') { $linkconverted = NativeWikiPage::convert_links($content,$wikiURL); From 6a825cc504901b6c09724e487f43b5012805c6a0 Mon Sep 17 00:00:00 2001 From: Pascal Deklerck Date: Sat, 15 Dec 2018 22:19:18 +0100 Subject: [PATCH 11/93] Update OAuth2Storage.php - fix email retrieval in getUser --- Zotlabs/Identity/OAuth2Storage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Identity/OAuth2Storage.php b/Zotlabs/Identity/OAuth2Storage.php index bbf61cf2b..a4ba9c526 100644 --- a/Zotlabs/Identity/OAuth2Storage.php +++ b/Zotlabs/Identity/OAuth2Storage.php @@ -64,7 +64,7 @@ class OAuth2Storage extends \OAuth2\Storage\Pdo { return( [ 'webfinger' => channel_reddress($x), 'portable_id' => $x['channel_hash'], - 'email' => $a['account_email'], + 'email' => $a[0]['account_email'], 'username' => $x['channel_address'], 'user_id' => $x['channel_id'], 'name' => $x['channel_name'], From 5bcc379530e6789f59397dc39f4da66cc8c5b2ae Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Sat, 15 Dec 2018 19:49:59 -0500 Subject: [PATCH 12/93] Add return if no local_channel() --- Zotlabs/Module/Articles.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Zotlabs/Module/Articles.php b/Zotlabs/Module/Articles.php index bc6c00483..ca132c01e 100644 --- a/Zotlabs/Module/Articles.php +++ b/Zotlabs/Module/Articles.php @@ -23,7 +23,9 @@ class Articles extends Controller { $channel = App::get_channel(); if($channel && $channel['channel_address']) $which = $channel['channel_address']; - } + } else { + return; + } } profile_load($which); From e0d68664c461f5649c760536c77532ef8c2e4818 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Sun, 16 Dec 2018 20:48:36 +0100 Subject: [PATCH 13/93] Remove photo_cache_enable variable --- Zotlabs/Module/Photo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Module/Photo.php b/Zotlabs/Module/Photo.php index ddff3a68e..7365a5f64 100644 --- a/Zotlabs/Module/Photo.php +++ b/Zotlabs/Module/Photo.php @@ -32,7 +32,7 @@ class Photo extends \Zotlabs\Web\Controller { } $cache_mode = array( - 'on' => get_config('system','photo_cache_enable', 0), + 'on' => false, 'age' => 86400, 'exp' => true, 'leak' => false From 1c07428f8968dc52c0bead76509fcd5400a8c5fd Mon Sep 17 00:00:00 2001 From: phani00 Date: Sun, 16 Dec 2018 20:35:20 +0000 Subject: [PATCH 14/93] add warning if upload_filesize < 4MB. --- Zotlabs/Module/Setup.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Zotlabs/Module/Setup.php b/Zotlabs/Module/Setup.php index c0716ca7c..b2d42418e 100644 --- a/Zotlabs/Module/Setup.php +++ b/Zotlabs/Module/Setup.php @@ -441,13 +441,19 @@ class Setup extends \Zotlabs\Web\Controller { require_once 'include/environment.php'; $help = ''; + $mem_warning = ''; $result = getPhpiniUploadLimits(); + if($result['post_max_size'] < 4194304 || $result['max_upload_filesize'] < 4194304) { + $mem_warning = '' .t('This is not sufficient to upload larger images or files. You should be able to upload at least 4 MB at once.') . ''; + } $help = sprintf(t('Your max allowed total upload size is set to %s. Maximum size of one file to upload is set to %s. You are allowed to upload up to %d files at once.'), userReadableSize($result['post_max_size']), userReadableSize($result['max_upload_filesize']), $result['max_file_uploads'] ); + $help .= $mem_warning; + $help .= '

' . t('You can adjust these settings in the server php.ini file.'); $this->check_add($checks, t('PHP upload limits'), true, false, $help); From 14735e0a48c3df8aef4817dcdee1e5e64de4ccaa Mon Sep 17 00:00:00 2001 From: phani00 Date: Sun, 16 Dec 2018 22:04:28 +0100 Subject: [PATCH 15/93] Update Zotlabs/Module/Setup.php --- Zotlabs/Module/Setup.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Zotlabs/Module/Setup.php b/Zotlabs/Module/Setup.php index b2d42418e..370b7b9f8 100644 --- a/Zotlabs/Module/Setup.php +++ b/Zotlabs/Module/Setup.php @@ -453,7 +453,6 @@ class Setup extends \Zotlabs\Web\Controller { $result['max_file_uploads'] ); $help .= $mem_warning; - $help .= '

' . t('You can adjust these settings in the server php.ini file.'); $this->check_add($checks, t('PHP upload limits'), true, false, $help); From 04a45a407ead8e7afcdd3423b773074207e885df Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 16 Dec 2018 14:38:58 -0800 Subject: [PATCH 16/93] default curl to http/1.1 --- include/network.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/network.php b/include/network.php index cd352e7db..df59a30e6 100644 --- a/include/network.php +++ b/include/network.php @@ -120,6 +120,14 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { @curl_setopt($ch, CURLOPT_USERPWD, $opts['http_auth']); } + if(array_key_exists('http_version',$opts)) { + @curl_setopt($ch,CURLOPT_HTTP_VERSION,$opts['http_version']); + } + else { + @curl_setopt($ch,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_1); + } + + if(x($opts,'cookiejar')) @curl_setopt($ch, CURLOPT_COOKIEJAR, $opts['cookiejar']); if(x($opts,'cookiefile')) @@ -290,6 +298,13 @@ function z_post_url($url, $params, $redirects = 0, $opts = array()) { @curl_setopt($ch, CURLOPT_USERPWD, $opts['http_auth']); } + if(array_key_exists('http_version',$opts)) { + @curl_setopt($ch,CURLOPT_HTTP_VERSION,$opts['http_version']); + } + else { + @curl_setopt($ch,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_1); + } + if(x($opts,'cookiejar')) @curl_setopt($ch, CURLOPT_COOKIEJAR, $opts['cookiejar']); if(x($opts,'cookiefile')) From 363ad01bce15313c0536cd5f0e437db0a133ee06 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Mon, 17 Dec 2018 00:30:36 +0100 Subject: [PATCH 17/93] SSLify cached URL on redirect if needed --- Zotlabs/Module/Photos.php | 1686 +++++++------------------------------ 1 file changed, 287 insertions(+), 1399 deletions(-) diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php index b87c586da..967a3b703 100644 --- a/Zotlabs/Module/Photos.php +++ b/Zotlabs/Module/Photos.php @@ -1,1424 +1,312 @@ 1) { - $nick = argv(1); - - profile_load($nick); - - $channelx = channelx_by_nick($nick); - - if(! $channelx) - return; - - \App::$data['channel'] = $channelx; - - $observer = \App::get_observer(); - \App::$data['observer'] = $observer; - - $observer_xchan = (($observer) ? $observer['xchan_hash'] : ''); - - head_set_icon(\App::$data['channel']['xchan_photo_s']); - - \App::$page['htmlhead'] .= "" ; - - } - - return; - } - - - - function post() { - - logger('mod-photos: photos_post: begin' , LOGGER_DEBUG); - - logger('mod_photos: REQUEST ' . print_r($_REQUEST,true), LOGGER_DATA); - logger('mod_photos: FILES ' . print_r($_FILES,true), LOGGER_DATA); - - $ph = photo_factory(''); - - $phototypes = $ph->supportedTypes(); - - $can_post = false; - - $page_owner_uid = \App::$data['channel']['channel_id']; - - if(perm_is_allowed($page_owner_uid,get_observer_hash(),'write_storage')) - $can_post = true; - - if(! $can_post) { - notice( t('Permission denied.') . EOL ); - if(is_ajax()) + + $streaming = null; + $channel = null; + $person = 0; + $renew = false; + + switch(argc()) { + case 4: + $person = argv(3); + $res = argv(2); + $type = argv(1); + break; + case 2: + $photo = argv(1); + break; + case 1: + default: killme(); - return; - } - - $s = abook_self($page_owner_uid); - - if(! $s) { - notice( t('Page owner information could not be retrieved.') . EOL); - logger('mod_photos: post: unable to locate contact record for page owner. uid=' . $page_owner_uid); - if(is_ajax()) - killme(); - return; - } - - $owner_record = $s[0]; - - $acl = new \Zotlabs\Access\AccessList(\App::$data['channel']); - - if((argc() > 3) && (argv(2) === 'album')) { - - $album = argv(3); - - if(! photos_album_exists($page_owner_uid, get_observer_hash(), $album)) { - notice( t('Album not found.') . EOL); - goaway(z_root() . '/' . $_SESSION['photo_return']); - } - - - /* - * DELETE photo album and all its photos - */ - - if($_REQUEST['dropalbum'] == t('Delete Album')) { - - - $folder_hash = ''; - - $r = q("select * from attach where is_dir = 1 and uid = %d and hash = '%s'", - intval($page_owner_uid), - dbesc($album) - ); - if(! $r) { - notice( t('Album not found.') . EOL); - return; - } - $folder_hash = $r[0]['hash']; - - - $res = array(); - $admin_delete = false; - - // get the list of photos we are about to delete - - if(remote_channel() && (! local_channel())) { - $str = photos_album_get_db_idstr($page_owner_uid,$album,remote_channel()); - } - elseif(local_channel()) { - $str = photos_album_get_db_idstr(local_channel(),$album); - } - elseif(is_site_admin()) { - $str = photos_album_get_db_idstr_admin($page_owner_uid,$album); - $admin_delete = true; - } - else { - $str = null; - } - if(! $str) { - goaway(z_root() . '/' . $_SESSION['photo_return']); - } - - $r = q("select id from item where resource_id in ( $str ) and resource_type = 'photo' and uid = %d " . item_normal(), - intval($page_owner_uid) - ); - if($r) { - foreach($r as $i) { - attach_delete($page_owner_uid, $i['resource_id'], true ); - } - } - - // remove the associated photos in case they weren't attached to an item - - q("delete from photo where resource_id in ( $str ) and uid = %d", - intval($page_owner_uid) - ); - - // @FIXME do the same for the linked attach - - if($folder_hash) { - attach_delete($page_owner_uid, $folder_hash, true ); - - if(! $admin_delete) { - $sync = attach_export_data(\App::$data['channel'],$folder_hash, true); - - if($sync) - build_sync_packet($page_owner_uid,array('file' => array($sync))); - } - } - - } - - goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']); - } - - if((argc() > 2) && (x($_REQUEST,'delete')) && ($_REQUEST['delete'] === t('Delete Photo'))) { - // same as above but remove single photo - - $ob_hash = get_observer_hash(); - if(! $ob_hash) - goaway(z_root() . '/' . $_SESSION['photo_return']); - - $r = q("SELECT id, resource_id FROM photo WHERE ( xchan = '%s' or uid = %d ) AND resource_id = '%s' LIMIT 1", - dbesc($ob_hash), - intval(local_channel()), - dbesc(argv(2)) - ); - - if($r) { - attach_delete($page_owner_uid, $r[0]['resource_id'], true ); - $sync = attach_export_data(\App::$data['channel'],$r[0]['resource_id'], true); - - if($sync) - build_sync_packet($page_owner_uid,array('file' => array($sync))); - } - elseif(is_site_admin()) { - // If the admin deletes a photo, don't sync - attach_delete($page_owner_uid, argv(2), true); - } - - - goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $_SESSION['album_return']); + // NOTREACHED } - if((argc() > 2) && array_key_exists('move_to_album',$_POST)) { - $m = q("select folder from attach where hash = '%s' and uid = %d limit 1", - dbesc(argv(2)), - intval($page_owner_uid) - ); - if(($m) && ($m[0]['folder'] != $_POST['move_to_album'])) { - attach_move($page_owner_uid,argv(2),$_POST['move_to_album']); - - $sync = attach_export_data(\App::$data['channel'],argv(2),true); - if($sync) - build_sync_packet($page_owner_uid,array('file' => array($sync))); - - if(! ($_POST['desc'] && $_POST['newtag'])) - goaway(z_root() . '/' . $_SESSION['photo_return']); - } - } - - if((argc() > 2) && ((x($_POST,'desc') !== false) || (x($_POST,'newtag') !== false))) { - - $desc = ((x($_POST,'desc')) ? notags(trim($_POST['desc'])) : ''); - $rawtags = ((x($_POST,'newtag')) ? notags(trim($_POST['newtag'])) : ''); - $item_id = ((x($_POST,'item_id')) ? intval($_POST['item_id']) : 0); - - $is_nsfw = ((x($_POST,'adult')) ? intval($_POST['adult']) : 0); - - $acl->set_from_array($_POST); - $perm = $acl->get(); - - $resource_id = argv(2); - - if((x($_POST,'rotate') !== false) && - ( (intval($_POST['rotate']) == 1) || (intval($_POST['rotate']) == 2) )) { - logger('rotate'); - - $r = q("select * from photo where resource_id = '%s' and uid = %d and imgscale = 0 limit 1", - dbesc($resource_id), - intval($page_owner_uid) - ); - if(count($r)) { - $d = (($r[0]['os_storage']) ? @file_get_contents(dbunescbin($r[0]['content'])) : dbunescbin($r[0]['content'])); - $ph = photo_factory($d, $r[0]['mimetype']); - if($ph->is_valid()) { - $rotate_deg = ( (intval($_POST['rotate']) == 1) ? 270 : 90 ); - $ph->rotate($rotate_deg); - - $width = $ph->getWidth(); - $height = $ph->getHeight(); - - if(intval($r[0]['os_storage'])) { - @file_put_contents($r[0]['content'],$ph->imageString()); - $data = $r[0]['content']; - $fsize = @filesize($r[0]['content']); - q("update attach set filesize = %d where hash = '%s' and uid = %d", - intval($fsize), - dbesc($resource_id), - intval($page_owner_uid) - ); - } - else { - $data = $ph->imageString(); - $fsize = strlen($data); - } - - $x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 0", - dbesc(datetime_convert()), - dbescbin($data), - intval($fsize), - intval($height), - intval($width), - dbesc($resource_id), - intval($page_owner_uid) - ); - - if($width > 1024 || $height > 1024) - $ph->scaleImage(1024); - - $width = $ph->getWidth(); - $height = $ph->getHeight(); - $data = $ph->imageString(); - $fsize = strlen($data); - - $x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 1", - dbesc(datetime_convert()), - dbescbin($data), - intval($fsize), - intval($height), - intval($width), - dbesc($resource_id), - intval($page_owner_uid) - ); - - - if($width > 640 || $height > 640) - $ph->scaleImage(640); - - $width = $ph->getWidth(); - $height = $ph->getHeight(); - $data = $ph->imageString(); - $fsize = strlen($data); - - $x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 2", - dbesc(datetime_convert()), - dbescbin($data), - intval($fsize), - intval($height), - intval($width), - dbesc($resource_id), - intval($page_owner_uid) - ); - - - if($width > 320 || $height > 320) - $ph->scaleImage(320); - - $width = $ph->getWidth(); - $height = $ph->getHeight(); - $data = $ph->imageString(); - $fsize = strlen($data); - - $x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 3", - dbesc(datetime_convert()), - dbescbin($data), - intval($fsize), - intval($height), - intval($width), - dbesc($resource_id), - intval($page_owner_uid) - ); - } - } - } - - $p = q("SELECT mimetype, is_nsfw, description, resource_id, imgscale, allow_cid, allow_gid, deny_cid, deny_gid FROM photo WHERE resource_id = '%s' AND uid = %d ORDER BY imgscale DESC", - dbesc($resource_id), - intval($page_owner_uid) - ); - if($p) { - $ext = $phototypes[$p[0]['mimetype']]; - - $r = q("UPDATE photo SET description = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' WHERE resource_id = '%s' AND uid = %d", - dbesc($desc), - dbesc($perm['allow_cid']), - dbesc($perm['allow_gid']), - dbesc($perm['deny_cid']), - dbesc($perm['deny_gid']), - dbesc($resource_id), - intval($page_owner_uid) - ); - } - - $item_private = (($str_contact_allow || $str_group_allow || $str_contact_deny || $str_group_deny) ? true : false); - - $old_is_nsfw = $p[0]['is_nsfw']; - if($old_is_nsfw != $is_nsfw) { - $r = q("update photo set is_nsfw = %d where resource_id = '%s' and uid = %d", - intval($is_nsfw), - dbesc($resource_id), - intval($page_owner_uid) - ); - } - - /* Don't make the item visible if the only change was the album name */ - - $visibility = 0; - if($p[0]['description'] !== $desc || strlen($rawtags)) - $visibility = 1; - - if(! $item_id) { - $item_id = photos_create_item(\App::$data['channel'],get_observer_hash(),$p[0],$visibility); - - } - - if($item_id) { - $r = q("SELECT * FROM item WHERE id = %d AND uid = %d LIMIT 1", - intval($item_id), - intval($page_owner_uid) - ); - - if($r) { - $old_tag = $r[0]['tag']; - $old_inform = $r[0]['inform']; - } - } - - - // make sure the linked item has the same permissions as the photo regardless of any other changes - $x = q("update item set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d - where id = %d", - dbesc($perm['allow_cid']), - dbesc($perm['allow_gid']), - dbesc($perm['deny_cid']), - dbesc($perm['deny_gid']), - intval($acl->is_private()), - intval($item_id) - ); - - // make sure the attach has the same permissions as the photo regardless of any other changes - $x = q("update attach set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where hash = '%s' and uid = %d and is_photo = 1", - dbesc($perm['allow_cid']), - dbesc($perm['allow_gid']), - dbesc($perm['deny_cid']), - dbesc($perm['deny_gid']), - dbesc($resource_id), - intval($page_owner_uid) - ); - - - - if(strlen($rawtags)) { - - $str_tags = ''; - $inform = ''; - - // if the new tag doesn't have a namespace specifier (@foo or #foo) give it a mention - - $x = substr($rawtags,0,1); - if($x !== '@' && $x !== '#') - $rawtags = '@' . $rawtags; - - require_once('include/text.php'); - $profile_uid = \App::$profile['profile_uid']; - - $results = linkify_tags($a, $rawtags, (local_channel()) ? local_channel() : $profile_uid); - - $success = $results['success']; - $post_tags = array(); - - foreach($results as $result) { - $success = $result['success']; - if($success['replaced']) { - $post_tags[] = array( - 'uid' => $profile_uid, - 'ttype' => $success['termtype'], - 'otype' => TERM_OBJ_POST, - 'term' => $success['term'], - 'url' => $success['url'] - ); - } - } - - $r = q("select * from item where id = %d and uid = %d limit 1", - intval($item_id), - intval($page_owner_uid) - ); - - if($r) { - $r = fetch_post_tags($r,true); - $datarray = $r[0]; - if($post_tags) { - if((! array_key_exists('term',$datarray)) || (! is_array($datarray['term']))) - $datarray['term'] = $post_tags; - else - $datarray['term'] = array_merge($datarray['term'],$post_tags); - } - item_store_update($datarray,$execflag); - } - - } - - $sync = attach_export_data(\App::$data['channel'],$resource_id); - - if($sync) - build_sync_packet($page_owner_uid,array('file' => array($sync))); - - goaway(z_root() . '/' . $_SESSION['photo_return']); - return; // NOTREACHED - - - } - - - /** - * default post action - upload a photo - */ - - $channel = \App::$data['channel']; - $observer = \App::$data['observer']; - - $_REQUEST['source'] = 'photos'; - require_once('include/attach.php'); - - if(! local_channel()) { - $_REQUEST['contact_allow'] = expand_acl($channel['channel_allow_cid']); - $_REQUEST['group_allow'] = expand_acl($channel['channel_allow_gid']); - $_REQUEST['contact_deny'] = expand_acl($channel['channel_deny_cid']); - $_REQUEST['group_deny'] = expand_acl($channel['channel_deny_gid']); - } - - - $matches = []; - $partial = false; - - - - if(array_key_exists('HTTP_CONTENT_RANGE',$_SERVER)) { - $pm = preg_match('/bytes (\d*)\-(\d*)\/(\d*)/',$_SERVER['HTTP_CONTENT_RANGE'],$matches); - if($pm) { - logger('Content-Range: ' . print_r($matches,true)); - $partial = true; - } - } - - if($partial) { - $x = save_chunk($channel,$matches[1],$matches[2],$matches[3]); - - if($x['partial']) { - header('Range: bytes=0-' . (($x['length']) ? $x['length'] - 1 : 0)); - json_return_and_die($result); - } - else { - header('Range: bytes=0-' . (($x['size']) ? $x['size'] - 1 : 0)); - - $_FILES['userfile'] = [ - 'name' => $x['name'], - 'type' => $x['type'], - 'tmp_name' => $x['tmp_name'], - 'error' => $x['error'], - 'size' => $x['size'] - ]; - } - } - else { - if(! array_key_exists('userfile',$_FILES)) { - $_FILES['userfile'] = [ - 'name' => $_FILES['files']['name'], - 'type' => $_FILES['files']['type'], - 'tmp_name' => $_FILES['files']['tmp_name'], - 'error' => $_FILES['files']['error'], - 'size' => $_FILES['files']['size'] - ]; - } - } - - $r = attach_store($channel,get_observer_hash(), '', $_REQUEST); - - if(! $r['success']) { - notice($r['message'] . EOL); - goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']); - } - - goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $r['data']['folder']); - - } - - - - function get() { - - // URLs: - // photos/name - // photos/name/album/xxxxx (xxxxx is album name) - // photos/name/image/xxxxx - - - if(observer_prohibited()) { - notice( t('Public access denied.') . EOL); - return; - } - - $unsafe = ((array_key_exists('unsafe',$_REQUEST) && $_REQUEST['unsafe']) ? 1 : 0); - - require_once('include/bbcode.php'); - require_once('include/security.php'); - require_once('include/conversation.php'); - - if(! x(\App::$data,'channel')) { - notice( t('No photos selected') . EOL ); - return; - } - - $ph = photo_factory(''); - $phototypes = $ph->supportedTypes(); - - $_SESSION['photo_return'] = \App::$cmd; - - // - // Parse arguments - // - - $can_comment = perm_is_allowed(\App::$profile['profile_uid'],get_observer_hash(),'post_comments'); - - if(argc() > 3) { - $datatype = argv(2); - $datum = argv(3); - } else { - if(argc() > 2) { - $datatype = argv(2); - $datum = ''; - } - else - $datatype = 'summary'; - } - - if(argc() > 4) - $cmd = argv(4); - else - $cmd = 'view'; - - // - // Setup permissions structures - // - - $can_post = false; - $visitor = 0; - - - $owner_uid = \App::$data['channel']['channel_id']; - $owner_aid = \App::$data['channel']['channel_account_id']; - - $observer = \App::get_observer(); - - $can_post = perm_is_allowed($owner_uid,$observer['xchan_hash'],'write_storage'); - $can_view = perm_is_allowed($owner_uid,$observer['xchan_hash'],'view_storage'); - - if(! $can_view) { - notice( t('Access to this item is restricted.') . EOL); - return; - } - - $sql_item = item_permissions_sql($owner_uid,get_observer_hash()); - $sql_extra = permissions_sql($owner_uid,get_observer_hash(),'photo'); - $sql_attach = permissions_sql($owner_uid,get_observer_hash(),'attach'); - - nav_set_selected('Photos'); - - $o = ' - - '; - - - $o .= "\r\n"; - - $_is_owner = (local_channel() && (local_channel() == $owner_uid)); - - /** - * Display upload form - */ - - if( $can_post) { - - $uploader = ''; - - $ret = array('post_url' => z_root() . '/photos/' . \App::$data['channel']['channel_address'], - 'addon_text' => $uploader, - 'default_upload' => true); - - call_hooks('photo_upload_form',$ret); - - /* Show space usage */ - - $r = q("select sum(filesize) as total from photo where aid = %d and imgscale = 0 ", - intval(\App::$data['channel']['channel_account_id']) - ); - - - $limit = engr_units_to_bytes(service_class_fetch(\App::$data['channel']['channel_id'],'photo_upload_limit')); - if($limit !== false) { - $usage_message = sprintf( t("%1$.2f MB of %2$.2f MB photo storage used."), $r[0]['total'] / 1024000, $limit / 1024000 ); - } - else { - $usage_message = sprintf( t('%1$.2f MB photo storage used.'), $r[0]['total'] / 1024000 ); - } - - if($_is_owner) { - $channel = \App::get_channel(); - - $acl = new \Zotlabs\Access\AccessList($channel); - $channel_acl = $acl->get(); - - $lockstate = (($acl->is_private()) ? 'lock' : 'unlock'); - } - - $aclselect = (($_is_owner) ? populate_acl($channel_acl,false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_storage')) : ''); - - // this is wrong but is to work around an issue with js_upload wherein it chokes if these variables - // don't exist. They really should be set to a parseable representation of the channel's default permissions - // which can be processed by getSelected() - - if(! $aclselect) { - $aclselect = ''; - } - - $selname = ''; - - if($datum) { - $h = attach_by_hash_nodata($datum,get_observer_hash()); - $selname = $h['data']['display_path']; - } - - - $albums = ((array_key_exists('albums', \App::$data)) ? \App::$data['albums'] : photos_albums_list(\App::$data['channel'],\App::$data['observer'])); - - if(! $selname) { - $def_album = get_pconfig(\App::$data['channel']['channel_id'],'system','photo_path'); - if($def_album) { - $selname = filepath_macro($def_album); - $albums['album'][] = array('text' => $selname); - } - } - - $tpl = get_markup_template('photos_upload.tpl'); - $upload_form = replace_macros($tpl,array( - '$pagename' => t('Upload Photos'), - '$sessid' => session_id(), - '$usage' => $usage_message, - '$nickname' => \App::$data['channel']['channel_address'], - '$newalbum_label' => t('Enter an album name'), - '$newalbum_placeholder' => t('or select an existing album (doubleclick)'), - '$visible' => array('visible', t('Create a status post for this upload'), 0,'', array(t('No'), t('Yes')), 'onclick="showHideBodyTextarea();"'), - '$caption' => array('description', t('Title (optional)')), - '$body' => array('body', t('Description (optional)'),'', 'Description will only appear in the status post'), - '$albums' => $albums['albums'], - '$selname' => $selname, - '$permissions' => t('Permissions'), - '$aclselect' => $aclselect, - '$allow_cid' => acl2json($channel_acl['allow_cid']), - '$allow_gid' => acl2json($channel_acl['allow_gid']), - '$deny_cid' => acl2json($channel_acl['deny_cid']), - '$deny_gid' => acl2json($channel_acl['deny_gid']), - '$lockstate' => $lockstate, - '$uploader' => $ret['addon_text'], - '$default' => (($ret['default_upload']) ? true : false), - '$uploadurl' => $ret['post_url'], - '$submit' => t('Upload') - - )); - - } - - // - // dispatch request - // - - /* - * Display a single photo album - */ - - if($datatype === 'album') { - - head_add_link([ - 'rel' => 'alternate', - 'type' => 'application/json+oembed', - 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string), - 'title' => 'oembed' - ]); - - if($x = photos_album_exists($owner_uid, get_observer_hash(), $datum)) { - \App::set_pager_itemspage(60); - $album = $x['display_path']; - } - else { - goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']); - } - - if($_GET['order'] === 'posted') - $order = 'ASC'; - else - $order = 'DESC'; - - $r = q("SELECT p.resource_id, p.id, p.filename, p.mimetype, p.imgscale, p.description, p.created FROM photo p INNER JOIN - (SELECT resource_id, max(imgscale) imgscale FROM photo left join attach on folder = '%s' and photo.resource_id = attach.hash WHERE attach.uid = %d AND imgscale <= 4 AND photo_usage IN ( %d, %d ) and is_nsfw = %d $sql_extra GROUP BY resource_id) ph - ON (p.resource_id = ph.resource_id AND p.imgscale = ph.imgscale) - ORDER BY created $order LIMIT %d OFFSET %d", - dbesc($x['hash']), - intval($owner_uid), - intval(PHOTO_NORMAL), - intval(PHOTO_PROFILE), - intval($unsafe), - intval(\App::$pager['itemspage']), - intval(\App::$pager['start']) - ); - - // edit album name - $album_edit = null; - - if($can_post) { - $album_e = $album; - $albums = ((array_key_exists('albums', \App::$data)) ? \App::$data['albums'] : photos_albums_list(\App::$data['channel'],\App::$data['observer'])); - - // @fixme - syncronise actions with DAV - - // $edit_tpl = get_markup_template('album_edit.tpl'); - // $album_edit = replace_macros($edit_tpl,array( - // '$nametext' => t('Enter a new album name'), - // '$name_placeholder' => t('or select an existing one (doubleclick)'), - // '$nickname' => \App::$data['channel']['channel_address'], - // '$album' => $album_e, - // '$albums' => $albums['albums'], - // '$hexalbum' => bin2hex($album), - // '$submit' => t('Submit'), - // '$dropsubmit' => t('Delete Album') - // )); - - } - - if($_GET['order'] === 'posted') - $order = array(t('Show Newest First'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $datum); - else - $order = array(t('Show Oldest First'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $datum . '?f=&order=posted'); - - $photos = array(); - if(count($r)) { - $twist = 'rotright'; - foreach($r as $rr) { - - if($twist == 'rotright') - $twist = 'rotleft'; - else - $twist = 'rotright'; - - $ext = $phototypes[$rr['mimetype']]; - - $imgalt_e = $rr['filename']; - $desc_e = $rr['description']; - - $imagelink = (z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $rr['resource_id'] - . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '')); - - $photos[] = array( - 'id' => $rr['id'], - 'twist' => ' ' . $twist . rand(2,4), - 'link' => $imagelink, - 'title' => t('View Photo'), - 'src' => z_root() . '/photo/' . $rr['resource_id'] . '-' . $rr['imgscale'] . '.' .$ext, - 'alt' => $imgalt_e, - 'desc'=> $desc_e, - 'ext' => $ext, - 'hash'=> $rr['resource_id'], - 'unknown' => t('Unknown') - ); - } - } - - if($_REQUEST['aj']) { - if($photos) { - $o = replace_macros(get_markup_template('photosajax.tpl'),array( - '$photos' => $photos, - '$album_id' => $datum - )); - } - else { - $o = '
'; - } - echo $o; - killme(); - } - else { - $o .= ""; - $tpl = get_markup_template('photo_album.tpl'); - $o .= replace_macros($tpl, array( - '$photos' => $photos, - '$album' => $album, - '$album_id' => $datum, - '$album_edit' => array(t('Edit Album'), $album_edit), - '$can_post' => $can_post, - '$upload' => array(t('Add Photos'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/upload/' . $datum), - '$order' => $order, - '$upload_form' => $upload_form, - '$usage' => $usage_message - )); - - } - - if((! $photos) && ($_REQUEST['aj'])) { - $o .= '
'; - echo $o; - killme(); - } - - return $o; - - } - - /** - * Display one photo - */ - - if($datatype === 'image') { - - \App::$page['htmlhead'] .= "\r\n" . '' . "\r\n"; - - $x = q("select folder from attach where hash = '%s' and uid = %d $sql_attach limit 1", - dbesc($datum), - intval($owner_uid) - ); - - // fetch image, item containing image, then comments - - $ph = q("SELECT id,aid,uid,xchan,resource_id,created,edited,title,description,album,filename,mimetype,height,width,filesize,imgscale,photo_usage,is_nsfw,allow_cid,allow_gid,deny_cid,deny_gid FROM photo WHERE uid = %d AND resource_id = '%s' - $sql_extra ORDER BY imgscale ASC ", - intval($owner_uid), - dbesc($datum) - ); - - if(! ($ph && $x)) { - - /* Check again - this time without specifying permissions */ - - $ph = q("SELECT id FROM photo WHERE uid = %d AND resource_id = '%s' LIMIT 1", - intval($owner_uid), - dbesc($datum) - ); - if($ph) - notice( t('Permission denied. Access to this item may be restricted.') . EOL); - else - notice( t('Photo not available') . EOL ); - return; - } - - - - $prevlink = ''; - $nextlink = ''; - - if($_GET['order'] === 'posted') - $order = 'ASC'; - else - $order = 'DESC'; - - - $prvnxt = q("SELECT hash FROM attach WHERE folder = '%s' AND uid = %d AND is_photo = 1 - $sql_attach ORDER BY created $order ", - dbesc($x[0]['folder']), - intval($owner_uid) - ); - - if(count($prvnxt)) { - for($z = 0; $z < count($prvnxt); $z++) { - if($prvnxt[$z]['hash'] == $ph[0]['resource_id']) { - $prv = $z - 1; - $nxt = $z + 1; - if($prv < 0) - $prv = count($prvnxt) - 1; - if($nxt >= count($prvnxt)) - $nxt = 0; - break; - } - } - - $prevlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$prv]['hash'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''); - $nextlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$nxt]['hash'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''); - } - - - if(count($ph) == 1) - $hires = $lores = $ph[0]; - if(count($ph) > 1) { - if($ph[1]['imgscale'] == 2) { - // original is 640 or less, we can display it directly - $hires = $lores = $ph[0]; - } - else { - $hires = $ph[0]; - $lores = $ph[1]; - } - } - - $album_link = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $x[0]['folder']; - $tools = Null; - $lock = Null; - - if($can_post && ($ph[0]['uid'] == $owner_uid)) { - $tools = array( - 'profile'=>array(z_root() . '/profile_photo/use/'.$ph[0]['resource_id'], t('Use as profile photo')), - 'cover'=>array(z_root() . '/cover_photo/use/'.$ph[0]['resource_id'], t('Use as cover photo')), - ); - } - - // lockstate - $lockstate = ( ( (strlen($ph[0]['allow_cid']) || strlen($ph[0]['allow_gid']) - || strlen($ph[0]['deny_cid']) || strlen($ph[0]['deny_gid'])) ) - ? array('lock', t('Private Photo')) - : array('unlock', Null)); - - \App::$page['htmlhead'] .= ''; - - if($prevlink) - $prevlink = array($prevlink, t('Previous')); - - $photo = array( - 'href' => z_root() . '/photo/' . $hires['resource_id'] . '-' . $hires['imgscale'] . '.' . $phototypes[$hires['mimetype']], - 'title'=> t('View Full Size'), - 'src' => z_root() . '/photo/' . $lores['resource_id'] . '-' . $lores['imgscale'] . '.' . $phototypes[$lores['mimetype']] . '?f=&_u=' . datetime_convert('','','','ymdhis') - ); - - if($nextlink) - $nextlink = array($nextlink, t('Next')); - - - // Do we have an item for this photo? - - $linked_items = q("SELECT * FROM item WHERE resource_id = '%s' and resource_type = 'photo' - $sql_item LIMIT 1", - dbesc($datum) - ); - - $map = null; - - if($linked_items) { - - xchan_query($linked_items); - $linked_items = fetch_post_tags($linked_items,true); - - $link_item = $linked_items[0]; - $item_normal = item_normal(); - - $r = q("select * from item where parent_mid = '%s' - $item_normal and uid = %d $sql_item ", - dbesc($link_item['mid']), - intval($link_item['uid']) - - ); - - if($r) { - xchan_query($r); - $r = fetch_post_tags($r,true); - $r = conv_sort($r,'commented'); - } - - $tags = array(); - if($link_item['term']) { - $cnt = 0; - foreach($link_item['term'] as $t) { - $tags[$cnt] = array(0 => format_term_for_display($t)); - if($can_post && ($ph[0]['uid'] == $owner_uid)) { - $tags[$cnt][1] = 'tagrm/drop/' . $link_item['id'] . '/' . bin2hex($t['term']); //?f=&item=' . $link_item['id']; - $tags[$cnt][2] = t('Remove'); - } - $cnt ++; - } - } - - if((local_channel()) && (local_channel() == $link_item['uid'])) { - q("UPDATE item SET item_unseen = 0 WHERE parent = %d and uid = %d and item_unseen = 1", - intval($link_item['parent']), - intval(local_channel()) - ); - } - - if($link_item['coord']) { - $map = generate_map($link_item['coord']); - } - } - - // logger('mod_photo: link_item' . print_r($link_item,true)); - - // FIXME - remove this when we move to conversation module - - $r = $r[0]['children']; - - $edit = null; - if($can_post) { - - $album_e = $ph[0]['album']; - $caption_e = $ph[0]['description']; - $aclselect_e = (($_is_owner) ? populate_acl($ph[0], true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_storage')) : ''); - $albums = ((array_key_exists('albums', \App::$data)) ? \App::$data['albums'] : photos_albums_list(\App::$data['channel'],\App::$data['observer'])); - - $_SESSION['album_return'] = bin2hex($ph[0]['album']); - - $folder_list = attach_folder_select_list($ph[0]['uid']); - - $edit = [ - 'edit' => t('Edit photo'), - 'id' => $link_item['id'], - 'rotatecw' => t('Rotate CW (right)'), - 'rotateccw' => t('Rotate CCW (left)'), - 'albums' => $albums['albums'], - 'album' => $album_e, - 'album_select' => [ 'move_to_album', t('Move photo to album'), $x[0]['folder'], '', $folder_list ], - 'newalbum_label' => t('Enter a new album name'), - 'newalbum_placeholder' => t('or select an existing one (doubleclick)'), - 'nickname' => \App::$data['channel']['channel_address'], - 'resource_id' => $ph[0]['resource_id'], - 'capt_label' => t('Title (optional)'), - 'caption' => $caption_e, - 'tag_label' => t('Add a Tag'), - 'permissions' => t('Permissions'), - 'aclselect' => $aclselect_e, - 'allow_cid' => acl2json($ph[0]['allow_cid']), - 'allow_gid' => acl2json($ph[0]['allow_gid']), - 'deny_cid' => acl2json($ph[0]['deny_cid']), - 'deny_gid' => acl2json($ph[0]['deny_gid']), - 'lockstate' => $lockstate[0], - 'help_tags' => t('Example: @bob, @Barbara_Jensen, @jim@example.com'), - 'item_id' => ((count($linked_items)) ? $link_item['id'] : 0), - 'adult_enabled' => feature_enabled($owner_uid,'adult_photo_flagging'), - 'adult' => array('adult',t('Flag as adult in album view'), intval($ph[0]['is_nsfw']),''), - 'submit' => t('Submit'), - 'delete' => t('Delete Photo') - ]; - } - - if(count($linked_items)) { - - $cmnt_tpl = get_markup_template('comment_item.tpl'); - $tpl = get_markup_template('photo_item.tpl'); - $return_url = \App::$cmd; - - $like_tpl = get_markup_template('like_noshare.tpl'); - - $likebuttons = ''; - - if($observer && ($can_post || $can_comment)) { - $likebuttons = [ - 'id' => $link_item['id'], - 'likethis' => t("I like this \x28toggle\x29"), - 'nolike' => t("I don't like this \x28toggle\x29"), - 'share' => t('Share'), - 'wait' => t('Please wait') - ]; - } - - $comments = ''; - if(! $r) { - if($observer && ($can_post || $can_comment)) { - $feature_auto_save_draft = ((feature_enabled($owner_uid, 'auto_save_draft')) ? "true" : "false"); - $commentbox = replace_macros($cmnt_tpl,array( - '$return_path' => '', - '$mode' => 'photos', - '$jsreload' => $return_url, - '$type' => 'wall-comment', - '$id' => $link_item['id'], - '$parent' => $link_item['id'], - '$profile_uid' => $owner_uid, - '$mylink' => $observer['xchan_url'], - '$mytitle' => t('This is you'), - '$myphoto' => $observer['xchan_photo_s'], - '$comment' => t('Comment'), - '$submit' => t('Submit'), - '$preview' => t('Preview'), - '$ww' => '', - '$feature_encrypt' => false, - '$auto_save_draft' => $feature_auto_save_draft - )); - } - } - - $alike = array(); - $dlike = array(); - - $like = ''; - $dislike = ''; - - $conv_responses = array( - 'like' => array('title' => t('Likes','title')),'dislike' => array('title' => t('Dislikes','title')), - 'agree' => array('title' => t('Agree','title')),'disagree' => array('title' => t('Disagree','title')), 'abstain' => array('title' => t('Abstain','title')), - 'attendyes' => array('title' => t('Attending','title')), 'attendno' => array('title' => t('Not attending','title')), 'attendmaybe' => array('title' => t('Might attend','title')) - ); - - - - - if($r) { - - foreach($r as $item) { - builtin_activity_puller($item, $conv_responses); - } - - $like_count = ((x($alike,$link_item['mid'])) ? $alike[$link_item['mid']] : ''); - $like_list = ((x($alike,$link_item['mid'])) ? $alike[$link_item['mid'] . '-l'] : ''); - - if(is_array($like_list) && (count($like_list) > MAX_LIKERS)) { - $like_list_part = array_slice($like_list, 0, MAX_LIKERS); - array_push($like_list_part, '' . t('View all') . ''); - } else { - $like_list_part = ''; - } - $like_button_label = tt('Like','Likes',$like_count,'noun'); - - //if (feature_enabled($conv->get_profile_owner(),'dislike')) { - $dislike_count = ((x($dlike,$link_item['mid'])) ? $dlike[$link_item['mid']] : ''); - $dislike_list = ((x($dlike,$link_item['mid'])) ? $dlike[$link_item['mid'] . '-l'] : ''); - $dislike_button_label = tt('Dislike','Dislikes',$dislike_count,'noun'); - if (is_array($dislike_list) && (count($dislike_list) > MAX_LIKERS)) { - $dislike_list_part = array_slice($dislike_list, 0, MAX_LIKERS); - array_push($dislike_list_part, '' . t('View all') . ''); - } else { - $dislike_list_part = ''; - } - //} - - - $like = ((isset($alike[$link_item['mid']])) ? format_like($alike[$link_item['mid']],$alike[$link_item['mid'] . '-l'],'like',$link_item['mid']) : ''); - $dislike = ((isset($dlike[$link_item['mid']])) ? format_like($dlike[$link_item['mid']],$dlike[$link_item['mid'] . '-l'],'dislike',$link_item['mid']) : ''); - - // display comments - - foreach($r as $item) { - $comment = ''; - $template = $tpl; - $sparkle = ''; - - if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE))) && ($item['id'] != $item['parent'])) - continue; - - $redirect_url = z_root() . '/redir/' . $item['cid'] ; - - - $profile_url = zid($item['author']['xchan_url']); - $sparkle = ''; - - - $profile_name = $item['author']['xchan_name']; - $profile_avatar = $item['author']['xchan_photo_m']; - - $profile_link = $profile_url; - - $drop = ''; - - if($observer['xchan_hash'] === $item['author_xchan'] || $observer['xchan_hash'] === $item['owner_xchan']) - $drop = replace_macros(get_markup_template('photo_drop.tpl'), array('$id' => $item['id'], '$delete' => t('Delete'))); - - - $name_e = $profile_name; - $title_e = $item['title']; - unobscure($item); - $body_e = prepare_text($item['body'],$item['mimetype']); - - $comments .= replace_macros($template,array( - '$id' => $item['id'], - '$mode' => 'photos', - '$profile_url' => $profile_link, - '$name' => $name_e, - '$thumb' => $profile_avatar, - '$sparkle' => $sparkle, - '$title' => $title_e, - '$body' => $body_e, - '$ago' => relative_date($item['created']), - '$indent' => (($item['parent'] != $item['id']) ? ' comment' : ''), - '$drop' => $drop, - '$comment' => $comment - )); - - } - - if($observer && ($can_post || $can_comment)) { - $commentbox = replace_macros($cmnt_tpl,array( - '$return_path' => '', - '$jsreload' => $return_url, - '$type' => 'wall-comment', - '$id' => $link_item['id'], - '$parent' => $link_item['id'], - '$profile_uid' => $owner_uid, - '$mylink' => $observer['xchan_url'], - '$mytitle' => t('This is you'), - '$myphoto' => $observer['xchan_photo_s'], - '$comment' => t('Comment'), - '$submit' => t('Submit'), - '$ww' => '' - )); - } - - } - $paginate = paginate($a); - } - - $album_e = array($album_link,$ph[0]['album']); - $like_e = $like; - $dislike_e = $dislike; - - - $response_verbs = array('like'); - if(feature_enabled($owner_uid,'dislike')) - $response_verbs[] = 'dislike'; - - $responses = get_responses($conv_responses,$response_verbs,'',$link_item); - - $hookdata = [ - 'onclick' => '$.colorbox({href: \'' . $photo['href'] . '\'}); return false;', - 'raw_photo' => $ph[0], - 'nickname' => \App::$data['channel']['channel_address'] - ]; - call_hooks('photo_view_filter', $hookdata); - - $photo_tpl = get_markup_template('photo_view.tpl'); - $o .= replace_macros($photo_tpl, array( - '$id' => $ph[0]['id'], - '$album' => $album_e, - '$tools_label' => t('Photo Tools'), - '$tools' => $tools, - '$lock' => $lockstate[1], - '$photo' => $photo, - '$prevlink' => $prevlink, - '$nextlink' => $nextlink, - '$desc' => $ph[0]['description'], - '$filename' => $ph[0]['filename'], - '$unknown' => t('Unknown'), - '$tag_hdr' => t('In This Photo:'), - '$tags' => $tags, - 'responses' => $responses, - '$edit' => $edit, - '$map' => $map, - '$map_text' => t('Map'), - '$likebuttons' => $likebuttons, - '$like' => $like_e, - '$dislike' => $dislike_e, - '$like_count' => $like_count, - '$like_list' => $like_list, - '$like_list_part' => $like_list_part, - '$like_button_label' => $like_button_label, - '$like_modal_title' => t('Likes','noun'), - '$dislike_modal_title' => t('Dislikes','noun'), - '$dislike_count' => $dislike_count, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_count : ''), - '$dislike_list' => $dislike_list, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list : ''), - '$dislike_list_part' => $dislike_list_part, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list_part : ''), - '$dislike_button_label' => $dislike_button_label, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_button_label : ''), - '$modal_dismiss' => t('Close'), - '$comments' => $comments, - '$commentbox' => $commentbox, - '$paginate' => $paginate, - '$onclick' => $hookdata['onclick'] - )); - - \App::$data['photo_html'] = $o; - - return $o; - } - - // Default - show recent photos with upload link (if applicable) - //$o = ''; - - \App::$page['htmlhead'] .= "\r\n" . '' . "\r\n"; - - - \App::set_pager_itemspage(60); - - $r = q("SELECT p.resource_id, p.id, p.filename, p.mimetype, p.album, p.imgscale, p.created, p.display_path - FROM photo p - INNER JOIN ( SELECT resource_id, max(imgscale) imgscale FROM photo - WHERE photo.uid = %d AND photo_usage IN ( %d, %d ) - AND is_nsfw = %d $sql_extra group by resource_id ) ph - ON (p.resource_id = ph.resource_id and p.imgscale = ph.imgscale) - ORDER by p.created DESC LIMIT %d OFFSET %d", - intval(\App::$data['channel']['channel_id']), - intval(PHOTO_NORMAL), - intval(PHOTO_PROFILE), - intval($unsafe), - intval(\App::$pager['itemspage']), - intval(\App::$pager['start']) + $cache_mode = array( + 'on' => false, + 'age' => 86400, + 'exp' => true, + 'leak' => false ); - - - - $photos = array(); - if($r) { - $twist = 'rotright'; - foreach($r as $rr) { - - if(! attach_can_view_folder(\App::$data['channel']['channel_id'],get_observer_hash(),$rr['resource_id'])) - continue; - - if($twist == 'rotright') - $twist = 'rotleft'; - else - $twist = 'rotright'; - $ext = $phototypes[$rr['mimetype']]; - - $alt_e = $rr['filename']; - $name_e = dirname($rr['display_path']); - - $photos[] = array( - 'id' => $rr['id'], - 'twist' => ' ' . $twist . rand(2,4), - 'link' => z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $rr['resource_id'], - 'title' => t('View Photo'), - 'src' => z_root() . '/photo/' . $rr['resource_id'] . '-' . ((($rr['imgscale']) == 6) ? 4 : $rr['imgscale']) . '.' . $ext, - 'alt' => $alt_e, - 'album' => array( - 'name' => $name_e, - ), - - ); - } - } + call_hooks('cache_mode_hook', $cache_mode); - if($_REQUEST['aj']) { - if($photos) { - $o = replace_macros(get_markup_template('photosajax.tpl'),array( - '$photos' => $photos, - '$album_id' => bin2hex(t('Recent Photos')) - )); + $observer_xchan = get_observer_hash(); + $ismodified = $_SERVER['HTTP_IF_MODIFIED_SINCE']; + + if(isset($type)) { + + /** + * Profile photos - Access controls on default profile photos are not honoured since they need to be exchanged with remote sites. + * + */ + + $default = get_default_profile_photo(); + + if($type === 'profile') { + switch($res) { + case 'm': + $resolution = 5; + $default = get_default_profile_photo(80); + break; + case 's': + $resolution = 6; + $default = get_default_profile_photo(48); + break; + case 'l': + default: + $resolution = 4; + break; + } } - else { - $o = '
'; + + $modified = filemtime($default); + $default = z_root() . '/' . $default; + $uid = $person; + + $d = [ 'imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '' ]; + call_hooks('get_profile_photo',$d); + + $resolution = $d['imgscale']; + $uid = $d['channel_id']; + $default = $d['default']; + $data = $d['data']; + $mimetype = $d['mimetype']; + + if(! $data) { + $r = q("SELECT * FROM photo WHERE imgscale = %d AND uid = %d AND photo_usage = %d LIMIT 1", + intval($resolution), + intval($uid), + intval(PHOTO_PROFILE) + ); + if($r) { + $modified = strtotime($r[0]['edited'] . "Z"); + $data = dbunescbin($r[0]['content']); + $mimetype = $r[0]['mimetype']; + } + if(intval($r[0]['os_storage'])) + $data = file_get_contents($data); + } + + if(! $data) { + $x = z_fetch_url($default,true,0,[ 'novalidate' => true ]); + $data = ($x['success'] ? $x['body'] : EMPTY_STR); + $mimetype = 'image/png'; } - echo $o; - killme(); } else { - $o .= ""; - $tpl = get_markup_template('photos_recent.tpl'); - $o .= replace_macros($tpl, array( - '$title' => t('Recent Photos'), - '$album_id' => bin2hex(t('Recent Photos')), - '$can_post' => $can_post, - '$upload' => array(t('Add Photos'), z_root().'/photos/'.\App::$data['channel']['channel_address'].'/upload'), - '$photos' => $photos, - '$upload_form' => $upload_form, - '$usage' => $usage_message - )); + /** + * Other photos + */ + + /* Check for a cookie to indicate display pixel density, in order to detect high-resolution + displays. This procedure was derived from the "Retina Images" by Jeremey Worboys, + used in accordance with the Creative Commons Attribution 3.0 Unported License. + Project link: https://github.com/Retina-Images/Retina-Images + License link: http://creativecommons.org/licenses/by/3.0/ + */ + + // @FIXME It seems this part doesn't work because we are not setting such cookie + $cookie_value = false; + if (isset($_COOKIE['devicePixelRatio'])) { + $cookie_value = intval($_COOKIE['devicePixelRatio']); + } + else { + // Force revalidation of cache on next request + // $prvcachecontrol = 'no-cache'; + $status = 'no cookie'; + } + + $resolution = 0; + + if(strpos($photo,'.') !== false) + $photo = substr($photo,0,strpos($photo,'.')); + + if(substr($photo,-2,1) == '-') { + $resolution = intval(substr($photo,-1,1)); + $photo = substr($photo,0,-2); + // If viewing on a high-res screen, attempt to serve a higher resolution image: + if ($resolution == 2 && ($cookie_value > 1)) + $resolution = 1; + } + + $r = q("SELECT uid, photo_usage, display_path FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1", + dbesc($photo), + intval($resolution) + ); + if($r) { + $allowed = (-1); + + $u = intval($r[0]['photo_usage']); + if($u) { + $allowed = 1; + if($u === PHOTO_COVER) + if($resolution < PHOTO_RES_COVER_1200) + $allowed = (-1); + if($u === PHOTO_PROFILE) + if(! in_array($resolution,[4,5,6])) + $allowed = (-1); + if($u === PHOTO_CACHE) { + // Validate cache + $cache = array( + 'resid' => $photo, + 'uid' => $r[0]['uid'], + 'status' => false + ); + if($cache_mode['on']) + call_hooks('cache_url_hook', $cache); + if(! $cache['status']) { + $url = htmlspecialchars_decode($r[0]['display_path']); + call_hooks('cache_sslify_hook', $url); + header("Location: " . $url); + killme(); + } + } + } + + if($allowed === (-1)) + $allowed = attach_can_view($r[0]['uid'],$observer_xchan,$photo); + + $channel = channelx_by_n($r[0]['uid']); + + // Now we'll see if we can access the photo + $e = q("SELECT * FROM photo WHERE resource_id = '%s' AND imgscale = %d $sql_extra LIMIT 1", + dbesc($photo), + intval($resolution) + ); + + $exists = (($e) ? true : false); + + if($exists && $allowed) { + $expires = strtotime($e[0]['expires'] . 'Z'); + $data = dbunescbin($e[0]['content']); + $filesize = $e[0]['filesize']; + $mimetype = $e[0]['mimetype']; + $modified = strtotime($e[0]['edited'] . 'Z'); + + if(intval($e[0]['os_storage'])) { + $streaming = $data; + } + if($e[0]['allow_cid'] != '' || $e[0]['allow_gid'] != '' || $e[0]['deny_gid'] != '' || $e[0]['deny_gid'] != '') + $prvcachecontrol = 'no-store, no-cache, must-revalidate'; + } + else { + if(! $allowed) { + http_status_exit(403,'forbidden'); + } + if(! $exists) { + http_status_exit(404,'not found'); + } + + } + } + else + http_status_exit(404,'not found'); + } + + header_remove('Pragma'); + + if($ismodified === gmdate("D, d M Y H:i:s", $modified) . " GMT") { + header_remove('Expires'); + header_remove('Cache-Control'); + header_remove('Set-Cookie'); + http_status_exit(304,'not modified'); + } + + if(! isset($data)) { + if(isset($resolution)) { + switch($resolution) { + case 4: + $default = get_default_profile_photo(); + break; + case 5: + $default = get_default_profile_photo(80); + break; + case 6: + $default = get_default_profile_photo(48); + break; + default: + killme(); + // NOTREACHED + break; + } + $x = z_fetch_url(z_root() . '/' . $default,true,0,[ 'novalidate' => true ]); + $data = ($x['success'] ? $x['body'] : EMPTY_STR); + $mimetype = 'image/png'; + } } - if((! $photos) && ($_REQUEST['aj'])) { - $o .= '
'; - echo $o; - killme(); + if(isset($res) && intval($res) && $res < 500) { + $ph = photo_factory($data, $mimetype); + if($ph->is_valid()) { + $ph->scaleImageSquare($res); + $data = $ph->imageString(); + $mimetype = $ph->getType(); + } } + + if(isset($prvcachecontrol)) { - // paginate($a); - return $o; + // it is a private photo that they have no permission to view. + // tell the browser not to cache it, in case they authenticate + // and subsequently have permission to see it + + header("Cache-Control: " . $prvcachecontrol); + + } + else { + // The photo cache default is 1 day to provide a privacy trade-off, + // as somebody reducing photo permissions on a photo that is already + // "in the wild" won't be able to stop the photo from being viewed + // for this amount amount of time once it is in the browser cache. + // The privacy expectations of your site members and their perception + // of privacy where it affects the entire project may be affected. + // This has performance considerations but we highly recommend you + // leave it alone. + + $maxage = $cache_mode['age']; + + if($cache_mode['exp'] || (! isset($expires)) || (isset($expires) && $expires - 60 < time())) + $expires = time() + $maxage; + else + $maxage = $expires - time(); + + header("Expires: " . gmdate("D, d M Y H:i:s", $expires) . " GMT"); + header("Cache-Control: max-age=" . $maxage); + + } + + header("Content-type: " . $mimetype); + header("Last-Modified: " . gmdate("D, d M Y H:i:s", $modified) . " GMT"); + header("Content-Length: " . (isset($filesize) ? $filesize : strlen($data))); + + // If it's a file resource, stream it. + if($streaming && $channel) { + if(strpos($streaming,'store') !== false) + $istream = fopen($streaming,'rb'); + else + $istream = fopen('store/' . $channel['channel_address'] . '/' . $streaming,'rb'); + $ostream = fopen('php://output','wb'); + if($istream && $ostream) { + pipe_streams($istream,$ostream); + fclose($istream); + fclose($ostream); + } + } + else { + echo $data; + } + + killme(); } - } From 1b0a6fe9ebe8e5ae8a142745a53e228df2c6bbcf Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Mon, 17 Dec 2018 00:58:46 +0100 Subject: [PATCH 18/93] SSLify cached URL on redirect if needed --- Zotlabs/Module/Photo.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Zotlabs/Module/Photo.php b/Zotlabs/Module/Photo.php index 7365a5f64..967a3b703 100644 --- a/Zotlabs/Module/Photo.php +++ b/Zotlabs/Module/Photo.php @@ -165,7 +165,9 @@ class Photo extends \Zotlabs\Web\Controller { if($cache_mode['on']) call_hooks('cache_url_hook', $cache); if(! $cache['status']) { - header("Location: " . htmlspecialchars_decode($r[0]['display_path'])); + $url = htmlspecialchars_decode($r[0]['display_path']); + call_hooks('cache_sslify_hook', $url); + header("Location: " . $url); killme(); } } From 72dc6ea77c0c6aa439ea5f7a47130fbb354175ce Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Mon, 17 Dec 2018 01:16:08 +0100 Subject: [PATCH 19/93] Revert Photos.php code --- Zotlabs/Module/Photos.php | 1698 ++++++++++++++++++++++++++++++------- 1 file changed, 1405 insertions(+), 293 deletions(-) diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php index 967a3b703..b87c586da 100644 --- a/Zotlabs/Module/Photos.php +++ b/Zotlabs/Module/Photos.php @@ -1,312 +1,1424 @@ false, - 'age' => 86400, - 'exp' => true, - 'leak' => false - ); - call_hooks('cache_mode_hook', $cache_mode); - - $observer_xchan = get_observer_hash(); - $ismodified = $_SERVER['HTTP_IF_MODIFIED_SINCE']; - - if(isset($type)) { - /** - * Profile photos - Access controls on default profile photos are not honoured since they need to be exchanged with remote sites. - * - */ - - $default = get_default_profile_photo(); - - if($type === 'profile') { - switch($res) { - case 'm': - $resolution = 5; - $default = get_default_profile_photo(80); - break; - case 's': - $resolution = 6; - $default = get_default_profile_photo(48); - break; - case 'l': - default: - $resolution = 4; - break; - } - } - - $modified = filemtime($default); - $default = z_root() . '/' . $default; - $uid = $person; - - $d = [ 'imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '' ]; - call_hooks('get_profile_photo',$d); - - $resolution = $d['imgscale']; - $uid = $d['channel_id']; - $default = $d['default']; - $data = $d['data']; - $mimetype = $d['mimetype']; - - if(! $data) { - $r = q("SELECT * FROM photo WHERE imgscale = %d AND uid = %d AND photo_usage = %d LIMIT 1", - intval($resolution), - intval($uid), - intval(PHOTO_PROFILE) - ); - if($r) { - $modified = strtotime($r[0]['edited'] . "Z"); - $data = dbunescbin($r[0]['content']); - $mimetype = $r[0]['mimetype']; - } - if(intval($r[0]['os_storage'])) - $data = file_get_contents($data); - } - - if(! $data) { - $x = z_fetch_url($default,true,0,[ 'novalidate' => true ]); - $data = ($x['success'] ? $x['body'] : EMPTY_STR); - $mimetype = 'image/png'; - } - } - else { - - /** - * Other photos - */ - - /* Check for a cookie to indicate display pixel density, in order to detect high-resolution - displays. This procedure was derived from the "Retina Images" by Jeremey Worboys, - used in accordance with the Creative Commons Attribution 3.0 Unported License. - Project link: https://github.com/Retina-Images/Retina-Images - License link: http://creativecommons.org/licenses/by/3.0/ - */ - - // @FIXME It seems this part doesn't work because we are not setting such cookie - $cookie_value = false; - if (isset($_COOKIE['devicePixelRatio'])) { - $cookie_value = intval($_COOKIE['devicePixelRatio']); - } - else { - // Force revalidation of cache on next request - // $prvcachecontrol = 'no-cache'; - $status = 'no cookie'; - } - - $resolution = 0; - - if(strpos($photo,'.') !== false) - $photo = substr($photo,0,strpos($photo,'.')); - - if(substr($photo,-2,1) == '-') { - $resolution = intval(substr($photo,-1,1)); - $photo = substr($photo,0,-2); - // If viewing on a high-res screen, attempt to serve a higher resolution image: - if ($resolution == 2 && ($cookie_value > 1)) - $resolution = 1; - } - - $r = q("SELECT uid, photo_usage, display_path FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1", - dbesc($photo), - intval($resolution) - ); - if($r) { - $allowed = (-1); - - $u = intval($r[0]['photo_usage']); - if($u) { - $allowed = 1; - if($u === PHOTO_COVER) - if($resolution < PHOTO_RES_COVER_1200) - $allowed = (-1); - if($u === PHOTO_PROFILE) - if(! in_array($resolution,[4,5,6])) - $allowed = (-1); - if($u === PHOTO_CACHE) { - // Validate cache - $cache = array( - 'resid' => $photo, - 'uid' => $r[0]['uid'], - 'status' => false - ); - if($cache_mode['on']) - call_hooks('cache_url_hook', $cache); - if(! $cache['status']) { - $url = htmlspecialchars_decode($r[0]['display_path']); - call_hooks('cache_sslify_hook', $url); - header("Location: " . $url); - killme(); - } - } - } - - if($allowed === (-1)) - $allowed = attach_can_view($r[0]['uid'],$observer_xchan,$photo); - - $channel = channelx_by_n($r[0]['uid']); - - // Now we'll see if we can access the photo - $e = q("SELECT * FROM photo WHERE resource_id = '%s' AND imgscale = %d $sql_extra LIMIT 1", - dbesc($photo), - intval($resolution) - ); - - $exists = (($e) ? true : false); - - if($exists && $allowed) { - $expires = strtotime($e[0]['expires'] . 'Z'); - $data = dbunescbin($e[0]['content']); - $filesize = $e[0]['filesize']; - $mimetype = $e[0]['mimetype']; - $modified = strtotime($e[0]['edited'] . 'Z'); - - if(intval($e[0]['os_storage'])) { - $streaming = $data; - } - if($e[0]['allow_cid'] != '' || $e[0]['allow_gid'] != '' || $e[0]['deny_gid'] != '' || $e[0]['deny_gid'] != '') - $prvcachecontrol = 'no-store, no-cache, must-revalidate'; - } - else { - if(! $allowed) { - http_status_exit(403,'forbidden'); - } - if(! $exists) { - http_status_exit(404,'not found'); - } - - } - } - else - http_status_exit(404,'not found'); - } - - header_remove('Pragma'); - - if($ismodified === gmdate("D, d M Y H:i:s", $modified) . " GMT") { - header_remove('Expires'); - header_remove('Cache-Control'); - header_remove('Set-Cookie'); - http_status_exit(304,'not modified'); - } - - if(! isset($data)) { - if(isset($resolution)) { - switch($resolution) { - case 4: - $default = get_default_profile_photo(); - break; - case 5: - $default = get_default_profile_photo(80); - break; - case 6: - $default = get_default_profile_photo(48); - break; - default: - killme(); - // NOTREACHED - break; - } - $x = z_fetch_url(z_root() . '/' . $default,true,0,[ 'novalidate' => true ]); - $data = ($x['success'] ? $x['body'] : EMPTY_STR); - $mimetype = 'image/png'; - } + if(observer_prohibited()) { + return; } - if(isset($res) && intval($res) && $res < 500) { - $ph = photo_factory($data, $mimetype); - if($ph->is_valid()) { - $ph->scaleImageSquare($res); - $data = $ph->imageString(); - $mimetype = $ph->getType(); - } - } - - if(isset($prvcachecontrol)) { + if(argc() > 1) { + $nick = argv(1); - // it is a private photo that they have no permission to view. - // tell the browser not to cache it, in case they authenticate - // and subsequently have permission to see it + profile_load($nick); - header("Cache-Control: " . $prvcachecontrol); + $channelx = channelx_by_nick($nick); + + if(! $channelx) + return; + + \App::$data['channel'] = $channelx; + + $observer = \App::get_observer(); + \App::$data['observer'] = $observer; + + $observer_xchan = (($observer) ? $observer['xchan_hash'] : ''); + + head_set_icon(\App::$data['channel']['xchan_photo_s']); + + \App::$page['htmlhead'] .= "" ; } - else { - // The photo cache default is 1 day to provide a privacy trade-off, - // as somebody reducing photo permissions on a photo that is already - // "in the wild" won't be able to stop the photo from being viewed - // for this amount amount of time once it is in the browser cache. - // The privacy expectations of your site members and their perception - // of privacy where it affects the entire project may be affected. - // This has performance considerations but we highly recommend you - // leave it alone. - $maxage = $cache_mode['age']; - - if($cache_mode['exp'] || (! isset($expires)) || (isset($expires) && $expires - 60 < time())) - $expires = time() + $maxage; - else - $maxage = $expires - time(); - - header("Expires: " . gmdate("D, d M Y H:i:s", $expires) . " GMT"); - header("Cache-Control: max-age=" . $maxage); - - } - - header("Content-type: " . $mimetype); - header("Last-Modified: " . gmdate("D, d M Y H:i:s", $modified) . " GMT"); - header("Content-Length: " . (isset($filesize) ? $filesize : strlen($data))); - - // If it's a file resource, stream it. - if($streaming && $channel) { - if(strpos($streaming,'store') !== false) - $istream = fopen($streaming,'rb'); - else - $istream = fopen('store/' . $channel['channel_address'] . '/' . $streaming,'rb'); - $ostream = fopen('php://output','wb'); - if($istream && $ostream) { - pipe_streams($istream,$ostream); - fclose($istream); - fclose($ostream); - } - } - else { - echo $data; - } - - killme(); + return; } + + + function post() { + + logger('mod-photos: photos_post: begin' , LOGGER_DEBUG); + + logger('mod_photos: REQUEST ' . print_r($_REQUEST,true), LOGGER_DATA); + logger('mod_photos: FILES ' . print_r($_FILES,true), LOGGER_DATA); + + $ph = photo_factory(''); + + $phototypes = $ph->supportedTypes(); + + $can_post = false; + + $page_owner_uid = \App::$data['channel']['channel_id']; + + if(perm_is_allowed($page_owner_uid,get_observer_hash(),'write_storage')) + $can_post = true; + + if(! $can_post) { + notice( t('Permission denied.') . EOL ); + if(is_ajax()) + killme(); + return; + } + + $s = abook_self($page_owner_uid); + + if(! $s) { + notice( t('Page owner information could not be retrieved.') . EOL); + logger('mod_photos: post: unable to locate contact record for page owner. uid=' . $page_owner_uid); + if(is_ajax()) + killme(); + return; + } + + $owner_record = $s[0]; + + $acl = new \Zotlabs\Access\AccessList(\App::$data['channel']); + + if((argc() > 3) && (argv(2) === 'album')) { + + $album = argv(3); + + if(! photos_album_exists($page_owner_uid, get_observer_hash(), $album)) { + notice( t('Album not found.') . EOL); + goaway(z_root() . '/' . $_SESSION['photo_return']); + } + + + /* + * DELETE photo album and all its photos + */ + + if($_REQUEST['dropalbum'] == t('Delete Album')) { + + + $folder_hash = ''; + + $r = q("select * from attach where is_dir = 1 and uid = %d and hash = '%s'", + intval($page_owner_uid), + dbesc($album) + ); + if(! $r) { + notice( t('Album not found.') . EOL); + return; + } + $folder_hash = $r[0]['hash']; + + + $res = array(); + $admin_delete = false; + + // get the list of photos we are about to delete + + if(remote_channel() && (! local_channel())) { + $str = photos_album_get_db_idstr($page_owner_uid,$album,remote_channel()); + } + elseif(local_channel()) { + $str = photos_album_get_db_idstr(local_channel(),$album); + } + elseif(is_site_admin()) { + $str = photos_album_get_db_idstr_admin($page_owner_uid,$album); + $admin_delete = true; + } + else { + $str = null; + } + if(! $str) { + goaway(z_root() . '/' . $_SESSION['photo_return']); + } + + $r = q("select id from item where resource_id in ( $str ) and resource_type = 'photo' and uid = %d " . item_normal(), + intval($page_owner_uid) + ); + if($r) { + foreach($r as $i) { + attach_delete($page_owner_uid, $i['resource_id'], true ); + } + } + + // remove the associated photos in case they weren't attached to an item + + q("delete from photo where resource_id in ( $str ) and uid = %d", + intval($page_owner_uid) + ); + + // @FIXME do the same for the linked attach + + if($folder_hash) { + attach_delete($page_owner_uid, $folder_hash, true ); + + if(! $admin_delete) { + $sync = attach_export_data(\App::$data['channel'],$folder_hash, true); + + if($sync) + build_sync_packet($page_owner_uid,array('file' => array($sync))); + } + } + + } + + goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']); + } + + if((argc() > 2) && (x($_REQUEST,'delete')) && ($_REQUEST['delete'] === t('Delete Photo'))) { + // same as above but remove single photo + + $ob_hash = get_observer_hash(); + if(! $ob_hash) + goaway(z_root() . '/' . $_SESSION['photo_return']); + + $r = q("SELECT id, resource_id FROM photo WHERE ( xchan = '%s' or uid = %d ) AND resource_id = '%s' LIMIT 1", + dbesc($ob_hash), + intval(local_channel()), + dbesc(argv(2)) + ); + + if($r) { + attach_delete($page_owner_uid, $r[0]['resource_id'], true ); + $sync = attach_export_data(\App::$data['channel'],$r[0]['resource_id'], true); + + if($sync) + build_sync_packet($page_owner_uid,array('file' => array($sync))); + } + elseif(is_site_admin()) { + // If the admin deletes a photo, don't sync + attach_delete($page_owner_uid, argv(2), true); + } + + + goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $_SESSION['album_return']); + } + + if((argc() > 2) && array_key_exists('move_to_album',$_POST)) { + $m = q("select folder from attach where hash = '%s' and uid = %d limit 1", + dbesc(argv(2)), + intval($page_owner_uid) + ); + if(($m) && ($m[0]['folder'] != $_POST['move_to_album'])) { + attach_move($page_owner_uid,argv(2),$_POST['move_to_album']); + + $sync = attach_export_data(\App::$data['channel'],argv(2),true); + if($sync) + build_sync_packet($page_owner_uid,array('file' => array($sync))); + + if(! ($_POST['desc'] && $_POST['newtag'])) + goaway(z_root() . '/' . $_SESSION['photo_return']); + } + } + + if((argc() > 2) && ((x($_POST,'desc') !== false) || (x($_POST,'newtag') !== false))) { + + $desc = ((x($_POST,'desc')) ? notags(trim($_POST['desc'])) : ''); + $rawtags = ((x($_POST,'newtag')) ? notags(trim($_POST['newtag'])) : ''); + $item_id = ((x($_POST,'item_id')) ? intval($_POST['item_id']) : 0); + + $is_nsfw = ((x($_POST,'adult')) ? intval($_POST['adult']) : 0); + + $acl->set_from_array($_POST); + $perm = $acl->get(); + + $resource_id = argv(2); + + if((x($_POST,'rotate') !== false) && + ( (intval($_POST['rotate']) == 1) || (intval($_POST['rotate']) == 2) )) { + logger('rotate'); + + $r = q("select * from photo where resource_id = '%s' and uid = %d and imgscale = 0 limit 1", + dbesc($resource_id), + intval($page_owner_uid) + ); + if(count($r)) { + $d = (($r[0]['os_storage']) ? @file_get_contents(dbunescbin($r[0]['content'])) : dbunescbin($r[0]['content'])); + $ph = photo_factory($d, $r[0]['mimetype']); + if($ph->is_valid()) { + $rotate_deg = ( (intval($_POST['rotate']) == 1) ? 270 : 90 ); + $ph->rotate($rotate_deg); + + $width = $ph->getWidth(); + $height = $ph->getHeight(); + + if(intval($r[0]['os_storage'])) { + @file_put_contents($r[0]['content'],$ph->imageString()); + $data = $r[0]['content']; + $fsize = @filesize($r[0]['content']); + q("update attach set filesize = %d where hash = '%s' and uid = %d", + intval($fsize), + dbesc($resource_id), + intval($page_owner_uid) + ); + } + else { + $data = $ph->imageString(); + $fsize = strlen($data); + } + + $x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 0", + dbesc(datetime_convert()), + dbescbin($data), + intval($fsize), + intval($height), + intval($width), + dbesc($resource_id), + intval($page_owner_uid) + ); + + if($width > 1024 || $height > 1024) + $ph->scaleImage(1024); + + $width = $ph->getWidth(); + $height = $ph->getHeight(); + $data = $ph->imageString(); + $fsize = strlen($data); + + $x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 1", + dbesc(datetime_convert()), + dbescbin($data), + intval($fsize), + intval($height), + intval($width), + dbesc($resource_id), + intval($page_owner_uid) + ); + + + if($width > 640 || $height > 640) + $ph->scaleImage(640); + + $width = $ph->getWidth(); + $height = $ph->getHeight(); + $data = $ph->imageString(); + $fsize = strlen($data); + + $x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 2", + dbesc(datetime_convert()), + dbescbin($data), + intval($fsize), + intval($height), + intval($width), + dbesc($resource_id), + intval($page_owner_uid) + ); + + + if($width > 320 || $height > 320) + $ph->scaleImage(320); + + $width = $ph->getWidth(); + $height = $ph->getHeight(); + $data = $ph->imageString(); + $fsize = strlen($data); + + $x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 3", + dbesc(datetime_convert()), + dbescbin($data), + intval($fsize), + intval($height), + intval($width), + dbesc($resource_id), + intval($page_owner_uid) + ); + } + } + } + + $p = q("SELECT mimetype, is_nsfw, description, resource_id, imgscale, allow_cid, allow_gid, deny_cid, deny_gid FROM photo WHERE resource_id = '%s' AND uid = %d ORDER BY imgscale DESC", + dbesc($resource_id), + intval($page_owner_uid) + ); + if($p) { + $ext = $phototypes[$p[0]['mimetype']]; + + $r = q("UPDATE photo SET description = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' WHERE resource_id = '%s' AND uid = %d", + dbesc($desc), + dbesc($perm['allow_cid']), + dbesc($perm['allow_gid']), + dbesc($perm['deny_cid']), + dbesc($perm['deny_gid']), + dbesc($resource_id), + intval($page_owner_uid) + ); + } + + $item_private = (($str_contact_allow || $str_group_allow || $str_contact_deny || $str_group_deny) ? true : false); + + $old_is_nsfw = $p[0]['is_nsfw']; + if($old_is_nsfw != $is_nsfw) { + $r = q("update photo set is_nsfw = %d where resource_id = '%s' and uid = %d", + intval($is_nsfw), + dbesc($resource_id), + intval($page_owner_uid) + ); + } + + /* Don't make the item visible if the only change was the album name */ + + $visibility = 0; + if($p[0]['description'] !== $desc || strlen($rawtags)) + $visibility = 1; + + if(! $item_id) { + $item_id = photos_create_item(\App::$data['channel'],get_observer_hash(),$p[0],$visibility); + + } + + if($item_id) { + $r = q("SELECT * FROM item WHERE id = %d AND uid = %d LIMIT 1", + intval($item_id), + intval($page_owner_uid) + ); + + if($r) { + $old_tag = $r[0]['tag']; + $old_inform = $r[0]['inform']; + } + } + + + // make sure the linked item has the same permissions as the photo regardless of any other changes + $x = q("update item set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d + where id = %d", + dbesc($perm['allow_cid']), + dbesc($perm['allow_gid']), + dbesc($perm['deny_cid']), + dbesc($perm['deny_gid']), + intval($acl->is_private()), + intval($item_id) + ); + + // make sure the attach has the same permissions as the photo regardless of any other changes + $x = q("update attach set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where hash = '%s' and uid = %d and is_photo = 1", + dbesc($perm['allow_cid']), + dbesc($perm['allow_gid']), + dbesc($perm['deny_cid']), + dbesc($perm['deny_gid']), + dbesc($resource_id), + intval($page_owner_uid) + ); + + + + if(strlen($rawtags)) { + + $str_tags = ''; + $inform = ''; + + // if the new tag doesn't have a namespace specifier (@foo or #foo) give it a mention + + $x = substr($rawtags,0,1); + if($x !== '@' && $x !== '#') + $rawtags = '@' . $rawtags; + + require_once('include/text.php'); + $profile_uid = \App::$profile['profile_uid']; + + $results = linkify_tags($a, $rawtags, (local_channel()) ? local_channel() : $profile_uid); + + $success = $results['success']; + $post_tags = array(); + + foreach($results as $result) { + $success = $result['success']; + if($success['replaced']) { + $post_tags[] = array( + 'uid' => $profile_uid, + 'ttype' => $success['termtype'], + 'otype' => TERM_OBJ_POST, + 'term' => $success['term'], + 'url' => $success['url'] + ); + } + } + + $r = q("select * from item where id = %d and uid = %d limit 1", + intval($item_id), + intval($page_owner_uid) + ); + + if($r) { + $r = fetch_post_tags($r,true); + $datarray = $r[0]; + if($post_tags) { + if((! array_key_exists('term',$datarray)) || (! is_array($datarray['term']))) + $datarray['term'] = $post_tags; + else + $datarray['term'] = array_merge($datarray['term'],$post_tags); + } + item_store_update($datarray,$execflag); + } + + } + + $sync = attach_export_data(\App::$data['channel'],$resource_id); + + if($sync) + build_sync_packet($page_owner_uid,array('file' => array($sync))); + + goaway(z_root() . '/' . $_SESSION['photo_return']); + return; // NOTREACHED + + + } + + + /** + * default post action - upload a photo + */ + + $channel = \App::$data['channel']; + $observer = \App::$data['observer']; + + $_REQUEST['source'] = 'photos'; + require_once('include/attach.php'); + + if(! local_channel()) { + $_REQUEST['contact_allow'] = expand_acl($channel['channel_allow_cid']); + $_REQUEST['group_allow'] = expand_acl($channel['channel_allow_gid']); + $_REQUEST['contact_deny'] = expand_acl($channel['channel_deny_cid']); + $_REQUEST['group_deny'] = expand_acl($channel['channel_deny_gid']); + } + + + $matches = []; + $partial = false; + + + + if(array_key_exists('HTTP_CONTENT_RANGE',$_SERVER)) { + $pm = preg_match('/bytes (\d*)\-(\d*)\/(\d*)/',$_SERVER['HTTP_CONTENT_RANGE'],$matches); + if($pm) { + logger('Content-Range: ' . print_r($matches,true)); + $partial = true; + } + } + + if($partial) { + $x = save_chunk($channel,$matches[1],$matches[2],$matches[3]); + + if($x['partial']) { + header('Range: bytes=0-' . (($x['length']) ? $x['length'] - 1 : 0)); + json_return_and_die($result); + } + else { + header('Range: bytes=0-' . (($x['size']) ? $x['size'] - 1 : 0)); + + $_FILES['userfile'] = [ + 'name' => $x['name'], + 'type' => $x['type'], + 'tmp_name' => $x['tmp_name'], + 'error' => $x['error'], + 'size' => $x['size'] + ]; + } + } + else { + if(! array_key_exists('userfile',$_FILES)) { + $_FILES['userfile'] = [ + 'name' => $_FILES['files']['name'], + 'type' => $_FILES['files']['type'], + 'tmp_name' => $_FILES['files']['tmp_name'], + 'error' => $_FILES['files']['error'], + 'size' => $_FILES['files']['size'] + ]; + } + } + + $r = attach_store($channel,get_observer_hash(), '', $_REQUEST); + + if(! $r['success']) { + notice($r['message'] . EOL); + goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']); + } + + goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $r['data']['folder']); + + } + + + + function get() { + + // URLs: + // photos/name + // photos/name/album/xxxxx (xxxxx is album name) + // photos/name/image/xxxxx + + + if(observer_prohibited()) { + notice( t('Public access denied.') . EOL); + return; + } + + $unsafe = ((array_key_exists('unsafe',$_REQUEST) && $_REQUEST['unsafe']) ? 1 : 0); + + require_once('include/bbcode.php'); + require_once('include/security.php'); + require_once('include/conversation.php'); + + if(! x(\App::$data,'channel')) { + notice( t('No photos selected') . EOL ); + return; + } + + $ph = photo_factory(''); + $phototypes = $ph->supportedTypes(); + + $_SESSION['photo_return'] = \App::$cmd; + + // + // Parse arguments + // + + $can_comment = perm_is_allowed(\App::$profile['profile_uid'],get_observer_hash(),'post_comments'); + + if(argc() > 3) { + $datatype = argv(2); + $datum = argv(3); + } else { + if(argc() > 2) { + $datatype = argv(2); + $datum = ''; + } + else + $datatype = 'summary'; + } + + if(argc() > 4) + $cmd = argv(4); + else + $cmd = 'view'; + + // + // Setup permissions structures + // + + $can_post = false; + $visitor = 0; + + + $owner_uid = \App::$data['channel']['channel_id']; + $owner_aid = \App::$data['channel']['channel_account_id']; + + $observer = \App::get_observer(); + + $can_post = perm_is_allowed($owner_uid,$observer['xchan_hash'],'write_storage'); + $can_view = perm_is_allowed($owner_uid,$observer['xchan_hash'],'view_storage'); + + if(! $can_view) { + notice( t('Access to this item is restricted.') . EOL); + return; + } + + $sql_item = item_permissions_sql($owner_uid,get_observer_hash()); + $sql_extra = permissions_sql($owner_uid,get_observer_hash(),'photo'); + $sql_attach = permissions_sql($owner_uid,get_observer_hash(),'attach'); + + nav_set_selected('Photos'); + + $o = ' + + '; + + + $o .= "\r\n"; + + $_is_owner = (local_channel() && (local_channel() == $owner_uid)); + + /** + * Display upload form + */ + + if( $can_post) { + + $uploader = ''; + + $ret = array('post_url' => z_root() . '/photos/' . \App::$data['channel']['channel_address'], + 'addon_text' => $uploader, + 'default_upload' => true); + + call_hooks('photo_upload_form',$ret); + + /* Show space usage */ + + $r = q("select sum(filesize) as total from photo where aid = %d and imgscale = 0 ", + intval(\App::$data['channel']['channel_account_id']) + ); + + + $limit = engr_units_to_bytes(service_class_fetch(\App::$data['channel']['channel_id'],'photo_upload_limit')); + if($limit !== false) { + $usage_message = sprintf( t("%1$.2f MB of %2$.2f MB photo storage used."), $r[0]['total'] / 1024000, $limit / 1024000 ); + } + else { + $usage_message = sprintf( t('%1$.2f MB photo storage used.'), $r[0]['total'] / 1024000 ); + } + + if($_is_owner) { + $channel = \App::get_channel(); + + $acl = new \Zotlabs\Access\AccessList($channel); + $channel_acl = $acl->get(); + + $lockstate = (($acl->is_private()) ? 'lock' : 'unlock'); + } + + $aclselect = (($_is_owner) ? populate_acl($channel_acl,false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_storage')) : ''); + + // this is wrong but is to work around an issue with js_upload wherein it chokes if these variables + // don't exist. They really should be set to a parseable representation of the channel's default permissions + // which can be processed by getSelected() + + if(! $aclselect) { + $aclselect = ''; + } + + $selname = ''; + + if($datum) { + $h = attach_by_hash_nodata($datum,get_observer_hash()); + $selname = $h['data']['display_path']; + } + + + $albums = ((array_key_exists('albums', \App::$data)) ? \App::$data['albums'] : photos_albums_list(\App::$data['channel'],\App::$data['observer'])); + + if(! $selname) { + $def_album = get_pconfig(\App::$data['channel']['channel_id'],'system','photo_path'); + if($def_album) { + $selname = filepath_macro($def_album); + $albums['album'][] = array('text' => $selname); + } + } + + $tpl = get_markup_template('photos_upload.tpl'); + $upload_form = replace_macros($tpl,array( + '$pagename' => t('Upload Photos'), + '$sessid' => session_id(), + '$usage' => $usage_message, + '$nickname' => \App::$data['channel']['channel_address'], + '$newalbum_label' => t('Enter an album name'), + '$newalbum_placeholder' => t('or select an existing album (doubleclick)'), + '$visible' => array('visible', t('Create a status post for this upload'), 0,'', array(t('No'), t('Yes')), 'onclick="showHideBodyTextarea();"'), + '$caption' => array('description', t('Title (optional)')), + '$body' => array('body', t('Description (optional)'),'', 'Description will only appear in the status post'), + '$albums' => $albums['albums'], + '$selname' => $selname, + '$permissions' => t('Permissions'), + '$aclselect' => $aclselect, + '$allow_cid' => acl2json($channel_acl['allow_cid']), + '$allow_gid' => acl2json($channel_acl['allow_gid']), + '$deny_cid' => acl2json($channel_acl['deny_cid']), + '$deny_gid' => acl2json($channel_acl['deny_gid']), + '$lockstate' => $lockstate, + '$uploader' => $ret['addon_text'], + '$default' => (($ret['default_upload']) ? true : false), + '$uploadurl' => $ret['post_url'], + '$submit' => t('Upload') + + )); + + } + + // + // dispatch request + // + + /* + * Display a single photo album + */ + + if($datatype === 'album') { + + head_add_link([ + 'rel' => 'alternate', + 'type' => 'application/json+oembed', + 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string), + 'title' => 'oembed' + ]); + + if($x = photos_album_exists($owner_uid, get_observer_hash(), $datum)) { + \App::set_pager_itemspage(60); + $album = $x['display_path']; + } + else { + goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']); + } + + if($_GET['order'] === 'posted') + $order = 'ASC'; + else + $order = 'DESC'; + + $r = q("SELECT p.resource_id, p.id, p.filename, p.mimetype, p.imgscale, p.description, p.created FROM photo p INNER JOIN + (SELECT resource_id, max(imgscale) imgscale FROM photo left join attach on folder = '%s' and photo.resource_id = attach.hash WHERE attach.uid = %d AND imgscale <= 4 AND photo_usage IN ( %d, %d ) and is_nsfw = %d $sql_extra GROUP BY resource_id) ph + ON (p.resource_id = ph.resource_id AND p.imgscale = ph.imgscale) + ORDER BY created $order LIMIT %d OFFSET %d", + dbesc($x['hash']), + intval($owner_uid), + intval(PHOTO_NORMAL), + intval(PHOTO_PROFILE), + intval($unsafe), + intval(\App::$pager['itemspage']), + intval(\App::$pager['start']) + ); + + // edit album name + $album_edit = null; + + if($can_post) { + $album_e = $album; + $albums = ((array_key_exists('albums', \App::$data)) ? \App::$data['albums'] : photos_albums_list(\App::$data['channel'],\App::$data['observer'])); + + // @fixme - syncronise actions with DAV + + // $edit_tpl = get_markup_template('album_edit.tpl'); + // $album_edit = replace_macros($edit_tpl,array( + // '$nametext' => t('Enter a new album name'), + // '$name_placeholder' => t('or select an existing one (doubleclick)'), + // '$nickname' => \App::$data['channel']['channel_address'], + // '$album' => $album_e, + // '$albums' => $albums['albums'], + // '$hexalbum' => bin2hex($album), + // '$submit' => t('Submit'), + // '$dropsubmit' => t('Delete Album') + // )); + + } + + if($_GET['order'] === 'posted') + $order = array(t('Show Newest First'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $datum); + else + $order = array(t('Show Oldest First'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $datum . '?f=&order=posted'); + + $photos = array(); + if(count($r)) { + $twist = 'rotright'; + foreach($r as $rr) { + + if($twist == 'rotright') + $twist = 'rotleft'; + else + $twist = 'rotright'; + + $ext = $phototypes[$rr['mimetype']]; + + $imgalt_e = $rr['filename']; + $desc_e = $rr['description']; + + $imagelink = (z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $rr['resource_id'] + . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '')); + + $photos[] = array( + 'id' => $rr['id'], + 'twist' => ' ' . $twist . rand(2,4), + 'link' => $imagelink, + 'title' => t('View Photo'), + 'src' => z_root() . '/photo/' . $rr['resource_id'] . '-' . $rr['imgscale'] . '.' .$ext, + 'alt' => $imgalt_e, + 'desc'=> $desc_e, + 'ext' => $ext, + 'hash'=> $rr['resource_id'], + 'unknown' => t('Unknown') + ); + } + } + + if($_REQUEST['aj']) { + if($photos) { + $o = replace_macros(get_markup_template('photosajax.tpl'),array( + '$photos' => $photos, + '$album_id' => $datum + )); + } + else { + $o = '
'; + } + echo $o; + killme(); + } + else { + $o .= ""; + $tpl = get_markup_template('photo_album.tpl'); + $o .= replace_macros($tpl, array( + '$photos' => $photos, + '$album' => $album, + '$album_id' => $datum, + '$album_edit' => array(t('Edit Album'), $album_edit), + '$can_post' => $can_post, + '$upload' => array(t('Add Photos'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/upload/' . $datum), + '$order' => $order, + '$upload_form' => $upload_form, + '$usage' => $usage_message + )); + + } + + if((! $photos) && ($_REQUEST['aj'])) { + $o .= '
'; + echo $o; + killme(); + } + + return $o; + + } + + /** + * Display one photo + */ + + if($datatype === 'image') { + + \App::$page['htmlhead'] .= "\r\n" . '' . "\r\n"; + + $x = q("select folder from attach where hash = '%s' and uid = %d $sql_attach limit 1", + dbesc($datum), + intval($owner_uid) + ); + + // fetch image, item containing image, then comments + + $ph = q("SELECT id,aid,uid,xchan,resource_id,created,edited,title,description,album,filename,mimetype,height,width,filesize,imgscale,photo_usage,is_nsfw,allow_cid,allow_gid,deny_cid,deny_gid FROM photo WHERE uid = %d AND resource_id = '%s' + $sql_extra ORDER BY imgscale ASC ", + intval($owner_uid), + dbesc($datum) + ); + + if(! ($ph && $x)) { + + /* Check again - this time without specifying permissions */ + + $ph = q("SELECT id FROM photo WHERE uid = %d AND resource_id = '%s' LIMIT 1", + intval($owner_uid), + dbesc($datum) + ); + if($ph) + notice( t('Permission denied. Access to this item may be restricted.') . EOL); + else + notice( t('Photo not available') . EOL ); + return; + } + + + + $prevlink = ''; + $nextlink = ''; + + if($_GET['order'] === 'posted') + $order = 'ASC'; + else + $order = 'DESC'; + + + $prvnxt = q("SELECT hash FROM attach WHERE folder = '%s' AND uid = %d AND is_photo = 1 + $sql_attach ORDER BY created $order ", + dbesc($x[0]['folder']), + intval($owner_uid) + ); + + if(count($prvnxt)) { + for($z = 0; $z < count($prvnxt); $z++) { + if($prvnxt[$z]['hash'] == $ph[0]['resource_id']) { + $prv = $z - 1; + $nxt = $z + 1; + if($prv < 0) + $prv = count($prvnxt) - 1; + if($nxt >= count($prvnxt)) + $nxt = 0; + break; + } + } + + $prevlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$prv]['hash'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''); + $nextlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$nxt]['hash'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''); + } + + + if(count($ph) == 1) + $hires = $lores = $ph[0]; + if(count($ph) > 1) { + if($ph[1]['imgscale'] == 2) { + // original is 640 or less, we can display it directly + $hires = $lores = $ph[0]; + } + else { + $hires = $ph[0]; + $lores = $ph[1]; + } + } + + $album_link = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $x[0]['folder']; + $tools = Null; + $lock = Null; + + if($can_post && ($ph[0]['uid'] == $owner_uid)) { + $tools = array( + 'profile'=>array(z_root() . '/profile_photo/use/'.$ph[0]['resource_id'], t('Use as profile photo')), + 'cover'=>array(z_root() . '/cover_photo/use/'.$ph[0]['resource_id'], t('Use as cover photo')), + ); + } + + // lockstate + $lockstate = ( ( (strlen($ph[0]['allow_cid']) || strlen($ph[0]['allow_gid']) + || strlen($ph[0]['deny_cid']) || strlen($ph[0]['deny_gid'])) ) + ? array('lock', t('Private Photo')) + : array('unlock', Null)); + + \App::$page['htmlhead'] .= ''; + + if($prevlink) + $prevlink = array($prevlink, t('Previous')); + + $photo = array( + 'href' => z_root() . '/photo/' . $hires['resource_id'] . '-' . $hires['imgscale'] . '.' . $phototypes[$hires['mimetype']], + 'title'=> t('View Full Size'), + 'src' => z_root() . '/photo/' . $lores['resource_id'] . '-' . $lores['imgscale'] . '.' . $phototypes[$lores['mimetype']] . '?f=&_u=' . datetime_convert('','','','ymdhis') + ); + + if($nextlink) + $nextlink = array($nextlink, t('Next')); + + + // Do we have an item for this photo? + + $linked_items = q("SELECT * FROM item WHERE resource_id = '%s' and resource_type = 'photo' + $sql_item LIMIT 1", + dbesc($datum) + ); + + $map = null; + + if($linked_items) { + + xchan_query($linked_items); + $linked_items = fetch_post_tags($linked_items,true); + + $link_item = $linked_items[0]; + $item_normal = item_normal(); + + $r = q("select * from item where parent_mid = '%s' + $item_normal and uid = %d $sql_item ", + dbesc($link_item['mid']), + intval($link_item['uid']) + + ); + + if($r) { + xchan_query($r); + $r = fetch_post_tags($r,true); + $r = conv_sort($r,'commented'); + } + + $tags = array(); + if($link_item['term']) { + $cnt = 0; + foreach($link_item['term'] as $t) { + $tags[$cnt] = array(0 => format_term_for_display($t)); + if($can_post && ($ph[0]['uid'] == $owner_uid)) { + $tags[$cnt][1] = 'tagrm/drop/' . $link_item['id'] . '/' . bin2hex($t['term']); //?f=&item=' . $link_item['id']; + $tags[$cnt][2] = t('Remove'); + } + $cnt ++; + } + } + + if((local_channel()) && (local_channel() == $link_item['uid'])) { + q("UPDATE item SET item_unseen = 0 WHERE parent = %d and uid = %d and item_unseen = 1", + intval($link_item['parent']), + intval(local_channel()) + ); + } + + if($link_item['coord']) { + $map = generate_map($link_item['coord']); + } + } + + // logger('mod_photo: link_item' . print_r($link_item,true)); + + // FIXME - remove this when we move to conversation module + + $r = $r[0]['children']; + + $edit = null; + if($can_post) { + + $album_e = $ph[0]['album']; + $caption_e = $ph[0]['description']; + $aclselect_e = (($_is_owner) ? populate_acl($ph[0], true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_storage')) : ''); + $albums = ((array_key_exists('albums', \App::$data)) ? \App::$data['albums'] : photos_albums_list(\App::$data['channel'],\App::$data['observer'])); + + $_SESSION['album_return'] = bin2hex($ph[0]['album']); + + $folder_list = attach_folder_select_list($ph[0]['uid']); + + $edit = [ + 'edit' => t('Edit photo'), + 'id' => $link_item['id'], + 'rotatecw' => t('Rotate CW (right)'), + 'rotateccw' => t('Rotate CCW (left)'), + 'albums' => $albums['albums'], + 'album' => $album_e, + 'album_select' => [ 'move_to_album', t('Move photo to album'), $x[0]['folder'], '', $folder_list ], + 'newalbum_label' => t('Enter a new album name'), + 'newalbum_placeholder' => t('or select an existing one (doubleclick)'), + 'nickname' => \App::$data['channel']['channel_address'], + 'resource_id' => $ph[0]['resource_id'], + 'capt_label' => t('Title (optional)'), + 'caption' => $caption_e, + 'tag_label' => t('Add a Tag'), + 'permissions' => t('Permissions'), + 'aclselect' => $aclselect_e, + 'allow_cid' => acl2json($ph[0]['allow_cid']), + 'allow_gid' => acl2json($ph[0]['allow_gid']), + 'deny_cid' => acl2json($ph[0]['deny_cid']), + 'deny_gid' => acl2json($ph[0]['deny_gid']), + 'lockstate' => $lockstate[0], + 'help_tags' => t('Example: @bob, @Barbara_Jensen, @jim@example.com'), + 'item_id' => ((count($linked_items)) ? $link_item['id'] : 0), + 'adult_enabled' => feature_enabled($owner_uid,'adult_photo_flagging'), + 'adult' => array('adult',t('Flag as adult in album view'), intval($ph[0]['is_nsfw']),''), + 'submit' => t('Submit'), + 'delete' => t('Delete Photo') + ]; + } + + if(count($linked_items)) { + + $cmnt_tpl = get_markup_template('comment_item.tpl'); + $tpl = get_markup_template('photo_item.tpl'); + $return_url = \App::$cmd; + + $like_tpl = get_markup_template('like_noshare.tpl'); + + $likebuttons = ''; + + if($observer && ($can_post || $can_comment)) { + $likebuttons = [ + 'id' => $link_item['id'], + 'likethis' => t("I like this \x28toggle\x29"), + 'nolike' => t("I don't like this \x28toggle\x29"), + 'share' => t('Share'), + 'wait' => t('Please wait') + ]; + } + + $comments = ''; + if(! $r) { + if($observer && ($can_post || $can_comment)) { + $feature_auto_save_draft = ((feature_enabled($owner_uid, 'auto_save_draft')) ? "true" : "false"); + $commentbox = replace_macros($cmnt_tpl,array( + '$return_path' => '', + '$mode' => 'photos', + '$jsreload' => $return_url, + '$type' => 'wall-comment', + '$id' => $link_item['id'], + '$parent' => $link_item['id'], + '$profile_uid' => $owner_uid, + '$mylink' => $observer['xchan_url'], + '$mytitle' => t('This is you'), + '$myphoto' => $observer['xchan_photo_s'], + '$comment' => t('Comment'), + '$submit' => t('Submit'), + '$preview' => t('Preview'), + '$ww' => '', + '$feature_encrypt' => false, + '$auto_save_draft' => $feature_auto_save_draft + )); + } + } + + $alike = array(); + $dlike = array(); + + $like = ''; + $dislike = ''; + + $conv_responses = array( + 'like' => array('title' => t('Likes','title')),'dislike' => array('title' => t('Dislikes','title')), + 'agree' => array('title' => t('Agree','title')),'disagree' => array('title' => t('Disagree','title')), 'abstain' => array('title' => t('Abstain','title')), + 'attendyes' => array('title' => t('Attending','title')), 'attendno' => array('title' => t('Not attending','title')), 'attendmaybe' => array('title' => t('Might attend','title')) + ); + + + + + if($r) { + + foreach($r as $item) { + builtin_activity_puller($item, $conv_responses); + } + + $like_count = ((x($alike,$link_item['mid'])) ? $alike[$link_item['mid']] : ''); + $like_list = ((x($alike,$link_item['mid'])) ? $alike[$link_item['mid'] . '-l'] : ''); + + if(is_array($like_list) && (count($like_list) > MAX_LIKERS)) { + $like_list_part = array_slice($like_list, 0, MAX_LIKERS); + array_push($like_list_part, '' . t('View all') . ''); + } else { + $like_list_part = ''; + } + $like_button_label = tt('Like','Likes',$like_count,'noun'); + + //if (feature_enabled($conv->get_profile_owner(),'dislike')) { + $dislike_count = ((x($dlike,$link_item['mid'])) ? $dlike[$link_item['mid']] : ''); + $dislike_list = ((x($dlike,$link_item['mid'])) ? $dlike[$link_item['mid'] . '-l'] : ''); + $dislike_button_label = tt('Dislike','Dislikes',$dislike_count,'noun'); + if (is_array($dislike_list) && (count($dislike_list) > MAX_LIKERS)) { + $dislike_list_part = array_slice($dislike_list, 0, MAX_LIKERS); + array_push($dislike_list_part, '' . t('View all') . ''); + } else { + $dislike_list_part = ''; + } + //} + + + $like = ((isset($alike[$link_item['mid']])) ? format_like($alike[$link_item['mid']],$alike[$link_item['mid'] . '-l'],'like',$link_item['mid']) : ''); + $dislike = ((isset($dlike[$link_item['mid']])) ? format_like($dlike[$link_item['mid']],$dlike[$link_item['mid'] . '-l'],'dislike',$link_item['mid']) : ''); + + // display comments + + foreach($r as $item) { + $comment = ''; + $template = $tpl; + $sparkle = ''; + + if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE))) && ($item['id'] != $item['parent'])) + continue; + + $redirect_url = z_root() . '/redir/' . $item['cid'] ; + + + $profile_url = zid($item['author']['xchan_url']); + $sparkle = ''; + + + $profile_name = $item['author']['xchan_name']; + $profile_avatar = $item['author']['xchan_photo_m']; + + $profile_link = $profile_url; + + $drop = ''; + + if($observer['xchan_hash'] === $item['author_xchan'] || $observer['xchan_hash'] === $item['owner_xchan']) + $drop = replace_macros(get_markup_template('photo_drop.tpl'), array('$id' => $item['id'], '$delete' => t('Delete'))); + + + $name_e = $profile_name; + $title_e = $item['title']; + unobscure($item); + $body_e = prepare_text($item['body'],$item['mimetype']); + + $comments .= replace_macros($template,array( + '$id' => $item['id'], + '$mode' => 'photos', + '$profile_url' => $profile_link, + '$name' => $name_e, + '$thumb' => $profile_avatar, + '$sparkle' => $sparkle, + '$title' => $title_e, + '$body' => $body_e, + '$ago' => relative_date($item['created']), + '$indent' => (($item['parent'] != $item['id']) ? ' comment' : ''), + '$drop' => $drop, + '$comment' => $comment + )); + + } + + if($observer && ($can_post || $can_comment)) { + $commentbox = replace_macros($cmnt_tpl,array( + '$return_path' => '', + '$jsreload' => $return_url, + '$type' => 'wall-comment', + '$id' => $link_item['id'], + '$parent' => $link_item['id'], + '$profile_uid' => $owner_uid, + '$mylink' => $observer['xchan_url'], + '$mytitle' => t('This is you'), + '$myphoto' => $observer['xchan_photo_s'], + '$comment' => t('Comment'), + '$submit' => t('Submit'), + '$ww' => '' + )); + } + + } + $paginate = paginate($a); + } + + $album_e = array($album_link,$ph[0]['album']); + $like_e = $like; + $dislike_e = $dislike; + + + $response_verbs = array('like'); + if(feature_enabled($owner_uid,'dislike')) + $response_verbs[] = 'dislike'; + + $responses = get_responses($conv_responses,$response_verbs,'',$link_item); + + $hookdata = [ + 'onclick' => '$.colorbox({href: \'' . $photo['href'] . '\'}); return false;', + 'raw_photo' => $ph[0], + 'nickname' => \App::$data['channel']['channel_address'] + ]; + call_hooks('photo_view_filter', $hookdata); + + $photo_tpl = get_markup_template('photo_view.tpl'); + $o .= replace_macros($photo_tpl, array( + '$id' => $ph[0]['id'], + '$album' => $album_e, + '$tools_label' => t('Photo Tools'), + '$tools' => $tools, + '$lock' => $lockstate[1], + '$photo' => $photo, + '$prevlink' => $prevlink, + '$nextlink' => $nextlink, + '$desc' => $ph[0]['description'], + '$filename' => $ph[0]['filename'], + '$unknown' => t('Unknown'), + '$tag_hdr' => t('In This Photo:'), + '$tags' => $tags, + 'responses' => $responses, + '$edit' => $edit, + '$map' => $map, + '$map_text' => t('Map'), + '$likebuttons' => $likebuttons, + '$like' => $like_e, + '$dislike' => $dislike_e, + '$like_count' => $like_count, + '$like_list' => $like_list, + '$like_list_part' => $like_list_part, + '$like_button_label' => $like_button_label, + '$like_modal_title' => t('Likes','noun'), + '$dislike_modal_title' => t('Dislikes','noun'), + '$dislike_count' => $dislike_count, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_count : ''), + '$dislike_list' => $dislike_list, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list : ''), + '$dislike_list_part' => $dislike_list_part, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list_part : ''), + '$dislike_button_label' => $dislike_button_label, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_button_label : ''), + '$modal_dismiss' => t('Close'), + '$comments' => $comments, + '$commentbox' => $commentbox, + '$paginate' => $paginate, + '$onclick' => $hookdata['onclick'] + )); + + \App::$data['photo_html'] = $o; + + return $o; + } + + // Default - show recent photos with upload link (if applicable) + //$o = ''; + + \App::$page['htmlhead'] .= "\r\n" . '' . "\r\n"; + + + \App::set_pager_itemspage(60); + + $r = q("SELECT p.resource_id, p.id, p.filename, p.mimetype, p.album, p.imgscale, p.created, p.display_path + FROM photo p + INNER JOIN ( SELECT resource_id, max(imgscale) imgscale FROM photo + WHERE photo.uid = %d AND photo_usage IN ( %d, %d ) + AND is_nsfw = %d $sql_extra group by resource_id ) ph + ON (p.resource_id = ph.resource_id and p.imgscale = ph.imgscale) + ORDER by p.created DESC LIMIT %d OFFSET %d", + intval(\App::$data['channel']['channel_id']), + intval(PHOTO_NORMAL), + intval(PHOTO_PROFILE), + intval($unsafe), + intval(\App::$pager['itemspage']), + intval(\App::$pager['start']) + ); + + + + $photos = array(); + if($r) { + $twist = 'rotright'; + foreach($r as $rr) { + + if(! attach_can_view_folder(\App::$data['channel']['channel_id'],get_observer_hash(),$rr['resource_id'])) + continue; + + if($twist == 'rotright') + $twist = 'rotleft'; + else + $twist = 'rotright'; + $ext = $phototypes[$rr['mimetype']]; + + $alt_e = $rr['filename']; + $name_e = dirname($rr['display_path']); + + $photos[] = array( + 'id' => $rr['id'], + 'twist' => ' ' . $twist . rand(2,4), + 'link' => z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $rr['resource_id'], + 'title' => t('View Photo'), + 'src' => z_root() . '/photo/' . $rr['resource_id'] . '-' . ((($rr['imgscale']) == 6) ? 4 : $rr['imgscale']) . '.' . $ext, + 'alt' => $alt_e, + 'album' => array( + 'name' => $name_e, + ), + + ); + } + } + + if($_REQUEST['aj']) { + if($photos) { + $o = replace_macros(get_markup_template('photosajax.tpl'),array( + '$photos' => $photos, + '$album_id' => bin2hex(t('Recent Photos')) + )); + } + else { + $o = '
'; + } + echo $o; + killme(); + } + else { + $o .= ""; + $tpl = get_markup_template('photos_recent.tpl'); + $o .= replace_macros($tpl, array( + '$title' => t('Recent Photos'), + '$album_id' => bin2hex(t('Recent Photos')), + '$can_post' => $can_post, + '$upload' => array(t('Add Photos'), z_root().'/photos/'.\App::$data['channel']['channel_address'].'/upload'), + '$photos' => $photos, + '$upload_form' => $upload_form, + '$usage' => $usage_message + )); + + } + + if((! $photos) && ($_REQUEST['aj'])) { + $o .= '
'; + echo $o; + killme(); + } + + // paginate($a); + return $o; + } + + } From 05cb4fd8971f9c196d21ab21f08e840e471ab804 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Mon, 17 Dec 2018 09:13:03 +0100 Subject: [PATCH 20/93] Move SSLify code from Photo cache addon --- Zotlabs/Module/Photo.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Zotlabs/Module/Photo.php b/Zotlabs/Module/Photo.php index 967a3b703..e236cc5f4 100644 --- a/Zotlabs/Module/Photo.php +++ b/Zotlabs/Module/Photo.php @@ -159,15 +159,14 @@ class Photo extends \Zotlabs\Web\Controller { // Validate cache $cache = array( 'resid' => $photo, - 'uid' => $r[0]['uid'], - 'status' => false + 'url' => htmlspecialchars_decode($r[0]['display_path']) ); if($cache_mode['on']) call_hooks('cache_url_hook', $cache); - if(! $cache['status']) { - $url = htmlspecialchars_decode($r[0]['display_path']); - call_hooks('cache_sslify_hook', $url); - header("Location: " . $url); + if($cache['url'] != '') { + if(strpos(z_root(),'https:') !== false && strpos($cache['url'],'https:') === false) + $cache['url'] = z_root() . '/sslify/' . $filename . '?f=&url=' . urlencode($cache['url']); + header("Location: " . $cache['url']); killme(); } } From 4d8a815932113c87333a4f3e95a7bf1c56d87e73 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Mon, 17 Dec 2018 09:34:30 +0100 Subject: [PATCH 21/93] Keep remote site headers for caching --- Zotlabs/Module/Sslify.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Zotlabs/Module/Sslify.php b/Zotlabs/Module/Sslify.php index 2891f3691..37be4423b 100644 --- a/Zotlabs/Module/Sslify.php +++ b/Zotlabs/Module/Sslify.php @@ -12,10 +12,16 @@ class Sslify extends \Zotlabs\Web\Controller { list($k,$v) = array_map("trim", explode(":", trim($l), 2)); $hdrs[strtolower($k)] = $v; } - if (array_key_exists('content-type', $hdrs)) { - $type = $hdrs['content-type']; - header('Content-Type: ' . $type); - } + + if (array_key_exists('content-type', $hdrs)) + header('Content-Type: ' . $hdrs['content-type']); + if (array_key_exists('last-modified', $hdrs)) + header('Last-Modified: ' . $hdrs['last-modified']); + if (array_key_exists('cache-control', $hdrs)) + header('Cache-Control: ' . $hdrs['cache-control']); + if (array_key_exists('expires', $hdrs)) + header('Expires: ' . $hdrs['expires']); + echo $x['body']; killme(); From 70a766171117fd94c7e0ca228d3b879f7f307e5f Mon Sep 17 00:00:00 2001 From: phani00 Date: Mon, 17 Dec 2018 10:08:45 +0000 Subject: [PATCH 22/93] remove my dark theme fixes. --- view/theme/redbasic/schema/dark.css | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/view/theme/redbasic/schema/dark.css b/view/theme/redbasic/schema/dark.css index e958d9ee7..c00ddca90 100644 --- a/view/theme/redbasic/schema/dark.css +++ b/view/theme/redbasic/schema/dark.css @@ -322,7 +322,9 @@ a, a:visited, a:link, .fakelink, .fakelink:visited, .fakelink:link { .text-dark { color: #aaa !important; } -a.text-dark:focus, a.text-dark:hover { + +/* phani: fix 1 */ +/*a.text-dark:focus, a.text-dark:hover { color: #ddd !important; } @@ -335,7 +337,8 @@ a.text-dark:focus, a.text-dark:hover { .badge-warning a.text-dark:focus, .badge-warning a.text-dark:hover { color: red !important; text-decoration: none; -} +}*/ + .group-selected, .fileas-selected, .categories-selected, .search-selected, a.active { color: #fff !important; @@ -492,10 +495,10 @@ pre { background-color: #222; } +/* phani: fix 2 */ /* change color of [hl] tag: */ -div.wall-item-body span /*strong:only-of-type */{ +/*div.wall-item-body span { color: #1212b6; padding: 2px 3px; -/* font-weight: 500; */ white-space: nowrap; -} +}*/ From a2959c6e9e795c0c8c6e87b70d8d0a935ae272f9 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Mon, 17 Dec 2018 13:28:18 +0100 Subject: [PATCH 23/93] Remove scale_external_images() --- include/markdown.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/markdown.php b/include/markdown.php index 64f0a0854..2513a7d77 100644 --- a/include/markdown.php +++ b/include/markdown.php @@ -91,8 +91,6 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) { // remove duplicate adjacent code tags $s = preg_replace("/(\[code\])+(.*?)(\[\/code\])+/ism","[code]$2[/code]", $s); - // Don't show link to full picture (until it is fixed) - $s = scale_external_images($s, false); /** * @hooks markdown_to_bb From 1541f67eab5f541d1f61001fc4e42132a9ac09f8 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Mon, 17 Dec 2018 13:28:58 +0100 Subject: [PATCH 24/93] Remove scale_external_images() --- include/network.php | 93 --------------------------------------------- 1 file changed, 93 deletions(-) diff --git a/include/network.php b/include/network.php index cd352e7db..e07001fa3 100644 --- a/include/network.php +++ b/include/network.php @@ -694,99 +694,6 @@ function sxml2array ( $xmlObject, $out = array () ) } -/** - * @brief Scales an external image. - * - * @param string $s - * @param string $include_link default true - * @param string $scale_replace default false - * @return string - */ -function scale_external_images($s, $include_link = true, $scale_replace = false) { - - // Picture addresses can contain special characters - $s = htmlspecialchars_decode($s, ENT_COMPAT); - - $matches = null; - $c = preg_match_all('/\[([zi])mg(.*?)\](.*?)\[\/[zi]mg\]/ism', $s, $matches, PREG_SET_ORDER); - if($c) { - require_once('include/photo/photo_driver.php'); - - foreach($matches as $mtch) { - logger('data: ' . $mtch[2] . ' ' . $mtch[3]); - - if(substr($mtch[2],0,1) == '=') { - $owidth = intval(substr($mtch[2],1)); - if($owidth > 0 && $owidth < 1024) - continue; - } - - $hostname = str_replace('www.','',substr(z_root(),strpos(z_root(),'://')+3)); - if(stristr($mtch[3],$hostname)) - continue; - - // $scale_replace, if passed, is an array of two elements. The - // first is the name of the full-size image. The second is the - // name of a remote, scaled-down version of the full size image. - // This allows Friendica to display the smaller remote image if - // one exists, while still linking to the full-size image - if($scale_replace) - $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); - - $cache = get_config('system', 'itemcache'); - if (($cache != '') and is_dir($cache)) { - $cachefile = $cache . '/' . hash('md5', $scaled); - file_put_contents($cachefile, $i['body']); - } - - // guess mimetype from headers or filename - - $type = guess_image_type($mtch[3], $i['header']); - if(strpos($type, 'image') === false) - continue; - - if($i['success']) { - $ph = photo_factory($i['body'], $type); - - if(! is_object($ph)) - continue; - - if($ph->is_valid()) { - $orig_width = $ph->getWidth(); - $orig_height = $ph->getHeight(); - - 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) - ? '[' . $linktag . '=' . $mtch[3] . ']' . t('view full size') . '[/' . $linktag . ']' . "\n" - : ''),$s); - logger('new string: ' . $s, LOGGER_DEBUG); - } - } - } - } - } - - // replace the special char encoding - - $s = htmlspecialchars($s, ENT_COMPAT, 'UTF-8'); - - return $s; -} - /** * @brief xml2array() will convert the given XML text to an array in the XML structure. * From 3a662555768840d18c6dbba027af644eda54f20e Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Mon, 17 Dec 2018 13:29:37 +0100 Subject: [PATCH 25/93] Remove scale_external_images() --- include/text.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/text.php b/include/text.php index bd0d8048d..3cc21e4ce 100644 --- a/include/text.php +++ b/include/text.php @@ -3305,8 +3305,6 @@ function cleanup_bbcode($body) { $body = preg_replace('/\[\/code\]\s*\[code\]/ism',"\n",$body); - $body = scale_external_images($body, false); - return $body; } From aace8a14cee2f173b7a11bb2bfcbcebbe0084863 Mon Sep 17 00:00:00 2001 From: phani00 Date: Mon, 17 Dec 2018 15:28:15 +0000 Subject: [PATCH 26/93] new fix for dark theme change implementation of hl-tags in include/bbcode.php insert class='default-highlight' instead of background-color: 'yellow' into span add span.default-highlight definition to view/theme/redbasic/css/style.css this works for all schemas incl. dark. --- include/bbcode.php | 3 ++- view/theme/redbasic/css/style.css | 10 ++++++++ view/theme/redbasic/schema/dark.css | 40 ++++++++++++----------------- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/include/bbcode.php b/include/bbcode.php index c5d6ef998..a0d41ccf0 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -1021,7 +1021,8 @@ function bbcode($Text, $options = []) { } // Check for colored text if (strpos($Text,'[/hl]') !== false) { - $Text = preg_replace("(\[hl\](.*?)\[\/hl\])ism", "$1", $Text); + $Text = preg_replace("(\[hl\](.*?)\[\/hl\])ism", "$1", $Text); +// $Text = preg_replace("(\[hl\](.*?)\[\/hl\])ism", "$1", $Text); $Text = preg_replace("(\[hl=(.*?)\](.*?)\[\/hl\])ism", "$2", $Text); } diff --git a/view/theme/redbasic/css/style.css b/view/theme/redbasic/css/style.css index f2c1b7a48..ba0cc7cd2 100644 --- a/view/theme/redbasic/css/style.css +++ b/view/theme/redbasic/css/style.css @@ -1803,3 +1803,13 @@ dl.bb-dl > dd > li { .hover-fx-show:hover .hover-fx-hide { opacity: 1; } + +/* default highlighted text if not specified by schema: */ +span.default-highlight { + background-color: yellow; + color: #111; + margin: 0 2px; + padding: 2px 4px 2px 5px; + border-radius: 4px; + white-space: nowrap; +} diff --git a/view/theme/redbasic/schema/dark.css b/view/theme/redbasic/schema/dark.css index c00ddca90..a0b9b12d3 100644 --- a/view/theme/redbasic/schema/dark.css +++ b/view/theme/redbasic/schema/dark.css @@ -323,23 +323,6 @@ a, a:visited, a:link, .fakelink, .fakelink:visited, .fakelink:link { color: #aaa !important; } -/* phani: fix 1 */ -/*a.text-dark:focus, a.text-dark:hover { - color: #ddd !important; -} - -.badge-warning { - background-color: #ffc927; -} -.badge-warning a.text-dark { - color: #333 !important; -} -.badge-warning a.text-dark:focus, .badge-warning a.text-dark:hover { - color: red !important; - text-decoration: none; -}*/ - - .group-selected, .fileas-selected, .categories-selected, .search-selected, a.active { color: #fff !important; text-decoration: underline !important; @@ -495,10 +478,19 @@ pre { background-color: #222; } -/* phani: fix 2 */ -/* change color of [hl] tag: */ -/*div.wall-item-body span { - color: #1212b6; - padding: 2px 3px; - white-space: nowrap; -}*/ + +/* category badge fix: */ +a.text-dark:focus, a.text-dark:hover { + color: #ddd !important; +} + +.badge-warning { +/* background-color: #ffc927; */ +} +.badge-warning a.text-dark { + color: #333 !important; +} +.badge-warning a.text-dark:focus, .badge-warning a.text-dark:hover { + color: red !important; + text-decoration: none; +} From a33ed05bec38d35131d72e9b3d6d61b5d6a2daaf Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 17 Dec 2018 11:32:59 -0800 Subject: [PATCH 27/93] fix default values for affinity tool and other information which could be lost when approving a connection without the entire form provided by connedit. --- Zotlabs/Lib/Libzot.php | 4 +--- Zotlabs/Module/Connedit.php | 27 +++++++++++++++++++-------- Zotlabs/Update/_1230.php | 12 ++++++++++++ boot.php | 2 +- include/follow.php | 4 +--- 5 files changed, 34 insertions(+), 15 deletions(-) create mode 100644 Zotlabs/Update/_1230.php diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index 0fbde9765..87a5126f4 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -397,9 +397,7 @@ logger('4'); } } - $closeness = get_pconfig($channel['channel_id'],'system','new_abook_closeness'); - if($closeness === false) - $closeness = 80; + $closeness = get_pconfig($channel['channel_id'],'system','new_abook_closeness',80); $y = abook_store_lowlevel( [ diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php index a9f643306..c14bcd0dd 100644 --- a/Zotlabs/Module/Connedit.php +++ b/Zotlabs/Module/Connedit.php @@ -101,7 +101,8 @@ class Connedit extends \Zotlabs\Web\Controller { } - $profile_id = $_POST['profile_assign']; + $profile_id = ((array_key_exists('profile_assign',$_POST)) ? $_POST['profile_assign'] : $orig_record[0]['abook_profile']); + if($profile_id) { $r = q("SELECT profile_guid FROM profile WHERE profile_guid = '%s' AND uid = %d LIMIT 1", dbesc($profile_id), @@ -113,18 +114,23 @@ class Connedit extends \Zotlabs\Web\Controller { } } - $abook_incl = escape_tags($_POST['abook_incl']); - $abook_excl = escape_tags($_POST['abook_excl']); - + $abook_incl = ((array_key_exists('abook_incl',$_POST)) ? escape_tags($_POST['abook_incl']) : $orig_record[0]['abook_incl']); + $abook_excl = ((array_key_exists('abook_excl',$_POST)) ? escape_tags($_POST['abook_excl']) : $orig_record[0]['abook_excl']); + + $hidden = intval($_POST['hidden']); $priority = intval($_POST['poll']); if($priority > 5 || $priority < 0) $priority = 0; + if(! array_key_exists('closeness',$_POST)) { + $_POST['closeness'] = 80; + } $closeness = intval($_POST['closeness']); - if($closeness < 0) - $closeness = 99; + if($closeness < 0 || $closeness > 99) { + $closeness = 80; + } $rating = intval($_POST['rating']); if($rating < (-10)) @@ -231,6 +237,8 @@ class Connedit extends \Zotlabs\Web\Controller { } $abook_pending = (($new_friend) ? 0 : $orig_record[0]['abook_pending']); + + $r = q("UPDATE abook SET abook_profile = '%s', abook_closeness = %d, abook_pending = %d, abook_incl = '%s', abook_excl = '%s' @@ -733,9 +741,12 @@ class Connedit extends \Zotlabs\Web\Controller { } $slider_tpl = get_markup_template('contact_slider.tpl'); + + $slideval = intval($contact['abook_closeness']); + $slide = replace_macros($slider_tpl,array( '$min' => 1, - '$val' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 99), + '$val' => $slideval, '$labels' => $label_str, )); } @@ -892,7 +903,7 @@ class Connedit extends \Zotlabs\Web\Controller { '$inherited' => t('inherited'), '$submit' => t('Submit'), '$lbl_vis2' => sprintf( t('Please choose the profile you would like to display to %s when viewing your profile securely.'), $contact['xchan_name']), - '$close' => $contact['abook_closeness'], + '$close' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 80), '$them' => t('Their Settings'), '$me' => t('My Settings'), '$perms' => $perms, diff --git a/Zotlabs/Update/_1230.php b/Zotlabs/Update/_1230.php new file mode 100644 index 000000000..fe59f2e08 --- /dev/null +++ b/Zotlabs/Update/_1230.php @@ -0,0 +1,12 @@ + Date: Mon, 17 Dec 2018 18:14:32 -0800 Subject: [PATCH 28/93] regression: mail from dev to core not delivering --- Zotlabs/Daemon/Notifier.php | 7 ++++++- include/zot.php | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php index 8b81c49da..beb30ed96 100644 --- a/Zotlabs/Daemon/Notifier.php +++ b/Zotlabs/Daemon/Notifier.php @@ -625,7 +625,12 @@ class Notifier { continue; } - $hash = new_uuid(); + // Do not change this to a uuid as long as we have traditional zot servers + // in the loop. The signature verification step can't handle dashes in the + // hashes. + + $hash = random_string(48); + $packet = null; $pmsg = ''; diff --git a/include/zot.php b/include/zot.php index d031b4a96..9934dae07 100644 --- a/include/zot.php +++ b/include/zot.php @@ -1232,6 +1232,7 @@ function zot_fetch($arr) { $datatosend = json_encode(crypto_encapsulate(json_encode($data),$hub['hubloc_sitekey'], $algorithm)); $import = zot_zot($url,$datatosend); + } else { $algorithm = zot_best_algorithm($hub['site_crypto']); @@ -4913,6 +4914,7 @@ function zot_reply_pickup($data) { dbesc($data['secret']), dbesc($data['callback']) ); + if(! $r) { $ret['message'] = 'nothing to pick up'; logger('mod_zot: pickup: ' . $ret['message']); From bc6d384ca91bf754c10ead1d787bf1452c20e9d4 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Tue, 18 Dec 2018 10:43:06 +0100 Subject: [PATCH 29/93] make mod channel deal with b64 encoded mid\s ; --- Zotlabs/Module/Channel.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index 12d87885f..5fdefd805 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -124,6 +124,11 @@ class Channel extends Controller { $mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : ''); + if(strpos($mid,'b64.') === 0) + $decoded = @base64url_decode(substr($mid,4)); + if($decoded) + $mid = $decoded; + $datequery = ((x($_GET,'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : ''); $datequery2 = ((x($_GET,'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : ''); @@ -375,6 +380,9 @@ class Channel extends Controller { if((! $update) && (! $load)) { + if($decoded) + $mid = 'b64.' . base64url_encode($mid); + // This is ugly, but we can't pass the profile_uid through the session to the ajax updater, // because browser prefetching might change it on us. We have to deliver it with the page. From aaab905e726c126a36453f4ae08c39c3045bf412 Mon Sep 17 00:00:00 2001 From: phani00 Date: Tue, 18 Dec 2018 12:37:51 +0100 Subject: [PATCH 30/93] remove some fancy formatting. --- include/bbcode.php | 1 - view/theme/redbasic/css/style.css | 4 ---- 2 files changed, 5 deletions(-) diff --git a/include/bbcode.php b/include/bbcode.php index a0d41ccf0..817986da0 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -1022,7 +1022,6 @@ function bbcode($Text, $options = []) { // Check for colored text if (strpos($Text,'[/hl]') !== false) { $Text = preg_replace("(\[hl\](.*?)\[\/hl\])ism", "$1", $Text); -// $Text = preg_replace("(\[hl\](.*?)\[\/hl\])ism", "$1", $Text); $Text = preg_replace("(\[hl=(.*?)\](.*?)\[\/hl\])ism", "$2", $Text); } diff --git a/view/theme/redbasic/css/style.css b/view/theme/redbasic/css/style.css index ba0cc7cd2..c7948cad1 100644 --- a/view/theme/redbasic/css/style.css +++ b/view/theme/redbasic/css/style.css @@ -1808,8 +1808,4 @@ dl.bb-dl > dd > li { span.default-highlight { background-color: yellow; color: #111; - margin: 0 2px; - padding: 2px 4px 2px 5px; - border-radius: 4px; - white-space: nowrap; } From b97143e9db5c002145e2811cad4a1e12a9eaa259 Mon Sep 17 00:00:00 2001 From: phani00 Date: Tue, 18 Dec 2018 14:02:50 +0100 Subject: [PATCH 31/93] change hl text color to the default text color in non-dark schema. looks good, except in dark, where i can change it in dark.css. --- view/theme/redbasic/css/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/theme/redbasic/css/style.css b/view/theme/redbasic/css/style.css index c7948cad1..303987c53 100644 --- a/view/theme/redbasic/css/style.css +++ b/view/theme/redbasic/css/style.css @@ -1807,5 +1807,5 @@ dl.bb-dl > dd > li { /* default highlighted text if not specified by schema: */ span.default-highlight { background-color: yellow; - color: #111; + color: #4d4d4d; } From 2354bb5427d5d6b384c2e5b0f8fb9e676249e77b Mon Sep 17 00:00:00 2001 From: phani00 Date: Tue, 18 Dec 2018 17:54:39 +0100 Subject: [PATCH 32/93] remove color from style.css (default) but add a little padding; add color & border radius to dark.css. --- view/theme/redbasic/css/style.css | 2 +- view/theme/redbasic/schema/dark.css | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/view/theme/redbasic/css/style.css b/view/theme/redbasic/css/style.css index 303987c53..b406e710c 100644 --- a/view/theme/redbasic/css/style.css +++ b/view/theme/redbasic/css/style.css @@ -1807,5 +1807,5 @@ dl.bb-dl > dd > li { /* default highlighted text if not specified by schema: */ span.default-highlight { background-color: yellow; - color: #4d4d4d; + padding: 2px 4px; } diff --git a/view/theme/redbasic/schema/dark.css b/view/theme/redbasic/schema/dark.css index a0b9b12d3..bf55fec72 100644 --- a/view/theme/redbasic/schema/dark.css +++ b/view/theme/redbasic/schema/dark.css @@ -494,3 +494,9 @@ a.text-dark:focus, a.text-dark:hover { color: red !important; text-decoration: none; } + +/* fix color for highlithed text */ +span.default-highlight { + color: #333; + border-radius: 4px; +} From 339c9cceeca1e9b54aa320aea48d164d1cc22e36 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 19 Dec 2018 10:05:18 +0100 Subject: [PATCH 33/93] check if we deal with an array before sizeof() --- Zotlabs/Module/Linkinfo.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Zotlabs/Module/Linkinfo.php b/Zotlabs/Module/Linkinfo.php index 7c7dc0e88..8b7defa39 100644 --- a/Zotlabs/Module/Linkinfo.php +++ b/Zotlabs/Module/Linkinfo.php @@ -138,8 +138,8 @@ class Linkinfo extends \Zotlabs\Web\Controller { } $image = ""; - - if(sizeof($siteinfo["images"]) > 0){ + + if(is_array($siteinfo["images"]) && (sizeof($siteinfo["images"]) > 0)){ /* Execute below code only if image is present in siteinfo */ $total_images = 0; @@ -161,7 +161,7 @@ class Linkinfo extends \Zotlabs\Web\Controller { $total_images ++; if($max_images && $max_images >= $total_images) break; - } + } } if(strlen($text)) { From 0e5d76e7359d3f38b971138069a239ae4ef171eb Mon Sep 17 00:00:00 2001 From: "M. Dent" Date: Wed, 19 Dec 2018 10:12:59 +0100 Subject: [PATCH 34/93] Add reload to util/addons --- util/addons | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/util/addons b/util/addons index 3d772bf73..7bd70984e 100755 --- a/util/addons +++ b/util/addons @@ -10,6 +10,7 @@ echo <<< EOT util/addons list all # list all addons (*)= installed, (!)= disabled due to version compatibility util/addons install foo # install addon named 'foo' util/addons uninstall foo # uninstall addon named 'foo' + util/addons reinstall # reinstall all plugins EOT; } @@ -68,6 +69,20 @@ if($argc == 2 && $argv[1] === 'list') { killme(); } +if($argc == 2 && $argv[1] === 'reinstall') { + require_once("include/plugin.php"); + if($plugins) { + foreach($plugins as $p) { + if($p[1]) { + echo "Reinstall: ". $p[0] . "\n"; + uninstall_plugin($p[0]); + install_plugin($p[0]); + } + } + } + killme(); +} + if($argc == 3 && $argv[1] === 'list' && $argv[2] === 'all') { if($plugins) { From 774dd6d5e333ac1988f1f3d830627cd7af68908e Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 19 Dec 2018 11:08:28 +0100 Subject: [PATCH 35/93] use count() instead of sizeof() --- Zotlabs/Module/Linkinfo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Module/Linkinfo.php b/Zotlabs/Module/Linkinfo.php index 8b7defa39..32b4c0281 100644 --- a/Zotlabs/Module/Linkinfo.php +++ b/Zotlabs/Module/Linkinfo.php @@ -139,7 +139,7 @@ class Linkinfo extends \Zotlabs\Web\Controller { $image = ""; - if(is_array($siteinfo["images"]) && (sizeof($siteinfo["images"]) > 0)){ + if(is_array($siteinfo["images"]) && count($siteinfo["images"])){ /* Execute below code only if image is present in siteinfo */ $total_images = 0; From 7a55dd512a49a8a3c3e7ad1cfec2e42f9825afd1 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 19 Dec 2018 20:03:31 -0800 Subject: [PATCH 36/93] reverse activity mapping improvements --- Zotlabs/Lib/Activity.php | 89 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 2 deletions(-) diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php index 8cef41c42..ef6ee6c3e 100644 --- a/Zotlabs/Lib/Activity.php +++ b/Zotlabs/Lib/Activity.php @@ -546,6 +546,12 @@ class Activity { } + + + + + + static function activity_mapper($verb) { if(strpos($verb,'/') === false) { @@ -588,6 +594,67 @@ class Activity { } + + static function activity_decode_mapper($verb) { + + $acts = [ + 'http://activitystrea.ms/schema/1.0/post' => 'Create', + 'http://activitystrea.ms/schema/1.0/share' => 'Announce', + 'http://activitystrea.ms/schema/1.0/update' => 'Update', + 'http://activitystrea.ms/schema/1.0/like' => 'Like', + 'http://activitystrea.ms/schema/1.0/favorite' => 'Like', + 'http://purl.org/zot/activity/dislike' => 'Dislike', + 'http://activitystrea.ms/schema/1.0/tag' => 'Add', + 'http://activitystrea.ms/schema/1.0/follow' => 'Follow', + 'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow', + ]; + + + foreach($acts as $k => $v) { + if($verb === $v) { + return $k; + } + } + + logger('Unmapped activity: ' . $verb); + return 'Create'; + + } + + static function activity_obj_decode_mapper($obj) { + + $objs = [ + 'http://activitystrea.ms/schema/1.0/note' => 'Note', + 'http://activitystrea.ms/schema/1.0/note' => 'Article', + 'http://activitystrea.ms/schema/1.0/comment' => 'Note', + 'http://activitystrea.ms/schema/1.0/person' => 'Person', + 'http://purl.org/zot/activity/profile' => 'Profile', + 'http://activitystrea.ms/schema/1.0/photo' => 'Image', + 'http://activitystrea.ms/schema/1.0/profile-photo' => 'Icon', + 'http://activitystrea.ms/schema/1.0/event' => 'Event', + 'http://activitystrea.ms/schema/1.0/wiki' => 'Document', + 'http://purl.org/zot/activity/location' => 'Place', + 'http://purl.org/zot/activity/chessgame' => 'Game', + 'http://purl.org/zot/activity/tagterm' => 'zot:Tag', + 'http://purl.org/zot/activity/thing' => 'Object', + 'http://purl.org/zot/activity/file' => 'zot:File', + 'http://purl.org/zot/activity/mood' => 'zot:Mood', + + ]; + + foreach($objs as $k => $v) { + if($obj === $v) { + return $k; + } + } + + logger('Unmapped activity object: ' . $obj); + return 'Note'; + } + + + + static function activity_obj_mapper($obj) { if(strpos($obj,'/') === false) { @@ -1236,6 +1303,20 @@ class Activity { } + static function get_actor_bbmention($id) { + + $x = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where hubloc_hash = '%s' or hubloc_id_url = '%s' limit 1", + dbesc($id), + dbesc($id) + ); + + if($x) { + return sprintf('@[zrl=%s]%s[/zrl]',$x[0]['xchan_url'],$x[0]['xchan_name']); + } + return '@{' . $id . '}'; + + } + static function decode_note($act) { @@ -1320,13 +1401,17 @@ class Activity { $s['summary'] = self::bb_content($content,'summary'); $s['body'] = ((self::bb_content($content,'bbcode') && (! $response_activity)) ? self::bb_content($content,'bbcode') : self::bb_content($content,'content')); - $s['verb'] = self::activity_mapper($act->type); + $s['verb'] = self::activity_decode_mapper($act->type); if($act->type === 'Tombstone') { $s['item_deleted'] = 1; } - $s['obj_type'] = self::activity_obj_mapper($act->obj['type']); + $s['obj_type'] = self::activity_obj_decode_mapper($act->obj['type']); + if($s['obj_type'] === ACTIVITY_OBJ_NOTE && $s['mid'] !== $s['parent_mid']) { + $s['obj_type'] = ACTIVITY_OBJ_COMMENT; + } + $s['obj'] = $act->obj; $instrument = $act->get_property_obj('instrument'); From ec769bc9f948956a8093c675a14970461c5d8304 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 20 Dec 2018 19:45:11 +0100 Subject: [PATCH 37/93] missing observer check --- Zotlabs/Module/Like.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Zotlabs/Module/Like.php b/Zotlabs/Module/Like.php index d19154eb4..0455c5265 100644 --- a/Zotlabs/Module/Like.php +++ b/Zotlabs/Module/Like.php @@ -251,6 +251,9 @@ class Like extends \Zotlabs\Web\Controller { } } else { + + if(! $observer) + killme(); // this is used to like an item or comment From 389b4beba47823ebc0549ee8d7c0549c27b73b7a Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 20 Dec 2018 11:06:52 -0800 Subject: [PATCH 38/93] like permission issue --- Zotlabs/Module/Like.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Module/Like.php b/Zotlabs/Module/Like.php index d19154eb4..142d3b499 100644 --- a/Zotlabs/Module/Like.php +++ b/Zotlabs/Module/Like.php @@ -52,7 +52,7 @@ class Like extends \Zotlabs\Web\Controller { $observer = \App::get_observer(); $interactive = $_REQUEST['interactive']; - if($interactive) { + if((! $observer) || ($interactive)) { $o .= '

' . t('Like/Dislike') . '

'; $o .= EOL . EOL; From 090fe394e4733aea9e9ca2e9a93c2c27b266d065 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Thu, 20 Dec 2018 20:38:35 +0100 Subject: [PATCH 39/93] Fix cURL with HTTP/2 --- include/network.php | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/include/network.php b/include/network.php index 65770221f..8ac71011e 100644 --- a/include/network.php +++ b/include/network.php @@ -120,13 +120,8 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { @curl_setopt($ch, CURLOPT_USERPWD, $opts['http_auth']); } - if(array_key_exists('http_version',$opts)) { + if(array_key_exists('http_version',$opts)) @curl_setopt($ch,CURLOPT_HTTP_VERSION,$opts['http_version']); - } - else { - @curl_setopt($ch,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_1); - } - if(x($opts,'cookiejar')) @curl_setopt($ch, CURLOPT_COOKIEJAR, $opts['cookiejar']); @@ -165,7 +160,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { // Pull out multiple headers, e.g. proxy and continuation headers // allow for HTTP/2.x without fixing code - while(preg_match('/^HTTP\/[1-3].+? [1-5][0-9][0-9]/',$base)) { + while(preg_match('/^HTTP\/[1-3](\.\d)? [1-5][0-9][0-9]/',$base)) { $chunk = substr($base,0,strpos($base,"\r\n\r\n")+4); $header .= $chunk; $base = substr($base,strlen($chunk)); @@ -298,12 +293,8 @@ function z_post_url($url, $params, $redirects = 0, $opts = array()) { @curl_setopt($ch, CURLOPT_USERPWD, $opts['http_auth']); } - if(array_key_exists('http_version',$opts)) { + if(array_key_exists('http_version',$opts)) @curl_setopt($ch,CURLOPT_HTTP_VERSION,$opts['http_version']); - } - else { - @curl_setopt($ch,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_1); - } if(x($opts,'cookiejar')) @curl_setopt($ch, CURLOPT_COOKIEJAR, $opts['cookiejar']); @@ -338,7 +329,7 @@ function z_post_url($url, $params, $redirects = 0, $opts = array()) { // Pull out multiple headers, e.g. proxy and continuation headers // allow for HTTP/2.x without fixing code - while(preg_match('/^HTTP\/[1-3].+? [1-5][0-9][0-9]/',$base)) { + while(preg_match('/^HTTP\/[1-3](\.\d)? [1-5][0-9][0-9]/',$base)) { $chunk = substr($base,0,strpos($base,"\r\n\r\n")+4); $header .= $chunk; $base = substr($base,strlen($chunk)); From e4958d5bb94af7880c7560e380f64de4d7f12b22 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Thu, 20 Dec 2018 20:58:48 +0100 Subject: [PATCH 40/93] Revert "Fix cURL with HTTP/2" This reverts commit 090fe394e4733aea9e9ca2e9a93c2c27b266d065 --- include/network.php | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/include/network.php b/include/network.php index 8ac71011e..65770221f 100644 --- a/include/network.php +++ b/include/network.php @@ -120,8 +120,13 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { @curl_setopt($ch, CURLOPT_USERPWD, $opts['http_auth']); } - if(array_key_exists('http_version',$opts)) + if(array_key_exists('http_version',$opts)) { @curl_setopt($ch,CURLOPT_HTTP_VERSION,$opts['http_version']); + } + else { + @curl_setopt($ch,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_1); + } + if(x($opts,'cookiejar')) @curl_setopt($ch, CURLOPT_COOKIEJAR, $opts['cookiejar']); @@ -160,7 +165,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { // Pull out multiple headers, e.g. proxy and continuation headers // allow for HTTP/2.x without fixing code - while(preg_match('/^HTTP\/[1-3](\.\d)? [1-5][0-9][0-9]/',$base)) { + while(preg_match('/^HTTP\/[1-3].+? [1-5][0-9][0-9]/',$base)) { $chunk = substr($base,0,strpos($base,"\r\n\r\n")+4); $header .= $chunk; $base = substr($base,strlen($chunk)); @@ -293,8 +298,12 @@ function z_post_url($url, $params, $redirects = 0, $opts = array()) { @curl_setopt($ch, CURLOPT_USERPWD, $opts['http_auth']); } - if(array_key_exists('http_version',$opts)) + if(array_key_exists('http_version',$opts)) { @curl_setopt($ch,CURLOPT_HTTP_VERSION,$opts['http_version']); + } + else { + @curl_setopt($ch,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_1); + } if(x($opts,'cookiejar')) @curl_setopt($ch, CURLOPT_COOKIEJAR, $opts['cookiejar']); @@ -329,7 +338,7 @@ function z_post_url($url, $params, $redirects = 0, $opts = array()) { // Pull out multiple headers, e.g. proxy and continuation headers // allow for HTTP/2.x without fixing code - while(preg_match('/^HTTP\/[1-3](\.\d)? [1-5][0-9][0-9]/',$base)) { + while(preg_match('/^HTTP\/[1-3].+? [1-5][0-9][0-9]/',$base)) { $chunk = substr($base,0,strpos($base,"\r\n\r\n")+4); $header .= $chunk; $base = substr($base,strlen($chunk)); From 60f890ce0dd95cf3c4f7cb72b61bcd71ec0c170a Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Thu, 20 Dec 2018 21:13:05 +0100 Subject: [PATCH 41/93] Fix for cURL with default HTTP/2 --- include/network.php | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/include/network.php b/include/network.php index 65770221f..8ac71011e 100644 --- a/include/network.php +++ b/include/network.php @@ -120,13 +120,8 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { @curl_setopt($ch, CURLOPT_USERPWD, $opts['http_auth']); } - if(array_key_exists('http_version',$opts)) { + if(array_key_exists('http_version',$opts)) @curl_setopt($ch,CURLOPT_HTTP_VERSION,$opts['http_version']); - } - else { - @curl_setopt($ch,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_1); - } - if(x($opts,'cookiejar')) @curl_setopt($ch, CURLOPT_COOKIEJAR, $opts['cookiejar']); @@ -165,7 +160,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { // Pull out multiple headers, e.g. proxy and continuation headers // allow for HTTP/2.x without fixing code - while(preg_match('/^HTTP\/[1-3].+? [1-5][0-9][0-9]/',$base)) { + while(preg_match('/^HTTP\/[1-3](\.\d)? [1-5][0-9][0-9]/',$base)) { $chunk = substr($base,0,strpos($base,"\r\n\r\n")+4); $header .= $chunk; $base = substr($base,strlen($chunk)); @@ -298,12 +293,8 @@ function z_post_url($url, $params, $redirects = 0, $opts = array()) { @curl_setopt($ch, CURLOPT_USERPWD, $opts['http_auth']); } - if(array_key_exists('http_version',$opts)) { + if(array_key_exists('http_version',$opts)) @curl_setopt($ch,CURLOPT_HTTP_VERSION,$opts['http_version']); - } - else { - @curl_setopt($ch,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_1); - } if(x($opts,'cookiejar')) @curl_setopt($ch, CURLOPT_COOKIEJAR, $opts['cookiejar']); @@ -338,7 +329,7 @@ function z_post_url($url, $params, $redirects = 0, $opts = array()) { // Pull out multiple headers, e.g. proxy and continuation headers // allow for HTTP/2.x without fixing code - while(preg_match('/^HTTP\/[1-3].+? [1-5][0-9][0-9]/',$base)) { + while(preg_match('/^HTTP\/[1-3](\.\d)? [1-5][0-9][0-9]/',$base)) { $chunk = substr($base,0,strpos($base,"\r\n\r\n")+4); $header .= $chunk; $base = substr($base,strlen($chunk)); From e34853e19ea10bde7a4dc2e585da3c26d7032bdb Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 21 Dec 2018 12:51:19 +0100 Subject: [PATCH 42/93] do not add timestamp to the photo src. caching is handled in mod photo now. --- Zotlabs/Module/Photos.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php index b87c586da..3833d5088 100644 --- a/Zotlabs/Module/Photos.php +++ b/Zotlabs/Module/Photos.php @@ -988,7 +988,7 @@ class Photos extends \Zotlabs\Web\Controller { $photo = array( 'href' => z_root() . '/photo/' . $hires['resource_id'] . '-' . $hires['imgscale'] . '.' . $phototypes[$hires['mimetype']], 'title'=> t('View Full Size'), - 'src' => z_root() . '/photo/' . $lores['resource_id'] . '-' . $lores['imgscale'] . '.' . $phototypes[$lores['mimetype']] . '?f=&_u=' . datetime_convert('','','','ymdhis') + 'src' => z_root() . '/photo/' . $lores['resource_id'] . '-' . $lores['imgscale'] . '.' . $phototypes[$lores['mimetype']] ); if($nextlink) From fac3579fb0124a13c5066c660e8a2bd89ed1e144 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 22 Dec 2018 19:47:46 +0100 Subject: [PATCH 43/93] revert padding for text highlight. It is messing with indent punctuation and decreases legibility of the highlighted text. --- view/theme/redbasic/css/style.css | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/view/theme/redbasic/css/style.css b/view/theme/redbasic/css/style.css index b406e710c..18c3db665 100644 --- a/view/theme/redbasic/css/style.css +++ b/view/theme/redbasic/css/style.css @@ -1806,6 +1806,5 @@ dl.bb-dl > dd > li { /* default highlighted text if not specified by schema: */ span.default-highlight { - background-color: yellow; - padding: 2px 4px; + background-color: yellow; } From cdb85f130933b2abe9da80119696f5d1d55bebc4 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 22 Dec 2018 21:00:01 +0100 Subject: [PATCH 44/93] update changelog --- CHANGELOG | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index a3dd1336b..5d0f35cc1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,21 @@ +Hubzilla 3.8.8 (2018-12-22) + - Fix issue with linkinfo + - Fix cURL with HTTP/2 + - Remove scale_external_images() + - Style highlight bbcode via css + - Make mod channel deal with b64 encoded mid's + - Fix email retrieval in OAuth2Storage + - Add reinstall option to util/addons + - Remove deprecated caching protection from mod photo + - Add missing check for observer in mod like + - Articles: default to logged in channel if channel name is not passed + - Wiki: fix preview issue with hyperlinks + - Cart: backport fixes from osada + - Gallery: provide file extensions for better compatibility + - Hsse: fix issue when linkinfo data was inserted + - Diaspora: remove deprecated scale_external_images() + + Hubzilla 3.8.7 (2018-12-14) - Fix issue with linkdropper in comment area - Fix regression wit app ordering From 37d7d18bb7b1e3bcadbb11c43a761d6953c2dc55 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Mon, 24 Dec 2018 09:22:58 +0100 Subject: [PATCH 45/93] Faster image processing with photo cache addon --- Zotlabs/Module/Photo.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Zotlabs/Module/Photo.php b/Zotlabs/Module/Photo.php index e236cc5f4..96a4e1f40 100644 --- a/Zotlabs/Module/Photo.php +++ b/Zotlabs/Module/Photo.php @@ -159,14 +159,15 @@ class Photo extends \Zotlabs\Web\Controller { // Validate cache $cache = array( 'resid' => $photo, - 'url' => htmlspecialchars_decode($r[0]['display_path']) + 'status' => false ); if($cache_mode['on']) call_hooks('cache_url_hook', $cache); - if($cache['url'] != '') { - if(strpos(z_root(),'https:') !== false && strpos($cache['url'],'https:') === false) - $cache['url'] = z_root() . '/sslify/' . $filename . '?f=&url=' . urlencode($cache['url']); - header("Location: " . $cache['url']); + if(! $cache['status']) { + $url = htmlspecialchars_decode($r[0]['display_path']); + if(strpos(z_root(),'https:') !== false && strpos($url,'https:') === false) + $url = z_root() . '/sslify/' . $filename . '?f=&url=' . urlencode($url); + header("Location: " . $url); killme(); } } From a50433dd958ec52eec88867517b3ae6467758618 Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Sun, 30 Dec 2018 15:05:45 -0500 Subject: [PATCH 46/93] Use subselect --- Zotlabs/Daemon/Master.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Zotlabs/Daemon/Master.php b/Zotlabs/Daemon/Master.php index 0656ca05b..70d80d75b 100644 --- a/Zotlabs/Daemon/Master.php +++ b/Zotlabs/Daemon/Master.php @@ -89,7 +89,7 @@ class Master { $workersleep = ($workersleep) ? $workersleep : 5; cli_startup(); - $work = q("update config set k='%s' where cat='queuework' and k like '%s' limit 1", + $work = q("update config set k='%s' where id in (select id from config where cat='queuework' and k like '%s' limit 1)", 'workitem_'.self::$queueworker, dbesc('workitem:%')); $jobs = 0; @@ -122,9 +122,9 @@ class Master { break; } sleep ($workersleep); - $work = q("update config set k='%s' where cat='queuework' and k like '%s' limit 1", - 'workitem_'.self::$queueworker, - dbesc('workitem:%')); + $work = q("update config set k='%s' where id in (select id from config where cat='queuework' and k like '%s' limit 1)", + 'workitem_'.self::$queueworker, + dbesc('workitem:%')); } logger('Master: Worker Thread: queue items processed:' . $jobs); From f3f106c21f81cdb297a9f76765df3686eec1d95d Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 2 Jan 2019 17:49:21 +0100 Subject: [PATCH 47/93] check suppported type if we get content type from header --- include/photo/photo_driver.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php index 9aeb2ef17..608237ce1 100644 --- a/include/photo/photo_driver.php +++ b/include/photo/photo_driver.php @@ -482,7 +482,6 @@ function guess_image_type($filename, $headers = '') { // logger('Photo: guess_image_type: '.$filename . ($headers?' from curl headers':''), LOGGER_DEBUG); $type = null; if ($headers) { - $hdrs=array(); $h = explode("\n",$headers); foreach ($h as $l) { @@ -490,11 +489,16 @@ function guess_image_type($filename, $headers = '') { $hdrs[strtolower($k)] = $v; } logger('Curl headers: '.var_export($hdrs, true), LOGGER_DEBUG); - if (array_key_exists('content-type', $hdrs)) + if (array_key_exists('content-type', $hdrs)) { $type = $hdrs['content-type']; + + $ph = photo_factory(''); + $types = $ph->supportedTypes(); + + $type = $types[$type]; + } } if (is_null($type)){ - $ignore_imagick = get_config('system', 'ignore_imagick'); // Guessing from extension? Isn't that... dangerous? if(class_exists('Imagick') && file_exists($filename) && is_readable($filename) && !$ignore_imagick) { @@ -638,7 +642,6 @@ function import_xchan_photo($photo,$xchan,$thing = false,$force = false) { $img_str = $result['body']; $type = guess_image_type($photo, $result['header']); $modified = gmdate('Y-m-d H:i:s', (preg_match('/last-modified: (.+) \S+/i', $result['header'], $o) ? strtotime($o[1] . 'Z') : time())); - if(is_null($type)) $photo_failure = true; } From b0339b848fc28aabee6cdc1b971330afc8e5ca89 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 2 Jan 2019 17:53:28 +0100 Subject: [PATCH 48/93] fix preg_match(): Delimiter must not be alphanumeric or backslash warning --- Zotlabs/Module/Pconfig.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Module/Pconfig.php b/Zotlabs/Module/Pconfig.php index f31d5fdf6..06b94b34f 100644 --- a/Zotlabs/Module/Pconfig.php +++ b/Zotlabs/Module/Pconfig.php @@ -24,7 +24,7 @@ class Pconfig extends \Zotlabs\Web\Controller { $aj = intval($_POST['aj']); // Do not store "serialized" data received in the $_POST - if (preg_match('|^a:[0-9]+:{.*}$|s',$v) || preg_match('O:8:"stdClass":[0-9]+:{.*}$|s',$v)) { + if (preg_match('|^a:[0-9]+:{.*}$|s',$v) || preg_match('|O:8:"stdClass":[0-9]+:{.*}$|s',$v)) { return; } From aae4943e64bc8874be0802ec4faddb77f378b6c2 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 2 Jan 2019 19:43:52 +0100 Subject: [PATCH 49/93] add zotsite.net to directory fallback servers --- boot.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boot.php b/boot.php index 410aa91b1..321f1a93b 100755 --- a/boot.php +++ b/boot.php @@ -84,7 +84,8 @@ define ( 'DIRECTORY_FALLBACK_MASTER', 'https://zotadel.net'); $DIRECTORY_FALLBACK_SERVERS = array( 'https://hubzilla.zottel.net', - 'https://zotadel.net' + 'https://zotadel.net', + 'https://zotsite.net' ); From a19563e1396cb882063db3ce3f355b2db48175e9 Mon Sep 17 00:00:00 2001 From: Mario Date: Wed, 2 Jan 2019 19:56:11 +0100 Subject: [PATCH 50/93] Revert "Use subselect" This reverts commit a50433dd958ec52eec88867517b3ae6467758618 --- Zotlabs/Daemon/Master.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Zotlabs/Daemon/Master.php b/Zotlabs/Daemon/Master.php index 70d80d75b..0656ca05b 100644 --- a/Zotlabs/Daemon/Master.php +++ b/Zotlabs/Daemon/Master.php @@ -89,7 +89,7 @@ class Master { $workersleep = ($workersleep) ? $workersleep : 5; cli_startup(); - $work = q("update config set k='%s' where id in (select id from config where cat='queuework' and k like '%s' limit 1)", + $work = q("update config set k='%s' where cat='queuework' and k like '%s' limit 1", 'workitem_'.self::$queueworker, dbesc('workitem:%')); $jobs = 0; @@ -122,9 +122,9 @@ class Master { break; } sleep ($workersleep); - $work = q("update config set k='%s' where id in (select id from config where cat='queuework' and k like '%s' limit 1)", - 'workitem_'.self::$queueworker, - dbesc('workitem:%')); + $work = q("update config set k='%s' where cat='queuework' and k like '%s' limit 1", + 'workitem_'.self::$queueworker, + dbesc('workitem:%')); } logger('Master: Worker Thread: queue items processed:' . $jobs); From f660530ef5cce1fab2e7c16daad2239524cb5aac Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 2 Jan 2019 12:49:04 -0800 Subject: [PATCH 51/93] allow notification updates when composing comments. This was disabled when it was possible to have liveUpdate run automatically while composing comments, but it seems that live update is no longer possible (however the setting still remains - this should probably be removed). --- include/zid.php | 6 +++--- view/js/main.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/zid.php b/include/zid.php index fe06948ba..a37ebe1f6 100644 --- a/include/zid.php +++ b/include/zid.php @@ -70,9 +70,9 @@ function zid($s, $address = '') { $zurl .= '#' . $fragment; $arr = [ - 'url' => $s, - 'zid' => urlencode($myaddr), - 'result' => $zurl + 'url' => $s, + 'zid' => urlencode($myaddr), + 'result' => $zurl ]; /** * @hooks zid diff --git a/view/js/main.js b/view/js/main.js index a69bcfa64..0169ee54c 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -888,7 +888,7 @@ function liveUpdate(notify_id) { if((src === null) || (stopped) || (! profile_uid)) { $('.like-rotator').hide(); return; } - if(($('.comment-edit-text.expanded').length) || (in_progress) || (mediaPlaying)) { + if(in_progress || mediaPlaying) { if(livetime) { clearTimeout(livetime); } From dbd230da7407ac70483c004bc82f4b8619c42760 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 2 Jan 2019 22:41:03 +0100 Subject: [PATCH 52/93] update composer libs --- composer.lock | 340 ++++++++++++------ .../bshaffer/oauth2-server-php/CHANGELOG.md | 4 +- vendor/bshaffer/oauth2-server-php/README.md | 2 +- .../oauth2-server-php/src/OAuth2/Request.php | 7 +- .../oauth2-server-php/src/OAuth2/Response.php | 2 +- .../OAuth2/ResponseType/JwtAccessToken.php | 18 +- .../oauth2-server-php/src/OAuth2/Server.php | 9 +- .../test/OAuth2/RequestTest.php | 18 + .../test/OAuth2/ResponseTest.php | 23 +- .../ResponseType/JwtAccessTokenTest.php | 21 +- .../test/OAuth2/Storage/PdoTest.php | 8 +- .../test/lib/OAuth2/Storage/Bootstrap.php | 2 +- vendor/composer/autoload_classmap.php | 5 +- vendor/composer/autoload_static.php | 5 +- vendor/composer/installed.json | 24 +- vendor/league/html-to-markdown/CHANGELOG.md | 11 +- .../src/Converter/DefaultConverter.php | 8 +- .../src/Converter/HardBreakConverter.php | 5 +- 18 files changed, 364 insertions(+), 148 deletions(-) diff --git a/composer.lock b/composer.lock index bd95e8c78..c4fba0975 100644 --- a/composer.lock +++ b/composer.lock @@ -63,16 +63,16 @@ }, { "name": "bshaffer/oauth2-server-php", - "version": "v1.10.0", + "version": "v1.11.1", "source": { "type": "git", "url": "https://github.com/bshaffer/oauth2-server-php.git", - "reference": "d158878425392fe5a0cc34f15dbaf46315ae0ed9" + "reference": "5a0c8000d4763b276919e2106f54eddda6bc50fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bshaffer/oauth2-server-php/zipball/d158878425392fe5a0cc34f15dbaf46315ae0ed9", - "reference": "d158878425392fe5a0cc34f15dbaf46315ae0ed9", + "url": "https://api.github.com/repos/bshaffer/oauth2-server-php/zipball/5a0c8000d4763b276919e2106f54eddda6bc50fa", + "reference": "5a0c8000d4763b276919e2106f54eddda6bc50fa", "shasum": "" }, "require": { @@ -117,7 +117,7 @@ "oauth", "oauth2" ], - "time": "2017-11-15T01:41:02+00:00" + "time": "2018-12-04T00:29:32+00:00" }, { "name": "commerceguys/intl", @@ -251,16 +251,16 @@ }, { "name": "league/html-to-markdown", - "version": "4.8.0", + "version": "4.8.1", "source": { "type": "git", "url": "https://github.com/thephpleague/html-to-markdown.git", - "reference": "f9a879a068c68ff47b722de63f58bec79e448f9d" + "reference": "250d1bf45f80d15594fb6b316df777d6d4c97ad1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/f9a879a068c68ff47b722de63f58bec79e448f9d", - "reference": "f9a879a068c68ff47b722de63f58bec79e448f9d", + "url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/250d1bf45f80d15594fb6b316df777d6d4c97ad1", + "reference": "250d1bf45f80d15594fb6b316df777d6d4c97ad1", "shasum": "" }, "require": { @@ -311,7 +311,7 @@ "html", "markdown" ], - "time": "2018-09-18T12:18:08+00:00" + "time": "2018-12-24T17:21:44+00:00" }, { "name": "lukasreschke/id3parser", @@ -1925,32 +1925,33 @@ }, { "name": "guzzlehttp/psr7", - "version": "1.4.2", + "version": "1.5.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" + "reference": "9f83dded91781a01c63574e387eaa769be769115" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115", + "reference": "9f83dded91781a01c63574e387eaa769be769115", "shasum": "" }, "require": { "php": ">=5.4.0", - "psr/http-message": "~1.0" + "psr/http-message": "~1.0", + "ralouphie/getallheaders": "^2.0.5" }, "provide": { "psr/http-message-implementation": "1.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.5-dev" } }, "autoload": { @@ -1980,13 +1981,14 @@ "keywords": [ "http", "message", + "psr-7", "request", "response", "stream", "uri", "url" ], - "time": "2017-03-20T17:10:46+00:00" + "time": "2018-12-04T20:46:45+00:00" }, { "name": "myclabs/deep-copy", @@ -2571,6 +2573,7 @@ "testing", "xunit" ], + "abandoned": true, "time": "2018-02-07T06:47:59+00:00" }, { @@ -2827,16 +2830,16 @@ }, { "name": "phpunit/phpunit", - "version": "7.4.4", + "version": "7.5.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "b1be2c8530c4c29c3519a052c9fb6cee55053bbd" + "reference": "c23d78776ad415d5506e0679723cb461d71f488f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b1be2c8530c4c29c3519a052c9fb6cee55053bbd", - "reference": "b1be2c8530c4c29c3519a052c9fb6cee55053bbd", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c23d78776ad415d5506e0679723cb461d71f488f", + "reference": "c23d78776ad415d5506e0679723cb461d71f488f", "shasum": "" }, "require": { @@ -2857,7 +2860,7 @@ "phpunit/php-timer": "^2.0", "sebastian/comparator": "^3.0", "sebastian/diff": "^3.0", - "sebastian/environment": "^3.1 || ^4.0", + "sebastian/environment": "^4.0", "sebastian/exporter": "^3.1", "sebastian/global-state": "^2.0", "sebastian/object-enumerator": "^3.0.3", @@ -2881,7 +2884,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "7.4-dev" + "dev-master": "7.5-dev" } }, "autoload": { @@ -2907,7 +2910,7 @@ "testing", "xunit" ], - "time": "2018-11-14T16:52:02+00:00" + "time": "2018-12-12T07:20:32+00:00" }, { "name": "psr/container", @@ -3008,6 +3011,46 @@ ], "time": "2016-08-06T14:39:51+00:00" }, + { + "name": "ralouphie/getallheaders", + "version": "2.0.5", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa", + "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "~3.7.0", + "satooshi/php-coveralls": ">=1.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "time": "2016-02-11T07:05:27+00:00" + }, { "name": "sebastian/code-unit-reverse-lookup", "version": "1.0.1", @@ -3175,28 +3218,28 @@ }, { "name": "sebastian/environment", - "version": "3.1.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" + "reference": "febd209a219cea7b56ad799b30ebbea34b71eb8f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", - "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/febd209a219cea7b56ad799b30ebbea34b71eb8f", + "reference": "febd209a219cea7b56ad799b30ebbea34b71eb8f", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^6.1" + "phpunit/phpunit": "^7.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3221,7 +3264,7 @@ "environment", "hhvm" ], - "time": "2017-07-01T08:51:00+00:00" + "time": "2018-11-25T09:31:21+00:00" }, { "name": "sebastian/exporter", @@ -3573,16 +3616,16 @@ }, { "name": "symfony/browser-kit", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "c55fe9257003b2d95c0211b3f6941e8dfd26dffd" + "reference": "db7e59fec9c82d45e745eb500e6ede2d96f4a6e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/c55fe9257003b2d95c0211b3f6941e8dfd26dffd", - "reference": "c55fe9257003b2d95c0211b3f6941e8dfd26dffd", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/db7e59fec9c82d45e745eb500e6ede2d96f4a6e9", + "reference": "db7e59fec9c82d45e745eb500e6ede2d96f4a6e9", "shasum": "" }, "require": { @@ -3599,7 +3642,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -3626,20 +3669,20 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", - "time": "2018-07-26T09:10:45+00:00" + "time": "2018-11-26T11:49:31+00:00" }, { "name": "symfony/class-loader", - "version": "v3.4.18", + "version": "v3.4.20", "source": { "type": "git", "url": "https://github.com/symfony/class-loader.git", - "reference": "5605edec7b8f034ead2497ff4aab17bb70d558c1" + "reference": "420458095cf60025eb0841276717e0da7f75e50e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/class-loader/zipball/5605edec7b8f034ead2497ff4aab17bb70d558c1", - "reference": "5605edec7b8f034ead2497ff4aab17bb70d558c1", + "url": "https://api.github.com/repos/symfony/class-loader/zipball/420458095cf60025eb0841276717e0da7f75e50e", + "reference": "420458095cf60025eb0841276717e0da7f75e50e", "shasum": "" }, "require": { @@ -3682,20 +3725,20 @@ ], "description": "Symfony ClassLoader Component", "homepage": "https://symfony.com", - "time": "2018-10-31T09:06:03+00:00" + "time": "2018-11-11T19:48:54+00:00" }, { "name": "symfony/config", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "991fec8bbe77367fc8b48ecbaa8a4bd6e905a238" + "reference": "005d9a083d03f588677d15391a716b1ac9b887c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/991fec8bbe77367fc8b48ecbaa8a4bd6e905a238", - "reference": "991fec8bbe77367fc8b48ecbaa8a4bd6e905a238", + "url": "https://api.github.com/repos/symfony/config/zipball/005d9a083d03f588677d15391a716b1ac9b887c0", + "reference": "005d9a083d03f588677d15391a716b1ac9b887c0", "shasum": "" }, "require": { @@ -3718,7 +3761,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -3745,24 +3788,25 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2018-10-31T09:09:42+00:00" + "time": "2018-11-30T22:21:14+00:00" }, { "name": "symfony/console", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "432122af37d8cd52fba1b294b11976e0d20df595" + "reference": "4dff24e5d01e713818805c1862d2e3f901ee7dd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/432122af37d8cd52fba1b294b11976e0d20df595", - "reference": "432122af37d8cd52fba1b294b11976e0d20df595", + "url": "https://api.github.com/repos/symfony/console/zipball/4dff24e5d01e713818805c1862d2e3f901ee7dd0", + "reference": "4dff24e5d01e713818805c1862d2e3f901ee7dd0", "shasum": "" }, "require": { "php": "^7.1.3", + "symfony/contracts": "^1.0", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { @@ -3786,7 +3830,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -3813,20 +3857,88 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2018-10-31T09:30:44+00:00" + "time": "2018-11-27T07:40:44+00:00" }, { - "name": "symfony/css-selector", - "version": "v3.4.18", + "name": "symfony/contracts", + "version": "v1.0.2", "source": { "type": "git", - "url": "https://github.com/symfony/css-selector.git", - "reference": "3503415d4aafabc31cd08c3a4ebac7f43fde8feb" + "url": "https://github.com/symfony/contracts.git", + "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/3503415d4aafabc31cd08c3a4ebac7f43fde8feb", - "reference": "3503415d4aafabc31cd08c3a4ebac7f43fde8feb", + "url": "https://api.github.com/repos/symfony/contracts/zipball/1aa7ab2429c3d594dd70689604b5cf7421254cdf", + "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "require-dev": { + "psr/cache": "^1.0", + "psr/container": "^1.0" + }, + "suggest": { + "psr/cache": "When using the Cache contracts", + "psr/container": "When using the Service contracts", + "symfony/cache-contracts-implementation": "", + "symfony/service-contracts-implementation": "", + "symfony/translation-contracts-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\": "" + }, + "exclude-from-classmap": [ + "**/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A set of abstractions extracted out of the Symfony components", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2018-12-05T08:06:11+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v3.4.20", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "345b9a48595d1ab9630db791dbc3e721bf0233e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/345b9a48595d1ab9630db791dbc3e721bf0233e8", + "reference": "345b9a48595d1ab9630db791dbc3e721bf0233e8", "shasum": "" }, "require": { @@ -3866,37 +3978,39 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2018-10-02T16:33:53+00:00" + "time": "2018-11-11T19:48:54+00:00" }, { "name": "symfony/dependency-injection", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "e72ee2c23d952e4c368ee98610fa22b79b89b483" + "reference": "e4adc57a48d3fa7f394edfffa9e954086d7740e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/e72ee2c23d952e4c368ee98610fa22b79b89b483", - "reference": "e72ee2c23d952e4c368ee98610fa22b79b89b483", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/e4adc57a48d3fa7f394edfffa9e954086d7740e5", + "reference": "e4adc57a48d3fa7f394edfffa9e954086d7740e5", "shasum": "" }, "require": { "php": "^7.1.3", - "psr/container": "^1.0" + "psr/container": "^1.0", + "symfony/contracts": "^1.0" }, "conflict": { - "symfony/config": "<4.1.1", + "symfony/config": "<4.2", "symfony/finder": "<3.4", "symfony/proxy-manager-bridge": "<3.4", "symfony/yaml": "<3.4" }, "provide": { - "psr/container-implementation": "1.0" + "psr/container-implementation": "1.0", + "symfony/service-contracts-implementation": "1.0" }, "require-dev": { - "symfony/config": "~4.1", + "symfony/config": "~4.2", "symfony/expression-language": "~3.4|~4.0", "symfony/yaml": "~3.4|~4.0" }, @@ -3910,7 +4024,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -3937,20 +4051,20 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2018-10-31T10:54:16+00:00" + "time": "2018-12-02T15:59:36+00:00" }, { "name": "symfony/dom-crawler", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "80e60271bb288de2a2259662cff125cff4f93f95" + "reference": "7438a32108fdd555295f443605d6de2cce473159" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/80e60271bb288de2a2259662cff125cff4f93f95", - "reference": "80e60271bb288de2a2259662cff125cff4f93f95", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/7438a32108fdd555295f443605d6de2cce473159", + "reference": "7438a32108fdd555295f443605d6de2cce473159", "shasum": "" }, "require": { @@ -3967,7 +4081,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -3994,24 +4108,25 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2018-10-02T12:40:59+00:00" + "time": "2018-11-26T10:55:26+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "552541dad078c85d9414b09c041ede488b456cd5" + "reference": "921f49c3158a276d27c0d770a5a347a3b718b328" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/552541dad078c85d9414b09c041ede488b456cd5", - "reference": "552541dad078c85d9414b09c041ede488b456cd5", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/921f49c3158a276d27c0d770a5a347a3b718b328", + "reference": "921f49c3158a276d27c0d770a5a347a3b718b328", "shasum": "" }, "require": { - "php": "^7.1.3" + "php": "^7.1.3", + "symfony/contracts": "^1.0" }, "conflict": { "symfony/dependency-injection": "<3.4" @@ -4030,7 +4145,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -4057,20 +4172,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2018-10-10T13:52:42+00:00" + "time": "2018-12-01T08:52:38+00:00" }, { "name": "symfony/filesystem", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "fd7bd6535beb1f0a0a9e3ee960666d0598546981" + "reference": "2f4c8b999b3b7cadb2a69390b01af70886753710" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/fd7bd6535beb1f0a0a9e3ee960666d0598546981", - "reference": "fd7bd6535beb1f0a0a9e3ee960666d0598546981", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/2f4c8b999b3b7cadb2a69390b01af70886753710", + "reference": "2f4c8b999b3b7cadb2a69390b01af70886753710", "shasum": "" }, "require": { @@ -4080,7 +4195,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -4107,7 +4222,7 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2018-10-30T13:18:25+00:00" + "time": "2018-11-11T19:52:12+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -4170,20 +4285,21 @@ }, { "name": "symfony/translation", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c" + "reference": "c0e2191e9bed845946ab3d99767513b56ca7dcd6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c", - "reference": "aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c", + "url": "https://api.github.com/repos/symfony/translation/zipball/c0e2191e9bed845946ab3d99767513b56ca7dcd6", + "reference": "c0e2191e9bed845946ab3d99767513b56ca7dcd6", "shasum": "" }, "require": { "php": "^7.1.3", + "symfony/contracts": "^1.0.2", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { @@ -4191,6 +4307,9 @@ "symfony/dependency-injection": "<3.4", "symfony/yaml": "<3.4" }, + "provide": { + "symfony/translation-contracts-implementation": "1.0" + }, "require-dev": { "psr/log": "~1.0", "symfony/config": "~3.4|~4.0", @@ -4208,7 +4327,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -4235,20 +4354,20 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2018-10-28T18:38:52+00:00" + "time": "2018-12-06T10:45:32+00:00" }, { "name": "symfony/yaml", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "367e689b2fdc19965be435337b50bc8adf2746c9" + "reference": "c41175c801e3edfda90f32e292619d10c27103d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/367e689b2fdc19965be435337b50bc8adf2746c9", - "reference": "367e689b2fdc19965be435337b50bc8adf2746c9", + "url": "https://api.github.com/repos/symfony/yaml/zipball/c41175c801e3edfda90f32e292619d10c27103d7", + "reference": "c41175c801e3edfda90f32e292619d10c27103d7", "shasum": "" }, "require": { @@ -4267,7 +4386,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -4294,7 +4413,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2018-10-02T16:36:10+00:00" + "time": "2018-11-11T19:52:12+00:00" }, { "name": "theseer/tokenizer", @@ -4338,20 +4457,21 @@ }, { "name": "webmozart/assert", - "version": "1.3.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a" + "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a", + "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9", + "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^5.3.3 || ^7.0", + "symfony/polyfill-ctype": "^1.8" }, "require-dev": { "phpunit/phpunit": "^4.6", @@ -4384,7 +4504,7 @@ "check", "validate" ], - "time": "2018-01-29T19:49:41+00:00" + "time": "2018-12-25T11:19:39+00:00" } ], "aliases": [], diff --git a/vendor/bshaffer/oauth2-server-php/CHANGELOG.md b/vendor/bshaffer/oauth2-server-php/CHANGELOG.md index 7671b2396..1b87f3da3 100644 --- a/vendor/bshaffer/oauth2-server-php/CHANGELOG.md +++ b/vendor/bshaffer/oauth2-server-php/CHANGELOG.md @@ -8,7 +8,7 @@ To see the files changed for a given bug, go to https://github.com/bshaffer/oaut To get the diff between two versions, go to https://github.com/bshaffer/oauth2-server-php/compare/v1.0...v1.1 To get the diff for a specific change, go to https://github.com/bshaffer/oauth2-server-php/commit/XXX where XXX is the change hash -* 1.10.0 (2017-12-14) +* 1.10.0 (2017-11-15) PR: https://github.com/bshaffer/oauth2-server-php/pull/889 @@ -26,7 +26,7 @@ To get the diff for a specific change, go to https://github.com/bshaffer/oauth2- * #794 - [docs] Fix typo in composer.json * #885 - [testing] Use PHPUnit\Framework\TestCase instead of PHPUnit_Framework_TestCase -* 1.9.0 (2016-01-06) +* 1.9.0 (2017-01-06) PR: https://github.com/bshaffer/oauth2-server-php/pull/788 diff --git a/vendor/bshaffer/oauth2-server-php/README.md b/vendor/bshaffer/oauth2-server-php/README.md index f1788e9ce..117743d4f 100644 --- a/vendor/bshaffer/oauth2-server-php/README.md +++ b/vendor/bshaffer/oauth2-server-php/README.md @@ -1,7 +1,7 @@ oauth2-server-php ================= -[![Build Status](https://travis-ci.org/bshaffer/oauth2-server-php.svg?branch=develop)](https://travis-ci.org/bshaffer/oauth2-server-php) +[![Build Status](https://travis-ci.org/bshaffer/oauth2-server-php.svg?branch=master)](https://travis-ci.org/bshaffer/oauth2-server-php) [![Total Downloads](https://poser.pugx.org/bshaffer/oauth2-server-php/downloads.png)](https://packagist.org/packages/bshaffer/oauth2-server-php) diff --git a/vendor/bshaffer/oauth2-server-php/src/OAuth2/Request.php b/vendor/bshaffer/oauth2-server-php/src/OAuth2/Request.php index c96cb972f..f547bf6e8 100644 --- a/vendor/bshaffer/oauth2-server-php/src/OAuth2/Request.php +++ b/vendor/bshaffer/oauth2-server-php/src/OAuth2/Request.php @@ -64,7 +64,12 @@ class Request implements RequestInterface $this->files = $files; $this->server = $server; $this->content = $content; - $this->headers = is_null($headers) ? $this->getHeadersFromServer($this->server) : $headers; + + if ($headers === null) { + $headers = array(); + } + + $this->headers = $headers + $this->getHeadersFromServer($this->server); } /** diff --git a/vendor/bshaffer/oauth2-server-php/src/OAuth2/Response.php b/vendor/bshaffer/oauth2-server-php/src/OAuth2/Response.php index ccd797ae7..88c1ad5f7 100644 --- a/vendor/bshaffer/oauth2-server-php/src/OAuth2/Response.php +++ b/vendor/bshaffer/oauth2-server-php/src/OAuth2/Response.php @@ -366,7 +366,7 @@ class Response implements ResponseInterface if (count($this->parameters) > 0) { // add parameters to URL redirection $parts = parse_url($url); - $sep = isset($parts['query']) && count($parts['query']) > 0 ? '&' : '?'; + $sep = isset($parts['query']) && !empty($parts['query']) ? '&' : '?'; $url .= $sep . http_build_query($this->parameters); } diff --git a/vendor/bshaffer/oauth2-server-php/src/OAuth2/ResponseType/JwtAccessToken.php b/vendor/bshaffer/oauth2-server-php/src/OAuth2/ResponseType/JwtAccessToken.php index 0af9705ff..0ee3708aa 100644 --- a/vendor/bshaffer/oauth2-server-php/src/OAuth2/ResponseType/JwtAccessToken.php +++ b/vendor/bshaffer/oauth2-server-php/src/OAuth2/ResponseType/JwtAccessToken.php @@ -128,7 +128,7 @@ class JwtAccessToken extends AccessToken $expires = time() + $this->config['access_lifetime']; $id = $this->generateAccessToken(); - return array( + $payload = array( 'id' => $id, // for BC (see #591) 'jti' => $id, 'iss' => $this->config['issuer'], @@ -139,5 +139,21 @@ class JwtAccessToken extends AccessToken 'token_type' => $this->config['token_type'], 'scope' => $scope ); + + if (isset($this->config['jwt_extra_payload_callable'])) { + if (!is_callable($this->config['jwt_extra_payload_callable'])) { + throw new \InvalidArgumentException('jwt_extra_payload_callable is not callable'); + } + + $extra = call_user_func($this->config['jwt_extra_payload_callable'], $client_id, $user_id, $scope); + + if (!is_array($extra)) { + throw new \InvalidArgumentException('jwt_extra_payload_callable must return array'); + } + + $payload = array_merge($extra, $payload); + } + + return $payload; } } diff --git a/vendor/bshaffer/oauth2-server-php/src/OAuth2/Server.php b/vendor/bshaffer/oauth2-server-php/src/OAuth2/Server.php index 62ae8970d..cf040c2bc 100644 --- a/vendor/bshaffer/oauth2-server-php/src/OAuth2/Server.php +++ b/vendor/bshaffer/oauth2-server-php/src/OAuth2/Server.php @@ -88,12 +88,12 @@ class Server implements ResourceControllerInterface, /** * @var array */ - protected $grantTypes = []; + protected $grantTypes = array(); /** * @var array */ - protected $responseTypes = []; + protected $responseTypes = array(); /** * @var TokenTypeInterface @@ -161,6 +161,7 @@ class Server implements ResourceControllerInterface, // merge all config values. These get passed to our controller objects $this->config = array_merge(array( 'use_jwt_access_tokens' => false, + 'jwt_extra_payload_callable' => null, 'store_encrypted_token_string' => true, 'use_openid_connect' => false, 'id_lifetime' => 3600, @@ -840,7 +841,7 @@ class Server implements ResourceControllerInterface, $refreshStorage = $this->storages['refresh_token']; } - $config = array_intersect_key($this->config, array_flip(explode(' ', 'store_encrypted_token_string issuer access_lifetime refresh_token_lifetime'))); + $config = array_intersect_key($this->config, array_flip(explode(' ', 'store_encrypted_token_string issuer access_lifetime refresh_token_lifetime jwt_extra_payload_callable'))); return new JwtAccessToken($this->storages['public_key'], $tokenStorage, $refreshStorage, $config); } @@ -1015,4 +1016,4 @@ class Server implements ResourceControllerInterface, { return isset($this->config[$name]) ? $this->config[$name] : $default; } -} \ No newline at end of file +} diff --git a/vendor/bshaffer/oauth2-server-php/test/OAuth2/RequestTest.php b/vendor/bshaffer/oauth2-server-php/test/OAuth2/RequestTest.php index cbf8f096b..770cd8994 100644 --- a/vendor/bshaffer/oauth2-server-php/test/OAuth2/RequestTest.php +++ b/vendor/bshaffer/oauth2-server-php/test/OAuth2/RequestTest.php @@ -86,6 +86,24 @@ class RequestTest extends TestCase $this->assertEquals('correct', $request->query('client_id', $request->request('client_id'))); } + public function testRequestHasHeadersAndServerHeaders() + { + $request = new Request( + array(), + array(), + array(), + array(), + array(), + array('CONTENT_TYPE' => 'text/xml', 'PHP_AUTH_USER' => 'client_id', 'PHP_AUTH_PW' => 'client_pass'), + null, + array('CONTENT_TYPE' => 'application/json') + ); + + $this->assertSame('client_id', $request->headers('PHP_AUTH_USER')); + $this->assertSame('client_pass', $request->headers('PHP_AUTH_PW')); + $this->assertSame('application/json', $request->headers('CONTENT_TYPE')); + } + private function getTestServer($config = array()) { $storage = Bootstrap::getInstance()->getMemoryStorage(); diff --git a/vendor/bshaffer/oauth2-server-php/test/OAuth2/ResponseTest.php b/vendor/bshaffer/oauth2-server-php/test/OAuth2/ResponseTest.php index 2d2c57ee6..172bc88fd 100644 --- a/vendor/bshaffer/oauth2-server-php/test/OAuth2/ResponseTest.php +++ b/vendor/bshaffer/oauth2-server-php/test/OAuth2/ResponseTest.php @@ -1,6 +1,8 @@ getResponseBody('xml'); $this->assertContains('baroates', $string); } + + public function testSetRedirect() + { + $response = new Response(); + $url = 'https://foo/bar'; + $state = 'stateparam'; + $response->setRedirect(301, $url, $state); + $this->assertEquals( + sprintf('%s?state=%s', $url, $state), + $response->getHttpHeader('Location') + ); + + $query = 'query=foo'; + $response->setRedirect(301, $url . '?' . $query, $state); + $this->assertEquals( + sprintf('%s?%s&state=%s', $url, $query, $state), + $response->getHttpHeader('Location') + ); + } } diff --git a/vendor/bshaffer/oauth2-server-php/test/OAuth2/ResponseType/JwtAccessTokenTest.php b/vendor/bshaffer/oauth2-server-php/test/OAuth2/ResponseType/JwtAccessTokenTest.php index 7e37509ef..6195d557a 100644 --- a/vendor/bshaffer/oauth2-server-php/test/OAuth2/ResponseType/JwtAccessTokenTest.php +++ b/vendor/bshaffer/oauth2-server-php/test/OAuth2/ResponseType/JwtAccessTokenTest.php @@ -40,6 +40,23 @@ class JwtAccessTokenTest extends TestCase $this->assertEquals(3600, $delta); $this->assertEquals($decodedAccessToken['id'], $decodedAccessToken['jti']); } + + public function testExtraPayloadCallback() + { + $jwtconfig = array('jwt_extra_payload_callable' => function() { + return array('custom_param' => 'custom_value'); + }); + + $server = $this->getTestServer($jwtconfig); + $jwtResponseType = $server->getResponseType('token'); + + $accessToken = $jwtResponseType->createAccessToken('Test Client ID', 123, 'test', false); + $jwt = new Jwt; + $decodedAccessToken = $jwt->decode($accessToken['access_token'], null, false); + + $this->assertArrayHasKey('custom_param', $decodedAccessToken); + $this->assertEquals('custom_value', $decodedAccessToken['custom_param']); + } public function testGrantJwtAccessToken() { @@ -140,7 +157,7 @@ class JwtAccessTokenTest extends TestCase $this->assertNotNull($response->getParameter('access_token')); } - private function getTestServer() + private function getTestServer($jwtconfig = array()) { $memoryStorage = Bootstrap::getInstance()->getMemoryStorage(); @@ -153,7 +170,7 @@ class JwtAccessTokenTest extends TestCase $server->addGrantType(new ClientCredentials($memoryStorage)); // make the "token" response type a JwtAccessToken - $config = array('issuer' => 'https://api.example.com'); + $config = array_merge(array('issuer' => 'https://api.example.com'), $jwtconfig); $server->addResponseType(new JwtAccessToken($memoryStorage, $memoryStorage, null, $config)); return $server; diff --git a/vendor/bshaffer/oauth2-server-php/test/OAuth2/Storage/PdoTest.php b/vendor/bshaffer/oauth2-server-php/test/OAuth2/Storage/PdoTest.php index 57eb39072..4599f69bf 100644 --- a/vendor/bshaffer/oauth2-server-php/test/OAuth2/Storage/PdoTest.php +++ b/vendor/bshaffer/oauth2-server-php/test/OAuth2/Storage/PdoTest.php @@ -6,7 +6,8 @@ class PdoTest extends BaseTest { public function testCreatePdoStorageUsingPdoClass() { - $pdo = new \PDO(sprintf('sqlite://%s', Bootstrap::getInstance()->getSqliteDir())); + $dsn = sprintf('sqlite:%s', Bootstrap::getInstance()->getSqliteDir()); + $pdo = new \PDO($dsn); $storage = new Pdo($pdo); $this->assertNotNull($storage->getClientDetails('oauth_test_client')); @@ -14,7 +15,7 @@ class PdoTest extends BaseTest public function testCreatePdoStorageUsingDSN() { - $dsn = sprintf('sqlite://%s', Bootstrap::getInstance()->getSqliteDir()); + $dsn = sprintf('sqlite:%s', Bootstrap::getInstance()->getSqliteDir()); $storage = new Pdo($dsn); $this->assertNotNull($storage->getClientDetails('oauth_test_client')); @@ -22,7 +23,8 @@ class PdoTest extends BaseTest public function testCreatePdoStorageUsingConfig() { - $config = array('dsn' => sprintf('sqlite://%s', Bootstrap::getInstance()->getSqliteDir())); + $dsn = sprintf('sqlite:%s', Bootstrap::getInstance()->getSqliteDir()); + $config = array('dsn' => $dsn); $storage = new Pdo($config); $this->assertNotNull($storage->getClientDetails('oauth_test_client')); diff --git a/vendor/bshaffer/oauth2-server-php/test/lib/OAuth2/Storage/Bootstrap.php b/vendor/bshaffer/oauth2-server-php/test/lib/OAuth2/Storage/Bootstrap.php index 3d7bdd4e9..8e428f9b5 100644 --- a/vendor/bshaffer/oauth2-server-php/test/lib/OAuth2/Storage/Bootstrap.php +++ b/vendor/bshaffer/oauth2-server-php/test/lib/OAuth2/Storage/Bootstrap.php @@ -36,7 +36,7 @@ class Bootstrap { if (!$this->sqlite) { $this->removeSqliteDb(); - $pdo = new \PDO(sprintf('sqlite://%s', $this->getSqliteDir())); + $pdo = new \PDO(sprintf('sqlite:%s', $this->getSqliteDir())); $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $this->createSqliteDb($pdo); diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 86acbb152..ff64c904f 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -380,9 +380,6 @@ return array( 'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerInterface.php', 'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerTrait.php', 'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/Psr/Log/NullLogger.php', - 'Psr\\Log\\Test\\DummyTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', - 'Psr\\Log\\Test\\LoggerInterfaceTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', - 'Psr\\Log\\Test\\TestLogger' => $vendorDir . '/psr/log/Psr/Log/Test/TestLogger.php', 'Ramsey\\Uuid\\BinaryUtils' => $vendorDir . '/ramsey/uuid/src/BinaryUtils.php', 'Ramsey\\Uuid\\Builder\\DefaultUuidBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/DefaultUuidBuilder.php', 'Ramsey\\Uuid\\Builder\\DegradedUuidBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/DegradedUuidBuilder.php', @@ -1343,6 +1340,8 @@ return array( 'Zotlabs\\Update\\_1226' => $baseDir . '/Zotlabs/Update/_1226.php', 'Zotlabs\\Update\\_1227' => $baseDir . '/Zotlabs/Update/_1227.php', 'Zotlabs\\Update\\_1228' => $baseDir . '/Zotlabs/Update/_1228.php', + 'Zotlabs\\Update\\_1229' => $baseDir . '/Zotlabs/Update/_1229.php', + 'Zotlabs\\Update\\_1230' => $baseDir . '/Zotlabs/Update/_1230.php', 'Zotlabs\\Web\\Controller' => $baseDir . '/Zotlabs/Web/Controller.php', 'Zotlabs\\Web\\HTTPHeaders' => $baseDir . '/Zotlabs/Web/HTTPHeaders.php', 'Zotlabs\\Web\\HTTPSig' => $baseDir . '/Zotlabs/Web/HTTPSig.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index ea23de753..69c31dd65 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -548,9 +548,6 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d 'Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerInterface.php', 'Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerTrait.php', 'Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/NullLogger.php', - 'Psr\\Log\\Test\\DummyTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', - 'Psr\\Log\\Test\\LoggerInterfaceTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', - 'Psr\\Log\\Test\\TestLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/TestLogger.php', 'Ramsey\\Uuid\\BinaryUtils' => __DIR__ . '/..' . '/ramsey/uuid/src/BinaryUtils.php', 'Ramsey\\Uuid\\Builder\\DefaultUuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/DefaultUuidBuilder.php', 'Ramsey\\Uuid\\Builder\\DegradedUuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/DegradedUuidBuilder.php', @@ -1511,6 +1508,8 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d 'Zotlabs\\Update\\_1226' => __DIR__ . '/../..' . '/Zotlabs/Update/_1226.php', 'Zotlabs\\Update\\_1227' => __DIR__ . '/../..' . '/Zotlabs/Update/_1227.php', 'Zotlabs\\Update\\_1228' => __DIR__ . '/../..' . '/Zotlabs/Update/_1228.php', + 'Zotlabs\\Update\\_1229' => __DIR__ . '/../..' . '/Zotlabs/Update/_1229.php', + 'Zotlabs\\Update\\_1230' => __DIR__ . '/../..' . '/Zotlabs/Update/_1230.php', 'Zotlabs\\Web\\Controller' => __DIR__ . '/../..' . '/Zotlabs/Web/Controller.php', 'Zotlabs\\Web\\HTTPHeaders' => __DIR__ . '/../..' . '/Zotlabs/Web/HTTPHeaders.php', 'Zotlabs\\Web\\HTTPSig' => __DIR__ . '/../..' . '/Zotlabs/Web/HTTPSig.php', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index d2f86ea99..7f829f6a4 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -58,17 +58,17 @@ }, { "name": "bshaffer/oauth2-server-php", - "version": "v1.10.0", - "version_normalized": "1.10.0.0", + "version": "v1.11.1", + "version_normalized": "1.11.1.0", "source": { "type": "git", "url": "https://github.com/bshaffer/oauth2-server-php.git", - "reference": "d158878425392fe5a0cc34f15dbaf46315ae0ed9" + "reference": "5a0c8000d4763b276919e2106f54eddda6bc50fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bshaffer/oauth2-server-php/zipball/d158878425392fe5a0cc34f15dbaf46315ae0ed9", - "reference": "d158878425392fe5a0cc34f15dbaf46315ae0ed9", + "url": "https://api.github.com/repos/bshaffer/oauth2-server-php/zipball/5a0c8000d4763b276919e2106f54eddda6bc50fa", + "reference": "5a0c8000d4763b276919e2106f54eddda6bc50fa", "shasum": "" }, "require": { @@ -89,7 +89,7 @@ "predis/predis": "Required to use Redis storage", "thobbs/phpcassa": "Required to use Cassandra storage" }, - "time": "2017-11-15T01:41:02+00:00", + "time": "2018-12-04T00:29:32+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -254,17 +254,17 @@ }, { "name": "league/html-to-markdown", - "version": "4.8.0", - "version_normalized": "4.8.0.0", + "version": "4.8.1", + "version_normalized": "4.8.1.0", "source": { "type": "git", "url": "https://github.com/thephpleague/html-to-markdown.git", - "reference": "f9a879a068c68ff47b722de63f58bec79e448f9d" + "reference": "250d1bf45f80d15594fb6b316df777d6d4c97ad1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/f9a879a068c68ff47b722de63f58bec79e448f9d", - "reference": "f9a879a068c68ff47b722de63f58bec79e448f9d", + "url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/250d1bf45f80d15594fb6b316df777d6d4c97ad1", + "reference": "250d1bf45f80d15594fb6b316df777d6d4c97ad1", "shasum": "" }, "require": { @@ -277,7 +277,7 @@ "phpunit/phpunit": "4.*", "scrutinizer/ocular": "~1.1" }, - "time": "2018-09-18T12:18:08+00:00", + "time": "2018-12-24T17:21:44+00:00", "bin": [ "bin/html-to-markdown" ], diff --git a/vendor/league/html-to-markdown/CHANGELOG.md b/vendor/league/html-to-markdown/CHANGELOG.md index ab07c94f5..e1893be9a 100644 --- a/vendor/league/html-to-markdown/CHANGELOG.md +++ b/vendor/league/html-to-markdown/CHANGELOG.md @@ -4,6 +4,14 @@ Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) princip ## [Unreleased][unreleased] +## [4.8.1] - 2018-12-24 +### Added + - Added support for PHP 7.3 + +### Fixed + - Fixed paragraphs following tables (#165, #166) + - Fixed incorrect list item escaping (#168, #169) + ## [4.8.0] - 2018-09-18 ### Added - Added support for email auto-linking @@ -235,7 +243,8 @@ not ideally set, so this releases fixes that. Moving forwards this should reduce ### Added - Initial release -[unreleased]: https://github.com/thephpleague/html-to-markdown/compare/4.8.0...master +[unreleased]: https://github.com/thephpleague/html-to-markdown/compare/4.8.1...master +[4.8.1]: https://github.com/thephpleague/html-to-markdown/compare/4.8.0...4.8.1 [4.8.0]: https://github.com/thephpleague/html-to-markdown/compare/4.7.0...4.8.0 [4.7.0]: https://github.com/thephpleague/html-to-markdown/compare/4.6.2...4.7.0 [4.6.2]: https://github.com/thephpleague/html-to-markdown/compare/4.6.1...4.6.2 diff --git a/vendor/league/html-to-markdown/src/Converter/DefaultConverter.php b/vendor/league/html-to-markdown/src/Converter/DefaultConverter.php index 964a71093..8de0af210 100644 --- a/vendor/league/html-to-markdown/src/Converter/DefaultConverter.php +++ b/vendor/league/html-to-markdown/src/Converter/DefaultConverter.php @@ -37,7 +37,13 @@ class DefaultConverter implements ConverterInterface, ConfigurationAwareInterfac return $element->getValue(); } - return html_entity_decode($element->getChildrenAsString()); + $markdown = html_entity_decode($element->getChildrenAsString()); + + if ($element->getTagName() === 'table') { + $markdown .= "\n\n"; + } + + return $markdown; } /** diff --git a/vendor/league/html-to-markdown/src/Converter/HardBreakConverter.php b/vendor/league/html-to-markdown/src/Converter/HardBreakConverter.php index d079d9127..1be10bd63 100644 --- a/vendor/league/html-to-markdown/src/Converter/HardBreakConverter.php +++ b/vendor/league/html-to-markdown/src/Converter/HardBreakConverter.php @@ -35,7 +35,10 @@ class HardBreakConverter implements ConverterInterface, ConfigurationAwareInterf $next_value = $next->getValue(); if ($next_value) { if (in_array(substr($next_value, 0, 2), array('- ', '* ', '+ '))) { - $return .= '\\'; + $parent = $element->getParent(); + if ($parent && $parent->getTagName() == 'li') { + $return .= '\\'; + } } } } From 8ac541e634838eb83e918f9c04cc0993602c473e Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 2 Jan 2019 23:33:33 -0800 Subject: [PATCH 53/93] better handling of notification updates while commenting --- view/js/main.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/view/js/main.js b/view/js/main.js index 0169ee54c..dcd04f053 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -888,7 +888,12 @@ function liveUpdate(notify_id) { if((src === null) || (stopped) || (! profile_uid)) { $('.like-rotator').hide(); return; } - if(in_progress || mediaPlaying) { + // if auto updates are enabled and a comment box is open, + // prevent live updates until the comment is submitted + + var lockUpdates = (($('.comment-edit-text.expanded').length && (! bParam_static)) ? true : false); + + if(lockUpdates || in_progress || mediaPlaying) { if(livetime) { clearTimeout(livetime); } From 3bf1866f4a7a619cedb445cd3e8a2ef9e827fa46 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Thu, 3 Jan 2019 17:13:40 +0100 Subject: [PATCH 54/93] Revert "Merge branch 'check_content_type' into 'dev'" This reverts merge request !1453 --- include/photo/photo_driver.php | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php index 608237ce1..9aeb2ef17 100644 --- a/include/photo/photo_driver.php +++ b/include/photo/photo_driver.php @@ -482,6 +482,7 @@ function guess_image_type($filename, $headers = '') { // logger('Photo: guess_image_type: '.$filename . ($headers?' from curl headers':''), LOGGER_DEBUG); $type = null; if ($headers) { + $hdrs=array(); $h = explode("\n",$headers); foreach ($h as $l) { @@ -489,16 +490,11 @@ function guess_image_type($filename, $headers = '') { $hdrs[strtolower($k)] = $v; } logger('Curl headers: '.var_export($hdrs, true), LOGGER_DEBUG); - if (array_key_exists('content-type', $hdrs)) { + if (array_key_exists('content-type', $hdrs)) $type = $hdrs['content-type']; - - $ph = photo_factory(''); - $types = $ph->supportedTypes(); - - $type = $types[$type]; - } } if (is_null($type)){ + $ignore_imagick = get_config('system', 'ignore_imagick'); // Guessing from extension? Isn't that... dangerous? if(class_exists('Imagick') && file_exists($filename) && is_readable($filename) && !$ignore_imagick) { @@ -642,6 +638,7 @@ function import_xchan_photo($photo,$xchan,$thing = false,$force = false) { $img_str = $result['body']; $type = guess_image_type($photo, $result['header']); $modified = gmdate('Y-m-d H:i:s', (preg_match('/last-modified: (.+) \S+/i', $result['header'], $o) ? strtotime($o[1] . 'Z') : time())); + if(is_null($type)) $photo_failure = true; } From ab9b8b8b0aa29c05acc627dac4989244959b9a39 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 3 Jan 2019 19:13:56 +0100 Subject: [PATCH 55/93] fix content type check --- include/photo/photo_driver.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php index 9aeb2ef17..84943bc27 100644 --- a/include/photo/photo_driver.php +++ b/include/photo/photo_driver.php @@ -482,7 +482,6 @@ function guess_image_type($filename, $headers = '') { // logger('Photo: guess_image_type: '.$filename . ($headers?' from curl headers':''), LOGGER_DEBUG); $type = null; if ($headers) { - $hdrs=array(); $h = explode("\n",$headers); foreach ($h as $l) { @@ -490,11 +489,16 @@ function guess_image_type($filename, $headers = '') { $hdrs[strtolower($k)] = $v; } logger('Curl headers: '.var_export($hdrs, true), LOGGER_DEBUG); - if (array_key_exists('content-type', $hdrs)) - $type = $hdrs['content-type']; - } - if (is_null($type)){ + if (array_key_exists('content-type', $hdrs)) { + $ph = photo_factory(''); + $types = $ph->supportedTypes(); + if(array_key_exists($hdrs['content-type'], $types) + $type = $hdrs['content-type']; + } + } + + if (is_null($type)){ $ignore_imagick = get_config('system', 'ignore_imagick'); // Guessing from extension? Isn't that... dangerous? if(class_exists('Imagick') && file_exists($filename) && is_readable($filename) && !$ignore_imagick) { @@ -638,7 +642,6 @@ function import_xchan_photo($photo,$xchan,$thing = false,$force = false) { $img_str = $result['body']; $type = guess_image_type($photo, $result['header']); $modified = gmdate('Y-m-d H:i:s', (preg_match('/last-modified: (.+) \S+/i', $result['header'], $o) ? strtotime($o[1] . 'Z') : time())); - if(is_null($type)) $photo_failure = true; } From b93bc142d3e6efa050d8cd75b367f607ee88eb2e Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 3 Jan 2019 19:18:49 +0100 Subject: [PATCH 56/93] missing closing parenthesis --- include/photo/photo_driver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php index 84943bc27..5c8ed9bdc 100644 --- a/include/photo/photo_driver.php +++ b/include/photo/photo_driver.php @@ -493,7 +493,7 @@ function guess_image_type($filename, $headers = '') { $ph = photo_factory(''); $types = $ph->supportedTypes(); - if(array_key_exists($hdrs['content-type'], $types) + if(array_key_exists($hdrs['content-type'], $types)) $type = $hdrs['content-type']; } } From 6f93001658e6c3a6c97f2be325622eb531104392 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 7 Jan 2019 09:47:08 +0100 Subject: [PATCH 57/93] fix issue with IE --- view/js/main.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/view/js/main.js b/view/js/main.js index dcd04f053..ca9ad8ca4 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -239,7 +239,11 @@ function handle_comment_form(e) { },10000); }); - function commentSaveChanges(convId,isFinal = false) { + function commentSaveChanges(convId, isFinal) { + + if(typeof isFinal === 'undefined') + isFinal = false; + if(auto_save_draft) { tmp = $('#' + emptyCommentElm).val(); if(tmp) { From 312e0dcbc813cdeea86e6ad9a0736f32b828c392 Mon Sep 17 00:00:00 2001 From: Mario Date: Mon, 7 Jan 2019 17:09:00 +0100 Subject: [PATCH 58/93] Update bbcode --- include/bbcode.php | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/include/bbcode.php b/include/bbcode.php index 817986da0..7531bd774 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -326,22 +326,11 @@ function bb_ShareAttributes($match) { $auth = is_matrix_url($profile); } - // message_id is never used, do we still need it? - $message_id = ""; - preg_match("/message_id='(.*?)'/ism", $attributes, $matches); - if ($matches[1] != "") - $message_id = $matches[1]; - - if(! $message_id) { - preg_match("/guid='(.*?)'/ism", $attributes, $matches); - if ($matches[1] != "") - $message_id = $matches[1]; - } - + $rnd = mt_rand(); $reldate = '' . datetime_convert('UTC', date_default_timezone_get(), $posted, 'r') . ''; - $headline = '
'; + $headline = '
'; if ($avatar != "") $headline .= '' . $author . ''; @@ -363,7 +352,7 @@ function bb_ShareAttributes($match) { $headline .= '' . $fmt . '
'; - $text = $headline . '
' . trim($match[2]) . '
'; + $text = $headline . '
' . trim($match[2]) . '
'; return $text; } From 563a5088be7e0c439e244ab9513404a97c3d6c44 Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Mon, 7 Jan 2019 19:48:14 -0500 Subject: [PATCH 59/93] Tweak to deal with changes that may happen within the same second. --- Zotlabs/Lib/PConfig.php | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Zotlabs/Lib/PConfig.php b/Zotlabs/Lib/PConfig.php index 5e5954c95..69f4de2db 100644 --- a/Zotlabs/Lib/PConfig.php +++ b/Zotlabs/Lib/PConfig.php @@ -131,14 +131,19 @@ class PConfig { $dbvalue = ((is_array($value)) ? serialize($value) : $value); $dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue); + $now = datetime_convert(); if (! $updated) { - $updated = datetime_convert(); + //Sometimes things happen fast... very fast. + //To make sure legitimate updates aren't rejected + //because not enough time has passed. We say our updates + //happened just a short time in the past rather than right now. + $updated = datetime_convert('UTC','UTC','-2 seconds'); } $hash = hash('sha256',$family.':'.$key); if (self::Get($uid, 'hz_delpconfig', $hash) !== false) { - if (self::Get($uid, 'hz_delpconfig', $hash) > $updated) { + if (self::Get($uid, 'hz_delpconfig', $hash) > $now) { logger('Refusing to update pconfig with outdated info (Item deleted more recently).', LOGGER_NORMAL, LOG_ERR); return self::Get($uid,$family,$key); } else { @@ -173,7 +178,7 @@ class PConfig { } else { - $new = (\App::$config[$uid][$family]['pcfgud:'.$key] < $updated); + $new = (\App::$config[$uid][$family]['pcfgud:'.$key] < $now); if ($new) { @@ -241,9 +246,9 @@ class PConfig { if(is_null($uid) || $uid === false) return false; - $updated = ($updated) ? $updated : datetime_convert(); - - $newer = (\App::$config[$uid][$family]['pcfgud:'.$key] < $updated); + $updated = ($updated) ? $updated : datetime_convert('UTC','UTC','-2 seconds'); + $now = datetime_convert(); + $newer = (\App::$config[$uid][$family]['pcfgud:'.$key] < $now); if (! $newer) { logger('Refusing to delete pconfig with outdated delete request.', LOGGER_NORMAL, LOG_ERR); From 06beb596283ee999e6b95b4a5eec9a6f948af962 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Tue, 8 Jan 2019 15:23:08 +0100 Subject: [PATCH 60/93] slightly improve item.is_new rendering --- view/tpl/conv_item.tpl | 6 +++--- view/tpl/conv_list.tpl | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/view/tpl/conv_item.tpl b/view/tpl/conv_item.tpl index 7dddf9c01..69e09b272 100755 --- a/view/tpl/conv_item.tpl +++ b/view/tpl/conv_item.tpl @@ -9,12 +9,12 @@
{{if $item.photo}} -
+
{{$item.photo}}
{{/if}} {{if $item.event}} -
+
{{$item.event}}
{{/if}} @@ -26,7 +26,7 @@
{{/if}} {{/if}} -
+
{{$item.name}} diff --git a/view/tpl/conv_list.tpl b/view/tpl/conv_list.tpl index c6da3d8a4..28e120d17 100755 --- a/view/tpl/conv_list.tpl +++ b/view/tpl/conv_list.tpl @@ -9,12 +9,12 @@
{{if $item.photo}} -
+
{{$item.photo}}
{{/if}} {{if $item.event}} -
+
{{$item.event}}
{{/if}} @@ -26,7 +26,7 @@
{{/if}} {{/if}} -
+
{{$item.name}} From 39de8e28da6f24530ee898d6b7a89e96547d283e Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 8 Jan 2019 14:14:55 -0800 Subject: [PATCH 61/93] make Apps::get_base_apps() pluggable --- Zotlabs/Lib/Apps.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 8cf62c01a..de7439ed7 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -57,7 +57,7 @@ class Apps { } static public function get_base_apps() { - return get_config('system','base_apps',[ + $x = get_config('system','base_apps',[ 'Connections', 'Network', 'Settings', @@ -72,6 +72,8 @@ class Apps { 'Mail', 'Profile Photo' ]); + call_hooks('get_base_apps',$x); + return $x; } static public function import_system_apps() { From 5d88326915790305b5ff6c4f8d6039d4171ac478 Mon Sep 17 00:00:00 2001 From: "M. Dent" Date: Wed, 9 Jan 2019 10:16:53 +0100 Subject: [PATCH 62/93] Remove Experimental Worker Queue from CORE - add hook 'daemon_master_release' --- Zotlabs/Daemon/Master.php | 135 ++++-------------------------- doc/hook/daemon_master_release.bb | 5 ++ doc/hooklist.bb | 3 + 3 files changed, 22 insertions(+), 121 deletions(-) create mode 100644 doc/hook/daemon_master_release.bb diff --git a/Zotlabs/Daemon/Master.php b/Zotlabs/Daemon/Master.php index 0656ca05b..857d47243 100644 --- a/Zotlabs/Daemon/Master.php +++ b/Zotlabs/Daemon/Master.php @@ -16,8 +16,6 @@ if(array_search( __file__ , get_included_files()) === 0) { class Master { - static public $queueworker = null; - static public function Summon($arr) { proc_run('php','Zotlabs/Daemon/Master.php',$arr); } @@ -25,126 +23,21 @@ class Master { static public function Release($argc,$argv) { cli_startup(); - $maxworkers = get_config('system','max_queue_workers'); + $hookinfo = [ + 'argv'=>$argv + ]; - if (!$maxworkers || $maxworkers == 0) { - logger('Master: release: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG); - $cls = '\\Zotlabs\\Daemon\\' . $argv[0]; - $cls::run($argc,$argv); - self::ClearQueue(); - } else { - logger('Master: enqueue: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG); - $workinfo = ['argc'=>$argc,'argv'=>$argv]; - q("insert into config (cat,k,v) values ('queuework','%s','%s')", - dbesc(uniqid('workitem:',true)), - dbesc(serialize($workinfo))); - self::Process(); + call_hooks ('daemon_master_release',$hookinfo); + + $argv = $hookinfo['argv']; + $argc = count($argv); + + if ((!is_array($argv) || (count($argv) < 1))) { + return; } + + logger('Master: release: ' . json_encode($argv), LOGGER_ALL,LOG_DEBUG); + $cls = '\\Zotlabs\\Daemon\\' . $argv[0]; + $cls::run($argc,$argv); } - - static public function GetWorkerID() { - $maxworkers = get_config('system','max_queue_workers'); - $maxworkers = ($maxworkers) ? $maxworkers : 3; - - $workermaxage = get_config('system','max_queue_worker_age'); - $workermaxage = ($workermaxage) ? $workermaxage : 300; - - $workers = q("select * from config where cat='queueworkers' and k like '%s'", 'workerstarted_%'); - - if (count($workers) > $maxworkers) { - foreach ($workers as $idx => $worker) { - $curtime = time(); - $age = (intval($curtime) - intval($worker['v'])); - if ( $age > $workermaxage) { - logger("Prune worker: ".$worker['k'], LOGGER_ALL, LOGGER_DEBUG); - $k = explode('_',$worker['k']); - q("delete from config where cat='queueworkers' and k='%s'", - 'workerstarted_'.$k[1]); - q("update config set k='%s' where cat='queuework' and k='%s'", - dbesc(uniqid('workitem:',true)), - 'workitem_'.$k[1]); - unset($workers[$idx]); - } - } - if (count($workers) > $maxworkers) { - return false; - } - } - return uniqid('',true); - - } - - static public function Process() { - - self::$queueworker = self::GetWorkerID(); - - if (!self::$queueworker) { - logger('Master: unable to obtain worker ID.'); - killme(); - } - - set_config('queueworkers','workerstarted_'.self::$queueworker,time()); - - $workersleep = get_config('system','queue_worker_sleep'); - $workersleep = ($workersleep) ? $workersleep : 5; - cli_startup(); - - $work = q("update config set k='%s' where cat='queuework' and k like '%s' limit 1", - 'workitem_'.self::$queueworker, - dbesc('workitem:%')); - $jobs = 0; - while ($work) { - $workitem = q("select * from config where cat='queuework' and k='%s'", - 'workitem_'.self::$queueworker); - - if (isset($workitem[0])) { - $jobs++; - $workinfo = unserialize($workitem[0]['v']); - $argc = $workinfo['argc']; - $argv = $workinfo['argv']; - logger('Master: process: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG); - - //Delete unclaimed duplicate workitems. - q("delete from config where cat='queuework' and k='workitem' and v='%s'", - serialize($argv)); - - $cls = '\\Zotlabs\\Daemon\\' . $argv[0]; - $cls::run($argc,$argv); - - //Right now we assume that if we get a return, everything is OK. - //At some point we may want to test whether the run returns true/false - // and requeue the work to be tried again. But we probably want - // to implement some sort of "retry interval" first. - - q("delete from config where cat='queuework' and k='%s'", - 'workitem_'.self::$queueworker); - } else { - break; - } - sleep ($workersleep); - $work = q("update config set k='%s' where cat='queuework' and k like '%s' limit 1", - 'workitem_'.self::$queueworker, - dbesc('workitem:%')); - - } - logger('Master: Worker Thread: queue items processed:' . $jobs); - q("delete from config where cat='queueworkers' and k='%s'", - 'workerstarted_'.self::$queueworker); - } - - static public function ClearQueue() { - $work = q("select * from config where cat='queuework' and k like '%s'", - dbesc('workitem%')); - foreach ($work as $workitem) { - $workinfo = unserialize($workitem['v']); - $argc = $workinfo['argc']; - $argv = $workinfo['argv']; - logger('Master: process: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG); - $cls = '\\Zotlabs\\Daemon\\' . $argv[0]; - $cls::run($argc,$argv); - } - $work = q("delete from config where cat='queuework' and k like '%s'", - dbesc('workitem%')); - } - } diff --git a/doc/hook/daemon_master_release.bb b/doc/hook/daemon_master_release.bb new file mode 100644 index 000000000..a17216d48 --- /dev/null +++ b/doc/hook/daemon_master_release.bb @@ -0,0 +1,5 @@ +[h2]daemon_master_release[/h2] + +Permit filtering or alternate methods of processing of background processes when [code] \Zotlabs\Daemon\Master::Release() [/code] is called. + +Default behavior is for a new PHP process to fire immediately upon a call to Master::Summon(). This hook permits pre-emption and the ability to provide queuing or other alternatives to this procedure. diff --git a/doc/hooklist.bb b/doc/hooklist.bb index 08fc587e2..afb2cebee 100644 --- a/doc/hooklist.bb +++ b/doc/hooklist.bb @@ -190,6 +190,9 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the [zrl=[baseurl]/help/hook/daemon_addon]daemon_addon[/zrl] Called when invoking the extensible background daemon +[zrl=[baseurl]/help/hook/daemon_master_release]daemon_master_release[/zrl] + Called at the start of processing \Zotlabs\Daemon\Master::Release() + [zrl=[baseurl]/help/hook/directory_item]directory_item[/zrl] Called when generating a directory listing for display From 90b6afe06bacd5377c638c89045801296d69ec44 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 10 Jan 2019 00:29:05 +0100 Subject: [PATCH 63/93] we must sslify all possible content variables --- include/text.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/text.php b/include/text.php index 3cc21e4ce..26cb61977 100644 --- a/include/text.php +++ b/include/text.php @@ -1691,7 +1691,14 @@ function prepare_body(&$item,$attach = false,$opts = false) { if(local_channel() == $item['uid']) $filer = format_filer($item); - $s = sslify($s); + if($s) + $s = sslify($s); + + if($photo) + $photo = sslify($photo); + + if($event) + $event = sslify($event); $prep_arr = array( 'item' => $item, From 01f4ce96f1fe835db774acffb65b2553e1b44c0a Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 10 Jan 2019 13:35:27 +0100 Subject: [PATCH 64/93] do not count removed channels --- Zotlabs/Module/New_channel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Module/New_channel.php b/Zotlabs/Module/New_channel.php index 73cdf4c8c..98aa480fe 100644 --- a/Zotlabs/Module/New_channel.php +++ b/Zotlabs/Module/New_channel.php @@ -134,7 +134,7 @@ class New_channel extends \Zotlabs\Web\Controller { $default_role = ''; $aid = get_account_id(); if($aid) { - $r = q("select count(channel_id) as total from channel where channel_account_id = %d", + $r = q("select count(channel_id) as total from channel where channel_account_id = %d and channel_removed = 0", intval($aid) ); if($r && (! intval($r[0]['total']))) { From b54ddccd7beece51d78b21b4ba9e98c908fec4c5 Mon Sep 17 00:00:00 2001 From: ZotSocial Admin Date: Wed, 9 Jan 2019 21:23:12 -0500 Subject: [PATCH 65/93] FIX: memory exhaustion on exceptionally large message queues & multiple Queue.php invocations duplicate work --- Zotlabs/Daemon/Queue.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Zotlabs/Daemon/Queue.php b/Zotlabs/Daemon/Queue.php index 8f529ff13..e041804f0 100644 --- a/Zotlabs/Daemon/Queue.php +++ b/Zotlabs/Daemon/Queue.php @@ -61,10 +61,18 @@ class Queue { // or just prior to this query based on recent and long-term delivery history. If we have good reason to believe // the site is permanently down, there's no reason to attempt delivery at all, or at most not more than once // or twice a day. - - $r = q("SELECT * FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s ", + + $r = q("SELECT *,RAND() as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1", db_utcnow() ); + while ($r) { + foreach($r as $rv) { + queue_deliver($rv); + } + $r = q("SELECT *,RAND() as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1", + db_utcnow() + ); + } } if(! $r) return; From 6791b05a4032a076651f7c8e4790614f0f405a55 Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Thu, 10 Jan 2019 15:29:24 -0500 Subject: [PATCH 66/93] Fix for PGSQL/MYSQL difference --- Zotlabs/Daemon/Queue.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Zotlabs/Daemon/Queue.php b/Zotlabs/Daemon/Queue.php index e041804f0..6b525b8c3 100644 --- a/Zotlabs/Daemon/Queue.php +++ b/Zotlabs/Daemon/Queue.php @@ -12,6 +12,15 @@ class Queue { require_once('include/items.php'); require_once('include/bbcode.php'); + switch (DBTYPE_ACTIVE) { + case DBTYPE_MYSQL: + $sqlrandfunc = "RAND()"; + break; + + case DBTYPE_POSTGRESQL: + $sqlrandfunc = "RANDOM()"; + break; + } if($argc > 1) $queue_id = $argv[1]; @@ -62,14 +71,14 @@ class Queue { // the site is permanently down, there's no reason to attempt delivery at all, or at most not more than once // or twice a day. - $r = q("SELECT *,RAND() as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1", + $r = q("SELECT *,$sqlrandfunc as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1", db_utcnow() ); while ($r) { foreach($r as $rv) { queue_deliver($rv); } - $r = q("SELECT *,RAND() as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1", + $r = q("SELECT *,$sqlrandfunc as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1", db_utcnow() ); } From 7b30fc4b82da0a64e152cdeb82564f8d52b7177e Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 10 Jan 2019 15:02:58 -0800 Subject: [PATCH 67/93] failure to import mail --- include/import.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/import.php b/include/import.php index 53b21c317..3bd8b4105 100644 --- a/include/import.php +++ b/include/import.php @@ -1035,8 +1035,9 @@ function import_mail($channel, $mails, $sync = false) { if(! $m) continue; - $m['aid'] = $channel['channel_account_id']; - $m['uid'] = $channel['channel_id']; + $m['account_id'] = $channel['channel_account_id']; + $m['channel_id'] = $channel['channel_id']; + $mail_id = mail_store($m); if($sync && $mail_id) { Zotlabs\Daemon\Master::Summon(array('Notifier','single_mail',$mail_id)); From caf2c0a6c43f3162fc8f4d758eb06cb2f56b3865 Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Fri, 11 Jan 2019 07:35:12 -0500 Subject: [PATCH 68/93] Use dba_driver.php::db_getfunc() --- Zotlabs/Daemon/Queue.php | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Zotlabs/Daemon/Queue.php b/Zotlabs/Daemon/Queue.php index 6b525b8c3..814148404 100644 --- a/Zotlabs/Daemon/Queue.php +++ b/Zotlabs/Daemon/Queue.php @@ -12,16 +12,6 @@ class Queue { require_once('include/items.php'); require_once('include/bbcode.php'); - switch (DBTYPE_ACTIVE) { - case DBTYPE_MYSQL: - $sqlrandfunc = "RAND()"; - break; - - case DBTYPE_POSTGRESQL: - $sqlrandfunc = "RANDOM()"; - break; - } - if($argc > 1) $queue_id = $argv[1]; else @@ -71,6 +61,8 @@ class Queue { // the site is permanently down, there's no reason to attempt delivery at all, or at most not more than once // or twice a day. + $sqlrandfunc = db_getfunc('rand'); + $r = q("SELECT *,$sqlrandfunc as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1", db_utcnow() ); From 8aa117e4ae550db2c156cec6431098700929ff5f Mon Sep 17 00:00:00 2001 From: "M. Dent" Date: Sat, 12 Jan 2019 09:22:37 +0100 Subject: [PATCH 69/93] FIX: memory exhaustion on zot message pickup with large message queue --- include/zot.php | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/include/zot.php b/include/zot.php index 9934dae07..6d9b6aeec 100644 --- a/include/zot.php +++ b/include/zot.php @@ -4924,12 +4924,13 @@ function zot_reply_pickup($data) { /* * Everything is good if we made it here, so find all messages that are going to this location - * and send them all. + * and send them all - or a reasonable number if there are a lot so we don't overflow memory. */ - $r = q("select * from outq where outq_posturl = '%s'", + $r = q("select * from outq where outq_posturl = '%s' limit 100", dbesc($data['callback']) ); + if($r) { logger('mod_zot: successful pickup message received from ' . $data['callback'] . ' ' . count($r) . ' message(s) picked up', LOGGER_DEBUG); @@ -4955,6 +4956,19 @@ function zot_reply_pickup($data) { } } + // It's possible that we have more than 100 messages waiting to be sent. + + // See if there are any more messages in the queue. + $x = q("select *,min(outq_created) as earliest from outq where outq_posturl = '%s'", + dbesc($data['callback']) + ); + + // If so, kick off a new delivery notification for the next batch + if ($x) { + logger("Send additional pickup request.", LOGGER_DEBUG); + queue_deliver($x[0],true); + } + // this is a bit of a hack because we don't have the hubloc_url here, only the callback url. // worst case is we'll end up using aes256cbc if they've got a different post endpoint @@ -4966,6 +4980,8 @@ function zot_reply_pickup($data) { $encrypted = crypto_encapsulate(json_encode($ret),$sitekey,$algorithm); json_return_and_die($encrypted); + // @FIXME: There is a possibility that the transmission will get interrupted + // and fail - in which case this packet of messages will be lost. /* pickup: end */ } From 598cbf2210ed6c978ff30be58f0909aa9f93a049 Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Sat, 12 Jan 2019 22:37:44 -0500 Subject: [PATCH 70/93] Add collect_public_recipients hook --- doc/hook/collect_public_recipients.bb | 42 +++++++++++++++++++++++++++ doc/hooklist.bb | 3 ++ include/items.php | 19 ++++++++++-- 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 doc/hook/collect_public_recipients.bb diff --git a/doc/hook/collect_public_recipients.bb b/doc/hook/collect_public_recipients.bb new file mode 100644 index 000000000..de3f4049e --- /dev/null +++ b/doc/hook/collect_public_recipients.bb @@ -0,0 +1,42 @@ +[h2]collect_public_recipients[/h2] + +Replace the default list of public recipients (i.e., all contacts). + +Allow plugins to create a list of recipients for public messages instead of the default +of all channel connections. + +Called with the following array: + [ + 'recipients' => [], + 'item' => $item, + 'private_envelope' => $private_envelope, + 'include_groups' => $include_groups + ]; + +[code] + if(array_key_exists('public_policy',$item) && $item['public_policy'] !== 'self') { + + $hookinfo = [ + 'recipients' => [], + 'item' => $item, + 'private_envelope' => $private_envelope, + 'include_groups' => $include_groups + ]; + + call_hooks('collect_public_recipients',$hookinfo); + + if ($hookinfo['recipients']) { + $r = $hookinfo['recipients']; + } else { + $r = q("select abook_xchan, xchan_network from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and abook_pending = 0 and abook_archived = 0 ", + intval($item['uid']) + ); + } + + if($r) { + + . . . + +[/code] + +see: include/item.php diff --git a/doc/hooklist.bb b/doc/hooklist.bb index afb2cebee..f7dbf3fa0 100644 --- a/doc/hooklist.bb +++ b/doc/hooklist.bb @@ -136,6 +136,9 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the [zrl=[baseurl]/help/hook/check_siteallowed]check_siteallowed[/zrl] Used to over-ride or bypass the site black/white block lists +[zrl=[baseurl]/help/hook/collect_public_recipients]collect_public_recipients[/zrl] + Used to establish a list of recipients to send a public message to. + [zrl=[baseurl]/help/hook/comment_buttons]comment_buttons[/zrl] Called when rendering the edit buttons for comments diff --git a/include/items.php b/include/items.php index 02d31fcb5..e5f2be003 100755 --- a/include/items.php +++ b/include/items.php @@ -95,9 +95,24 @@ function collect_recipients($item, &$private_envelope,$include_groups = true) { //$sys = get_sys_channel(); if(array_key_exists('public_policy',$item) && $item['public_policy'] !== 'self') { - $r = q("select abook_xchan, xchan_network from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and abook_pending = 0 and abook_archived = 0 ", + + $hookinfo = [ + 'recipients' => [], + 'item' => $item, + 'private_envelope' => $private_envelope, + 'include_groups' => $include_groups + ]; + + call_hooks('collect_public_recipients',$hookinfo); + + if ($hookinfo['recipients']) { + $r = $hookinfo['recipients']; + } else { + $r = q("select abook_xchan, xchan_network from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and abook_pending = 0 and abook_archived = 0 ", intval($item['uid']) - ); + ); + } + if($r) { // filter out restrictive public_policy settings from remote networks From 121fa834d56ab3496c82d4d6c5fd8ba70743c26a Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Sun, 13 Jan 2019 14:06:36 -0500 Subject: [PATCH 71/93] FIX: aggregated query error in MYSQL --- include/zot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zot.php b/include/zot.php index 6d9b6aeec..f2aa58ee7 100644 --- a/include/zot.php +++ b/include/zot.php @@ -4959,7 +4959,7 @@ function zot_reply_pickup($data) { // It's possible that we have more than 100 messages waiting to be sent. // See if there are any more messages in the queue. - $x = q("select *,min(outq_created) as earliest from outq where outq_posturl = '%s'", + $x = q("select * from outq order by outq_scheduled where outq_posturl = '%s' limit 1", dbesc($data['callback']) ); From ab074f52fece902d1057f531c5289562a7d5343f Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Sun, 13 Jan 2019 14:10:35 -0500 Subject: [PATCH 72/93] outq_created not outq_scheduled --- include/zot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zot.php b/include/zot.php index f2aa58ee7..7467eccde 100644 --- a/include/zot.php +++ b/include/zot.php @@ -4959,7 +4959,7 @@ function zot_reply_pickup($data) { // It's possible that we have more than 100 messages waiting to be sent. // See if there are any more messages in the queue. - $x = q("select * from outq order by outq_scheduled where outq_posturl = '%s' limit 1", + $x = q("select * from outq order by outq_created where outq_posturl = '%s' limit 1", dbesc($data['callback']) ); From dba9c2fbb01c3d9de1d25aeb7c86a9be0e5031cf Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Sun, 13 Jan 2019 14:34:04 -0500 Subject: [PATCH 73/93] Add pgrp_extras hook & display --- Zotlabs/Module/Group.php | 5 +++++ view/tpl/privacy_groups.tpl | 1 + 2 files changed, 6 insertions(+) diff --git a/Zotlabs/Module/Group.php b/Zotlabs/Module/Group.php index c8ccaa2cb..6f3d09662 100644 --- a/Zotlabs/Module/Group.php +++ b/Zotlabs/Module/Group.php @@ -127,6 +127,10 @@ class Group extends Controller { $i++; } + $hookinfo = [ 'pgrp_extras' => '', 'group'=>$argv(1) ]; + call_hooks ('privacygroup_extras',$hookinfo); + $pgrp_extras = $hookinfo['pgrp_extras']; + $tpl = get_markup_template('privacy_groups.tpl'); $o = replace_macros($tpl, [ '$title' => t('Privacy Groups'), @@ -136,6 +140,7 @@ class Group extends Controller { // new group form '$gname' => array('groupname',t('Privacy group name')), '$public' => array('public',t('Members are visible to other channels'), false), + '$pgrp_extras' => $pgrp_extras, '$form_security_token' => get_form_security_token("group_edit"), '$submit' => t('Submit'), diff --git a/view/tpl/privacy_groups.tpl b/view/tpl/privacy_groups.tpl index b4e27ef2c..327a15aee 100644 --- a/view/tpl/privacy_groups.tpl +++ b/view/tpl/privacy_groups.tpl @@ -8,6 +8,7 @@ {{include file="field_input.tpl" field=$gname}} {{include file="field_checkbox.tpl" field=$public}} + {{$pgrp_extras}}
From b4c1ca88f32420cc1653e11811bad74d6f0231a5 Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Sun, 13 Jan 2019 14:41:44 -0500 Subject: [PATCH 74/93] move order by and rewrite similar in update_queue_item() --- include/queue_fn.php | 4 ++-- include/zot.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/queue_fn.php b/include/queue_fn.php index f7e2922c6..85f98aaf9 100644 --- a/include/queue_fn.php +++ b/include/queue_fn.php @@ -13,7 +13,7 @@ function update_queue_item($id, $add_priority = 0) { return; - $y = q("select min(outq_created) as earliest from outq where outq_posturl = '%s'", + $y = q("select outq_created as earliest from outq where outq_posturl = '%s' order by earliest limit 1", dbesc($x[0]['outq_posturl']) ); @@ -311,4 +311,4 @@ function queue_deliver($outq, $immediate = false) { return; } -} \ No newline at end of file +} diff --git a/include/zot.php b/include/zot.php index 7467eccde..df54f2b27 100644 --- a/include/zot.php +++ b/include/zot.php @@ -4959,7 +4959,7 @@ function zot_reply_pickup($data) { // It's possible that we have more than 100 messages waiting to be sent. // See if there are any more messages in the queue. - $x = q("select * from outq order by outq_created where outq_posturl = '%s' limit 1", + $x = q("select * from outq where outq_posturl = '%s' order by outq_created limit 1", dbesc($data['callback']) ); From e43331b7a2c0136a9c576b4cc0391f66d469b4cd Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Sun, 13 Jan 2019 15:43:25 -0500 Subject: [PATCH 75/93] Add privacygroup_extras_post/drop hooks --- Zotlabs/Module/Group.php | 9 ++++++++- doc/hook/privacygroup_extras.bb | 12 ++++++++++++ doc/hook/privacygroup_extras_drop.bb | 11 +++++++++++ doc/hook/privacygroup_extras_post.bb | 11 +++++++++++ doc/hooklist.bb | 9 +++++++++ 5 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 doc/hook/privacygroup_extras.bb create mode 100644 doc/hook/privacygroup_extras_drop.bb create mode 100644 doc/hook/privacygroup_extras_post.bb diff --git a/Zotlabs/Module/Group.php b/Zotlabs/Module/Group.php index 6f3d09662..8c5e4f943 100644 --- a/Zotlabs/Module/Group.php +++ b/Zotlabs/Module/Group.php @@ -75,6 +75,10 @@ class Group extends Controller { ); if($r) info( t('Privacy group updated.') . EOL ); + + $hookinfo = [ 'pgrp_extras' => '', 'group'=>$group['id'] ]; + call_hooks ('privacygroup_extras_post',$hookinfo); + build_sync_packet(local_channel(),null,true); } @@ -171,8 +175,11 @@ class Group extends Controller { ); if($r) $result = group_rmv(local_channel(),$r[0]['gname']); - if($result) + if($result) { + $hookinfo = [ 'pgrp_extras' => '', 'group'=>$argv(2) ]; + call_hooks ('privacygroup_extras_drop',$hookinfo); info( t('Privacy group removed.') . EOL); + } else notice( t('Unable to remove privacy group.') . EOL); } diff --git a/doc/hook/privacygroup_extras.bb b/doc/hook/privacygroup_extras.bb new file mode 100644 index 000000000..bd67f2470 --- /dev/null +++ b/doc/hook/privacygroup_extras.bb @@ -0,0 +1,12 @@ +[h2]privacygroup_extras[/h2] + +Add items to the Privacy Group edit form + +[code] + $hookinfo = [ 'pgrp_extras' => '', 'group'=>$argv(1) ]; + call_hooks ('privacygroup_extras',$hookinfo); + $pgrp_extras = $hookinfo['pgrp_extras']; +[/code] + +see: Zotlabs/Module/Group.php +see: view/tpl/privacy_groups.tpl diff --git a/doc/hook/privacygroup_extras_drop.bb b/doc/hook/privacygroup_extras_drop.bb new file mode 100644 index 000000000..fd27ab255 --- /dev/null +++ b/doc/hook/privacygroup_extras_drop.bb @@ -0,0 +1,11 @@ +[h2]privacygroup_extras_drop[/h2] + +Called after privacy group is dropped + +[code] + $hookinfo = [ 'pgrp_extras' => '', 'group'=>$argv(2) ]; + call_hooks ('privacygroup_extras_drop',$hookinfo); +[/code] + +see: Zotlabs/Module/Group.php +see: view/tpl/privacy_groups.tpl diff --git a/doc/hook/privacygroup_extras_post.bb b/doc/hook/privacygroup_extras_post.bb new file mode 100644 index 000000000..704db1997 --- /dev/null +++ b/doc/hook/privacygroup_extras_post.bb @@ -0,0 +1,11 @@ +[h2]privacygroup_extras_post[/h2] + +Called as privacy group edit form is edited. + +[code] + $hookinfo = [ 'pgrp_extras' => '', 'group'=>$group['id'] ]; + call_hooks ('privacygroup_extras_post',$hookinfo); +[/code] + +see: Zotlabs/Module/Group.php +see: view/tpl/privacy_groups.tpl diff --git a/doc/hooklist.bb b/doc/hooklist.bb index afb2cebee..298da5659 100644 --- a/doc/hooklist.bb +++ b/doc/hooklist.bb @@ -556,6 +556,15 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the [zrl=[baseurl]/help/hook/prepare_body_init]prepare_body_init[/zrl] Called before generating the HTML for a displayed conversation item +[zrl=[baseurl]/help/hook/privacygroup_extras]privacygroup_extras[/zrl] + Called before generating the HTML for the Privacy Group edit options + +[zrl=[baseurl]/help/hook/privacygroup_extras_delete]privacygroup_extras_delete[/zrl] + Called after privacy group is dropped. + +[zrl=[baseurl]/help/hook/privacygroup_extras_post]privacygroup_extras_post[/zrl] + Called when privacy group edit form is submitted. + [zrl=[baseurl]/help/hook/proc_run]proc_run[/zrl] Called when invoking PHP sub processes From f5e571ba40a7d3b98158af61b1ab649980bb8e27 Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Sun, 13 Jan 2019 20:04:12 -0500 Subject: [PATCH 76/93] Remove stray $ --- Zotlabs/Module/Group.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Module/Group.php b/Zotlabs/Module/Group.php index 8c5e4f943..3dcf903ad 100644 --- a/Zotlabs/Module/Group.php +++ b/Zotlabs/Module/Group.php @@ -131,7 +131,7 @@ class Group extends Controller { $i++; } - $hookinfo = [ 'pgrp_extras' => '', 'group'=>$argv(1) ]; + $hookinfo = [ 'pgrp_extras' => '', 'group'=>argv(1) ]; call_hooks ('privacygroup_extras',$hookinfo); $pgrp_extras = $hookinfo['pgrp_extras']; From f3554804bfe5bf88984bce925470934429567516 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 14 Jan 2019 10:14:37 +0100 Subject: [PATCH 77/93] only load new content onpopstate if the mid has actually changed --- view/tpl/notifications_widget.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/tpl/notifications_widget.tpl b/view/tpl/notifications_widget.tpl index 98047f1d9..bc7f80906 100644 --- a/view/tpl/notifications_widget.tpl +++ b/view/tpl/notifications_widget.tpl @@ -24,7 +24,7 @@ }); window.onpopstate = function(e) { - if(e.state !== null) + if(e.state !== null && e.state.b64mid !== bParam_mid) getData(e.state.b64mid, ''); }; }); From 7daf18b0771abbc483edf3e85c30c5df8bc82839 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 14 Jan 2019 14:07:56 +0100 Subject: [PATCH 78/93] fix a new instance of autocomplete created on each conversation update --- view/js/main.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/view/js/main.js b/view/js/main.js index ca9ad8ca4..017d39353 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -44,6 +44,17 @@ $(document).ready(function() { $(document).on('click', '.conversation-settings-link', getConversationSettings); $(document).on('click', '#settings_module_ajax_submit', postConversationSettings); + $(document).on('click focus', '.comment-edit-form textarea', function(e) { + if(! this.autocomplete_handled) { + /* autocomplete @nicknames */ + $(this).editor_autocomplete(baseurl+"/acl?f=&n=1"); + /* autocomplete bbcode */ + $(this).bbco_autocomplete('bbcode'); + + this.autocomplete_handled = true; + } + }); + var tf = new Function('n', 's', 'var k = s.split("/")['+aStr['plural_func']+']; return (k ? k : s);'); jQuery.timeago.settings.strings = { @@ -755,11 +766,6 @@ function updateConvItems(mode,data) { mediaPlaying = false; }); - /* autocomplete @nicknames */ - $(".comment-edit-form textarea").editor_autocomplete(baseurl+"/acl?f=&n=1"); - /* autocomplete bbcode */ - $(".comment-edit-form textarea").bbco_autocomplete('bbcode'); - var bimgs = ((preloadImages) ? false : $(".wall-item-body img").not(function() { return this.complete; })); var bimgcount = bimgs.length; From c26e112bee8c57c2a9d7d5f6f24ddca8de033c19 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 14 Jan 2019 15:06:21 +0100 Subject: [PATCH 79/93] whitespace --- view/js/autocomplete.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/view/js/autocomplete.js b/view/js/autocomplete.js index 6b77f0631..278a0a176 100644 --- a/view/js/autocomplete.js +++ b/view/js/autocomplete.js @@ -216,8 +216,6 @@ function string2bb(element) { }); textcomplete.register([contacts,forums,smilies,tags]); }); - - }; })( jQuery ); From ad6eb15eac2297d3ad058a587ad39ce2957ee637 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Tue, 15 Jan 2019 22:36:01 +0100 Subject: [PATCH 80/93] fix legacy zot dreport not passing the is_storable check --- Zotlabs/Lib/DReport.php | 9 +++++++-- Zotlabs/Lib/Libzot.php | 9 +++++++++ include/zot.php | 9 +++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/Zotlabs/Lib/DReport.php b/Zotlabs/Lib/DReport.php index 21b320cac..2cda7ce5d 100644 --- a/Zotlabs/Lib/DReport.php +++ b/Zotlabs/Lib/DReport.php @@ -93,11 +93,16 @@ class DReport { if(! $c) return false; + // legacy zot recipients add a space and their name to the xchan. remove it if true. + + $legacy_recipient = strpos($dr['recipient'], ' '); + if($legacy_recipient !== false) + $rxchan = substr($dr['recipient'], 0 , $legacy_recipient); + else + $rxchan = $dr['recipient']; // is the recipient one of our connections, or do we want to store every report? - - $rxchan = $dr['recipient']; $pcf = get_pconfig($c[0]['channel_id'],'system','dreport_store_all'); if($pcf) return true; diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index 87a5126f4..268622430 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -998,6 +998,15 @@ logger('4'); foreach($x['delivery_report'] as $xx) { call_hooks('dreport_process',$xx); if(is_array($xx) && array_key_exists('message_id',$xx) && DReport::is_storable($xx)) { + + // legacy recipients add a space and their name to the xchan. split those if true. + $legacy_recipient = strpos($xx['recipient'], ' '); + if($legacy_recipient !== false) { + $legacy_recipient_parts = explode(' ', $xx['recipient'], 2); + $xx['recipient'] = $legacy_recipient_parts[0]; + $xx['name'] = $legacy_recipient_parts[1]; + } + q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s', '%s','%s','%s','%s','%s' ) ", dbesc($xx['message_id']), dbesc($xx['location']), diff --git a/include/zot.php b/include/zot.php index df54f2b27..1741c1616 100644 --- a/include/zot.php +++ b/include/zot.php @@ -1123,6 +1123,15 @@ function zot_process_response($hub, $arr, $outq) { foreach($x['delivery_report'] as $xx) { call_hooks('dreport_process',$xx); if(is_array($xx) && array_key_exists('message_id',$xx) && DReport::is_storable($xx)) { + + // legacy zot recipients add a space and their name to the xchan. split those if true. + $legacy_recipient = strpos($xx['recipient'], ' '); + if($legacy_recipient !== false) { + $legacy_recipient_parts = explode(' ', $xx['recipient'], 2); + $xx['recipient'] = $legacy_recipient_parts[0]; + $xx['name'] = $legacy_recipient_parts[1]; + } + q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s','%s' ) ", dbesc($xx['message_id']), dbesc($xx['location']), From a1ac507a94b52c58c497f22be2b55d8d7b515cca Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 16 Jan 2019 10:02:13 +0100 Subject: [PATCH 81/93] change logic for consistency --- Zotlabs/Lib/DReport.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Zotlabs/Lib/DReport.php b/Zotlabs/Lib/DReport.php index 2cda7ce5d..ef1ce2678 100644 --- a/Zotlabs/Lib/DReport.php +++ b/Zotlabs/Lib/DReport.php @@ -96,10 +96,13 @@ class DReport { // legacy zot recipients add a space and their name to the xchan. remove it if true. $legacy_recipient = strpos($dr['recipient'], ' '); - if($legacy_recipient !== false) - $rxchan = substr($dr['recipient'], 0 , $legacy_recipient); - else + if($legacy_recipient !== false) { + $legacy_recipient_parts = explode(' ', $dr['recipient'], 2); + $rxchan = $legacy_recipient_parts[0]; + } + else { $rxchan = $dr['recipient']; + } // is the recipient one of our connections, or do we want to store every report? From 4450a01014c15a77c2e086c7d964a578b135cfba Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 16 Jan 2019 15:09:18 +0100 Subject: [PATCH 82/93] do not return if delivery report could not bedecrypted --- include/zot.php | 49 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/include/zot.php b/include/zot.php index df54f2b27..bc2187f91 100644 --- a/include/zot.php +++ b/include/zot.php @@ -1100,6 +1100,8 @@ function zot_process_response($hub, $arr, $outq) { return; } + $dreport = true; + $x = json_decode($arr['body'], true); if(! $x) { @@ -1116,31 +1118,44 @@ function zot_process_response($hub, $arr, $outq) { } if(! (is_array($x['delivery_report']) && count($x['delivery_report']))) { logger('encrypted delivery report could not be decrypted'); - return; + $dreport = false; } } - foreach($x['delivery_report'] as $xx) { - call_hooks('dreport_process',$xx); - if(is_array($xx) && array_key_exists('message_id',$xx) && DReport::is_storable($xx)) { - q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s','%s' ) ", - dbesc($xx['message_id']), - dbesc($xx['location']), - dbesc($xx['recipient']), - dbesc($xx['name']), - dbesc($xx['status']), - dbesc(datetime_convert('UTC','UTC',$xx['date'])), - dbesc($xx['sender']) - ); + if($dreport) { + foreach($x['delivery_report'] as $xx) { + call_hooks('dreport_process',$xx); + if(is_array($xx) && array_key_exists('message_id',$xx) && DReport::is_storable($xx)) { + + // legacy zot recipients add a space and their name to the xchan. split those if true. + $legacy_recipient = strpos($xx['recipient'], ' '); + if($legacy_recipient !== false) { + $legacy_recipient_parts = explode(' ', $xx['recipient'], 2); + $xx['recipient'] = $legacy_recipient_parts[0]; + $xx['name'] = $legacy_recipient_parts[1]; + } + + q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s','%s' ) ", + dbesc($xx['message_id']), + dbesc($xx['location']), + dbesc($xx['recipient']), + dbesc($xx['name']), + dbesc($xx['status']), + dbesc(datetime_convert('UTC','UTC',$xx['date'])), + dbesc($xx['sender']) + ); + } } } } - // we have a more descriptive delivery report, so discard the per hub 'queued' report. - q("delete from dreport where dreport_queue = '%s' ", - dbesc($outq['outq_hash']) - ); + if($dreport) { + // we have a more descriptive delivery report, so discard the per hub 'queued' report. + q("delete from dreport where dreport_queue = '%s' ", + dbesc($outq['outq_hash']) + ); + } // update the timestamp for this site From eaa375936fc3c23f1b6629cba56fce2eb116a1c6 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 16 Jan 2019 15:28:30 -0800 Subject: [PATCH 83/93] more z6 compatibility fixes --- Zotlabs/Daemon/Onepoll.php | 2 +- Zotlabs/Daemon/Poller.php | 2 +- Zotlabs/Lib/Activity.php | 6 ++++++ include/follow.php | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Zotlabs/Daemon/Onepoll.php b/Zotlabs/Daemon/Onepoll.php index 920916828..1d9fd5f72 100644 --- a/Zotlabs/Daemon/Onepoll.php +++ b/Zotlabs/Daemon/Onepoll.php @@ -69,7 +69,7 @@ class Onepoll { return; } - if($contact['xchan_network'] !== 'zot') + if(! in_array($contact['xchan_network'],['zot','zot6'])) return; // update permissions diff --git a/Zotlabs/Daemon/Poller.php b/Zotlabs/Daemon/Poller.php index 49151437c..a8cf34ce2 100644 --- a/Zotlabs/Daemon/Poller.php +++ b/Zotlabs/Daemon/Poller.php @@ -110,7 +110,7 @@ class Poller { } - if($contact['xchan_network'] !== 'zot') + if(! in_array($contact['xchan_network'],['zot','zot6'])) continue; if($c == $t) { diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php index ef6ee6c3e..b4c833594 100644 --- a/Zotlabs/Lib/Activity.php +++ b/Zotlabs/Lib/Activity.php @@ -568,6 +568,9 @@ class Activity { 'http://activitystrea.ms/schema/1.0/tag' => 'Add', 'http://activitystrea.ms/schema/1.0/follow' => 'Follow', 'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow', + 'http://purl.org/zot/activity/attendyes' => 'Accept', + 'http://purl.org/zot/activity/attendno' => 'Reject', + 'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept' ]; @@ -607,6 +610,9 @@ class Activity { 'http://activitystrea.ms/schema/1.0/tag' => 'Add', 'http://activitystrea.ms/schema/1.0/follow' => 'Follow', 'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow', + 'http://purl.org/zot/activity/attendyes' => 'Accept', + 'http://purl.org/zot/activity/attendno' => 'Reject', + 'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept' ]; diff --git a/include/follow.php b/include/follow.php index 038e6e9c0..db77a0160 100644 --- a/include/follow.php +++ b/include/follow.php @@ -190,7 +190,7 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false) return $result; } - $allowed = (($is_zot || $r[0]['xchan_network'] === 'rss') ? 1 : 0); + $allowed = (($is_zot || in_array($r[0]['xchan_network'],['rss','zot6'])) ? 1 : 0); $x = array('channel_id' => $uid, 'follow_address' => $url, 'xchan' => $r[0], 'allowed' => $allowed, 'singleton' => 0); From 20eea2184bc1336efb811c29e3fb49262ae02262 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 16 Jan 2019 16:50:44 -0800 Subject: [PATCH 84/93] more work on z6 events --- Zotlabs/Lib/Activity.php | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php index b4c833594..b4d78d809 100644 --- a/Zotlabs/Lib/Activity.php +++ b/Zotlabs/Lib/Activity.php @@ -32,6 +32,9 @@ class Activity { if($x['type'] === ACTIVITY_OBJ_THING) { return self::fetch_thing($x); } + if($x['type'] === ACTIVITY_OBJ_EVENT) { + return self::fetch_event($x); + } return $x; @@ -99,6 +102,40 @@ class Activity { } } + static function fetch_event($x) { + + // convert old Zot event objects to ActivityStreams Event objects + + if (array_key_exists('content',$x) && array_key_exists('dtstart',$x)) { + $ev = bbtoevent($x['content']); + if($ev) { + + $actor = null; + if(array_key_exists('author',$x) && array_key_exists('link',$x['author'])) { + $actor = $x['author']['link'][0]['href']; + } + $y = [ + 'type' => 'Event', + 'id' => z_root() . '/event/' . $ev['event_hash'], + 'summary' => bbcode($ev['summary']), + // RFC3339 Section 4.3 + 'startTime' => (($ev['adjust']) ? datetime_convert('UTC','UTC',$ev['dtstart'], ATOM_TIME) : datetime_convert('UTC','UTC',$ev['dtstart'],'Y-m-d\\TH:i:s-00:00')), + 'content' => bbcode($ev['description']), + 'location' => [ 'type' => 'Place', 'content' => bbcode($ev['location']) ], + 'source' => [ 'content' => format_event_bbcode($ev), 'mediaType' => 'text/bbcode' ], + 'actor' => $actor, + ]; + if($actor) { + return $y; + } + } + } + + return $x; + + } + + static function encode_item_collection($items,$id,$type,$extra = null) { $ret = [ From e9f709301c64ca0f276e089d643da29fe8aada98 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 16 Jan 2019 17:32:16 -0800 Subject: [PATCH 85/93] more z6 event work --- Zotlabs/Lib/Activity.php | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php index b4d78d809..f87dd6b15 100644 --- a/Zotlabs/Lib/Activity.php +++ b/Zotlabs/Lib/Activity.php @@ -1455,7 +1455,33 @@ class Activity { $s['obj_type'] = ACTIVITY_OBJ_COMMENT; } - $s['obj'] = $act->obj; + + if($s['obj_type'] === 'Event') { + $s['obj'] = []; + $s['obj']['asld'] = $act->obj; + $s['obj']['type'] = ACTIVITY_OBJ_EVENT; + $s['obj']['id'] = $act->obj['id']; + $s['obj']['title'] = $act->obj['summary']; + + if(strpos($act->obj['startTime'],'Z')) + $s['obj']['adjust'] = true; + else + $s['obj']['adjust'] = false; + + $s['obj']['dtstart'] = datetime_convert('UTC','UTC',$act->obj['startTime']); + if($act->obj['endTime']) + $s['obj']['dtend'] = datetime_convert('UTC','UTC',$act->obj['endTime']); + else + $s['obj']['nofinish'] = true; + $s['obj']['description'] = $act->obj['content']; + + if(array_path_exists('location/content',$act->obj)) + $s['obj']['location'] = $act->obj['location']['content']; + + } + else { + $s['obj'] = $act->obj; + } $instrument = $act->get_property_obj('instrument'); if((! $instrument) && (! $response_activity)) { From eda7c5369c0228ed11ef3bddfa33d81b0c6a3747 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 16 Jan 2019 21:09:04 -0800 Subject: [PATCH 86/93] event attendance testing continued (now works at a basic level from one direction, more testing needed) --- Zotlabs/Lib/Activity.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php index f87dd6b15..154421b6a 100644 --- a/Zotlabs/Lib/Activity.php +++ b/Zotlabs/Lib/Activity.php @@ -1456,7 +1456,7 @@ class Activity { } - if($s['obj_type'] === 'Event') { + if($act->obj['type'] === 'Event') { $s['obj'] = []; $s['obj']['asld'] = $act->obj; $s['obj']['type'] = ACTIVITY_OBJ_EVENT; From 07f6465872e807224e54e3d73f5296d0fa057ca2 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 17 Jan 2019 11:39:52 +0100 Subject: [PATCH 87/93] fix delivery report for zot6 connections --- Zotlabs/Lib/DReport.php | 6 +++++- Zotlabs/Lib/Libzot.php | 1 + Zotlabs/Module/Dreport.php | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Zotlabs/Lib/DReport.php b/Zotlabs/Lib/DReport.php index ef1ce2678..1292e7488 100644 --- a/Zotlabs/Lib/DReport.php +++ b/Zotlabs/Lib/DReport.php @@ -87,9 +87,11 @@ class DReport { // Is the sender one of our channels? - $c = q("select channel_id from channel where channel_hash = '%s' limit 1", + $c = q("select channel_id from channel where channel_hash = '%s' or channel_portable_id = '%s'limit 1", + dbesc($dr['sender']), dbesc($dr['sender']) ); + if(! $c) return false; @@ -104,6 +106,8 @@ class DReport { $rxchan = $dr['recipient']; } + + // is the recipient one of our connections, or do we want to store every report? $pcf = get_pconfig($c[0]['channel_id'],'system','dreport_store_all'); diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index 268622430..e66c929bf 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -995,6 +995,7 @@ logger('4'); } if(is_array($x) && array_key_exists('delivery_report',$x) && is_array($x['delivery_report'])) { + foreach($x['delivery_report'] as $xx) { call_hooks('dreport_process',$xx); if(is_array($xx) && array_key_exists('message_id',$xx) && DReport::is_storable($xx)) { diff --git a/Zotlabs/Module/Dreport.php b/Zotlabs/Module/Dreport.php index 16ae7941f..2c125b7a9 100644 --- a/Zotlabs/Module/Dreport.php +++ b/Zotlabs/Module/Dreport.php @@ -80,8 +80,9 @@ class Dreport extends \Zotlabs\Web\Controller { return; } - $r = q("select * from dreport where dreport_xchan = '%s' and dreport_mid = '%s'", + $r = q("select * from dreport where (dreport_xchan = '%s' or dreport_xchan = '%s') and dreport_mid = '%s'", dbesc($channel['channel_hash']), + dbesc($channel['channel_portable_id']), dbesc($mid) ); From b1b1e0eba4f1e698c5f0f4f14b0527741e5b9ffb Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 17 Jan 2019 10:47:04 -0800 Subject: [PATCH 88/93] channel connect issue --- Zotlabs/Zot/Finger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Zot/Finger.php b/Zotlabs/Zot/Finger.php index 77634777a..cb38c7f2b 100644 --- a/Zotlabs/Zot/Finger.php +++ b/Zotlabs/Zot/Finger.php @@ -55,7 +55,7 @@ class Finger { $r = q("select xchan.*, hubloc.* from xchan left join hubloc on xchan_hash = hubloc_hash - where xchan_addr = '%s' and hubloc_primary = 1 and hubloc_deleted = 0 limit 1", + where xchan_addr = '%s' and hubloc_primary = 1 and hubloc_deleted = 0 and hubloc_network = 'zot' limit 1", dbesc($xchan_addr) ); From 5aa0267936e391e1d1a98de5287546ad5817fb41 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 17 Jan 2019 20:09:19 +0100 Subject: [PATCH 89/93] add space --- Zotlabs/Lib/DReport.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Lib/DReport.php b/Zotlabs/Lib/DReport.php index 1292e7488..18087e29f 100644 --- a/Zotlabs/Lib/DReport.php +++ b/Zotlabs/Lib/DReport.php @@ -87,7 +87,7 @@ class DReport { // Is the sender one of our channels? - $c = q("select channel_id from channel where channel_hash = '%s' or channel_portable_id = '%s'limit 1", + $c = q("select channel_id from channel where channel_hash = '%s' or channel_portable_id = '%s' limit 1", dbesc($dr['sender']), dbesc($dr['sender']) ); From cc1e1a525f2c928590d1da6e775dc29dddc2166d Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 17 Jan 2019 21:42:24 +0100 Subject: [PATCH 90/93] possible fix for #1326 --- view/js/main.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/view/js/main.js b/view/js/main.js index 017d39353..ee11ab1c6 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -468,6 +468,9 @@ function notificationsUpdate(cached_data) { $.get(pingCmd,function(data) { // Put the object into storage + if(! data) + return; + sessionStorage.setItem('notifications_cache', JSON.stringify(data)); var fnotifs = []; From d6167636fab15dfdead2b70dc7ee167dd2c13ddd Mon Sep 17 00:00:00 2001 From: Klaus Weidenbach Date: Tue, 15 Jan 2019 01:01:49 +0100 Subject: [PATCH 91/93] Add PostgreSQL to gitlab-ci setup. Run our tests against a PostgreSQL again. --- .gitlab-ci.yml | 47 +++++++++++++++++++++++++++++++++++------ tests/phpunit-pgsql.xml | 33 ++++++++++++++++------------- 2 files changed, 58 insertions(+), 22 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0b8e0430f..d162d57ba 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -11,13 +11,11 @@ variables: MYSQL_DATABASE: hello_world_test MYSQL_ROOT_PASSWORD: mysql - -services: -- mysql:5.7 - before_script: +# prevent error installing buggy postgresql-client package +- mkdir -p /usr/share/man/man1 /usr/share/man/man7 - apt-get update -yqq -- apt-get install -yqq git mysql-server mysql-client libmcrypt-dev libpq-dev libcurl4-gnutls-dev libicu-dev libvpx-dev libjpeg-dev libpng-dev libxpm-dev zlib1g-dev libfreetype6-dev libxml2-dev libexpat1-dev libbz2-dev libgmp3-dev libldap2-dev unixodbc-dev libsqlite3-dev libaspell-dev libsnmp-dev libpcre3-dev libtidy-dev +- apt-get install -yqq --no-install-recommends git mysql-client postgresql-client libmcrypt-dev libpq-dev libcurl4-gnutls-dev libicu-dev libvpx-dev libjpeg-dev libpng-dev libxpm-dev zlib1g-dev libfreetype6-dev libxml2-dev libexpat1-dev libbz2-dev libgmp3-dev libldap2-dev unixodbc-dev libaspell-dev libpcre3-dev libtidy-dev # Install PHP extensions - docker-php-ext-install mbstring mcrypt pdo_mysql pdo_pgsql curl json intl gd xml zip bz2 opcache # Install & enable Xdebug for code coverage reports @@ -25,12 +23,47 @@ before_script: - docker-php-ext-enable xdebug # Install and run Composer - curl -sS https://getcomposer.org/installer | php -- php composer.phar install +# Install dev libraries from composer +- php composer.phar install --no-progress +# Configure PHP values, needed for phpunit code coverage HTML generation +- echo "memory_limit = 256M" > /usr/local/etc/php/conf.d/hubzilla.ini -# We test PHP7 with MySQL, but we allow it to fail + +# We test PHP7 with MySQL test:php:mysql: + services: + - mysql:5.7 script: - echo "USE $MYSQL_DATABASE; $(cat ./install/schema_mysql.sql)" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE" - echo "SHOW DATABASES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE" - echo "USE $MYSQL_DATABASE; SHOW TABLES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE" - vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-text + +# test PHP7 with PostgreSQL +test:php:postgres: + services: + - postgres:latest + variables: + POSTGRES_DB: ci-db + POSTGRES_USER: ci-user + POSTGRES_PASSWORD: ci-pass + script: + - export PGPASSWORD=$POSTGRES_PASSWORD + - psql --version + - psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT VERSION();" + # Import hubzilla's DB schema + - psql -h "postgres" -U "$POSTGRES_USER" -v ON_ERROR_STOP=1 --quiet "$POSTGRES_DB" < ./install/schema_postgres.sql + # Show databases and relations/tables of hubzilla's database + #- psql -h "postgres" -U "$POSTGRES_USER" -l + #- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\dt;" + # Run the actual tests + - vendor/bin/phpunit --configuration tests/phpunit-pgsql.xml --testdox + artifacts: + expire_in: 1 week + # Gitlab should show the results, but has problems parsing PHPUnit's junit file. + reports: + junit: tests/results/junit.xml + # Archive test results (coverage, testdox, junit) + name: "$CI_COMMIT_REF_SLUG-$CI_JOB_NAME" + paths: + - tests/results/ diff --git a/tests/phpunit-pgsql.xml b/tests/phpunit-pgsql.xml index 078056d56..8b11aae31 100644 --- a/tests/phpunit-pgsql.xml +++ b/tests/phpunit-pgsql.xml @@ -1,24 +1,26 @@ - - ./unit/ - - - ./unit/ - + + + ./unit/ + + + ./unit/ + + mysql - + ../Zotlabs/ @@ -26,21 +28,22 @@ - - + + - + + - + - - - + + + From bba20c27fe01e4f6879969e98b52d5ce2de5ed5f Mon Sep 17 00:00:00 2001 From: Klaus Weidenbach Date: Fri, 18 Jan 2019 22:37:05 +0100 Subject: [PATCH 92/93] Some fixes in include/help.php. Remove unused variables and a wrong function name. --- include/help.php | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/include/help.php b/include/help.php index f2aa4add3..61dbc7bb3 100644 --- a/include/help.php +++ b/include/help.php @@ -12,12 +12,12 @@ use \Michelf\MarkdownExtra; function get_help_fullpath($path,$suffix=null) { $docroot = (\App::$override_helproot) ? \App::$override_helproot : 'doc/'; - $docroot = (substr($docroot,-1)!='/') ? $docroot .= '/' : $docroot; + $docroot = (substr($docroot,-1)!='/') ? $docroot .= '/' : $docroot; // Determine the language and modify the path accordingly $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 // subfolders named by the language code such as "de", "es", etc. if($lang !== 'en') { @@ -53,15 +53,14 @@ function get_help_fullpath($path,$suffix=null) { * @return string|unknown */ function get_help_content($tocpath = false) { - global $lang; $doctype = 'markdown'; $text = ''; $path = (($tocpath !== false) ? $tocpath : ''); - $docroot = (\App::$override_helproot) ? \App::$override_helproot : 'doc/'; - $docroot = (substr($docroot,-1)!='/') ? $docroot .= '/' : $docroot; + $docroot = (\App::$override_helproot) ? \App::$override_helproot : 'doc/'; + $docroot = (substr($docroot,-1)!='/') ? $docroot .= '/' : $docroot; if($tocpath === false && argc() > 1) { $path = ''; @@ -74,7 +73,7 @@ function get_help_content($tocpath = false) { if($path) { - $fullpath = get_help_fullpath($path); + $fullpath = get_help_fullpath($path); $title = basename($path); if(! $tocpath) \App::$page['title'] = t('Help:') . ' ' . ucwords(str_replace('-',' ',notags($title))); @@ -88,10 +87,10 @@ function get_help_content($tocpath = false) { load_doc_file($fullpath . '.md') === '' && load_doc_file($fullpath . '.bb') === '' && load_doc_file($fullpath . '.html') === '' - ) { + ) { $path = $title; } - $fullpath = get_help_fullpath($path); + $fullpath = get_help_fullpath($path); $text = load_doc_file($fullpath . '.md'); if(! $text) { @@ -111,15 +110,15 @@ function get_help_content($tocpath = false) { if($tocpath === false) { if(! $text) { - $path = 'Site'; - $fullpath = get_help_fullpath($path,'.md'); + $path = 'Site'; + $fullpath = get_help_fullpath($path,'.md'); $text = load_doc_file($fullpath . '.md'); \App::$page['title'] = t('Help'); } if(! $text) { $doctype = 'bbcode'; - $path = 'main'; - $fullpath = get_help_fullpath($path,'.md'); + $path = 'main'; + $fullpath = get_help_fullpath($path,'.md'); $text = load_doc_file($fullpath . '.bb'); goaway('/help/about/about'); \App::$page['title'] = t('Help'); @@ -219,7 +218,6 @@ function find_doc_file($s) { */ function search_doc_files($s) { - \App::set_pager_itemspage(60); $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start'])); @@ -351,7 +349,7 @@ function store_doc_file($s) { $x = item_store_update($item); } else { - $item['uuid'] = $item_message_id(); + $item['uuid'] = item_message_id(); $item['mid'] = $item['parent_mid'] = z_root() . '/item/' . $item['uuid']; $x = item_store($item); } From 90a62405ca54a78ec9ce7316812d8d041ec1bed2 Mon Sep 17 00:00:00 2001 From: Klaus Weidenbach Date: Sat, 19 Jan 2019 00:28:01 +0100 Subject: [PATCH 93/93] Fix wrong variable name in include/plugin.php. --- include/plugin.php | 72 +++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/include/plugin.php b/include/plugin.php index 7eeb39ce8..ec14fd945 100755 --- a/include/plugin.php +++ b/include/plugin.php @@ -213,8 +213,8 @@ function reload_plugins() { try { $func(); } catch (Exception $e) { - handleerrors_plugin($plugin,"","UNLOAD FAILED (uninstalling) : ".$e->getMessage(),true); - continue; + handleerrors_plugin($pl, '', 'UNLOAD FAILED (uninstalling) : ' . $e->getMessage(),true); + continue; } } if(function_exists($pl . '_load')) { @@ -222,8 +222,8 @@ function reload_plugins() { try { $func(); } catch (Exception $e) { - handleerrors_plugin($plugin,"","LOAD FAILED (uninstalling): ".$e->getMessage(),true); - continue; + handleerrors_plugin($pl, '', 'LOAD FAILED (uninstalling): ' . $e->getMessage(),true); + continue; } } q("UPDATE addon SET tstamp = %d WHERE id = %d", @@ -305,7 +305,7 @@ function plugins_sync() { * @return array */ function visible_plugin_list() { - + $r = q("select * from addon where hidden = 0 order by aname asc"); $x = (($r) ? ids_to_array($r,'aname') : array()); $y = []; @@ -315,7 +315,7 @@ function visible_plugin_list() { $y[] = $xv; } } - } + } return $y; } @@ -456,21 +456,21 @@ function insert_hook($hook, $fn, $version = 0, $priority = 0) { function call_hooks($name, &$data = null) { $a = 0; - if (isset(App::$hooks[$name])) { + if (isset(App::$hooks[$name])) { foreach(App::$hooks[$name] as $hook) { if ($name != 'permit_hook') { // avoid looping $checkhook = [ - 'name'=>$name, - 'hook'=>$hook, - 'data'=>$data, + 'name'=>$name, + 'hook'=>$hook, + 'data'=>$data, // Note: Since PHP uses COPY-ON-WRITE - // for variables, there is no cost to + // for variables, there is no cost to // passing the $data structure (unless // the permit_hook processors change the // information it contains. - 'permit'=>true - ]; + 'permit'=>true + ]; call_hooks('permit_hook',$checkhook); if (!$checkhook['permit']) { continue; @@ -618,7 +618,7 @@ function get_widget_info($widget){ } } - if(! ($widget_found && $f)) + if(! ($widget_found && $f)) return $info; $f = escape_tags($f); @@ -1041,7 +1041,7 @@ function get_intltext_template($s, $root = '') { if (isset(\App::$override_intltext_templates[$testroot][$s]["content"])) { return \App::$override_intltext_templates[$testroot][$s]["content"]; } else { - if (isset(\App::$override_intltext_templates[$testroot][$s]["root"]) && + if (isset(\App::$override_intltext_templates[$testroot][$s]["root"]) && isset(\App::$override_intltext_templates[$testroot][$s]["file"])) { $s = \App::$override_intltext_templates[$testroot][$s]["file"]; $root = \App::$override_intltext_templates[$testroot][$s]["root"]; @@ -1058,30 +1058,30 @@ function get_intltext_template($s, $root = '') { } function get_markup_template($s, $root = '') { - $testroot = ($root=='') ? $testroot = "ROOT" : $root; + $testroot = ($root=='') ? $testroot = "ROOT" : $root; - $t = App::template_engine(); + $t = App::template_engine(); - if (isset(\App::$override_markup_templates[$testroot][$s]["content"])) { - return \App::$override_markup_templates[$testroot][$s]["content"]; - } else { - if (isset(\App::$override_markup_templates[$testroot][$s]["root"]) && - isset(\App::$override_markup_templates[$testroot][$s]["file"])) { - $root = \App::$override_markup_templates[$testroot][$s]["root"]; - $s = \App::$override_markup_templates[$testroot][$s]["file"]; - $template = $t->get_markup_template($s, $root); - } elseif (\App::$override_templateroot) { - $newroot = \App::$override_templateroot; - if ($newroot != '' && substr($newroot,-1) != '/' ) { - $newroot .= '/'; - } - $newroot .= $root; - $template = $t->get_markup_template($s, $newroot); - } else { - $template = $t->get_markup_template($s, $root); + if (isset(\App::$override_markup_templates[$testroot][$s]["content"])) { + return \App::$override_markup_templates[$testroot][$s]["content"]; + } else { + if (isset(\App::$override_markup_templates[$testroot][$s]["root"]) && + isset(\App::$override_markup_templates[$testroot][$s]["file"])) { + $root = \App::$override_markup_templates[$testroot][$s]["root"]; + $s = \App::$override_markup_templates[$testroot][$s]["file"]; + $template = $t->get_markup_template($s, $root); + } elseif (\App::$override_templateroot) { + $newroot = \App::$override_templateroot; + if ($newroot != '' && substr($newroot,-1) != '/' ) { + $newroot .= '/'; + } + $newroot .= $root; + $template = $t->get_markup_template($s, $newroot); + } else { + $template = $t->get_markup_template($s, $root); } - return $template; - } + return $template; + } } /**