From 5ed4ed2246233d7e5c0a1136824a94e864420911 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 23 Jul 2017 19:54:32 -0700 Subject: [PATCH 001/441] suppress fopen errors from dav --- Zotlabs/Storage/File.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Storage/File.php b/Zotlabs/Storage/File.php index 1475241ab..7a102134f 100644 --- a/Zotlabs/Storage/File.php +++ b/Zotlabs/Storage/File.php @@ -265,7 +265,7 @@ class File extends DAV\Node implements DAV\IFile { $f = 'store/' . $this->auth->owner_nick . '/' . (($this->os_path) ? $this->os_path . '/' : '') . $x; else $f = $x; - return fopen($f, 'rb'); + return @fopen($f, 'rb'); } return dbunescbin($r[0]['content']); } From 6a7fa6bf5414a89c27f4f7d8da1ad8bb33d7c5a1 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 24 Jul 2017 20:23:00 -0700 Subject: [PATCH 002/441] provide a keychange operation to rebase an identity on a new keypair --- Zotlabs/Daemon/Notifier.php | 25 +++- Zotlabs/Zot/IHandler.php | 2 + Zotlabs/Zot/Receiver.php | 4 + Zotlabs/Zot/ZotHandler.php | 4 + include/channel.php | 99 ++++++++++++++++ include/xchan.php | 229 ++++++++++++++++++++++++++++++++++++ include/zot.php | 44 +++++++ 7 files changed, 405 insertions(+), 2 deletions(-) diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php index 20dd96ddd..f64e6748c 100644 --- a/Zotlabs/Daemon/Notifier.php +++ b/Zotlabs/Daemon/Notifier.php @@ -67,6 +67,7 @@ require_once('include/bbcode.php'); * location channel_id * request channel_id xchan_hash message_id * rating xlink_id + * keychange channel_id * */ @@ -144,6 +145,20 @@ class Notifier { $packet_type = 'request'; $normal_mode = false; } + elseif($cmd === 'keychange') { + $channel = channelx_by_n($item_id); + $r = q("select abook_xchan from abook where abook_channel = %d", + intval($item_id) + ); + if($r) { + foreach($r as $rr) { + $recipients[] = $rr['abook_xchan']; + } + } + $private = false; + $packet_type = 'keychange'; + $normal_mode = false; + } elseif($cmd == 'permission_update' || $cmd == 'permission_create') { // Get the (single) recipient $r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_self = 0", @@ -570,12 +585,17 @@ class Notifier { } - $hash = random_string(); + $hash = random_string(); $packet = null; + $pmsg = ''; if($packet_type === 'refresh' || $packet_type === 'purge') { $packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null)); } + if($packet_type === 'keychange') { + $packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null)); + $pmsg = get_pconfig($channel['channel_id'],'system','keychange'); + } elseif($packet_type === 'request') { $env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : ''); $packet = zot_build_packet($channel,$packet_type,$env,$hub['hubloc_sitekey'],$hub['site_crypto'], @@ -589,7 +609,8 @@ class Notifier { 'account_id' => $channel['channel_account_id'], 'channel_id' => $channel['channel_id'], 'posturl' => $hub['hubloc_callback'], - 'notify' => $packet + 'notify' => $packet, + 'msg' => (($pmsg) ? json_encode($pmsg) : '') )); } else { diff --git a/Zotlabs/Zot/IHandler.php b/Zotlabs/Zot/IHandler.php index eeca1555c..dd82f5be6 100644 --- a/Zotlabs/Zot/IHandler.php +++ b/Zotlabs/Zot/IHandler.php @@ -12,6 +12,8 @@ interface IHandler { function Request($data); + function Rekey($sender,$data); + function AuthCheck($data,$encrypted); function Purge($sender,$recipients); diff --git a/Zotlabs/Zot/Receiver.php b/Zotlabs/Zot/Receiver.php index 0050a2559..c521c9d64 100644 --- a/Zotlabs/Zot/Receiver.php +++ b/Zotlabs/Zot/Receiver.php @@ -120,6 +120,10 @@ class Receiver { $this->handler->Notify($this->data); break; + case 'rekey': + $this->handler->Rekey($this->sender, $this->data); + break; + default: $this->response['message'] = 'Not implemented'; json_return_and_die($this->response); diff --git a/Zotlabs/Zot/ZotHandler.php b/Zotlabs/Zot/ZotHandler.php index aab336545..ab8815b3d 100644 --- a/Zotlabs/Zot/ZotHandler.php +++ b/Zotlabs/Zot/ZotHandler.php @@ -20,6 +20,10 @@ class ZotHandler implements IHandler { zot_reply_message_request($data); } + function Rekey($sender,$data) { + zot_rekey_request($sender,$data); + } + function AuthCheck($data,$encrypted) { zot_reply_auth_check($data,$encrypted); } diff --git a/include/channel.php b/include/channel.php index 49da57fd6..23ceb1414 100644 --- a/include/channel.php +++ b/include/channel.php @@ -454,6 +454,105 @@ function create_identity($arr) { return $ret; } + +function change_channel_keys($channel) { + + $ret = array('success' => false); + + $stored = []; + + $key = new_keypair(4096); + + $sig = base64url_encode(rsa_sign($channel['channel_guid'],$key['prvkey'])); + $hash = make_xchan_hash($channel['channel_guid'],$sig); + + $stored['old_guid'] = $channel['channel_guid']; + $stored['old_guid_sig'] = $channel['channel_guid_sig']; + $stored['old_key'] = $channel['channel_pubkey']; + $stored['old_hash'] = $channel['channel_hash']; + + $stored['new_key'] = $key['pubkey']; + $stored['new_sig'] = base64url_encode(rsa_sign($key['pubkey'],$channel['channel_prvkey'])); + + // Save this info for the notifier to collect + + set_pconfig($channel['channel_id'],'system','keychange',$stored); + + $r = q("update channel set channel_prvkey = '%s', channel_pubkey = '%s', channel_guid_sig = '%s', channel_hash = '%s' where channel_id = %d", + dbesc($key['prvkey']), + dbesc($key['pubkey']), + dbesc($sig), + dbesc($hash), + intval($channel['channel_id']) + ); + if(! $r) { + return $ret; + } + $r = q("select * from channel where channel_id = %d", + intval($channel['channel_id']) + ); + + if(! $r) { + $ret['message'] = t('Unable to retrieve modified identity'); + return $ret; + } + + $modified = $r[0]; + + $h = q("select * from hubloc where hubloc_hash = '%s' and hubloc_url = '%s' ", + dbesc($stored['old_hash']), + dbesc(z_root()) + ); + + if($h) { + foreach($h as $hv) { + $hv['hubloc_guid_sig'] = $sig; + $hv['hubloc_hash'] = $hash; + $hv['hubloc_url_sig'] = base64url_encode(rsa_sign(z_root(),$modifed['channel_prvkey'])); + hubloc_store_lowlevel($hv); + } + } + + $x = q("select * from xchan where xchan_hash = '%s' ", + dbesc($stored['old_hash']) + ); + + $check = q("select * from xchan where xchan_hash = '%s'", + dbesc($hash) + ); + + if(($x) && (! $check)) { + $oldxchan = $x[0]; + foreach($x as $xv) { + $xv['xchan_guid_sig'] = $sig; + $xv['xchan_hash'] = $hash; + $xv['xchan_pubkey'] = $key['pubkey']; + xchan_store_lowlevel($xv); + $newxchan = $xv; + } + } + + $a = q("select * from abook where abook_xchan = '%s' and abook_self = 1", + dbesc($stored['old_hash']) + ); + + if($a) { + q("update abook set abook_xchan = '%s' where abook_id = %d", + dbesc($hash), + intval($a[0]['abook_id']) + ); + } + + xchan_change_key($oldxchan,$newxchan,$stored); + + Zotlabs\Daemon\Master::Summon(array('Notifier', 'keychange', $channel['channel_id'])); + + $ret['success'] = true; + return $ret; +} + + + /** * @brief Set default channel to be used on login. * diff --git a/include/xchan.php b/include/xchan.php index 12eb674fa..dba0b8b88 100644 --- a/include/xchan.php +++ b/include/xchan.php @@ -137,3 +137,232 @@ function xchan_fetch($arr) { } +function xchan_change_key($oldx,$newx,$data) { + + $r = q("update abook set abook_xchan = '%s' where abook_xchan = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update abconfig set xchan = '%s' where xchan = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update group_member set xchan = '%s' where xchan = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update chat set chat_xchan = '%s' where chat_xchan = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update chatpresence set cp_xchan = '%s' where cp_xchan = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update event set event_xchan = '%s' where event_xchan = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update item set owner_xchan = '%s' where owner_xchan = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update item set author_xchan = '%s' where author_xchan = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update item set source_xchan = '%s' where source_xchan = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update mail set from_xchan = '%s' where from_xchan = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update mail set to_xchan = '%s' where to_xchan = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update shares set share_xchan = '%s' where share_xchan = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update source set src_channel_xchan = '%s' where src_channel_xchan = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update source set src_xchan = '%s' where src_xchan = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update xchat set xchat_xchan = '%s' where xchat_xchan = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update xconfig set xchan = '%s' where xchan = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update xign set xchan = '%s' where xchan = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update xlink set xlink_xchan = '%s' where xlink_xchan = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update xprof set xprof_hash = '%s' where xprof_hash = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("update xtag set xtag_hash = '%s' where xtag_hash = '%s'", + dbsec($newx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + $r = q("select channel_id, channel_allow_cid, channel_deny_cid from channel where (channel_allow_cid like '%s' or channel_deny_cid like '%s') ", + dbesc($oldx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + if($r) { + foreach($r as $rv) { + $z = q("update channel set channel_allow_cid = '%s', channel_deny_cid = '%s' where channel_id = %d", + dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['channel_allow_cid'])), + dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['channel_deny_cid'])), + intval($rv['channel_id']) + ); + } + } + + $r = q("select id, allow_cid, deny_cid from attach where (allow_cid like '%s' or deny_cid like '%s') ", + dbesc($oldx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + if($r) { + foreach($r as $rv) { + $z = q("update attach set allow_cid = '%s', deny_cid = '%s' where id = %d", + dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])), + dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])), + intval($rv['id']) + ); + } + } + + $r = q("select cr_id, allow_cid, deny_cid from chatroom where (allow_cid like '%s' or deny_cid like '%s') ", + dbesc($oldx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + if($r) { + foreach($r as $rv) { + $z = q("update chatroom set allow_cid = '%s', deny_cid = '%s' where cr_id = %d", + dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])), + dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])), + intval($rv['cr_id']) + ); + } + } + + + $r = q("select id, allow_cid, deny_cid from event where (allow_cid like '%s' or deny_cid like '%s') ", + dbesc($oldx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + if($r) { + foreach($r as $rv) { + $z = q("update event set allow_cid = '%s', deny_cid = '%s' where id = %d", + dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])), + dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])), + intval($rv['id']) + ); + } + } + + + $r = q("select id, allow_cid, deny_cid from item where (allow_cid like '%s' or deny_cid like '%s') ", + dbesc($oldx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + if($r) { + foreach($r as $rv) { + $z = q("update item set allow_cid = '%s', deny_cid = '%s' where id = %d", + dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])), + dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])), + intval($rv['id']) + ); + } + } + + + $r = q("select mitem_id, allow_cid, deny_cid from menu_item where (allow_cid like '%s' or deny_cid like '%s') ", + dbesc($oldx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + if($r) { + foreach($r as $rv) { + $z = q("update menu_item set allow_cid = '%s', deny_cid = '%s' where mitem_id = %d", + dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])), + dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])), + intval($rv['mitem_id']) + ); + } + } + + + + $r = q("select obj_id, allow_cid, deny_cid from obj where (allow_cid like '%s' or deny_cid like '%s') ", + dbesc($oldx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + if($r) { + foreach($r as $rv) { + $z = q("update obj set allow_cid = '%s', deny_cid = '%s' where obj_id = %d", + dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])), + dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])), + intval($rv['obj_id']) + ); + } + } + + $r = q("select id, allow_cid, deny_cid from photo where (allow_cid like '%s' or deny_cid like '%s') ", + dbesc($oldx['xchan_hash']), + dbesc($oldx['xchan_hash']) + ); + + if($r) { + foreach($r as $rv) { + $z = q("update photo set allow_cid = '%s', deny_cid = '%s' where id = %d", + dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])), + dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])), + intval($rv['id']) + ); + } + } + + +} \ No newline at end of file diff --git a/include/zot.php b/include/zot.php index 8bbc4a969..220292994 100644 --- a/include/zot.php +++ b/include/zot.php @@ -3757,6 +3757,50 @@ function zot_reply_message_request($data) { json_return_and_die($ret); } +function zot_rekey_request($sender,$data) { + + $ret = array('success' => false); + + // newsig is newkey signed with oldkey + + // The original xchan will remain. In Zot/Receiver we will have imported the new xchan and hubloc to verify + // the packet authenticity. What we will do now is verify that the keychange operation was signed by the + // oldkey, and if so change all the abook, abconfig, group, and permission elements which reference the + // old xchan_hash. + + if((! $data['oldkey']) && (! $data['oldsig']) && (! $data['newkey']) && (! $data['newsig'])) + json_return_and_die($ret); + + $oldhash = make_xchan_hash($data['old_guid'],$data['old_guid_sig']); + + $r = q("select * from xchan where xchan_hash = '%s' limit 1", + dbesc($oldhash) + ); + + if(! $r) { + json_return_and_die($ret); + } + + $xchan = $r[0]; + + if(! rsa_verify($data['newkey'],base64url_decode($data['newsig']),$xchan['xchan_pubkey'])) { + json_return_and_die($ret); + } + + $newhash = make_xchan_hash($sender['guid'],$sender['guid_sig']); + + $r = q("select * from xchan where xchan_hash = '%s' limit 1", + dbesc($newhash) + ); + + $newxchan = $r[0]; + + xchan_change_key($xchan,$newxchan,$data); + + $ret['success'] = true; + json_return_and_die($ret); +} + function zotinfo($arr) { From ddecbf052eabe92f61091bcd2541190b1037e466 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 24 Jul 2017 22:45:50 -0700 Subject: [PATCH 003/441] new field names did not get saved --- include/zot.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/zot.php b/include/zot.php index 220292994..33cf1d40d 100644 --- a/include/zot.php +++ b/include/zot.php @@ -3768,7 +3768,7 @@ function zot_rekey_request($sender,$data) { // oldkey, and if so change all the abook, abconfig, group, and permission elements which reference the // old xchan_hash. - if((! $data['oldkey']) && (! $data['oldsig']) && (! $data['newkey']) && (! $data['newsig'])) + if((! $data['old_key']) && (! $data['new_key']) && (! $data['new_sig'])) json_return_and_die($ret); $oldhash = make_xchan_hash($data['old_guid'],$data['old_guid_sig']); @@ -3783,7 +3783,7 @@ function zot_rekey_request($sender,$data) { $xchan = $r[0]; - if(! rsa_verify($data['newkey'],base64url_decode($data['newsig']),$xchan['xchan_pubkey'])) { + if(! rsa_verify($data['new_key'],base64url_decode($data['new_sig']),$xchan['xchan_pubkey'])) { json_return_and_die($ret); } From c24cfbc62af111f18576cfde8e4e920e66c57ff5 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 25 Jul 2017 15:59:58 -0700 Subject: [PATCH 004/441] make signing methods variable and signable --- boot.php | 2 +- include/crypto.php | 10 ++++++++++ include/zot.php | 3 ++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/boot.php b/boot.php index 061c14554..f5fe4b185 100755 --- a/boot.php +++ b/boot.php @@ -50,7 +50,7 @@ require_once('include/attach.php'); define ( 'PLATFORM_NAME', 'hubzilla' ); define ( 'STD_VERSION', '2.5.9' ); -define ( 'ZOT_REVISION', '1.2' ); +define ( 'ZOT_REVISION', '1.3' ); define ( 'DB_UPDATE_VERSION', 1192 ); diff --git a/include/crypto.php b/include/crypto.php index 2c5545e9b..6ac3fd732 100644 --- a/include/crypto.php +++ b/include/crypto.php @@ -185,6 +185,16 @@ function crypto_methods() { } +function signing_methods() { + + + $r = [ 'sha256' ]; + call_hooks('signing_methods',$r); + return $r; + +} + + function aes_encapsulate($data,$pubkey) { if(! $pubkey) logger('aes_encapsulate: no key. data: ' . $data); diff --git a/include/zot.php b/include/zot.php index 33cf1d40d..f9682237e 100644 --- a/include/zot.php +++ b/include/zot.php @@ -122,7 +122,8 @@ function zot_build_packet($channel, $type = 'notify', $recipients = null, $remot ], 'callback' => '/post', 'version' => ZOT_REVISION, - 'encryption' => crypto_methods() + 'encryption' => crypto_methods(), + 'signing' => signing_methods() ]; if ($recipients) { From 029cf6395dc1da503ebda7718cae30a8c19de691 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 25 Jul 2017 17:58:46 -0700 Subject: [PATCH 005/441] sync key changes to clones --- include/channel.php | 3 ++ include/zot.php | 114 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 111 insertions(+), 6 deletions(-) diff --git a/include/channel.php b/include/channel.php index 23ceb1414..f6252f094 100644 --- a/include/channel.php +++ b/include/channel.php @@ -488,6 +488,7 @@ function change_channel_keys($channel) { if(! $r) { return $ret; } + $r = q("select * from channel where channel_id = %d", intval($channel['channel_id']) ); @@ -532,6 +533,8 @@ function change_channel_keys($channel) { } } + build_sync_packet($channel['channel_id'], [ 'keychange' => $stored ]); + $a = q("select * from abook where abook_xchan = '%s' and abook_self = 1", dbesc($stored['old_hash']) ); diff --git a/include/zot.php b/include/zot.php index f9682237e..a86948ef9 100644 --- a/include/zot.php +++ b/include/zot.php @@ -2949,6 +2949,11 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { if($packet) logger('packet: ' . print_r($packet, true),LOGGER_DATA, LOG_DEBUG); + $keychange = (($packet && array_key_exists('keychange',$packet)) ? true : false); + if($keychange) { + logger('keychange sync'); + } + if(! $uid) $uid = local_channel(); @@ -2962,6 +2967,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { return; $channel = $r[0]; + unset($channel['channel_password']); unset($channel['channel_salt']); @@ -2972,12 +2978,11 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { } } - if(intval($channel['channel_removed'])) return; $h = q("select hubloc.*, site.site_crypto from hubloc left join site on site_url = hubloc_url where hubloc_hash = '%s' and hubloc_deleted = 0", - dbesc($channel['channel_hash']) + dbesc(($keychange) ? $packet['keychange']['old_hash'] : $channel['channel_hash']) ); if(! $h) @@ -3032,7 +3037,15 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { // don't pass these elements, they should not be synchronised - $disallowed = array('channel_id','channel_account_id','channel_primary','channel_prvkey','channel_address','channel_deleted','channel_removed','channel_system'); + + $disallowed = [ + 'channel_id','channel_account_id','channel_primary','channel_address', + 'channel_deleted','channel_removed','channel_system' + ]; + + if(! $keychange) { + $disallowed[] = 'channel_prvkey'; + } if(in_array($k,$disallowed)) continue; @@ -3092,17 +3105,18 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { function process_channel_sync_delivery($sender, $arr, $deliveries) { - require_once('include/import.php'); /** @FIXME this will sync red structures (channel, pconfig and abook). Eventually we need to make this application agnostic. */ - $result = array(); + $result = []; + + $keychange = ((array_key_exists('keychange',$arr)) ? true : false); foreach ($deliveries as $d) { $r = q("select * from channel where channel_hash = '%s' limit 1", - dbesc($d['hash']) + dbesc(($keychange) ? $arr['keychange']['old_hash'] : $d['hash']) ); if (! $r) { @@ -3121,6 +3135,94 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { continue; } + if($keychange) { + // verify the keychange operation + if(! rsa_verify($arr['channel']['channel_pubkey'],base64url_decode($arr['keychange']['new_sig']),$channel['channel_prvkey'])) { + logger('sync keychange: verification failed'); + continue; + } + + $sig = base64url_encode(rsa_sign($channel['channel_guid'],$arr['channel']['channel_prvkey'])); + $hash = make_xchan_hash($channel['channel_guid'],$sig); + + + $r = q("update channel set channel_prvkey = '%s', channel_pubkey = '%s', channel_guid_sig = '%s', + channel_hash = '%s' where channel_id = %d", + dbesc($arr['channel']['channel_prvkey']), + dbesc($arr['channel']['channel_pubkey']), + dbesc($sig), + dbesc($hash), + intval($channel['channel_id']) + ); + if(! $r) { + logger('keychange sync: channel update failed'); + continue; + } + + $r = q("select * from channel where channel_id = %d", + intval($channel['channel_id']) + ); + + if(! $r) { + logger('keychange sync: channel retrieve failed'); + continue; + } + + $channel = $r[0]; + + $h = q("select * from hubloc where hubloc_hash = '%s' and hubloc_url = '%s' ", + dbesc($arr['keychange']['old_hash']), + dbesc(z_root()) + ); + + if($h) { + foreach($h as $hv) { + $hv['hubloc_guid_sig'] = $sig; + $hv['hubloc_hash'] = $hash; + $hv['hubloc_url_sig'] = base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])); + hubloc_store_lowlevel($hv); + } + } + + $x = q("select * from xchan where xchan_hash = '%s' ", + dbesc($arr['keychange']['old_hash']) + ); + + $check = q("select * from xchan where xchan_hash = '%s'", + dbesc($hash) + ); + + if(($x) && (! $check)) { + $oldxchan = $x[0]; + foreach($x as $xv) { + $xv['xchan_guid_sig'] = $sig; + $xv['xchan_hash'] = $hash; + $xv['xchan_pubkey'] = $channel['channel_pubkey']; + xchan_store_lowlevel($xv); + $newxchan = $xv; + } + } + + $a = q("select * from abook where abook_xchan = '%s' and abook_self = 1", + dbesc($arr['keychange']['old_hash']) + ); + + if($a) { + q("update abook set abook_xchan = '%s' where abook_id = %d", + dbesc($hash), + intval($a[0]['abook_id']) + ); + } + + xchan_change_key($oldxchan,$newxchan,$arr['keychange']); + + // keychange operations can end up in a confused state if you try and sync anything else + // besides the channel keys, so ignore any other packets. + + continue; + } + + if(array_key_exists('config',$arr) && is_array($arr['config']) && count($arr['config'])) { foreach($arr['config'] as $cat => $k) { foreach($arr['config'][$cat] as $k => $v) From eec2871680ae97810de4bdc20bb3decf2d919019 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 25 Jul 2017 20:52:29 -0700 Subject: [PATCH 006/441] consolidate duplicated code --- include/xchan.php | 291 +++++++++++----------------------------------- 1 file changed, 71 insertions(+), 220 deletions(-) diff --git a/include/xchan.php b/include/xchan.php index dba0b8b88..8c9c09c72 100644 --- a/include/xchan.php +++ b/include/xchan.php @@ -137,232 +137,83 @@ function xchan_fetch($arr) { } +function xchan_keychange_table($table,$column,$oldxchan,$newxchan) { + $r = q("update $table set $column = '%s' where $column = '%s'", + dbesc($newxchan['xchan_hash']), + dbesc($oldxchan['xchan_hash']) + ); + return $r; +} + +function xchan_keychange_acl($table,$column,$oldxchan,$newxchan) { + + $allow = (($table === 'channel') ? 'channel_allow_cid' : 'allow_cid'); + $deny = (($table === 'channel') ? 'channel_deny_cid' : 'deny_cid'); + + + $r = q("select $column, $allow, $deny from $table where ($allow like '%s' or $deny like '%s') ", + dbesc('<' . $oldxchan['xchan_hash'] . '>'), + dbesc('<' . $oldxchan['xchan_hash'] . '>') + ); + + if($r) { + foreach($r as $rv) { + $z = q("update $table set $allow = '%s', $deny = '%s' where $column = %d", + dbesc(str_replace('<' . $oldxchan['xchan_hash'] . '>', '<' . $newxchan['xchan_hash'] . '>', + $rv[$allow])), + dbesc(str_replace('<' . $oldxchan['xchan_hash'] . '>', '<' . $newxchan['xchan_hash'] . '>', + $rv[$deny])), + intval($rv[$column]) + ); + } + } + return $z; +} + + function xchan_change_key($oldx,$newx,$data) { - $r = q("update abook set abook_xchan = '%s' where abook_xchan = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); + $tables = [ + 'abook' => 'abook_xchan', + 'abconfig' => 'xchan', + 'group_member' => 'xchan', + 'chat' => 'chat_xchan', + 'chatpresence' => 'cp_xchan', + 'event' => 'event_xchan', + 'item' => 'owner_xchan', + 'item' => 'author_xchan', + 'item' => 'source_xchan', + 'mail' => 'from_xchan', + 'mail' => 'to_xchan', + 'shares' => 'share_xchan', + 'source' => 'src_channel_xchan', + 'source' => 'src_xchan', + 'xchat' => 'xchat_xchan', + 'xconfig' => 'xchan', + 'xign' => 'xchan', + 'xlink' => 'xlink_xchan', + 'xprof' => 'xprof_hash', + 'xtag' => 'xtag_hash' + ]; + - $r = q("update abconfig set xchan = '%s' where xchan = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); + $acls = [ + 'channel' => 'channel_id', + 'attach' => 'id', + 'chatroom' => 'cr_id', + 'event' => 'id', + 'item' => 'id', + 'menu_item' => 'mitem_id', + 'obj' => 'obj_id', + 'photo' => 'id' + ]; - $r = q("update group_member set xchan = '%s' where xchan = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - $r = q("update chat set chat_xchan = '%s' where chat_xchan = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - $r = q("update chatpresence set cp_xchan = '%s' where cp_xchan = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - $r = q("update event set event_xchan = '%s' where event_xchan = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - $r = q("update item set owner_xchan = '%s' where owner_xchan = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - $r = q("update item set author_xchan = '%s' where author_xchan = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - $r = q("update item set source_xchan = '%s' where source_xchan = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - $r = q("update mail set from_xchan = '%s' where from_xchan = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - $r = q("update mail set to_xchan = '%s' where to_xchan = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - $r = q("update shares set share_xchan = '%s' where share_xchan = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - $r = q("update source set src_channel_xchan = '%s' where src_channel_xchan = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - $r = q("update source set src_xchan = '%s' where src_xchan = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - $r = q("update xchat set xchat_xchan = '%s' where xchat_xchan = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - $r = q("update xconfig set xchan = '%s' where xchan = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - $r = q("update xign set xchan = '%s' where xchan = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - $r = q("update xlink set xlink_xchan = '%s' where xlink_xchan = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - $r = q("update xprof set xprof_hash = '%s' where xprof_hash = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - $r = q("update xtag set xtag_hash = '%s' where xtag_hash = '%s'", - dbsec($newx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - $r = q("select channel_id, channel_allow_cid, channel_deny_cid from channel where (channel_allow_cid like '%s' or channel_deny_cid like '%s') ", - dbesc($oldx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - if($r) { - foreach($r as $rv) { - $z = q("update channel set channel_allow_cid = '%s', channel_deny_cid = '%s' where channel_id = %d", - dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['channel_allow_cid'])), - dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['channel_deny_cid'])), - intval($rv['channel_id']) - ); - } + foreach($tables as $k => $v) { + xchan_keychange_table($k,$v,$oldx,$newx); } - $r = q("select id, allow_cid, deny_cid from attach where (allow_cid like '%s' or deny_cid like '%s') ", - dbesc($oldx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - if($r) { - foreach($r as $rv) { - $z = q("update attach set allow_cid = '%s', deny_cid = '%s' where id = %d", - dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])), - dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])), - intval($rv['id']) - ); - } + foreach($acls as $k => $v) { + xchan_keychange_acl($k,$v,$oldx,$newx); } - - $r = q("select cr_id, allow_cid, deny_cid from chatroom where (allow_cid like '%s' or deny_cid like '%s') ", - dbesc($oldx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - if($r) { - foreach($r as $rv) { - $z = q("update chatroom set allow_cid = '%s', deny_cid = '%s' where cr_id = %d", - dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])), - dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])), - intval($rv['cr_id']) - ); - } - } - - - $r = q("select id, allow_cid, deny_cid from event where (allow_cid like '%s' or deny_cid like '%s') ", - dbesc($oldx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - if($r) { - foreach($r as $rv) { - $z = q("update event set allow_cid = '%s', deny_cid = '%s' where id = %d", - dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])), - dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])), - intval($rv['id']) - ); - } - } - - - $r = q("select id, allow_cid, deny_cid from item where (allow_cid like '%s' or deny_cid like '%s') ", - dbesc($oldx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - if($r) { - foreach($r as $rv) { - $z = q("update item set allow_cid = '%s', deny_cid = '%s' where id = %d", - dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])), - dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])), - intval($rv['id']) - ); - } - } - - - $r = q("select mitem_id, allow_cid, deny_cid from menu_item where (allow_cid like '%s' or deny_cid like '%s') ", - dbesc($oldx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - if($r) { - foreach($r as $rv) { - $z = q("update menu_item set allow_cid = '%s', deny_cid = '%s' where mitem_id = %d", - dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])), - dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])), - intval($rv['mitem_id']) - ); - } - } - - - - $r = q("select obj_id, allow_cid, deny_cid from obj where (allow_cid like '%s' or deny_cid like '%s') ", - dbesc($oldx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - if($r) { - foreach($r as $rv) { - $z = q("update obj set allow_cid = '%s', deny_cid = '%s' where obj_id = %d", - dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])), - dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])), - intval($rv['obj_id']) - ); - } - } - - $r = q("select id, allow_cid, deny_cid from photo where (allow_cid like '%s' or deny_cid like '%s') ", - dbesc($oldx['xchan_hash']), - dbesc($oldx['xchan_hash']) - ); - - if($r) { - foreach($r as $rv) { - $z = q("update photo set allow_cid = '%s', deny_cid = '%s' where id = %d", - dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['allow_cid'])), - dbesc(str_replace('<' . $oldx['xchan_hash'] . '>', '<' . $newx['xchan_hash'] . '>', $rv['deny_cid'])), - intval($rv['id']) - ); - } - } - - } \ No newline at end of file From 7d82b5f28d3fe10792098d8ecc4c60e224b8bd3d Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 25 Jul 2017 22:17:31 -0700 Subject: [PATCH 007/441] start to implement the code needed for verifying variable signature algorithms --- include/zot.php | 46 +++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/include/zot.php b/include/zot.php index a86948ef9..976b4290e 100644 --- a/include/zot.php +++ b/include/zot.php @@ -111,13 +111,15 @@ function zot_get_hublocs($hash) { */ function zot_build_packet($channel, $type = 'notify', $recipients = null, $remote_key = null, $methods = '', $secret = null, $extra = null) { + $sig_method = get_config('system','signature_algorithm','sha256'); + $data = [ 'type' => $type, 'sender' => [ 'guid' => $channel['channel_guid'], - 'guid_sig' => base64url_encode(rsa_sign($channel['channel_guid'],$channel['channel_prvkey'])), + 'guid_sig' => base64url_encode(rsa_sign($channel['channel_guid'],$channel['channel_prvkey'],$sig_method)), 'url' => z_root(), - 'url_sig' => base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])), + 'url_sig' => base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'],$sig_method)), 'sitekey' => get_config('system','pubkey') ], 'callback' => '/post', @@ -135,7 +137,7 @@ function zot_build_packet($channel, $type = 'notify', $recipients = null, $remot if ($secret) { $data['secret'] = $secret; - $data['secret_sig'] = base64url_encode(rsa_sign($secret,$channel['channel_prvkey'])); + $data['secret_sig'] = base64url_encode(rsa_sign($secret,$channel['channel_prvkey'],$sig_method)); } if ($extra) { @@ -576,6 +578,8 @@ function zot_register_hub($arr) { if($arr['url'] && $arr['url_sig'] && $arr['guid'] && $arr['guid_sig']) { + $sig_methods = ((array_key_exists('signing',$arr) && is_array($arr['signing'])) ? $arr['signing'] : [ 'sha256' ]); + $guid_hash = make_xchan_hash($arr['guid'],$arr['guid_sig']); $url = $arr['url'] . '/.well-known/zot-info/?f=&guid_hash=' . $guid_hash; @@ -595,17 +599,18 @@ function zot_register_hub($arr) { * our current communication. */ - if((rsa_verify($arr['guid'],base64url_decode($arr['guid_sig']),$record['key'])) - && (rsa_verify($arr['url'],base64url_decode($arr['url_sig']),$record['key'])) + foreach($sig_methods as $method) { + if((rsa_verify($arr['guid'],base64url_decode($arr['guid_sig']),$record['key'],$method)) + && (rsa_verify($arr['url'],base64url_decode($arr['url_sig']),$record['key'],$method)) && ($arr['guid'] === $record['guid']) && ($arr['guid_sig'] === $record['guid_sig'])) { - - $c = import_xchan($record); - if($c['success']) - $result['success'] = true; - } - else { - logger('zot_register_hub: failure to verify returned packet.'); + $c = import_xchan($record); + if($c['success']) + $result['success'] = true; + } + else { + logger('zot_register_hub: failure to verify returned packet using ' . $method); + } } } } @@ -658,8 +663,19 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { $import_photos = false; - if(! rsa_verify($arr['guid'],base64url_decode($arr['guid_sig']),$arr['key'])) { - logger('import_xchan: Unable to verify channel signature for ' . $arr['address']); + $sig_methods = ((array_key_exists('signing',$arr) && is_array($arr['signing'])) ? $arr['signing'] : [ 'sha256' ]); + $verified = false; + + foreach($sig_methods as $method) { + if(! rsa_verify($arr['guid'],base64url_decode($arr['guid_sig']),$arr['key'],$method)) { + logger('import_xchan: Unable to verify channel signature for ' . $arr['address'] . ' using ' . $method); + continue; + } + else { + $verified = true; + } + } + if(! $verified) { $ret['message'] = t('Unable to verify channel signature'); return $ret; } @@ -918,7 +934,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { } elseif(! $ud_flags) { // nothing changed but we still need to update the updates record - q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and not (ud_flags & %d)>0 ", + q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and not (ud_flags & %d) > 0 ", intval(UPDATE_FLAGS_UPDATED), dbesc($address), intval(UPDATE_FLAGS_UPDATED) From 7d891a54e7a47dc7471774a3e51e0e4da7e2e3d9 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 26 Jul 2017 16:22:20 -0700 Subject: [PATCH 008/441] improve the formatting of shares when converting from bbcode to markdown --- include/markdown.php | 69 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/include/markdown.php b/include/markdown.php index 5d3c4c7df..ccd108c1b 100644 --- a/include/markdown.php +++ b/include/markdown.php @@ -84,6 +84,72 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) { +function bb_to_markdown_share($match) { + + $matches = array(); + $attributes = $match[1]; + + $author = ""; + preg_match("/author='(.*?)'/ism", $attributes, $matches); + if ($matches[1] != "") + $author = urldecode($matches[1]); + + $link = ""; + preg_match("/link='(.*?)'/ism", $attributes, $matches); + if ($matches[1] != "") + $link = $matches[1]; + + $avatar = ""; + preg_match("/avatar='(.*?)'/ism", $attributes, $matches); + if ($matches[1] != "") + $avatar = $matches[1]; + + $profile = ""; + preg_match("/profile='(.*?)'/ism", $attributes, $matches); + if ($matches[1] != "") + $profile = $matches[1]; + + $posted = ""; + preg_match("/posted='(.*?)'/ism", $attributes, $matches); + if ($matches[1] != "") + $posted = $matches[1]; + + // 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]; + } + + + $reldate = datetime_convert('UTC', date_default_timezone_get(), $posted, 'r'); + + $headline = ''; + + if ($avatar != "") + $headline .= '[url=' . zid($profile) . '][img]' . $avatar . '[/img][/url]'; + + // Bob Smith wrote the following post 2 hours ago + + $fmt = sprintf( t('%1$s wrote the following %2$s %3$s'), + '[url=' . zid($profile) . ']' . $author . '[/url]', + '[url=' . zid($link) . ']' . t('post') . '[/url]', + $reldate + ); + + $headline .= $fmt . "\n\n"; + + $text = $headline . trim($match[2]); + + return $text; +} + + function bb_to_markdown($Text) { @@ -100,9 +166,12 @@ function bb_to_markdown($Text) { // Converting images with size parameters to simple images. Markdown doesn't know it. $Text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $Text); + $Text = preg_replace_callback("/\[share(.*?)\](.*?)\[\/share\]/ism", 'bb_to_markdown_share', $Text); + call_hooks('bb_to_markdown_bb',$Text); + // Convert it to HTML - don't try oembed $Text = bbcode($Text, $preserve_nl, false); From 769f697ae32b9c8a2ac30d7e9e349c1f54975219 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 26 Jul 2017 16:36:09 -0700 Subject: [PATCH 009/441] more work on signature algorithm choice --- include/zot.php | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/include/zot.php b/include/zot.php index 976b4290e..75c37836d 100644 --- a/include/zot.php +++ b/include/zot.php @@ -31,9 +31,9 @@ require_once('include/perm_upgrade.php'); * @param string $channel_nick a unique nickname of controlling entity * @returns string */ + function zot_new_uid($channel_nick) { $rawstr = z_root() . '/' . $channel_nick . '.' . mt_rand(); - return(base64url_encode(hash('whirlpool', $rawstr, true), true)); } @@ -49,6 +49,7 @@ function zot_new_uid($channel_nick) { * @param string $guid * @param string $guid_sig */ + function make_xchan_hash($guid, $guid_sig) { return base64url_encode(hash('whirlpool', $guid . $guid_sig, true)); } @@ -62,17 +63,17 @@ function make_xchan_hash($guid, $guid_sig) { * @param string $hash - xchan_hash * @returns array of hubloc (hub location structures) * * \b hubloc_id int - * * \b hubloc_guid char(255) + * * \b hubloc_guid char(191) * * \b hubloc_guid_sig text - * * \b hubloc_hash char(255) - * * \b hubloc_addr char(255) + * * \b hubloc_hash char(191) + * * \b hubloc_addr char(191) * * \b hubloc_flags int * * \b hubloc_status int - * * \b hubloc_url char(255) + * * \b hubloc_url char(191) * * \b hubloc_url_sig text - * * \b hubloc_host char(255) - * * \b hubloc_callback char(255) - * * \b hubloc_connect char(255) + * * \b hubloc_host char(191) + * * \b hubloc_callback char(191) + * * \b hubloc_connect char(191) * * \b hubloc_sitekey text * * \b hubloc_updated datetime * * \b hubloc_connected datetime @@ -97,7 +98,7 @@ function zot_get_hublocs($hash) { * @param array $channel * sender channel structure * @param string $type - * packet type: one of 'ping', 'pickup', 'purge', 'refresh', 'force_refresh', 'notify', 'auth_check' + * packet type: one of 'ping', 'pickup', 'purge', 'refresh', 'keychange', 'force_refresh', 'notify', 'auth_check' * @param array $recipients * envelope information, array ( 'guid' => string, 'guid_sig' => string ); empty for public posts * @param string $remote_key @@ -532,7 +533,7 @@ function zot_gethub($arr, $multiple = false) { } $limit = (($multiple) ? '' : ' limit 1 '); - $sitekey = ((array_key_exists('sitekey',$arr) && $arr['sitekey']) ? " and hubloc_sitekey = '" . protect_sprintf($arr['sitekey']) . "' " : ''); + $sitekey = ((array_key_exists('sitekey',$arr) && $arr['sitekey']) ? " and hubloc_sitekey = '" . dbesc(protect_sprintf($arr['sitekey'])) . "' " : ''); $r = q("select hubloc.*, site.site_crypto from hubloc left join site on hubloc_url = site_url where hubloc_guid = '%s' and hubloc_guid_sig = '%s' @@ -3925,6 +3926,8 @@ function zotinfo($arr) { $ret = array('success' => false); + $sig_method = get_config('system','signature_algorithm','sha256'); + $zhash = ((x($arr,'guid_hash')) ? $arr['guid_hash'] : ''); $zguid = ((x($arr,'guid')) ? $arr['guid'] : ''); $zguid_sig = ((x($arr,'guid_sig')) ? $arr['guid_sig'] : ''); @@ -4088,7 +4091,7 @@ function zotinfo($arr) { // Communication details if($token) - $ret['signed_token'] = base64url_encode(rsa_sign('token.' . $token,$e['channel_prvkey'])); + $ret['signed_token'] = base64url_encode(rsa_sign('token.' . $token,$e['channel_prvkey'],$sig_method)); $ret['guid'] = $e['xchan_guid']; @@ -4157,7 +4160,7 @@ function zotinfo($arr) { $ret['site'] = array(); $ret['site']['url'] = z_root(); - $ret['site']['url_sig'] = base64url_encode(rsa_sign(z_root(),$e['channel_prvkey'])); + $ret['site']['url_sig'] = base64url_encode(rsa_sign(z_root(),$e['channel_prvkey'],$sig_method)); $ret['site']['zot_auth'] = z_root() . '/magic'; $dirmode = get_config('system','directory_mode'); @@ -4175,6 +4178,7 @@ function zotinfo($arr) { $ret['site']['encryption'] = crypto_methods(); + $ret['site']['signing'] = signing_methods(); // hide detailed site information if you're off the grid From 9132b9c02661586a54823517c331fb718a9cbd17 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 26 Jul 2017 16:39:13 -0700 Subject: [PATCH 010/441] remove activitypub components from core --- include/feedutils.php | 182 ------------------------------------------ 1 file changed, 182 deletions(-) diff --git a/include/feedutils.php b/include/feedutils.php index 4f68fdeef..e660574ed 100644 --- a/include/feedutils.php +++ b/include/feedutils.php @@ -1868,185 +1868,3 @@ function atom_entry($item, $type, $author, $owner, $comment = false, $cid = 0, $ return $x['entry']; } -/** - * @brief - * - * @param array $items - * @return array - */ -function gen_asld($items) { - $ret = array(); - if(! $items) - return $ret; - - foreach($items as $item) { - $ret[] = i2asld($item); - } - - return $ret; -} - -/** - * @brief - * - * @param array $i - * @return array - */ -function i2asld($i) { - - if(! $i) - return array(); - - $ret = array(); - - $ret['@context'] = array( 'https://www.w3.org/ns/activitystreams', 'zot' => 'http://purl.org/zot/protocol'); - - if($i['verb']) { - if(strpos(dirname($i['verb'],'activitystrea.ms/schema/1.0'))) { - $ret['type'] = ucfirst(basename($i['verb'])); - } - elseif(strpos(dirname($i['verb'],'purl.org/zot'))) { - $ret['type'] = 'zot:' . ucfirst(basename($i['verb'])); - } - } - $ret['id'] = $i['plink']; - - $ret['published'] = datetime_convert('UTC','UTC',$i['created'],ATOM_TIME); - - // we need to pass the parent into this -// if($i['id'] != $i['parent'] && $i['obj_type'] === ACTIVITY_OBJ_NOTE) { -// $ret['inReplyTo'] = asencode_note -// } - - if($i['obj_type'] === ACTIVITY_OBJ_NOTE) - $ret['object'] = asencode_note($i); - - $ret['actor'] = asencode_person($i['author']); - - return $ret; -} - -function asencode_note($i) { - - $ret = array(); - - $ret['@type'] = 'Note'; - $ret['id'] = $i['plink']; - if($i['title']) - $ret['title'] = bbcode($i['title']); - - $ret['content'] = bbcode($i['body']); - $ret['zot:owner'] = asencode_person($i['owner']); - $ret['published'] = datetime_convert('UTC','UTC',$i['created'],ATOM_TIME); - if($i['created'] !== $i['edited']) - $ret['updated'] = datetime_convert('UTC','UTC',$i['edited'],ATOM_TIME); - - return $ret; -} - - -function asencode_person($p) { - $ret = []; - $ret['type'] = 'Person'; - $ret['id'] = $p['xchan_url']; - $ret['name'] = $p['xchan_name']; - $ret['icon'] = [ - [ - 'type' => 'Image', - 'mediaType' => $p['xchan_photo_mimetype'], - 'url' => $p['xchan_photo_l'], - 'height' => 300, - 'width' => 300, - ], - [ - 'type' => 'Image', - 'mediaType' => $p['xchan_photo_mimetype'], - 'url' => $p['xchan_photo_m'], - 'height' => 80, - 'width' => 80, - ], - [ - 'type' => 'Image', - 'mediaType' => $p['xchan_photo_mimetype'], - 'url' => $p['xchan_photo_l'], - 'height' => 48, - 'width' => 48, - ] - ]; - $ret['url'] = [ - 'type' => 'Link', - 'mediaType' => 'text/html', - 'href' => $p['xchan_url'] - ]; - - if(array_key_exists('channel_id',$p)) { - $ret['inbox'] = z_root() . '/inbox/' . $p['channel_address']; - $ret['outbox'] = z_root() . '/outbox/' . $p['channel_address']; - $ret['me:magic_keys'] = [ - [ - 'value' => salmon_key($p['channel_pubkey']), - 'key_id' => base64url_encode(hash('sha256',salmon_key($p['channel_pubkey'])),true) - ] - ]; - - - } - else { - $collections = get_xconfig($p['xchan_hash'],'activitystreams','collections',[]); - if($collections) { - $ret = array_merge($ret,$collections); - } - } - - return $ret; -} - - -function activity_mapper($verb) { - - $acts = [ - 'http://activitystrea.ms/schema/1.0/post' => 'Create', - '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', - ]; - - - if(array_key_exists($acts[$verb])) { - return $acts[$verb]; - } - return false; -} - - -function activity_obj_mapper($obj,$reverse = false) { - - $objs = [ - 'http://activitystrea.ms/schema/1.0/note' => 'Note', - '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' => 'zot:Thing', - 'http://purl.org/zot/activity/file' => 'zot:File', - 'http://purl.org/zot/activity/poke' => 'zot:Action', - 'http://purl.org/zot/activity/react' => 'zot:Reaction', - 'http://purl.org/zot/activity/mood' => 'zot:Mood', - - ]; - - if(array_key_exists($objs[$verb])) { - return $objs[$verb]; - } - return false; -} From dbbae4bac81d18f814c18ac8d0ea51667e00703f Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 26 Jul 2017 17:38:34 -0700 Subject: [PATCH 011/441] issue with OStatus comments being propagated downstream --- include/feedutils.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/feedutils.php b/include/feedutils.php index e660574ed..eb24f9032 100644 --- a/include/feedutils.php +++ b/include/feedutils.php @@ -999,6 +999,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { foreach($items as $item) { $is_reply = false; + $send_downstream = false; $parent_link = ''; logger('processing ' . $item->get_id(), LOGGER_DEBUG); @@ -1200,6 +1201,15 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { $status = 202; continue; } + + // The salmon endpoint sets this to indicate that we should send comments from + // interactive feeds (such as OStatus) downstream to our followers + // We do not want to set it for non-interactive feeds or conversations we do not own + + if(array_key_exists('send_downstream',$importer) && intval($importer['send_downstream']) + && ($parent_item['owner_xchan'] == $importer['channel_hash'])) { + $send_downstream = true; + } } else { if((! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'send_stream')) && (! $importer['system'])) { @@ -1229,6 +1239,11 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { $xx = item_store($datarray); $r = $xx['item_id']; + + if($send_downstream) { + \Zotlabs\Daemon\Master::Summon(array('Notifier', 'comment', $r)); + } + continue; } else { From 41a6300d3ce205fae4f4210815ef0b6a04d22406 Mon Sep 17 00:00:00 2001 From: git-marijus Date: Thu, 27 Jul 2017 20:47:07 +0200 Subject: [PATCH 012/441] remove borders from navbar toggler --- view/tpl/nav.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/tpl/nav.tpl b/view/tpl/nav.tpl index c0b34bbe8..b9abf4d48 100755 --- a/view/tpl/nav.tpl +++ b/view/tpl/nav.tpl @@ -68,7 +68,7 @@ {{/if}} - From 179478a9401c059e16588654d878e6a7813904cb Mon Sep 17 00:00:00 2001 From: git-marijus Date: Thu, 27 Jul 2017 21:51:59 +0200 Subject: [PATCH 013/441] default to static updates if not local channel --- Zotlabs/Module/Display.php | 2 +- Zotlabs/Module/Pubstream.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php index df3cb1e2b..81c72adb3 100644 --- a/Zotlabs/Module/Display.php +++ b/Zotlabs/Module/Display.php @@ -140,7 +140,7 @@ class Display extends \Zotlabs\Web\Controller { if((! $update) && (! $load)) { - $static = ((local_channel()) ? channel_manual_conv_update(local_channel()) : 0); + $static = ((local_channel()) ? channel_manual_conv_update(local_channel()) : 1); $o .= '
' . "\r\n"; $o .= " +
diff --git a/view/tpl/photos_recent.tpl b/view/tpl/photos_recent.tpl index 8fe631ca6..c6a9067c1 100755 --- a/view/tpl/photos_recent.tpl +++ b/view/tpl/photos_recent.tpl @@ -19,5 +19,8 @@
- +
From 297057d2bdc227a8729e136a290f81012248d033 Mon Sep 17 00:00:00 2001 From: git-marijus Date: Sun, 30 Jul 2017 17:49:35 +0200 Subject: [PATCH 026/441] do not include ACTIVITY_OBJ_FILE obj_type in the ping/something query --- Zotlabs/Module/Ping.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Zotlabs/Module/Ping.php b/Zotlabs/Module/Ping.php index bf926075c..190208727 100644 --- a/Zotlabs/Module/Ping.php +++ b/Zotlabs/Module/Ping.php @@ -291,9 +291,12 @@ class Ping extends \Zotlabs\Web\Controller { $r = q("SELECT * FROM item WHERE item_unseen = 1 and uid = %d $item_normal - and author_xchan != '%s' ORDER BY created DESC limit 300", + AND author_xchan != '%s' + AND obj_type != '%s' + ORDER BY created DESC limit 300", intval(local_channel()), - dbesc($ob_hash) + dbesc($ob_hash), + dbesc(ACTIVITY_OBJ_FILE) ); if($r) { From ead80481b967d529956694c7d8125e92fccee8c1 Mon Sep 17 00:00:00 2001 From: git-marijus Date: Sun, 30 Jul 2017 18:01:01 +0200 Subject: [PATCH 027/441] another syntax error --- Zotlabs/Module/Network.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index d689efd14..597ba084b 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -534,7 +534,7 @@ class Network extends \Zotlabs\Web\Controller { if($parents_str) { $update_unseen = " AND ( id IN ( " . dbesc($parents_str) . " )"; - $update_unseen .= " AND obj_type != " . dbesc(ACTIVITY_OBJ_FILE) . ""; + $update_unseen .= " AND obj_type != '" . dbesc(ACTIVITY_OBJ_FILE) . "'"; $update_unseen .= " OR ( parent IN ( " . dbesc($parents_str) . " ) AND verb in ( '" . dbesc(ACTIVITY_LIKE) . "','" . dbesc(ACTIVITY_DISLIKE) . "' ))) "; } } From 4a071b9a1cac32ed331a9a4e76d8a6c9aa312bef Mon Sep 17 00:00:00 2001 From: git-marijus Date: Sun, 30 Jul 2017 19:21:02 +0200 Subject: [PATCH 028/441] ltrim $display_path in attach_store() to be consistent with attach_mkdir() and go to created folder after successfully creating one --- Zotlabs/Module/File_upload.php | 2 ++ include/attach.php | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Zotlabs/Module/File_upload.php b/Zotlabs/Module/File_upload.php index f036d3f43..bce81ad7a 100644 --- a/Zotlabs/Module/File_upload.php +++ b/Zotlabs/Module/File_upload.php @@ -35,6 +35,8 @@ class File_upload extends \Zotlabs\Web\Controller { if($_REQUEST['filename']) { $r = attach_mkdir($channel, get_observer_hash(), $_REQUEST); + if($r['success']) + goaway(z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['data']['display_path']); } else { $r = attach_store($channel, get_observer_hash(), '', $_REQUEST); diff --git a/include/attach.php b/include/attach.php index 4d20f094c..8de4983fa 100644 --- a/include/attach.php +++ b/include/attach.php @@ -708,7 +708,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $os_relpath = ltrim($os_relpath,'/'); $os_path = $os_relpath; - $display_path = $pathname . '/' . $filename; + $display_path = ltrim($pathname . '/' . $filename,'/'); if($src) @file_put_contents($os_basepath . $os_relpath,@file_get_contents($src)); @@ -886,7 +886,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { } if($notify) { - $cloudPath = z_root() . '/cloud/' . $channel['channel_address'] . $r['0']['display_path']; + $cloudPath = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['0']['display_path']; $object = get_file_activity_object($channel['channel_id'], $r['0']['hash'], $cloudPath); file_activity($channel['channel_id'], $object, $r['0']['allow_cid'], $r['0']['allow_gid'], $r['0']['deny_cid'], $r['0']['deny_gid'], 'post', $notify); } From 35c05a318016e3269e4bc677a36b515833fab66e Mon Sep 17 00:00:00 2001 From: git-marijus Date: Sun, 30 Jul 2017 19:46:52 +0200 Subject: [PATCH 029/441] fix a bug where if multiple channels uploaded the same file to the same folder, the uploaded file would end up with an incremental number added to the filename for each upload even if the file did not exist yet in the channels folder --- include/attach.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/attach.php b/include/attach.php index 8de4983fa..785969a32 100644 --- a/include/attach.php +++ b/include/attach.php @@ -611,7 +611,8 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { // A freshly uploaded file. Check for duplicate and resolve with the channel's overwrite settings. - $r = q("select filename, id, hash, filesize from attach where filename = '%s' and folder = '%s' ", + $r = q("select filename, id, hash, filesize from attach where uid = %d and filename = '%s' and folder = '%s' ", + intval($channel_id), dbesc($filename), dbesc($folder_hash) ); @@ -633,7 +634,8 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $ext = $def_extension; } - $r = q("select filename from attach where ( filename = '%s' OR filename like '%s' ) and folder = '%s' ", + $r = q("select filename from attach where uid = %d and ( filename = '%s' OR filename like '%s' ) and folder = '%s' ", + intval($channel_id), dbesc($basename . $ext), dbesc($basename . '(%)' . $ext), dbesc($folder_hash) From 40effa441743fcbb8d62591421611a3193e352d4 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 30 Jul 2017 13:52:16 -0700 Subject: [PATCH 030/441] add options flag to bb_to_markdown so we can distinguish between diaspora use and other use and therefore filter and adjust content selectively --- include/markdown.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/markdown.php b/include/markdown.php index ccd108c1b..530af57a0 100644 --- a/include/markdown.php +++ b/include/markdown.php @@ -151,7 +151,7 @@ function bb_to_markdown_share($match) { -function bb_to_markdown($Text) { +function bb_to_markdown($Text, $options = []) { /* * Transform #tags, strip off the [url] and replace spaces with underscore @@ -168,9 +168,11 @@ function bb_to_markdown($Text) { $Text = preg_replace_callback("/\[share(.*?)\](.*?)\[\/share\]/ism", 'bb_to_markdown_share', $Text); + $x = [ 'bbcode' => $Text, 'options' => $options ]; - call_hooks('bb_to_markdown_bb',$Text); + call_hooks('bb_to_markdown_bb',$x); + $Text = $x['bbcode']; // Convert it to HTML - don't try oembed $Text = bbcode($Text, $preserve_nl, false); From 964a02d68456912e08e76ec2bbfa1074e624cae7 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 30 Jul 2017 16:15:34 -0700 Subject: [PATCH 031/441] provide a better "is_commentable" default for OStatus conversations that were fetched on the fly --- include/feedutils.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/include/feedutils.php b/include/feedutils.php index eb24f9032..e3f899a1e 100644 --- a/include/feedutils.php +++ b/include/feedutils.php @@ -1028,6 +1028,11 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { if(! $datarray['mid']) continue; + // This probably isn't an appropriate default but we're about to change it + // if it's wrong. + + $datarray['comment_policy'] = 'authenticated'; + // A Mastodon privacy tag has been found. We cannot send private comments // through the OStatus protocol, so block commenting. @@ -1256,6 +1261,11 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { if(! $datarray['mid']) continue; + // This probably isn't an appropriate default but we're about to change it + // if it's wrong. + + $datarray['comment_policy'] = 'authenticated'; + // A Mastodon privacy tag has been found. We cannot send private comments // through the OStatus protocol, so block commenting. @@ -1270,6 +1280,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { } + // if we have everything but a photo, provide the default profile photo if($author['author_name'] && $author['author_link'] && (! $author['author_photo'])) @@ -1493,7 +1504,7 @@ function process_salmon_feed($xml, $importer) { // reset policies which are restricted by default for RSS connections // This item is likely coming from GNU-social via salmon and allows public interaction $datarray['public_policy'] = ''; - $datarray['comment_policy'] = ''; + $datarray['comment_policy'] = 'authenticated'; $ret['item'] = $datarray; } From b4efe8ad8d91c70bf869259e6764e7e4a079563b Mon Sep 17 00:00:00 2001 From: git-marijus Date: Mon, 31 Jul 2017 02:24:49 +0200 Subject: [PATCH 032/441] implement system configs as app requirement and add the pubstream app --- Zotlabs/Lib/Apps.php | 14 ++++++++++---- app/pubstream.apd | 6 ++++++ 2 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 app/pubstream.apd diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 68587df49..7287bdd52 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -169,6 +169,7 @@ class Apps { $requires = explode(',',$ret['requires']); foreach($requires as $require) { $require = trim(strtolower($require)); + $toggle = (($require[0] == '!') ? 0 : 1); switch($require) { case 'nologin': if(local_channel()) @@ -191,10 +192,12 @@ class Apps { unset($ret); break; default: - if(! (local_channel() && feature_enabled(local_channel(),$require))) + $unset = ((local_channel() && feature_enabled(local_channel(),$require)) ? false : true); + $unset = ((get_config('system', ltrim($require, '!')) == $toggle) ? false : true); + + if($unset) unset($ret); break; - } } } @@ -307,6 +310,7 @@ class Apps { $requires = explode(',',$v); foreach($requires as $require) { $require = trim(strtolower($require)); + $toggle = (($require[0] == '!') ? 0 : 1); switch($require) { case 'nologin': if(local_channel()) @@ -330,10 +334,12 @@ class Apps { return ''; break; default: - if(! (local_channel() && feature_enabled(local_channel(),$require))) + $unset = ((local_channel() && feature_enabled(local_channel(),$require)) ? false : true); + $unset = ((get_config('system', ltrim($require, '!')) == $toggle) ? false : true); + + if($unset) return ''; break; - } } } diff --git a/app/pubstream.apd b/app/pubstream.apd new file mode 100644 index 000000000..065be24bc --- /dev/null +++ b/app/pubstream.apd @@ -0,0 +1,6 @@ +version: 1 +url: $baseurl/pubstream +requires: !disable_discover_tab +name: Public Stream +photo: icon:globe +categories: Social From 988371be0b2df3f917da67f39814e21f96f9f957 Mon Sep 17 00:00:00 2001 From: git-marijus Date: Mon, 31 Jul 2017 02:35:46 +0200 Subject: [PATCH 033/441] disable file notifications on initial upload for now - it can behave funky when uploading multiple small files at once --- include/attach.php | 6 +++--- view/tpl/cloud_actionspanel.tpl | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/attach.php b/include/attach.php index 785969a32..75235d7e1 100644 --- a/include/attach.php +++ b/include/attach.php @@ -888,9 +888,9 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { } if($notify) { - $cloudPath = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['0']['display_path']; - $object = get_file_activity_object($channel['channel_id'], $r['0']['hash'], $cloudPath); - file_activity($channel['channel_id'], $object, $r['0']['allow_cid'], $r['0']['allow_gid'], $r['0']['deny_cid'], $r['0']['deny_gid'], 'post', $notify); + //$cloudPath = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['0']['display_path']; + //$object = get_file_activity_object($channel['channel_id'], $r['0']['hash'], $cloudPath); + //file_activity($channel['channel_id'], $object, $r['0']['allow_cid'], $r['0']['allow_gid'], $r['0']['deny_cid'], $r['0']['deny_gid'], 'post', $notify); } return $ret; diff --git a/view/tpl/cloud_actionspanel.tpl b/view/tpl/cloud_actionspanel.tpl index fc3e7f82f..baee48da3 100644 --- a/view/tpl/cloud_actionspanel.tpl +++ b/view/tpl/cloud_actionspanel.tpl @@ -26,7 +26,7 @@ - {{include file="field_checkbox.tpl" field=$notify}} + {{**include file="field_checkbox.tpl" field=$notify**}}
{{if $lockstate}} From 8f3a99ad1f87973d0788596371f311e0e4fa1ee3 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 30 Jul 2017 19:04:17 -0700 Subject: [PATCH 034/441] ensure we can work around the $is_http var in include/follow - this is left over from when the only non-webfinger connections we could make were RSS/Atom feeds. --- include/follow.php | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/include/follow.php b/include/follow.php index 2c2f5e209..9e2fd6a9c 100644 --- a/include/follow.php +++ b/include/follow.php @@ -182,6 +182,11 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false) $hash = get_observer_hash(); $default_group = $channel['channel_default_group']; + if($hash == $xchan_hash) { + $result['message'] = t('Cannot connect to yourself.'); + return $result; + } + if($xchan['xchan_network'] === 'rss') { // check service class feed limits @@ -196,28 +201,22 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false) $result['message'] = upgrade_message(); return $result; } - } - - if($hash == $xchan_hash) { - $result['message'] = t('Cannot connect to yourself.'); - return $result; - } - - $r = q("select abook_id, abook_xchan, abook_pending, abook_instance from abook - where abook_xchan = '%s' and abook_channel = %d limit 1", - dbesc($xchan_hash), - intval($uid) - ); - - if($is_http) { // Always set these "remote" permissions for feeds since we cannot interact with them // to negotiate a suitable permission response set_abconfig($uid,$xchan_hash,'their_perms','view_stream',1); set_abconfig($uid,$xchan_hash,'their_perms','republish',1); + } + + $r = q("select abook_id, abook_xchan, abook_pending, abook_instance from abook + where abook_xchan = '%s' and abook_channel = %d limit 1", + dbesc($xchan_hash), + intval($uid) + ); + if($r) { $abook_instance = $r[0]['abook_instance']; @@ -250,7 +249,7 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false) 'abook_channel' => intval($uid), 'abook_closeness' => intval($closeness), 'abook_xchan' => $xchan_hash, - 'abook_feed' => intval(($is_http) ? 1 : 0), + 'abook_feed' => intval(($xchan['xchan_network'] === 'rss') ? 1 : 0), 'abook_created' => datetime_convert(), 'abook_updated' => datetime_convert(), 'abook_instance' => (($singleton) ? z_root() : '') From e3c8e4f4833b485469616c753cc660e8a55bef29 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 30 Jul 2017 21:55:28 -0700 Subject: [PATCH 035/441] modify connection edit display for channels with no address/webbie --- Zotlabs/Module/Connedit.php | 3 ++- boot.php | 1 + include/network.php | 27 ++++++++++++++------------- view/tpl/abook_edit.tpl | 2 +- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php index d301c2d45..0f18b432d 100644 --- a/Zotlabs/Module/Connedit.php +++ b/Zotlabs/Module/Connedit.php @@ -841,7 +841,7 @@ class Connedit extends \Zotlabs\Web\Controller { } } else - $locstr = t('none'); + $locstr = $contact['xchan_url']; $clone_warn = ''; $clonable = (in_array($contact['xchan_network'],['zot','rss']) ? true : false); @@ -866,6 +866,7 @@ class Connedit extends \Zotlabs\Web\Controller { '$permcat_new' => t('Add permission role'), '$permcat_enable' => feature_enabled(local_channel(),'permcats'), '$addr' => $contact['xchan_addr'], + '$primeurl' => $contact['xchan_url'], '$section' => $section, '$sections' => $sections, '$vcard' => $vcard, diff --git a/boot.php b/boot.php index 69b4db269..965a11a6e 100755 --- a/boot.php +++ b/boot.php @@ -256,6 +256,7 @@ define ( 'NETWORK_OSTATUS', 'stat'); // status.net, identi.ca, GNU-s define ( 'NETWORK_GNUSOCIAL', 'gnusoc'); // status.net, identi.ca, GNU-social, other OStatus implementations define ( 'NETWORK_FEED', 'rss'); // RSS/Atom feeds with no known "post/notify" protocol define ( 'NETWORK_DIASPORA', 'diaspora'); // Diaspora +define ( 'NETWORK_ACTIVITYPUB' 'activitypub'); define ( 'NETWORK_MAIL', 'mail'); // IMAP/POP define ( 'NETWORK_MAIL2', 'mai2'); // extended IMAP/POP define ( 'NETWORK_FACEBOOK', 'face'); // Facebook API diff --git a/include/network.php b/include/network.php index fe9a9aa2b..fa49e5765 100644 --- a/include/network.php +++ b/include/network.php @@ -1142,7 +1142,7 @@ function discover_by_webbie($webbie) { $network = null; - $webbie = strtolower($webbie); +// $webbie = strtolower($webbie); $x = webfinger_rfc7033($webbie,true); if($x && array_key_exists('links',$x) && $x['links']) { @@ -1688,18 +1688,19 @@ function get_repository_version($branch = 'master') { function network_to_name($s) { $nets = array( - NETWORK_DFRN => t('Friendica'), - NETWORK_FRND => t('Friendica'), - NETWORK_OSTATUS => t('OStatus'), - NETWORK_GNUSOCIAL => t('GNU-Social'), - NETWORK_FEED => t('RSS/Atom'), - NETWORK_MAIL => t('Email'), - NETWORK_DIASPORA => t('Diaspora'), - NETWORK_FACEBOOK => t('Facebook'), - NETWORK_ZOT => t('Zot'), - NETWORK_LINKEDIN => t('LinkedIn'), - NETWORK_XMPP => t('XMPP/IM'), - NETWORK_MYSPACE => t('MySpace'), + NETWORK_DFRN => t('Friendica'), + NETWORK_FRND => t('Friendica'), + NETWORK_OSTATUS => t('OStatus'), + NETWORK_GNUSOCIAL => t('GNU-Social'), + NETWORK_FEED => t('RSS/Atom'), + NETWORK_ACTIVITYPUB => t('ActivityPub'), + NETWORK_MAIL => t('Email'), + NETWORK_DIASPORA => t('Diaspora'), + NETWORK_FACEBOOK => t('Facebook'), + NETWORK_ZOT => t('Zot'), + NETWORK_LINKEDIN => t('LinkedIn'), + NETWORK_XMPP => t('XMPP/IM'), + NETWORK_MYSPACE => t('MySpace'), ); call_hooks('network_to_name', $nets); diff --git a/view/tpl/abook_edit.tpl b/view/tpl/abook_edit.tpl index 146030494..13b94a560 100755 --- a/view/tpl/abook_edit.tpl +++ b/view/tpl/abook_edit.tpl @@ -52,7 +52,7 @@ {{/foreach}} - diff --git a/include/help.php b/include/help.php index 4f9251b1b..cbadd02d9 100644 --- a/include/help.php +++ b/include/help.php @@ -107,20 +107,39 @@ function preg_callback_help_include($matches) { } - +function determine_help_language() { + require_once('Text/LanguageDetect.php'); + $lang_detect = new Text_LanguageDetect(); + $lang_detect->setNameMode(2); + if($lang_detect->languageExists(argv(1))) { + $lang = argv(1); + $from_url = true; + } else { + $lang = \App::$language; + if(! isset($lang)) + $lang = 'en'; + $from_url = false; + } + return array('language' => $lang, 'from_url' => $from_url); +} function load_doc_file($s) { - $lang = \App::$language; - if(! isset($lang)) - $lang = 'en'; - $b = basename($s); - $d = dirname($s); - - if($dirname !== '-') { - $c = find_doc_file("$d/$lang/$b"); - if($c) - return $c; + $path = 'doc'; + $x = determine_help_language(); + $lang = $x['language']; + $url_idx = ($x['from_url'] ? 1 : 0); + if($x['from_url'] && $lang !== 'en') { + $path .= '/' . $lang; } + + $b = basename($s); + + for($i=1+$url_idx; $i').find('ul'); + tocUl.removeClass(); // Classes are automatically added to
    elements by something else + tocUl.toc({content: "#doco-content", headings: "h3"}); + tocUl.addClass('toc-content'); + tocUl.addClass('list-unstyled'); + tocUl.attr('id', 'doco-side-toc'); + + } + }); + + $(document.body).trigger("sticky_kit:recalc"); + + toc.contentTop = []; + toc.edgeMargin = 20; // margin above the top or margin from the end of the page + toc.topRange = 200; // measure from the top of the viewport to X pixels down + // Set up content an array of locations + $('#doco-side-toc').find('a').each(function () { + toc.contentTop.push($('#' + $(this).attr('href').split('#').pop()).offset().top); + }); + + + // adjust side menu + $(window).scroll(function () { + var winTop = $(window).scrollTop(), + bodyHt = $(document).height(), + vpHt = $(window).height() + toc.edgeMargin; // viewport height + margin + $.each(toc.contentTop, function (i, loc) { + if ((loc > winTop - toc.edgeMargin && (loc < winTop + toc.topRange || (winTop + vpHt) >= bodyHt))) { + $('#doco-side-toc li') + .removeClass('selected-doco-nav') + .eq(i).addClass('selected-doco-nav'); + if (typeof ($('#doco-side-toc li').eq(i).find('a').attr('href').split('#')[1]) !== 'undefined') { + window.history.pushState({}, '', location.href.split('#')[0] + '#' + $('#doco-side-toc li').eq(i).find('a').attr('href').split('#')[1]); + } + } + }); + }); + + // When the page loads, it does not scroll to the section specified in the URL because it + // has not been constructed yet by the script. This will reload the URL + if (typeof (location.href.split('#')[1]) !== 'undefined') { + var p = document.createElement('a'); + p.href = location.href; + var portstr = ''; + if (p.port !== '') { + portstr = ':' + p.port; + } + var newref = p.protocol + '//' + p.hostname + portstr + p.pathname + p.hash.split('?').shift(); + location.replace(newref) + } +}); diff --git a/view/tpl/help.tpl b/view/tpl/help.tpl index 43b061dcc..31e5b9794 100644 --- a/view/tpl/help.tpl +++ b/view/tpl/help.tpl @@ -13,21 +13,3 @@ {{$content}}
- - From e084b776eee9f1fc66e3f4a37b92ec70ccc49286 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 23 Aug 2017 00:01:02 -0700 Subject: [PATCH 124/441] cards feature --- Zotlabs/Daemon/Notifier.php | 2 +- Zotlabs/Lib/Apps.php | 1 + Zotlabs/Module/Cards.php | 189 ++++++++++++++++++++++++++++++++++ Zotlabs/Widget/Categories.php | 13 ++- app/cards.apd | 5 + include/contact_widgets.php | 43 ++++++++ include/conversation.php | 16 ++- include/features.php | 9 ++ include/nav.php | 12 +++ include/taxonomy.php | 76 ++++++++++++++ view/pdl/mod_cards.pdl | 2 + view/tpl/cards.tpl | 8 ++ view/tpl/jot.tpl | 4 +- 13 files changed, 373 insertions(+), 7 deletions(-) create mode 100644 Zotlabs/Module/Cards.php create mode 100644 app/cards.apd create mode 100644 view/pdl/mod_cards.pdl create mode 100644 view/tpl/cards.tpl diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php index 33dcbbf20..e8cd4dac8 100644 --- a/Zotlabs/Daemon/Notifier.php +++ b/Zotlabs/Daemon/Notifier.php @@ -276,7 +276,7 @@ class Notifier { $deleted_item = true; } - if(! in_array(intval($target_item['item_type']), [ ITEM_TYPE_POST, ITEM_TYPE_CARD ] )) { + if(! in_array(intval($target_item['item_type']), [ ITEM_TYPE_POST ] )) { logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG); return; } diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 3730f3a23..37cbf9497 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -221,6 +221,7 @@ class Apps { static public function translate_system_apps(&$arr) { $apps = array( 'Apps' => t('Apps'), + 'Cards' => t('Cards'), 'Site Admin' => t('Site Admin'), 'Report Bug' => t('Report Bug'), 'View Bookmarks' => t('View Bookmarks'), diff --git a/Zotlabs/Module/Cards.php b/Zotlabs/Module/Cards.php new file mode 100644 index 000000000..1fdd3b63f --- /dev/null +++ b/Zotlabs/Module/Cards.php @@ -0,0 +1,189 @@ + 1) + $which = argv(1); + else + return; + + profile_load($which); + + } + + + function get() { + + if(observer_prohibited(true)) { + return login(); + } + + if(! \App::$profile) { + notice( t('Requested profile is not available.') . EOL ); + \App::$error = 404; + return; + } + + if(! feature_enabled(\App::$profile_uid,'cards')) { + return; + } + + nav_set_selected(t('Cards')); + + $category = (($_REQUEST['cat']) ? escape_tags(trim($_REQUEST['cat'])) : ''); + + if($category) { + $sql_extra2 .= protect_sprintf(term_item_parent_query(\App::$profile['profile_uid'],'item', $category, TERM_CATEGORY)); + } + + + $which = argv(1); + + $_SESSION['return_url'] = \App::$query_string; + + $uid = \App::$profile_uid; + $owner = 0; + $observer = \App::get_observer(); + + $channel = \App::$profile; + + if(! $owner) { + // Figure out who the page owner is. + $r = q("select channel_id from channel where channel_address = '%s'", + dbesc($which) + ); + if($r) { + $owner = intval($r[0]['channel_id']); + } + } + + $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); + + if(! perm_is_allowed($owner,$ob_hash,'view_pages')) { + notice( t('Permission denied.') . EOL); + return; + } + + $mimetype = (($_REQUEST['mimetype']) ? $_REQUEST['mimetype'] : get_pconfig($owner,'system','page_mimetype')); + + $layout = (($_REQUEST['layout']) ? $_REQUEST['layout'] : get_pconfig($owner,'system','page_layout')); + + // Create a status editor (for now - we'll need a WYSIWYG eventually) to create pages + // Nickname is set to the observers xchan, and profile_uid to the owner's. + // This lets you post pages at other people's channels. + + if((! $channel) && ($uid) && ($uid == \App::$profile_uid)) { + $channel = \App::get_channel(); + } + if($channel) { + $channel_acl = array( + 'allow_cid' => $channel['channel_allow_cid'], + 'allow_gid' => $channel['channel_allow_gid'], + 'deny_cid' => $channel['channel_deny_cid'], + 'deny_gid' => $channel['channel_deny_gid'] + ); + } + else { + $channel_acl = [ 'allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ]; + } + + + $is_owner = ($uid && $uid == $owner); + + if(perm_is_allowed($owner,$ob_hash,'write_pages')) { + + $x = array( + 'webpage' => ITEM_TYPE_CARD, + 'is_owner' => true, + 'nickname' => \App::$profile['channel_address'], + 'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), + 'acl' => (($is_owner) ? populate_acl($channel_acl,false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')) : ''), + 'permissions' => $channel_acl, + 'showacl' => (($is_owner) ? true : false), + 'visitor' => true, + 'hide_location' => true, + 'hide_voting' => true, + 'profile_uid' => intval($owner), + 'mimetype' => $mimetype, + 'mimeselect' => false, + 'layoutselect' => false, + 'expanded' => false, + 'novoting'=> true, + 'bbco_autocomplete' => 'bbcode', + 'bbcode' => true + ); + } + else { + $x = ''; + } + + if($_REQUEST['title']) + $x['title'] = $_REQUEST['title']; + if($_REQUEST['body']) + $x['body'] = $_REQUEST['body']; + + // Get a list of webpages. We can't display all them because endless scroll makes that unusable, + // so just list titles and an edit link. + + + $sql_extra = item_permissions_sql($owner); + + $r = q("select * from item + where item.uid = %d and item_type = %d + $sql_extra order by item.created desc", + intval($owner), + intval(ITEM_TYPE_CARD) + ); + + $item_normal = " and item.item_hidden = 0 and item.item_type in (0,6) and item.item_deleted = 0 + and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0 + and item.item_blocked = 0 "; + + + if($x) + $editor = status_editor($a,$x); + + if($r) { + + $parents_str = ids_to_querystr($r,'id'); + + $items = q("SELECT item.*, item.id AS item_id + FROM item + WHERE item.uid = %d $item_normal + AND item.parent IN ( %s ) + $sql_extra $sql_extra2 ", + intval(\App::$profile['profile_uid']), + dbesc($parents_str) + ); + if($items) { + xchan_query($items); + $items = fetch_post_tags($items, true); + $items = conv_sort($items,'created'); + } + else + $items = []; + } + + $mode = 'channel'; + + $content = conversation($items,$mode,false,'traditional'); + + $o = replace_macros(get_markup_template('cards.tpl'), [ + '$title' => t('Cards'), + '$editor' => $editor, + '$content' => $content, + '$pager' => alt_pager($a,count($items)) + ]); + + return $o; + } + +} diff --git a/Zotlabs/Widget/Categories.php b/Zotlabs/Widget/Categories.php index d1dcfda93..a11b3d919 100644 --- a/Zotlabs/Widget/Categories.php +++ b/Zotlabs/Widget/Categories.php @@ -8,8 +8,13 @@ class Categories { function widget($arr) { + $cards = ((array_key_exists('cards',$arr) && $arr['cards']) ? true : false); + + if(($cards) && (! feature_enabled(\App::$profile['profile_uid'],'cards')) + return ''; + if((! \App::$profile['profile_uid']) - || (! perm_is_allowed(\App::$profile['profile_uid'],get_observer_hash(),'view_stream'))) { + || (! perm_is_allowed(\App::$profile['profile_uid'],get_observer_hash(),(($cards) ? 'view_pages' : 'view_stream')))) { return ''; } @@ -18,6 +23,10 @@ class Categories { $srchurl = rtrim(preg_replace('/cat\=[^\&].*?(\&|$)/is','',$srchurl),'&'); $srchurl = str_replace(array('?f=','&f='),array('',''),$srchurl); - return categories_widget($srchurl, $cat); + if($cards) + return cardcategories_widget($srchurl, $cat); + else + return categories_widget($srchurl, $cat); + } } diff --git a/app/cards.apd b/app/cards.apd new file mode 100644 index 000000000..4577dd681 --- /dev/null +++ b/app/cards.apd @@ -0,0 +1,5 @@ +version: 1 +url: $baseurl/cards/$nick +name: Cards +photo: icon:list +categories: Productivity diff --git a/include/contact_widgets.php b/include/contact_widgets.php index 8f76bb4bc..aac756a46 100644 --- a/include/contact_widgets.php +++ b/include/contact_widgets.php @@ -100,6 +100,49 @@ function categories_widget($baseurl,$selected = '') { return ''; } +function cardcategories_widget($baseurl,$selected = '') { + + if(! feature_enabled(App::$profile['profile_uid'],'categories')) + return ''; + + $item_normal = "and item.item_hidden = 0 and item.item_type = 6 and item.item_deleted = 0 + and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0 + and item.item_blocked = 0 "; + + $terms = array(); + $r = q("select distinct(term.term) + from term join item on term.oid = item.id + where item.uid = %d + and term.uid = item.uid + and term.ttype = %d + and term.otype = %d + and item.owner_xchan = '%s' + $item_normal + order by term.term asc", + intval(App::$profile['profile_uid']), + intval(TERM_CATEGORY), + intval(TERM_OBJ_POST), + dbesc(App::$profile['channel_hash']) + ); + if($r && count($r)) { + foreach($r as $rr) + $terms[] = array('name' => $rr['term'], 'selected' => (($selected == $rr['term']) ? 'selected' : '')); + + return replace_macros(get_markup_template('categories_widget.tpl'),array( + '$title' => t('Categories'), + '$desc' => '', + '$sel_all' => (($selected == '') ? 'selected' : ''), + '$all' => t('Everything'), + '$terms' => $terms, + '$base' => $baseurl, + + )); + } + return ''; +} + + + function common_friends_visitor_widget($profile_uid) { if(local_channel() == $profile_uid) diff --git a/include/conversation.php b/include/conversation.php index 3b8ec19d3..c9142ac30 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -1835,7 +1835,8 @@ function profile_tabs($a, $is_owner = false, $nickname = null){ require_once('include/menu.php'); $has_bookmarks = menu_list_count(local_channel(),'',MENU_BOOKMARK) + menu_list_count(local_channel(),'',MENU_SYSTEM|MENU_BOOKMARK); - if ($is_owner && $has_bookmarks) { + + if($is_owner && $has_bookmarks) { $tabs[] = array( 'label' => t('Bookmarks'), 'url' => z_root() . '/bookmarks', @@ -1846,6 +1847,17 @@ function profile_tabs($a, $is_owner = false, $nickname = null){ ); } + if(feature_enabled($uid,'cards')) { + $tabs[] = array( + 'label' => t('Cards'), + 'url' => z_root() . '/cards/' . $nickname, + 'sel' => ((argv(0) == 'cards') ? 'active' : ''), + 'title' => t('View Cards'), + 'id' => 'cards-tab', + 'icon' => 'list' + ); + } + if($has_webpages && feature_enabled($uid,'webpages')) { $tabs[] = array( 'label' => t('Webpages'), @@ -1856,7 +1868,7 @@ function profile_tabs($a, $is_owner = false, $nickname = null){ 'icon' => 'newspaper-o' ); } - + if ($p['view_wiki']) { if(feature_enabled($uid,'wiki') && (get_account_techlevel($account_id) > 3)) { diff --git a/include/features.php b/include/features.php index f32dbe82e..f84c9cb05 100644 --- a/include/features.php +++ b/include/features.php @@ -117,6 +117,15 @@ function get_features($filtered = true) { feature_level('private_notes',1), ], + [ + 'cards', + t('Cards'), + t('Create personal planning cards'), + false, + get_config('feature_lock','cards'), + feature_level('cards',1), + ], + [ 'nav_channel_select', t('Navigation Channel Select'), diff --git a/include/nav.php b/include/nav.php index 76a8f8fb9..f5a1236a8 100644 --- a/include/nav.php +++ b/include/nav.php @@ -434,6 +434,18 @@ function channel_apps($is_owner = false, $nickname = null) { ]; } + if($p['view_pages'] && feature_enabled($uid,'cards')) { + $tabs[] = [ + 'label' => t('Cards'), + 'url' => z_root() . '/cards/' . $nickname , + 'sel' => ((argv(0) == 'cards') ? 'active' : ''), + 'title' => t('View Cards'), + 'id' => 'cards-tab', + 'icon' => 'list' + ]; + } + + if($has_webpages && feature_enabled($uid,'webpages')) { $tabs[] = [ 'label' => t('Webpages'), diff --git a/include/taxonomy.php b/include/taxonomy.php index 46d661581..36e05b008 100644 --- a/include/taxonomy.php +++ b/include/taxonomy.php @@ -199,6 +199,62 @@ function tagadelic($uid, $count = 0, $authors = '', $owner = '', $flags = 0, $re } + + +function card_tagadelic($uid, $count = 0, $authors = '', $owner = '', $flags = 0, $restrict = 0, $type = TERM_CATEGORY) { + + require_once('include/security.php'); + + if(! perm_is_allowed($uid,get_observer_hash(),'view_pages')) + return array(); + + + $item_normal = item_normal(); + $sql_options = item_permissions_sql($uid); + $count = intval($count); + + if($flags) { + if($flags === 'wall') + $sql_options .= " and item_wall = 1 "; + } + + if($authors) { + if(! is_array($authors)) + $authors = array($authors); + + stringify_array_elms($authors,true); + $sql_options .= " and author_xchan in (" . implode(',',$authors) . ") "; + } + + if($owner) { + $sql_options .= " and owner_xchan = '" . dbesc($owner) . "' "; + } + + + // Fetch tags + $r = q("select term, count(term) as total from term left join item on term.oid = item.id + where term.uid = %d and term.ttype = %d + and otype = %d and item_type = %d and item_private = 0 + $sql_options $item_normal + group by term order by total desc %s", + intval($uid), + intval($type), + intval(TERM_OBJ_POST), + intval($restrict), + ((intval($count)) ? "limit $count" : '') + ); + + if(! $r) + return array(); + + return Zotlabs\Text\Tagadelic::calc($r); + +} + + + + + function dir_tagadelic($count = 0) { $count = intval($count); @@ -316,6 +372,26 @@ function catblock($uid,$count = 0,$authors = '',$owner = '', $flags = 0,$restric return $o; } +function card_catblock($uid,$count = 0,$authors = '',$owner = '', $flags = 0,$restrict = 0,$type = TERM_CATEGORY) { + $o = ''; + + $r = card_tagadelic($uid,$count,$authors,$owner,$flags,$restrict,$type); + + if($r) { + $c = q("select channel_address from channel where channel_id = %d limit 1", + intval($uid) + ); + + $o = '

' . t('Categories') . '

'; + foreach($r as $rr) { + $o .= ''.$rr[0].' ' . "\r\n"; + } + $o .= '
'; + } + + return $o; +} + function dir_tagblock($link,$r) { $o = ''; diff --git a/view/pdl/mod_cards.pdl b/view/pdl/mod_cards.pdl new file mode 100644 index 000000000..2d87136c9 --- /dev/null +++ b/view/pdl/mod_cards.pdl @@ -0,0 +1,2 @@ +[region=aside] +[widget=categories][var=cards]1[/var][/widget][/region] diff --git a/view/tpl/cards.tpl b/view/tpl/cards.tpl new file mode 100644 index 000000000..ae382a97f --- /dev/null +++ b/view/tpl/cards.tpl @@ -0,0 +1,8 @@ +
+
+

{{$title}}

+
+ {{$editor}} + {{$content}} +
+ {{$pager}} diff --git a/view/tpl/jot.tpl b/view/tpl/jot.tpl index 39ba9e59b..8e8070402 100755 --- a/view/tpl/jot.tpl +++ b/view/tpl/jot.tpl @@ -27,7 +27,7 @@ - {{if $webpage}} + {{if $webpage && $webpage != 6 }}
@@ -35,7 +35,7 @@
- {{if $catsenabled}} + {{if $catsenabled || $webpage == 6 }}
From 9518dc0e4ee40c9672e533afbb1a506c3a85c598 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 23 Aug 2017 02:03:39 -0700 Subject: [PATCH 125/441] typo --- Zotlabs/Widget/Categories.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Widget/Categories.php b/Zotlabs/Widget/Categories.php index a11b3d919..84deb03d6 100644 --- a/Zotlabs/Widget/Categories.php +++ b/Zotlabs/Widget/Categories.php @@ -10,7 +10,7 @@ class Categories { $cards = ((array_key_exists('cards',$arr) && $arr['cards']) ? true : false); - if(($cards) && (! feature_enabled(\App::$profile['profile_uid'],'cards')) + if(($cards) && (! feature_enabled(\App::$profile['profile_uid'],'cards'))) return ''; if((! \App::$profile['profile_uid']) From 3b68df1be6173cbcc50386efc0161ece2015112d Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 23 Aug 2017 17:46:20 -0700 Subject: [PATCH 126/441] several card enhancements --- Zotlabs/Lib/ThreadItem.php | 5 +- Zotlabs/Module/Card_edit.php | 135 +++++++++++++++++++++++++++++++++++ Zotlabs/Module/Cards.php | 54 ++++++-------- app/cards.apd | 3 +- boot.php | 2 + include/conversation.php | 7 +- include/items.php | 2 + view/tpl/jot.tpl | 4 +- 8 files changed, 175 insertions(+), 37 deletions(-) create mode 100644 Zotlabs/Module/Card_edit.php diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index ad944203c..526169e1b 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -101,10 +101,13 @@ class ThreadItem { if($item['author']['xchan_network'] === 'rss') $shareable = true; + $mode = $conv->get_mode(); + $edlink = (($item['item_type'] == ITEM_TYPE_CARD) ? 'card_edit' : 'editpost'); + if(local_channel() && $observer['xchan_hash'] === $item['author_xchan']) - $edpost = array(z_root()."/editpost/".$item['id'], t("Edit")); + $edpost = array(z_root() . '/' . $edlink . '/' . $item['id'], t('Edit')); else $edpost = false; diff --git a/Zotlabs/Module/Card_edit.php b/Zotlabs/Module/Card_edit.php new file mode 100644 index 000000000..216d2cf63 --- /dev/null +++ b/Zotlabs/Module/Card_edit.php @@ -0,0 +1,135 @@ + 1) ? intval(argv(1)) : 0); + + if(! $post_id) { + notice( t('Item not found') . EOL); + return; + } + + $itm = q("SELECT * FROM item WHERE id = %d and item_type = %d LIMIT 1", + intval($post_id), + intval(ITEM_TYPE_CARD) + ); + if($itm) { + $item_id = q("select * from iconfig where cat = 'system' and k = 'CARD' and iid = %d limit 1", + intval($itm[0]['id']) + ); + if($item_id) + $card_title = $item_id[0]['v']; + } + else { + notice( t('Item not found') . EOL); + return; + } + + $owner = $itm[0]['uid']; + $uid = local_channel(); + + $observer = \App::get_observer(); + + $channel = channelx_by_n($owner); + if(! $channel) { + notice( t('Channel not found.') . EOL); + return; + } + + $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); + + if(! perm_is_allowed($owner,$ob_hash,'write_pages')) { + notice( t('Permission denied.') . EOL); + return; + } + + $is_owner = (($uid && $uid == $owner) ? true : false); + + $o = ''; + + + + $category = ''; + $catsenabled = ((feature_enabled($owner,'categories')) ? 'categories' : ''); + + if ($catsenabled){ + $itm = fetch_post_tags($itm); + + $cats = get_terms_oftype($itm[0]['term'], TERM_CATEGORY); + + foreach ($cats as $cat) { + if (strlen($category)) + $category .= ', '; + $category .= $cat['term']; + } + } + + if($itm[0]['attach']) { + $j = json_decode($itm[0]['attach'],true); + if($j) { + foreach($j as $jj) { + $itm[0]['body'] .= "\n" . '[attachment]' . basename($jj['href']) . ',' . $jj['revision'] . '[/attachment]' . "\n"; + } + } + } + + + $mimetype = $itm[0]['mimetype']; + + $content = $itm[0]['body']; + + + + $rp = 'cards/' . $channel['channel_address']; + + $x = array( + 'nickname' => $channel['channel_address'], + 'bbco_autocomplete'=> 'bbcode', + 'return_path' => $rp, + 'webpage' => ITEM_TYPE_CARD, + 'button' => t('Edit'), + 'writefiles' => perm_is_allowed($owner, get_observer_hash(), 'write_pages'), + 'weblink' => t('Insert web link'), + 'hide_voting' => false, + 'hide_future' => false, + 'hide_location' => false, + 'hide_expire' => false, + 'showacl' => true, + 'ptyp' => $itm[0]['type'], + 'mimeselect' => false, + 'mimetype' => $itm[0]['mimetype'], + 'body' => undo_post_tagging($content), + 'post_id' => $post_id, + 'visitor' => true, + 'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'), + 'placeholdertitle' => t('Title (optional)'), + 'pagetitle' => $card_title, + 'profile_uid' => (intval($channel['channel_id'])), + 'catsenabled' => $catsenabled, + 'category' => $category, + 'bbcode' => (($mimetype == 'text/bbcode') ? true : false) + ); + + $editor = status_editor($a, $x); + + $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( + '$title' => t('Edit Block'), + '$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false), + '$id' => $itm[0]['id'], + '$editor' => $editor + )); + + return $o; + + } + +} diff --git a/Zotlabs/Module/Cards.php b/Zotlabs/Module/Cards.php index 1fdd3b63f..1c37ca13d 100644 --- a/Zotlabs/Module/Cards.php +++ b/Zotlabs/Module/Cards.php @@ -47,24 +47,14 @@ class Cards extends \Zotlabs\Web\Controller { $which = argv(1); + $selected_card = ((argc() > 2) ? argv(2) : ''); + $_SESSION['return_url'] = \App::$query_string; - $uid = \App::$profile_uid; - $owner = 0; + $uid = local_channel(); + $owner = \App::$profile_uid; $observer = \App::get_observer(); - $channel = \App::$profile; - - if(! $owner) { - // Figure out who the page owner is. - $r = q("select channel_id from channel where channel_address = '%s'", - dbesc($which) - ); - if($r) { - $owner = intval($r[0]['channel_id']); - } - } - $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); if(! perm_is_allowed($owner,$ob_hash,'view_pages')) { @@ -76,13 +66,10 @@ class Cards extends \Zotlabs\Web\Controller { $layout = (($_REQUEST['layout']) ? $_REQUEST['layout'] : get_pconfig($owner,'system','page_layout')); - // Create a status editor (for now - we'll need a WYSIWYG eventually) to create pages - // Nickname is set to the observers xchan, and profile_uid to the owner's. - // This lets you post pages at other people's channels. + $is_owner = ($uid && $uid == $owner); - if((! $channel) && ($uid) && ($uid == \App::$profile_uid)) { - $channel = \App::get_channel(); - } + $channel = channelx_by_n($owner); + if($channel) { $channel_acl = array( 'allow_cid' => $channel['channel_allow_cid'], @@ -95,28 +82,25 @@ class Cards extends \Zotlabs\Web\Controller { $channel_acl = [ 'allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ]; } - - $is_owner = ($uid && $uid == $owner); - if(perm_is_allowed($owner,$ob_hash,'write_pages')) { $x = array( 'webpage' => ITEM_TYPE_CARD, 'is_owner' => true, - 'nickname' => \App::$profile['channel_address'], + 'nickname' => $channel['channel_address'], 'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), 'acl' => (($is_owner) ? populate_acl($channel_acl,false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')) : ''), 'permissions' => $channel_acl, 'showacl' => (($is_owner) ? true : false), 'visitor' => true, - 'hide_location' => true, - 'hide_voting' => true, + 'hide_location' => false, + 'hide_voting' => false, 'profile_uid' => intval($owner), 'mimetype' => $mimetype, 'mimeselect' => false, 'layoutselect' => false, 'expanded' => false, - 'novoting'=> true, + 'novoting'=> false, 'bbco_autocomplete' => 'bbcode', 'bbcode' => true ); @@ -130,12 +114,18 @@ class Cards extends \Zotlabs\Web\Controller { if($_REQUEST['body']) $x['body'] = $_REQUEST['body']; - // Get a list of webpages. We can't display all them because endless scroll makes that unusable, - // so just list titles and an edit link. - - + $sql_extra = item_permissions_sql($owner); - + + if($selected_card) { + $r = q("select * from iconfig where iconfig.cat = 'system' and iconfig.k = 'CARD' and iconfig.v = '%s' limit 1", + dbesc($selected_card) + ); + if($r) { + $sql_extra .= "and item.id = " . intval($r[0]['iid']) . " "; + } + } + $r = q("select * from item where item.uid = %d and item_type = %d $sql_extra order by item.created desc", diff --git a/app/cards.apd b/app/cards.apd index 4577dd681..047aaeac9 100644 --- a/app/cards.apd +++ b/app/cards.apd @@ -1,5 +1,6 @@ -version: 1 +version: 1.1 url: $baseurl/cards/$nick name: Cards +requires: local_channel, cards photo: icon:list categories: Productivity diff --git a/boot.php b/boot.php index 94f66e5a7..d9a6cd230 100755 --- a/boot.php +++ b/boot.php @@ -548,6 +548,8 @@ define ( 'ITEM_PDL', 0x0200); // Page Description Language - e.g. Comanche define ( 'ITEM_BUG', 0x0400); // Is a bug, can be used by the internal bug tracker define ( 'ITEM_PENDING_REMOVE', 0x0800); // deleted, notification period has lapsed define ( 'ITEM_DOC', 0x1000); // hubzilla only, define here so that item import does the right thing +define ( 'ITEM_CARD', 0x2000); + define ( 'ITEM_TYPE_POST', 0 ); define ( 'ITEM_TYPE_BLOCK', 1 ); diff --git a/include/conversation.php b/include/conversation.php index c9142ac30..e0de6fdce 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -1305,6 +1305,11 @@ function status_editor($a, $x, $popup = false) { if(! $cipher) $cipher = 'aes256'; + if(array_key_exists('catsenabled',$x)) + $catsenabled = $x['catsenabled']; + else + $catsenabled = ((feature_enabled($x['profile_uid'], 'categories') && (! $webpage)) ? 'categories' : ''); + // avoid illegal offset errors if(! array_key_exists('permissions',$x)) $x['permissions'] = [ 'allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ]; @@ -1349,7 +1354,7 @@ function status_editor($a, $x, $popup = false) { '$clearloc' => $clearloc, '$title' => ((x($x, 'title')) ? htmlspecialchars($x['title'], ENT_COMPAT,'UTF-8') : ''), '$placeholdertitle' => ((x($x, 'placeholdertitle')) ? $x['placeholdertitle'] : t('Title (optional)')), - '$catsenabled' => ((feature_enabled($x['profile_uid'], 'categories') && (! $webpage)) ? 'categories' : ''), + '$catsenabled' => $catsenabled, '$category' => ((x($x, 'category')) ? $x['category'] : ''), '$placeholdercategory' => t('Categories (optional, comma-separated list)'), '$permset' => t('Permission settings'), diff --git a/include/items.php b/include/items.php index e7bec7f20..070c4571a 100755 --- a/include/items.php +++ b/include/items.php @@ -4111,6 +4111,8 @@ function webpage_to_namespace($webpage) { $page_type = 'BUILDBLOCK'; elseif($webpage == ITEM_TYPE_PDL) $page_type = 'PDL'; + elseif($webpage == ITEM_TYPE_CARD) + $page_type = 'CARD'; elseif($webpage == ITEM_TYPE_DOC) $page_type = 'docfile'; else diff --git a/view/tpl/jot.tpl b/view/tpl/jot.tpl index 8e8070402..39ba9e59b 100755 --- a/view/tpl/jot.tpl +++ b/view/tpl/jot.tpl @@ -27,7 +27,7 @@ - {{if $webpage && $webpage != 6 }} + {{if $webpage}}
@@ -35,7 +35,7 @@
- {{if $catsenabled || $webpage == 6 }} + {{if $catsenabled}}
From ecfc7b8f4cc6fbc646e58a2445398341fae5e642 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 23 Aug 2017 18:15:31 -0700 Subject: [PATCH 127/441] add category support to main page --- Zotlabs/Module/Cards.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Zotlabs/Module/Cards.php b/Zotlabs/Module/Cards.php index 1c37ca13d..c542cd6ff 100644 --- a/Zotlabs/Module/Cards.php +++ b/Zotlabs/Module/Cards.php @@ -82,6 +82,8 @@ class Cards extends \Zotlabs\Web\Controller { $channel_acl = [ 'allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ]; } + + if(perm_is_allowed($owner,$ob_hash,'write_pages')) { $x = array( @@ -101,6 +103,7 @@ class Cards extends \Zotlabs\Web\Controller { 'layoutselect' => false, 'expanded' => false, 'novoting'=> false, + 'catsenabled' => feature_enabled($owner,'categories'), 'bbco_autocomplete' => 'bbcode', 'bbcode' => true ); From 89df4551aa22aa4c9a30221d4b13ae715673d567 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 23 Aug 2017 18:20:12 -0700 Subject: [PATCH 128/441] cards: acl support --- Zotlabs/Module/Card_edit.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Zotlabs/Module/Card_edit.php b/Zotlabs/Module/Card_edit.php index 216d2cf63..b5b44c567 100644 --- a/Zotlabs/Module/Card_edit.php +++ b/Zotlabs/Module/Card_edit.php @@ -104,6 +104,7 @@ class Card_edit extends \Zotlabs\Web\Controller { 'hide_location' => false, 'hide_expire' => false, 'showacl' => true, + 'acl' => populate_acl($itm[0],false,\Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')), 'ptyp' => $itm[0]['type'], 'mimeselect' => false, 'mimetype' => $itm[0]['mimetype'], From 8873fbfee9a8c0437fa1acdf1588aeb3fd3e7681 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 23 Aug 2017 19:18:44 -0700 Subject: [PATCH 129/441] fix permalink for cards --- Zotlabs/Module/Item.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index 5e7a3fbc0..797b46f93 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -735,6 +735,10 @@ class Item extends \Zotlabs\Web\Controller { if($parent_item) $parent_mid = $parent_item['mid']; + if($webpage == ITEM_TYPE_CARD && $pagetitle) { + $plink = z_root() . '/cards/' . $channel['channel_address'] . '/' . $pagetitle; + } + // Fallback so that we alway have a thr_parent if(!$thr_parent) From 64cf36a2b5dc314728fbb262471f1dd7b0ad2d96 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 23 Aug 2017 19:25:42 -0700 Subject: [PATCH 130/441] lognoise: don't log sync packet contents if there are no clones to receive them --- include/zot.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/zot.php b/include/zot.php index 3e2a66734..343bc8ad8 100644 --- a/include/zot.php +++ b/include/zot.php @@ -2965,8 +2965,6 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { logger('build_sync_packet'); - if($packet) - logger('packet: ' . print_r($packet, true),LOGGER_DATA, LOG_DEBUG); $keychange = (($packet && array_key_exists('keychange',$packet)) ? true : false); if($keychange) { @@ -3033,6 +3031,9 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { $env_recips = array(); $env_recips[] = array('guid' => $r[0]['xchan_guid'],'guid_sig' => $r[0]['xchan_guid_sig']); + if($packet) + logger('packet: ' . print_r($packet, true),LOGGER_DATA, LOG_DEBUG); + $info = (($packet) ? $packet : array()); $info['type'] = 'channel_sync'; $info['encoding'] = 'red'; // note: not zot, this packet is very platform specific From f2e802229acb871e0b50afb729445cdef8586951 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 23 Aug 2017 20:02:28 -0700 Subject: [PATCH 131/441] add new conv_sort option --- Zotlabs/Module/Cards.php | 2 +- include/conversation.php | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Zotlabs/Module/Cards.php b/Zotlabs/Module/Cards.php index c542cd6ff..33688cba0 100644 --- a/Zotlabs/Module/Cards.php +++ b/Zotlabs/Module/Cards.php @@ -159,7 +159,7 @@ class Cards extends \Zotlabs\Web\Controller { if($items) { xchan_query($items); $items = fetch_post_tags($items, true); - $items = conv_sort($items,'created'); + $items = conv_sort($items,'updated'); } else $items = []; diff --git a/include/conversation.php b/include/conversation.php index e0de6fdce..2448775af 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -1461,6 +1461,8 @@ function conv_sort($arr, $order) { usort($parents,'sort_thr_created'); elseif(stristr($order,'commented')) usort($parents,'sort_thr_commented'); + elseif(stristr($order,'updated')) + usort($parents,'sort_thr_updated'); elseif(stristr($order,'ascending')) usort($parents,'sort_thr_created_rev'); @@ -1502,6 +1504,10 @@ function sort_thr_commented($a,$b) { return strcmp($b['commented'],$a['commented']); } +function sort_thr_updated($a,$b) { + return strcmp($b['updated'],$a['updated']); +} + function find_thread_parent_index($arr,$x) { foreach($arr as $k => $v) if($v['id'] == $x['parent']) From e7788156052bcb3676fe761f89769c2d72dc4bca Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 23 Aug 2017 20:12:40 -0700 Subject: [PATCH 132/441] use two keys for the updated sort --- include/conversation.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/conversation.php b/include/conversation.php index 2448775af..7e0394058 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -1505,7 +1505,9 @@ function sort_thr_commented($a,$b) { } function sort_thr_updated($a,$b) { - return strcmp($b['updated'],$a['updated']); + $indexa = (($a['changed'] > $a['edited']) ? $a['changed'] : $a['edited']); + $indexb = (($b['changed'] > $b['edited']) ? $b['changed'] : $b['edited']); + return strcmp($indexb,$indexa); } function find_thread_parent_index($arr,$x) { From bf7b0b11ef7a8d110f2fc2a5967d8178183d9435 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 23 Aug 2017 20:16:08 -0700 Subject: [PATCH 133/441] add autotime to cards --- view/js/mod_cards.js | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 view/js/mod_cards.js diff --git a/view/js/mod_cards.js b/view/js/mod_cards.js new file mode 100644 index 000000000..477cd61ed --- /dev/null +++ b/view/js/mod_cards.js @@ -0,0 +1,4 @@ +$(document).ready( function() { + $("> .wall-item-outside-wrapper .autotime, > .thread-wrapper .autotime").timeago(); + $("> .shared_header .autotime").timeago(); +}); \ No newline at end of file From c9745a41295337444832f0c787d0dd4fb3425e1f Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 23 Aug 2017 20:19:52 -0700 Subject: [PATCH 134/441] apply autotime to all autotime classed elements when static loading a page --- view/js/mod_cards.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/view/js/mod_cards.js b/view/js/mod_cards.js index 477cd61ed..78b2e1bd0 100644 --- a/view/js/mod_cards.js +++ b/view/js/mod_cards.js @@ -1,4 +1,3 @@ $(document).ready( function() { - $("> .wall-item-outside-wrapper .autotime, > .thread-wrapper .autotime").timeago(); - $("> .shared_header .autotime").timeago(); + $(".autotime").timeago(); }); \ No newline at end of file From 66b032823b4fd941f613b0194bb8412b216cc748 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 23 Aug 2017 20:47:08 -0700 Subject: [PATCH 135/441] oembed provider cleanup, add oembed to cards --- Zotlabs/Module/Cards.php | 8 +++ Zotlabs/Module/Channel.php | 7 ++- Zotlabs/Module/Display.php | 9 ++-- Zotlabs/Module/Oep.php | 106 ++++++++++++++++++++++++++++++++++++- Zotlabs/Module/Photos.php | 9 +++- Zotlabs/Module/Profile.php | 14 ++--- 6 files changed, 139 insertions(+), 14 deletions(-) diff --git a/Zotlabs/Module/Cards.php b/Zotlabs/Module/Cards.php index 33688cba0..f354544d5 100644 --- a/Zotlabs/Module/Cards.php +++ b/Zotlabs/Module/Cards.php @@ -38,6 +38,14 @@ class Cards extends \Zotlabs\Web\Controller { nav_set_selected(t('Cards')); + head_add_link([ + 'rel' => 'alternate', + 'type' => 'application/json+oembed', + 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string), + 'title' => 'oembed' + ]); + + $category = (($_REQUEST['cat']) ? escape_tags(trim($_REQUEST['cat'])) : ''); if($category) { diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index c006d65d4..5e7db79d9 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -180,7 +180,12 @@ class Channel extends \Zotlabs\Web\Controller { $simple_update = (($update) ? " AND item_unseen = 1 " : ''); - \App::$page['htmlhead'] .= "\r\n" . '' . "\r\n"; + head_add_link([ + 'rel' => 'alternate', + 'type' => 'application/json+oembed', + 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string), + 'title' => 'oembed' + ]); if($update && $_SESSION['loadtime']) $simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) "; diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php index 1077cbdb9..b698513ba 100644 --- a/Zotlabs/Module/Display.php +++ b/Zotlabs/Module/Display.php @@ -175,9 +175,12 @@ class Display extends \Zotlabs\Web\Controller { '$mid' => $item_hash )); - \App::$page['htmlhead'] .= "\r\n" . '' . "\r\n"; - - + head_add_link([ + 'rel' => 'alternate', + 'type' => 'application/json+oembed', + 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string), + 'title' => 'oembed' + ]); } $observer_hash = get_observer_hash(); diff --git a/Zotlabs/Module/Oep.php b/Zotlabs/Module/Oep.php index 6469a7007..02aa4aba9 100644 --- a/Zotlabs/Module/Oep.php +++ b/Zotlabs/Module/Oep.php @@ -41,6 +41,8 @@ class Oep extends \Zotlabs\Web\Controller { $arr = $this->oep_profile_reply($_REQUEST); elseif(fnmatch('*/profile/*',$url)) $arr = $this->oep_profile_reply($_REQUEST); + elseif(fnmatch('*/cards/*',$url)) + $arr = $this->oep_cards_reply($_REQUEST); if($arr) { if($html) { @@ -89,7 +91,10 @@ class Oep extends \Zotlabs\Web\Controller { if(! ($c && $res)) return; - + + if(! perm_is_allowed($c[0]['channel_id'],get_observer_hash(),'view_stream')) + return; + $sql_extra = item_permissions_sql($c['channel_id']); $p = q("select * from item where mid like '%s' and uid = %d $sql_extra $item_normal limit 1", @@ -140,6 +145,91 @@ class Oep extends \Zotlabs\Web\Controller { return $ret; } + + + function oep_cards_reply($args) { + + $ret = []; + $url = $args['url']; + $maxwidth = intval($args['maxwidth']); + $maxheight = intval($args['maxheight']); + + if(preg_match('#//(.*?)/cards/(.*?)/(.*?)(&|\?|$)#',$url,$matches)) { + $nick = $matches[2]; + $res = $matches[3]; + } + if(! ($nick && $res)) + return $ret; + + $channel = channelx_by_nick($nick); + + if(! $channel) + return $ret; + + + if(! perm_is_allowed($channel['channel_id'],get_observer_hash(),'view_pages')) + return $ret; + + $sql_extra = items_permissions_sql($channel['channel_id'],get_observer_hash()); + + $r = q("select * from iconfig where iconfig.cat = 'system' and iconfig.k = 'CARD' and iconfig.v = '%s' limit 1", + dbesc($res) + ); + if($r) { + $sql_extra = "and item.id = " . intval($r[0]['iid']) . " "; + } + else { + return $ret; + } + + $r = q("select * from item + where item.uid = %d and item_type = %d + $sql_extra order by item.created desc", + intval($channel['channel_id']), + intval(ITEM_TYPE_CARD) + ); + + $item_normal = " and item.item_hidden = 0 and item.item_type in (0,6) and item.item_deleted = 0 + and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0 + and item.item_blocked = 0 "; + + if($r) { + xchan_query($r); + $p = fetch_post_tags($r, true); + } + + $x = '2eGriplW^*Jmf4'; + + + $o = "[share author='".urlencode($p[0]['author']['xchan_name']). + "' profile='".$p[0]['author']['xchan_url'] . + "' avatar='".$p[0]['author']['xchan_photo_s']. + "' link='".$p[0]['plink']. + "' posted='".$p[0]['created']. + "' message_id='".$p[0]['mid']."']"; + if($p[0]['title']) + $o .= '[b]'.$p[0]['title'].'[/b]'."\r\n"; + + $o .= $x; + $o .= "[/share]"; + $o = bbcode($o); + + $o = str_replace($x,bbcode($p[0]['body']),$o); + + $ret['type'] = 'rich'; + + $w = (($maxwidth) ? $maxwidth : 640); + $h = (($maxheight) ? $maxheight : intval($w * 2 / 3)); + + $ret['html'] = '
' . $o . '
'; + + $ret['width'] = $w; + $ret['height'] = $h; + + return $ret; + + } + function oep_mid_reply($args) { @@ -161,6 +251,9 @@ class Oep extends \Zotlabs\Web\Controller { if(! $c) return; + + if(! perm_is_allowed($c[0]['channel_id'],get_observer_hash(),'view_stream')) + return; $sql_extra = item_permissions_sql($c[0]['channel_id']); @@ -279,6 +372,9 @@ class Oep extends \Zotlabs\Web\Controller { if(! $c) return; + if(! perm_is_allowed($c[0]['channel_id'],get_observer_hash(),'view_files')) + return; + $sql_extra = permissions_sql($c[0]['channel_id']); $p = q("select resource_id from photo where album = '%s' and uid = %d and imgscale = 0 $sql_extra order by created desc limit 1", @@ -340,6 +436,9 @@ class Oep extends \Zotlabs\Web\Controller { if(! $c) return; + if(! perm_is_allowed($c[0]['channel_id'],get_observer_hash(),'view_files')) + return; + $sql_extra = permissions_sql($c[0]['channel_id']); $p = q("select resource_id from photo where uid = %d and imgscale = 0 $sql_extra order by created desc limit 1", @@ -400,7 +499,10 @@ class Oep extends \Zotlabs\Web\Controller { if(! $c) return; - + + if(! perm_is_allowed($c[0]['channel_id'],get_observer_hash(),'view_files')) + return; + $sql_extra = permissions_sql($c[0]['channel_id']); diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php index 0f80f46a5..bb7079a6a 100644 --- a/Zotlabs/Module/Photos.php +++ b/Zotlabs/Module/Photos.php @@ -671,8 +671,13 @@ class Photos extends \Zotlabs\Web\Controller { */ if($datatype === 'album') { - - \App::$page['htmlhead'] .= "\r\n" . '' . "\r\n"; + + 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); diff --git a/Zotlabs/Module/Profile.php b/Zotlabs/Module/Profile.php index 6930d50ca..43106e3af 100644 --- a/Zotlabs/Module/Profile.php +++ b/Zotlabs/Module/Profile.php @@ -94,7 +94,6 @@ class Profile extends \Zotlabs\Web\Controller { echo \App::$profile['profile_vcard']; killme(); } - $is_owner = ((local_channel()) && (local_channel() == \App::$profile['profile_uid']) ? true : false); @@ -102,11 +101,14 @@ class Profile extends \Zotlabs\Web\Controller { notice( t('Permission denied.') . EOL); return; } - - //$o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']); - - \App::$page['htmlhead'] .= "\r\n" . '' . "\r\n"; - + + head_add_link([ + 'rel' => 'alternate', + 'type' => 'application/json+oembed', + 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string), + 'title' => 'oembed' + ]); + $o .= advanced_profile($a); call_hooks('profile_advanced',$o); return $o; From 4450170790de3999dc9c6f8876074e76edee8241 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 23 Aug 2017 21:26:09 -0700 Subject: [PATCH 136/441] partial support (unfinished) for ajax loading cards with liveupdate; page still functions even though this isn't finished --- Zotlabs/Module/Cards.php | 5 ++--- Zotlabs/Module/Update_cards.php | 39 +++++++++++++++++++++++++++++++++ include/conversation.php | 9 ++++++++ view/js/main.js | 1 + 4 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 Zotlabs/Module/Update_cards.php diff --git a/Zotlabs/Module/Cards.php b/Zotlabs/Module/Cards.php index f354544d5..19932769f 100644 --- a/Zotlabs/Module/Cards.php +++ b/Zotlabs/Module/Cards.php @@ -19,8 +19,7 @@ class Cards extends \Zotlabs\Web\Controller { } - - function get() { + function get($update = 0, $load = false) { if(observer_prohibited(true)) { return login(); @@ -173,7 +172,7 @@ class Cards extends \Zotlabs\Web\Controller { $items = []; } - $mode = 'channel'; + $mode = 'cards'; $content = conversation($items,$mode,false,'traditional'); diff --git a/Zotlabs/Module/Update_cards.php b/Zotlabs/Module/Update_cards.php new file mode 100644 index 000000000..bb87357e8 --- /dev/null +++ b/Zotlabs/Module/Update_cards.php @@ -0,0 +1,39 @@ + 1) && (argv(1) == 'load')) ? 1 : 0); + + header("Content-type: text/html"); + echo "
\r\n"; + + killme(); + + + $mod = new Cards(); + + $text = $mod->get($profile_uid,$load); + + /** + * reportedly some versions of MSIE don't handle tabs in XMLHttpRequest documents very well + */ + + echo str_replace("\t",' ',$text); + echo (($_GET['msie'] == 1) ? '' : ''); + echo "\r\n"; + killme(); + +} +} diff --git a/include/conversation.php b/include/conversation.php index 7e0394058..0d2dd2224 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -517,6 +517,15 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa } } + elseif ($mode === 'cards') { + $profile_owner = App::$profile['profile_uid']; + $page_writeable = ($profile_owner == local_channel()); + $live_update_div = '
' . "\r\n" + . "\r\n"; + } + + elseif ($mode === 'display') { $profile_owner = local_channel(); $page_writeable = false; diff --git a/view/js/main.js b/view/js/main.js index f20432735..bbdb0759b 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -380,6 +380,7 @@ function NavUpdate() { if($('#live-pubstream').length) { src = 'pubstream'; liveUpdate(); } if($('#live-display').length) { src = 'display'; liveUpdate(); } if($('#live-search').length) { src = 'search'; liveUpdate(); } + if($('#live-cards').length) { src = 'cards'; liveUpdate(); } if($('#live-photos').length) { if(liking) { From e157e3bec8722c04ed8dc2d215cd2efd0ce3ce79 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 23 Aug 2017 22:06:42 -0700 Subject: [PATCH 137/441] cards: make page load after comment post --- Zotlabs/Lib/ThreadItem.php | 11 +++++- Zotlabs/Lib/ThreadStream.php | 6 ++++ Zotlabs/Module/Cards.php | 70 +++++++++++++++++------------------- include/conversation.php | 6 ++++ 4 files changed, 55 insertions(+), 38 deletions(-) diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index 526169e1b..313001cc7 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -29,6 +29,7 @@ class ThreadItem { private $visiting = false; private $channel = null; private $display_mode = 'normal'; + private $reload = ''; public function __construct($data) { @@ -483,6 +484,14 @@ class ThreadItem { return $this->threaded; } + public function set_reload($val) { + $this->reload = $val; + } + + public function get_reload() { + return $this->reload; + } + public function set_commentable($val) { $this->commentable = $val; foreach($this->get_children() as $child) @@ -719,7 +728,7 @@ class ThreadItem { $comment_box = replace_macros($template,array( '$return_path' => '', '$threaded' => $this->is_threaded(), - '$jsreload' => '', //(($conv->get_mode() === 'display') ? $_SESSION['return_url'] : ''), + '$jsreload' => $conv->reload, '$type' => (($conv->get_mode() === 'channel') ? 'wall-comment' : 'net-comment'), '$id' => $this->get_id(), '$parent' => $this->get_id(), diff --git a/Zotlabs/Lib/ThreadStream.php b/Zotlabs/Lib/ThreadStream.php index 0465b20ef..d7a898704 100644 --- a/Zotlabs/Lib/ThreadStream.php +++ b/Zotlabs/Lib/ThreadStream.php @@ -22,6 +22,7 @@ class ThreadStream { private $profile_owner = 0; private $preview = false; private $prepared_item = ''; + public $reload = ''; private $cipher = 'aes256'; // $prepared_item is for use by alternate conversation structures such as photos @@ -57,6 +58,11 @@ class ThreadStream { $this->profile_owner = \App::$profile['profile_uid']; $this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments'); break; + case 'cards': + $this->profile_owner = \App::$profile['profile_uid']; + $this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments'); + $this->reload = $_SESSION['return_url']; + break; case 'display': // in this mode we set profile_owner after initialisation (from conversation()) and then // pull some trickery which allows us to re-invoke this function afterward diff --git a/Zotlabs/Module/Cards.php b/Zotlabs/Module/Cards.php index 19932769f..9114e3b89 100644 --- a/Zotlabs/Module/Cards.php +++ b/Zotlabs/Module/Cards.php @@ -58,8 +58,8 @@ class Cards extends \Zotlabs\Web\Controller { $_SESSION['return_url'] = \App::$query_string; - $uid = local_channel(); - $owner = \App::$profile_uid; + $uid = local_channel(); + $owner = \App::$profile_uid; $observer = \App::get_observer(); $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); @@ -68,11 +68,7 @@ class Cards extends \Zotlabs\Web\Controller { notice( t('Permission denied.') . EOL); return; } - - $mimetype = (($_REQUEST['mimetype']) ? $_REQUEST['mimetype'] : get_pconfig($owner,'system','page_mimetype')); - - $layout = (($_REQUEST['layout']) ? $_REQUEST['layout'] : get_pconfig($owner,'system','page_layout')); - + $is_owner = ($uid && $uid == $owner); $channel = channelx_by_n($owner); @@ -93,38 +89,42 @@ class Cards extends \Zotlabs\Web\Controller { if(perm_is_allowed($owner,$ob_hash,'write_pages')) { - $x = array( - 'webpage' => ITEM_TYPE_CARD, - 'is_owner' => true, - 'nickname' => $channel['channel_address'], - 'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), - 'acl' => (($is_owner) ? populate_acl($channel_acl,false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')) : ''), - 'permissions' => $channel_acl, - 'showacl' => (($is_owner) ? true : false), - 'visitor' => true, - 'hide_location' => false, - 'hide_voting' => false, - 'profile_uid' => intval($owner), - 'mimetype' => $mimetype, - 'mimeselect' => false, - 'layoutselect' => false, - 'expanded' => false, - 'novoting'=> false, - 'catsenabled' => feature_enabled($owner,'categories'), + $x = [ + 'webpage' => ITEM_TYPE_CARD, + 'is_owner' => true, + 'nickname' => $channel['channel_address'], + 'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] + || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), + 'acl' => (($is_owner) ? populate_acl($channel_acl, false, + \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')) : ''), + 'permissions' => $channel_acl, + 'showacl' => (($is_owner) ? true : false), + 'visitor' => true, + 'hide_location' => false, + 'hide_voting' => false, + 'profile_uid' => intval($owner), + 'mimetype' => 'text/bbcode', + 'mimeselect' => false, + 'layoutselect' => false, + 'expanded' => false, + 'novoting' => false, + 'catsenabled' => feature_enabled($owner,'categories'), 'bbco_autocomplete' => 'bbcode', - 'bbcode' => true - ); + 'bbcode' => true + ]; + + if($_REQUEST['title']) + $x['title'] = $_REQUEST['title']; + if($_REQUEST['body']) + $x['body'] = $_REQUEST['body']; + $editor = status_editor($a,$x); + } else { - $x = ''; + $editor = ''; } - if($_REQUEST['title']) - $x['title'] = $_REQUEST['title']; - if($_REQUEST['body']) - $x['body'] = $_REQUEST['body']; - $sql_extra = item_permissions_sql($owner); if($selected_card) { @@ -147,10 +147,6 @@ class Cards extends \Zotlabs\Web\Controller { and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0 and item.item_blocked = 0 "; - - if($x) - $editor = status_editor($a,$x); - if($r) { $parents_str = ids_to_querystr($r,'id'); diff --git a/include/conversation.php b/include/conversation.php index 0d2dd2224..2d5ccb5b1 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -464,6 +464,7 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa $profile_owner = 0; $page_writeable = false; $live_update_div = ''; + $jsreload = ''; $preview = (($page_mode === 'preview') ? true : false); $previewing = (($preview) ? ' preview ' : ''); @@ -523,6 +524,7 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa $live_update_div = '
' . "\r\n" . "\r\n"; + $jsreload = $_SESSION['return_url']; } @@ -817,6 +819,10 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa $item_object->set_template('conv_list.tpl'); $item_object->set_display_mode('list'); } + if($page_mode === 'cards') { + $item_object->set_reload($jsreload); + } + } } From 186f85483fe3ab45281c442b2b275448c5230c4f Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 23 Aug 2017 22:17:15 -0700 Subject: [PATCH 138/441] cards: make likes reload page --- view/js/main.js | 4 ++-- view/tpl/cards.tpl | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/view/js/main.js b/view/js/main.js index bbdb0759b..fd3c8b08f 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -380,9 +380,9 @@ function NavUpdate() { if($('#live-pubstream').length) { src = 'pubstream'; liveUpdate(); } if($('#live-display').length) { src = 'display'; liveUpdate(); } if($('#live-search').length) { src = 'search'; liveUpdate(); } - if($('#live-cards').length) { src = 'cards'; liveUpdate(); } + // if($('#live-cards').length) { src = 'cards'; liveUpdate(); } - if($('#live-photos').length) { + if($('#live-photos').length || $('#live-cards').length) { if(liking) { liking = 0; window.location.href=window.location.href; diff --git a/view/tpl/cards.tpl b/view/tpl/cards.tpl index ae382a97f..a06e2fd22 100644 --- a/view/tpl/cards.tpl +++ b/view/tpl/cards.tpl @@ -2,6 +2,7 @@

{{$title}}

+
{{$editor}} {{$content}} From af8ed605f8619fa9ec14521137d7781f3f0f97ef Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 23 Aug 2017 22:40:52 -0700 Subject: [PATCH 139/441] add a section to the admin guide about admin rights and how to grant them if the first account on the system used a different email address than the desired administrator email. --- doc/admin/administrator_guide.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/admin/administrator_guide.md b/doc/admin/administrator_guide.md index 9e0ee3c59..e3b6190cb 100644 --- a/doc/admin/administrator_guide.md +++ b/doc/admin/administrator_guide.md @@ -346,6 +346,19 @@ empty: 1. After successful import (check!) delete your channel on the old RedMatrix Server. 1. On the $Projectname server visit new.hub/locs and upgrade to your channel to a primary one. And when the old Redmatrix server is still listed delete them here as well. Press "Sync" to inform all other server in the grid. +### Administration + +#### Site Administration + +Administration of the website is commonly done through the admin webpage located at /admin on your website. In order to access this page you must have administration rights to the server. Administration rights are granted to the first account to register on your site, **provided** the email address of that account exactly matches the email address you provided as the administrator's email address during setup. + +There are several ways that this can fail and leave the system without an administrator account, for instance if the first account that was created provided a different email address than the administrator email address that was supplied during setup. + +For security reasons there is no web page or interface on the system which will give you administrator access. If you need to correct a situation where a system has no administrator account it **must** be done by editing the account table in the database. There is no other way. To do this, you will need to locate the entry in the account table which belongs to the desired administrator, and set 'account_roles' for that entry to 4096. You will then be able to access the admin page from your system's profile menu or directly via /admin . + +A hub can have multiple admins and there is no limit to how administrators you can have. Repeat the above process for every account you wish to provide with administration rights. + + ### Troubleshooting #### Log files From 1c4629f5e1b7733472e2f721e5a4080734b9e2d5 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 23 Aug 2017 23:37:45 -0700 Subject: [PATCH 140/441] add tasklist and notes to cards page --- view/pdl/mod_cards.pdl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/view/pdl/mod_cards.pdl b/view/pdl/mod_cards.pdl index 2d87136c9..5546d97cb 100644 --- a/view/pdl/mod_cards.pdl +++ b/view/pdl/mod_cards.pdl @@ -1,2 +1,5 @@ [region=aside] -[widget=categories][var=cards]1[/var][/widget][/region] +[widget=categories][var=cards]1[/var][/widget] +[widget=tasklist][/widget] +[widget=notes][/widget] +[/region] From 85f24c292f071b9a83aea0aa122231afd57e7f73 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 23 Aug 2017 23:59:05 -0700 Subject: [PATCH 141/441] last remaining task in tasklist was not removed from view when 'completed' --- Zotlabs/Module/Tasks.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Zotlabs/Module/Tasks.php b/Zotlabs/Module/Tasks.php index c8deb11bf..0709f31f6 100644 --- a/Zotlabs/Module/Tasks.php +++ b/Zotlabs/Module/Tasks.php @@ -19,8 +19,8 @@ class Tasks extends \Zotlabs\Web\Controller { $arr['all'] = 1; $x = tasks_fetch($arr); + $x['html'] = ''; if($x['tasks']) { - $x['html'] = ''; foreach($x['tasks'] as $y) { $x['html'] .= '
' . $y['summary'] . '
'; } @@ -69,6 +69,7 @@ class Tasks extends \Zotlabs\Web\Controller { if($x) $ret['success'] = true; } + json_return_and_die($ret); } From 592cf893c006f24c652902fa4fae7d2d94496c3c Mon Sep 17 00:00:00 2001 From: Andrew Manning Date: Thu, 24 Aug 2017 11:19:11 +0000 Subject: [PATCH 142/441] Fixed incorrect language path when choosing the language from browser preference --- include/help.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/help.php b/include/help.php index cbadd02d9..f38f77854 100644 --- a/include/help.php +++ b/include/help.php @@ -128,7 +128,7 @@ function load_doc_file($s) { $x = determine_help_language(); $lang = $x['language']; $url_idx = ($x['from_url'] ? 1 : 0); - if($x['from_url'] && $lang !== 'en') { + if($lang !== 'en') { $path .= '/' . $lang; } From cf2609530fcffdc7f5477336232b7cfde8b6403f Mon Sep 17 00:00:00 2001 From: Andrew Manning Date: Thu, 24 Aug 2017 18:57:41 +0000 Subject: [PATCH 143/441] Added language selector menu for Help pages --- Zotlabs/Module/Help.php | 5 ++++- include/help.php | 25 ++++++++++++++++++++- view/js/mod_help.js | 50 +++++++++++++++++++++++++++++++++++++++++ view/tpl/help.tpl | 15 +++++++++++++ 4 files changed, 93 insertions(+), 2 deletions(-) diff --git a/Zotlabs/Module/Help.php b/Zotlabs/Module/Help.php index e98cb9d4d..f3cc3aa5f 100644 --- a/Zotlabs/Module/Help.php +++ b/Zotlabs/Module/Help.php @@ -88,12 +88,15 @@ class Help extends \Zotlabs\Web\Controller { $heading = $headings[argv(1)]; $content = get_help_content(); + + $language = determine_help_language()['language']; return replace_macros(get_markup_template('help.tpl'), array( '$title' => t('$Projectname Documentation'), '$tocHeading' => t('Contents'), '$content' => $content, - '$heading' => $heading + '$heading' => $heading, + '$language' => $language )); } diff --git a/include/help.php b/include/help.php index f38f77854..ef6b77e12 100644 --- a/include/help.php +++ b/include/help.php @@ -32,6 +32,13 @@ function get_help_content($tocpath = false) { if(! $tocpath) \App::$page['title'] = t('Help:') . ' ' . ucwords(str_replace('-',' ',notags($title))); + if($tocpath !== false && + load_doc_file('doc/' . $path . '.md') === '' && + load_doc_file('doc/' . $path . '.bb') === '' && + load_doc_file('doc/' . $path . '.html') === '' + ) { + $path = 'toc'; + } $text = load_doc_file('doc/' . $path . '.md'); if(! $text) { @@ -110,7 +117,10 @@ function preg_callback_help_include($matches) { function determine_help_language() { require_once('Text/LanguageDetect.php'); $lang_detect = new Text_LanguageDetect(); + // Set this mode to recognize language by the short code like "en", "ru", etc. $lang_detect->setNameMode(2); + // If the language was specified in the URL, override the language preference + // of the browser. Default to English if both of these are absent. if($lang_detect->languageExists(argv(1))) { $lang = argv(1); $from_url = true; @@ -125,13 +135,16 @@ function determine_help_language() { function load_doc_file($s) { $path = 'doc'; + // 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') { $path .= '/' . $lang; } - + $b = basename($s); for($i=1+$url_idx; $i 0) { + pathParts.push(help_language); + pick_me = false; + if($.inArray(path[i], langChoices) < 0) { + i--; + } + } + } else { + if(path[i].length > 0) { + pathParts.push(path[i]); + } + } + + } + // Update the address bar to reflect the loaded language + window.history.pushState({}, '', '/' + pathParts.join('/')); + + // Highlight the language in the language selector that is currently viewed + $('.lang-selector').find('.lang-choice:contains("' + help_language + '")').css('font-weight','bold').css('background-color','lightgray'); + + // Construct the links to the available translations based and populate the selector menu + $('.lang-selector').find('.lang-choice').each(function (idx, a) { + var langLink = []; + + for (var i = 0; i < pathParts.length; i++) { + + if(i === 1) { + langLink.push($(a).html()); + } else { + langLink.push(pathParts[i]); + } + + } + $(a).attr('href', '/' + langLink.join('/')); + }); + }); diff --git a/view/tpl/help.tpl b/view/tpl/help.tpl index 31e5b9794..bdb25edf1 100644 --- a/view/tpl/help.tpl +++ b/view/tpl/help.tpl @@ -1,5 +1,17 @@
+
+
+ + +
+

{{$title}}: {{$heading}}

@@ -13,3 +25,6 @@ {{$content}}
+ From 2d5768b71c0fa588524849749cfb0b6ffe6300b7 Mon Sep 17 00:00:00 2001 From: git-marijus Date: Thu, 24 Aug 2017 21:47:01 +0200 Subject: [PATCH 144/441] ditch discover tab in favour of the public stream app --- Zotlabs/Module/Network.php | 22 ++++------------------ include/conversation.php | 19 +------------------ 2 files changed, 5 insertions(+), 36 deletions(-) diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index 36ae7f047..82c997270 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -116,7 +116,6 @@ class Network extends \Zotlabs\Web\Controller { $spam = ((x($_GET,'spam')) ? intval($_GET['spam']) : 0); $cmin = ((x($_GET,'cmin')) ? intval($_GET['cmin']) : 0); $cmax = ((x($_GET,'cmax')) ? intval($_GET['cmax']) : 99); - $firehose = ((x($_GET,'fh')) ? intval($_GET['fh']) : 0); $file = ((x($_GET,'file')) ? $_GET['file'] : ''); $xchan = ((x($_GET,'xchan')) ? $_GET['xchan'] : ''); @@ -290,9 +289,6 @@ class Network extends \Zotlabs\Web\Controller { // We only launch liveUpdate if you aren't filtering in some incompatible // way and also you aren't writing a comment (discovered in javascript). - if($gid || $cid || $cmin || ($cmax != 99) || $star || $liked || $conv || $spam || $nouveau || $list) - $firehose = 0; - $maxheight = get_pconfig(local_channel(),'system','network_divmore_height'); if(! $maxheight) $maxheight = 400; @@ -315,7 +311,7 @@ class Network extends \Zotlabs\Web\Controller { '$liked' => (($liked) ? $liked : '0'), '$conv' => (($conv) ? $conv : '0'), '$spam' => (($spam) ? $spam : '0'), - '$fh' => (($firehose) ? $firehose : '0'), + '$fh' => '0', '$nouveau' => (($nouveau) ? $nouveau : '0'), '$wall' => '0', '$static' => $static, @@ -409,17 +405,7 @@ class Network extends \Zotlabs\Web\Controller { } $abook_uids = " and abook.abook_channel = " . local_channel() . " "; - - $disable_discover_tab = get_config('system','disable_discover_tab') || get_config('system','disable_discover_tab') === false; - if($firehose && (! $disable_discover_tab)) { - require_once('include/channel.php'); - $sys = get_sys_channel(); - $uids = " and item.uid = " . intval($sys['channel_id']) . " "; - \App::$data['firehose'] = intval($sys['channel_id']); - } - else { - $uids = " and item.uid = " . local_channel() . " "; - } + $uids = " and item.uid = " . local_channel() . " "; if(get_pconfig(local_channel(),'system','network_list_mode')) $page_mode = 'list'; @@ -516,7 +502,7 @@ class Network extends \Zotlabs\Web\Controller { dbesc($parents_str) ); - xchan_query($items,true,(($firehose) ? local_channel() : 0)); + xchan_query($items,true); $items = fetch_post_tags($items,true); $items = conv_sort($items,$ordering); } @@ -546,7 +532,7 @@ class Network extends \Zotlabs\Web\Controller { } } - if(($update_unseen) && (! $firehose)) { + if($update_unseen) { $x = [ 'channel_id' => local_channel(), 'update' => 'unset' ]; call_hooks('update_unseen',$x); if($x['update'] === 'unset' || intval($x['update'])) { diff --git a/include/conversation.php b/include/conversation.php index 2d5ccb5b1..78d90a6fc 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -1616,7 +1616,6 @@ function network_tabs() { $conv_active = ''; $spam_active = ''; $postord_active = ''; - $public_active = ''; if(x($_GET,'new')) { $new_active = 'active'; @@ -1638,16 +1637,11 @@ function network_tabs() { $spam_active = 'active'; } - if(x($_GET,'fh')) { - $public_active = 'active'; - } - if (($new_active == '') && ($starred_active == '') && ($conv_active == '') && ($search_active == '') - && ($spam_active == '') - && ($public_active == '')) { + && ($spam_active == '')) { $no_active = 'active'; } @@ -1665,17 +1659,6 @@ function network_tabs() { // tabs $tabs = array(); - $disable_discover_tab = get_config('system','disable_discover_tab') || get_config('system','disable_discover_tab') === false; - - if(! $disable_discover_tab) { - $tabs[] = array( - 'label' => t('Discover'), - 'url' => z_root() . '/' . $cmd . '?f=&fh=1' , - 'sel' => $public_active, - 'title' => t('Imported public streams'), - ); - } - $tabs[] = array( 'label' => t('Commented Order'), 'url'=>z_root() . '/' . $cmd . '?f=&order=comment' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''), From 383b7928cf41b750ec367abfc8cbfdc71e1a6291 Mon Sep 17 00:00:00 2001 From: git-marijus Date: Thu, 24 Aug 2017 22:32:28 +0200 Subject: [PATCH 145/441] minor adjustmen to the help language selector --- view/js/mod_help.js | 2 +- view/tpl/help.tpl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/view/js/mod_help.js b/view/js/mod_help.js index 257be67e6..8ee89dd61 100644 --- a/view/js/mod_help.js +++ b/view/js/mod_help.js @@ -103,7 +103,7 @@ $(document).ready(function () { window.history.pushState({}, '', '/' + pathParts.join('/')); // Highlight the language in the language selector that is currently viewed - $('.lang-selector').find('.lang-choice:contains("' + help_language + '")').css('font-weight','bold').css('background-color','lightgray'); + $('.lang-selector').find('.lang-choice:contains("' + help_language + '")').addClass('active'); // Construct the links to the available translations based and populate the selector menu $('.lang-selector').find('.lang-choice').each(function (idx, a) { diff --git a/view/tpl/help.tpl b/view/tpl/help.tpl index bdb25edf1..d36494123 100644 --- a/view/tpl/help.tpl +++ b/view/tpl/help.tpl @@ -1,9 +1,9 @@
-
+
{{/if}}
- +
{{if $attachment}}
From 45c033b9aa461ade1e9041f919c317752d86a315 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 24 Aug 2017 18:39:50 -0700 Subject: [PATCH 149/441] fix title of edit card which showed up as 'edit block' due to copy/paste --- Zotlabs/Module/Card_edit.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Module/Card_edit.php b/Zotlabs/Module/Card_edit.php index b5b44c567..6927c0b6f 100644 --- a/Zotlabs/Module/Card_edit.php +++ b/Zotlabs/Module/Card_edit.php @@ -123,7 +123,7 @@ class Card_edit extends \Zotlabs\Web\Controller { $editor = status_editor($a, $x); $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( - '$title' => t('Edit Block'), + '$title' => t('Edit Card'), '$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false), '$id' => $itm[0]['id'], '$editor' => $editor From 0098dce5976bffb23dbb31d151d2d871c7cab8f9 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Fri, 25 Aug 2017 00:00:51 -0700 Subject: [PATCH 150/441] radically reduce code duplication in updateConvItems(); it's a bit easier to understand now although the different modes aren't as cleanly separated as they were. --- view/js/main.js | 166 ++++++++++++++++-------------------------------- 1 file changed, 56 insertions(+), 110 deletions(-) diff --git a/view/js/main.js b/view/js/main.js index fd3c8b08f..ece4c2015 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -533,133 +533,76 @@ function updatePageItems(mode, data) { function updateConvItems(mode,data) { - if(mode === 'update') { + if(mode === 'update' || mode === 'replace') { prev = 'threads-begin'; - - $('.thread-wrapper.toplevel_item',data).each(function() { - - var ident = $(this).attr('id'); - // This should probably use the context argument instead - var commentWrap = $('#'+ident+' .collapsed-comments').attr('id'); - var itmId = 0; - var isVisible = false; - - if(typeof commentWrap !== 'undefined') - itmId = commentWrap.replace('collapsed-comments-',''); - - if($('#' + ident).length == 0 && profile_page == 1) { - $('img',this).each(function() { - $(this).attr('src',$(this).attr('dst')); - }); - if($('#collapsed-comments-'+itmId).is(':visible')) - isVisible = true; - $('#' + prev).after($(this)); - if(isVisible) - showHideComments(itmId); - $("> .wall-item-outside-wrapper .autotime, > .thread-wrapper .autotime",this).timeago(); - $("> .shared_header .autotime",this).timeago(); - } - else { - $('img',this).each(function() { - $(this).attr('src',$(this).attr('dst')); - }); - if($('#collapsed-comments-'+itmId).is(':visible')) - isVisible = true; - $('#' + ident).replaceWith($(this)); - if(isVisible) - showHideComments(itmId); - $("> .wall-item-outside-wrapper .autotime, > .thread-wrapper .autotime",this).timeago(); - $("> .shared_header .autotime",this).timeago(); - } - prev = ident; - }); } if(mode === 'append') { - next = 'threads-end'; - - $('.thread-wrapper.toplevel_item',data).each(function() { - var ident = $(this).attr('id'); - var commentWrap = $('#'+ident+' .collapsed-comments').attr('id'); - var itmId = 0; - var isVisible = false; - - if(typeof commentWrap !== 'undefined') - itmId = commentWrap.replace('collapsed-comments-', ''); - - if($('#' + ident).length == 0) { - $('img',this).each(function() { - $(this).attr('src',$(this).attr('dst')); - }); - if($('#collapsed-comments-'+itmId).is(':visible')) - isVisible = true; - $('#threads-end').before($(this)); - if(isVisible) - showHideComments(itmId); - $("> .wall-item-outside-wrapper .autotime, > .thread-wrapper .autotime",this).timeago(); - $("> .shared_header .autotime",this).timeago(); - } - else { - $('img',this).each(function() { - $(this).attr('src', $(this).attr('dst')); - }); - if($('#collapsed-comments-'+itmId).is(':visible')) - isVisible = true; - $('#' + ident).replaceWith($(this)); - if(isVisible) - showHideComments(itmId); - $("> .wall-item-outside-wrapper .autotime, > .thread-wrapper .autotime",this).timeago(); - $("> .shared_header .autotime",this).timeago(); - } - }); - - if(loadingPage) { - loadingPage = false; - } } + if(mode === 'replace') { - // clear existing content - $('.thread-wrapper').remove(); + $('.thread-wrapper').remove(); // clear existing content + } - prev = 'threads-begin'; + $('.thread-wrapper.toplevel_item',data).each(function() { - $('.thread-wrapper.toplevel_item',data).each(function() { + var ident = $(this).attr('id'); - var ident = $(this).attr('id'); - var commentWrap = $('#'+ident+' .collapsed-comments').attr('id'); - var itmId = 0; - var isVisible = false; + var commentWrap = $('#'+ident+' .collapsed-comments').attr('id'); + var itmId = 0; + var isVisible = false; - if(typeof commentWrap !== 'undefined') - itmId = commentWrap.replace('collapsed-comments-',''); + // figure out the comment state + if(typeof commentWrap !== 'undefined') + itmId = commentWrap.replace('collapsed-comments-',''); + + if($('#collapsed-comments-'+itmId).is(':visible')) + isVisible = true; - if($('#' + ident).length == 0 && profile_page == 1) { - $('img',this).each(function() { - $(this).attr('src',$(this).attr('dst')); - }); - if($('#collapsed-comments-'+itmId).is(':visible')) - isVisible = true; - $('#' + prev).after($(this)); - if(isVisible) - showHideComments(itmId); - $("> .wall-item-outside-wrapper .autotime, > .thread-wrapper .autotime",this).timeago(); - $("> .shared_header .autotime",this).timeago(); + // insert the content according to the mode and first_page + // and whether or not the content exists already (overwrite it) + + if($('#' + ident).length == 0) { + if((mode === 'update' || mode === 'replace') && profile_page == 1) { + $('#' + prev).after($(this)); + prev = ident; } - prev = ident; - }); + if(mode === 'append') { + $('#' + next).before($(this)); + } + } + else { + $('#' + ident).replaceWith($(this)); + } - if(loadingPage) { + // set the comment state to the state we discovered earlier + + if(isVisible) + showHideComments(itmId); + + // trigger the autotime function on all newly created content + + $("> .wall-item-outside-wrapper .autotime, > .thread-wrapper .autotime",this).timeago(); + $("> .shared_header .autotime",this).timeago(); + + if((mode === 'append' || mode === 'replace') && (loadingPage)) { loadingPage = false; } - if (window.location.search.indexOf("mid=") != -1 || window.location.pathname.indexOf("display") != -1) { - var title = $(".wall-item-title").text(); - title.replace(/^\s+/, ''); - title.replace(/\s+$/, ''); - if (title) - document.title = title + " - " + document.title; + // if single thread view and the item has a title, display it in the title bar + + if(mode === 'replace') { + if (window.location.search.indexOf("mid=") != -1 || window.location.pathname.indexOf("display") != -1) { + var title = $(".wall-item-title").text(); + title.replace(/^\s+/, ''); + title.replace(/\s+$/, ''); + if (title) + document.title = title + " - " + document.title; + } } - } + }); + + // reset rotators and cursors we may have set before reaching this place $('.like-rotator').spin(false); @@ -668,6 +611,9 @@ function updateConvItems(mode,data) { $('body').css('cursor', 'auto'); } + // Setup to determine if the media player is playing. This affects + // some content loading decisions. + $('video').off('playing'); $('video').off('pause'); $('audio').off('playing'); From 75f3e9202e191486b8c9079b08cc6de4e1251b8d Mon Sep 17 00:00:00 2001 From: Andrew Manning Date: Fri, 25 Aug 2017 11:32:18 +0000 Subject: [PATCH 151/441] Removed duplicated table of contents (TOC) in Help pages by breaking hierarchical TOC loading. --- Zotlabs/Widget/Helpindex.php | 2 ++ include/help.php | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Zotlabs/Widget/Helpindex.php b/Zotlabs/Widget/Helpindex.php index 8299cf16a..6c8748194 100644 --- a/Zotlabs/Widget/Helpindex.php +++ b/Zotlabs/Widget/Helpindex.php @@ -25,6 +25,7 @@ class Helpindex { // TODO: Implement support for translations in hierarchical table of content files + /* if(argc() > 2) { $path = ''; for($x = 1; $x < argc(); $x ++) { @@ -36,6 +37,7 @@ class Helpindex { $levels[] = preg_replace('/\/','
{{/if}} - + {{if $qcomment}} + {{if $qcomment}} + {{$mimetype}} {{include file="field_input.tpl" field=$pageName}} @@ -33,7 +34,7 @@ {{if $canadd}} \ No newline at end of file + diff --git a/view/tpl/cdav_calendar.tpl b/view/tpl/cdav_calendar.tpl index 5d683d751..b0245e853 100644 --- a/view/tpl/cdav_calendar.tpl +++ b/view/tpl/cdav_calendar.tpl @@ -129,11 +129,11 @@ $(document).ready(function() { }, loading: function(isLoading, view) { - $('#events-spinner').spin('tiny'); - $('#events-spinner > i').css('color', 'transparent'); + $('#events-spinner').show(); + $('#today-btn > i').hide(); if(!isLoading) { - $('#events-spinner').spin(false); - $('#events-spinner > i').css('color', ''); + $('#events-spinner').hide(); + $('#today-btn > i').show(); } } }); @@ -292,7 +292,7 @@ function on_more() {
- +
diff --git a/view/tpl/chat.tpl b/view/tpl/chat.tpl index 22f3465bf..c189cbd15 100644 --- a/view/tpl/chat.tpl +++ b/view/tpl/chat.tpl @@ -16,6 +16,9 @@
+
+
+
@@ -25,7 +28,7 @@
-
+
@@ -42,7 +45,7 @@ {{/if}}
-
+
+
+
+
+
+
-
-
-
-
@@ -101,7 +105,7 @@ var last_chat = 0; var chat_timer = null; $(document).ready(function() { - $('#chatTopBar').spin('small'); + $('#chat-top-spinner').show(); chat_timer = setTimeout(load_chats,300); $('#chatroom_bookmarks, #vcard').hide(); $('#chatroom_list, #chatroom_members').show(); @@ -134,7 +138,7 @@ function load_chats() { if(data.success && (! stopped)) { update_inroom(data.inroom); update_chats(data.chats); - $('#chatTopBar').spin(false); + $('#chat-top-spinner').hide(); } }); @@ -293,10 +297,10 @@ function toggleChatNotifications() { function chatJotGetLink() { reply = prompt("{{$linkurl}}"); if(reply && reply.length) { - $('#chat-rotator').spin('tiny'); + $('#chat-rotator').show(); $.get('linkinfo?f=&url=' + reply, function(data) { addmailtext(data); - $('#chat-rotator').spin(false); + $('#chat-rotator').hide(); }); } } diff --git a/view/tpl/conv_frame.tpl b/view/tpl/conv_frame.tpl index 1f0e00db4..8aa865076 100755 --- a/view/tpl/conv_frame.tpl +++ b/view/tpl/conv_frame.tpl @@ -1,6 +1,8 @@
-
+
+
+
diff --git a/view/tpl/conv_item.tpl b/view/tpl/conv_item.tpl index b3fe60750..b0c143f4a 100755 --- a/view/tpl/conv_item.tpl +++ b/view/tpl/conv_item.tpl @@ -86,6 +86,11 @@ {{/if}}
+
+
+
+
+
{{if $item.toplevel && $item.emojis && $item.reactions}}
- {{if $item.responses || $item.attachments}}
diff --git a/view/tpl/event_head.tpl b/view/tpl/event_head.tpl index 3b2cb5041..2f440e826 100755 --- a/view/tpl/event_head.tpl +++ b/view/tpl/event_head.tpl @@ -67,11 +67,11 @@ showEvent(calEvent.id); }, loading: function(isLoading, view) { - $('#events-spinner').spin('tiny'); - $('#events-spinner > i').css('color', 'transparent'); + $('#events-spinner').show(); + $('#today-btn > i').hide(); if(!isLoading) { - $('#events-spinner').spin(false); - $('#events-spinner > i').css('color', ''); + $('#events-spinner').hide(); + $('#today-btn > i').show(); $('td.fc-day').dblclick(function() { openMenu('form'); //window.location.href='/events/new?start='+$(this).data('date'); diff --git a/view/tpl/events-js.tpl b/view/tpl/events-js.tpl index 9d32c76be..d3f3414ff 100755 --- a/view/tpl/events-js.tpl +++ b/view/tpl/events-js.tpl @@ -11,7 +11,7 @@
- +
diff --git a/view/tpl/events_cal-js.tpl b/view/tpl/events_cal-js.tpl index ba9e16dd6..2c4d961f9 100755 --- a/view/tpl/events_cal-js.tpl +++ b/view/tpl/events_cal-js.tpl @@ -4,7 +4,7 @@
- +
diff --git a/view/tpl/jot-header.tpl b/view/tpl/jot-header.tpl index 2d37b3ca2..2f9dd9f15 100755 --- a/view/tpl/jot-header.tpl +++ b/view/tpl/jot-header.tpl @@ -6,10 +6,10 @@ var pretext = '{{$pretext}}'; function initEditor(cb){ if (editor==false){ - $("#profile-jot-text-loading").spin('small').show(); + $("#profile-jot-text-loading").show(); {{$geotag}} if(plaintext == 'none') { - $("#profile-jot-text-loading").spin(false).hide(); + $("#profile-jot-text-loading").hide(); $("#profile-jot-text").css({ 'height': 200 }); {{if $bbco_autocomplete}} $("#profile-jot-text").bbco_autocomplete('{{$bbco_autocomplete}}'); // autocomplete bbcode @@ -80,7 +80,7 @@ function initEditor(cb){ ed.onInit.add(function(ed) { ed.pasteAsPlainText = true; - $("#profile-jot-text-loading").spin(false).hide(); + $("#profile-jot-text-loading").hide(); $(".jothidden").show(); if (typeof cb!="undefined") cb(); }); @@ -121,7 +121,7 @@ var activeCommentText = ''; dropZone: $('#profile-jot-text'), maxChunkSize: 4 * 1024 * 1024, add: function(e,data) { - $('#profile-rotator').spin('tiny'); + $('#profile-rotator').show(); data.submit(); }, done: function(e,data) { @@ -130,7 +130,7 @@ var activeCommentText = ''; }, stop: function(e,data) { preview_post(); - $('#profile-rotator').spin(false); + $('#profile-rotator').hide(); }, }); @@ -204,11 +204,11 @@ var activeCommentText = ''; reply = prompt("{{$linkurl}}"); if(reply && reply.length) { reply = bin2hex(reply); - $('#profile-rotator').spin('tiny'); + $('#profile-rotator').show(); $.get('{{$baseurl}}/linkinfo?f=&binurl=' + reply, function(data) { addeditortext(data); preview_post(); - $('#profile-rotator').spin(false); + $('#profile-rotator').hide(); }); } } @@ -254,12 +254,12 @@ var activeCommentText = ''; else { if ($('#jot-popup').length != 0) $('#jot-popup').show(); - $('#like-rotator-' + id).spin('tiny'); + $('#like-rotator-' + id).show(); $.get('{{$baseurl}}/share/' + id, function(data) { if (!editor) $("#profile-jot-text").val(""); initEditor(function(){ addeditortext(data); - $('#like-rotator-' + id).spin(false); + $('#like-rotator-' + id).hide(); $(window).scrollTop(0); }); }); @@ -312,17 +312,17 @@ var activeCommentText = ''; if(reply && reply.length) { reply = bin2hex(reply); - $('#profile-rotator').spin('tiny'); + $('#profile-rotator').show(); $.get('{{$baseurl}}/linkinfo?f=&binurl=' + reply, function(data) { if(commentwin) { $(editwin).val( $(editwin).val() + data ); - $('#profile-rotator').spin(false); + $('#profile-rotator').hide(); } else { if (!editor) $("#profile-jot-text").val(""); initEditor(function(){ addeditortext(data); - $('#profile-rotator').spin(false); + $('#profile-rotator').hide(); }); } }); diff --git a/view/tpl/jot.tpl b/view/tpl/jot.tpl index ce17f2f24..13e7602be 100755 --- a/view/tpl/jot.tpl +++ b/view/tpl/jot.tpl @@ -168,9 +168,11 @@
{{/if}} -
-
-
+
+
+
+
+
{{if $preview}} diff --git a/view/tpl/msg-header.tpl b/view/tpl/msg-header.tpl index 48bf5de4b..d71d432fb 100755 --- a/view/tpl/msg-header.tpl +++ b/view/tpl/msg-header.tpl @@ -12,7 +12,7 @@ dropZone: $('#prvmail-text'), maxChunkSize: 4 * 1024 * 1024, add: function(e,data) { - $('#prvmail-rotator').spin('tiny'); + $('#prvmail-rotator').show(); data.submit(); }, done: function(e,data) { @@ -21,7 +21,7 @@ }, stop: function(e,data) { preview_mail(); - $('#prvmail-rotator').spin(false); + $('#prvmail-rotator').hide(); }, }); @@ -34,11 +34,11 @@ function prvmailJotGetLink() { reply = prompt("{{$linkurl}}"); if(reply && reply.length) { - $('#prvmail-rotator').spin('tiny'); + $('#prvmail-rotator').show(); $.get('linkinfo?f=&url=' + reply, function(data) { addmailtext(data); preview_mail(); - $('#prvmail-rotator').spin(false); + $('#prvmail-rotator').hide(); }); } } @@ -61,11 +61,11 @@ event.target.textContent = reply; event.preventDefault(); if(reply && reply.length) { - $('#prvmail-rotator').spin('tiny'); + $('#prvmail-rotator').show(); $.get('linkinfo?f=&url=' + reply, function(data) { addmailtext(data); preview_mail(); - $('#prvmail-rotator').spin(false); + $('#prvmail-rotator').hide(); }); } } diff --git a/view/tpl/nav.tpl b/view/tpl/nav.tpl index f21017076..72860aebe 100755 --- a/view/tpl/nav.tpl +++ b/view/tpl/nav.tpl @@ -191,7 +191,9 @@ - +
{{/if}} -
+
@@ -31,12 +31,12 @@
-
+
-
+
{{if $feature_expire || $feature_encrypt}} -
+
{{if $feature_expire}}
+
+
+
+
+
-
-
-
-
From 4a270d10d189471496438489a9b444bd12340aab Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Tue, 26 Sep 2017 13:50:29 +0200 Subject: [PATCH 325/441] bump version --- boot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot.php b/boot.php index df5c77e43..4f738a7a1 100755 --- a/boot.php +++ b/boot.php @@ -49,7 +49,7 @@ require_once('include/hubloc.php'); require_once('include/attach.php'); define ( 'PLATFORM_NAME', 'hubzilla' ); -define ( 'STD_VERSION', '2.7.4' ); +define ( 'STD_VERSION', '2.7.5' ); define ( 'ZOT_REVISION', '1.3' ); define ( 'DB_UPDATE_VERSION', 1196 ); From b8a0bc0b0b31670d2c424a40f7511132896a76d2 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 27 Sep 2017 12:06:06 +0200 Subject: [PATCH 326/441] fix some missing spinners --- view/theme/redbasic/css/style.css | 3 ++- view/tpl/connections.tpl | 4 +++- view/tpl/conv_item.tpl | 2 +- view/tpl/conv_list.tpl | 2 +- view/tpl/directory_header.tpl | 4 +++- view/tpl/photo_album.tpl | 4 +++- view/tpl/photos_recent.tpl | 4 +++- view/tpl/search_item.tpl | 2 +- view/tpl/viewcontact_template.tpl | 4 +++- 9 files changed, 20 insertions(+), 9 deletions(-) diff --git a/view/theme/redbasic/css/style.css b/view/theme/redbasic/css/style.css index 0d85162d3..1b7aee30d 100644 --- a/view/theme/redbasic/css/style.css +++ b/view/theme/redbasic/css/style.css @@ -1259,7 +1259,8 @@ img.mail-conv-sender-photo { .generic-content-wrapper { border: 1px solid #ccc; box-shadow: 0px 0px 5px 1px rgba(0,0,0,0.2); - border-radius: $radius; + border-radius: $radius; + margin-bottom: 1.5rem; } .section-title-wrapper { diff --git a/view/tpl/connections.tpl b/view/tpl/connections.tpl index 13261965a..3b152ef5e 100755 --- a/view/tpl/connections.tpl +++ b/view/tpl/connections.tpl @@ -33,4 +33,6 @@
-
+
+
+
diff --git a/view/tpl/conv_item.tpl b/view/tpl/conv_item.tpl index b0c143f4a..b0e1cb6fb 100755 --- a/view/tpl/conv_item.tpl +++ b/view/tpl/conv_item.tpl @@ -4,7 +4,7 @@