aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/api_zot.php87
-rw-r--r--include/attach.php6
-rw-r--r--include/bb2diaspora.php12
-rw-r--r--include/bbcode.php66
-rw-r--r--include/config.php24
-rw-r--r--include/conversation.php4
-rw-r--r--include/crypto.php117
-rwxr-xr-xinclude/dba/dba_driver.php2
-rwxr-xr-xinclude/dba/dba_pdo.php2
-rw-r--r--include/dir_fns.php10
-rw-r--r--include/help.php5
-rwxr-xr-xinclude/items.php34
-rw-r--r--include/nav.php20
-rwxr-xr-xinclude/oembed.php2
-rw-r--r--include/queue_fn.php2
-rw-r--r--include/taxonomy.php2
-rw-r--r--include/text.php9
-rw-r--r--include/widgets.php30
-rw-r--r--include/wiki.php96
-rw-r--r--include/zot.php342
20 files changed, 578 insertions, 294 deletions
diff --git a/include/api_zot.php b/include/api_zot.php
index 60cb288af..bdbed6a5f 100644
--- a/include/api_zot.php
+++ b/include/api_zot.php
@@ -28,11 +28,12 @@
api_register_func('api/z/1.0/group','api_group', true);
api_register_func('api/red/xchan','api_red_xchan',true);
api_register_func('api/z/1.0/xchan','api_red_xchan',true);
- api_register_func('api/red/item/new','red_item_new', true);
- api_register_func('api/z/1.0/item/new','red_item_new', true);
+ api_register_func('api/red/item/update','zot_item_update', true);
+ api_register_func('api/z/1.0/item/update','zot_item_update', true);
api_register_func('api/red/item/full','red_item', true);
api_register_func('api/z/1.0/item/full','red_item', true);
+ api_register_func('api/z/1.0/network/stream','api_network_stream', true);
api_register_func('api/z/1.0/abook','api_zot_abook_xchan',true);
api_register_func('api/z/1.0/abconfig','api_zot_abconfig',true);
api_register_func('api/z/1.0/perm_allowed','api_zot_perm_allowed',true);
@@ -55,24 +56,81 @@
}
+ function api_network_stream($type) {
+ if(api_user() === false) {
+ logger('api_channel_stream: no user');
+ return false;
+ }
+
+ $channel = channelx_by_n(api_user());
+ if(! $channel)
+ return false;
+
+
+ if($_SERVER['REQUEST_METHOD'] == 'POST') {
+ // json_return_and_die(post_activity_item($_REQUEST));
+ }
+ else {
+ $mindate = (($_REQUEST['mindate']) ? datetime_convert('UTC','UTC',$_REQUEST['mindate']) : '');
+ if(! $mindate)
+ $mindate = datetime_convert('UTC','UTC', 'now - 14 days');
+
+ $arr = $_REQUEST;
+ $ret = [];
+ $i = items_fetch($arr,App::get_channel(),get_observer_hash());
+ if($i) {
+ foreach($i as $iv) {
+ $ret[] = encode_item($iv);
+ }
+ }
+
+ json_return_and_die($ret);
+ }
+ }
+
+
+
+
+
+
function api_channel_stream($type) {
if(api_user() === false) {
logger('api_channel_stream: no user');
return false;
}
+ $channel = channelx_by_n(api_user());
+ if(! $channel)
+ return false;
+
+
if($_SERVER['REQUEST_METHOD'] == 'POST') {
json_return_and_die(post_activity_item($_REQUEST));
}
else {
- // fetch stream
+ $mindate = (($_REQUEST['mindate']) ? datetime_convert('UTC','UTC',$_REQUEST['mindate']) : '');
+ if(! $mindate)
+ $mindate = datetime_convert('UTC','UTC', 'now - 14 days');
+ json_return_and_die(zot_feed($channel['channel_id'],$channel['channel_hash'],[ 'mindate' => $mindate ]));
}
}
function api_attach_list($type) {
logger('api_user: ' . api_user());
- json_return_and_die(attach_list_files(api_user(),get_observer_hash(),'','','','created asc'));
+ $hash = ((array_key_exists('filehash',$_REQUEST)) ? $_REQUEST['filehash'] : '');
+ $filename = ((array_key_exists('filename',$_REQUEST)) ? $_REQUEST['filename'] : '');
+ $filetype = ((array_key_exists('filetype',$_REQUEST)) ? $_REQUEST['filetype'] : '');
+ $start = ((array_key_exists('start',$_REQUEST)) ? intval($_REQUEST['start']) : 0);
+ $records = ((array_key_exists('records',$_REQUEST)) ? intval($_REQUEST['records']) : 0);
+
+ $x = attach_list_files(api_user(),get_observer_hash(),$hash,$filename,$filetype,'created asc',$start,$records);
+ if($start || $records) {
+ $x['start'] = $start;
+ $x['records'] = count($x['results']);
+ }
+
+ json_return_and_die($x);
}
@@ -237,8 +295,8 @@
}
if($r) {
- $x = q("select * from group_member left join xchan on group_member.xchan = xchan.xchan_hash
- left join abook on abook_xchan = xchan_hash where gid = %d",
+ $x = q("select * from group_member left join abook on abook_xchan = xchan and abook_channel = group_member.uid left join xchan on group_member.xchan = xchan.xchan_hash
+ where gid = %d",
intval($r[0]['id'])
);
json_return_and_die($x);
@@ -266,7 +324,7 @@
require_once('include/hubloc.php');
if($_SERVER['REQUEST_METHOD'] === 'POST') {
- $r = xchan_store($_REQUEST);
+ // $r = xchan_store($_REQUEST);
}
$r = xchan_fetch($_REQUEST);
json_return_and_die($r);
@@ -341,15 +399,15 @@
}
- function red_item_new($type) {
+ function zot_item_update($type) {
if (api_user() === false) {
- logger('api_red_item_new: no user');
+ logger('api_red_item_store: no user');
return false;
}
- logger('api_red_item_new: REQUEST ' . print_r($_REQUEST,true));
- logger('api_red_item_new: FILES ' . print_r($_FILES,true));
+ logger('api_red_item_store: REQUEST ' . print_r($_REQUEST,true));
+ logger('api_red_item_store: FILES ' . print_r($_FILES,true));
// set this so that the item_post() function is quiet and doesn't redirect or emit json
@@ -360,11 +418,10 @@
if(x($_FILES,'media')) {
$_FILES['userfile'] = $_FILES['media'];
// upload the image if we have one
- $_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
- $mod = new Zotlabs\Module\Wall_upload();
+ $mod = new Zotlabs\Module\Wall_attach();
$media = $mod->post();
- if(strlen($media)>0)
- $_REQUEST['body'] .= "\n\n".$media;
+ if($media)
+ $_REQUEST['body'] .= "\n\n" . $media;
}
$mod = new Zotlabs\Module\Item();
diff --git a/include/attach.php b/include/attach.php
index ac0185f5d..ba2f60a90 100644
--- a/include/attach.php
+++ b/include/attach.php
@@ -197,13 +197,13 @@ function attach_list_files($channel_id, $observer, $hash = '', $filename = '', $
$sql_extra .= protect_sprintf(" and hash = '" . dbesc($hash) . "' ");
if($filename)
- $sql_extra .= protect_sprintf(" and filename like '@" . dbesc($filename) . "@' ");
+ $sql_extra .= protect_sprintf(" and filename like '%" . dbesc($filename) . "%' ");
if($filetype)
- $sql_extra .= protect_sprintf(" and filetype like '@" . dbesc($filetype) . "@' ");
+ $sql_extra .= protect_sprintf(" and filetype like '%" . dbesc($filetype) . "%' ");
if($entries)
- $limit = " limit " . intval($start) . ", " . intval(entries) . " ";
+ $limit = " limit " . intval($start) . ", " . intval($entries) . " ";
// Retrieve all columns except 'data'
diff --git a/include/bb2diaspora.php b/include/bb2diaspora.php
index da02d6cac..e22b6a7dd 100644
--- a/include/bb2diaspora.php
+++ b/include/bb2diaspora.php
@@ -149,16 +149,18 @@ function markdown_to_bb($s, $use_zrl = false) {
$s = html2bbcode($s);
+ $s = preg_replace("/\[([uz])rl=(.*?)\]\[\/[uz]rl\]/ism",'[$1rl=$2]$2[/$1rl]',$s);
+
// protect the recycle symbol from turning into a tag, but without unescaping angles and naked ampersands
$s = str_replace('♲',html_entity_decode('♲',ENT_QUOTES,'UTF-8'),$s);
// Convert everything that looks like a link to a link
if($use_zrl) {
$s = str_replace(array('[img','/img]'),array('[zmg','/zmg]'),$s);
- $s = preg_replace("/([^\]\=]|^)(https?\:\/\/)([a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)/ism", '$1[zrl=$2$3]$2$3[/zrl]',$s);
+ $s = preg_replace("/([^\]\=]|^)(https?\:\/\/)([a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\(\)]+)/ism", '$1[zrl=$2$3]$2$3[/zrl]',$s);
}
else {
- $s = preg_replace("/([^\]\=]|^)(https?\:\/\/)([a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)/ism", '$1[url=$2$3]$2$3[/url]',$s);
+ $s = preg_replace("/([^\]\=]|^)(https?\:\/\/)([a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\(\)]+)/ism", '$1[url=$2$3]$2$3[/url]',$s);
}
// remove duplicate adjacent code tags
@@ -427,6 +429,12 @@ function bb2diaspora($Text,$preserve_nl = false, $fordiaspora = true) {
$Text = preg_replace_callback('/\@\!?\[([zu])rl\=(\w+.*?)\](\w+.*?)\[\/([zu])rl\]/i', 'bb2dmention_callback', $Text);
+ // strip map tags, as the rendering is performed in bbcode() and the resulting output
+ // is not compatible with Diaspora (at least in the case of openstreetmap and probably
+ // due to the inclusion of an html iframe)
+
+ $Text = preg_replace("/\[map\=(.*?)\]/ism", '$1', $Text);
+ $Text = preg_replace("/\[map\](.*?)\[\/map\]/ism", '$1', $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);
diff --git a/include/bbcode.php b/include/bbcode.php
index 21bc6de77..b315255f5 100644
--- a/include/bbcode.php
+++ b/include/bbcode.php
@@ -512,10 +512,10 @@ function bb_code($match) {
}
function bb_highlight($match) {
- if(in_array(strtolower($match[1]),['php','css','mysql','sql','abap','diff','html','perl','ruby',
+ $lang = ((in_array(strtolower($match[1]),['php','css','mysql','sql','abap','diff','html','perl','ruby',
'vbscript','avrc','dtd','java','xml','cpp','python','javascript','js','json','sh']))
- return text_highlight($match[2],strtolower($match[1]));
- return $match[0];
+ ? strtolower($match[1]) : 'php' );
+ return text_highlight($match[2],$lang);
}
function bb_fixtable_lf($match) {
@@ -529,7 +529,49 @@ function bb_fixtable_lf($match) {
}
+function parseIdentityAwareHTML($Text) {
+
+ // process [observer] tags before we do anything else because we might
+ // be stripping away stuff that then doesn't need to be worked on anymore
+ $observer = App::get_observer();
+
+ if ((strpos($Text,'[/observer]') !== false) || (strpos($Text,'[/rpost]') !== false)) {
+ if ($observer) {
+ $Text = preg_replace("/\[observer\=1\](.*?)\[\/observer\]/ism", '$1', $Text);
+ $Text = preg_replace("/\[observer\=0\].*?\[\/observer\]/ism", '', $Text);
+ $Text = preg_replace_callback("/\[rpost(=(.*?))?\](.*?)\[\/rpost\]/ism", 'rpost_callback', $Text);
+ } else {
+ $Text = preg_replace("/\[observer\=1\].*?\[\/observer\]/ism", '', $Text);
+ $Text = preg_replace("/\[observer\=0\](.*?)\[\/observer\]/ism", '$1', $Text);
+ $Text = preg_replace("/\[rpost(=.*?)?\](.*?)\[\/rpost\]/ism", '', $Text);
+ }
+ }
+ // replace [observer.baseurl]
+ if ($observer) {
+ $s1 = '<span class="bb_observer" title="' . t('Different viewers will see this text differently') . '">';
+ $s2 = '</span>';
+ $obsBaseURL = $observer['xchan_connurl'];
+ $obsBaseURL = preg_replace("/\/poco\/.*$/", '', $obsBaseURL);
+ $Text = str_replace('[observer.baseurl]', $obsBaseURL, $Text);
+ $Text = str_replace('[observer.url]',$observer['xchan_url'], $Text);
+ $Text = str_replace('[observer.name]',$s1 . $observer['xchan_name'] . $s2, $Text);
+ $Text = str_replace('[observer.address]',$s1 . $observer['xchan_addr'] . $s2, $Text);
+ $Text = str_replace('[observer.webname]', substr($observer['xchan_addr'],0,strpos($observer['xchan_addr'],'@')), $Text);
+ $Text = str_replace('[observer.photo]',$s1 . '[zmg]'.$observer['xchan_photo_l'].'[/zmg]' . $s2, $Text);
+ } else {
+ $Text = str_replace('[observer.baseurl]', '', $Text);
+ $Text = str_replace('[observer.url]','', $Text);
+ $Text = str_replace('[observer.name]','', $Text);
+ $Text = str_replace('[observer.address]','', $Text);
+ $Text = str_replace('[observer.webname]','',$Text);
+ $Text = str_replace('[observer.photo]','', $Text);
+ }
+
+ $Text = str_replace(array('[baseurl]','[sitename]'),array(z_root(),get_config('system','sitename')),$Text);
+
+ return $Text;
+}
// BBcode 2 HTML was written by WAY2WEB.net
// extended to work with Mistpark/Friendica/Redmatrix/Hubzilla - Mike Macgirvin
@@ -661,7 +703,7 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
// Perform URL Search
- $urlchars = '[a-zA-Z0-9\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\+\,\@]';
+ $urlchars = '[a-zA-Z0-9\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\+\,\@\(\)]';
if (strpos($Text,'http') !== false) {
if($tryoembed) {
@@ -745,6 +787,12 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
if (strpos($Text,'[/color]') !== false) {
$Text = preg_replace("(\[color=(.*?)\](.*?)\[\/color\])ism", "<span style=\"color: $1;\">$2</span>", $Text);
}
+ // Check for colored text
+ if (strpos($Text,'[/hl]') !== false) {
+ $Text = preg_replace("(\[hl\](.*?)\[\/hl\])ism", "<span style=\"background-color: yellow;\">$1</span>", $Text);
+ $Text = preg_replace("(\[hl=(.*?)\](.*?)\[\/hl\])ism", "<span style=\"background-color: $1;\">$2</span>", $Text);
+ }
+
// Check for sized text
// [size=50] --> font-size: 50px (with the unit).
if (strpos($Text,'[/size]') !== false) {
@@ -776,12 +824,14 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
$Text = preg_replace("(\[h6\](.*?)\[\/h6\])ism",'<h6>$1</h6>',$Text);
}
// Check for table of content without params
- if (strpos($Text,'[toc]') !== false) {
- $Text = preg_replace("/\[toc\]/ism",'<ul id="toc"></ul>',$Text);
+ while(strpos($Text,'[toc]') !== false) {
+ $toc_id = 'toc-' . random_string(10);
+ $Text = preg_replace("/\[toc\]/ism", '<ul id="' . $toc_id . '" class="toc" data-toc=".section-content-wrapper"></ul><script>$("#' . $toc_id . '").toc();</script>', $Text, 1);
}
// Check for table of content with params
- if (strpos($Text,'[toc') !== false) {
- $Text = preg_replace("/\[toc([^\]]+?)\]/ism",'<ul$1></ul>',$Text);
+ while(strpos($Text,'[toc') !== false) {
+ $toc_id = 'toc-' . random_string(10);
+ $Text = preg_replace("/\[toc([^\]]+?)\]/ism", '<ul id="' . $toc_id . '" class="toc"$1></ul><script>$("#' . $toc_id . '").toc();</script>', $Text, 1);
}
// Check for centered text
if (strpos($Text,'[/center]') !== false) {
diff --git a/include/config.php b/include/config.php
index 44ef29614..0b0e639ab 100644
--- a/include/config.php
+++ b/include/config.php
@@ -35,8 +35,8 @@ function load_config($family) {
Zlib\Config::Load($family);
}
-function get_config($family, $key) {
- return Zlib\Config::Get($family,$key);
+function get_config($family, $key, $default = false) {
+ return Zlib\Config::Get($family,$key,$default);
}
function set_config($family, $key, $value) {
@@ -51,8 +51,8 @@ function load_pconfig($uid) {
Zlib\PConfig::Load($uid);
}
-function get_pconfig($uid, $family, $key, $instore = false) {
- return Zlib\PConfig::Get($uid,$family,$key,$instore = false);
+function get_pconfig($uid, $family, $key, $default = false) {
+ return Zlib\PConfig::Get($uid,$family,$key,$default);
}
function set_pconfig($uid, $family, $key, $value) {
@@ -67,8 +67,8 @@ function load_xconfig($xchan) {
Zlib\XConfig::Load($xchan);
}
-function get_xconfig($xchan, $family, $key) {
- return Zlib\XConfig::Get($xchan,$family,$key);
+function get_xconfig($xchan, $family, $key, $default = false) {
+ return Zlib\XConfig::Get($xchan,$family,$key, $default);
}
function set_xconfig($xchan, $family, $key, $value) {
@@ -83,8 +83,8 @@ function load_aconfig($account_id) {
Zlib\AConfig::Load($account_id);
}
-function get_aconfig($account_id, $family, $key) {
- return Zlib\AConfig::Get($account_id, $family, $key);
+function get_aconfig($account_id, $family, $key, $default = false) {
+ return Zlib\AConfig::Get($account_id, $family, $key, $default);
}
function set_aconfig($account_id, $family, $key, $value) {
@@ -99,8 +99,8 @@ function load_abconfig($chan, $xhash, $family = '') {
return Zlib\AbConfig::Load($chan,$xhash,$family);
}
-function get_abconfig($chan,$xhash,$family,$key) {
- return Zlib\AbConfig::Get($chan,$xhash,$family,$key);
+function get_abconfig($chan,$xhash,$family,$key, $default = false) {
+ return Zlib\AbConfig::Get($chan,$xhash,$family,$key, $default);
}
function set_abconfig($chan,$xhash,$family,$key,$value) {
@@ -115,8 +115,8 @@ function load_iconfig(&$item) {
Zlib\IConfig::Load($item);
}
-function get_iconfig(&$item, $family, $key) {
- return Zlib\IConfig::Get($item, $family, $key);
+function get_iconfig(&$item, $family, $key, $default = false) {
+ return Zlib\IConfig::Get($item, $family, $key, $default);
}
function set_iconfig(&$item, $family, $key, $value, $sharing = false) {
diff --git a/include/conversation.php b/include/conversation.php
index c260eb4a0..0f61eea27 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -363,7 +363,7 @@ function localize_item(&$item){
if(intval($item['item_obscured'])
&& strlen($item['body']) && (! strpos($item['body'],'data'))) {
- $item['body'] = json_encode(crypto_encapsulate($item['body'],get_config('system','pubkey')));
+ $item['body'] = z_obscure($item['body']);
}
}
@@ -1752,7 +1752,7 @@ function profile_tabs($a, $is_owner = false, $nickname = null){
if(feature_enabled($uid,'wiki') && (get_account_techlevel($account_id) > 3)) {
$tabs[] = array(
- 'label' => t('Wiki'),
+ 'label' => t('Wikis'),
'url' => z_root() . '/wiki/' . $nickname,
'sel' => ((argv(0) == 'wiki') ? 'active' : ''),
'title' => t('Wiki'),
diff --git a/include/crypto.php b/include/crypto.php
index bc798d919..f75390985 100644
--- a/include/crypto.php
+++ b/include/crypto.php
@@ -48,27 +48,122 @@ function pkcs5_unpad($text)
function AES256CBC_encrypt($data,$key,$iv) {
return openssl_encrypt($data,'aes-256-cbc',str_pad($key,32,"\0"),OPENSSL_RAW_DATA,str_pad($iv,16,"\0"));
-
}
function AES256CBC_decrypt($data,$key,$iv) {
return openssl_decrypt($data,'aes-256-cbc',str_pad($key,32,"\0"),OPENSSL_RAW_DATA,str_pad($iv,16,"\0"));
+}
+
+function AES128CBC_encrypt($data,$key,$iv) {
+ $key = substr($key,0,16);
+ $iv = substr($iv,0,16);
+ return openssl_encrypt($data,'aes-128-cbc',str_pad($key,16,"\0"),OPENSSL_RAW_DATA,str_pad($iv,16,"\0"));
+}
+
+function AES128CBC_decrypt($data,$key,$iv) {
+ $key = substr($key,0,16);
+ $iv = substr($iv,0,16);
+ return openssl_decrypt($data,'aes-128-cbc',str_pad($key,16,"\0"),OPENSSL_RAW_DATA,str_pad($iv,16,"\0"));
+}
+
+function STD_encrypt($data,$key,$iv) {
+ $key = substr($key,0,32);
+ $iv = substr($iv,0,16);
+ return openssl_encrypt($data,'aes-256-cbc',str_pad($key,32,"\0"),OPENSSL_RAW_DATA,str_pad($iv,16,"\0"));
+}
+
+function STD_decrypt($data,$key,$iv) {
+ $key = substr($key,0,32);
+ $iv = substr($iv,0,16);
+ return openssl_decrypt($data,'aes-256-cbc',str_pad($key,32,"\0"),OPENSSL_RAW_DATA,str_pad($iv,16,"\0"));
+}
+function CAST5CBC_encrypt($data,$key,$iv) {
+ $key = substr($key,0,16);
+ $iv = substr($iv,0,8);
+ return openssl_encrypt($data,'cast5-cbc',str_pad($key,16,"\0"),OPENSSL_RAW_DATA,str_pad($iv,8,"\0"));
+}
+
+function CAST5CBC_decrypt($data,$key,$iv) {
+ $key = substr($key,0,16);
+ $iv = substr($iv,0,8);
+ return openssl_decrypt($data,'cast5-cbc',str_pad($key,16,"\0"),OPENSSL_RAW_DATA,str_pad($iv,8,"\0"));
}
function crypto_encapsulate($data,$pubkey,$alg='aes256cbc') {
+ $fn = strtoupper($alg) . '_encrypt';
+
if($alg === 'aes256cbc')
return aes_encapsulate($data,$pubkey);
+ return other_encapsulate($data,$pubkey,$alg);
+
+}
+
+function other_encapsulate($data,$pubkey,$alg) {
+ if(! $pubkey)
+ logger('no key. data: ' . $data);
+
+ $fn = strtoupper($alg) . '_encrypt';
+ if(function_exists($fn)) {
+
+ // A bit hesitant to use openssl_random_pseudo_bytes() as we know
+ // it has been historically targeted by US agencies for 'weakening'.
+ // It is still arguably better than trying to come up with an
+ // alternative cryptographically secure random generator.
+ // There is little point in using the optional second arg to flag the
+ // assurance of security since it is meaningless if the source algorithms
+ // have been compromised. Also none of this matters if RSA has been
+ // compromised by state actors and evidence is mounting that this has
+ // already happened.
+
+ $key = openssl_random_pseudo_bytes(256);
+ $iv = openssl_random_pseudo_bytes(256);
+ $result['data'] = base64url_encode($fn($data,$key,$iv),true);
+ // log the offending call so we can track it down
+ if(! openssl_public_encrypt($key,$k,$pubkey)) {
+ $x = debug_backtrace();
+ logger('RSA failed. ' . print_r($x[0],true));
+ }
+
+ $result['alg'] = $alg;
+ $result['key'] = base64url_encode($k,true);
+ openssl_public_encrypt($iv,$i,$pubkey);
+ $result['iv'] = base64url_encode($i,true);
+ return $result;
+ }
+ else {
+ $x = [ 'data' => $data, 'pubkey' => $pubkey, 'alg' => $alg, 'result' => $data ];
+ call_hooks('other_encapsulate', $x);
+ return $x['result'];
+ }
+}
+
+function crypto_methods() {
+
+ if(\Zotlabs\Lib\System::get_server_role() !== 'pro')
+ return [ 'aes256cbc' ];
+
+ // 'std' is the new project standard which is aes256cbc but transmits/receives 256-byte key and iv.
+ // aes256cbc is provided for compatibility with earlier zot implementations which assume 32-byte key and 16-byte iv.
+ // other_encapsulate() now produces these longer keys/ivs by default so that it is difficult to guess a
+ // particular implementation or choice of underlying implementations based on the key/iv length.
+ // The actual methods are responsible for deriving the actual key/iv from the provided parameters;
+ // possibly by truncation or segmentation - though many other methods could be used.
+
+ $r = [ 'std', 'aes256cbc', 'aes128cbc', 'cast5cbc' ];
+ call_hooks('crypto_methods',$r);
+ return $r;
+
}
function aes_encapsulate($data,$pubkey) {
if(! $pubkey)
logger('aes_encapsulate: no key. data: ' . $data);
- $key = random_string(32,RANDOM_STRING_TEXT);
- $iv = random_string(16,RANDOM_STRING_TEXT);
+ $key = openssl_random_pseudo_bytes(32);
+ $iv = openssl_random_pseudo_bytes(16);
$result['data'] = base64url_encode(AES256CBC_encrypt($data,$key,$iv),true);
// log the offending call so we can track it down
if(! openssl_public_encrypt($key,$k,$pubkey)) {
@@ -89,6 +184,22 @@ function crypto_unencapsulate($data,$prvkey) {
if($alg === 'aes256cbc')
return aes_unencapsulate($data,$prvkey);
+ return other_unencapsulate($data,$prvkey,$alg);
+
+}
+
+function other_unencapsulate($data,$prvkey,$alg) {
+ $fn = strtoupper($alg) . '_decrypt';
+ if(function_exists($fn)) {
+ openssl_private_decrypt(base64url_decode($data['key']),$k,$prvkey);
+ openssl_private_decrypt(base64url_decode($data['iv']),$i,$prvkey);
+ return $fn(base64url_decode($data['data']),$k,$i);
+ }
+ else {
+ $x = [ 'data' => $data, 'prvkey' => $prvkey, 'alg' => $alg, 'result' => $data ];
+ call_hooks('other_unencapsulate',$x);
+ return $x['result'];
+ }
}
diff --git a/include/dba/dba_driver.php b/include/dba/dba_driver.php
index 0b5f085af..81a3bd590 100755
--- a/include/dba/dba_driver.php
+++ b/include/dba/dba_driver.php
@@ -98,7 +98,7 @@ class DBA {
abstract class dba_driver {
// legacy behavior
- protected $db;
+ public $db;
protected $pdo = array();
public $debug = 0;
diff --git a/include/dba/dba_pdo.php b/include/dba/dba_pdo.php
index e235c467b..f76e6cdd7 100755
--- a/include/dba/dba_pdo.php
+++ b/include/dba/dba_pdo.php
@@ -133,7 +133,7 @@ class dba_pdo extends dba_driver {
}
function unescapebin($str) {
- if($this->driver_dbtype === 'pgsql') {
+ if($this->driver_dbtype === 'pgsql' && (! is_null($str))) {
$x = '';
while(! feof($str)) {
$x .= fread($str,8192);
diff --git a/include/dir_fns.php b/include/dir_fns.php
index 03cc2706a..3922730fc 100644
--- a/include/dir_fns.php
+++ b/include/dir_fns.php
@@ -192,17 +192,19 @@ function sync_directories($dirmode) {
'site_update' => NULL_DATE,
'site_directory' => DIRECTORY_FALLBACK_MASTER . '/dirsearch',
'site_realm' => DIRECTORY_REALM,
- 'site_valid' => 1
+ 'site_valid' => 1,
+ 'site_crypto' => 'aes256cbc'
);
- $x = q("insert into site ( site_url, site_flags, site_update, site_directory, site_realm, site_valid )
- values ( '%s', %d, '%s', '%s', '%s', %d ) ",
+ $x = q("insert into site ( site_url, site_flags, site_update, site_directory, site_realm, site_valid, site_crypto )
+ values ( '%s', %d, '%s', '%s', '%s', %d, '%s' ) ",
dbesc($r[0]['site_url']),
intval($r[0]['site_flags']),
dbesc($r[0]['site_update']),
dbesc($r[0]['site_directory']),
dbesc($r[0]['site_realm']),
- intval($r[0]['site_valid'])
+ intval($r[0]['site_valid']),
+ dbesc($r[0]['site_crypto'])
);
$r = q("select * from site where site_flags in (%d, %d) and site_url != '%s' and site_type = %d ",
diff --git a/include/help.php b/include/help.php
index f7fffc4d4..03d01d1a1 100644
--- a/include/help.php
+++ b/include/help.php
@@ -15,7 +15,7 @@ function get_help_content($tocpath = false) {
$text = '';
$path = (($tocpath !== false) ? $tocpath : '');
-
+
if($tocpath === false && argc() > 1) {
$path = '';
for($x = 1; $x < argc(); $x ++) {
@@ -55,6 +55,7 @@ function get_help_content($tocpath = false) {
if(! $text) {
$doctype = 'bbcode';
$text = load_doc_file('doc/main.bb');
+ goaway('/help/about/about_hubzilla');
\App::$page['title'] = t('Help');
}
@@ -68,7 +69,7 @@ function get_help_content($tocpath = false) {
}
if($doctype === 'html')
- $content = $text;
+ $content = parseIdentityAwareHTML($text);
if($doctype === 'markdown') {
require_once('library/markdown.php');
# escape #include tags
diff --git a/include/items.php b/include/items.php
index 4ac4d6049..3bbd4cce3 100755
--- a/include/items.php
+++ b/include/items.php
@@ -1463,6 +1463,11 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
$ret = array('success' => false, 'item_id' => 0);
+ if(array_key_exists('cancel',$arr) && $arr['cancel']) {
+ logger('cancelled by plugin');
+ return $ret;
+ }
+
if(! $arr['uid']) {
logger('item_store: no uid');
$ret['message'] = 'No uid.';
@@ -1808,6 +1813,7 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
$x = q("update item set parent = id where id = %d",
intval($r[0]['id'])
);
+ $arr['parent'] = $r[0]['id'];
}
@@ -1881,6 +1887,12 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
$allow_exec = $d['allow_exec'];
$ret = array('success' => false, 'item_id' => 0);
+
+ if(array_key_exists('cancel',$arr) && $arr['cancel']) {
+ logger('cancelled by plugin');
+ return $ret;
+ }
+
if(! intval($arr['uid'])) {
logger('item_store_update: no uid');
$ret['message'] = 'no uid.';
@@ -3968,8 +3980,8 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
$sql_nets .= "( abook.abook_closeness >= " . intval($arr['cmin']) . " ";
$sql_nets .= " AND abook.abook_closeness <= " . intval($arr['cmax']) . " ) ";
- /** @fixme dead code, $cmax is undefined */
- if ($cmax == 99)
+
+ if ($arr['cmax'] == 99)
$sql_nets .= " OR abook.abook_closeness IS NULL ) ";
}
}
@@ -4104,25 +4116,21 @@ function webpage_to_namespace($webpage) {
function update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remote_id,$mid) {
- $page_type = '';
-
if(! $post_id)
return;
- if($webpage == ITEM_TYPE_WEBPAGE)
- $page_type = 'WEBPAGE';
- elseif($webpage == ITEM_TYPE_BLOCK)
- $page_type = 'BUILDBLOCK';
- elseif($webpage == ITEM_TYPE_PDL)
- $page_type = 'PDL';
- elseif($webpage == ITEM_TYPE_DOC)
- $page_type = 'docfile';
- elseif($namespace && $remote_id) {
+ $page_type = webpage_to_namespace($webpage);
+
+ if($page_type == 'unknown' && $namespace && $remote_id) {
$page_type = $namespace;
$pagetitle = $remote_id;
}
+ else {
+ $page_type = '';
+ }
if($page_type) {
+
// store page info as an alternate message_id so we can access it via
// https://sitename/page/$channelname/$pagetitle
// if no pagetitle was given or it couldn't be transliterated into a url, use the first
diff --git a/include/nav.php b/include/nav.php
index c2a058457..2762e2a14 100644
--- a/include/nav.php
+++ b/include/nav.php
@@ -108,7 +108,7 @@ EOT;
if(feature_enabled($channel['channel_id'],'webpages') && (! $basic))
$nav['usermenu'][] = Array('webpages/' . $channel['channel_address'],t('Webpages'),"",t('Your webpages'),'webpages_nav_btn');
if(feature_enabled($channel['channel_id'],'wiki') && (! $basic))
- $nav['usermenu'][] = Array('wiki/' . $channel['channel_address'],t('Wiki'),"",t('Your wiki'),'wiki_nav_btn');
+ $nav['usermenu'][] = Array('wiki/' . $channel['channel_address'],t('Wikis'),"",t('Your wikis'),'wiki_nav_btn');
}
else {
if(! get_account_id()) {
@@ -127,26 +127,24 @@ EOT;
);
}
- if($observer) {
- $nav['lock'] = array('logout','','lock',
- sprintf( t('%s - click to logout'), $observer['xchan_addr']));
- }
elseif(! $_SESSION['authenticated']) {
$nav['loginmenu'][] = Array('rmagic',t('Remote authentication'),'',t('Click to authenticate to your home hub'),'rmagic_nav_btn');
}
- /**
- * "Home" should also take you home from an authenticated remote profile connection
- */
-
$homelink = get_my_url();
if(! $homelink) {
$observer = App::get_observer();
$homelink = (($observer) ? $observer['xchan_url'] : '');
}
- if(! local_channel())
- $nav['home'] = array($homelink, t('Home'), "", t('Home Page'),'home_nav_btn');
+ if(! local_channel()) {
+ $nav['rusermenu'] = array(
+ $homelink,
+ t('Get me home'),
+ 'logout',
+ t('Log me out of this site')
+ );
+ }
if(((get_config('system','register_policy') == REGISTER_OPEN) || (get_config('system','register_policy') == REGISTER_APPROVE)) && (! $_SESSION['authenticated']))
$nav['register'] = array('register',t('Register'), "", t('Create an account'),'register_nav_btn');
diff --git a/include/oembed.php b/include/oembed.php
index 52fb04058..eb7b76437 100755
--- a/include/oembed.php
+++ b/include/oembed.php
@@ -338,7 +338,7 @@ function oembed_iframe($src,$width,$height) {
// Make sure any children are sandboxed within their own iframe.
- return '<iframe ' . $scroll . 'height="' . $height . '" width="' . $width . '" src="' . $s . '" frameborder="no" >'
+ return '<iframe ' . $scroll . 'height="' . $height . '" width="' . $width . '" src="' . $s . '" allowfullscreen frameborder="no" >'
. t('Embedded content') . '</iframe>';
}
diff --git a/include/queue_fn.php b/include/queue_fn.php
index 1e3126f77..0950faf85 100644
--- a/include/queue_fn.php
+++ b/include/queue_fn.php
@@ -93,7 +93,7 @@ function queue_deliver($outq, $immediate = false) {
// your site has existed. Since we don't know for sure what these sites are,
// call them unknown
- q("insert into site (site_url, site_update, site_dead, site_type) values ('%s','%s',0,%d) ",
+ q("insert into site (site_url, site_update, site_dead, site_type, site_crypto) values ('%s','%s',0,%d,'') ",
dbesc($base),
dbesc(datetime_convert()),
intval(($outq['outq_driver'] === 'post') ? SITE_TYPE_NOTZOT : SITE_TYPE_UNKNOWN)
diff --git a/include/taxonomy.php b/include/taxonomy.php
index 067bd3246..0b4b2aa9a 100644
--- a/include/taxonomy.php
+++ b/include/taxonomy.php
@@ -386,7 +386,7 @@ function get_things($profile_hash,$uid) {
$things[$k] = null;
foreach($r as $rr) {
- $l = q("select xchan_name, xchan_photo_s, xchan_url from likes left join xchan on likee = xchan_hash where
+ $l = q("select xchan_name, xchan_photo_s, xchan_url from likes left join xchan on liker = xchan_hash where
target_type = '%s' and target_id = '%s' and channel_id = %d",
dbesc(ACTIVITY_OBJ_THING),
dbesc($rr['obj_obj']),
diff --git a/include/text.php b/include/text.php
index 12b37222b..b25eb8e46 100644
--- a/include/text.php
+++ b/include/text.php
@@ -2049,7 +2049,7 @@ function ids_to_array($arr,$idx = 'id') {
$t = array();
if($arr) {
foreach($arr as $x) {
- if(array_key_exists($idx,$x) && strlen($x[$idx]) && (! in_array($x[$idx],$t))) {
+ if(array_key_exists($idx,$x) && strlen($x[$idx]) && (! in_array($x[$idx],$t))) {
$t[] = $x[$idx];
}
}
@@ -2060,12 +2060,15 @@ function ids_to_array($arr,$idx = 'id') {
-function ids_to_querystr($arr,$idx = 'id') {
+function ids_to_querystr($arr,$idx = 'id',$quote = false) {
$t = array();
if($arr) {
foreach($arr as $x) {
if(! in_array($x[$idx],$t)) {
- $t[] = $x[$idx];
+ if($quote)
+ $t[] = "'" . dbesc($x[$idx]) . "'";
+ else
+ $t[] = $x[$idx];
}
}
}
diff --git a/include/widgets.php b/include/widgets.php
index 3dc555b46..b6d3fb7ae 100644
--- a/include/widgets.php
+++ b/include/widgets.php
@@ -956,7 +956,7 @@ function widget_wiki_list($arr) {
}
}
if ($wikis) {
- return replace_macros(get_markup_template('wikilist.tpl'), array(
+ return replace_macros(get_markup_template('wikilist_widget.tpl'), array(
'$header' => t('Wiki List'),
'$channel' => $channel['channel_address'],
'$wikis' => $wikis['wikis'],
@@ -967,7 +967,7 @@ function widget_wiki_list($arr) {
'$view' => t('View'),
'$addnew' => t('Create new wiki'),
'$create' => t('Create'),
- '$wikiName' => array('wikiName', t('Wiki name'), '', ''),
+ '$wikiName' => array('wikiName', t('Wiki name')),
'$lockstate' => $x['lockstate'],
'$acl' => $x['acl'],
'$allow_cid' => $x['allow_cid'],
@@ -975,7 +975,7 @@ function widget_wiki_list($arr) {
'$deny_cid' => $x['deny_cid'],
'$deny_gid' => $x['deny_gid'],
'$bang' => $x['bang'],
- '$notify' => t('Send notification')
+ '$notify' => array('postVisible', t('Send notification'), '', '', array(t('No'), t('Yes')))
));
}
return '';
@@ -1017,6 +1017,7 @@ function widget_wiki_pages($arr) {
'$pages' => $pages,
'$canadd' => $can_create,
'$addnew' => t('Add new page'),
+ '$pageName' => array('pageName', t('Page name')),
));
}
@@ -1472,14 +1473,23 @@ function widget_forums($arr) {
$perms_sql = item_permissions_sql(local_channel()) . item_normal();
- /**
- * We used to try and find public forums with custom permissions by checking to see if
- * send_stream was false and tag_deliver was true. However with the newer extensible
- * permissions infrastructure this makes for a very complicated query. Now we're only
- * checking channels that report themselves specifically as pubforums
- */
+ $xf = false;
+
+ $x1 = q("select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'send_stream' and v = 0",
+ intval(local_channel())
+ );
+ if($x1) {
+ $xc = ids_to_querystr($x1,'xchan',true);
+ $x2 = q("select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'tag_deliver' and v = 1 and xchan in (" . $xc . ") ",
+ intval(local_channel())
+ );
+ if($x2)
+ $xf = ids_to_querystr($x2,'xchan',true);
+ }
+
+ $sql_extra = (($xf) ? " and ( xchan_hash in (" . $xf . ") or xchan_pubforum = 1 ) " : " and xchan_pubforum = 1 ");
- $r1 = q("select abook_id, xchan_hash, xchan_name, xchan_url, xchan_photo_s from abook left join xchan on abook_xchan = xchan_hash where xchan_pubforum = 1 and xchan_deleted = 0 and abook_channel = %d order by xchan_name $limit ",
+ $r1 = q("select abook_id, xchan_hash, xchan_name, xchan_url, xchan_photo_s from abook left join xchan on abook_xchan = xchan_hash where xchan_deleted = 0 and abook_channel = %d $sql_extra order by xchan_name $limit ",
intval(local_channel())
);
if(! $r1)
diff --git a/include/wiki.php b/include/wiki.php
index bcdf9d7d8..542d617b9 100644
--- a/include/wiki.php
+++ b/include/wiki.php
@@ -19,6 +19,7 @@ function wiki_list($channel, $observer_hash) {
$w['htmlName'] = get_iconfig($w, 'wiki', 'htmlName');
$w['urlName'] = get_iconfig($w, 'wiki', 'urlName');
$w['path'] = get_iconfig($w, 'wiki', 'path');
+ $w['mimeType'] = get_iconfig($w, 'wiki', 'mimeType');
}
}
// TODO: query db for wikis the observer can access. Return with two lists, for read and write access
@@ -31,14 +32,30 @@ function wiki_page_list($resource_id) {
if (!$w['path']) {
return array('pages' => null, 'wiki' => null);
}
- $pages = array();
+
+ $pages[] = [
+ 'resource_id' => '',
+ 'title' => 'Home',
+ 'url' => 'Home',
+ 'link_id' => 'id_wiki_home_0'
+ ];
+
if (is_dir($w['path']) === true) {
$files = array_diff(scandir($w['path']), array('.', '..', '.git'));
// TODO: Check that the files are all text files
-
+ $i = 1;
foreach($files as $file) {
- // strip the .md file extension and unwrap URL encoding to leave HTML encoded name
- $pages[] = array('title' => urldecode(substr($file, 0, -3)), 'url' => urlencode(substr($file, 0, -3)));
+ // strip the file extension and unwrap URL encoding to leave HTML encoded name
+ $title = substr($file, 0, -3);
+ if(urldecode($title) !== 'Home') {
+ $pages[] = [
+ 'resource_id' => $resource_id,
+ 'title' => urldecode($title),
+ 'url' => $title,
+ 'link_id' => 'id_' . substr($resource_id, 0, 10) . '_' . $i
+ ];
+ $i++;
+ }
}
}
@@ -75,7 +92,7 @@ function wiki_create_wiki($channel, $observer_hash, $wiki, $acl) {
$resource_id = random_string();
$r = q("SELECT mid FROM item WHERE resource_id = '%s' AND resource_type = '%s' AND uid = %d LIMIT 1",
dbesc($resource_id),
- dbesc(WIKI_ITEM_RESOURCE_TYPE),
+ dbesc(WIKI_ITEM_RESOURCE_TYPE),
intval($channel['channel_id'])
);
if (count($r))
@@ -123,6 +140,9 @@ function wiki_create_wiki($channel, $observer_hash, $wiki, $acl) {
if (!set_iconfig($arr, 'wiki', 'urlName', $wiki['urlName'], true)) {
return array('item' => null, 'success' => false);
}
+ if (!set_iconfig($arr, 'wiki', 'mimeType', $wiki['mimeType'], true)) {
+ return array('item' => null, 'success' => false);
+ }
$post = item_store($arr);
$item_id = $post['item_id'];
@@ -152,8 +172,8 @@ function wiki_delete_wiki($resource_id) {
function wiki_get_wiki($resource_id) {
$item = q("SELECT * FROM item WHERE resource_type = '%s' AND resource_id = '%s' AND item_deleted = 0 limit 1",
- dbesc(WIKI_ITEM_RESOURCE_TYPE),
- dbesc($resource_id)
+ dbesc(WIKI_ITEM_RESOURCE_TYPE),
+ dbesc($resource_id)
);
if (!$item) {
return array('wiki' => null, 'path' => null);
@@ -163,17 +183,21 @@ function wiki_get_wiki($resource_id) {
$rawName = get_iconfig($w, 'wiki', 'rawName');
$htmlName = get_iconfig($w, 'wiki', 'htmlName');
$urlName = get_iconfig($w, 'wiki', 'urlName');
+ $mimeType = get_iconfig($w, 'wiki', 'mimeType');
+
$path = get_iconfig($w, 'wiki', 'path');
if (!realpath(__DIR__ . '/../' . $path)) {
return array('wiki' => null, 'path' => null);
}
// Path to wiki exists
$abs_path = realpath(__DIR__ . '/../' . $path);
- return array( 'wiki' => $w,
- 'path' => $abs_path,
- 'rawName' => $rawName,
- 'htmlName' => $htmlName,
- 'urlName' => $urlName
+ return array(
+ 'wiki' => $w,
+ 'path' => $abs_path,
+ 'rawName' => $rawName,
+ 'htmlName' => $htmlName,
+ 'urlName' => $urlName,
+ 'mimeType' => $mimeType
);
}
}
@@ -220,7 +244,8 @@ function wiki_create_page($name, $resource_id) {
if (!$w['path']) {
return array('page' => null, 'wiki' => null, 'message' => 'Wiki not found.', 'success' => false);
}
- $page = array('rawName' => $name, 'htmlName' => escape_tags($name), 'urlName' => urlencode(escape_tags($name)), 'fileName' => urlencode(escape_tags($name)).'.md');
+
+ $page = array('rawName' => $name, 'htmlName' => escape_tags($name), 'urlName' => urlencode(escape_tags($name)), 'fileName' => urlencode(escape_tags($name)) . wiki_get_file_ext($w));
$page_path = $w['path'] . '/' . $page['fileName'];
if (is_file($page_path)) {
return array('page' => null, 'wiki' => null, 'message' => 'Page already exists.', 'success' => false);
@@ -242,11 +267,11 @@ function wiki_rename_page($arr) {
if (!$w['path']) {
return array('message' => 'Wiki not found.', 'success' => false);
}
- $page_path_old = $w['path'].'/'.$pageUrlName.'.md';
+ $page_path_old = $w['path'] . '/' . $pageUrlName . wiki_get_file_ext($w);
if (!is_readable($page_path_old) === true) {
return array('message' => 'Cannot read wiki page: ' . $page_path_old, 'success' => false);
}
- $page = array('rawName' => $pageNewName, 'htmlName' => escape_tags($pageNewName), 'urlName' => urlencode(escape_tags($pageNewName)), 'fileName' => urlencode(escape_tags($pageNewName)).'.md');
+ $page = array('rawName' => $pageNewName, 'htmlName' => escape_tags($pageNewName), 'urlName' => urlencode(escape_tags($pageNewName)), 'fileName' => urlencode(escape_tags($pageNewName)) . wiki_get_file_ext($w));
$page_path_new = $w['path'] . '/' . $page['fileName'] ;
if (is_file($page_path_new)) {
return array('message' => 'Page already exists.', 'success' => false);
@@ -267,7 +292,7 @@ function wiki_get_page_content($arr) {
if (!$w['path']) {
return array('content' => null, 'message' => 'Error reading wiki', 'success' => false);
}
- $page_path = $w['path'].'/'.$pageUrlName.'.md';
+ $page_path = $w['path'] . '/' . $pageUrlName . wiki_get_file_ext($w);
if (is_readable($page_path) === true) {
if(filesize($page_path) === 0) {
$content = '';
@@ -278,7 +303,7 @@ function wiki_get_page_content($arr) {
}
}
// TODO: Check that the files are all text files
- return array('content' => json_encode($content), 'message' => '', 'success' => true);
+ return array('content' => json_encode($content), 'mimeType' => $w['mimeType'], 'message' => '', 'success' => true);
}
}
@@ -289,7 +314,7 @@ function wiki_page_history($arr) {
if (!$w['path']) {
return array('history' => null, 'message' => 'Error reading wiki', 'success' => false);
}
- $page_path = $w['path'].'/'.$pageUrlName.'.md';
+ $page_path = $w['path'] . '/' . $pageUrlName . wiki_get_file_ext($w);
if (!is_readable($page_path) === true) {
return array('history' => null, 'message' => 'Cannot read wiki page: ' . $page_path, 'success' => false);
}
@@ -314,12 +339,14 @@ function wiki_save_page($arr) {
if (!$w['path']) {
return array('message' => 'Error reading wiki', 'success' => false);
}
- $page_path = $w['path'].'/'.$pageUrlName.'.md';
+
+ $fileName = $pageUrlName . wiki_get_file_ext($w);
+ $page_path = $w['path'] . '/' . $fileName;
if (is_writable($page_path) === true) {
if(!file_put_contents($page_path, $content)) {
return array('message' => 'Error writing to page file', 'success' => false);
}
- return array('message' => '', 'success' => true);
+ return array('message' => '', 'filename' => $filename, 'success' => true);
} else {
return array('message' => 'Page file not writable', 'success' => false);
}
@@ -332,7 +359,7 @@ function wiki_delete_page($arr) {
if (!$w['path']) {
return array('message' => 'Error reading wiki', 'success' => false);
}
- $page_path = $w['path'].'/'.$pageUrlName.'.md';
+ $page_path = $w['path'] . '/' . $pageUrlName . wiki_get_file_ext($w);
if (is_writable($page_path) === true) {
if(!unlink($page_path)) {
return array('message' => 'Error deleting page file', 'success' => false);
@@ -354,7 +381,7 @@ function wiki_revert_page($arr) {
if (!$w['path']) {
return array('content' => $content, 'message' => 'Error reading wiki', 'success' => false);
}
- $page_path = $w['path'].'/'.$pageUrlName.'.md';
+ $page_path = $w['path'] . '/' . $pageUrlName . wiki_get_file_ext($w);
if (is_writable($page_path) === true) {
$reponame = ((array_key_exists('title', $w['wiki'])) ? urlencode($w['wiki']['title']) : 'repo');
@@ -366,7 +393,7 @@ function wiki_revert_page($arr) {
try {
$git->setIdentity($observer['xchan_name'], $observer['xchan_addr']);
foreach ($git->git->tree($commitHash) as $object) {
- if ($object['type'] == 'blob' && $object['file'] === $pageUrlName.'.md' ) {
+ if ($object['type'] == 'blob' && $object['file'] === $pageUrlName . wiki_get_file_ext($w)) {
$content = $git->git->cat->blob($object['hash']);
}
}
@@ -391,7 +418,7 @@ function wiki_compare_page($arr) {
if (!$w['path']) {
return array('message' => 'Error reading wiki', 'success' => false);
}
- $page_path = $w['path'].'/'.$pageUrlName.'.md';
+ $page_path = $w['path'] . '/' . $pageUrlName . wiki_get_file_ext($w);
if (is_readable($page_path) === true) {
$reponame = ((array_key_exists('title', $w['wiki'])) ? urlencode($w['wiki']['title']) : 'repo');
if($reponame === '') {
@@ -401,12 +428,12 @@ function wiki_compare_page($arr) {
$compareContent = $currentContent = '';
try {
foreach ($git->git->tree($currentCommit) as $object) {
- if ($object['type'] == 'blob' && $object['file'] === $pageUrlName.'.md' ) {
+ if ($object['type'] == 'blob' && $object['file'] === $pageUrlName . wiki_get_file_ext($w)) {
$currentContent = $git->git->cat->blob($object['hash']);
}
}
foreach ($git->git->tree($compareCommit) as $object) {
- if ($object['type'] == 'blob' && $object['file'] === $pageUrlName.'.md' ) {
+ if ($object['type'] == 'blob' && $object['file'] === $pageUrlName . wiki_get_file_ext($w)) {
$compareContent = $git->git->cat->blob($object['hash']);
}
}
@@ -469,15 +496,6 @@ function wiki_git_commit($arr) {
}
}
-function wiki_generate_page_filename($name) {
- $file = urlencode(escape_tags($name));
- if( $file === '') {
- return null;
- } else {
- return $file . '.md';
- }
-}
-
function wiki_convert_links($s, $wikiURL) {
if (strpos($s,'[[') !== false) {
@@ -505,7 +523,6 @@ function wiki_convert_links($s, $wikiURL) {
* @return string
*/
function wiki_generate_toc($s) {
-
if (strpos($s,'[toc]') !== false) {
//$toc_md = wiki_toc($s); // Generate Markdown-formatted list prior to HTML render
$toc_md = '<ul id="wiki-toc"></ul>'; // use the available jQuery plugin http://ndabas.github.io/toc/
@@ -547,6 +564,13 @@ function wiki_bbcode($s) {
return $s;
}
+function wiki_get_file_ext($arr) {
+ if($arr['mimeType'] == 'text/bbcode')
+ return '.bb';
+ else
+ return '.md';
+}
+
// This function is derived from
// http://stackoverflow.com/questions/32068537/generate-table-of-contents-from-markdown-in-php
function wiki_toc($content) {
diff --git a/include/zot.php b/include/zot.php
index 5c9fb4e82..c80081cc8 100644
--- a/include/zot.php
+++ b/include/zot.php
@@ -110,20 +110,21 @@ function zot_get_hublocs($hash) {
* @param string $extra
* @returns string json encoded zot packet
*/
-function zot_build_packet($channel, $type = 'notify', $recipients = null, $remote_key = null, $secret = null, $extra = null) {
+function zot_build_packet($channel, $type = 'notify', $recipients = null, $remote_key = null, $methods = '', $secret = null, $extra = null) {
- $data = array(
+ $data = [
'type' => $type,
- 'sender' => array(
+ 'sender' => [
'guid' => $channel['channel_guid'],
'guid_sig' => base64url_encode(rsa_sign($channel['channel_guid'],$channel['channel_prvkey'])),
'url' => z_root(),
'url_sig' => base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])),
'sitekey' => get_config('system','pubkey')
- ),
+ ],
'callback' => '/post',
- 'version' => ZOT_REVISION
- );
+ 'version' => ZOT_REVISION,
+ 'encryption' => crypto_methods()
+ ];
if ($recipients) {
for ($x = 0; $x < count($recipients); $x ++)
@@ -146,122 +147,67 @@ function zot_build_packet($channel, $type = 'notify', $recipients = null, $remot
// Hush-hush ultra top-secret mode
- if ($remote_key) {
- $data = crypto_encapsulate(json_encode($data),$remote_key);
+ if($remote_key) {
+ $algorithm = zot_best_algorithm($methods);
+ $data = crypto_encapsulate(json_encode($data),$remote_key, $algorithm);
}
return json_encode($data);
}
/**
- * @brief
- *
- * @see z_post_url()
- *
- * @param string $url
- * @param array $data
- * @return array see z_post_url() for returned data format
- */
-function zot_zot($url, $data) {
- return z_post_url($url, array('data' => $data));
-}
-
-/**
- * @brief Look up information about channel.
- *
- * @param string $webbie
- * does not have to be host qualified e.g. 'foo' is treated as 'foo\@thishub'
- * @param array $channel
- * (optional), if supplied permissions will be enumerated specifically for $channel
- * @param boolean $autofallback
- * fallback/failover to http if https connection cannot be established. Default is true.
- *
- * @return array see z_post_url() and \ref Zotlabs::Zot::Finger "\\Zotlabs\\Zot\\Finger"
+ * @brief choose best encryption function from those available on both sites
+ *
+ * @param string $methods
+ * comma separated list of encryption methods
+ * @return string first match from our site method preferences crypto_methods() array
+ * of a method which is common to both sites; or 'aes256cbc' if no matches are found.
*/
-function zot_finger($webbie, $channel = null, $autofallback = true) {
-
- if (strpos($webbie,'@') === false) {
- $address = $webbie;
- $host = App::get_hostname();
- } else {
- $address = substr($webbie,0,strpos($webbie,'@'));
- $host = substr($webbie,strpos($webbie,'@')+1);
- if(strpos($host,'/'))
- $host = substr($host,0,strpos($host,'/'));
- }
-
- $xchan_addr = $address . '@' . $host;
- if ((! $address) || (! $xchan_addr)) {
- logger('zot_finger: no address :' . $webbie);
- return array('success' => false);
- }
- logger('using xchan_addr: ' . $xchan_addr, LOGGER_DATA, LOG_DEBUG);
+function zot_best_algorithm($methods) {
- // potential issue here; the xchan_addr points to the primary hub.
- // The webbie we were called with may not, so it might not be found
- // unless we query for hubloc_addr instead of xchan_addr
+ if(\Zotlabs\Lib\System::get_server_role() !== 'pro')
+ return 'aes256cbc';
- $r = q("select xchan.*, hubloc.* from xchan
- left join hubloc on xchan_hash = hubloc_hash
- where xchan_addr = '%s' and hubloc_primary = 1 limit 1",
- dbesc($xchan_addr)
- );
-
- if ($r) {
- $url = $r[0]['hubloc_url'];
-
- if ($r[0]['hubloc_network'] && $r[0]['hubloc_network'] !== 'zot') {
- logger('zot_finger: alternate network: ' . $webbie);
- logger('url: '.$url.', net: '.var_export($r[0]['hubloc_network'],true), LOGGER_DATA, LOG_DEBUG);
- return array('success' => false);
+ if($methods) {
+ $x = explode(',',$methods);
+ if($x) {
+ $y = crypto_methods();
+ if($y) {
+ foreach($y as $yv) {
+ $yv = trim($yv);
+ if(in_array($yv,$x)) {
+ return($yv);
+ }
+ }
+ }
}
- } else {
- $url = 'https://' . $host;
}
- $rhs = '/.well-known/zot-info';
- $https = ((strpos($url,'https://') === 0) ? true : false);
-
- logger('zot_finger: ' . $address . ' at ' . $url, LOGGER_DEBUG);
-
- if ($channel) {
- $postvars = array(
- 'address' => $address,
- 'target' => $channel['channel_guid'],
- 'target_sig' => $channel['channel_guid_sig'],
- 'key' => $channel['channel_pubkey']
- );
-
- $result = z_post_url($url . $rhs,$postvars);
-
- if ((! $result['success']) && ($autofallback)) {
- if ($https) {
- logger('zot_finger: https failed. falling back to http');
- $result = z_post_url('http://' . $host . $rhs,$postvars);
- }
- }
- } else {
- $rhs .= '?f=&address=' . urlencode($address);
+ return 'aes256cbc';
+}
- $result = z_fetch_url($url . $rhs);
- if ((! $result['success']) && ($autofallback)) {
- if ($https) {
- logger('zot_finger: https failed. falling back to http');
- $result = z_fetch_url('http://' . $host . $rhs);
- }
- }
- }
- if (! $result['success'])
- logger('zot_finger: no results');
- return $result;
+/**
+ * @brief
+ *
+ * @see z_post_url()
+ *
+ * @param string $url
+ * @param array $data
+ * @return array see z_post_url() for returned data format
+ */
+function zot_zot($url, $data) {
+ return z_post_url($url, array('data' => $data));
}
/**
* @brief Refreshes after permission changed or friending, etc.
*
+ * The top half of this function is similar to \Zotlabs\Zot\Finger::run() and could potentially be
+ * consolidated.
+ *
* zot_refresh is typically invoked when somebody has changed permissions of a channel and they are notified
* to fetch new permissions via a finger/discovery operation. This may result in a new connection
* (abook entry) being added to a local channel and it may result in auto-permissions being granted.
@@ -283,6 +229,7 @@ function zot_finger($webbie, $channel = null, $autofallback = true) {
*
* @returns boolean true if successful, else false
*/
+
function zot_refresh($them, $channel = null, $force = false) {
if (array_key_exists('xchan_network', $them) && ($them['xchan_network'] !== 'zot')) {
@@ -298,7 +245,8 @@ function zot_refresh($them, $channel = null, $force = false) {
if ($them['hubloc_url']) {
$url = $them['hubloc_url'];
- } else {
+ }
+ else {
$r = null;
// if they re-installed the server we could end up with the wrong record - pointing to the old install.
@@ -334,7 +282,7 @@ function zot_refresh($them, $channel = null, $force = false) {
$token = random_string();
- $postvars = array();
+ $postvars = [];
$postvars['token'] = $token;
@@ -395,10 +343,13 @@ function zot_refresh($them, $channel = null, $force = false) {
if($channel) {
if($j['permissions']['data']) {
- $permissions = crypto_unencapsulate(array(
+ $permissions = crypto_unencapsulate(
+ [
'data' => $j['permissions']['data'],
'key' => $j['permissions']['key'],
- 'iv' => $j['permissions']['iv']),
+ 'iv' => $j['permissions']['iv'],
+ 'alg' => $j['permissions']['alg']
+ ],
$channel['channel_prvkey']);
if($permissions)
$permissions = json_decode($permissions,true);
@@ -424,6 +375,10 @@ function zot_refresh($them, $channel = null, $force = false) {
$next_birthday = NULL_DATE;
}
+
+ // Keep original perms to check if we need to notify them
+ $previous_perms = get_all_perms($channel['channel_id'],$x['hash']);
+
$r = q("select * from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1",
dbesc($x['hash']),
intval($channel['channel_id'])
@@ -487,10 +442,6 @@ function zot_refresh($them, $channel = null, $force = false) {
}
}
- // Keep original perms to check if we need to notify them
- $previous_perms = get_all_perms($channel['channel_id'],$x['hash']);
-
-
$closeness = get_pconfig($channel['channel_id'],'system','new_abook_closeness');
if($closeness === false)
$closeness = 80;
@@ -520,12 +471,14 @@ function zot_refresh($them, $channel = null, $force = false) {
if($new_connection) {
if(! \Zotlabs\Access\Permissions::PermsCompare($new_perms,$previous_perms))
Zotlabs\Daemon\Master::Summon(array('Notifier','permission_create',$new_connection[0]['abook_id']));
- Zotlabs\Lib\Enotify::submit(array(
+ Zotlabs\Lib\Enotify::submit(
+ [
'type' => NOTIFY_INTRO,
'from_xchan' => $x['hash'],
'to_xchan' => $channel['channel_hash'],
- 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id'],
- ));
+ 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id']
+ ]
+ );
if(intval($permissions['view_stream'])) {
if(intval(get_pconfig($channel['channel_id'],'perm_limits','send_stream') & PERMS_PENDING)
@@ -535,6 +488,7 @@ function zot_refresh($them, $channel = null, $force = false) {
/** If there is a default group for this channel, add this connection to it */
+
$default_group = $channel['channel_default_group'];
if($default_group) {
require_once('include/group.php');
@@ -580,6 +534,7 @@ function zot_refresh($them, $channel = null, $force = false) {
* @returns array|null null if site is blacklisted or not found, otherwise an
* array with an hubloc record
*/
+
function zot_gethub($arr, $multiple = false) {
if($arr['guid'] && $arr['guid_sig'] && $arr['url'] && $arr['url_sig']) {
@@ -592,7 +547,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']) . "' " : '');
- $r = q("select * from hubloc
+ $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'
and hubloc_url = '%s' and hubloc_url_sig = '%s'
$sitekey $limit",
@@ -629,9 +584,10 @@ function zot_gethub($arr, $multiple = false) {
* * \b success boolean true or false
* * \b message (optional) error string only if success is false
*/
+
function zot_register_hub($arr) {
- $result = array('success' => false);
+ $result = [ 'success' => false ];
if($arr['url'] && $arr['url_sig'] && $arr['guid'] && $arr['guid_sig']) {
@@ -690,6 +646,7 @@ function zot_register_hub($arr) {
* * \e boolean \b success boolean true or false
* * \e string \b message (optional) error string only if success is false
*/
+
function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
call_hooks('import_xchan', $arr);
@@ -788,7 +745,8 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
$what .= 'xchan ';
$changed = true;
}
- } else {
+ }
+ else {
$import_photos = true;
if((($arr['site']['directory_mode'] === 'standalone')
@@ -824,7 +782,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
$changed = true;
}
- if ($import_photos) {
+ if($import_photos) {
require_once('include/photo/photo_driver.php');
@@ -833,9 +791,9 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
$local = q("select channel_account_id, channel_id from channel where channel_hash = '%s' limit 1",
dbesc($xchan_hash)
);
- if ($local) {
+ if($local) {
$ph = z_fetch_url($arr['photo'], true);
- if ($ph['success']) {
+ if($ph['success']) {
$hash = import_channel_photo($ph['body'], $arr['photo_mimetype'], $local[0]['channel_account_id'], $local[0]['channel_id']);
@@ -873,11 +831,12 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
false
);
}
- } else {
+ }
+ else {
$photos = import_xchan_photo($arr['photo'], $xchan_hash);
}
- if ($photos) {
- if ($photos[4]) {
+ if($photos) {
+ if($photos[4]) {
// importing the photo failed somehow. Leave the photo_date alone so we can try again at a later date.
// This often happens when somebody joins the matrix with a bad cert.
$r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
@@ -888,7 +847,8 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
dbesc($photos[3]),
dbesc($xchan_hash)
);
- } else {
+ }
+ else {
$r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
where xchan_hash = '%s'",
dbescdate(datetime_convert('UTC','UTC',$arr['photo_updated'])),
@@ -945,7 +905,8 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
$what .= 'profile ';
$changed = true;
}
- } else {
+ }
+ else {
logger('import_xchan: profile not available - hiding');
// they may have made it private
$r = q("delete from xprof where xprof_hash = '%s'",
@@ -998,16 +959,17 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
* @param array $arr - output of z_post_url()
* @param array $outq - The queue structure attached to this request
*/
+
function zot_process_response($hub, $arr, $outq) {
- if (! $arr['success']) {
+ if(! $arr['success']) {
logger('zot_process_response: failed: ' . $hub);
return;
}
$x = json_decode($arr['body'], true);
- if (! $x) {
+ if(! $x) {
logger('zot_process_response: No json from ' . $hub);
logger('zot_process_response: headers: ' . print_r($arr['header'],true), LOGGER_DATA, LOG_DEBUG);
}
@@ -1065,6 +1027,7 @@ function zot_process_response($hub, $arr, $outq) {
* decrypted and json decoded notify packet from remote site
* @return array from zot_import()
*/
+
function zot_fetch($arr) {
logger('zot_fetch: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG);
@@ -1082,16 +1045,18 @@ function zot_fetch($arr) {
}
foreach($ret_hubs as $ret_hub) {
- $data = array(
- 'type' => 'pickup',
- 'url' => z_root(),
- 'callback_sig' => base64url_encode(rsa_sign(z_root() . '/post',get_config('system','prvkey'))),
- 'callback' => z_root() . '/post',
- 'secret' => $arr['secret'],
- 'secret_sig' => base64url_encode(rsa_sign($arr['secret'],get_config('system','prvkey')))
- );
- $datatosend = json_encode(crypto_encapsulate(json_encode($data),$ret_hub['hubloc_sitekey']));
+ $data = [
+ 'type' => 'pickup',
+ 'url' => z_root(),
+ 'callback_sig' => base64url_encode(rsa_sign(z_root() . '/post', get_config('system','prvkey'))),
+ 'callback' => z_root() . '/post',
+ 'secret' => $arr['secret'],
+ 'secret_sig' => base64url_encode(rsa_sign($arr['secret'], get_config('system','prvkey')))
+ ];
+
+ $algorithm = zot_best_algorithm($ret_hub['site_crypto']);
+ $datatosend = json_encode(crypto_encapsulate(json_encode($data),$ret_hub['hubloc_sitekey'], $algorithm));
$fetch = zot_zot($url,$datatosend);
@@ -1142,6 +1107,11 @@ function zot_import($arr, $sender_url) {
$data = json_decode(crypto_unencapsulate($data,get_config('system','prvkey')),true);
}
+ if(! is_array($data)) {
+ logger('decode error');
+ return array();
+ }
+
if(! $data['success']) {
if($data['message'])
logger('remote pickup failed: ' . $data['message']);
@@ -1167,6 +1137,12 @@ function zot_import($arr, $sender_url) {
logger('zot_import: notify: ' . print_r($i['notify'],true), LOGGER_DATA, LOG_DEBUG);
+ if(! is_array($i['notify'])) {
+ logger('decode error');
+ continue;
+ }
+
+
$hub = zot_gethub($i['notify']['sender']);
if((! $hub) || ($hub['hubloc_url'] != $sender_url)) {
logger('zot_import: potential forgery: wrong site for sender: ' . $sender_url . ' != ' . print_r($i['notify'],true));
@@ -1357,6 +1333,7 @@ function zot_import($arr, $sender_url) {
* @param array $msg
* @return NULL|array
*/
+
function public_recips($msg) {
require_once('include/channel.php');
@@ -1566,6 +1543,7 @@ function allowed_public_recips($msg) {
* @param boolean $request (optional) default false
* @return array
*/
+
function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $request = false) {
$result = array();
@@ -1875,6 +1853,7 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $
* * \e int \b mid
* @param int $uid
*/
+
function remove_community_tag($sender, $arr, $uid) {
if(! (activity_match($arr['verb'], ACTIVITY_TAG) && ($arr['obj_type'] == ACTIVITY_OBJ_TAGTERM)))
@@ -1945,6 +1924,7 @@ function remove_community_tag($sender, $arr, $uid) {
* @param array $orig
* @param int $uid
*/
+
function update_imported_item($sender, $item, $orig, $uid) {
// If this is a comment being updated, remove any privacy information
@@ -1985,6 +1965,7 @@ function update_imported_item($sender, $item, $orig, $uid) {
* @param boolean $relay
* @return boolean|int post_id
*/
+
function delete_imported_item($sender, $item, $uid, $relay) {
logger('delete_imported_item invoked', LOGGER_DEBUG);
@@ -2002,13 +1983,14 @@ function delete_imported_item($sender, $item, $uid, $relay) {
intval($uid)
);
- if ($r) {
- if ($r[0]['author_xchan'] === $sender['hash'] || $r[0]['owner_xchan'] === $sender['hash'] || $r[0]['source_xchan'] === $sender['hash'])
+ if($r) {
+ if($r[0]['author_xchan'] === $sender['hash'] || $r[0]['owner_xchan'] === $sender['hash'] || $r[0]['source_xchan'] === $sender['hash'])
$ownership_valid = true;
$post_id = $r[0]['id'];
$item_found = true;
- } else {
+ }
+ else {
// perhaps the item is still in transit and the delete notification got here before the actual item did. Store it with the deleted flag set.
// item_store() won't try to deliver any notifications or start delivery chains if this flag is set.
@@ -2017,25 +1999,24 @@ function delete_imported_item($sender, $item, $uid, $relay) {
logger('delete received for non-existent item - storing item data.');
- /** @BUG $arr is undefined here, so this is dead code */
- if ($arr['author_xchan'] === $sender['hash'] || $arr['owner_xchan'] === $sender['hash'] || $arr['source_xchan'] === $sender['hash']) {
+ if($item['author_xchan'] === $sender['hash'] || $item['owner_xchan'] === $sender['hash'] || $item['source_xchan'] === $sender['hash']) {
$ownership_valid = true;
- $item_result = item_store($arr);
+ $item_result = item_store($item);
$post_id = $item_result['item_id'];
}
}
- if ($ownership_valid === false) {
+ if($ownership_valid === false) {
logger('delete_imported_item: failed: ownership issue');
return false;
}
require_once('include/items.php');
- if ($item_found) {
- if (intval($r[0]['item_deleted'])) {
+ if($item_found) {
+ if(intval($r[0]['item_deleted'])) {
logger('delete_imported_item: item was already deleted');
- if (! $relay)
+ if(! $relay)
return false;
// This is a bit hackish, but may have to suffice until the notification/delivery loop is optimised
@@ -2146,6 +2127,7 @@ function process_mail_delivery($sender, $arr, $deliveries) {
* * \e string \b hash a xchan_hash
* @param array $arr
*/
+
function process_rating_delivery($sender, $arr) {
logger('process_rating_delivery: ' . print_r($arr,true));
@@ -2205,6 +2187,7 @@ function process_rating_delivery($sender, $arr) {
* @param array $arr
* @param array $deliveries (unused)
*/
+
function process_profile_delivery($sender, $arr, $deliveries) {
logger('process_profile_delivery', LOGGER_DEBUG);
@@ -2301,6 +2284,7 @@ function check_location_move($sender_hash,$locations) {
* @param boolean $absolute (optional) default false
* @return array
*/
+
function sync_locations($sender, $arr, $absolute = false) {
$ret = array();
@@ -2548,7 +2532,7 @@ function zot_encode_locations($channel) {
if(intval($channel['channel_removed']) && $hub['hubloc_url'] === z_root())
$hub['hubloc_deleted'] = 1;
- $ret[] = array(
+ $ret[] = [
'host' => $hub['hubloc_host'],
'address' => $hub['hubloc_addr'],
'primary' => (intval($hub['hubloc_primary']) ? true : false),
@@ -2557,7 +2541,7 @@ function zot_encode_locations($channel) {
'callback' => $hub['hubloc_callback'],
'sitekey' => $hub['hubloc_sitekey'],
'deleted' => (intval($hub['hubloc_deleted']) ? true : false)
- );
+ ];
}
}
@@ -2574,6 +2558,7 @@ function zot_encode_locations($channel) {
* @param number $suppress_update default 0
* @return boolean $updated if something changed
*/
+
function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLAGS_UPDATED, $suppress_update = 0) {
logger('import_directory_profile', LOGGER_DEBUG);
@@ -2708,6 +2693,7 @@ function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLA
* @param string $hash
* @param array $keywords
*/
+
function import_directory_keywords($hash, $keywords) {
$existing = array();
@@ -2752,6 +2738,7 @@ function import_directory_keywords($hash, $keywords) {
* @param string $addr
* @param int $flags (optional) default 0
*/
+
function update_modtime($hash, $guid, $addr, $flags = 0) {
$dirmode = intval(get_config('system', 'directory_mode'));
@@ -2784,6 +2771,7 @@ function update_modtime($hash, $guid, $addr, $flags = 0) {
* @param string $pubkey
* @return boolean true if updated or inserted
*/
+
function import_site($arr, $pubkey) {
if( (! is_array($arr)) || (! $arr['url']) || (! $arr['url_sig']))
return false;
@@ -2851,6 +2839,7 @@ function import_site($arr, $pubkey) {
$site_location = htmlspecialchars($arr['location'],ENT_COMPAT,'UTF-8',false);
$site_realm = htmlspecialchars($arr['realm'],ENT_COMPAT,'UTF-8',false);
$site_project = htmlspecialchars($arr['project'],ENT_COMPAT,'UTF-8',false);
+ $site_crypto = ((array_key_exists('encryption',$arr) && is_array($arr['encryption'])) ? htmlspecialchars(implode(',',$arr['encryption']),ENT_COMPAT,'UTF-8',false) : '');
$site_version = ((array_key_exists('version',$arr)) ? htmlspecialchars($arr['version'],ENT_COMPAT,'UTF-8',false) : '');
// You can have one and only one primary directory per realm.
@@ -2872,6 +2861,7 @@ function import_site($arr, $pubkey) {
|| ($siterecord['site_register'] != $register_policy)
|| ($siterecord['site_project'] != $site_project)
|| ($siterecord['site_realm'] != $site_realm)
+ || ($siterecord['site_crypto'] != $site_crypto)
|| ($siterecord['site_version'] != $site_version) ) {
$update = true;
@@ -2880,7 +2870,7 @@ function import_site($arr, $pubkey) {
// logger('import_site: stored: ' . print_r($siterecord,true));
- $r = q("update site set site_dead = 0, site_location = '%s', site_flags = %d, site_access = %d, site_directory = '%s', site_register = %d, site_update = '%s', site_sellpage = '%s', site_realm = '%s', site_type = %d, site_project = '%s', site_version = '%s'
+ $r = q("update site set site_dead = 0, site_location = '%s', site_flags = %d, site_access = %d, site_directory = '%s', site_register = %d, site_update = '%s', site_sellpage = '%s', site_realm = '%s', site_type = %d, site_project = '%s', site_version = '%s', site_crypto = '%s'
where site_url = '%s'",
dbesc($site_location),
intval($site_directory),
@@ -2893,6 +2883,7 @@ function import_site($arr, $pubkey) {
intval(SITE_TYPE_ZOT),
dbesc($site_project),
dbesc($site_version),
+ dbesc($site_crypto),
dbesc($url)
);
if(! $r) {
@@ -2910,8 +2901,8 @@ function import_site($arr, $pubkey) {
else {
$update = true;
- $r = q("insert into site ( site_location, site_url, site_access, site_flags, site_update, site_directory, site_register, site_sellpage, site_realm, site_type, site_project, site_version )
- values ( '%s', '%s', %d, %d, '%s', '%s', %d, '%s', '%s', %d, '%s', '%s' )",
+ $r = q("insert into site ( site_location, site_url, site_access, site_flags, site_update, site_directory, site_register, site_sellpage, site_realm, site_type, site_project, site_version, site_crypto )
+ values ( '%s', '%s', %d, %d, '%s', '%s', %d, '%s', '%s', %d, '%s', '%s', '%s' )",
dbesc($site_location),
dbesc($url),
intval($access_policy),
@@ -2923,7 +2914,8 @@ function import_site($arr, $pubkey) {
dbesc($site_realm),
intval(SITE_TYPE_ZOT),
dbesc($site_project),
- dbesc($site_version)
+ dbesc($site_version),
+ dbesc($site_crypto)
);
if(! $r) {
logger('import_site: record create failed. ' . print_r($arr,true));
@@ -2942,6 +2934,7 @@ function import_site($arr, $pubkey) {
* @param array $packet (optional) default null
* @param boolean $groups_changed (optional) default false
*/
+
function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
if(get_config('system','server_role') === 'basic')
@@ -2977,7 +2970,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
if(intval($channel['channel_removed']))
return;
- $h = q("select * from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0",
+ $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'])
);
@@ -3064,7 +3057,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
foreach($synchubs as $hub) {
$hash = random_string();
- $n = zot_build_packet($channel,'notify',$env_recips,$hub['hubloc_sitekey'],$hash);
+ $n = zot_build_packet($channel,'notify',$env_recips,$hub['hubloc_sitekey'],$hub['site_crypto'],$hash);
queue_insert(array(
'hash' => $hash,
'account_id' => $channel['channel_account_id'],
@@ -3090,6 +3083,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
* @param array $deliveries
* @return array
*/
+
function process_channel_sync_delivery($sender, $arr, $deliveries) {
if(get_config('system','server_role') === 'basic')
@@ -3564,6 +3558,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
* * \e string \b xchan_url
* @return string
*/
+
function get_rpost_path($observer) {
if(! $observer)
return '';
@@ -3579,6 +3574,7 @@ function get_rpost_path($observer) {
* @param array $x
* @return boolean|string return false or a hash
*/
+
function import_author_zot($x) {
$hash = make_xchan_hash($x['guid'],$x['guid_sig']);
@@ -3618,6 +3614,7 @@ function import_author_zot($x) {
* @param array $data
* @return array
*/
+
function zot_reply_message_request($data) {
$ret = array('success' => false);
@@ -3654,7 +3651,7 @@ function zot_reply_message_request($data) {
if ($messages) {
$env_recips = null;
- $r = q("select * from hubloc where hubloc_hash = '%s' and hubloc_error = 0 and hubloc_deleted = 0",
+ $r = q("select hubloc.*, site.site_crypto from hubloc left join site on hubloc_url = site_url where hubloc_hash = '%s' and hubloc_error = 0 and hubloc_deleted = 0",
dbesc($sender_hash)
);
if (! $r) {
@@ -3676,7 +3673,7 @@ function zot_reply_message_request($data) {
* create a notify packet and drop the actual message packet in the queue for pickup
*/
- $n = zot_build_packet($c[0],'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null),$hash,array('message_id' => $data['message_id']));
+ $n = zot_build_packet($c[0],'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null),$hub['site_crypto'],$hash,array('message_id' => $data['message_id']));
queue_insert(array(
'hash' => $hash,
@@ -3913,6 +3910,11 @@ function zotinfo($arr) {
$permissions['connected'] = true;
}
+ // encrypt this with the default aes256cbc since we cannot be sure at this point which
+ // algorithms are preferred for communications with the remote site; notably
+ // because ztarget refers to an xchan and we don't necessarily know the origination
+ // location.
+
$ret['permissions'] = (($ztarget && $zkey) ? crypto_encapsulate(json_encode($permissions),$zkey) : $permissions);
if($permissions['view_profile'])
@@ -3943,6 +3945,8 @@ function zotinfo($arr) {
$ret['site']['directory_url'] = z_root() . '/dirsearch';
+ $ret['site']['encryption'] = crypto_methods();
+
// hide detailed site information if you're off the grid
if($dirmode != DIRECTORY_MODE_STANDALONE) {
@@ -3980,17 +3984,17 @@ function zotinfo($arr) {
$r = q("select * from addon where hidden = 0");
if($r)
foreach($r as $rr)
- $visible_plugins[] = $rr['name'];
+ $visible_plugins[] = $rr['aname'];
}
- $ret['site']['plugins'] = $visible_plugins;
- $ret['site']['sitehash'] = get_config('system','location_hash');
- $ret['site']['sitename'] = get_config('system','sitename');
- $ret['site']['sellpage'] = get_config('system','sellpage');
- $ret['site']['location'] = get_config('system','site_location');
- $ret['site']['realm'] = get_directory_realm();
- $ret['site']['project'] = Zotlabs\Lib\System::get_platform_name() . ' ' . Zotlabs\Lib\System::get_server_role();
- $ret['site']['version'] = Zotlabs\Lib\System::get_project_version();
+ $ret['site']['plugins'] = $visible_plugins;
+ $ret['site']['sitehash'] = get_config('system','location_hash');
+ $ret['site']['sitename'] = get_config('system','sitename');
+ $ret['site']['sellpage'] = get_config('system','sellpage');
+ $ret['site']['location'] = get_config('system','site_location');
+ $ret['site']['realm'] = get_directory_realm();
+ $ret['site']['project'] = Zotlabs\Lib\System::get_platform_name() . ' ' . Zotlabs\Lib\System::get_server_role();
+ $ret['site']['version'] = Zotlabs\Lib\System::get_project_version();
}
@@ -4175,7 +4179,7 @@ function update_hub_connected($hub,$sitekey = '') {
dbesc($sitekey)
);
if(intval($hub['hubloc_orphancheck'])) {
- q("update hubloc set hubloc_orhpancheck = 0 where hubloc_id = %d and hubloc_sitekey = '%s' ",
+ q("update hubloc set hubloc_orphancheck = 0 where hubloc_id = %d and hubloc_sitekey = '%s' ",
intval($hub['hubloc_id']),
dbesc($sitekey)
);
@@ -4317,7 +4321,15 @@ function zot_reply_pickup($data) {
}
}
- $encrypted = crypto_encapsulate(json_encode($ret),$sitekey);
+ // this is a bit of a hack because we don't have the hubloc_url here, only the callback url.
+ // worst case is we'll end up using aes256cbc if they've got a different post endpoint
+
+ $x = q("select site_crypto from site where site_url = '%s' limit 1",
+ dbesc(str_replace('/post','',$data['callback']))
+ );
+ $algorithm = zot_best_algorithm(($x) ? $x[0]['site_crypto'] : '');
+
+ $encrypted = crypto_encapsulate(json_encode($ret),$sitekey,$algorithm);
json_return_and_die($encrypted);
/* pickup: end */