diff options
Diffstat (limited to 'Zotlabs')
-rw-r--r-- | Zotlabs/Lib/ActivityStreams.php | 43 | ||||
-rw-r--r-- | Zotlabs/Lib/LDSignatures.php | 117 | ||||
-rw-r--r-- | Zotlabs/Lib/ThreadItem.php | 6 | ||||
-rw-r--r-- | Zotlabs/Module/Acl.php | 7 | ||||
-rw-r--r-- | Zotlabs/Module/Display.php | 13 | ||||
-rw-r--r-- | Zotlabs/Module/Item.php | 11 | ||||
-rw-r--r-- | Zotlabs/Module/Oep.php | 2 | ||||
-rw-r--r-- | Zotlabs/Module/Rpost.php | 41 | ||||
-rw-r--r-- | Zotlabs/Module/Xrd.php | 2 | ||||
-rw-r--r-- | Zotlabs/Web/CheckJS.php | 6 | ||||
-rw-r--r-- | Zotlabs/Widget/Categories.php | 2 |
11 files changed, 207 insertions, 43 deletions
diff --git a/Zotlabs/Lib/ActivityStreams.php b/Zotlabs/Lib/ActivityStreams.php index 3bbe3b190..686f4a140 100644 --- a/Zotlabs/Lib/ActivityStreams.php +++ b/Zotlabs/Lib/ActivityStreams.php @@ -14,6 +14,8 @@ class ActivityStreams { public $origin = null; public $owner = null; + public $recips = null; + function __construct($string) { $this->data = json_decode($string,true); @@ -28,7 +30,7 @@ class ActivityStreams { $this->obj = $this->get_compound_property('object'); $this->tgt = $this->get_compound_property('target'); $this->origin = $this->get_compound_property('origin'); - $this->owner = $this->get_compound_property('owner','','http://purl.org/zot/protocol'); + $this->recips = $this->collect_recips(); if(($this->type === 'Note') && (! $this->obj)) { $this->obj = $this->data; @@ -41,6 +43,45 @@ class ActivityStreams { return $this->valid; } + function collect_recips($base = '',$namespace = 'https://www.w3.org/ns/activitystreams') { + $x = []; + $fields = [ 'to','cc','bto','bcc','audience']; + foreach($fields as $f) { + $y = $this->get_compound_property($f,$base,$namespace); + if($y) + $x = array_merge($x,$y); + } +// not yet ready for prime time +// $x = $this->expand($x,$base,$namespace); + return $x; + } + + function expand($arr,$base = '',$namespace = 'https://www.w3.org/ns/activitystreams') { + $ret = []; + + // right now use a hardwired recursion depth of 5 + + for($z = 0; $z < 5; $z ++) { + if(is_array($arr) && $arr) { + foreach($arr as $a) { + if(is_array($a)) { + $ret[] = $a; + } + else { + $x = $this->get_compound_property($a,$base,$namespace); + if($x) { + $ret = array_merge($ret,$x); + } + } + } + } + } + + // @fixme de-duplicate + + return $ret; + } + function get_namespace($base,$namespace) { $key = null; diff --git a/Zotlabs/Lib/LDSignatures.php b/Zotlabs/Lib/LDSignatures.php new file mode 100644 index 000000000..88dfe80c0 --- /dev/null +++ b/Zotlabs/Lib/LDSignatures.php @@ -0,0 +1,117 @@ +<?php + +namespace Zotlabs\Lib; + +require_once('library/jsonld/jsonld.php'); + +class LDSignatures { + + + static function verify($data,$pubkey) { + + $ohash = self::hash(self::signable_options($data['signature'])); + $dhash = self::hash(self::signable_data($data)); + + return rsa_verify($ohash . $dhash,base64_decode($data['signature']['signatureValue']), $pubkey); + } + + static function dopplesign(&$data,$channel) { + $data['magicEnv'] = self::salmon_sign($data,$channel); + return self::sign($data,$channel); + } + + static function sign($data,$channel) { + $options = [ + 'type' => 'RsaSignature2017', + 'nonce' => random_string(64), + 'creator' => z_root() . '/channel/' . $channel['channel_address'] . '/public_key_pem', + 'created' => datetime_convert('UTC','UTC', 'now', 'Y-m-d\Th:i:s\Z') + ]; + + $ohash = self::hash(self::signable_options($options)); + $dhash = self::hash(self::signable_data($data)); + $options['signatureValue'] = base64_encode(rsa_sign($ohash . $dhash,$channel['channel_prvkey'])); + + $signed = array_merge([ + '@context' => [ 'https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1' ], + ],$options); + + return $signed; + } + + + static function signable_data($data) { + + $newdata = []; + if($data) { + foreach($data as $k => $v) { + if(! in_array($k,[ 'signature' ])) { + $newopts[$k] = $v; + } + } + } + return json_encode($newdata,JSON_UNESCAPED_SLASHES); + } + + + static function signable_options($options) { + + $newopts = [ '@context' => 'https://w3id.org/identity/v1' ]; + if($options) { + foreach($options as $k => $v) { + if(! in_array($k,[ 'type','id','signatureValue' ])) { + $newopts[$k] = $v; + } + } + } + return json_encode($newopts,JSON_UNESCAPED_SLASHES); + } + + static function hash($obj) { + return hash('sha256',self::normalise($obj)); + } + + static function normalise($data) { + if(is_string($data)) { + $data = json_decode($data); + } + + if(! is_object($data)) + return ''; + + return jsonld_normalize($data,[ 'algorithm' => 'URDNA2015', 'format' => 'application/nquads' ]); + } + + static function salmon_sign($data,$channel) { + + $arr = $data; + $data = json_encode($data,JSON_UNESCAPED_SLASHES); + $data = base64url_encode($data, false); // do not strip padding + $data_type = 'application/activity+json'; + $encoding = 'base64url'; + $algorithm = 'RSA-SHA256'; + $keyhash = base64url_encode(z_root() . '/channel/' . $channel['channel_address']); + + $data = str_replace(array(" ","\t","\r","\n"),array("","","",""),$data); + + // precomputed base64url encoding of data_type, encoding, algorithm concatenated with periods + + $precomputed = '.' . base64url_encode($data_type,false) . '.YmFzZTY0dXJs.UlNBLVNIQTI1Ng=='; + + $signature = base64url_encode(rsa_sign($data . $precomputed,$channel['channel_prvkey'])); + + return ([ + 'id' => $arr['id'], + 'meData' => $data, + 'meDataType' => $data_type, + 'meEncoding' => $encoding, + 'meAlgorithm' => $algorithm, + 'meCreator' => z_root() . '/channel/' . $channel['channel_address'] . '/public_key_pem', + 'meSignatureValue' => $signature + ]); + + } + + + +}
\ No newline at end of file diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index 313001cc7..f9565d339 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -758,9 +758,9 @@ class ThreadItem { '$sourceapp' => \App::$sourcename, '$observer' => get_observer_hash(), '$anoncomments' => (($conv->get_mode() === 'channel' && perm_is_allowed($conv->get_profile_owner(),'','post_comments')) ? true : false), - '$anonname' => [ 'anonname', t('Your full name (required)'),'','','','onBlur="commentCloseUI(this,\'' . $this->get_id() . '\')"' ], - '$anonmail' => [ 'anonmail', t('Your email address (required)'),'','','','onBlur="commentCloseUI(this,\'' . $this->get_id() . '\')"' ], - '$anonurl' => [ 'anonurl', t('Your website URL (optional)'),'','','','onBlur="commentCloseUI(this,\'' . $this->get_id() . '\')"' ] + '$anonname' => [ 'anonname', t('Your full name (required)') ], + '$anonmail' => [ 'anonmail', t('Your email address (required)') ], + '$anonurl' => [ 'anonurl', t('Your website URL (optional)') ] )); return $comment_box; diff --git a/Zotlabs/Module/Acl.php b/Zotlabs/Module/Acl.php index 83fafbdff..4d7654f3d 100644 --- a/Zotlabs/Module/Acl.php +++ b/Zotlabs/Module/Acl.php @@ -324,11 +324,12 @@ class Acl extends \Zotlabs\Web\Controller { $r = array(); if($r) { - foreach($r as $g){ + foreach($r as $g) { - // remove RSS feeds from ACLs - they are inaccessible - if(strpos($g['hash'],'/') && $type != 'a') + if(($g['network'] === 'rss') && ($type != 'a')) continue; + + $g['hash'] = urlencode($g['hash']); if(in_array($g['hash'],$permitted) && $type == 'c' && (! $noforums)) { $contacts[] = array( diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php index b698513ba..66a09b983 100644 --- a/Zotlabs/Module/Display.php +++ b/Zotlabs/Module/Display.php @@ -76,7 +76,6 @@ class Display extends \Zotlabs\Web\Controller { $o = '<div id="jot-popup">'; $o .= status_editor($a,$x); $o .= '</div>'; - } // This page can be viewed by anybody so the query could be complicated @@ -181,6 +180,7 @@ class Display extends \Zotlabs\Web\Controller { 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string), 'title' => 'oembed' ]); + } $observer_hash = get_observer_hash(); @@ -190,7 +190,6 @@ class Display extends \Zotlabs\Web\Controller { if(($update && $load) || ($checkjs->disabled())) { - $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']),intval(\App::$pager['start'])); if($load || ($checkjs->disabled())) { @@ -224,7 +223,6 @@ class Display extends \Zotlabs\Web\Controller { if(! perm_is_allowed($sysid,$observer_hash,'view_stream')) $sysid = 0; - $r = q("SELECT item.id as item_id from item WHERE mid = '%s' AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = '' @@ -237,7 +235,6 @@ class Display extends \Zotlabs\Web\Controller { dbesc($target_item['parent_mid']), intval($sysid) ); - } } } @@ -250,6 +247,7 @@ class Display extends \Zotlabs\Web\Controller { $sysid = $sys['channel_id']; if(local_channel()) { + $r = q("SELECT item.parent AS item_id from item WHERE uid = %d and parent_mid = '%s' @@ -269,12 +267,12 @@ class Display extends \Zotlabs\Web\Controller { // make that content unsearchable by ensuring the owner_xchan can't match if(! perm_is_allowed($sysid,$observer_hash,'view_stream')) $sysid = 0; - + $r = q("SELECT item.parent AS item_id from item WHERE parent_mid = '%s' AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = '' AND item.deny_gid = '' AND item_private = 0 ) - and owner_xchan in ( " . stream_perms_xchans(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " )) + and uid in ( " . stream_perms_api_uids(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " )) OR uid = %d ) $sql_extra ) $item_normal @@ -292,7 +290,7 @@ class Display extends \Zotlabs\Web\Controller { } if($r) { - + $parents_str = ids_to_querystr($r,'item_id'); if($parents_str) { @@ -310,7 +308,6 @@ class Display extends \Zotlabs\Web\Controller { $items = array(); } - if ($checkjs->disabled()) { $o .= conversation($items, 'display', $update, 'traditional'); if ($items[0]['title']) diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index a86106b6a..3e023ae8b 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -659,14 +659,23 @@ class Item extends \Zotlabs\Web\Controller { // BBCODE end alert if(strlen($categories)) { + $cats = explode(',',$categories); foreach($cats as $cat) { + + if($webpage == ITEM_TYPE_CARD) { + $catlink = z_root() . '/cards/' . $channel['channel_address'] . '?f=&cat=' . urlencode(trim($cat)); + } + else { + $catlink = $owner_xchan['xchan_url'] . '?f=&cat=' . urlencode(trim($cat)); + } + $post_tags[] = array( 'uid' => $profile_uid, 'ttype' => TERM_CATEGORY, 'otype' => TERM_OBJ_POST, 'term' => trim($cat), - 'url' => $owner_xchan['xchan_url'] . '?f=&cat=' . urlencode(trim($cat)) + 'url' => $catlink ); } } diff --git a/Zotlabs/Module/Oep.php b/Zotlabs/Module/Oep.php index 02aa4aba9..9a1317142 100644 --- a/Zotlabs/Module/Oep.php +++ b/Zotlabs/Module/Oep.php @@ -1,6 +1,8 @@ <?php namespace Zotlabs\Module; +require_once('include/security.php'); + // oembed provider diff --git a/Zotlabs/Module/Rpost.php b/Zotlabs/Module/Rpost.php index 731eab82e..56f4f23f6 100644 --- a/Zotlabs/Module/Rpost.php +++ b/Zotlabs/Module/Rpost.php @@ -90,8 +90,6 @@ class Rpost extends \Zotlabs\Web\Controller { } $plaintext = true; - // if(feature_enabled(local_channel(),'richtext')) - // $plaintext = false; if(array_key_exists('type', $_REQUEST) && $_REQUEST['type'] === 'html') { require_once('include/html2bbcode.php'); @@ -112,26 +110,25 @@ class Rpost extends \Zotlabs\Web\Controller { } $x = array( - 'is_owner' => true, - 'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''), - 'default_location' => $channel['channel_location'], - 'nickname' => $channel['channel_address'], - 'lockstate' => (($acl->is_private()) ? 'lock' : 'unlock'), - 'acl' => populate_acl($channel_acl, true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'), - 'permissions' => $channel_acl, - 'bang' => '', - 'visitor' => true, - 'profile_uid' => local_channel(), - 'title' => $_REQUEST['title'], - 'body' => $_REQUEST['body'], - 'attachment' => $_REQUEST['attachment'], - 'source' => ((x($_REQUEST,'source')) ? strip_tags($_REQUEST['source']) : ''), - 'return_path' => 'rpost/return', - 'bbco_autocomplete' => 'bbcode', - 'editor_autocomplete'=> true, - 'bbcode' => true, - 'jotnets' => true - + 'is_owner' => true, + 'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''), + 'default_location' => $channel['channel_location'], + 'nickname' => $channel['channel_address'], + 'lockstate' => (($acl->is_private()) ? 'lock' : 'unlock'), + 'acl' => populate_acl($channel_acl, true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'), + 'permissions' => $channel_acl, + 'bang' => '', + 'visitor' => true, + 'profile_uid' => local_channel(), + 'title' => $_REQUEST['title'], + 'body' => $_REQUEST['body'], + 'attachment' => $_REQUEST['attachment'], + 'source' => ((x($_REQUEST,'source')) ? strip_tags($_REQUEST['source']) : ''), + 'return_path' => 'rpost/return', + 'bbco_autocomplete' => 'bbcode', + 'editor_autocomplete' => true, + 'bbcode' => true, + 'jotnets' => true ); $editor = status_editor($a,$x); diff --git a/Zotlabs/Module/Xrd.php b/Zotlabs/Module/Xrd.php index 64e5042cb..60a8f58fa 100644 --- a/Zotlabs/Module/Xrd.php +++ b/Zotlabs/Module/Xrd.php @@ -57,7 +57,7 @@ class Xrd extends \Zotlabs\Web\Controller { '$poco_url' => z_root() . '/poco/' . $r[0]['channel_address'], '$photo' => z_root() . '/photo/profile/l/' . $r[0]['channel_id'], '$modexp' => 'data:application/magic-public-key,' . $salmon_key, - '$subscribe' => z_root() . '/follow?f=&url={uri}', + '$subscribe' => z_root() . '/follow?f=&url={uri}', )); diff --git a/Zotlabs/Web/CheckJS.php b/Zotlabs/Web/CheckJS.php index 109790fa5..8179ceb15 100644 --- a/Zotlabs/Web/CheckJS.php +++ b/Zotlabs/Web/CheckJS.php @@ -21,9 +21,9 @@ class CheckJS { $page = urlencode(\App::$query_string); if($test) { - self::$jsdisabled = 1; + $this->jsdisabled = 1; if(array_key_exists('jsdisabled',$_COOKIE)) - self::$jsdisabled = $_COOKIE['jsdisabled']; + $this->jsdisabled = $_COOKIE['jsdisabled']; if(! array_key_exists('jsdisabled',$_COOKIE)) { \App::$page['htmlhead'] .= "\r\n" . '<script>document.cookie="jsdisabled=0; path=/"; var jsMatch = /\&jsdisabled=0/; if (!jsMatch.exec(location.href)) { location.href = "' . z_root() . '/nojs/0?f=&redir=' . $page . '" ; }</script>' . "\r\n"; @@ -41,7 +41,7 @@ class CheckJS { } function disabled() { - return self::$jsdisabled; + return $this->jsdisabled; } diff --git a/Zotlabs/Widget/Categories.php b/Zotlabs/Widget/Categories.php index 84deb03d6..305869706 100644 --- a/Zotlabs/Widget/Categories.php +++ b/Zotlabs/Widget/Categories.php @@ -19,7 +19,7 @@ class Categories { } $cat = ((x($_REQUEST,'cat')) ? htmlspecialchars($_REQUEST['cat'],ENT_COMPAT,'UTF-8') : ''); - $srchurl = \App::$query_string; + $srchurl = (($cards) ? \App::$argv[0] . '/' . \App::$argv[1] : \App::$query_string); $srchurl = rtrim(preg_replace('/cat\=[^\&].*?(\&|$)/is','',$srchurl),'&'); $srchurl = str_replace(array('?f=','&f='),array('',''),$srchurl); |