Merge branch 'master' of ../z

This commit is contained in:
zotlabs 2019-10-04 16:31:41 -07:00
commit d7a0456bdc
2100 changed files with 222428 additions and 290655 deletions

View file

View file

@ -1,11 +1,34 @@
ZAP ZAP
=== ===
Zap is a decentralised social network server application with a number of powerful features, yet very easy to use. Zap is an open source decentralised social network with more privacy and less drama.
=====
Installation The Zot Manifesto
============
You have the right to a permanent internet identity which is not associated with what server you are currently using and cannot be taken away from you by anybody, ever.
You have the right to refuse/reject or possibly moderate comments on your posts by anybody you don't know.
You also have the right to not allow them to comment on your posts in the first place, until such time as they have earned your trust.
You have the right to show your photos and videos to anybody you desire and also NOT show them to anybody you desire.
If your software does not implement these rights, you have the right to fix it or replace it.
=====
The Earth Manifesto
The earth is your mother. She gave you life. Respect her or she will take it away.
Silence is complicity. Speak.
Those who are leading us to destruction can be stopped.
7.5 billion people cannot be stopped.
=====
Read `install/INSTALL.txt` for installation instructions.

View file

@ -17,7 +17,7 @@ class PermissionRoles {
* @return number * @return number
*/ */
static public function version() { static public function version() {
return 2; return 3;
} }
static function role_perms($role) { static function role_perms($role) {
@ -34,7 +34,7 @@ class PermissionRoles {
$ret['online'] = true; $ret['online'] = true;
$ret['perms_connect'] = [ $ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'send_stream', 'post_wall', 'post_comments' 'view_pages', 'send_stream', 'post_wall', 'post_comments', 'post_like'
]; ];
$ret['limits'] = PermissionLimits::Std_Limits(); $ret['limits'] = PermissionLimits::Std_Limits();
break; break;
@ -43,13 +43,13 @@ class PermissionRoles {
$ret['perms_auto'] = false; $ret['perms_auto'] = false;
$ret['default_collection'] = true; $ret['default_collection'] = true;
$ret['directory_publish'] = true; $ret['directory_publish'] = true;
$ret['online'] = true; $ret['online'] = false;
$ret['perms_connect'] = [ $ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_stream', 'view_profile', 'view_storage',
'view_pages', 'send_stream', 'post_wall', 'post_comments' 'view_pages', 'send_stream', 'post_wall', 'post_comments', 'post_like'
]; ];
$ret['limits'] = PermissionLimits::Std_Limits(); $ret['limits'] = PermissionLimits::Std_Limits();
$ret['limits']['view_contacts'] = PERMS_SPECIFIC;
break; break;
case 'forum': case 'forum':
@ -58,10 +58,11 @@ class PermissionRoles {
$ret['directory_publish'] = true; $ret['directory_publish'] = true;
$ret['online'] = false; $ret['online'] = false;
$ret['perms_connect'] = [ $ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'write_storage',
'view_pages', 'post_wall', 'post_comments' 'view_pages', 'post_wall', 'post_comments', 'post_like'
]; ];
$ret['limits'] = PermissionLimits::Std_Limits(); $ret['limits'] = PermissionLimits::Std_Limits();
$ret['channel_type'] = 'group';
break; break;
@ -73,9 +74,10 @@ class PermissionRoles {
$ret['online'] = false; $ret['online'] = false;
$ret['perms_connect'] = [ $ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'post_wall', 'post_comments', 'moderated' 'view_pages', 'post_wall', 'post_comments', 'post_like', 'moderated'
]; ];
$ret['limits'] = PermissionLimits::Std_Limits(); $ret['limits'] = PermissionLimits::Std_Limits();
$ret['channel_type'] = 'group';
break; break;
@ -85,10 +87,12 @@ class PermissionRoles {
$ret['directory_publish'] = true; $ret['directory_publish'] = true;
$ret['online'] = false; $ret['online'] = false;
$ret['perms_connect'] = [ $ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'write_storage',
'view_pages', 'post_wall', 'post_comments' 'view_pages', 'post_wall', 'post_comments', 'post_like'
]; ];
$ret['limits'] = PermissionLimits::Std_Limits(); $ret['limits'] = PermissionLimits::Std_Limits();
$ret['limits']['view_contacts'] = PERMS_SPECIFIC;
$ret['channel_type'] = 'group';
break; break;
case 'collection': case 'collection':
@ -98,9 +102,10 @@ class PermissionRoles {
$ret['online'] = false; $ret['online'] = false;
$ret['perms_connect'] = [ $ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'post_comments' 'view_pages', 'post_comments', 'post_like'
]; ];
$ret['limits'] = PermissionLimits::Std_Limits(); $ret['limits'] = PermissionLimits::Std_Limits();
$ret['channel_type'] = 'collection';
break; break;
@ -110,10 +115,12 @@ class PermissionRoles {
$ret['directory_publish'] = true; $ret['directory_publish'] = true;
$ret['online'] = false; $ret['online'] = false;
$ret['perms_connect'] = [ $ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_stream', 'view_profile', 'view_storage',
'view_pages', 'post_comments' 'view_pages', 'post_comments', 'post_like'
]; ];
$ret['limits'] = PermissionLimits::Std_Limits(); $ret['limits'] = PermissionLimits::Std_Limits();
$ret['limits']['view_contacts'] = PERMS_SPECIFIC;
$ret['channel_type'] = 'collection';
break; break;
case 'feed': case 'feed':
@ -130,6 +137,10 @@ class PermissionRoles {
break; break;
case 'repository':
//Legacy settings to cover all channel_types previously in Libzot.php
$ret['channel_type'] = 'group';
default: default:
break; break;
} }

View file

@ -41,7 +41,7 @@ class Permissions {
* @return number * @return number
*/ */
static public function version() { static public function version() {
return 2; return 3;
} }
/** /**
@ -53,18 +53,18 @@ class Permissions {
static public function Perms($filter = '') { static public function Perms($filter = '') {
$perms = [ $perms = [
'view_stream' => t('Can view my channel stream and posts'), 'view_stream' => t('Grant viewing access to and delivery of your channel stream and posts'),
'send_stream' => t('Can send me their channel stream and posts'), 'view_profile' => t('Grant viewing access to your default channel profile'),
'view_profile' => t('Can view my default channel profile'), 'view_contacts' => t('Grant viewing access to your address book (connections)'),
'view_contacts' => t('Can view my connections'), 'view_storage' => t('Grant viewing access to your file storage and photos'),
'view_storage' => t('Can view my file storage and photos'), 'post_wall' => t('Grant permission to post on your channel (wall) page'),
'write_storage' => t('Can upload/modify my file storage and photos'), 'send_stream' => t('Accept delivery of their posts and comments to their posts'),
'post_wall' => t('Can post on my channel (wall) page'), 'post_comments' => t('Accept delivery of their comments and likes on your posts'),
'post_comments' => t('Can comment on or like my posts'), 'post_like' => t('Accept delivery of their likes of your profile'),
'post_like' => t('Can like/dislike profiles and profile things'), 'write_storage' => t('Grant upload permissions to your file storage and photos'),
'republish' => t('Can source my public posts in derived channels'), 'republish' => t('Grant permission to republish/mirror your posts'),
'moderated' => t('Comments are moderated'), 'moderated' => t('Accept comments and wall posts only after approval (moderation)'),
'delegate' => t('Can administer my channel') 'delegate' => t('Grant channel administration (delegation) permission')
]; ];
$x = [ $x = [

View file

@ -193,7 +193,7 @@ class Cron {
$restart = true; $restart = true;
$generation = intval($argv[2]); $generation = intval($argv[2]);
if(! $generation) if(! $generation)
killme(); return;
} }
reload_plugins(); reload_plugins();

View file

@ -13,7 +13,7 @@ class CurlAuth {
static public function run($argc,$argv) { static public function run($argc,$argv) {
if($argc != 2) if($argc != 2)
killme(); return;
\App::$session->start(); \App::$session->start();
@ -50,6 +50,6 @@ class CurlAuth {
file_put_contents($c,$x); file_put_contents($c,$x);
killme(); return;
} }
} }

View file

@ -13,11 +13,11 @@ class Delxitems {
cli_startup(); cli_startup();
if($argc != 3) { if($argc != 3) {
killme(); return;
} }
remove_abook_items($argv[1],$argv[2]); remove_abook_items($argv[1],$argv[2]);
killme(); return;
} }
} }

View file

@ -27,11 +27,6 @@ class Expire {
db_utcnow(), db_quoteinterval('36 DAY') db_utcnow(), db_quoteinterval('36 DAY')
); );
/** @FIXME make this optional as it could have a performance impact on large sites */
if (intval(get_config('system', 'optimize_items')))
q("optimize table item");
logger('expire: start', LOGGER_DEBUG); logger('expire: start', LOGGER_DEBUG);
$site_expire = intval(get_config('system', 'default_expire_days')); $site_expire = intval(get_config('system', 'default_expire_days'));
@ -51,15 +46,18 @@ class Expire {
// service class default (if non-zero) over-rides the site default // service class default (if non-zero) over-rides the site default
$service_class_expire = service_class_fetch($rr['channel_id'], 'expire_days'); $service_class_expire = service_class_fetch($rr['channel_id'], 'expire_days');
if (intval($service_class_expire)) if (intval($service_class_expire)) {
$channel_expire = $service_class_expire; $channel_expire = $service_class_expire;
else }
else {
$channel_expire = $site_expire; $channel_expire = $site_expire;
}
if (intval($channel_expire) && (intval($channel_expire) < intval($rr['channel_expire_days'])) || if (intval($channel_expire) && (intval($channel_expire) < intval($rr['channel_expire_days'])) ||
intval($rr['channel_expire_days'] == 0)) { intval($rr['channel_expire_days'] == 0)) {
$expire_days = $channel_expire; $expire_days = $channel_expire;
} else { }
else {
$expire_days = $rr['channel_expire_days']; $expire_days = $rr['channel_expire_days'];
} }
@ -75,9 +73,7 @@ class Expire {
// this should probably just fetch the channel_expire_days from the sys channel, // this should probably just fetch the channel_expire_days from the sys channel,
// but there's no convenient way to set it. // but there's no convenient way to set it.
$expire_days = get_config('system', 'sys_expire_days'); $expire_days = get_config('system', 'sys_expire_days',30);
if ($expire_days === false)
$expire_days = 30;
if (intval($site_expire) && (intval($site_expire) < intval($expire_days))) { if (intval($site_expire) && (intval($site_expire) < intval($expire_days))) {
$expire_days = $site_expire; $expire_days = $site_expire;
@ -85,8 +81,9 @@ class Expire {
logger('Expire: sys interval: ' . $expire_days, LOGGER_DEBUG); logger('Expire: sys interval: ' . $expire_days, LOGGER_DEBUG);
if ($expire_days) if ($expire_days) {
item_expire($x['channel_id'], $expire_days, $commented_days); item_expire($x['channel_id'], $expire_days, $commented_days);
}
logger('Expire: sys: done', LOGGER_DEBUG); logger('Expire: sys: done', LOGGER_DEBUG);
} }

View file

@ -1,12 +1,9 @@
<?php /** @file */ <?php
namespace Zotlabs\Daemon; namespace Zotlabs\Daemon;
use Zotlabs\Lib\Libzot; use Zotlabs\Lib\Libzot;
require_once('include/channel.php');
class Externals { class Externals {
@ -15,13 +12,14 @@ class Externals {
$total = 0; $total = 0;
$attempts = 0; $attempts = 0;
$sys = get_sys_channel();
logger('externals: startup', LOGGER_DEBUG); logger('externals: startup', LOGGER_DEBUG);
// pull in some public posts // pull in some public posts
while ($total == 0 && $attempts < 3) { while ($total == 0 && $attempts < 3) {
$arr = array('url' => ''); $arr = [ 'url' => EMPTY_STR ];
call_hooks('externals_url_select',$arr); call_hooks('externals_url_select',$arr);
if ($arr['url']) { if ($arr['url']) {
@ -37,9 +35,10 @@ class Externals {
intval(DIRECTORY_MODE_STANDALONE), intval(DIRECTORY_MODE_STANDALONE),
intval(SITE_TYPE_ZOT) intval(SITE_TYPE_ZOT)
); );
if($r) if ($r) {
$url = $r[0]['site_url']; $url = $r[0]['site_url'];
} }
}
$blacklisted = false; $blacklisted = false;
@ -53,19 +52,19 @@ class Externals {
// make sure we can eventually break out if somebody blacklists all known sites // make sure we can eventually break out if somebody blacklists all known sites
if ($blacklisted) { if ($blacklisted) {
if($attempts > 20) if ($attempts > 20) {
break; break;
}
$attempts --; $attempts --;
continue; continue;
} }
if ($url) { if ($url) {
if($r[0]['site_pull'] > NULL_DATE) if ($r[0]['site_pull'] > NULL_DATE) {
$mindate = urlencode(datetime_convert('','',$r[0]['site_pull'] . ' - 1 day')); $mindate = urlencode(datetime_convert('','',$r[0]['site_pull'] . ' - 1 day'));
}
else { else {
$days = get_config('externals','since_days'); $days = get_config('externals','since_days',15);
if($days === false)
$days = 15;
$mindate = urlencode(datetime_convert('','','now - ' . intval($days) . ' days')); $mindate = urlencode(datetime_convert('','','now - ' . intval($days) . ' days'));
} }
@ -83,10 +82,9 @@ class Externals {
$j = json_decode($x['body'],true); $j = json_decode($x['body'],true);
if($j['success'] && $j['messages']) { if($j['success'] && $j['messages']) {
$sys = get_sys_channel();
foreach($j['messages'] as $message) { foreach($j['messages'] as $message) {
// on these posts, clear any route info. // on these posts, clear any route info.
$message['route'] = ''; $message['route'] = EMPTY_STR;
$results = Libzot::process_delivery('undefined', null, get_item_elements($message), [ $sys['xchan_hash'] ], false, true); $results = Libzot::process_delivery('undefined', null, get_item_elements($message), [ $sys['xchan_hash'] ], false, true);
$total ++; $total ++;
} }

View file

@ -10,7 +10,7 @@ if(array_search( __file__ , get_included_files()) === 0) {
if($argc) if($argc)
Master::Release($argc,$argv); Master::Release($argc,$argv);
killme(); return;
} }

View file

@ -89,53 +89,37 @@ class Notifier {
static public function run($argc,$argv) { static public function run($argc,$argv) {
if($argc < 3) if ($argc < 3) {
return; return;
}
logger('notifier: invoked: ' . print_r($argv,true), LOGGER_DEBUG); logger('notifier: invoked: ' . print_r($argv,true), LOGGER_DEBUG, LOG_INFO);
$cmd = $argv[1]; $cmd = $argv[1];
$item_id = $argv[2]; $item_id = $argv[2];
if(! $item_id) if (! $item_id) {
return; return;
}
self::$deliveries = [];
self::$recipients = [];
self::$env_recips = [];
self::$packet_type = 'activity';
self::$encoding = 'activitystreams';
self::$encoded_item = null;
self::$channel = null;
self::$private = false;
$sys = get_sys_channel(); $sys = get_sys_channel();
$mail = false;
$top_level = false; $top_level = false;
$url_recipients = array(); $url_recipients = array();
$normal_mode = true; $normal_mode = true;
if ($cmd === 'request') {
if($cmd === 'mail' || $cmd === 'single_mail') {
$normal_mode = false;
$mail = true;
self::$private = true;
$message = q("SELECT * FROM mail WHERE id = %d LIMIT 1",
intval($item_id)
);
if(! $message) {
return;
}
xchan_mail_query($message[0]);
self::$recipients[] = $message[0]['to_xchan'];
$item = $message[0];
self::$encoded_item = encode_mail($item);
$s = q("select * from channel where channel_id = %d limit 1",
intval($item['channel_id'])
);
if($s)
self::$channel = $s[0];
self::$packet_type = 'mail';
self::$encoding = 'zot';
}
elseif($cmd === 'request') {
$xchan = $argv[3]; $xchan = $argv[3];
if ($argc < 5) { if ($argc < 5) {
@ -176,19 +160,19 @@ class Notifier {
); );
if ($r) { if ($r) {
$uid = $r[0]['abook_channel']; $recip = array_shift($r);
$uid = $recip['abook_channel'];
// Get the sender // Get the sender
self::$channel = channelx_by_n($uid); self::$channel = channelx_by_n($uid);
if (self::$channel) { if (self::$channel) {
$perm_update = array('sender' => self::$channel, 'recipient' => $r[0], 'success' => false, 'deliveries' => ''); $perm_update = [ 'sender' => self::$channel, 'recipient' => $recip, 'success' => false, 'deliveries' => '' ];
switch ($cmd) { switch ($cmd) {
case 'permissions_create': case 'permissions_create':
ActivityPub::permissions_create($perm_update); ActivityPub::permissions_create($perm_update);
break; break;
case 'permissions_accept': case 'permissions_accept':
ActivityPub::permissions_accept($perm_update); ActivityPub::permissions_accept($perm_update);
break; break;
default: default:
@ -206,10 +190,10 @@ class Notifier {
return; return;
} }
else { else {
self::$recipients[] = $r[0]['abook_xchan']; self::$recipients[] = $recip['abook_xchan'];
self::$private = false; self::$private = false;
self::$packet_type = 'refresh'; self::$packet_type = 'refresh';
self::$env_recips = [ $r[0]['xchan_hash'] ]; self::$env_recips = [ $$recip['xchan_hash'] ];
} }
} }
} }
@ -230,7 +214,7 @@ class Notifier {
self::$packet_type = 'refresh'; self::$packet_type = 'refresh';
} }
elseif ($cmd === 'purge') { elseif ($cmd === 'purge') {
$xchan = argv(3); $xchan = $argv[3];
logger('notifier: purge: ' . $item_id . ' => ' . $xchan); logger('notifier: purge: ' . $item_id . ' => ' . $xchan);
if (! $xchan) { if (! $xchan) {
return; return;
@ -245,15 +229,17 @@ class Notifier {
logger('notifier: purge_all: ' . $item_id); logger('notifier: purge_all: ' . $item_id);
self::$channel = channelx_by_n($item_id); self::$channel = channelx_by_n($item_id);
self::$recipients = array(); self::$recipients = [];
$r = q("select abook_xchan from abook where abook_channel = %d and abook_self = 0", $r = q("select abook_xchan from abook where abook_channel = %d and abook_self = 0",
intval($item_id) intval($item_id)
); );
if($r) { if (! $r) {
return;
}
foreach ($r as $rr) { foreach ($r as $rr) {
self::$recipients[] = $rr['abook_xchan']; self::$recipients[] = $rr['abook_xchan'];
} }
}
self::$private = false; self::$private = false;
self::$packet_type = 'purge'; self::$packet_type = 'purge';
} }
@ -267,14 +253,14 @@ class Notifier {
intval($item_id) intval($item_id)
); );
if(! $r) if (! $r) {
return; return;
}
xchan_query($r); xchan_query($r);
$r = fetch_post_tags($r); $r = fetch_post_tags($r);
$target_item = $r[0]; $target_item = array_shift($r);
$deleted_item = false; $deleted_item = false;
if (intval($target_item['item_deleted'])) { if (intval($target_item['item_deleted'])) {
@ -283,9 +269,22 @@ class Notifier {
} }
if (! in_array(intval($target_item['item_type']), [ ITEM_TYPE_POST, ITEM_TYPE_MAIL ] )) { if (! in_array(intval($target_item['item_type']), [ ITEM_TYPE_POST, ITEM_TYPE_MAIL ] )) {
if (intval($target_item['item_type'] == ITEM_TYPE_CUSTOM)) {
$hookinfo=[
'targetitem'=>$target_item,
'deliver'=>false
];
call_hooks('customitem_deliver',$hookinfo);
}
if (!$hookinfo['deliver']) {
logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG); logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG);
return; return;
} }
}
// Check for non published items, but allow an exclusion for transmitting hidden file activities // Check for non published items, but allow an exclusion for transmitting hidden file activities
@ -296,16 +295,12 @@ class Notifier {
return; return;
} }
if(strpos($target_item['postopts'],'nodeliver') !== false) {
logger('notifier: target item is undeliverable', LOGGER_DEBUG);
return;
}
$s = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1", $s = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1",
intval($target_item['uid']) intval($target_item['uid'])
); );
if($s) if ($s) {
self::$channel = $s[0]; self::$channel = array_shift($s);
}
if (self::$channel['channel_hash'] !== $target_item['author_xchan'] && self::$channel['channel_hash'] !== $target_item['owner_xchan']) { if (self::$channel['channel_hash'] !== $target_item['author_xchan'] && self::$channel['channel_hash'] !== $target_item['owner_xchan']) {
logger("notifier: Sending channel is not owner {$target_item['owner_xchan']} or author {$target_item['author_xchan']}", LOGGER_NORMAL, LOG_WARNING); logger("notifier: Sending channel is not owner {$target_item['owner_xchan']} or author {$target_item['author_xchan']}", LOGGER_NORMAL, LOG_WARNING);
@ -317,7 +312,6 @@ class Notifier {
if ($target_item['mid'] === $target_item['parent_mid']) { if ($target_item['mid'] === $target_item['parent_mid']) {
$parent_item = $target_item; $parent_item = $target_item;
$top_level_post = true; $top_level_post = true;
} }
else { else {
@ -326,26 +320,28 @@ class Notifier {
intval($target_item['parent']) intval($target_item['parent'])
); );
if(! $r) if (! $r) {
return; return;
}
xchan_query($r); xchan_query($r);
$r = fetch_post_tags($r); $r = fetch_post_tags($r);
$parent_item = $r[0]; $parent_item = array_shift($r);
$top_level_post = false; $top_level_post = false;
$thread_is_public = 1 - intval($parent_item['item_private']) ; $thread_is_public = 1 - intval($parent_item['item_private']) ;
} }
// avoid looping of discover items 12/4/2014 // avoid looping of discover items 12/4/2014
if($sys && $parent_item['uid'] == $sys['channel_id']) if ($sys && $parent_item['uid'] == $sys['channel_id']) {
return; return;
}
$m = get_iconfig($target_item,'activitypub','signed_data'); $m = get_iconfig($target_item,'activitypub','signed_data');
if($m) if ($m) {
self::$encoded_item = json_decode($m,true); self::$encoded_item = json_decode($m,true);
}
else { else {
self::$encoded_item = array_merge(['@context' => [ self::$encoded_item = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV, ACTIVITYSTREAMS_JSONLD_REV,
@ -355,12 +351,7 @@ class Notifier {
); );
} }
logger('target_item: ' . print_r($target_item,true)); logger('target_item: ' . print_r($target_item,true));
// self::$encoded_item = encode_item($target_item);
logger('encoded: ' . print_r(self::$encoded_item,true)); logger('encoded: ' . print_r(self::$encoded_item,true));
// Send comments to the owner to re-deliver to everybody in the conversation // Send comments to the owner to re-deliver to everybody in the conversation
@ -374,8 +365,6 @@ class Notifier {
$relay_to_owner = (((! $top_level_post) && (intval($target_item['item_origin'])) && comment_local_origin($target_item) && $cmd !== 'hyper') ? true : false); $relay_to_owner = (((! $top_level_post) && (intval($target_item['item_origin'])) && comment_local_origin($target_item) && $cmd !== 'hyper') ? true : false);
$uplink = false; $uplink = false;
// $cmd === 'relay' indicates the owner is sending it to the original recipients // $cmd === 'relay' indicates the owner is sending it to the original recipients
@ -401,8 +390,10 @@ class Notifier {
self::$packet_type = 'response'; self::$packet_type = 'response';
$is_moderated = their_perms_contains($parent_item['uid'],$sendto,'moderated'); $is_moderated = their_perms_contains($parent_item['uid'],$sendto,'moderated');
if ($relay_to_owner && $thread_is_public && (! $is_moderated)) { if ($relay_to_owner && $thread_is_public && (! $is_moderated)) {
if (get_pconfig($target_item['uid'],'system','hyperdrive',false)) {
Master::Summon([ 'Notifier' , 'hyper', $item_id ]); Master::Summon([ 'Notifier' , 'hyper', $item_id ]);
} }
}
} }
else { else {
@ -425,7 +416,7 @@ class Notifier {
} }
if ($thread_is_public && $cmd === 'hyper') { if ($thread_is_public && $cmd === 'hyper') {
$rcps = []; self::$recipients = [];
$r = q("select abook_xchan, xchan_network from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and abook_pending = 0 and abook_archived = 0 and not abook_xchan in ( '%s', '%s', '%s' ) ", $r = q("select abook_xchan, xchan_network from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and abook_pending = 0 and abook_archived = 0 and not abook_xchan in ( '%s', '%s', '%s' ) ",
intval($target_item['uid']), intval($target_item['uid']),
dbesc($target_item['author_xchan']), dbesc($target_item['author_xchan']),
@ -434,11 +425,10 @@ class Notifier {
); );
if ($r) { if ($r) {
foreach ($r as $rv) { foreach ($r as $rv) {
$rcps[] = $rv['abook_xchan']; self::$recipients[] = $rv['abook_xchan'];
} }
} }
self::$private = false; self::$private = false;
self::$recipients = $rcps;
} }
else { else {
self::$private = false; self::$private = false;
@ -452,9 +442,7 @@ class Notifier {
self::$recipients = array_diff(self::$recipients, [ $target_item['owner_xchan'] ]); self::$recipients = array_diff(self::$recipients, [ $target_item['owner_xchan'] ]);
} }
// don't send deletions onward for other people's stuff // don't send deletions onward for other people's stuff
// TODO verify this is needed - copied logic from same place in old code
if (intval($target_item['item_deleted']) && (! intval($target_item['item_wall']))) { if (intval($target_item['item_deleted']) && (! intval($target_item['item_wall']))) {
logger('notifier: ignoring delete notification for non-wall item', LOGGER_NORMAL, LOG_NOTICE); logger('notifier: ignoring delete notification for non-wall item', LOGGER_NORMAL, LOG_NOTICE);
@ -476,17 +464,17 @@ class Notifier {
// logger('recipients: ' . print_r(self::$recipients,true), LOGGER_NORMAL, LOG_DEBUG); // logger('recipients: ' . print_r(self::$recipients,true), LOGGER_NORMAL, LOG_DEBUG);
if(! count(self::$env_recips)) if (! count(self::$env_recips)) {
self::$env_recips = ((self::$private) ? [] : null); self::$env_recips = ((self::$private) ? [] : null);
}
$details = q("select xchan_hash, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . protect_sprintf(implode(',',self::$recipients)) . ")"); $recip_list = [];
$details = q("select xchan_hash, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan
$recip_list = array(); where xchan_hash in (" . protect_sprintf(implode(',',self::$recipients)) . ")");
if ($details) { if ($details) {
foreach ($details as $d) { foreach ($details as $d) {
$recip_list[] = $d['xchan_addr'] . ' (' . $d['xchan_hash'] . ')'; $recip_list[] = $d['xchan_addr'] . ' (' . $d['xchan_hash'] . ')';
if (self::$private) { if (self::$private) {
self::$env_recips[] = $d['xchan_hash']; self::$env_recips[] = $d['xchan_hash'];
@ -508,21 +496,19 @@ class Notifier {
'relay_to_owner' => $relay_to_owner, 'relay_to_owner' => $relay_to_owner,
'uplink' => $uplink, 'uplink' => $uplink,
'cmd' => $cmd, 'cmd' => $cmd,
'mail' => $mail, 'single' => (($cmd === 'single_activity') ? true : false),
'single' => (($cmd === 'single_mail' || $cmd === 'single_activity') ? true : false),
'request' => $request, 'request' => $request,
'normal_mode' => $normal_mode, 'normal_mode' => $normal_mode,
'packet_type' => self::$packet_type, 'packet_type' => self::$packet_type,
'queued' => [] 'queued' => []
]; ];
call_hooks('notifier_process', $narr); call_hooks('notifier_process', $narr);
if ($narr['queued']) { if ($narr['queued']) {
foreach($narr['queued'] as $pq) foreach ($narr['queued'] as $pq) {
self::$deliveries[] = $pq; self::$deliveries[] = $pq;
} }
}
// notifier_process can alter the recipient list // notifier_process can alter the recipient list
@ -537,22 +523,19 @@ class Notifier {
logger('notifier: recipients (may be delivered to more if public): ' . print_r($recip_list,true), LOGGER_DEBUG); logger('notifier: recipients (may be delivered to more if public): ' . print_r($recip_list,true), LOGGER_DEBUG);
// Now we have collected recipients (except for external mentions, @FIXME)
// Now we have collected recipients (except for external mentions, FIXME)
// Let's reduce this to a set of hubs; checking that the site is not dead. // Let's reduce this to a set of hubs; checking that the site is not dead.
$r = q("select hubloc.*, site.site_crypto, site.site_flags from hubloc left join site on site_url = hubloc_url where hubloc_hash in (" . protect_sprintf(implode(',',self::$recipients)) . ") $hubs = q("select hubloc.*, site.site_crypto, site.site_flags from hubloc left join site on site_url = hubloc_url
where hubloc_hash in (" . protect_sprintf(implode(',',self::$recipients)) . ")
and hubloc_error = 0 and hubloc_deleted = 0 and ( site_dead = 0 OR site_dead is null ) " and hubloc_error = 0 and hubloc_deleted = 0 and ( site_dead = 0 OR site_dead is null ) "
); );
if (! $hubs) {
if(! $r) {
logger('notifier: no hubs', LOGGER_NORMAL, LOG_NOTICE); logger('notifier: no hubs', LOGGER_NORMAL, LOG_NOTICE);
return; return;
} }
$hubs = $r;
/** /**
* Reduce the hubs to those that are unique. For zot hubs, we need to verify uniqueness by the sitekey, * Reduce the hubs to those that are unique. For zot hubs, we need to verify uniqueness by the sitekey,
* since it may have been a re-install which has not yet been detected and pruned. * since it may have been a re-install which has not yet been detected and pruned.
@ -600,7 +583,9 @@ class Notifier {
foreach ($dhubs as $hub) { foreach ($dhubs as $hub) {
logger('notifier_hub: ' . $hub['hubloc_url'],LOGGER_DEBUG); logger('notifier_hub: ' . $hub['hubloc_url'],LOGGER_DEBUG, LOG_DEBUG);
// deliver to any non-zot networks
if ($hub['hubloc_network'] !== 'zot6') { if ($hub['hubloc_network'] !== 'zot6') {
$narr = [ $narr = [
@ -617,15 +602,13 @@ class Notifier {
'relay_to_owner' => $relay_to_owner, 'relay_to_owner' => $relay_to_owner,
'uplink' => $uplink, 'uplink' => $uplink,
'cmd' => $cmd, 'cmd' => $cmd,
'mail' => $mail, 'single' => (($cmd === 'single_activity') ? true : false),
'single' => (($cmd === 'single_mail' || $cmd === 'single_activity') ? true : false),
'request' => $request, 'request' => $request,
'normal_mode' => $normal_mode, 'normal_mode' => $normal_mode,
'packet_type' => self::$packet_type, 'packet_type' => self::$packet_type,
'queued' => [] 'queued' => []
]; ];
ActivityPub::notifier_process($narr); ActivityPub::notifier_process($narr);
call_hooks('notifier_hub',$narr); call_hooks('notifier_hub',$narr);
@ -637,7 +620,7 @@ class Notifier {
} }
// singleton deliveries by definition 'not got zot'. // singleton deliveries by definition 'not got zot'.
// Single deliveries are other federated networks (plugins) and we're essentially // Single deliveries are other federated networks and we're essentially
// delivering only to those that have this site url in their abook_instance // delivering only to those that have this site url in their abook_instance
// and only from within a sync operation. This means if you post from a clone, // and only from within a sync operation. This means if you post from a clone,
// and a connection is connected to one of your other clones; assuming that hub // and a connection is connected to one of your other clones; assuming that hub
@ -645,9 +628,7 @@ class Notifier {
// will invoke a delivery to those connections which are connected to just that // will invoke a delivery to those connections which are connected to just that
// hub instance. // hub instance.
// Note: Legacy Hubzilla and Osada code. In Zap this should never happen. if ($cmd === 'single_activity') {
if($cmd === 'single_mail' || $cmd === 'single_activity') {
continue; continue;
} }
@ -660,7 +641,8 @@ class Notifier {
continue; continue;
} }
$packet = Libzot::build_packet(self::$channel, self::$packet_type, $env, self::$encoded_item, self::$encoding, ((self::$private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto']); $packet = Libzot::build_packet(self::$channel, self::$packet_type, $env, self::$encoded_item, self::$encoding,
((self::$private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto']);
Queue::insert( Queue::insert(
[ [
@ -674,8 +656,9 @@ class Notifier {
); );
// only create delivery reports for normal undeleted items // only create delivery reports for normal undeleted items
if(is_array($target_item) && array_key_exists('postopts',$target_item) && (! $target_item['item_deleted']) && (! get_config('system','disable_dreport'))) { if (is_array($target_item) && (! $target_item['item_deleted']) && (! get_config('system','disable_dreport'))) {
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan, dreport_queue ) values ( '%s', '%s','%s','%s','%s','%s','%s','%s' ) ", q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan, dreport_queue )
values ( '%s', '%s','%s','%s','%s','%s','%s','%s' ) ",
dbesc($target_item['mid']), dbesc($target_item['mid']),
dbesc($hub['hubloc_host']), dbesc($hub['hubloc_host']),
dbesc($hub['hubloc_host']), dbesc($hub['hubloc_host']),
@ -691,16 +674,16 @@ class Notifier {
} }
if ($normal_mode) { if ($normal_mode) {
// This wastes a process if there are no delivery hooks configured, so check this before launching the new process
$x = q("select * from hook where hook = 'notifier_normal'"); $x = q("select * from hook where hook = 'notifier_normal'");
if ($x) { if ($x) {
Master::Summon( [ 'Deliver_hooks', $target_item['id'] ] ); Master::Summon( [ 'Deliver_hooks', $target_item['id'] ] );
} }
} }
if(self::$deliveries) if (self::$deliveries) {
do_delivery(self::$deliveries); do_delivery(self::$deliveries);
}
logger('notifier: basic loop complete.', LOGGER_DEBUG);
call_hooks('notifier_end',$target_item); call_hooks('notifier_end',$target_item);

View file

@ -99,20 +99,26 @@ class Onepoll {
if(! $responded) if(! $responded)
return; return;
if(defined('USE_OUTBOX')) {
// @fixme
// This needs to be converted from zotfeed to ActivityStreams (such as an ActivityPub outbox).
// The zotfeed has serious compatibility issues between Hubzilla and Zap.
if($contact['xchan_connurl']) { if($contact['xchan_connurl']) {
$fetch_feed = true; $fetch_feed = true;
$x = null; $x = null;
// They haven't given us permission to see their stream // They haven't given us permission to see their stream
$can_view_stream = their_perms_contains($importer_uid,$contact['abook_xchan'],'view_stream'); $can_view_stream = intval(get_abconfig($importer_uid,$contact['abook_xchan'],'their_perms','view_stream'));
if(! $can_view_stream) if(! $can_view_stream)
$fetch_feed = false; $fetch_feed = false;
// we haven't given them permission to send us their stream // we haven't given them permission to send us their stream
$can_send_stream = ((strpos(get_abconfig($importer_uid,$contact['abook_xchan'],'system','my_perms',EMPTY_STR),'send_stream') !== false) ? true : false); $can_send_stream = intval(get_abconfig($importer_uid,$contact['abook_xchan'],'my_perms','send_stream'));
if(! $can_send_stream) if(! $can_send_stream)
$fetch_feed = false; $fetch_feed = false;
@ -151,7 +157,7 @@ class Onepoll {
$j = json_decode($x['body'],true); $j = json_decode($x['body'],true);
if($j['success'] && $j['messages']) { if($j['success'] && $j['messages']) {
foreach($j['messages'] as $message) { foreach($j['messages'] as $message) {
$results = Libzot::process_delivery($contact['xchan_hash'], null, get_item_elements($message), [ $importer['xchan_hash'] ], false); // process delivery here once we have parsed the AS
logger('onepoll: feed_update: process_delivery: ' . print_r($results,true), LOGGER_DATA); logger('onepoll: feed_update: process_delivery: ' . print_r($results,true), LOGGER_DATA);
$total ++; $total ++;
} }
@ -161,6 +167,8 @@ class Onepoll {
} }
} // end USE_OUTBOX
// update the poco details for this connection // update the poco details for this connection
if($contact['xchan_connurl']) { if($contact['xchan_connurl']) {

View file

@ -29,8 +29,8 @@ class Poller {
return; return;
} }
// Create a lockfile. Needs two vars, but $x doesn't need to contain anything. // Create a lockfile.
file_put_contents($lockfile, $x); file_put_contents($lockfile, EMPTY_STR);
logger('poller: start'); logger('poller: start');
@ -47,7 +47,7 @@ class Poller {
$restart = true; $restart = true;
$generation = intval($argv[2]); $generation = intval($argv[2]);
if(! $generation) if(! $generation)
killme(); return;
} }
if(($argc > 1) && intval($argv[1])) { if(($argc > 1) && intval($argv[1])) {

View file

@ -1,18 +0,0 @@
<?php
namespace Zotlabs\Identity\BasicId;
class BasicId {
private $name;
private $profile_photo;
private $profile_url;
private $address;
private $protocol;
}

View file

@ -2,27 +2,34 @@
namespace Zotlabs\Identity; namespace Zotlabs\Identity;
class OAuth2Server extends \OAuth2\Server { use Zotlabs\Lib\System;
use OAuth2\Server;
use OAuth2\Storage\Memory;
use OAuth2\GrantType\ClientCredentials;
use OAuth2\OpenID\GrantType\AuthorizationCode;
class OAuth2Server extends Server {
public function __construct(OAuth2Storage $storage, $config = null) { public function __construct(OAuth2Storage $storage, $config = null) {
if (! is_array($config)) { if (! is_array($config)) {
$config = [ $config = [
'use_openid_connect' => true, 'use_openid_connect' => true,
'issuer' => \Zotlabs\Lib\System::get_site_name() 'issuer' => System::get_site_name()
]; ];
} }
parent::__construct($storage, $config); parent::__construct($storage, $config);
// Add the "Client Credentials" grant type (it is the simplest of the grant types) // Add the "Client Credentials" grant type (it is the simplest of the grant types)
$this->addGrantType(new \OAuth2\GrantType\ClientCredentials($storage)); $this->addGrantType(new ClientCredentials($storage));
// Add the "Authorization Code" grant type (this is where the oauth magic happens) // Add the "Authorization Code" grant type (this is where the oauth magic happens)
// Need to use OpenID\GrantType to return id_token (see:https://github.com/bshaffer/oauth2-server-php/issues/443) // Need to use OpenID\GrantType to return id_token
$this->addGrantType(new \OAuth2\OpenID\GrantType\AuthorizationCode($storage)); // (see:https://github.com/bshaffer/oauth2-server-php/issues/443)
$this->addGrantType(new AuthorizationCode($storage));
$keyStorage = new \OAuth2\Storage\Memory( [ $keyStorage = new Memory( [
'keys' => [ 'keys' => [
'public_key' => get_config('system', 'pubkey'), 'public_key' => get_config('system', 'pubkey'),
'private_key' => get_config('system', 'prvkey') 'private_key' => get_config('system', 'prvkey')

View file

@ -96,10 +96,10 @@ class OAuth2Storage extends \OAuth2\Storage\Pdo {
// @TODO: create a more reasonable/comprehensive list. // @TODO: create a more reasonable/comprehensive list.
// @TODO: present claims on the AUTHORIZATION screen // @TODO: present claims on the AUTHORIZATION screen
$userClaims = Array(); $userClaims = [];
$claims = explode (' ', trim($claims)); $claims = explode (' ', trim($claims));
$validclaims = Array ("name","preferred_username","webfinger","portable_id","email","picture","firstName","lastName"); $validclaims = [ "name", "preferred_username", "webfinger", "portable_id", "email", "picture", "firstName", "lastName" ];
$claimsmap = Array ( $claimsmap = [
"webfinger" => 'webfinger', "webfinger" => 'webfinger',
"portable_id" => 'portable_id', "portable_id" => 'portable_id',
"name" => 'name', "name" => 'name',
@ -108,13 +108,14 @@ class OAuth2Storage extends \OAuth2\Storage\Pdo {
"picture" => 'picture', "picture" => 'picture',
"given_name" => 'firstName', "given_name" => 'firstName',
"family_name" => 'lastName' "family_name" => 'lastName'
); ];
$userinfo = $this->getUser($user_id); $userinfo = $this->getUser($user_id);
foreach ($validclaims as $validclaim) { foreach ($validclaims as $validclaim) {
if (in_array($validclaim,$claims)) { if (in_array($validclaim,$claims)) {
$claimkey = $claimsmap[$validclaim]; $claimkey = $claimsmap[$validclaim];
$userClaims[$validclaim] = $userinfo[$claimkey]; $userClaims[$validclaim] = $userinfo[$claimkey];
} else { }
else {
$userClaims[$validclaim] = $validclaim; $userClaims[$validclaim] = $validclaim;
} }
} }
@ -136,4 +137,35 @@ class OAuth2Storage extends \OAuth2\Storage\Pdo {
return true; return true;
} }
public function setClientDetails($client_id, $client_secret = null, $redirect_uri = null, $grant_types = null, $scope = null, $user_id = null, $client_name = null)
{
// if it exists, update it.
if ($this->getClientDetails($client_id)) {
$stmt = $this->db->prepare($sql = sprintf('UPDATE %s SET client_secret=:client_secret, redirect_uri=:redirect_uri, grant_types=:grant_types, scope=:scope, user_id=:user_id, client_name=:client_name where client_id=:client_id', $this->config['client_table']));
} else {
$stmt = $this->db->prepare(sprintf('INSERT INTO %s (client_id, client_secret, redirect_uri, grant_types, scope, user_id, client_name) VALUES (:client_id, :client_secret, :redirect_uri, :grant_types, :scope, :user_id, :client_name)', $this->config['client_table']));
}
return $stmt->execute(compact('client_id', 'client_secret', 'redirect_uri', 'grant_types', 'scope', 'user_id', 'client_name'));
}
public function checkRestrictedGrantType($client_id, $grant_type)
{
$details = $this->getClientDetails($client_id);
if ($details['grant_types']) {
$grant_types = explode(' ', $details['grant_types']);
return in_array($grant_type, (array) $grant_types);
}
// if grant_types are not defined, then none are restricted
return true;
}
} }

View file

@ -1,16 +0,0 @@
<?php
namespace Zotlabs\Identity\ProfilePhoto;
class ProfilePhoto {
private $photo_large_url;
private $photo_medium_url;
private $photo_small_url;
private $photo_mimetype;
private $photo_updated;
}

View file

@ -0,0 +1,81 @@
<?php
namespace Zotlabs\Lib;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\Activity;
/**
* Class for dealing with ActivityStreams ordered collections.
* Construct with the object url and an optional channel to sign the request.
* Returns an array of collection members.
* If desired, call $collection->next to return additional pages (arrays of collection members).
* Returns an empty array when there is nothing more to return
*/
class ASCollection {
private $url = null;
private $channel = null;
private $nextpage = null;
private $data = null;
function __construct($url,$channel = null) {
$this->url = $url;
$this->channel = $channel;
$data = Activity::fetch($url,$channel);
if (! $data) {
return false;
}
$ptr = $data;
if ($data['type'] === 'OrderedCollection') {
if (array_key_exists('first',$data)) {
$ptr = $data['first'];
}
}
if ($ptr['type'] === 'OrderedCollectionPage' && $ptr['orderedItems']) {
$this->data = $ptr['orderedItems'];
}
$this->setnext($data);
return $this->data;
}
function next() {
if (! $this->nextpage) {
return [];
}
$data = Activity::fetch($this->nextpage,$channel);
if (! $data) {
return [];
}
if ($data['type'] === 'OrderedCollectionPage' && $data['orderedItems']) {
$this->data = $data['orderedItems'];
}
$this->setnext($data);
return $this->data;
}
function setnext($data) {
if (array_key_exists('next',$data)) {
$this->nextpage = $data['next'];
}
elseif (array_key_exists('last',$data)) {
$this->nextpage = $data['last'];
}
}
}

View file

@ -10,7 +10,7 @@ class AccessList {
static function add($uid,$name,$public = 0) { static function add($uid,$name,$public = 0) {
$ret = false; $ret = false;
if(x($uid) && x($name)) { if ($uid && $name) {
$r = self::byname($uid,$name); // check for dups $r = self::byname($uid,$name); // check for dups
if ($r !== false) { if ($r !== false) {
@ -30,15 +30,7 @@ class AccessList {
return true; return true;
} }
do { $hash = new_uuid();
$dups = false;
$hash = random_string(32) . str_replace(['<','>'],['.','.'], $name);
$r = q("SELECT id FROM pgrp WHERE hash = '%s' LIMIT 1", dbesc($hash));
if($r)
$dups = true;
} while($dups == true);
$r = q("INSERT INTO pgrp ( hash, uid, visible, gname ) $r = q("INSERT INTO pgrp ( hash, uid, visible, gname )
VALUES( '%s', %d, %d, '%s' ) ", VALUES( '%s', %d, %d, '%s' ) ",
@ -214,15 +206,15 @@ class AccessList {
} }
static function members($gid) { static function members($uid, $gid) {
$ret = array(); $ret = array();
if(intval($gid)) { if(intval($gid)) {
$r = q("SELECT * FROM pgrp_member $r = q("SELECT * FROM pgrp_member
LEFT JOIN abook ON abook_xchan = pgrp_member.xchan left join xchan on xchan_hash = abook_xchan LEFT JOIN abook ON abook_xchan = pgrp_member.xchan left join xchan on xchan_hash = abook_xchan
WHERE gid = %d AND abook_channel = %d and pgrp_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ", WHERE gid = %d AND abook_channel = %d and pgrp_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ",
intval($gid), intval($gid),
intval(local_channel()), intval($uid),
intval(local_channel()) intval($uid)
); );
if($r) if($r)
$ret = $r; $ret = $r;
@ -230,12 +222,12 @@ class AccessList {
return $ret; return $ret;
} }
static function members_xchan($gid) { static function members_xchan($uid,$gid) {
$ret = []; $ret = [];
if(intval($gid)) { if(intval($gid)) {
$r = q("SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d", $r = q("SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d",
intval($gid), intval($gid),
intval(local_channel()) intval($uid)
); );
if($r) { if($r) {
foreach($r as $rr) { foreach($r as $rr) {
@ -293,7 +285,7 @@ class AccessList {
static function widget($every="connections",$each="group",$edit = false, $group_id = 0, $cid = '',$mode = 1) { static function widget($every="connections",$each="lists",$edit = false, $group_id = 0, $cid = '',$mode = 1) {
$o = ''; $o = '';
@ -312,7 +304,7 @@ class AccessList {
$selected = (($group_id == $rr['id']) ? ' group-selected' : ''); $selected = (($group_id == $rr['id']) ? ' group-selected' : '');
if ($edit) { if ($edit) {
$groupedit = [ 'href' => "alist/".$rr['id'], 'title' => t('edit') ]; $groupedit = [ 'href' => "lists/".$rr['id'], 'title' => t('edit') ];
} }
else { else {
$groupedit = null; $groupedit = null;
@ -334,7 +326,7 @@ class AccessList {
$tpl = get_markup_template("group_side.tpl"); $tpl = get_markup_template("group_side.tpl");
$o = replace_macros($tpl, array( $o = replace_macros($tpl, array(
'$title' => t('Access Lists'), '$title' => t('Lists'),
'$edittext' => t('Edit list'), '$edittext' => t('Edit list'),
'$createtext' => t('Create new list'), '$createtext' => t('Create new list'),
'$ungrouped' => (($every === 'contacts') ? t('Channels not in any access list') : ''), '$ungrouped' => (($every === 'contacts') ? t('Channels not in any access list') : ''),

File diff suppressed because it is too large Load diff

View file

@ -6,14 +6,15 @@ use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\Activity; use Zotlabs\Lib\Activity;
use Zotlabs\Lib\Queue; use Zotlabs\Lib\Queue;
use Zotlabs\Daemon\Master; use Zotlabs\Daemon\Master;
use Zotlabs\Lib\IConfig;
class ActivityPub { class ActivityPub {
static public function notifier_process(&$arr) { static public function notifier_process(&$arr) {
if($arr['hub']['hubloc_network'] !== 'activitypub') if ($arr['hub']['hubloc_network'] !== 'activitypub') {
return; return;
}
logger('upstream: ' . intval($arr['upstream'])); logger('upstream: ' . intval($arr['upstream']));
@ -29,10 +30,6 @@ class ActivityPub {
return; return;
} }
if(strpos($arr['target_item']['postopts'],'nopub') !== false) {
return;
}
$signed_msg = get_iconfig($arr['target_item'],'activitypub','rawmsg'); $signed_msg = get_iconfig($arr['target_item'],'activitypub','rawmsg');
// If we have an activity already stored with an LD-signature // If we have an activity already stored with an LD-signature
@ -51,8 +48,9 @@ class ActivityPub {
$target_item = $arr['target_item']; $target_item = $arr['target_item'];
if(! $target_item['mid']) if (! $target_item['mid']) {
return; return;
}
$prv_recips = $arr['env_recips']; $prv_recips = $arr['env_recips'];
@ -61,9 +59,23 @@ class ActivityPub {
$jmsg = $signed_msg; $jmsg = $signed_msg;
} }
else { else {
$ti = Activity::encode_activity($target_item, true); $ti = Activity::encode_activity($target_item, true);
if(! $ti) if (! $ti) {
return; return;
}
if ($target_item['mid'] !== $target_item['parent_mid']) {
$token = IConfig::get($target_item['id'],'ocap','relay');
if ($token) {
if (defined('USE_BEARCAPS')) {
$ti['id'] = 'bear:?u=' . $ti['id'] . '&t=' . $token;
}
else {
$ti['id'] = $ti['id'] . '?token=' . $token;
}
}
}
$msg = array_merge(['@context' => [ $msg = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV, ACTIVITYSTREAMS_JSONLD_REV,
@ -79,12 +91,13 @@ class ActivityPub {
} }
if ($prv_recips) { if ($prv_recips) {
$hashes = array(); $hashes = [];
// re-explode the recipients, but only for this hub/pod // re-explode the recipients, but only for this hub/pod
foreach($prv_recips as $recip) foreach ($prv_recips as $recip) {
$hashes[] = "'" . $recip . "'"; $hashes[] = "'" . $recip . "'";
}
$r = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_url = '%s' $r = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_url = '%s'
and xchan_hash in (" . implode(',', $hashes) . ") and xchan_network = 'activitypub' ", and xchan_hash in (" . implode(',', $hashes) . ") and xchan_network = 'activitypub' ",
@ -103,8 +116,9 @@ class ActivityPub {
// They'll reject it if they don't like it. // They'll reject it if they don't like it.
// $single = deliverable_singleton($arr['channel']['channel_id'],$contact); // $single = deliverable_singleton($arr['channel']['channel_id'],$contact);
if(! $arr['normal_mode']) if (! $arr['normal_mode']) {
continue; continue;
}
$qi = self::queue_message($jmsg,$arr['channel'],$contact,$target_item['mid']); $qi = self::queue_message($jmsg,$arr['channel'],$contact,$target_item['mid']);
if ($qi) { if ($qi) {
@ -145,7 +159,6 @@ class ActivityPub {
// $single = deliverable_singleton($arr['channel']['channel_id'],$contact); // $single = deliverable_singleton($arr['channel']['channel_id'],$contact);
$qi = self::queue_message($jmsg,$arr['channel'],$contact,$target_item['mid']); $qi = self::queue_message($jmsg,$arr['channel'],$contact,$target_item['mid']);
if ($qi) { if ($qi) {
$arr['queued'][] = $qi; $arr['queued'][] = $qi;
@ -161,7 +174,6 @@ class ActivityPub {
static function queue_message($msg,$sender,$recip,$message_id = '') { static function queue_message($msg,$sender,$recip,$message_id = '') {
$dest_url = $recip['hubloc_callback']; $dest_url = $recip['hubloc_callback'];
logger('URL: ' . $dest_url, LOGGER_DEBUG); logger('URL: ' . $dest_url, LOGGER_DEBUG);
@ -175,7 +187,7 @@ class ActivityPub {
$hash = random_string(); $hash = random_string();
logger('queue: ' . $hash . ' ' . $dest_url, LOGGER_DEBUG); logger('queue: ' . $hash . ' ' . $dest_url, LOGGER_DEBUG);
Queue::insert(array( Queue::insert([
'hash' => $hash, 'hash' => $hash,
'account_id' => $sender['channel_account_id'], 'account_id' => $sender['channel_account_id'],
'channel_id' => $sender['channel_id'], 'channel_id' => $sender['channel_id'],
@ -183,7 +195,7 @@ class ActivityPub {
'posturl' => $dest_url, 'posturl' => $dest_url,
'notify' => '', 'notify' => '',
'msg' => $msg 'msg' => $msg
)); ]);
if ($message_id && (! get_config('system','disable_dreport'))) { if ($message_id && (! get_config('system','disable_dreport'))) {
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan, dreport_queue ) values ( '%s','%s','%s','%s','%s','%s','%s' ) ", q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan, dreport_queue ) values ( '%s','%s','%s','%s','%s','%s','%s' ) ",
@ -198,7 +210,6 @@ class ActivityPub {
} }
return $hash; return $hash;
} }
@ -211,9 +222,10 @@ class ActivityPub {
return; return;
} }
$p = Activity::encode_person($x['sender'],true,true); $p = Activity::encode_person($x['sender'],false);
if(! $p) if (! $p) {
return; return;
}
$msg = array_merge(['@context' => [ $msg = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV, ACTIVITYSTREAMS_JSONLD_REV,
@ -239,12 +251,12 @@ class ActivityPub {
if ($h) { if ($h) {
$qi = self::queue_message($jmsg,$x['sender'],$h[0]); $qi = self::queue_message($jmsg,$x['sender'],$h[0]);
if($qi) if ($qi) {
$x['deliveries'] = $qi; $x['deliveries'] = $qi;
} }
}
$x['success'] = true; $x['success'] = true;
} }
@ -259,12 +271,14 @@ class ActivityPub {
// we currently are not handling send of reject follow activities; this is permitted by protocol // we currently are not handling send of reject follow activities; this is permitted by protocol
$accept = get_abconfig($x['recipient']['abook_channel'],$x['recipient']['xchan_hash'],'activitypub','their_follow_id'); $accept = get_abconfig($x['recipient']['abook_channel'],$x['recipient']['xchan_hash'],'activitypub','their_follow_id');
if(! $accept) if (! $accept) {
return; return;
}
$p = Activity::encode_person($x['sender'],true,true); $p = Activity::encode_person($x['sender'],false);
if(! $p) if (! $p) {
return; return;
}
$msg = array_merge(['@context' => [ $msg = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV, ACTIVITYSTREAMS_JSONLD_REV,
@ -294,9 +308,10 @@ class ActivityPub {
if ($h) { if ($h) {
$qi = self::queue_message($jmsg,$x['sender'],$h[0]); $qi = self::queue_message($jmsg,$x['sender'],$h[0]);
if($qi) if ($qi) {
$x['deliveries'] = $qi; $x['deliveries'] = $qi;
} }
}
$x['success'] = true; $x['success'] = true;
@ -312,12 +327,14 @@ class ActivityPub {
return; return;
$channel = channelx_by_n($recip[0]['abook_channel']); $channel = channelx_by_n($recip[0]['abook_channel']);
if(! $channel) if (! $channel) {
return; return;
}
$p = Activity::encode_person($channel,true,true); $p = Activity::encode_person($channel,true,true);
if(! $p) if (! $p) {
return; return;
}
// send an unfollow activity to the followee's inbox // send an unfollow activity to the followee's inbox
@ -325,7 +342,6 @@ class ActivityPub {
if ($orig_activity && $recip[0]['abook_pending']) { if ($orig_activity && $recip[0]['abook_pending']) {
// was never approved // was never approved
$msg = array_merge(['@context' => [ $msg = array_merge(['@context' => [

View file

@ -24,6 +24,7 @@ class ActivityStreams {
public $actor = null; public $actor = null;
public $obj = null; public $obj = null;
public $tgt = null; public $tgt = null;
public $replyto = null;
public $origin = null; public $origin = null;
public $owner = null; public $owner = null;
public $signer = null; public $signer = null;
@ -35,17 +36,20 @@ class ActivityStreams {
/** /**
* @brief Constructor for ActivityStreams. * @brief Constructor for ActivityStreams.
* *
* Takes a JSON string as parameter, decodes it and sets up this object. * Takes a JSON string or previously decode activity array as parameter,
* decodes it and sets up this object/activity, fetching any required attributes
* which were only referenced by @id/URI.
* *
* @param string $string * @param string $string
*/ */
function __construct($string,$hub = null) { function __construct($string,$hub = null,$client = null) {
$this->raw = $string; $this->raw = $string;
$this->hub = $hub; $this->hub = $hub;
if (is_array($string)) { if (is_array($string)) {
$this->data = $string; $this->data = $string;
$this->raw = json_encode($string,JSON_UNESCAPED_SLASHES);
} }
else { else {
$this->data = json_decode($string, true); $this->data = json_decode($string, true);
@ -54,12 +58,14 @@ class ActivityStreams {
if ($this->data) { if ($this->data) {
// verify and unpack JSalmon signature if present // verify and unpack JSalmon signature if present
// This will only be the case for Zot6 packets
if (is_array($this->data) && array_key_exists('signed',$this->data)) { if (is_array($this->data) && array_key_exists('signed',$this->data)) {
$ret = JSalmon::verify($this->data); $ret = JSalmon::verify($this->data);
$tmp = JSalmon::unpack($this->data['data']); $tmp = JSalmon::unpack($this->data['data']);
if ($ret && $ret['success']) { if ($ret && $ret['success']) {
if ($ret['signer']) { if ($ret['signer']) {
logger('Unpacked: ' . json_encode($tmp,JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT),LOGGER_DATA,LOG_DEBUG);
$saved = json_encode($this->data,JSON_UNESCAPED_SLASHES); $saved = json_encode($this->data,JSON_UNESCAPED_SLASHES);
$this->data = $tmp; $this->data = $tmp;
$this->data['signer'] = $ret['signer']; $this->data['signer'] = $ret['signer'];
@ -71,8 +77,12 @@ class ActivityStreams {
} }
} }
// This indicates only that we have sucessfully decoded JSON.
$this->valid = true; $this->valid = true;
// Special handling for Mastodon "delete actor" activities which will often fail to verify
// because the key cannot be fetched. We will catch this condition elsewhere.
if (array_key_exists('type',$this->data) && array_key_exists('actor',$this->data) && array_key_exists('object',$this->data)) { if (array_key_exists('type',$this->data) && array_key_exists('actor',$this->data) && array_key_exists('object',$this->data)) {
if ($this->data['type'] === 'Delete' && $this->data['actor'] === $this->data['object']) { if ($this->data['type'] === 'Delete' && $this->data['actor'] === $this->data['object']) {
$this->deleted = $this->data['actor']; $this->deleted = $this->data['actor'];
@ -82,6 +92,8 @@ class ActivityStreams {
} }
// Attempt to assemble an Activity from what we were given.
if ($this->is_valid()) { if ($this->is_valid()) {
$this->id = $this->get_property_obj('id'); $this->id = $this->get_property_obj('id');
$this->type = $this->get_primary_type(); $this->type = $this->get_primary_type();
@ -90,16 +102,20 @@ class ActivityStreams {
$this->tgt = $this->get_compound_property('target'); $this->tgt = $this->get_compound_property('target');
$this->origin = $this->get_compound_property('origin'); $this->origin = $this->get_compound_property('origin');
$this->recips = $this->collect_recips(); $this->recips = $this->collect_recips();
$this->replyto = $this->get_compound_property('replyTo');
$this->ldsig = $this->get_compound_property('signature'); $this->ldsig = $this->get_compound_property('signature');
if ($this->ldsig) { if ($this->ldsig) {
$this->signer = $this->get_compound_property('creator',$this->ldsig); $this->signer = $this->get_compound_property('creator',$this->ldsig);
if($this->signer && is_array($this->signer) && array_key_exists('publicKey',$this->signer) && is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']) { if ($this->signer && is_array($this->signer) && array_key_exists('publicKey',$this->signer)
&& is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']) {
$this->sigok = LDSignatures::verify($this->data,$this->signer['publicKey']['publicKeyPem']); $this->sigok = LDSignatures::verify($this->data,$this->signer['publicKey']['publicKeyPem']);
} }
} }
if(! $this->obj) { // Implied create activity required by C2S specification if no object is present
if ($client && ! $this->obj) {
$this->obj = $this->data; $this->obj = $this->data;
$this->type = 'Create'; $this->type = 'Create';
if (! $this->actor) { if (! $this->actor) {
@ -107,10 +123,16 @@ class ActivityStreams {
} }
} }
if($this->obj && is_array($this->obj) && $this->obj['actor']) // Enumerate and store actors in referenced objects
if ($this->obj && is_array($this->obj) && $this->obj['actor']) {
$this->obj['actor'] = $this->get_actor('actor',$this->obj); $this->obj['actor'] = $this->get_actor('actor',$this->obj);
if($this->tgt && is_array($this->tgt) && $this->tgt['actor']) }
if ($this->tgt && is_array($this->tgt) && $this->tgt['actor']) {
$this->tgt['actor'] = $this->get_actor('actor',$this->tgt); $this->tgt['actor'] = $this->get_actor('actor',$this->tgt);
}
// Determine if this is a followup or response activity
$this->parent_id = $this->get_property_obj('inReplyTo'); $this->parent_id = $this->get_property_obj('inReplyTo');
@ -153,12 +175,14 @@ class ActivityStreams {
$y = [ $y ]; $y = [ $y ];
} }
$x = array_merge($x, $y); $x = array_merge($x, $y);
if(! is_array($this->raw_recips)) if (! is_array($this->raw_recips)) {
$this->raw_recips = []; $this->raw_recips = [];
}
$this->raw_recips[$f] = $x; $this->raw_recips[$f] = $x;
} }
} }
// not yet ready for prime time // not yet ready for prime time
// $x = $this->expand($x,$base,$namespace); // $x = $this->expand($x,$base,$namespace);
return $x; return $x;
@ -197,26 +221,30 @@ class ActivityStreams {
* @param string $namespace if not set return empty string * @param string $namespace if not set return empty string
* @return string|NULL * @return string|NULL
*/ */
function get_namespace($base, $namespace) { function get_namespace($base, $namespace) {
if(! $namespace) if (! $namespace) {
return ''; return EMPTY_STR;
}
$key = null; $key = null;
foreach ( [ $this->data, $base ] as $b ) { foreach ( [ $this->data, $base ] as $b ) {
if(! $b) if (! $b) {
continue; continue;
}
if (array_key_exists('@context', $b)) { if (array_key_exists('@context', $b)) {
if (is_array($b['@context'])) { if (is_array($b['@context'])) {
foreach ($b['@context'] as $ns) { foreach ($b['@context'] as $ns) {
if (is_array($ns)) { if (is_array($ns)) {
foreach ($ns as $k => $v) { foreach ($ns as $k => $v) {
if($namespace === $v) if ($namespace === $v) {
$key = $k; $key = $k;
} }
} }
}
else { else {
if ($namespace === $ns) { if ($namespace === $ns) {
$key = ''; $key = '';
@ -243,10 +271,12 @@ class ActivityStreams {
* @param string $namespace (optional) default empty * @param string $namespace (optional) default empty
* @return NULL|mixed * @return NULL|mixed
*/ */
function get_property_obj($property, $base = '', $namespace = '') { function get_property_obj($property, $base = '', $namespace = '') {
$prefix = $this->get_namespace($base, $namespace); $prefix = $this->get_namespace($base, $namespace);
if($prefix === null) if ($prefix === null) {
return null; return null;
}
$base = (($base) ? $base : $this->data); $base = (($base) ? $base : $this->data);
$propname = (($prefix) ? $prefix . ':' : '') . $property; $propname = (($prefix) ? $prefix . ':' : '') . $property;
@ -299,6 +329,7 @@ class ActivityStreams {
dbesc($x) dbesc($x)
); );
if ($r) { if ($r) {
// indicate that this is a cached record
$y = Activity::encode_person($r[0]); $y = Activity::encode_person($r[0]);
$y['cached'] = true; $y['cached'] = true;
$y['updated'] = datetime_convert('UTC','UTC',$r[0]['hubloc_updated'],ATOM_TIME); $y['updated'] = datetime_convert('UTC','UTC',$r[0]['hubloc_updated'],ATOM_TIME);
@ -325,6 +356,7 @@ class ActivityStreams {
* @param boolean $first (optional) default false, if true and result is a sequential array return only the first element * @param boolean $first (optional) default false, if true and result is a sequential array return only the first element
* @return NULL|mixed * @return NULL|mixed
*/ */
function get_compound_property($property, $base = '', $namespace = '', $first = false) { function get_compound_property($property, $base = '', $namespace = '', $first = false) {
$x = $this->get_property_obj($property, $base, $namespace); $x = $this->get_property_obj($property, $base, $namespace);
if ($this->is_url($x)) { if ($this->is_url($x)) {
@ -335,12 +367,14 @@ class ActivityStreams {
} }
// verify and unpack JSalmon signature if present // verify and unpack JSalmon signature if present
// This may be present in Zot6 packets
if (is_array($x) && array_key_exists('signed',$x)) { if (is_array($x) && array_key_exists('signed',$x)) {
$ret = JSalmon::verify($x); $ret = JSalmon::verify($x);
$tmp = JSalmon::unpack($x['data']); $tmp = JSalmon::unpack($x['data']);
if ($ret && $ret['success']) { if ($ret && $ret['success']) {
if ($ret['signer']) { if ($ret['signer']) {
logger('Unpacked: ' . json_encode($tmp,JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT),LOGGER_DATA,LOG_DEBUG);
$saved = json_encode($x,JSON_UNESCAPED_SLASHES); $saved = json_encode($x,JSON_UNESCAPED_SLASHES);
$x = $tmp; $x = $tmp;
$x['signer'] = $ret['signer']; $x['signer'] = $ret['signer'];
@ -364,8 +398,9 @@ class ActivityStreams {
* @param string $url * @param string $url
* @return boolean * @return boolean
*/ */
function is_url($url) { function is_url($url) {
if(($url) && (! is_array($url)) && ((strpos($url, 'http') === 0) || (strpos($url,'x-zot') === 0))) { if (($url) && (! is_array($url)) && ((strpos($url, 'http') === 0) || (strpos($url,'x-zot') === 0) || (strpos($url,'bear') === 0))) {
return true; return true;
} }
@ -379,10 +414,11 @@ class ActivityStreams {
* @param string $namespace (optional) default empty * @param string $namespace (optional) default empty
* @return NULL|mixed * @return NULL|mixed
*/ */
function get_primary_type($base = '', $namespace = '') {
if(! $base)
$base = $this->data;
function get_primary_type($base = '', $namespace = '') {
if (! $base) {
$base = $this->data;
}
$x = $this->get_property_obj('type', $base, $namespace); $x = $this->get_property_obj('type', $base, $namespace);
if (is_array($x)) { if (is_array($x)) {
foreach ($x as $y) { foreach ($x as $y) {
@ -410,8 +446,5 @@ class ActivityStreams {
]); ]);
return(($x) ? true : false); return(($x) ? true : false);
} }
} }

View file

@ -74,7 +74,7 @@ class Apps {
'Events', 'Events',
'Search', 'Search',
'Profile Photo', 'Profile Photo',
'Access Lists' 'Lists'
]); ]);
call_hooks('get_base_apps',$x); call_hooks('get_base_apps',$x);
return $x; return $x;
@ -313,7 +313,7 @@ class Apps {
static public function translate_system_apps(&$arr) { static public function translate_system_apps(&$arr) {
$apps = array( $apps = array(
'Apps' => t('Apps'), 'Apps' => t('Apps'),
'Affinity Tool' => t('Affinity Tool'), 'Friend Zoom' => t('Friend Zoom'),
'Articles' => t('Articles'), 'Articles' => t('Articles'),
'Cards' => t('Cards'), 'Cards' => t('Cards'),
'Calendar' => t('Calendar'), 'Calendar' => t('Calendar'),
@ -331,6 +331,7 @@ class Apps {
'Suggest Channels' => t('Suggest Channels'), 'Suggest Channels' => t('Suggest Channels'),
'Login' => t('Login'), 'Login' => t('Login'),
'Channel Manager' => t('Channel Manager'), 'Channel Manager' => t('Channel Manager'),
'Notes' => t('Notes'),
'Network' => t('Stream'), 'Network' => t('Stream'),
'Settings' => t('Settings'), 'Settings' => t('Settings'),
'Files' => t('Files'), 'Files' => t('Files'),
@ -339,7 +340,10 @@ class Apps {
'Channel Home' => t('Channel Home'), 'Channel Home' => t('Channel Home'),
'View Profile' => t('View Profile'), 'View Profile' => t('View Profile'),
'Photos' => t('Photos'), 'Photos' => t('Photos'),
'Photomap' => t('Photomap'),
'Events' => t('Events'), 'Events' => t('Events'),
'Tasks' => t('Tasks'),
'No Comment' => t('No Comment'),
'Directory' => t('Directory'), 'Directory' => t('Directory'),
'Help' => t('Help'), 'Help' => t('Help'),
'Mail' => t('Mail'), 'Mail' => t('Mail'),
@ -359,7 +363,7 @@ class Apps {
'Profile Photo' => t('Profile Photo'), 'Profile Photo' => t('Profile Photo'),
'Profile' => t('Profile'), 'Profile' => t('Profile'),
'Profiles' => t('Profiles'), 'Profiles' => t('Profiles'),
'Access Lists' => t('Access Lists'), 'Lists' => t('Lists'),
'Notifications' => t('Notifications'), 'Notifications' => t('Notifications'),
'Order Apps' => t('Order Apps'), 'Order Apps' => t('Order Apps'),
'CalDAV' => t('CalDAV'), 'CalDAV' => t('CalDAV'),
@ -579,7 +583,8 @@ class Apps {
'$featured' => ((strpos($papp['categories'], 'nav_featured_app') === false) ? false : true), '$featured' => ((strpos($papp['categories'], 'nav_featured_app') === false) ? false : true),
'$pinned' => ((strpos($papp['categories'], 'nav_pinned_app') === false) ? false : true), '$pinned' => ((strpos($papp['categories'], 'nav_pinned_app') === false) ? false : true),
'$navapps' => (($mode === 'nav') ? true : false), '$navapps' => (($mode === 'nav') ? true : false),
'$order' => (($mode === 'nav-order') ? true : false), '$order' => (($mode === 'nav-order' || $mode === 'nav-order-pinned') ? true : false),
'$mode' => $mode,
'$add' => t('Add to app-tray'), '$add' => t('Add to app-tray'),
'$remove' => t('Remove from app-tray'), '$remove' => t('Remove from app-tray'),
'$add_nav' => t('Pin to navbar'), '$add_nav' => t('Pin to navbar'),
@ -921,8 +926,6 @@ class Apps {
if ($list) { if ($list) {
foreach ($list as $li) { foreach ($list as $li) {
$papp = self::app_encode($li); $papp = self::app_encode($li);
if ($menu !== 'nav_pinned_app' && strpos($papp['categories'],'nav_pinned_app') !== false)
continue;
$syslist[] = $papp; $syslist[] = $papp;
} }
} }
@ -970,9 +973,6 @@ class Apps {
if ($list) { if ($list) {
foreach ($list as $li) { foreach ($list as $li) {
$papp = self::app_encode($li); $papp = self::app_encode($li);
if ($menu !== 'nav_pinned_app' && strpos($papp['categories'],'nav_pinned_app') !== false) {
continue;
}
$syslist[] = $papp; $syslist[] = $papp;
} }
} }

View file

@ -2,6 +2,7 @@
namespace Zotlabs\Lib; namespace Zotlabs\Lib;
use App;
use Zotlabs\Access\Permissions; use Zotlabs\Access\Permissions;
use Zotlabs\Daemon\Master; use Zotlabs\Daemon\Master;
@ -24,6 +25,10 @@ class Connect {
$uid = $channel['channel_id']; $uid = $channel['channel_id'];
if (strpos($url,'@') === false && strpos($url,'/') === false) {
$url = $url . '@' . App::get_hostname();
}
$result = [ 'success' => false, 'message' => '' ]; $result = [ 'success' => false, 'message' => '' ];
$my_perms = false; $my_perms = false;
@ -37,7 +42,7 @@ class Connect {
} }
} }
if(! allowed_url($url)) { if (! check_siteallowed($url)) {
$result['message'] = t('Channel is blocked on this site.'); $result['message'] = t('Channel is blocked on this site.');
return $result; return $result;
} }
@ -76,6 +81,13 @@ class Connect {
// note: this is a single record and not an array of results // note: this is a single record and not an array of results
$r = Libzot::zot_record_preferred($r,'xchan_network'); $r = Libzot::zot_record_preferred($r,'xchan_network');
// Some Hubzilla records were originally stored as activitypub. If we find one, force rediscovery
// since Zap cannot connect with them.
if ($r['xchan_network'] === 'activitypub' && ! get_config('system','activitypub')) {
$r = null;
}
} }
@ -101,7 +113,6 @@ class Connect {
} }
} }
if ($wf || $d) { if ($wf || $d) {
// something was discovered - find the record which was just created. // something was discovered - find the record which was just created.
@ -135,13 +146,24 @@ class Connect {
return $result; return $result;
} }
// Now start processing the new connection if (! check_channelallowed($xchan_hash)) {
$result['message'] = t('Channel is blocked on this site.');
logger('follow: ' . $result['message']);
return $result;
}
$ap_allowed = get_config('system','activitypub',false) && get_pconfig($uid,'system','activitypub',true);
if ($r['xchan_network'] === 'activitypub') { if ($r['xchan_network'] === 'activitypub') {
// ActivityPub is not nomadic if (! $ap_allowed) {
$result['message'] = t('Protocol not supported'); $result['message'] = t('Protocol not supported');
return $result; return $result;
} }
$singleton = true;
}
// Now start processing the new connection
$aid = $channel['channel_account_id']; $aid = $channel['channel_account_id'];
$hash = $channel['channel_hash']; $hash = $channel['channel_hash'];
@ -172,8 +194,9 @@ class Connect {
// to negotiate a suitable permission response // to negotiate a suitable permission response
$p = get_abconfig($uid,$xchan_hash,'system','their_perms',EMPTY_STR); $p = get_abconfig($uid,$xchan_hash,'system','their_perms',EMPTY_STR);
if($p) if ($p) {
$p .= ','; $p .= ',';
}
$p .= 'view_stream,republish'; $p .= 'view_stream,republish';
set_abconfig($uid,$xchan_hash,'system','their_perms',$p); set_abconfig($uid,$xchan_hash,'system','their_perms',$p);

View file

@ -1,41 +0,0 @@
<?php
namespace Zotlabs\Lib;
class Discover {
private $resource = null;
private $resource_type = null;
private $webfinger = null;
private $zotinfo = null;
function run($resource) {
$this->resource = $resource;
$this->webfinger = webfinger_rfc7033($this->resource);
if(is_array($this->webfinger) && array_key_exists('links',$this->webfinger)) {
foreach($this->webfinger['links'] as $link) {
if(array_key_exists('rel',$link) && $link['rel'] === PROTOCOL_ZOT6) {
if(array_key_exists('href',$link) && $link['href'] !== EMPTY_STR) {
$headers = 'Accept: application/x-zot+json';
$redirects = 0;
$this->zotinfo = z_fetch_url($link['href'],true,$redirects,
[ 'headers' => [ $headers ]]
);
}
}
}
}
return [
'resource' => $this->resource,
'resource_type' => $this->resource_type,
'webfinger' => $this->webfinger,
'zotinfo' => $this->zotinfo
];
}
}

View file

@ -29,7 +29,7 @@ class LDSignatures {
$options = [ $options = [
'type' => 'RsaSignature2017', 'type' => 'RsaSignature2017',
'nonce' => random_string(64), 'nonce' => random_string(64),
'creator' => z_root() . '/channel/' . $channel['channel_address'] . '/public_key_pem', 'creator' => channel_url($channel),
'created' => datetime_convert('UTC','UTC', 'now', 'Y-m-d\Th:i:s\Z') 'created' => datetime_convert('UTC','UTC', 'now', 'Y-m-d\Th:i:s\Z')
]; ];
@ -110,7 +110,7 @@ class LDSignatures {
$data_type = 'application/activity+json'; $data_type = 'application/activity+json';
$encoding = 'base64url'; $encoding = 'base64url';
$algorithm = 'RSA-SHA256'; $algorithm = 'RSA-SHA256';
$keyhash = base64url_encode(z_root() . '/channel/' . $channel['channel_address']); $keyhash = base64url_encode(channel_url($channel));
$data = str_replace(array(" ","\t","\r","\n"),array("","","",""),$data); $data = str_replace(array(" ","\t","\r","\n"),array("","","",""),$data);
@ -126,7 +126,7 @@ class LDSignatures {
'meDataType' => $data_type, 'meDataType' => $data_type,
'meEncoding' => $encoding, 'meEncoding' => $encoding,
'meAlgorithm' => $algorithm, 'meAlgorithm' => $algorithm,
'meCreator' => z_root() . '/channel/' . $channel['channel_address'] . '/public_key_pem', 'meCreator' => channel_url($channel),
'meSignatureValue' => $signature 'meSignatureValue' => $signature
]); ]);

View file

@ -66,6 +66,14 @@ class Libprofile {
dbesc($nickname), dbesc($nickname),
dbesc($profile) dbesc($profile)
); );
if (! $p) {
$p = q("SELECT profile.uid AS profile_uid, profile.*, channel.* FROM profile
LEFT JOIN channel ON profile.uid = channel.channel_id
WHERE channel.channel_address = '%s' AND profile.id = %d LIMIT 1",
dbesc($nickname),
intval($profile)
);
}
} }
if (! $p) { if (! $p) {

View file

@ -399,6 +399,9 @@ class Libsync {
} }
$columns = db_columns('channel');
$disallowed = [ $disallowed = [
'channel_id', 'channel_account_id', 'channel_primary', 'channel_prvkey', 'channel_id', 'channel_account_id', 'channel_primary', 'channel_prvkey',
'channel_address', 'channel_notifyflags', 'channel_removed', 'channel_deleted', 'channel_address', 'channel_notifyflags', 'channel_removed', 'channel_deleted',
@ -409,19 +412,17 @@ class Libsync {
'channel_a_delegate', 'channel_moved' 'channel_a_delegate', 'channel_moved'
]; ];
$clean = array();
foreach($arr['channel'] as $k => $v) { foreach($arr['channel'] as $k => $v) {
if(in_array($k,$disallowed)) if (in_array($k,$disallowed)) {
continue;
}
if (! in_array($k,$columns)) {
continue; continue;
$clean[$k] = $v;
} }
if(count($clean)) {
foreach($clean as $k => $v) {
$r = dbq("UPDATE channel set " . dbesc($k) . " = '" . dbesc($v) $r = dbq("UPDATE channel set " . dbesc($k) . " = '" . dbesc($v)
. "' where channel_id = " . intval($channel['channel_id']) ); . "' where channel_id = " . intval($channel['channel_id']) );
} }
} }
}
if(array_key_exists('abook',$arr) && is_array($arr['abook']) && count($arr['abook'])) { if(array_key_exists('abook',$arr) && is_array($arr['abook']) && count($arr['abook'])) {
@ -853,11 +854,6 @@ class Libsync {
continue; continue;
} }
// Catch some malformed entries from the past which still exist
if(strpos($location['address'],'/') !== false)
$location['address'] = substr($location['address'],0,strpos($location['address'],'/'));
// match as many fields as possible in case anything at all changed. // match as many fields as possible in case anything at all changed.
$r = q("select * from hubloc where hubloc_hash = '%s' and hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_id_url = '%s' and hubloc_url = '%s' and hubloc_url_sig = '%s' and hubloc_site_id = '%s' and hubloc_host = '%s' and hubloc_addr = '%s' and hubloc_callback = '%s' and hubloc_sitekey = '%s' ", $r = q("select * from hubloc where hubloc_hash = '%s' and hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_id_url = '%s' and hubloc_url = '%s' and hubloc_url_sig = '%s' and hubloc_site_id = '%s' and hubloc_host = '%s' and hubloc_addr = '%s' and hubloc_callback = '%s' and hubloc_sitekey = '%s' ",

View file

@ -11,6 +11,7 @@ use App;
use Zotlabs\Web\HTTPSig; use Zotlabs\Web\HTTPSig;
use Zotlabs\Access\Permissions; use Zotlabs\Access\Permissions;
use Zotlabs\Access\PermissionLimits; use Zotlabs\Access\PermissionLimits;
use Zotlabs\Access\PermissionRoles;
use Zotlabs\Daemon\Master; use Zotlabs\Daemon\Master;
@ -322,13 +323,13 @@ class Libzot {
return false; return false;
} }
logger('zot-info: ' . print_r($record,true), LOGGER_DATA, LOG_DEBUG); logger('zot-info: ' . print_r($record,true), LOGGER_DATA, LOG_DEBUG);
$x = self::import_xchan($record['data'], (($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED)); $x = self::import_xchan($record['data'], (($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
if (! $x['success']) if (! $x['success']) {
return false; return false;
}
if ($channel && $record['data']['permissions']) { if ($channel && $record['data']['permissions']) {
$old_read_stream_perm = their_perms_contains($channel['channel_id'],$x['hash'],'view_stream'); $old_read_stream_perm = their_perms_contains($channel['channel_id'],$x['hash'],'view_stream');
@ -381,6 +382,19 @@ class Libzot {
} }
else { else {
// limit the ability to do connection spamming, this limit is per channel
$lim = intval(get_config('system','max_connections_per_day',50));
if ($lim) {
$n = q("select count(abook_id) as total from abook where abook_channel = %d and abook_created > '%s'",
intval($channel['channel_id']),
dbesc(datetime_convert('UTC','UTC','now - 24 hours'))
);
if ($n && intval($n['total']) > $lim) {
logger('channel: ' . $channel['channel_id'] . ' too many new connections per day. This one from ' . $hsig['signer'], LOGGER_NORMAL, LOG_WARNING);
return false;
}
}
$p = Permissions::connect_perms($channel['channel_id']); $p = Permissions::connect_perms($channel['channel_id']);
$my_perms = Permissions::serialise($p['perms']); $my_perms = Permissions::serialise($p['perms']);
@ -1169,6 +1183,14 @@ class Libzot {
if ($env['encoding'] === 'activitystreams') { if ($env['encoding'] === 'activitystreams') {
$AS = new ActivityStreams($data); $AS = new ActivityStreams($data);
if ($AS->is_valid() && $AS->type === 'Announce' && is_array($AS->obj)
&& array_key_exists('object',$AS->obj) && array_key_exists('actor',$AS->obj)) {
// This is a relayed/forwarded Activity (as opposed to a shared/boosted object)
// Reparse the encapsulated Activity and use that instead
logger('relayed activity',LOGGER_DEBUG);
$AS = new ActivityStreams($AS->obj);
}
if (! $AS->is_valid()) { if (! $AS->is_valid()) {
logger('Activity rejected: ' . print_r($data,true)); logger('Activity rejected: ' . print_r($data,true));
return; return;
@ -1289,8 +1311,8 @@ class Libzot {
$arr['owner_xchan'] = $env['sender']; $arr['owner_xchan'] = $env['sender'];
} }
if ($private) { if ($private && (! intval($arr['item_private']))) {
$arr['item_private'] = true; $arr['item_private'] = 1;
} }
if ($arr['mid'] === $arr['parent_mid']) { if ($arr['mid'] === $arr['parent_mid']) {
if (is_array($AS->obj) && array_key_exists('commentPolicy',$AS->obj)) { if (is_array($AS->obj) && array_key_exists('commentPolicy',$AS->obj)) {
@ -1523,7 +1545,8 @@ class Libzot {
* @brief * @brief
* *
* @param array $sender * @param array $sender
* @param array $arr * @param ActivityStreams object $act
* @param array $msg_arr
* @param array $deliveries * @param array $deliveries
* @param boolean $relay * @param boolean $relay
* @param boolean $public (optional) default false * @param boolean $public (optional) default false
@ -1535,6 +1558,8 @@ class Libzot {
$result = []; $result = [];
//logger('msg_arr: ' . print_r($msg_arr,true),LOGGER_ALL);
// If an upstream hop used ActivityPub, set the identities to zot6 nomadic identities where applicable // If an upstream hop used ActivityPub, set the identities to zot6 nomadic identities where applicable
// else things could easily get confused // else things could easily get confused
@ -1681,24 +1706,23 @@ class Libzot {
// Conversation fetches (e.g. $request == true) take place for // Conversation fetches (e.g. $request == true) take place for
// a) new comments on expired posts // a) new comments on expired posts
// b) hyperdrive (friend-of-friend) conversations // b) hyperdrive (friend-of-friend) conversations
// c) Repeats of posts by others
// over-ride normal connection permissions for hyperdrive (friend-of-friend) conversations // over-ride normal connection permissions for hyperdrive (friend-of-friend) conversations
// (if hyperdrive is enabled) and repeated posts by a friend. // (if hyperdrive is enabled).
// If $allowed is already true, this is probably the conversation of a direct friend or a // If $allowed is already true, this is probably the conversation of a direct friend or a
// conversation fetch for a new comment on an expired post // conversation fetch for a new comment on an expired post
// Comments of all these activities are allowed and will only be rejected (later) if the parent // Comments of all these activities are allowed and will only be rejected (later) if the parent
// doesn't exist. // doesn't exist.
// if ($perm === 'send_stream') { if ($perm === 'send_stream') {
// if (get_pconfig($channel['channel_id'],'system','hyperdrive',true) || $arr['verb'] === 'Announce') { if (get_pconfig($channel['channel_id'],'system','hyperdrive',false)) {
// $allowed = true;
// }
// }
// else {
$allowed = true; $allowed = true;
// } }
}
else {
$allowed = true;
}
$friendofriend = true; $friendofriend = true;
} }
@ -1876,10 +1900,11 @@ class Libzot {
// We need this line to ensure wall-to-wall comments are relayed (by falling through to the relay bit), // We need this line to ensure wall-to-wall comments are relayed (by falling through to the relay bit),
// and at the same time not relay any other relayable posts more than once, because to do so is very wasteful. // and at the same time not relay any other relayable posts more than once, because to do so is very wasteful.
if (! intval($r[0]['item_origin'])) if (! intval($r[0]['item_origin'])) {
continue; continue;
} }
} }
}
else { else {
$arr['aid'] = $channel['channel_account_id']; $arr['aid'] = $channel['channel_account_id'];
$arr['uid'] = $channel['channel_id']; $arr['uid'] = $channel['channel_id'];
@ -1967,9 +1992,6 @@ class Libzot {
if (get_pconfig($channel['channel_id'],'system','hyperdrive',true)) { if (get_pconfig($channel['channel_id'],'system','hyperdrive',true)) {
return true; return true;
} }
if ($item['verb'] === 'Announce' && get_pconfig($channel['channel_id'],'system','hyperdrive_announce',true)) {
return true;
}
return false; return false;
} }
@ -2006,6 +2028,14 @@ class Libzot {
foreach ($a['data']['orderedItems'] as $activity) { foreach ($a['data']['orderedItems'] as $activity) {
$AS = new ActivityStreams($activity); $AS = new ActivityStreams($activity);
if ($AS->is_valid() && $AS->type === 'Announce' && is_array($AS->obj)
&& array_key_exists('object',$AS->obj) && array_key_exists('actor',$AS->obj)) {
// This is a relayed/forwarded Activity (as opposed to a shared/boosted object)
// Reparse the encapsulated Activity and use that instead
logger('relayed activity',LOGGER_DEBUG);
$AS = new ActivityStreams($AS->obj);
}
if (! $AS->is_valid()) { if (! $AS->is_valid()) {
logger('FOF Activity rejected: ' . print_r($activity,true)); logger('FOF Activity rejected: ' . print_r($activity,true));
continue; continue;
@ -2236,7 +2266,7 @@ class Libzot {
$item_found = false; $item_found = false;
$post_id = 0; $post_id = 0;
$r = q("select id, author_xchan, owner_xchan, source_xchan, item_deleted from item where ( author_xchan = '%s' or owner_xchan = '%s' or source_xchan = '%s' ) $r = q("select * from item where ( author_xchan = '%s' or owner_xchan = '%s' or source_xchan = '%s' )
and mid = '%s' and uid = %d limit 1", and mid = '%s' and uid = %d limit 1",
dbesc($sender), dbesc($sender),
dbesc($sender), dbesc($sender),
@ -2246,11 +2276,12 @@ class Libzot {
); );
if ($r) { if ($r) {
if ($r[0]['author_xchan'] === $sender || $r[0]['owner_xchan'] === $sender || $r[0]['source_xchan'] === $sender) { $stored = $r[0];
if ($stored['author_xchan'] === $sender || $stored['owner_xchan'] === $sender || $stored['source_xchan'] === $sender) {
$ownership_valid = true; $ownership_valid = true;
} }
$post_id = $r[0]['id']; $post_id = $stored['id'];
$item_found = true; $item_found = true;
} }
else { else {
@ -2274,8 +2305,26 @@ class Libzot {
return false; return false;
} }
if ($stored['resource_type'] === 'event') {
$i = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
dbesc($stored['resource_id']),
intval($uid)
);
if ($i) {
if ($i[0]['event_xchan'] === $sender) {
q("delete from event where event_hash = '%s' and uid = %d",
dbesc($stored['resource_id']),
intval($uid)
);
}
else {
logger('delete linked event: not owner');
return;
}
}
}
if ($item_found) { if ($item_found) {
if (intval($r[0]['item_deleted'])) { if (intval($stored['item_deleted'])) {
logger('delete_imported_item: item was already deleted'); logger('delete_imported_item: item was already deleted');
if (! $relay) { if (! $relay) {
return false; return false;
@ -2288,10 +2337,10 @@ class Libzot {
// back, and we aren't going to (or shouldn't at any rate) delete it again in the future - so losing // back, and we aren't going to (or shouldn't at any rate) delete it again in the future - so losing
// this information from the metadata should have no other discernible impact. // this information from the metadata should have no other discernible impact.
if (($r[0]['id'] != $r[0]['parent']) && intval($r[0]['item_origin'])) { if (($stored['id'] != $stored['parent']) && intval($stored['item_origin'])) {
q("update item set item_origin = 0 where id = %d and uid = %d", q("update item set item_origin = 0 where id = %d and uid = %d",
intval($r[0]['id']), intval($stored['id']),
intval($r[0]['uid']) intval($stored['uid'])
); );
} }
} }
@ -2307,90 +2356,6 @@ class Libzot {
return $post_id; return $post_id;
} }
static function process_mail_delivery($sender, $arr, $deliveries) {
$result = array();
if ($sender != $arr['from_xchan']) {
logger('process_mail_delivery: sender is not mail author');
return;
}
foreach ($deliveries as $d) {
$DR = new DReport(z_root(),$sender,$d,$arr['mid']);
$r = q("select * from channel where channel_hash = '%s' limit 1",
dbesc($d['hash'])
);
if (! $r) {
$DR->update('recipient not found');
$result[] = $DR->get();
continue;
}
$channel = $r[0];
$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
if (! perm_is_allowed($channel['channel_id'],$sender,'post_mail')) {
/*
* Always allow somebody to reply if you initiated the conversation. It's anti-social
* and a bit rude to send a private message to somebody and block their ability to respond.
* If you are being harrassed and want to put an end to it, delete the conversation.
*/
$return = false;
if ($arr['parent_mid']) {
$return = q("select * from mail where mid = '%s' and channel_id = %d limit 1",
dbesc($arr['parent_mid']),
intval($channel['channel_id'])
);
}
if (! $return) {
logger("permission denied for mail delivery {$channel['channel_id']}");
$DR->update('permission denied');
$result[] = $DR->get();
continue;
}
}
$r = q("select id from mail where mid = '%s' and channel_id = %d limit 1",
dbesc($arr['mid']),
intval($channel['channel_id'])
);
if ($r) {
if (intval($arr['mail_recalled'])) {
$x = q("delete from mail where id = %d and channel_id = %d",
intval($r[0]['id']),
intval($channel['channel_id'])
);
$DR->update('mail recalled');
$result[] = $DR->get();
logger('mail_recalled');
}
else {
$DR->update('duplicate mail received');
$result[] = $DR->get();
logger('duplicate mail received');
}
continue;
}
else {
$arr['account_id'] = $channel['channel_account_id'];
$arr['channel_id'] = $channel['channel_id'];
$item_id = mail_store($arr);
$DR->update('mail delivered');
$result[] = $DR->get();
}
}
return $result;
}
/** /**
* @brief Processes delivery of profile. * @brief Processes delivery of profile.
@ -2935,15 +2900,10 @@ class Libzot {
// now all forums (public, restricted, and private) set the public_forum flag. So it really means "is a group" // now all forums (public, restricted, and private) set the public_forum flag. So it really means "is a group"
// and has nothing to do with accessibility. // and has nothing to do with accessibility.
$channel_type = 'normal';
$role = get_pconfig($e['channel_id'],'system','permissions_role'); $role = get_pconfig($e['channel_id'],'system','permissions_role');
if (in_array($role, ['forum','forum_restricted','repository'])) { $rolesettings = PermissionRoles::role_perms($role);
$channel_type = 'group';
} $channel_type = isset($rolesettings['channel_type']) ? $rolesettings['channel_type'] : 'normal';
if (in_array($role, ['collection','collection_restricted'])) {
$channel_type = 'collection';
}
// This is for birthdays and keywords, but must check access permissions // This is for birthdays and keywords, but must check access permissions
$p = q("select * from profile where uid = %d and is_default = 1", $p = q("select * from profile where uid = %d and is_default = 1",

View file

@ -108,7 +108,7 @@ class Libzotdir {
if($ret === false) { if($ret === false) {
$ret = get_config('directory', $setting); $ret = get_config('directory', $setting);
if($ret === false) { if($ret === false) {
$default = (in_array($setting,['globaldir','safemode']) ? 1 : 0); $ret = (in_array($setting,['globaldir','safemode']) ? 1 : 0);
} }
} }
@ -132,16 +132,18 @@ class Libzotdir {
$pubforums = self::get_directory_setting($observer, 'chantype'); $pubforums = self::get_directory_setting($observer, 'chantype');
$hide_local = intval(get_config('system','localdir_hide')); $hide_local = intval(get_config('system','localdir_hide'));
if($hide_local) if ($hide_local) {
$globaldir = 1; $globaldir = 1;
}
// Build urls without order and pubforums so it's easy to tack on the changed value // Build urls without order and pubforums so it's easy to tack on the changed value
// Probably there's an easier way to do this // Probably there's an easier way to do this
$directory_sort_order = get_config('system','directory_sort_order'); $directory_sort_order = get_config('system','directory_sort_order');
if(! $directory_sort_order) if (! $directory_sort_order) {
$directory_sort_order = 'date'; $directory_sort_order = 'date';
}
$current_order = (($_REQUEST['order']) ? $_REQUEST['order'] : $directory_sort_order); $current_order = (($_REQUEST['order']) ? $_REQUEST['order'] : $directory_sort_order);
$suggest = (($_REQUEST['suggest']) ? '&suggest=' . $_REQUEST['suggest'] : ''); $suggest = (($_REQUEST['suggest']) ? '&suggest=' . $_REQUEST['suggest'] : '');
@ -156,7 +158,8 @@ class Libzotdir {
unset($tmp['safe']); unset($tmp['safe']);
unset($tmp['req']); unset($tmp['req']);
unset($tmp['f']); unset($tmp['f']);
$forumsurl = $url . http_build_query($tmp) . $suggest; $q = http_build_query($tmp);
$forumsurl = $url . (($q) ? '&' . $q : '') . $suggest;
$o = replace_macros(get_markup_template('dir_sort_links.tpl'), [ $o = replace_macros(get_markup_template('dir_sort_links.tpl'), [
'$header' => t('Directory Options'), '$header' => t('Directory Options'),

View file

@ -236,7 +236,7 @@ class Queue {
$headers = []; $headers = [];
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ; $headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ;
$ret = $outq['outq_msg']; $ret = $outq['outq_msg'];
logger('ActivityPub send: ' . $ret, LOGGER_DATA); logger('ActivityPub send: ' . jindent($ret), LOGGER_DATA);
$headers['Digest'] = HTTPSig::generate_digest_header($ret); $headers['Digest'] = HTTPSig::generate_digest_header($ret);
$headers['(request-target)'] = 'post ' . get_request_string($outq['outq_posturl']); $headers['(request-target)'] = 'post ' . get_request_string($outq['outq_posturl']);

View file

@ -95,7 +95,7 @@ class Share {
$is_photo = (($this->item['obj_type'] === ACTIVITY_OBJ_PHOTO) ? true : false); $is_photo = (($this->item['obj_type'] === ACTIVITY_OBJ_PHOTO) ? true : false);
if($is_photo) { if($is_photo) {
$object = json_decode($this->item['obj'],true); $object = json_decode($this->item['obj'],true);
$photo_bb = $object['body']; $photo_bb = (($object['source']) ? $object['source']['content'] : $object['body']);
} }
if (strpos($this->item['body'], "[/share]") !== false) { if (strpos($this->item['body'], "[/share]") !== false) {
@ -107,7 +107,7 @@ class Share {
"' portable_id='" . $this->item['author']['xchan_hash'] . "' portable_id='" . $this->item['author']['xchan_hash'] .
"' avatar='" . $this->item['author']['xchan_photo_s'] . "' avatar='" . $this->item['author']['xchan_photo_s'] .
"' link='" . $this->item['plink'] . "' link='" . $this->item['plink'] .
"' auth='" . (($this->item['author']['network'] === 'zot') ? 'true' : 'false') . "' auth='" . (($this->item['author']['network'] === 'zot6') ? 'true' : 'false') .
"' posted='" . $this->item['created'] . "' posted='" . $this->item['created'] .
"' message_id='" . $this->item['mid'] . "' message_id='" . $this->item['mid'] .
"']"; "']";

View file

@ -1,127 +0,0 @@
<?php
namespace Zotlabs\Lib;
/**
* @brief wrapper for z_fetch_url() which can be instantiated with several built-in parameters and
* these can be modified and re-used. Useful for CalDAV and other processes which need to authenticate
* and set lots of CURL options (many of which stay the same from one call to the next).
*/
class SuperCurl {
private $auth;
private $url;
private $curlopt = array();
private $headers = null;
public $filepos = 0;
public $filehandle = 0;
public $request_data = '';
private $request_method = 'GET';
private $upload = false;
private $cookies = false;
private function set_data($s) {
$this->request_data = $s;
$this->filepos = 0;
}
public function curl_read($ch,$fh,$size) {
if($this->filepos < 0) {
unset($fh);
return '';
}
$s = substr($this->request_data,$this->filepos,$size);
if(strlen($s) < $size)
$this->filepos = (-1);
else
$this->filepos = $this->filepos + $size;
return $s;
}
public function __construct($opts = array()) {
$this->set($opts);
}
private function set($opts = array()) {
if($opts) {
foreach($opts as $k => $v) {
switch($k) {
case 'http_auth':
$this->auth = $v;
break;
case 'magicauth':
// currently experimental
$this->magicauth = $v;
\Zotlabs\Daemon\Master::Summon([ 'CurlAuth', $v ]);
break;
case 'custom':
$this->request_method = $v;
break;
case 'url':
$this->url = $v;
break;
case 'data':
$this->set_data($v);
if($v) {
$this->upload = true;
}
else {
$this->upload = false;
}
break;
case 'headers':
$this->headers = $v;
break;
default:
$this->curlopts[$k] = $v;
break;
}
}
}
}
function exec() {
$opts = $this->curlopts;
$url = $this->url;
if($this->auth)
$opts['http_auth'] = $this->auth;
if($this->magicauth) {
$opts['cookiejar'] = 'store/[data]/cookie_' . $this->magicauth;
$opts['cookiefile'] = 'store/[data]/cookie_' . $this->magicauth;
$opts['cookie'] = 'PHPSESSID=' . trim(file_get_contents('store/[data]/cookien_' . $this->magicauth));
$c = channelx_by_n($this->magicauth);
if($c)
$url = zid($this->url,channel_reddress($c));
}
if($this->custom)
$opts['custom'] = $this->custom;
if($this->headers)
$opts['headers'] = $this->headers;
if($this->upload) {
$opts['upload'] = true;
$opts['infile'] = $this->filehandle;
$opts['infilesize'] = strlen($this->request_data);
$opts['readfunc'] = [ $this, 'curl_read' ] ;
}
$recurse = 0;
return z_fetch_url($this->url,true,$recurse,(($opts) ? $opts : null));
}
}

View file

@ -31,7 +31,7 @@ class System {
if(is_array(App::$config) && is_array(App::$config['system']) && array_key_exists('icon',App::$config['system'])) { if(is_array(App::$config) && is_array(App::$config['system']) && array_key_exists('icon',App::$config['system'])) {
return App::$config['system']['icon']; return App::$config['system']['icon'];
} }
return z_root() . '/images/z-64.png'; return z_root() . '/images/z2-64.png';
} }
@ -68,7 +68,7 @@ class System {
static public function get_project_link() { static public function get_project_link() {
if(is_array(App::$config) && is_array(App::$config['system']) && App::$config['system']['project_link']) if(is_array(App::$config) && is_array(App::$config['system']) && App::$config['system']['project_link'])
return App::$config['system']['project_link']; return App::$config['system']['project_link'];
return 'https://framagit.org/zot/zap'; return 'https://zotlabs.com/zap';
} }
static public function get_project_srclink() { static public function get_project_srclink() {

View file

@ -2,6 +2,8 @@
namespace Zotlabs\Lib; namespace Zotlabs\Lib;
use App;
require_once('include/text.php'); require_once('include/text.php');
/** /**
@ -36,9 +38,9 @@ class ThreadItem {
$this->data = $data; $this->data = $data;
$this->toplevel = ($this->get_id() == $this->get_data_value('parent')); $this->toplevel = ($this->get_id() == $this->get_data_value('parent'));
$this->threaded = get_config('system','thread_allow',((defined('NOMADIC')) ? false : true)); $this->threaded = get_config('system','thread_allow',true);
$observer = \App::get_observer(); $observer = App::get_observer();
// Prepare the children // Prepare the children
if($data['children']) { if($data['children']) {
@ -48,7 +50,7 @@ class ThreadItem {
* Only add those that will be displayed * Only add those that will be displayed
*/ */
if((! visible_activity($item)) || array_key_exists('blocked',$item)) { if(! visible_activity($item)) {
continue; continue;
} }
@ -116,7 +118,7 @@ class ThreadItem {
// logger('parent: ' . $item['thr_parent']); // logger('parent: ' . $item['thr_parent']);
} }
$lock = ((($item['item_private'] == 1) || (($item['uid'] == local_channel()) && (strlen($item['allow_cid']) || strlen($item['allow_gid']) $lock = (((intval($item['item_private'])) || (($item['uid'] == local_channel()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
|| strlen($item['deny_cid']) || strlen($item['deny_gid'])))) || strlen($item['deny_cid']) || strlen($item['deny_gid']))))
? t('Private Message') ? t('Private Message')
: false); : false);
@ -132,7 +134,7 @@ class ThreadItem {
$privacy_warning = true; $privacy_warning = true;
} }
if(($item['item_private'] == 1) && ($item['owner']['xchan_network'] === 'activitypub')) { if(intval($item['item_private']) && ($item['owner']['xchan_network'] === 'activitypub')) {
$recips = get_iconfig($item['parent'], 'activitypub', 'recips'); $recips = get_iconfig($item['parent'], 'activitypub', 'recips');
@ -193,7 +195,6 @@ class ThreadItem {
$drop = [ 'dropping' => true, 'delete' => t('Admin Delete') ]; $drop = [ 'dropping' => true, 'delete' => t('Admin Delete') ];
} }
// FIXME
if($observer_is_pageowner) { if($observer_is_pageowner) {
$multidrop = array( $multidrop = array(
'select' => t('Select'), 'select' => t('Select'),
@ -215,9 +216,8 @@ class ThreadItem {
$canvote = false; $canvote = false;
// process action responses - e.g. like/dislike/attend/agree/whatever // process action responses - e.g. like/dislike/attend/agree/whatever
$response_verbs = array('like'); $response_verbs = [ 'like', 'dislike' ];
// if(feature_enabled($conv->get_profile_owner(),'dislike'))
$response_verbs[] = 'dislike';
if($item['obj_type'] === ACTIVITY_OBJ_EVENT) { if($item['obj_type'] === ACTIVITY_OBJ_EVENT) {
$response_verbs[] = 'attendyes'; $response_verbs[] = 'attendyes';
$response_verbs[] = 'attendno'; $response_verbs[] = 'attendno';
@ -239,9 +239,6 @@ class ThreadItem {
} }
} }
// if(! feature_enabled($conv->get_profile_owner(),'dislike'))
// unset($conv_responses['dislike']);
$responses = get_responses($conv_responses,$response_verbs,$this,$item); $responses = get_responses($conv_responses,$response_verbs,$this,$item);
$my_responses = []; $my_responses = [];
@ -257,19 +254,29 @@ class ThreadItem {
} else { } else {
$like_list_part = ''; $like_list_part = '';
} }
if(get_config('system','show_like_counts',true)) {
$like_button_label = tt('Like','Likes',$like_count,'noun'); $like_button_label = tt('Like','Likes',$like_count,'noun');
}
else {
$like_button_label = t('Likes','noun');
}
// if (feature_enabled($conv->get_profile_owner(),'dislike')) {
$dislike_count = ((x($conv_responses['dislike'],$item['mid'])) ? $conv_responses['dislike'][$item['mid']] : ''); $dislike_count = ((x($conv_responses['dislike'],$item['mid'])) ? $conv_responses['dislike'][$item['mid']] : '');
$dislike_list = ((x($conv_responses['dislike'],$item['mid'])) ? $conv_responses['dislike'][$item['mid'] . '-l'] : ''); $dislike_list = ((x($conv_responses['dislike'],$item['mid'])) ? $conv_responses['dislike'][$item['mid'] . '-l'] : '');
if(get_config('system','show_like_counts',true)) {
$dislike_button_label = tt('Dislike','Dislikes',$dislike_count,'noun'); $dislike_button_label = tt('Dislike','Dislikes',$dislike_count,'noun');
}
else {
$dislike_button_label = t('Dislikes','noun');
}
if (($dislike_list) && (count($dislike_list) > MAX_LIKERS)) { if (($dislike_list) && (count($dislike_list) > MAX_LIKERS)) {
$dislike_list_part = array_slice($dislike_list, 0, MAX_LIKERS); $dislike_list_part = array_slice($dislike_list, 0, MAX_LIKERS);
array_push($dislike_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#dislikeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>'); array_push($dislike_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#dislikeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
} else { } else {
$dislike_list_part = ''; $dislike_list_part = '';
} }
// }
$showlike = ((x($conv_responses['like'],$item['mid'])) ? format_like($conv_responses['like'][$item['mid']],$conv_responses['like'][$item['mid'] . '-l'],'like',$item['mid']) : ''); $showlike = ((x($conv_responses['like'],$item['mid'])) ? format_like($conv_responses['like'][$item['mid']],$conv_responses['like'][$item['mid'] . '-l'],'like',$item['mid']) : '');
$showdislike = ((x($conv_responses['dislike'],$item['mid'])) $showdislike = ((x($conv_responses['dislike'],$item['mid']))
@ -284,7 +291,6 @@ class ThreadItem {
$this->check_wall_to_wall(); $this->check_wall_to_wall();
if($this->is_toplevel()) { if($this->is_toplevel()) {
// FIXME check this permission
if(($conv->get_profile_owner() == local_channel()) && (! array_key_exists('real_uid',$item))) { if(($conv->get_profile_owner() == local_channel()) && (! array_key_exists('real_uid',$item))) {
$star = array( $star = array(
@ -304,8 +310,6 @@ class ThreadItem {
$unverified = '' ; // (($this->is_wall_to_wall() && (! intval($item['item_verified']))) ? t('Message cannot be verified') : ''); $unverified = '' ; // (($this->is_wall_to_wall() && (! intval($item['item_verified']))) ? t('Message cannot be verified') : '');
// FIXME - check this permission
if($conv->get_profile_owner() == local_channel()) { if($conv->get_profile_owner() == local_channel()) {
$tagger = array( $tagger = array(
'tagit' => t("Add Tag"), 'tagit' => t("Add Tag"),
@ -443,7 +447,9 @@ class ThreadItem {
'event' => $body['event'], 'event' => $body['event'],
'has_tags' => $has_tags, 'has_tags' => $has_tags,
'reactions' => $this->reactions, 'reactions' => $this->reactions,
// Item toolbar buttons // Item toolbar buttons
'emojis' => (($this->is_toplevel() && $this->is_commentable() && $observer) ? '1' : ''), 'emojis' => (($this->is_toplevel() && $this->is_commentable() && $observer) ? '1' : ''),
'like' => $like, 'like' => $like,
'dislike' => $dislike, 'dislike' => $dislike,
@ -456,10 +462,11 @@ class ThreadItem {
'tagger' => ((feature_enabled($conv->get_profile_owner(),'commtag')) ? $tagger : ''), 'tagger' => ((feature_enabled($conv->get_profile_owner(),'commtag')) ? $tagger : ''),
'filer' => ((feature_enabled($conv->get_profile_owner(),'filing')) ? $filer : ''), 'filer' => ((feature_enabled($conv->get_profile_owner(),'filing')) ? $filer : ''),
'bookmark' => (($conv->get_profile_owner() == local_channel() && local_channel() && $has_bookmarks) ? t('Save Bookmarks') : ''), 'bookmark' => (($conv->get_profile_owner() == local_channel() && local_channel() && $has_bookmarks) ? t('Save Bookmarks') : ''),
'addtocal' => (($has_event) ? t('Add to Calendar') : ''), 'addtocal' => (($has_event && ! $item['resource_id']) ? t('Add to Calendar') : ''),
'drop' => $drop, 'drop' => $drop,
'multidrop' => ((feature_enabled($conv->get_profile_owner(),'multi_delete')) ? $multidrop : ''), 'multidrop' => ((feature_enabled($conv->get_profile_owner(),'multi_delete')) ? $multidrop : ''),
'dropdown_extras' => $dropdown_extras, 'dropdown_extras' => $dropdown_extras,
// end toolbar buttons // end toolbar buttons
'unseen_comments' => $unseen_comments, 'unseen_comments' => $unseen_comments,
@ -476,7 +483,7 @@ class ThreadItem {
'like_modal_title' => t('Likes','noun'), 'like_modal_title' => t('Likes','noun'),
'dislike_modal_title' => t('Dislikes','noun'), 'dislike_modal_title' => t('Dislikes','noun'),
'dislike_count' => $dislike_count, 'dislike_count' => $dislike_count,
'dislike_list' => $dislkie_list, 'dislike_list' => $dislike_list,
'dislike_list_part' => $dislike_list_part, 'dislike_list_part' => $dislike_list_part,
'dislike_button_label' => $dislike_button_label, 'dislike_button_label' => $dislike_button_label,
'modal_dismiss' => t('Close'), 'modal_dismiss' => t('Close'),
@ -487,7 +494,8 @@ class ThreadItem {
'preview_lbl' => t('This is an unsaved preview'), 'preview_lbl' => t('This is an unsaved preview'),
'wait' => t('Please wait'), 'wait' => t('Please wait'),
'submid' => str_replace(['+','='], ['',''], base64_encode($item['mid'])), 'submid' => str_replace(['+','='], ['',''], base64_encode($item['mid'])),
'thread_level' => $thread_level 'thread_level' => $thread_level,
'thread_max' => intval(get_config('system','thread_maxlevel',2)) + 1
); );
$arr = array('item' => $item, 'output' => $tmp_item); $arr = array('item' => $item, 'output' => $tmp_item);
@ -495,23 +503,50 @@ class ThreadItem {
$result = $arr['output']; $result = $arr['output'];
$censored = false; $censored = ((strpos($body['html'],"<button id=\"nsfw-wrap-") !== false && $collapse_all === false) ? true : false);
if(strpos($body['html'],"<button id=\"nsfw-wrap-") !== false && $collapse_all === false) {
$censored = true;
}
$result['children'] = []; $result['children'] = [];
if (get_config('system','activitypub') && local_channel() && get_pconfig(local_channel(),'system','activitypub',true)) {
// place to store all the author addresses (links if not available) in the thread so we can auto-mention them in JS. // place to store all the author addresses (links if not available) in the thread so we can auto-mention them in JS.
$result['authors'] = []; $result['authors'] = [];
$add_top_author = true; // fix to add in sub-replies if replying to a comment on your own post from the top level.
if ($observer && ($profile_addr === $observer['xchan_hash'] || $profile_addr === $observer['xchan_addr'])) { if ($observer && ($profile_addr === $observer['xchan_hash'] || $profile_addr === $observer['xchan_addr'])) {
$add_top_author = false; // ignore it
} }
if($add_top_author && (! defined('NOMADIC'))) { else {
$result['authors'][] = $profile_addr; $result['authors'][] = $profile_addr;
} }
if ($children) {
foreach ($children as $child) {
$cdata = $child->get_data();
if ($cdata['author']['xchan_addr']) {
if (! in_array($cdata['author']['xchan_addr'],$result['authors'])) {
$result['authors'][] = $cdata['author']['xchan_addr'];
}
}
}
}
// Add any mentions from the immediate parent, unless they are mentions of the current viewer or duplicates
if ($item['term']) {
foreach ($item['term'] as $t) {
if ($t['ttype'] == TERM_MENTION) {
if (strpos($t['term'],'@') !== false) {
if ($observer && $t['term'] !== $observer['xchan_addr'] && ! in_array($t['term'],$result['authors'])) {
$result['authors'][] = $t['term'];
}
}
else {
$url = ((($position = strpos($t['url'],'url=')) !== false) ? urldecode(substr($t['url'],$position + 4)) : $t['url']);
if ($observer && $url !== $observer['xchan_url'] && ! in_array($url,$result['authors'])) {
$result['authors'][] = $url;
}
}
}
}
}
}
$nb_children = count($children); $nb_children = count($children);
@ -528,15 +563,6 @@ class ThreadItem {
if(strpos($xz['body'],"<button id=\"nsfw-wrap-") !== false && $collapse_all === false) { if(strpos($xz['body'],"<button id=\"nsfw-wrap-") !== false && $collapse_all === false) {
$censored = true; $censored = true;
} }
$author = $child->get_author();
if($author && ! in_array($author,$result['authors'])) {
if($observer && ($author === $observer['xchan_hash'] || $author === $observer['xchan_addr'])) {
// do nothing
}
elseif(! defined('NOMADIC')) {
$result['authors'][] = $author;
}
}
$result['children'][] = $xz; $result['children'][] = $xz;
} }
// Collapse // Collapse
@ -553,14 +579,6 @@ class ThreadItem {
} }
} }
if(count($result['authors']) > 6) {
$slice = array_slice($result['authors'],0,3);
$slice2 = array_slice($result['authors'],-3,3);
$result['authors'] = array_merge($slice,$slice2);
}
//logger('authors: ' . print_r($result['authors'],true));
$result['private'] = $item['item_private']; $result['private'] = $item['item_private'];
$result['toplevel'] = ($this->is_toplevel() ? 'toplevel_item' : ''); $result['toplevel'] = ($this->is_toplevel() ? 'toplevel_item' : '');
@ -637,6 +655,7 @@ class ThreadItem {
logger('[WARN] Item::add_child : Item already exists ('. $item->get_id() .').', LOGGER_DEBUG); logger('[WARN] Item::add_child : Item already exists ('. $item->get_id() .').', LOGGER_DEBUG);
return false; return false;
} }
/* /*
* Only add what will be displayed * Only add what will be displayed
*/ */
@ -653,6 +672,7 @@ class ThreadItem {
/** /**
* Get a child by its ID * Get a child by its ID
*/ */
public function get_child($id) { public function get_child($id) {
foreach($this->get_children() as $child) { foreach($this->get_children() as $child) {
if($child->get_id() == $id) if($child->get_id() == $id)
@ -664,6 +684,7 @@ class ThreadItem {
/** /**
* Get all our children * Get all our children
*/ */
public function get_children() { public function get_children() {
return $this->children; return $this->children;
} }
@ -683,6 +704,7 @@ class ThreadItem {
/** /**
* Remove our parent * Remove our parent
*/ */
protected function remove_parent() { protected function remove_parent() {
$this->parent = null; $this->parent = null;
$this->conversation = null; $this->conversation = null;
@ -691,6 +713,7 @@ class ThreadItem {
/** /**
* Remove a child * Remove a child
*/ */
public function remove_child($item) { public function remove_child($item) {
$id = $item->get_id(); $id = $item->get_id();
foreach($this->get_children() as $key => $child) { foreach($this->get_children() as $key => $child) {
@ -803,7 +826,7 @@ class ThreadItem {
$total = count($children); $total = count($children);
if($total > 0) { if($total > 0) {
foreach($children as $child) { foreach($children as $child) {
if((! visible_activity($child->data)) || array_key_exists('blocked',$child->data)) { if(! visible_activity($child->data)) {
continue; continue;
} }
if(! array_key_exists('sequence',$this->data)) { if(! array_key_exists('sequence',$this->data)) {
@ -822,7 +845,7 @@ class ThreadItem {
if($total > 0) { if($total > 0) {
$total = 0; $total = 0;
foreach($children as $child) { foreach($children as $child) {
if((! visible_activity($child->data)) || array_key_exists('author_blocked',$child->data)) { if(! visible_activity($child->data)) {
continue; continue;
} }
if(intval($child->data['item_unseen'])) if(intval($child->data['item_unseen']))
@ -849,7 +872,7 @@ class ThreadItem {
*/ */
private function get_comment_box($indent) { private function get_comment_box($indent) {
if(!$this->is_toplevel() && !get_config('system','thread_allow',((defined('NOMADIC')) ? false : true))) { if(!$this->is_toplevel() && !get_config('system','thread_allow',true)) {
return ''; return '';
} }
@ -885,7 +908,7 @@ class ThreadItem {
'$myphoto' => $observer['xchan_photo_s'], '$myphoto' => $observer['xchan_photo_s'],
'$comment' => t('Comment'), '$comment' => t('Comment'),
'$submit' => t('Submit'), '$submit' => t('Submit'),
'$edat' => ((defined('NOMADIC')) ? '' : t('Add Conversation Mentions')), '$edat' => EMPTY_STR,
'$edbold' => t('Bold'), '$edbold' => t('Bold'),
'$editalic' => t('Italic'), '$editalic' => t('Italic'),
'$eduline' => t('Underline'), '$eduline' => t('Underline'),
@ -895,13 +918,13 @@ class ThreadItem {
'$edatt' => t('Attach/Upload file'), '$edatt' => t('Attach/Upload file'),
'$edurl' => t('Insert Link'), '$edurl' => t('Insert Link'),
'$edvideo' => t('Video'), '$edvideo' => t('Video'),
'$preview' => t('Preview'), // ((feature_enabled($conv->get_profile_owner(),'preview')) ? t('Preview') : ''), '$preview' => t('Preview'),
'$indent' => $indent, '$indent' => $indent,
'$can_upload' => (perm_is_allowed($conv->get_profile_owner(),get_observer_hash(),'write_storage') && $conv->is_uploadable()), '$can_upload' => (perm_is_allowed($conv->get_profile_owner(),get_observer_hash(),'write_storage') && $conv->is_uploadable()),
'$feature_encrypt' => ((feature_enabled($conv->get_profile_owner(),'content_encrypt')) ? true : false), '$feature_encrypt' => ((feature_enabled($conv->get_profile_owner(),'content_encrypt')) ? true : false),
'$encrypt' => t('Encrypt text'), '$encrypt' => t('Encrypt text'),
'$cipher' => $conv->get_cipher(), '$cipher' => $conv->get_cipher(),
'$sourceapp' => \App::$sourcename, '$sourceapp' => App::$sourcename,
'$observer' => get_observer_hash(), '$observer' => get_observer_hash(),
'$anoncomments' => ((($conv->get_mode() === 'channel' || $conv->get_mode() === 'display') && perm_is_allowed($conv->get_profile_owner(),'','post_comments')) ? true : false), '$anoncomments' => ((($conv->get_mode() === 'channel' || $conv->get_mode() === 'display') && perm_is_allowed($conv->get_profile_owner(),'','post_comments')) ? true : false),
'$anonname' => [ 'anonname', t('Your full name (required)') ], '$anonname' => [ 'anonname', t('Your full name (required)') ],
@ -936,7 +959,45 @@ class ThreadItem {
$this->owner_name = $this->data['owner']['xchan_name']; $this->owner_name = $this->data['owner']['xchan_name'];
$this->wall_to_wall = true; $this->wall_to_wall = true;
} }
// present friend-of-friend conversations from hyperdrive as relayed posts from the first friend
// we find among the respondents.
if ($this->is_toplevel() && (! $this->data['owner']['abook_id'])) {
if ($this->data['children']) {
$friend = $this->find_a_friend($this->data['children']);
if ($friend) {
$this->owner_url = $friend['url'];
$this->owner_photo = $friend['photo'];
$this->owner_name = $friend['name'];
$this->wall_to_wall = true;
} }
}
}
}
private function find_a_friend($items) {
$ret = null;
if ($items) {
foreach ($items as $child) {
if ($child['author']['abook_id'] && (! intval($child['author']['abook_self']))) {
return [
'url' => chanlink_hash($child['author']['xchan_hash']),
'photo' => $child['author']['xchan_photo_m'],
'name' => $child['author']['xchan_name']
];
if ($child['children']) {
$ret = $this->find_a_friend($child['children']);
if ($ret) {
break;
}
}
}
}
}
return $ret;
}
private function is_wall_to_wall() { private function is_wall_to_wall() {
return $this->wall_to_wall; return $this->wall_to_wall;

View file

@ -86,6 +86,8 @@ class Acl extends \Zotlabs\Web\Controller {
$sql_extra = " AND pgrp.gname LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " "; $sql_extra = " AND pgrp.gname LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ";
$sql_extra2 = "AND ( xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'%" . dbesc(punify($search)) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . ") "; $sql_extra2 = "AND ( xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'%" . dbesc(punify($search)) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . ") ";
// This horrible mess is needed because position also returns 0 if nothing is found. // This horrible mess is needed because position also returns 0 if nothing is found.
// Would be MUCH easier if it instead returned a very large value // Would be MUCH easier if it instead returned a very large value
// Otherwise we could just // Otherwise we could just
@ -96,11 +98,14 @@ class Acl extends \Zotlabs\Web\Controller {
. " then POSITION('" . protect_sprintf(dbesc($search)) . " then POSITION('" . protect_sprintf(dbesc($search))
. "' IN xchan_name) else position('" . protect_sprintf(dbesc(punify($search))) . "' IN xchan_addr) end, "; . "' IN xchan_name) else position('" . protect_sprintf(dbesc(punify($search))) . "' IN xchan_addr) end, ";
$sql_extra3 = "AND ( xchan_addr like " . protect_sprintf( "'%" . dbesc(punify($search)) . "%'" ) . " OR xchan_name like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ) "; $sql_extra3 = "AND ( xchan_addr like " . protect_sprintf( "'%" . dbesc(punify($search)) . "%'" ) . " OR ( xchan_name like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR abook_alias like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " )) ";
$sql_extra4 = "AND ( xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'%" . dbesc(punify($search)) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . " OR abook_alias LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'") . ") ";
} }
else { else {
$sql_extra = $sql_extra2 = $sql_extra3 = ""; $sql_extra = $sql_extra2 = $sql_extra3 = $sql_extra4 = "";
} }
@ -145,14 +150,14 @@ class Acl extends \Zotlabs\Web\Controller {
if($r) { if($r) {
foreach($r as $g){ foreach($r as $g){
// logger('acl: group: ' . $g['gname'] . ' members: ' . AccessList::members_xchan($g['id'])); // logger('acl: group: ' . $g['gname'] . ' members: ' . AccessList::members_xchan(local_channel(),$g['id']));
$groups[] = array( $groups[] = array(
"type" => "g", "type" => "g",
"photo" => "images/twopeople.png", "photo" => "images/twopeople.png",
"name" => $g['gname'], "name" => $g['gname'],
"id" => $g['id'], "id" => $g['id'],
"xid" => $g['hash'], "xid" => $g['hash'],
"uids" => AccessList::members_xchan($g['id']), "uids" => AccessList::members_xchan(local_channel(),$g['id']),
"link" => '' "link" => ''
); );
} }
@ -217,10 +222,11 @@ class Acl extends \Zotlabs\Web\Controller {
$r = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, xchan_type, abook_flags, abook_self $r = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, xchan_type, abook_flags, abook_self
FROM abook left join xchan on abook_xchan = xchan_hash FROM abook left join xchan on abook_xchan = xchan_hash
WHERE (abook_channel = %d $extra_channels_sql) AND abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc" , WHERE (abook_channel = %d $extra_channels_sql) AND abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 $sql_extra4 order by xchan_name asc" ,
intval(local_channel()) intval(local_channel())
); );
if($r2)
if($r && $r2)
$r = array_merge($r2,$r); $r = array_merge($r2,$r);
} }
@ -318,7 +324,7 @@ class Acl extends \Zotlabs\Web\Controller {
$contacts[] = array( $contacts[] = array(
"photo" => $g['photo'], "photo" => $g['photo'],
"name" => $g['name'], "name" => $g['name'],
"nick" => $g['address'] "nick" => $g['address'],
); );
} }
} }
@ -419,6 +425,8 @@ class Acl extends \Zotlabs\Web\Controller {
$address = true; $address = true;
} }
$remote_dir = false;
if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) { if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
$url = z_root() . '/dirsearch'; $url = z_root() . '/dirsearch';
} }
@ -426,6 +434,7 @@ class Acl extends \Zotlabs\Web\Controller {
if(! $url) { if(! $url) {
$directory = Libzotdir::find_upstream_directory($dirmode); $directory = Libzotdir::find_upstream_directory($dirmode);
$url = $directory['url'] . '/dirsearch'; $url = $directory['url'] . '/dirsearch';
$remote_dir = true;
} }
$token = get_config('system','realm_token'); $token = get_config('system','realm_token');
@ -440,11 +449,41 @@ class Acl extends \Zotlabs\Web\Controller {
$t = 0; $t = 0;
$j = json_decode($x['body'],true); $j = json_decode($x['body'],true);
if($j && $j['results']) { if($j && $j['results']) {
return $j['results']; $results = $j['results'];
} }
} }
} }
return array();
if($remote_dir) {
$query = z_root() . '/dirsearch' . '?f=&navsearch=1' . (($token) ? '&t=' . urlencode($token) : '');
$query .= '&name=' . urlencode($search) . "&limit=$count" . (($address) ? '&address=' . urlencode(punify($search)) : '');
$x = z_fetch_url($query);
if($x['success']) {
$t = 0;
$j = json_decode($x['body'],true);
if($j && $j['results']) {
$results2 = $j['results'];
}
}
}
if($results2 && $results) {
foreach($results2 as $x) {
$found = false;
foreach($results as $y) {
if($y['url'] === $x['url']) {
$found = true;
}
}
if (! $found) {
$x['local'] = true;
$results[] = $x;
}
}
}
return $results;
} }
} }

View file

@ -1,25 +1,56 @@
<?php <?php
namespace Zotlabs\Module; namespace Zotlabs\Module;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\ActivityStreams; use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\Activity as ZActivity; use Zotlabs\Lib\Activity as ZlibActivity;
class Activity extends \Zotlabs\Web\Controller { class Activity extends Controller {
function init() { function init() {
if (ActivityStreams::is_as_request()) { if (ActivityStreams::is_as_request()) {
$item_id = argv(1); $item_id = argv(1);
if(! $item_id)
if (! $item_id) {
return; return;
}
$ob_authorise = false;
$item_uid = 0;
$bear = ZlibActivity::token_from_request();
if ($bear) {
logger('bear: ' . $bear, LOGGER_DEBUG);
$t = q("select item.uid, iconfig.v from iconfig left join item on iid = item.id where cat = 'ocap' and item.uuid = '%s'",
dbesc($item_id)
);
if ($t) {
foreach ($t as $token) {
if ($token['v'] === $bear) {
$ob_authorize = true;
$item_uid = $token['uid'];
break;
}
}
}
}
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0
and item.item_delayed = 0 and item.item_blocked = 0 "; and item.item_delayed = 0 and item.item_blocked = 0 ";
$sql_extra = item_permissions_sql(0); // if passed an owner_id of 0 to item_permissions_sql(), we force "guest access" or observer checking
// Give ocap tokens priority
$r = q("select * from item where uuid = '%s' $item_normal $sql_extra limit 1", if ($ob_authorize) {
$sql_extra = " and item.uid = " . intval($token['uid']) . " ";
}
else {
$sql_extra = item_permissions_sql(0);
}
$r = q("select * from item where uuid = '%s' $item_normal $sql_extra and item_deleted = 0 limit 1",
dbesc($item_id) dbesc($item_id)
); );
if (! $r) { if (! $r) {
@ -42,8 +73,7 @@ class Activity extends \Zotlabs\Web\Controller {
ACTIVITYSTREAMS_JSONLD_REV, ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1', 'https://w3id.org/security/v1',
z_root() . ZOT_APSCHEMA_REV z_root() . ZOT_APSCHEMA_REV
]], ZActivity::encode_activity($items[0])); ]], ZlibActivity::encode_activity($items[0]));
$headers = []; $headers = [];
@ -59,7 +89,7 @@ class Activity extends \Zotlabs\Web\Controller {
killme(); killme();
} }
goaway(z_root() . '/item/' . argv(1));
} }
} }

View file

@ -2,7 +2,7 @@
namespace Zotlabs\Module\Admin; namespace Zotlabs\Module\Admin;
use App;
class Accounts { class Accounts {
@ -23,7 +23,7 @@ class Accounts {
check_form_security_token_redirectOnErr('/admin/accounts', 'admin_accounts'); check_form_security_token_redirectOnErr('/admin/accounts', 'admin_accounts');
// change to switch structure?
// account block/unblock button was submitted // account block/unblock button was submitted
if (x($_POST, 'page_accounts_block')) { if (x($_POST, 'page_accounts_block')) {
for ($i = 0; $i < count($users); $i++) { for ($i = 0; $i < count($users); $i++) {
@ -36,6 +36,7 @@ class Accounts {
} }
notice( sprintf( tt("%s account blocked/unblocked", "%s account blocked/unblocked", count($users)), count($users)) ); notice( sprintf( tt("%s account blocked/unblocked", "%s account blocked/unblocked", count($users)), count($users)) );
} }
// account delete button was submitted // account delete button was submitted
if (x($_POST, 'page_accounts_delete')) { if (x($_POST, 'page_accounts_delete')) {
foreach ($users as $uid){ foreach ($users as $uid){
@ -43,12 +44,14 @@ class Accounts {
} }
notice( sprintf( tt("%s account deleted", "%s accounts deleted", count($users)), count($users)) ); notice( sprintf( tt("%s account deleted", "%s accounts deleted", count($users)), count($users)) );
} }
// registration approved button was submitted // registration approved button was submitted
if (x($_POST, 'page_accounts_approve')) { if (x($_POST, 'page_accounts_approve')) {
foreach ($pending as $hash) { foreach ($pending as $hash) {
account_allow($hash); account_allow($hash);
} }
} }
// registration deny button was submitted // registration deny button was submitted
if (x($_POST, 'page_accounts_deny')) { if (x($_POST, 'page_accounts_deny')) {
foreach ($pending as $hash) { foreach ($pending as $hash) {
@ -112,7 +115,7 @@ class Accounts {
} }
/* get pending */ /* get pending */
$pending = q("SELECT account.*, register.hash from account left join register on account_id = register.uid where (account_flags & %d )>0 ", $pending = q("SELECT account.*, register.hash from account left join register on account_id = register.uid where (account_flags & %d ) != 0 ",
intval(ACCOUNT_PENDING) intval(ACCOUNT_PENDING)
); );
@ -120,16 +123,17 @@ class Accounts {
$total = q("SELECT count(*) as total FROM account"); $total = q("SELECT count(*) as total FROM account");
if (count($total)) { if (count($total)) {
\App::set_pager_total($total[0]['total']); App::set_pager_total($total[0]['total']);
\App::set_pager_itemspage(100); App::set_pager_itemspage(100);
} }
$serviceclass = (($_REQUEST['class']) ? " and account_service_class = '" . dbesc($_REQUEST['class']) . "' " : ''); $serviceclass = (($_REQUEST['class']) ? " and account_service_class = '" . dbesc($_REQUEST['class']) . "' " : '');
$key = (($_REQUEST['key']) ? dbesc($_REQUEST['key']) : 'account_id'); $key = (($_REQUEST['key']) ? dbesc($_REQUEST['key']) : 'account_id');
$dir = 'asc'; $dir = 'asc';
if(array_key_exists('dir',$_REQUEST)) if (array_key_exists('dir',$_REQUEST)) {
$dir = ((intval($_REQUEST['dir'])) ? 'asc' : 'desc'); $dir = ((intval($_REQUEST['dir'])) ? 'asc' : 'desc');
}
$base = z_root() . '/admin/accounts?f='; $base = z_root() . '/admin/accounts?f=';
$odir = (($dir === 'asc') ? '0' : '1'); $odir = (($dir === 'asc') ? '0' : '1');
@ -140,29 +144,25 @@ class Accounts {
intval(ACCOUNT_BLOCKED), intval(ACCOUNT_BLOCKED),
db_concat('ch.channel_address', ' '), db_concat('ch.channel_address', ' '),
intval(ACCOUNT_BLOCKED | ACCOUNT_PENDING), intval(ACCOUNT_BLOCKED | ACCOUNT_PENDING),
intval(\App::$pager['itemspage']), intval(App::$pager['itemspage']),
intval(\App::$pager['start']) intval(App::$pager['start'])
); );
// function _setup_users($e){ if ($users) {
// $accounts = Array( for($x = 0; $x < count($users); $x ++) {
// t('Normal Account'), $channel_arr = explode(' ',$users[$x]['channels']);
// t('Soapbox Account'), if ($channel_arr) {
// t('Community/Celebrity Account'), $linked = [];
// t('Automatic Friend Account') foreach ( $channel_arr as $c) {
// ); $linked[] = '<a href="' . z_root() . '/channel/' . $c . '">' . $c . '</a>';
}
$users[$x]['channels'] = implode(' ',$linked);
}
}
}
// $e['page_flags'] = $accounts[$e['page-flags']]; $t =
// $e['register_date'] = relative_date($e['register_date']); $o = replace_macros(get_markup_template('admin_accounts.tpl'), [
// $e['login_date'] = relative_date($e['login_date']);
// $e['lastitem_date'] = relative_date($e['lastitem_date']);
// return $e;
// }
// $users = array_map("_setup_users", $users);
$t = get_markup_template('admin_accounts.tpl');
$o = replace_macros($t, array(
// strings //
'$title' => t('Administration'), '$title' => t('Administration'),
'$page' => t('Accounts'), '$page' => t('Accounts'),
'$submit' => t('Submit'), '$submit' => t('Submit'),
@ -178,30 +178,25 @@ class Accounts {
'$odir' => $odir, '$odir' => $odir,
'$base' => $base, '$base' => $base,
'$h_users' => t('Accounts'), '$h_users' => t('Accounts'),
'$th_users' => array( '$th_users' => [
[ t('ID'), 'account_id' ], [ t('ID'), 'account_id' ],
[ t('Email'), 'account_email' ], [ t('Email'), 'account_email' ],
[ t('All Channels'), 'channels' ], [ t('All Channels'), 'channels' ],
[ t('Register date'), 'account_created' ], [ t('Register date'), 'account_created' ],
[ t('Last login'), 'account_lastlog' ], [ t('Last login'), 'account_lastlog' ],
[ t('Expires'), 'account_expires' ], [ t('Expires'), 'account_expires' ],
[ t('Service Class'), 'account_service_class'] ), [ t('Service Class'), 'account_service_class']
],
'$confirm_delete_multi' => t('Selected accounts will be deleted!\n\nEverything these accounts had posted on this site will be permanently deleted!\n\nAre you sure?'), '$confirm_delete_multi' => t('Selected accounts will be deleted!\n\nEverything these accounts had posted on this site will be permanently deleted!\n\nAre you sure?'),
'$confirm_delete' => t('The account {0} will be deleted!\n\nEverything this account has posted on this site will be permanently deleted!\n\nAre you sure?'), '$confirm_delete' => t('The account {0} will be deleted!\n\nEverything this account has posted on this site will be permanently deleted!\n\nAre you sure?'),
'$form_security_token' => get_form_security_token("admin_accounts"), '$form_security_token' => get_form_security_token("admin_accounts"),
// values //
'$baseurl' => z_root(), '$baseurl' => z_root(),
'$pending' => $pending, '$pending' => $pending,
'$users' => $users, '$users' => $users,
)); ]);
$o .= paginate($a); $o .= paginate($a);
return $o; return $o;
} }
} }

View file

@ -2,6 +2,8 @@
namespace Zotlabs\Module\Admin; namespace Zotlabs\Module\Admin;
use Zotlabs\Daemon\Master;
/** /**
* @brief Admin Module for Channels. * @brief Admin Module for Channels.
* *
@ -26,7 +28,7 @@ class Channels {
intval(PAGE_CENSORED), intval(PAGE_CENSORED),
intval( $uid ) intval( $uid )
); );
\Zotlabs\Daemon\Master::Summon(array('Directory', $uid, 'nopush')); Master::Summon( [ 'Directory', $uid, 'nopush' ] );
} }
notice( sprintf( tt("%s channel censored/uncensored", "%s channels censored/uncensored", count($channels)), count($channels)) ); notice( sprintf( tt("%s channel censored/uncensored", "%s channels censored/uncensored", count($channels)), count($channels)) );
} }
@ -82,7 +84,7 @@ class Channels {
intval($pflags), intval($pflags),
intval( $uid ) intval( $uid )
); );
\Zotlabs\Daemon\Master::Summon(array('Directory',$uid,'nopush')); Master::Summon( [ 'Directory', $uid, 'nopush' ]);
notice( sprintf( (($pflags & PAGE_CENSORED) ? t("Channel '%s' censored"): t("Channel '%s' uncensored")) , $channel[0]['channel_name'] . ' (' . $channel[0]['channel_address'] . ')' ) . EOL); notice( sprintf( (($pflags & PAGE_CENSORED) ? t("Channel '%s' censored"): t("Channel '%s' uncensored")) , $channel[0]['channel_name'] . ' (' . $channel[0]['channel_address'] . ')' ) . EOL);
}; break; }; break;

View file

@ -29,7 +29,7 @@ class Site {
$admininfo = ((x($_POST,'admininfo')) ? trim($_POST['admininfo']) : false); $admininfo = ((x($_POST,'admininfo')) ? trim($_POST['admininfo']) : false);
$siteinfo = ((x($_POST,'siteinfo')) ? trim($_POST['siteinfo']) : ''); $siteinfo = ((x($_POST,'siteinfo')) ? trim($_POST['siteinfo']) : '');
$language = ((x($_POST,'language')) ? notags(trim($_POST['language'])) : ''); $language = ((x($_POST,'language')) ? notags(trim($_POST['language'])) : 'en');
$theme = ((x($_POST,'theme')) ? notags(trim($_POST['theme'])) : ''); $theme = ((x($_POST,'theme')) ? notags(trim($_POST['theme'])) : '');
// $theme_mobile = ((x($_POST,'theme_mobile')) ? notags(trim($_POST['theme_mobile'])) : ''); // $theme_mobile = ((x($_POST,'theme_mobile')) ? notags(trim($_POST['theme_mobile'])) : '');
// $site_channel = ((x($_POST,'site_channel')) ? notags(trim($_POST['site_channel'])) : ''); // $site_channel = ((x($_POST,'site_channel')) ? notags(trim($_POST['site_channel'])) : '');
@ -53,7 +53,6 @@ class Site {
} }
$mirror_frontpage = ((x($_POST,'mirror_frontpage')) ? intval(trim($_POST['mirror_frontpage'])) : 0); $mirror_frontpage = ((x($_POST,'mirror_frontpage')) ? intval(trim($_POST['mirror_frontpage'])) : 0);
$directory_server = ((x($_POST,'directory_server')) ? trim($_POST['directory_server']) : ''); $directory_server = ((x($_POST,'directory_server')) ? trim($_POST['directory_server']) : '');
$allowed_sites = ((x($_POST,'allowed_sites')) ? notags(trim($_POST['allowed_sites'])) : '');
$force_publish = ((x($_POST,'publish_all')) ? True : False); $force_publish = ((x($_POST,'publish_all')) ? True : False);
$disable_discover_tab = ((x($_POST,'disable_discover_tab')) ? False : True); $disable_discover_tab = ((x($_POST,'disable_discover_tab')) ? False : True);
$site_firehose = ((x($_POST,'site_firehose')) ? True : False); $site_firehose = ((x($_POST,'site_firehose')) ? True : False);
@ -73,11 +72,13 @@ class Site {
$proxyuser = ((x($_POST,'proxyuser')) ? notags(trim($_POST['proxyuser'])) : ''); $proxyuser = ((x($_POST,'proxyuser')) ? notags(trim($_POST['proxyuser'])) : '');
$proxy = ((x($_POST,'proxy')) ? notags(trim($_POST['proxy'])) : ''); $proxy = ((x($_POST,'proxy')) ? notags(trim($_POST['proxy'])) : '');
$timeout = ((x($_POST,'timeout')) ? intval(trim($_POST['timeout'])) : 60); $timeout = ((x($_POST,'timeout')) ? intval(trim($_POST['timeout'])) : 60);
$show_like_counts = ((x($_POST,'show_like_counts')) ? intval(trim($_POST['show_like_counts'])) : 0);
$delivery_interval = ((x($_POST,'delivery_interval'))? intval(trim($_POST['delivery_interval'])) : 0); $delivery_interval = ((x($_POST,'delivery_interval'))? intval(trim($_POST['delivery_interval'])) : 0);
$delivery_batch_count = ((x($_POST,'delivery_batch_count') && $_POST['delivery_batch_count'] > 0)? intval(trim($_POST['delivery_batch_count'])) : 3); $delivery_batch_count = ((x($_POST,'delivery_batch_count') && $_POST['delivery_batch_count'] > 0)? intval(trim($_POST['delivery_batch_count'])) : 3);
$poll_interval = ((x($_POST,'poll_interval')) ? intval(trim($_POST['poll_interval'])) : 0); $poll_interval = ((x($_POST,'poll_interval')) ? intval(trim($_POST['poll_interval'])) : 0);
$maxloadavg = ((x($_POST,'maxloadavg')) ? intval(trim($_POST['maxloadavg'])) : 50); $maxloadavg = ((x($_POST,'maxloadavg')) ? intval(trim($_POST['maxloadavg'])) : 50);
$feed_contacts = ((x($_POST,'feed_contacts')) ? intval($_POST['feed_contacts']) : 0); $feed_contacts = ((x($_POST,'feed_contacts')) ? intval($_POST['feed_contacts']) : 0);
$ap_contacts = ((x($_POST,'ap_contacts')) ? intval($_POST['ap_contacts']) : 0);
$verify_email = ((x($_POST,'verify_email')) ? 1 : 0); $verify_email = ((x($_POST,'verify_email')) ? 1 : 0);
$imagick_path = ((x($_POST,'imagick_path')) ? trim($_POST['imagick_path']) : ''); $imagick_path = ((x($_POST,'imagick_path')) ? trim($_POST['imagick_path']) : '');
$thumbnail_security = ((x($_POST,'thumbnail_security')) ? intval($_POST['thumbnail_security']) : 0); $thumbnail_security = ((x($_POST,'thumbnail_security')) ? intval($_POST['thumbnail_security']) : 0);
@ -88,6 +89,7 @@ class Site {
$permissions_role = escape_tags(trim($_POST['permissions_role'])); $permissions_role = escape_tags(trim($_POST['permissions_role']));
set_config('system', 'feed_contacts', $feed_contacts); set_config('system', 'feed_contacts', $feed_contacts);
set_config('system', 'activitypub', $ap_contacts);
set_config('system', 'delivery_interval', $delivery_interval); set_config('system', 'delivery_interval', $delivery_interval);
set_config('system', 'delivery_batch_count', $delivery_batch_count); set_config('system', 'delivery_batch_count', $delivery_batch_count);
set_config('system', 'poll_interval', $poll_interval); set_config('system', 'poll_interval', $poll_interval);
@ -109,6 +111,7 @@ class Site {
set_config('system', 'imagick_convert_path' , $imagick_path); set_config('system', 'imagick_convert_path' , $imagick_path);
set_config('system', 'thumbnail_security' , $thumbnail_security); set_config('system', 'thumbnail_security' , $thumbnail_security);
set_config('system', 'default_permissions_role', $permissions_role); set_config('system', 'default_permissions_role', $permissions_role);
set_config('system', 'show_like_counts', $show_like_counts);
set_config('system', 'pubstream_incl',$pub_incl); set_config('system', 'pubstream_incl',$pub_incl);
set_config('system', 'pubstream_excl',$pub_excl); set_config('system', 'pubstream_excl',$pub_excl);
@ -144,7 +147,6 @@ class Site {
set_config('system','access_policy', $access_policy); set_config('system','access_policy', $access_policy);
set_config('system','account_abandon_days', $abandon_days); set_config('system','account_abandon_days', $abandon_days);
set_config('system','register_text', $register_text); set_config('system','register_text', $register_text);
set_config('system','allowed_sites', $allowed_sites);
set_config('system','publish_all', $force_publish); set_config('system','publish_all', $force_publish);
set_config('system','disable_discover_tab', $disable_discover_tab); set_config('system','disable_discover_tab', $disable_discover_tab);
set_config('system','site_firehose', $site_firehose); set_config('system','site_firehose', $site_firehose);
@ -177,10 +179,10 @@ class Site {
/* Installed langs */ /* Installed langs */
$lang_choices = array(); $lang_choices = array();
$langs = glob('view/*/hstrings.php'); $langs = glob('view/*/strings.php');
if (is_array($langs) && count($langs)) { if (is_array($langs) && count($langs)) {
if (! in_array('view/en/hstrings.php',$langs)) if (! in_array('view/en/strings.php',$langs))
$langs[] = 'view/en/'; $langs[] = 'view/en/';
asort($langs); asort($langs);
foreach ($langs as $l) { foreach ($langs as $l) {
@ -302,11 +304,12 @@ class Site {
'$banner' => [ 'banner', t("Banner/Logo"), $banner, t('Unfiltered HTML/CSS/JS is allowed') ], '$banner' => [ 'banner', t("Banner/Logo"), $banner, t('Unfiltered HTML/CSS/JS is allowed') ],
'$admininfo' => [ 'admininfo', t("Administrator Information"), $admininfo, t("Contact information for site administrators. Displayed on siteinfo page. BBCode may be used here.") ], '$admininfo' => [ 'admininfo', t("Administrator Information"), $admininfo, t("Contact information for site administrators. Displayed on siteinfo page. BBCode may be used here.") ],
'$siteinfo' => [ 'siteinfo', t('Site Information'), get_config('system','siteinfo'), t("Publicly visible description of this site. Displayed on siteinfo page. BBCode may be used here.") ], '$siteinfo' => [ 'siteinfo', t('Site Information'), get_config('system','siteinfo'), t("Publicly visible description of this site. Displayed on siteinfo page. BBCode may be used here.") ],
'$language' => [ 'language', t("System language"), get_config('system','language'), "", $lang_choices ], '$language' => [ 'language', t("System language"), get_config('system','language','en'), "", $lang_choices ],
'$theme' => [ 'theme', t("System theme"), get_config('system','theme'), t("Default system theme - may be over-ridden by user profiles - <a href='#' id='cnftheme'>change theme settings</a>"), $theme_choices ], '$theme' => [ 'theme', t("System theme"), get_config('system','theme'), t("Default system theme - may be over-ridden by user profiles - <a href='#' id='cnftheme'>change theme settings</a>"), $theme_choices ],
// '$theme_mobile' => [ 'theme_mobile', t("Mobile system theme"), get_config('system','mobile_theme'), t("Theme for mobile devices"), $theme_choices_mobile ], // '$theme_mobile' => [ 'theme_mobile', t("Mobile system theme"), get_config('system','mobile_theme'), t("Theme for mobile devices"), $theme_choices_mobile ],
// '$site_channel' => [ 'site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel") ], // '$site_channel' => [ 'site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel") ],
'$feed_contacts' => [ 'feed_contacts', t('Allow Feeds as Connections'),get_config('system','feed_contacts'),t('(Heavy system resource usage)') ], '$feed_contacts' => [ 'feed_contacts', t('Allow Feeds as Connections'),get_config('system','feed_contacts'),t('(Heavy system resource usage)') ],
'$ap_contacts' => [ 'ap_contacts', t('Allow ActivityPub Connections'),get_config('system','activitypub'),t('Experimental and unsupported. ActivityPub does not fully support privacy and account mobility.') ],
'$maximagesize' => [ 'maximagesize', t("Maximum image size"), intval(get_config('system','maximagesize')), t("Maximum size in bytes of uploaded images. Default is 0, which means no limits.") ], '$maximagesize' => [ 'maximagesize', t("Maximum image size"), intval(get_config('system','maximagesize')), t("Maximum size in bytes of uploaded images. Default is 0, which means no limits.") ],
'$register_policy' => [ 'register_policy', t("Does this site allow new member registration?"), get_config('system','register_policy'), "", $register_choices ], '$register_policy' => [ 'register_policy', t("Does this site allow new member registration?"), get_config('system','register_policy'), "", $register_choices ],
'$invite_only' => [ 'invite_only', t("Invitation only"), get_config('system','invitation_only'), t("Only allow new member registrations with an invitation code. New member registration must be allowed for this to work.") ], '$invite_only' => [ 'invite_only', t("Invitation only"), get_config('system','invitation_only'), t("Only allow new member registrations with an invitation code. New member registration must be allowed for this to work.") ],
@ -317,12 +320,12 @@ class Site {
'$frontpage' => [ 'frontpage', t("Site homepage to show visitors (default: login box)"), get_config('system','frontpage'), t("example: 'public' to show public stream, 'page/sys/home' to show a system webpage called 'home' or 'include:home.html' to include a file.") ], '$frontpage' => [ 'frontpage', t("Site homepage to show visitors (default: login box)"), get_config('system','frontpage'), t("example: 'public' to show public stream, 'page/sys/home' to show a system webpage called 'home' or 'include:home.html' to include a file.") ],
'$mirror_frontpage' => [ 'mirror_frontpage', t("Preserve site homepage URL"), get_config('system','mirror_frontpage'), t('Present the site homepage in a frame at the original location instead of redirecting') ], '$mirror_frontpage' => [ 'mirror_frontpage', t("Preserve site homepage URL"), get_config('system','mirror_frontpage'), t('Present the site homepage in a frame at the original location instead of redirecting') ],
'$abandon_days' => [ 'abandon_days', t('Accounts abandoned after x days'), get_config('system','account_abandon_days'), t('Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit.') ], '$abandon_days' => [ 'abandon_days', t('Accounts abandoned after x days'), get_config('system','account_abandon_days'), t('Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit.') ],
'$allowed_sites' => [ 'allowed_sites', t("Allowed friend domains"), get_config('system','allowed_sites'), t("Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains") ],
'$verify_email' => [ 'verify_email', t("Verify Email Addresses"), get_config('system','verify_email'), t("Check to verify email addresses used in account registration (recommended).") ], '$verify_email' => [ 'verify_email', t("Verify Email Addresses"), get_config('system','verify_email'), t("Check to verify email addresses used in account registration (recommended).") ],
'$force_publish' => [ 'publish_all', t("Force publish"), get_config('system','publish_all'), t("Check to force all profiles on this site to be listed in the site directory.") ], '$force_publish' => [ 'publish_all', t("Force publish"), get_config('system','publish_all'), t("Check to force all profiles on this site to be listed in the site directory.") ],
'$disable_discover_tab' => [ 'disable_discover_tab', t('Import Public Streams'), $discover_tab, t('Import and allow access to public content pulled from other sites. Warning: this content is unmoderated.') ], '$disable_discover_tab' => [ 'disable_discover_tab', t('Import Public Streams'), $discover_tab, t('Import and allow access to public content pulled from other sites. Warning: this content is unmoderated.') ],
'$site_firehose' => [ 'site_firehose', t('Site only Public Streams'), get_config('system','site_firehose'), t('Allow access to public content originating only from this site if Imported Public Streams are disabled.') ], '$site_firehose' => [ 'site_firehose', t('Site only Public Streams'), get_config('system','site_firehose'), t('Allow access to public content originating only from this site if Imported Public Streams are disabled.') ],
'$open_pubstream' => [ 'open_pubstream', t('Allow anybody on the internet to access the Public streams'), get_config('system','open_pubstream',0), t('Default is to only allow viewing by site members. Warning: this content is unmoderated.') ], '$open_pubstream' => [ 'open_pubstream', t('Allow anybody on the internet to access the Public streams'), get_config('system','open_pubstream',0), t('Default is to only allow viewing by site members. Warning: this content is unmoderated.') ],
'$show_like_counts' => [ 'show_like_counts', t('Show numbers of likes and dislikes in conversations'), get_config('system','show_like_counts',1), t('If disabled, the presence of likes and dislikes will be shown, but without totals.') ],
'$incl' => [ 'pub_incl',t('Only import Public stream posts with this text'), get_config('system','pubstream_incl'),t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts') ], '$incl' => [ 'pub_incl',t('Only import Public stream posts with this text'), get_config('system','pubstream_incl'),t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts') ],
'$excl' => [ 'pub_excl',t('Do not import Public stream posts with this text'), get_config('system','pubstream_excl'),t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts') ], '$excl' => [ 'pub_excl',t('Do not import Public stream posts with this text'), get_config('system','pubstream_excl'),t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts') ],
'$login_on_homepage' => [ 'login_on_homepage', t("Login on Homepage"),((intval($homelogin) || $homelogin === false) ? 1 : '') , t("Present a login box to visitors on the home page if no other content has been configured.") ], '$login_on_homepage' => [ 'login_on_homepage', t("Login on Homepage"),((intval($homelogin) || $homelogin === false) ? 1 : '') , t("Present a login box to visitors on the home page if no other content has been configured.") ],
@ -341,7 +344,7 @@ class Site {
'$imagick_path' => [ 'imagick_path', t("Path to ImageMagick convert program"), get_config('system','imagick_convert_path'), t("If set, use this program to generate photo thumbnails for huge images ( > 4000 pixels in either dimension), otherwise memory exhaustion may occur. Example: /usr/bin/convert") ], '$imagick_path' => [ 'imagick_path', t("Path to ImageMagick convert program"), get_config('system','imagick_convert_path'), t("If set, use this program to generate photo thumbnails for huge images ( > 4000 pixels in either dimension), otherwise memory exhaustion may occur. Example: /usr/bin/convert") ],
'$thumbnail_security' => [ 'thumbnail_security', t("Allow SVG thumbnails in file browser"), get_config('system','thumbnail_security',0), t("WARNING: SVG images may contain malicious code.") ], '$thumbnail_security' => [ 'thumbnail_security', t("Allow SVG thumbnails in file browser"), get_config('system','thumbnail_security',0), t("WARNING: SVG images may contain malicious code.") ],
'$maxloadavg' => [ 'maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.") ], '$maxloadavg' => [ 'maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.") ],
'$default_expire_days' => [ 'default_expire_days', t('Expiration period in days for imported (grid/network) content'), intval(get_config('system','default_expire_days')), t('0 for no expiration of imported content') ], '$default_expire_days' => [ 'default_expire_days', t('Expiration period in days for imported streams'), intval(get_config('system','default_expire_days')), t('0 for no expiration of imported content') ],
'$active_expire_days' => [ 'active_expire_days', t('Do not expire any posts which have comments less than this many days ago'), intval(get_config('system','active_expire_days',7)), '' ], '$active_expire_days' => [ 'active_expire_days', t('Do not expire any posts which have comments less than this many days ago'), intval(get_config('system','active_expire_days',7)), '' ],
'$sellpage' => [ 'site_sellpage', t('Public servers: Optional landing (marketing) webpage for new registrants'), get_config('system','sellpage',''), sprintf( t('Create this page first. Default is %s/register'),z_root()) ], '$sellpage' => [ 'site_sellpage', t('Public servers: Optional landing (marketing) webpage for new registrants'), get_config('system','sellpage',''), sprintf( t('Create this page first. Default is %s/register'),z_root()) ],
'$first_page' => [ 'first_page', t('Page to display after creating a new channel'), get_config('system','workflow_channel_next','profiles'), t('Default: profiles') ], '$first_page' => [ 'first_page', t('Page to display after creating a new channel'), get_config('system','workflow_channel_next','profiles'), t('Default: profiles') ],

View file

@ -9,7 +9,7 @@ class Affinity extends \Zotlabs\Web\Controller {
function post() { function post() {
if(! ( local_channel() && Apps::system_app_installed(local_channel(),'Affinity Tool'))) { if(! ( local_channel() && Apps::system_app_installed(local_channel(),'Friend Zoom'))) {
return; return;
} }
@ -23,7 +23,7 @@ class Affinity extends \Zotlabs\Web\Controller {
set_pconfig(local_channel(),'affinity','cmin',0); set_pconfig(local_channel(),'affinity','cmin',0);
set_pconfig(local_channel(),'affinity','cmax',$cmax); set_pconfig(local_channel(),'affinity','cmax',$cmax);
info( t('Affinity Tool settings updated.') . EOL); info( t('Friend Zoom settings updated.') . EOL);
} }
@ -34,11 +34,11 @@ class Affinity extends \Zotlabs\Web\Controller {
function get() { function get() {
$desc = t('This app (when installed) presents a slider control in your connection editor and also on your network page. The slider represents your degree of friendship or <em>affinity</em> with each connection. It allows you to zoom in or out and display conversations from only your closest friends or everybody in your stream.'); $desc = t('This app (when installed) presents a slider control in your connection editor and also on your network page. The slider represents your degree of friendship with each connection. It allows you to zoom in or out and display conversations from only your closest friends or everybody in your stream.');
$text = '<div class="section-content-info-wrapper">' . $desc . '</div>'; $text = '<div class="section-content-info-wrapper">' . $desc . '</div>';
if(! ( local_channel() && Apps::system_app_installed(local_channel(),'Affinity Tool'))) { if(! ( local_channel() && Apps::system_app_installed(local_channel(),'Friend Zoom'))) {
return $text; return $text;
} }
@ -52,7 +52,7 @@ class Affinity extends \Zotlabs\Web\Controller {
// '$field' => array('affinity_cmax', t('Default maximum affinity level'), $cmax, t('0-99 default 99')) // '$field' => array('affinity_cmax', t('Default maximum affinity level'), $cmax, t('0-99 default 99'))
// )); // ));
if(Apps::system_app_installed(local_channel(),'Affinity Tool')) { if(Apps::system_app_installed(local_channel(),'Friend Zoom')) {
$labels = array( $labels = array(
0 => t('Me'), 0 => t('Me'),
@ -80,7 +80,7 @@ class Affinity extends \Zotlabs\Web\Controller {
} }
$s .= replace_macros(get_markup_template('generic_app_settings.tpl'), array( $s .= replace_macros(get_markup_template('generic_app_settings.tpl'), array(
'$addon' => array('affinity', '' . t('Affinity Tool Settings'), '', t('Submit')), '$addon' => array('affinity', '' . t('Friend Zoom Settings'), '', t('Submit')),
'$content' => $setting_fields '$content' => $setting_fields
)); ));

View file

@ -1,279 +0,0 @@
<?php
namespace Zotlabs\Module;
use Zotlabs\Lib\Libsync;
use Zotlabs\Lib\AccessList;
class Alist extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
\App::$profile_uid = local_channel();
nav_set_selected('Access Lists');
}
function post() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
if((argc() == 2) && (argv(1) === 'new')) {
check_form_security_token_redirectOnErr('/alist/new', 'group_edit');
$name = notags(trim($_POST['groupname']));
$public = intval($_POST['public']);
$r = AccessList::add(local_channel(),$name,$public);
if($r) {
info( t('Access list created.') . EOL );
}
else {
notice( t('Could not create access list.') . EOL );
}
goaway(z_root() . '/alist');
}
if((argc() == 2) && (intval(argv(1)))) {
check_form_security_token_redirectOnErr('/alist', 'group_edit');
$r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d LIMIT 1",
intval(argv(1)),
intval(local_channel())
);
if(! $r) {
notice( t('Access list not found.') . EOL );
goaway(z_root() . '/connections');
}
$group = $r[0];
$groupname = notags(trim($_POST['groupname']));
$public = intval($_POST['public']);
if((strlen($groupname)) && (($groupname != $group['gname']) || ($public != $group['visible']))) {
$r = q("UPDATE pgrp SET gname = '%s', visible = %d WHERE uid = %d AND id = %d",
dbesc($groupname),
intval($public),
intval(local_channel()),
intval($group['id'])
);
if($r)
info( t('Access list updated.') . EOL );
Libsync::build_sync_packet(local_channel(),null,true);
}
goaway(z_root() . '/alist/' . argv(1) . '/' . argv(2));
}
return;
}
function get() {
$change = false;
logger('mod_alist: ' . \App::$cmd,LOGGER_DEBUG);
if(! local_channel()) {
notice( t('Permission denied') . EOL);
return;
}
// Switch to text mode interface if we have more than 'n' contacts or group members
$switchtotext = get_pconfig(local_channel(),'system','groupedit_image_limit');
if($switchtotext === false)
$switchtotext = get_config('system','groupedit_image_limit');
if($switchtotext === false)
$switchtotext = 400;
if((argc() == 1) || ((argc() == 2) && (argv(1) === 'new'))) {
$new = (((argc() == 2) && (argv(1) === 'new')) ? true : false);
$groups = q("SELECT id, gname FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
intval(local_channel())
);
$i = 0;
foreach($groups as $group) {
$entries[$i]['name'] = $group['gname'];
$entries[$i]['id'] = $group['id'];
$entries[$i]['count'] = count(AccessList::members($group['id']));
$i++;
}
$tpl = get_markup_template('privacy_groups.tpl');
$o = replace_macros($tpl, [
'$title' => t('Access Lists'),
'$add_new_label' => t('Create access list'),
'$new' => $new,
// new group form
'$gname' => array('groupname',t('Access list name')),
'$public' => array('public',t('Members are visible to other channels'), false),
'$form_security_token' => get_form_security_token("group_edit"),
'$submit' => t('Submit'),
// groups list
'$title' => t('Access Lists'),
'$name_label' => t('Name'),
'$count_label' => t('Members'),
'$entries' => $entries
]);
return $o;
}
$context = array('$submit' => t('Submit'));
$tpl = get_markup_template('group_edit.tpl');
if((argc() == 3) && (argv(1) === 'drop')) {
check_form_security_token_redirectOnErr('/alist', 'group_drop', 't');
if(intval(argv(2))) {
$r = q("SELECT gname FROM pgrp WHERE id = %d AND uid = %d LIMIT 1",
intval(argv(2)),
intval(local_channel())
);
if($r)
$result = AccessList::remove(local_channel(),$r[0]['gname']);
if($result)
info( t('Access list removed.') . EOL);
else
notice( t('Unable to remove access list.') . EOL);
}
goaway(z_root() . '/alist');
// NOTREACHED
}
if((argc() > 2) && intval(argv(1)) && argv(2)) {
check_form_security_token_ForbiddenOnErr('group_member_change', 't');
$r = q("SELECT abook_xchan from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 limit 1",
dbesc(base64url_decode(argv(2))),
intval(local_channel())
);
if(count($r))
$change = base64url_decode(argv(2));
}
if((argc() > 1) && (intval(argv(1)))) {
require_once('include/acl_selectors.php');
$r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d AND deleted = 0 LIMIT 1",
intval(argv(1)),
intval(local_channel())
);
if(! $r) {
notice( t('Access list not found.') . EOL );
goaway(z_root() . '/connections');
}
$group = $r[0];
$members = AccessList::members($group['id']);
$preselected = array();
if(count($members)) {
foreach($members as $member)
if(! in_array($member['xchan_hash'],$preselected))
$preselected[] = $member['xchan_hash'];
}
if($change) {
if(in_array($change,$preselected)) {
AccessList::member_remove(local_channel(),$group['gname'],$change);
}
else {
AccessList::member_add(local_channel(),$group['gname'],$change);
}
$members = AccessList::members($group['id']);
$preselected = array();
if(count($members)) {
foreach($members as $member)
$preselected[] = $member['xchan_hash'];
}
}
$context = $context + array(
'$title' => sprintf(t('Access List: %s'), $group['gname']),
'$details_label' => t('Edit'),
'$gname' => array('groupname',t('Access list name: '),$group['gname'], ''),
'$gid' => $group['id'],
'$drop' => $drop_txt,
'$public' => array('public',t('Members are visible to other channels'), $group['visible'], ''),
'$form_security_token_edit' => get_form_security_token('group_edit'),
'$delete' => t('Delete access list'),
'$form_security_token_drop' => get_form_security_token("group_drop"),
);
}
if(! isset($group))
return;
$groupeditor = array(
'label_members' => t('List members'),
'members' => array(),
'label_contacts' => t('Not in this list'),
'contacts' => array(),
);
$sec_token = addslashes(get_form_security_token('group_member_change'));
$textmode = (($switchtotext && (count($members) > $switchtotext)) ? true : 'card');
foreach($members as $member) {
if($member['xchan_url']) {
$member['archived'] = (intval($member['abook_archived']) ? true : false);
$member['click'] = 'groupChangeMember(' . $group['id'] . ',\'' . base64url_encode($member['xchan_hash']) . '\',\'' . $sec_token . '\'); return false;';
$groupeditor['members'][] = micropro($member,true,'mpgroup', $textmode);
}
else
AccessList::member_remove(local_channel(),$group['gname'],$member['xchan_hash']);
}
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d AND abook_self = 0 and abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 order by xchan_name asc",
intval(local_channel())
);
if(count($r)) {
$textmode = (($switchtotext && (count($r) > $switchtotext)) ? true : 'card');
foreach($r as $member) {
if(! in_array($member['xchan_hash'],$preselected)) {
$member['archived'] = (intval($member['abook_archived']) ? true : false);
$member['click'] = 'groupChangeMember(' . $group['id'] . ',\'' . base64url_encode($member['xchan_hash']) . '\',\'' . $sec_token . '\'); return false;';
$groupeditor['contacts'][] = micropro($member,true,'mpall', $textmode);
}
}
}
$context['$groupeditor'] = $groupeditor;
$context['$desc'] = t('Click a channel to toggle membership');
if($change) {
$tpl = get_markup_template('groupeditor.tpl');
echo replace_macros($tpl, $context);
killme();
}
return replace_macros($tpl, $context);
}
}

View file

@ -1,20 +1,21 @@
<?php /** @file */ <?php
namespace Zotlabs\Module; namespace Zotlabs\Module;
//require_once('include/apps.php'); use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Apps;
use \Zotlabs\Lib as Zlib; class Appman extends Controller {
class Appman extends \Zotlabs\Web\Controller {
function post() { function post() {
if(! local_channel()) if (! local_channel()) {
return; return;
}
if ($_POST['url']) { if ($_POST['url']) {
$arr = array( $arr = [
'uid' => intval($_REQUEST['uid']), 'uid' => intval($_REQUEST['uid']),
'url' => escape_tags($_REQUEST['url']), 'url' => escape_tags($_REQUEST['url']),
'guid' => escape_tags($_REQUEST['guid']), 'guid' => escape_tags($_REQUEST['guid']),
@ -25,25 +26,25 @@ class Appman extends \Zotlabs\Web\Controller {
'photo' => escape_tags($_REQUEST['photo']), 'photo' => escape_tags($_REQUEST['photo']),
'version' => escape_tags($_REQUEST['version']), 'version' => escape_tags($_REQUEST['version']),
'price' => escape_tags($_REQUEST['price']), 'price' => escape_tags($_REQUEST['price']),
'page' => escape_tags($_REQUEST['page']), 'page' => escape_tags($_REQUEST['sellpage']), // do not use 'page' as a request variable here as it conflicts with pagination
'requires' => escape_tags($_REQUEST['requires']), 'requires' => escape_tags($_REQUEST['requires']),
'system' => intval($_REQUEST['system']), 'system' => intval($_REQUEST['system']),
'plugin' => escape_tags($_REQUEST['plugin']), 'plugin' => escape_tags($_REQUEST['plugin']),
'sig' => escape_tags($_REQUEST['sig']), 'sig' => escape_tags($_REQUEST['sig']),
'categories' => escape_tags($_REQUEST['categories']) 'categories' => escape_tags($_REQUEST['categories'])
); ];
$_REQUEST['appid'] = Zlib\Apps::app_install(local_channel(),$arr); $_REQUEST['appid'] = Apps::app_install(local_channel(),$arr);
if(Zlib\Apps::app_installed(local_channel(),$arr)) if (Apps::app_installed(local_channel(),$arr)) {
info( t('App installed.') . EOL); info( t('App installed.') . EOL);
}
goaway(z_root() . '/apps'); goaway(z_root() . '/apps');
return; //not reached
} }
$papp = Zlib\Apps::app_decode($_POST['papp']); $papp = Apps::app_decode($_POST['papp']);
if (! is_array($papp)) { if (! is_array($papp)) {
notice( t('Malformed app.') . EOL); notice( t('Malformed app.') . EOL);
@ -51,13 +52,13 @@ class Appman extends \Zotlabs\Web\Controller {
} }
if ($_POST['install']) { if ($_POST['install']) {
Zlib\Apps::app_install(local_channel(),$papp); Apps::app_install(local_channel(),$papp);
if(Zlib\Apps::app_installed(local_channel(),$papp)) if (Apps::app_installed(local_channel(),$papp))
info( t('App installed.') . EOL); info( t('App installed.') . EOL);
} }
if ($_POST['delete']) { if ($_POST['delete']) {
Zlib\Apps::app_destroy(local_channel(),$papp); Apps::app_destroy(local_channel(),$papp);
} }
if ($_POST['edit']) { if ($_POST['edit']) {
@ -65,19 +66,18 @@ class Appman extends \Zotlabs\Web\Controller {
} }
if ($_POST['feature']) { if ($_POST['feature']) {
Zlib\Apps::app_feature(local_channel(), $papp, $_POST['feature']); Apps::app_feature(local_channel(), $papp, $_POST['feature']);
} }
if ($_POST['pin']) { if ($_POST['pin']) {
Zlib\Apps::app_feature(local_channel(), $papp, $_POST['pin']); Apps::app_feature(local_channel(), $papp, $_POST['pin']);
} }
if($_SESSION['return_url']) if ($_SESSION['return_url']) {
goaway(z_root() . '/' . $_SESSION['return_url']); goaway(z_root() . '/' . $_SESSION['return_url']);
}
goaway(z_root() . '/apps'); goaway(z_root() . '/apps');
} }
@ -88,21 +88,18 @@ class Appman extends \Zotlabs\Web\Controller {
return; return;
} }
$channel = \App::get_channel(); $channel = App::get_channel();
if (argc() > 3) { if (argc() > 3) {
if(argv(2) === 'moveup') { if(argv(2) === 'moveup') {
Zlib\Apps::moveup(local_channel(),argv(1),argv(3)); Apps::moveup(local_channel(),argv(1),argv(3));
} }
if(argv(2) === 'movedown') { if(argv(2) === 'movedown') {
Zlib\Apps::movedown(local_channel(),argv(1),argv(3)); Apps::movedown(local_channel(),argv(1),argv(3));
} }
goaway(z_root() . '/apporder'); goaway(z_root() . '/apporder');
} }
$app = null; $app = null;
$embed = null; $embed = null;
if ($_REQUEST['appid']) { if ($_REQUEST['appid']) {
@ -119,40 +116,33 @@ class Appman extends \Zotlabs\Web\Controller {
intval(local_channel()) intval(local_channel())
); );
if ($term) { if ($term) {
$app['categories'] = ''; $app['categories'] = array_elm_to_str($term,'term');
foreach($term as $t) {
if($app['categories'])
$app['categories'] .= ',';
$app['categories'] .= $t['term'];
}
} }
} }
$embed = array('embed', t('Embed code'), Zlib\Apps::app_encode($app,true),'', 'onclick="this.select();"'); $embed = [ 'embed', t('Embed code'), Apps::app_encode($app,true), EMPTY_STR, 'onclick="this.select();"' ];
} }
return replace_macros(get_markup_template('app_create.tpl'), array( return replace_macros(get_markup_template('app_create.tpl'), [
'$banner' => (($app) ? t('Edit App') : t('Create App')), '$banner' => (($app) ? t('Edit App') : t('Create App')),
'$app' => $app, '$app' => $app,
'$guid' => (($app) ? $app['app_id'] : ''), '$guid' => (($app) ? $app['app_id'] : EMPTY_STR),
'$author' => (($app) ? $app['app_author'] : $channel['channel_hash']), '$author' => (($app) ? $app['app_author'] : $channel['channel_hash']),
'$addr' => (($app) ? $app['app_addr'] : $channel['xchan_addr']), '$addr' => (($app) ? $app['app_addr'] : $channel['xchan_addr']),
'$name' => array('name', t('Name of app'),(($app) ? $app['app_name'] : ''), t('Required')), '$name' => [ 'name', t('Name of app'),(($app) ? $app['app_name'] : EMPTY_STR), t('Required') ],
'$url' => array('url', t('Location (URL) of app'),(($app) ? $app['app_url'] : ''), t('Required')), '$url' => [ 'url', t('Location (URL) of app'),(($app) ? $app['app_url'] : EMPTY_STR), t('Required') ],
'$desc' => array('desc', t('Description'),(($app) ? $app['app_desc'] : ''), ''), '$desc' => [ 'desc', t('Description'),(($app) ? $app['app_desc'] : EMPTY_STR), EMPTY_STR],
'$photo' => array('photo', t('Photo icon URL'),(($app) ? $app['app_photo'] : ''), t('80 x 80 pixels - optional')), '$photo' => [ 'photo', t('Photo icon URL'),(($app) ? $app['app_photo'] : EMPTY_STR), t('80 x 80 pixels - optional') ],
'$categories' => array('categories',t('Categories (optional, comma separated list)'),(($app) ? $app['categories'] : ''),''), '$categories' => [ 'categories',t('Categories (optional, comma separated list)'),(($app) ? $app['categories'] : EMPTY_STR), EMPTY_STR ],
'$version' => array('version', t('Version ID'),(($app) ? $app['app_version'] : ''), ''), '$version' => [ 'version', t('Version ID'),(($app) ? $app['app_version'] : EMPTY_STR), EMPTY_STR ],
'$price' => array('price', t('Price of app'),(($app) ? $app['app_price'] : ''), ''), '$price' => [ 'price', t('Price of app'),(($app) ? $app['app_price'] : EMPTY_STR), EMPTY_STR ],
'$page' => array('page', t('Location (URL) to purchase app'),(($app) ? $app['app_page'] : ''), ''), '$page' => [ 'sellpage', t('Location (URL) to purchase app'),(($app) ? $app['app_page'] : EMPTY_STR), EMPTY_STR ],
'$system' => (($app) ? intval($app['app_system']) : 0), '$system' => (($app) ? intval($app['app_system']) : 0),
'$plugin' => (($app) ? $app['app_plugin'] : ''), '$plugin' => (($app) ? $app['app_plugin'] : EMPTY_STR),
'$requires' => (($app) ? $app['app_requires'] : ''), '$requires' => (($app) ? $app['app_requires'] : EMPTY_STR),
'$embed' => $embed, '$embed' => $embed,
'$submit' => t('Submit') '$submit' => t('Submit')
)); ]);
} }

View file

@ -2,53 +2,51 @@
namespace Zotlabs\Module; namespace Zotlabs\Module;
use \Zotlabs\Lib as Zlib; use Zotlabs\Web\Controller;
use Zotlabs\Lib\Apps;
class Apporder extends \Zotlabs\Web\Controller { class Apporder extends \Zotlabs\Web\Controller {
function post() {
}
function get() { function get() {
if(! local_channel()) if (! local_channel()) {
return; return;
}
nav_set_selected('Order Apps'); nav_set_selected('Order Apps');
foreach ( [ 'nav_featured_app', 'nav_pinned_app' ] as $l ) { foreach ( [ 'nav_featured_app', 'nav_pinned_app' ] as $l ) {
$syslist = []; $syslist = [];
$list = Zlib\Apps::app_list(local_channel(), false, [ $l ]); $list = Apps::app_list(local_channel(), false, [ $l ]);
if ($list) { if ($list) {
foreach ($list as $li) { foreach ($list as $li) {
$syslist[] = Zlib\Apps::app_encode($li); $syslist[] = Apps::app_encode($li);
} }
} }
Zlib\Apps::translate_system_apps($syslist); Apps::translate_system_apps($syslist);
usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare'); usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');
$syslist = Zlib\Apps::app_order(local_channel(),$syslist, $l); $syslist = Apps::app_order(local_channel(),$syslist, $l);
foreach ($syslist as $app) { foreach ($syslist as $app) {
if ($l === 'nav_pinned_app') { if ($l === 'nav_pinned_app') {
$navbar_apps[] = Zlib\Apps::app_render($app,'nav-order'); $navbar_apps[] = Apps::app_render($app,'nav-order-pinned');
} }
elseif(strpos($app['categories'],'nav_pinned_app') === false) { else {
$nav_apps[] = Zlib\Apps::app_render($app,'nav-order'); $nav_apps[] = Apps::app_render($app,'nav-order');
} }
} }
} }
return replace_macros(get_markup_template('apporder.tpl'), return replace_macros(get_markup_template('apporder.tpl'), [
[
'$header' => [ t('Change Order of Pinned Navbar Apps'), t('Change Order of App Tray Apps') ], '$header' => [ t('Change Order of Pinned Navbar Apps'), t('Change Order of App Tray Apps') ],
'$desc' => [t('Use arrows to move the corresponding app left (top) or right (bottom) in the navbar'), t('Use arrows to move the corresponding app up or down in the app tray')], '$desc' => [ t('Use arrows to move the corresponding app left (top) or right (bottom) in the navbar'),
t('Use arrows to move the corresponding app up or down in the app tray') ],
'$nav_apps' => $nav_apps, '$nav_apps' => $nav_apps,
'$navbar_apps' => $navbar_apps '$navbar_apps' => $navbar_apps
] ]);
);
} }
} }

View file

@ -17,12 +17,17 @@ class Apschema extends \Zotlabs\Web\Controller {
'ostatus' => 'http://ostatus.org#', 'ostatus' => 'http://ostatus.org#',
'conversation' => 'ostatus:conversation', 'conversation' => 'ostatus:conversation',
'sensitive' => 'as:sensitive', 'sensitive' => 'as:sensitive',
'movedTo' => 'as:movedTo',
'copiedTo' => 'as:copiedTo',
'alsoKnownAs' => 'as:alsoKnownAs',
'inheritPrivacy' => 'as:inheritPrivacy', 'inheritPrivacy' => 'as:inheritPrivacy',
'commentPolicy' => 'zot:commentPolicy', 'commentPolicy' => 'zot:commentPolicy',
'topicalCollection' => 'zot:topicalCollection', 'topicalCollection' => 'zot:topicalCollection',
'eventRepeat' => 'zot:eventRepeat', 'eventRepeat' => 'zot:eventRepeat',
'emojiReaction' => 'zot:emojiReaction', 'emojiReaction' => 'zot:emojiReaction',
'expires' => 'zot:expires', 'expires' => 'zot:expires',
'directMessage' => 'zot:directMessage',
'replyTo' => 'zot:replyTo'
] ]
]; ];

View file

@ -51,12 +51,20 @@ class Authorize extends \Zotlabs\Web\Controller {
// closely to "OAuth 2.0 Dynamic Client Registration Protocol" defined // closely to "OAuth 2.0 Dynamic Client Registration Protocol" defined
// at https://tools.ietf.org/html/rfc7591 // at https://tools.ietf.org/html/rfc7591
// If no client_id was provided, generate a new one.
if (x($_POST, 'client_name')) {
$client_name = $_POST['client_name'];
} else {
$client_name = $_POST['client_name'] = EMPTY_STR;
}
// If no client_id was provided, generate a new one. // If no client_id was provided, generate a new one.
if (x($_POST, 'client_id')) { if (x($_POST, 'client_id')) {
$client_id = $_POST['client_id']; $client_id = $_POST['client_id'];
} else { } else {
$client_id = $_POST['client_id'] = random_string(16); $client_id = $_POST['client_id'] = random_string(16);
} }
// If no redirect_uri was provided, generate a fake one. // If no redirect_uri was provided, generate a fake one.
if (x($_POST, 'redirect_uri')) { if (x($_POST, 'redirect_uri')) {
$redirect_uri = $_POST['redirect_uri']; $redirect_uri = $_POST['redirect_uri'];
@ -76,7 +84,7 @@ class Authorize extends \Zotlabs\Web\Controller {
// Until "Dynamic Client Registration" is pursued - allow new clients to assign their own secret in the REQUEST // Until "Dynamic Client Registration" is pursued - allow new clients to assign their own secret in the REQUEST
$client_secret = (isset($_REQUEST['client_secret'])) ? $_REQUEST['client_secret'] : random_string(16); $client_secret = (isset($_REQUEST['client_secret'])) ? $_REQUEST['client_secret'] : random_string(16);
// Client apps are registered per channel // Client apps are registered per channel
$storage->setClientDetails($client_id, $client_secret, $redirect_uri, 'authorization_code', $_REQUEST['scope'], $user_id); $storage->setClientDetails($client_id, $client_secret, $redirect_uri, $_REQUEST['grant_types'], $_REQUEST['scope'], $user_id, $client_name);
} }
if (!$client = $storage->getClientDetails($client_id)) { if (!$client = $storage->getClientDetails($client_id)) {
// There was an error registering the client. // There was an error registering the client.

View file

@ -82,8 +82,7 @@ class Cal extends Controller {
$sql_extra = permissions_sql($channel['channel_id'],get_observer_hash(),'event'); $sql_extra = permissions_sql($channel['channel_id'],get_observer_hash(),'event');
$first_day = get_pconfig(local_channel(),'system','cal_first_day'); $first_day = intval(get_pconfig($channel['channel_id'],'system','cal_first_day',0));
$first_day = (($first_day) ? $first_day : 0);
$htpl = get_markup_template('event_head.tpl'); $htpl = get_markup_template('event_head.tpl');
\App::$page['htmlhead'] .= replace_macros($htpl,array( \App::$page['htmlhead'] .= replace_macros($htpl,array(

View file

@ -429,12 +429,12 @@ class Calendar extends Controller {
'end' => $end, 'end' => $end,
'drop' => $drop, 'drop' => $drop,
'allDay' => $allDay, 'allDay' => $allDay,
'title' => htmlentities($rr['summary'], ENT_COMPAT, 'UTF-8'), 'title' => html_entity_decode($rr['summary'], ENT_COMPAT, 'UTF-8'),
'editable' => $edit ? true : false, 'editable' => $edit ? true : false,
'item' => $rr, 'item' => $rr,
'plink' => [ $rr['plink'], t('Link to source') ], 'plink' => [ $rr['plink'], t('Link to source') ],
'description' => htmlentities($rr['description'], ENT_COMPAT, 'UTF-8'), 'description' => htmlentities($rr['description'], ENT_COMPAT, 'UTF-8',false),
'location' => htmlentities($rr['location'], ENT_COMPAT, 'UTF-8'), 'location' => htmlentities($rr['location'], ENT_COMPAT, 'UTF-8',false),
'allow_cid' => expand_acl($rr['allow_cid']), 'allow_cid' => expand_acl($rr['allow_cid']),
'allow_gid' => expand_acl($rr['allow_gid']), 'allow_gid' => expand_acl($rr['allow_gid']),
'deny_cid' => expand_acl($rr['deny_cid']), 'deny_cid' => expand_acl($rr['deny_cid']),

View file

@ -76,6 +76,7 @@ class Channel extends Controller {
'href' => z_root() . '/feed/' . $which . '?f=&top=1' 'href' => z_root() . '/feed/' . $which . '?f=&top=1'
]); ]);
// handle zot6 channel discovery // handle zot6 channel discovery
if(Libzot::is_zot_request()) { if(Libzot::is_zot_request()) {
@ -113,7 +114,7 @@ class Channel extends Controller {
ACTIVITYSTREAMS_JSONLD_REV, ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1', 'https://w3id.org/security/v1',
z_root() . ZOT_APSCHEMA_REV z_root() . ZOT_APSCHEMA_REV
]], Activity::encode_person($channel,true,((defined('NOMADIC')) ? false : true))); ]], Activity::encode_person($channel,true,true));
$headers = []; $headers = [];
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ; $headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ;
@ -135,6 +136,16 @@ class Channel extends Controller {
Libprofile::load($which,$profile); Libprofile::load($which,$profile);
App::$meta->set('og:title', $channel['channel_name']);
App::$meta->set('og:image', $channel['xchan_photo_l']);
App::$meta->set('og:type','webpage');
App::$meta->set('og:url', channel_url($channel));
if(App::$profile['about'] && perm_is_allowed($channel['channel_id'],get_observer_hash(),'view_profile')) {
App::$meta->set('og:description', App::$profile['about']);
}
else {
App::$meta->set('og:description', sprintf( t('This is the home page of %s.'), $channel['channel_name']));
}
} }
function get($update = 0, $load = false) { function get($update = 0, $load = false) {
@ -440,6 +451,7 @@ class Channel extends Controller {
'$nouveau' => '0', '$nouveau' => '0',
'$wall' => '1', '$wall' => '1',
'$fh' => '0', '$fh' => '0',
'$dm' => '0',
'$static' => $static, '$static' => $static,
'$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1), '$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
'$search' => $search, '$search' => $search,

View file

@ -37,18 +37,11 @@ class Cloud extends Controller {
if (argc() > 1) if (argc() > 1)
$which = argv(1); $which = argv(1);
if (argc() < 2 && intval(get_config('system','cloud_disable_siteroot'))) {
notice( t('Permission denied.') . EOL);
construct_page();
killme();
}
$profile = 0; $profile = 0;
if ($which) if ($which) {
Libprofile::load( $which, $profile); Libprofile::load( $which, $profile);
}
$auth = new \Zotlabs\Storage\BasicAuth(); $auth = new \Zotlabs\Storage\BasicAuth();

View file

@ -1,20 +1,24 @@
<?php <?php
namespace Zotlabs\Module; namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
require_once('include/socgraph.php'); require_once('include/socgraph.php');
class Connections extends \Zotlabs\Web\Controller { class Connections extends Controller {
function init() { function init() {
if(! local_channel()) if (! local_channel()) {
return; return;
}
$channel = \App::get_channel(); $channel = App::get_channel();
if($channel) if ($channel) {
head_set_icon($channel['xchan_photo_s']); head_set_icon($channel['xchan_photo_s']);
}
} }
@ -41,8 +45,9 @@ class Connections extends \Zotlabs\Web\Controller {
$unconnected = false; $unconnected = false;
$all = false; $all = false;
if(! $_REQUEST['aj']) if (! $_REQUEST['aj']) {
$_SESSION['return_url'] = \App::$query_string; $_SESSION['return_url'] = App::$query_string;
}
$search_flags = ""; $search_flags = "";
$head = ''; $head = '';
@ -80,21 +85,25 @@ class Connections extends \Zotlabs\Web\Controller {
$pending = true; $pending = true;
break; break;
case 'ifpending': case 'ifpending':
case intval(argv(1)):
$r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ", $r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ",
intval(local_channel()) intval(local_channel())
); );
if ($r && $r[0]['total']) { if ($r && $r[0]['total']) {
$search_flags = " and abook_pending = 1 "; $search_flags = " and abook_pending = 1 ";
if(intval(argv(1))) {
$search_flags .= " and abook_id = " . intval(argv(1)) . " ";
}
$head = t('New'); $head = t('New');
$pending = true; $pending = true;
\App::$argv[1] = 'pending'; App::$argv[1] = 'pending';
} }
else { else {
$head = t('All'); $head = t('All');
$search_flags = ''; $search_flags = '';
$all = true; $all = true;
\App::$argc = 1; App::$argc = 1;
unset(\App::$argv[1]); unset(App::$argv[1]);
} }
break; break;
@ -109,9 +118,9 @@ class Connections extends \Zotlabs\Web\Controller {
} }
$sql_extra = $search_flags; $sql_extra = $search_flags;
if(argv(1) === 'pending') if (argv(1) === 'pending') {
$sql_extra .= " and abook_ignored = 0 "; $sql_extra .= " and abook_ignored = 0 ";
}
} }
else { else {
$sql_extra = " and abook_blocked = 0 "; $sql_extra = " and abook_blocked = 0 ";
@ -179,7 +188,7 @@ class Connections extends \Zotlabs\Web\Controller {
$search_txt = dbesc(protect_sprintf(preg_quote($search))); $search_txt = dbesc(protect_sprintf(preg_quote($search)));
$searching = true; $searching = true;
} }
$sql_extra .= (($searching) ? protect_sprintf(" AND xchan_name like '%$search_txt%' ") : ""); $sql_extra .= (($searching) ? protect_sprintf(" AND ( xchan_name like '%$search_txt%' OR abook_alias like '%$search_txt%' ) ") : "");
if($_REQUEST['gid']) { if($_REQUEST['gid']) {
$sql_extra .= " and xchan_hash in ( select xchan from pgrp_member where gid = " . intval($_REQUEST['gid']) . " and uid = " . intval(local_channel()) . " ) "; $sql_extra .= " and xchan_hash in ( select xchan from pgrp_member where gid = " . intval($_REQUEST['gid']) . " and uid = " . intval(local_channel()) . " ) ";
@ -190,15 +199,15 @@ class Connections extends \Zotlabs\Web\Controller {
intval(local_channel()) intval(local_channel())
); );
if($r) { if($r) {
\App::set_pager_total($r[0]['total']); App::set_pager_total($r[0]['total']);
$total = $r[0]['total']; $total = $r[0]['total'];
} }
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash $r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
WHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra $sql_extra2 ORDER BY xchan_name LIMIT %d OFFSET %d ", WHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra $sql_extra2 ORDER BY xchan_name LIMIT %d OFFSET %d ",
intval(local_channel()), intval(local_channel()),
intval(\App::$pager['itemspage']), intval(App::$pager['itemspage']),
intval(\App::$pager['start']) intval(App::$pager['start'])
); );
$contacts = array(); $contacts = array();
@ -247,7 +256,7 @@ class Connections extends \Zotlabs\Web\Controller {
'delete_hover' => t('Delete connection'), 'delete_hover' => t('Delete connection'),
'id' => $rr['abook_id'], 'id' => $rr['abook_id'],
'thumb' => $rr['xchan_photo_m'], 'thumb' => $rr['xchan_photo_m'],
'name' => $rr['xchan_name'], 'name' => $rr['xchan_name'] . (($rr['abook_alias']) ? ' &lt;' . $rr['abook_alias'] . '&gt;' : ''),
'classes' => ((intval($rr['abook_archived']) || intval($rr['abook_not_here'])) ? 'archived' : ''), 'classes' => ((intval($rr['abook_archived']) || intval($rr['abook_not_here'])) ? 'archived' : ''),
'link' => z_root() . '/connedit/' . $rr['abook_id'], 'link' => z_root() . '/connedit/' . $rr['abook_id'],
'deletelink' => z_root() . '/connedit/' . intval($rr['abook_id']) . '/drop', 'deletelink' => z_root() . '/connedit/' . intval($rr['abook_id']) . '/drop',
@ -303,7 +312,7 @@ class Connections extends \Zotlabs\Web\Controller {
'$finding' => (($searching) ? t('Connections search') . ": '" . $search . "'" : ""), '$finding' => (($searching) ? t('Connections search') . ": '" . $search . "'" : ""),
'$submit' => t('Find'), '$submit' => t('Find'),
'$edit' => t('Edit'), '$edit' => t('Edit'),
'$cmd' => \App::$cmd, '$cmd' => App::$cmd,
'$contacts' => $contacts, '$contacts' => $contacts,
'$paginate' => paginate($a), '$paginate' => paginate($a),

View file

@ -74,15 +74,6 @@ class Connedit extends Controller {
$channel = App::get_channel(); $channel = App::get_channel();
// TODO if configured for hassle-free permissions, we'll post the form with ajax as soon as the
// connection enable is toggled to a special autopost url and set permissions immediately, leaving
// the other form elements alone pending a manual submit of the form. The downside is that there
// will be a window of opportunity when the permissions have been set but before you've had a chance
// to review and possibly restrict them. The upside is we won't have to warn you that your connection
// can't do anything until you save the bloody form.
$autopost = (((argc() > 2) && (argv(2) === 'auto')) ? true : false);
$orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1", $orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1",
intval($contact_id), intval($contact_id),
intval(local_channel()) intval(local_channel())
@ -127,6 +118,7 @@ class Connedit extends Controller {
$abook_incl = ((array_key_exists('abook_incl',$_POST)) ? escape_tags($_POST['abook_incl']) : $orig_record[0]['abook_incl']); $abook_incl = ((array_key_exists('abook_incl',$_POST)) ? escape_tags($_POST['abook_incl']) : $orig_record[0]['abook_incl']);
$abook_excl = ((array_key_exists('abook_excl',$_POST)) ? escape_tags($_POST['abook_excl']) : $orig_record[0]['abook_excl']); $abook_excl = ((array_key_exists('abook_excl',$_POST)) ? escape_tags($_POST['abook_excl']) : $orig_record[0]['abook_excl']);
$abook_alias = ((array_key_exists('abook_alias',$_POST)) ? escape_tags(trim($_POST['abook_alias'])) : $orig_record[0]['abook_alias']);
$hidden = intval($_POST['hidden']); $hidden = intval($_POST['hidden']);
@ -184,13 +176,14 @@ class Connedit extends Controller {
$abook_pending = (($new_friend) ? 0 : $orig_record[0]['abook_pending']); $abook_pending = (($new_friend) ? 0 : $orig_record[0]['abook_pending']);
$r = q("UPDATE abook SET abook_profile = '%s', abook_closeness = %d, abook_pending = %d, $r = q("UPDATE abook SET abook_profile = '%s', abook_closeness = %d, abook_pending = %d,
abook_incl = '%s', abook_excl = '%s' abook_incl = '%s', abook_excl = '%s', abook_alias = '%s'
where abook_id = %d AND abook_channel = %d", where abook_id = %d AND abook_channel = %d",
dbesc($profile_id), dbesc($profile_id),
intval($closeness), intval($closeness),
intval($abook_pending), intval($abook_pending),
dbesc($abook_incl), dbesc($abook_incl),
dbesc($abook_excl), dbesc($abook_excl),
dbesc($abook_alias),
intval($contact_id), intval($contact_id),
intval(local_channel()) intval(local_channel())
); );
@ -248,7 +241,6 @@ class Connedit extends Controller {
} }
// pull in a bit of content if there is any to pull in // pull in a bit of content if there is any to pull in
Master::Summon( [ 'Onepoll', $contact_id ]); Master::Summon( [ 'Onepoll', $contact_id ]);
@ -287,9 +279,9 @@ class Connedit extends Controller {
function connedit_clone(&$a) { function connedit_clone(&$a) {
if(! App::$poi) if (! App::$poi) {
return; return;
}
$channel = App::get_channel(); $channel = App::get_channel();
@ -310,10 +302,10 @@ class Connedit extends Controller {
unset($clone['abook_channel']); unset($clone['abook_channel']);
$abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']); $abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
if($abconfig) if ($abconfig) {
$clone['abconfig'] = $abconfig; $clone['abconfig'] = $abconfig;
}
Libsync::build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone))); Libsync::build_sync_packet($channel['channel_id'], [ 'abook' => [ $clone ] ] );
} }
/* @brief Generate content of connection edit page /* @brief Generate content of connection edit page
@ -441,6 +433,15 @@ class Connedit extends Controller {
goaway(z_root() . '/connedit/' . $contact_id); goaway(z_root() . '/connedit/' . $contact_id);
} }
if($cmd === 'censor') {
if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_CENSORED)) {
$this->connedit_clone($a);
}
else
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
if($cmd === 'archive') { if($cmd === 'archive') {
if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_ARCHIVED)) { if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_ARCHIVED)) {
$this->connedit_clone($a); $this->connedit_clone($a);
@ -575,6 +576,14 @@ class Connedit extends Controller {
'info' => (intval($contact['abook_ignored']) ? t('This connection is ignored!') : ''), 'info' => (intval($contact['abook_ignored']) ? t('This connection is ignored!') : ''),
), ),
'censor' => array(
'label' => (intval($contact['abook_censor']) ? t('Uncensor') : t('Censor')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/censor',
'sel' => (intval($contact['abook_censor']) ? 'active' : ''),
'title' => t('Censor (or Uncensor) images from this connection'),
'info' => (intval($contact['abook_censor']) ? t('This connection is censored!') : ''),
),
'archive' => array( 'archive' => array(
'label' => (intval($contact['abook_archived']) ? t('Unarchive') : t('Archive')), 'label' => (intval($contact['abook_archived']) ? t('Unarchive') : t('Archive')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/archive', 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/archive',
@ -637,13 +646,13 @@ class Connedit extends Controller {
$tpl = get_markup_template("abook_edit.tpl"); $tpl = get_markup_template("abook_edit.tpl");
if(Apps::system_app_installed(local_channel(),'Affinity Tool')) { if(Apps::system_app_installed(local_channel(),'Friend Zoom')) {
$sections['affinity'] = [ $sections['affinity'] = [
'label' => t('Affinity'), 'label' => t('Friend Zoom'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/?f=&section=affinity', 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/?f=&section=affinity',
'sel' => '', 'sel' => '',
'title' => t('Open Set Affinity section by default'), 'title' => t('Open Friend Zoom section by default'),
]; ];
$labels = [ $labels = [
@ -714,13 +723,13 @@ class Connedit extends Controller {
$multiprofs = ((feature_enabled(local_channel(),'multi_profiles')) ? true : false); $multiprofs = ((feature_enabled(local_channel(),'multi_profiles')) ? true : false);
if($slide && !$multiprofs) if($slide && !$multiprofs)
$affinity = t('Set Affinity'); $affinity = t('Set Friend Zoom');
if(!$slide && $multiprofs) if(!$slide && $multiprofs)
$affinity = t('Set Profile'); $affinity = t('Set Profile');
if($slide && $multiprofs) if($slide && $multiprofs)
$affinity = t('Set Affinity & Profile'); $affinity = t('Set Friend Zoom & Profile');
$theirs = get_abconfig(local_channel(),$contact['abook_xchan'],'system','their_perms',EMPTY_STR); $theirs = get_abconfig(local_channel(),$contact['abook_xchan'],'system','their_perms',EMPTY_STR);
@ -776,7 +785,7 @@ class Connedit extends Controller {
$not_here = t('This connection is unreachable from this location. Location independence is not supported by their network.'); $not_here = t('This connection is unreachable from this location. Location independence is not supported by their network.');
$o .= replace_macros($tpl, [ $o .= replace_macros($tpl, [
'$header' => (($self) ? t('Connection Default Permissions') : sprintf( t('Connection: %s'),$contact['xchan_name'])), '$header' => (($self) ? t('Connection Default Permissions') : sprintf( t('Connection: %s'),$contact['xchan_name']) . (($contact['abook_alias']) ? ' &lt;' . $contact['abook_alias'] . '&gt;' : '')),
'$autoperms' => array('autoperms',t('Apply these permissions automatically'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('Connection requests will be approved without your interaction'), $yes_no), '$autoperms' => array('autoperms',t('Apply these permissions automatically'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('Connection requests will be approved without your interaction'), $yes_no),
'$permcat' => [ 'permcat', t('Permission role'), '', '<span class="loading invisible">' . t('Loading') . '<span class="jumping-dots"><span class="dot-1">.</span><span class="dot-2">.</span><span class="dot-3">.</span></span></span>',$permcats ], '$permcat' => [ 'permcat', t('Permission role'), '', '<span class="loading invisible">' . t('Loading') . '<span class="jumping-dots"><span class="dot-1">.</span><span class="dot-2">.</span><span class="dot-3">.</span></span></span>',$permcats ],
'$permcat_new' => t('Add permission role'), '$permcat_new' => t('Add permission role'),
@ -803,6 +812,7 @@ class Connedit extends Controller {
'$connfilter_label' => t('Custom Filter'), '$connfilter_label' => t('Custom Filter'),
'$incl' => array('abook_incl',t('Only import posts with this text'), $contact['abook_incl'],t('words one per line or #tags, $categories, /patterns/, or lang=xx, leave blank to import all posts')), '$incl' => array('abook_incl',t('Only import posts with this text'), $contact['abook_incl'],t('words one per line or #tags, $categories, /patterns/, or lang=xx, leave blank to import all posts')),
'$excl' => array('abook_excl',t('Do not import posts with this text'), $contact['abook_excl'],t('words one per line or #tags, $categories, /patterns/, or lang=xx, leave blank to import all posts')), '$excl' => array('abook_excl',t('Do not import posts with this text'), $contact['abook_excl'],t('words one per line or #tags, $categories, /patterns/, or lang=xx, leave blank to import all posts')),
'$alias' => array('abook_alias',t('Nickname'), $contact['abook_alias'],t('optional - allows you to search by a name that you have chosen')),
'$rating_text' => array('rating_text', t('Optionally explain your rating'),$rating_text,''), '$rating_text' => array('rating_text', t('Optionally explain your rating'),$rating_text,''),
'$rating_info' => t('This information is public!'), '$rating_info' => t('This information is public!'),
'$rating' => $rating, '$rating' => $rating,

View file

@ -38,7 +38,7 @@ class Contactgroup extends Controller {
killme(); killme();
} }
$members = AccessList::members($group['id']); $members = AccessList::members(local_channel(),$group['id']);
$preselected = ids_to_array($members,'xchan_hash'); $preselected = ids_to_array($members,'xchan_hash');
if ($change) { if ($change) {

View file

@ -1,6 +1,7 @@
<?php <?php
namespace Zotlabs\Module; namespace Zotlabs\Module;
use App;
use Zotlabs\Lib\Activity; use Zotlabs\Lib\Activity;
use Zotlabs\Lib\Libprofile; use Zotlabs\Lib\Libprofile;
use Zotlabs\Access\AccessControl; use Zotlabs\Access\AccessControl;
@ -12,6 +13,7 @@ use Zotlabs\Web\Controller;
*/ */
require_once('include/attach.php');
require_once('include/photo_factory.php'); require_once('include/photo_factory.php');
require_once('include/photos.php'); require_once('include/photos.php');
@ -25,14 +27,14 @@ require_once('include/photos.php');
*/ */
class Cover_photo extends \Zotlabs\Web\Controller { class Cover_photo extends Controller {
function init() { function init() {
if (! local_channel()) { if (! local_channel()) {
return; return;
} }
$channel = \App::get_channel(); $channel = App::get_channel();
Libprofile::load($channel['channel_address']); Libprofile::load($channel['channel_address']);
} }
@ -49,7 +51,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
return; return;
} }
$channel = \App::get_channel(); $channel = App::get_channel();
check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo'); check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
@ -80,7 +82,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
intval(local_channel()) intval(local_channel())
); );
if ($r) { if ($r) {
$profile = $r[0]; $profile = array_shift($r);
} }
$r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND imgscale > 0 order by imgscale asc LIMIT 1", $r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND imgscale > 0 order by imgscale asc LIMIT 1",
@ -121,7 +123,7 @@ logger('gis: ' . print_r($gis,true));
} }
if (! $iscaled) { if (! $iscaled) {
$base_image = $r[0]; $base_image = $r[0];
$base_image['content'] = (($r[0]['os_storage']) ? @file_get_contents(dbunescbin($base_image['content'])) : dbunescbin($base_image['content'])); $base_image['content'] = (($base_image['os_storage']) ? @file_get_contents(dbunescbin($base_image['content'])) : dbunescbin($base_image['content']));
} }
$im = photo_factory($base_image['content'], $base_image['mimetype']); $im = photo_factory($base_image['content'], $base_image['mimetype']);
@ -179,18 +181,17 @@ logger('gis: ' . print_r($gis,true));
$p['imgscale'] = 7; $p['imgscale'] = 7;
$p['photo_usage'] = PHOTO_COVER; $p['photo_usage'] = PHOTO_COVER;
$r1 = $im->save($p); $r1 = $im->storeThumbnail($p, PHOTO_RES_COVER_1200);
$im->doScaleImage(850,310); $im->doScaleImage(850,310);
$p['imgscale'] = 8; $p['imgscale'] = 8;
$r2 = $im->save($p); $r2 = $im->storeThumbnail($p, PHOTO_RES_COVER_850);
$im->doScaleImage(425,160); $im->doScaleImage(425,160);
$p['imgscale'] = 9; $p['imgscale'] = 9;
$r3 = $im->save($p); $r3 = $im->storeThumbnail($p, PHOTO_RES_COVER_425);
if ($r1 === false || $r2 === false || $r3 === false) { if ($r1 === false || $r2 === false || $r3 === false) {
// if one failed, delete them all so we can start over. // if one failed, delete them all so we can start over.
@ -202,7 +203,7 @@ logger('gis: ' . print_r($gis,true));
return; return;
} }
$channel = \App::get_channel(); $channel = App::get_channel();
$this->send_cover_photo_activity($channel,$base_image,$profile); $this->send_cover_photo_activity($channel,$base_image,$profile);
@ -219,8 +220,6 @@ logger('gis: ' . print_r($gis,true));
$hash = photo_new_resource(); $hash = photo_new_resource();
$smallest = 0; $smallest = 0;
require_once('include/attach.php');
$matches = []; $matches = [];
$partial = false; $partial = false;
@ -263,9 +262,9 @@ logger('gis: ' . print_r($gis,true));
} }
} }
$res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Cover Photos'), 'hash' => $hash)); $res = attach_store(App::get_channel(), get_observer_hash(), '', array('album' => t('Cover Photos'), 'hash' => $hash));
logger('attach_store: ' . print_r($res,true)); logger('attach_store: ' . print_r($res,true),LOGGER_DEBUG);
json_return_and_die([ 'message' => $hash ]); json_return_and_die([ 'message' => $hash ]);
@ -273,7 +272,7 @@ logger('gis: ' . print_r($gis,true));
function send_cover_photo_activity($channel,$photo,$profile) { function send_cover_photo_activity($channel,$photo,$profile) {
$arr = array(); $arr = [];
$arr['item_thread_top'] = 1; $arr['item_thread_top'] = 1;
$arr['item_origin'] = 1; $arr['item_origin'] = 1;
$arr['item_wall'] = 1; $arr['item_wall'] = 1;
@ -282,12 +281,15 @@ logger('gis: ' . print_r($gis,true));
$arr['obj_type'] = ACTIVITY_OBJ_NOTE; $arr['obj_type'] = ACTIVITY_OBJ_NOTE;
$arr['verb'] = ACTIVITY_CREATE; $arr['verb'] = ACTIVITY_CREATE;
if($profile && stripos($profile['gender'],t('female')) !== false) if ($profile && stripos($profile['gender'],t('female')) !== false) {
$t = t('%1$s updated her %2$s'); $t = t('%1$s updated her %2$s');
elseif($profile && stripos($profile['gender'],t('male')) !== false) }
elseif ($profile && stripos($profile['gender'],t('male')) !== false) {
$t = t('%1$s updated his %2$s'); $t = t('%1$s updated his %2$s');
else }
else {
$t = t('%1$s updated their %2$s'); $t = t('%1$s updated their %2$s');
}
$ptext = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo['resource_id'] . ']' . t('cover photo') . '[/zrl]'; $ptext = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo['resource_id'] . ']' . t('cover photo') . '[/zrl]';
@ -341,7 +343,7 @@ logger('gis: ' . print_r($gis,true));
return; return;
} }
$channel = \App::get_channel(); $channel = App::get_channel();
$newuser = false; $newuser = false;
@ -368,9 +370,10 @@ logger('gis: ' . print_r($gis,true));
} }
$havescale = false; $havescale = false;
foreach ($r as $rr) { foreach ($r as $rr) {
if($rr['imgscale'] == 7) if ($rr['imgscale'] == 7) {
$havescale = true; $havescale = true;
} }
}
$r = q("SELECT content, mimetype, resource_id, os_storage FROM photo WHERE id = %d and uid = %d limit 1", $r = q("SELECT content, mimetype, resource_id, os_storage FROM photo WHERE id = %d and uid = %d limit 1",
intval($r[0]['id']), intval($r[0]['id']),
@ -382,10 +385,12 @@ logger('gis: ' . print_r($gis,true));
return; return;
} }
if(intval($r[0]['os_storage'])) if (intval($r[0]['os_storage'])) {
$data = @file_get_contents(dbunescbin($r[0]['content'])); $data = @file_get_contents(dbunescbin($r[0]['content']));
else }
else {
$data = dbunescbin($r[0]['content']); $data = dbunescbin($r[0]['content']);
}
$ph = photo_factory($data, $r[0]['mimetype']); $ph = photo_factory($data, $r[0]['mimetype']);
$smallest = 0; $smallest = 0;
@ -404,16 +409,14 @@ logger('gis: ' . print_r($gis,true));
} }
} }
$this->cover_photo_crop_ui_head($a, $ph, $hash, $smallest); $this->cover_photo_crop_ui_head($ph, $hash, $smallest);
} }
if(! x(\App::$data,'imagecrop')) { if(! array_key_exists('imagecrop',App::$data)) {
$tpl = get_markup_template('cover_photo.tpl'); $o .= replace_macros(get_markup_template('cover_photo.tpl'), [
'$user' => App::$channel['channel_address'],
$o .= replace_macros($tpl,array(
'$user' => \App::$channel['channel_address'],
'$info' => t('Your cover photo may be visible to anybody on the internet'), '$info' => t('Your cover photo may be visible to anybody on the internet'),
'$existing' => get_cover_photo(local_channel(),'array',PHOTO_RES_COVER_850), '$existing' => get_cover_photo(local_channel(),'array',PHOTO_RES_COVER_850),
'$lbl_upfile' => t('Upload File:'), '$lbl_upfile' => t('Upload File:'),
@ -432,20 +435,19 @@ logger('gis: ' . print_r($gis,true));
'$modalerrorlink' => t('Error getting photo link'), '$modalerrorlink' => t('Error getting photo link'),
'$modalerroralbum' => t('Error getting album'), '$modalerroralbum' => t('Error getting album'),
'$form_security_token' => get_form_security_token("cover_photo"), '$form_security_token' => get_form_security_token("cover_photo"),
/// @FIXME - yuk '$select' => t('Select previously uploaded photo'),
'$select' => t('Select existing photo'),
)); ]);
call_hooks('cover_photo_content_end', $o); call_hooks('cover_photo_content_end', $o);
return $o; return $o;
} }
else { else {
$filename = \App::$data['imagecrop'] . '-3'; $filename = App::$data['imagecrop'] . '-3';
$resolution = 3; $resolution = 3;
$tpl = get_markup_template("cropcover.tpl");
$o .= replace_macros($tpl,array( $o .= replace_macros(get_markup_template('cropcover.tpl'), [
'$filename' => $filename, '$filename' => $filename,
'$profile' => intval($_REQUEST['profile']), '$profile' => intval($_REQUEST['profile']),
'$resource' => \App::$data['imagecrop'] . '-3', '$resource' => \App::$data['imagecrop'] . '-3',
@ -454,11 +456,9 @@ logger('gis: ' . print_r($gis,true));
'$desc' => t('Please adjust the image cropping for optimum viewing.'), '$desc' => t('Please adjust the image cropping for optimum viewing.'),
'$form_security_token' => get_form_security_token("cover_photo"), '$form_security_token' => get_form_security_token("cover_photo"),
'$done' => t('Done Editing') '$done' => t('Done Editing')
)); ]);
return $o; return $o;
} }
return; // NOTREACHED
} }
/* @brief Generate the UI for photo-cropping /* @brief Generate the UI for photo-cropping
@ -469,13 +469,15 @@ logger('gis: ' . print_r($gis,true));
* *
*/ */
function cover_photo_crop_ui_head(&$a, $ph, $hash, $smallest){ function cover_photo_crop_ui_head($ph, $hash, $smallest){
$max_length = get_config('system','max_image_length'); $max_length = get_config('system','max_image_length');
if(! $max_length) if (! $max_length) {
$max_length = MAX_IMAGE_LENGTH; $max_length = MAX_IMAGE_LENGTH;
if($max_length > 0) }
if ($max_length > 0) {
$ph->scaleImage($max_length); $ph->scaleImage($max_length);
}
$width = $ph->getWidth(); $width = $ph->getWidth();
$height = $ph->getHeight(); $height = $ph->getHeight();
@ -487,9 +489,9 @@ logger('gis: ' . print_r($gis,true));
} }
\App::$data['imagecrop'] = $hash; App::$data['imagecrop'] = $hash;
\App::$data['imagecrop_resolution'] = $smallest; App::$data['imagecrop_resolution'] = $smallest;
\App::$page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), array()); App::$page['htmlhead'] .= replace_macros(get_markup_template('crophead.tpl'), []);
return; return;
} }

View file

@ -96,6 +96,8 @@ class Dav extends Controller {
$auth = new \Zotlabs\Storage\BasicAuth(); $auth = new \Zotlabs\Storage\BasicAuth();
$auth->observer = get_observer_hash();
$auth->setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . ' ' . 'WebDAV'); $auth->setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . ' ' . 'WebDAV');
$rootDirectory = new \Zotlabs\Storage\Directory('/', $auth); $rootDirectory = new \Zotlabs\Storage\Directory('/', $auth);

View file

@ -42,10 +42,10 @@ class Dircensor extends Controller {
info( t('Entry censored') . EOL); info( t('Entry censored') . EOL);
} }
else { else {
info( t('Entry censored') . EOL); info( t('Entry uncensored') . EOL);
} }
return; goaway(z_root() . '/directory');
} }

View file

@ -25,7 +25,9 @@ class Directory extends Controller {
); );
Libsync::build_sync_packet(local_channel(), [ 'xign' => [ [ 'uid' => local_channel(), 'xchan' => $_GET['ignore'] ]]] ); Libsync::build_sync_packet(local_channel(), [ 'xign' => [ [ 'uid' => local_channel(), 'xchan' => $_GET['ignore'] ]]] );
if ($_REQUEST['return']) {
goaway(z_root() . '/' . base64_decode($_REQUEST['return']));
}
goaway(z_root() . '/directory?f=&suggest=1'); goaway(z_root() . '/directory?f=&suggest=1');
} }
@ -34,8 +36,6 @@ class Directory extends Controller {
$safe_changed = false; $safe_changed = false;
$type_changed = false; $type_changed = false;
if (array_key_exists('global',$_REQUEST)) { if (array_key_exists('global',$_REQUEST)) {
$globaldir = intval($_REQUEST['global']); $globaldir = intval($_REQUEST['global']);
if (get_config('system','localdir_hide')) { if (get_config('system','localdir_hide')) {
@ -45,9 +45,10 @@ class Directory extends Controller {
} }
if ($global_changed) { if ($global_changed) {
$_SESSION['globaldir'] = $globaldir; $_SESSION['globaldir'] = $globaldir;
if($observer) if ($observer) {
set_xconfig($observer,'directory','globaldir',$globaldir); set_xconfig($observer,'directory','globaldir',$globaldir);
} }
}
if (array_key_exists('safe',$_REQUEST)) { if (array_key_exists('safe',$_REQUEST)) {
$safemode = intval($_REQUEST['safe']); $safemode = intval($_REQUEST['safe']);
@ -55,10 +56,10 @@ class Directory extends Controller {
} }
if ($safe_changed) { if ($safe_changed) {
$_SESSION['safemode'] = $safemode; $_SESSION['safemode'] = $safemode;
if($observer) if ($observer) {
set_xconfig($observer,'directory','safemode',$safemode); set_xconfig($observer,'directory','safemode',$safemode);
} }
}
if (array_key_exists('type',$_REQUEST)) { if (array_key_exists('type',$_REQUEST)) {
$type = intval($_REQUEST['type']); $type = intval($_REQUEST['type']);
@ -66,10 +67,11 @@ class Directory extends Controller {
} }
if ($type_changed) { if ($type_changed) {
$_SESSION['chantype'] = $type; $_SESSION['chantype'] = $type;
if($observer) if ($observer) {
set_xconfig($observer,'directory','chantype',$type); set_xconfig($observer,'directory','chantype',$type);
} }
} }
}
function get() { function get() {
@ -78,18 +80,19 @@ class Directory extends Controller {
return; return;
} }
if(get_config('system','block_public_directory',false) && (! get_observer_hash())) { $observer = get_observer_hash();
if (get_config('system','block_public_directory',false) && (! $observer)) {
notice( t('Public access denied.') . EOL); notice( t('Public access denied.') . EOL);
return; return;
} }
$observer = get_observer_hash();
$globaldir = Libzotdir::get_directory_setting($observer, 'globaldir'); $globaldir = Libzotdir::get_directory_setting($observer, 'globaldir');
// override your personal global search pref if we're doing a navbar search of the directory // override your personal global search pref if we're doing a navbar search of the directory
if(intval($_REQUEST['navsearch'])) if (intval($_REQUEST['navsearch'])) {
$globaldir = 1; $globaldir = 1;
}
$safe_mode = Libzotdir::get_directory_setting($observer, 'safemode'); $safe_mode = Libzotdir::get_directory_setting($observer, 'safemode');
@ -98,14 +101,16 @@ class Directory extends Controller {
$o = ''; $o = '';
nav_set_selected('Directory'); nav_set_selected('Directory');
if(x($_POST,'search')) if (x($_POST,'search')) {
$search = notags(trim($_POST['search'])); $search = notags(trim($_POST['search']));
else }
else {
$search = ((x($_GET,'search')) ? notags(trim(rawurldecode($_GET['search']))) : ''); $search = ((x($_GET,'search')) ? notags(trim(rawurldecode($_GET['search']))) : '');
}
if (strpos($search,'=')) {
if(strpos($search,'=') && local_channel() && feature_enabled(local_channel(), 'advanced_dirsearch'))
$advanced = $search; $advanced = $search;
}
$keywords = (($_GET['keywords']) ? $_GET['keywords'] : ''); $keywords = (($_GET['keywords']) ? $_GET['keywords'] : '');
@ -120,7 +125,6 @@ class Directory extends Controller {
$safe_mode = 1; $safe_mode = 1;
$type = 0; $type = 0;
// only return DIRECTORY_PAGESIZE suggestions as the suggestion sorting // only return DIRECTORY_PAGESIZE suggestions as the suggestion sorting
// only works if the suggestion query and the directory query have the // only works if the suggestion query and the directory query have the
// same number of results // same number of results
@ -173,7 +177,6 @@ class Directory extends Controller {
$token = get_config('system','realm_token'); $token = get_config('system','realm_token');
logger('mod_directory: URL = ' . $url, LOGGER_DEBUG); logger('mod_directory: URL = ' . $url, LOGGER_DEBUG);
$contacts = array(); $contacts = array();
@ -183,10 +186,11 @@ class Directory extends Controller {
intval(local_channel()) intval(local_channel())
); );
if ($x) { if ($x) {
foreach($x as $xx) foreach ($x as $xx) {
$contacts[] = $xx['abook_xchan']; $contacts[] = $xx['abook_xchan'];
} }
} }
}
if ($url) { if ($url) {
@ -194,39 +198,48 @@ class Directory extends Controller {
$kw = ((intval($numtags) > 0) ? intval($numtags) : 50); $kw = ((intval($numtags) > 0) ? intval($numtags) : 50);
if(get_config('system','disable_directory_keywords')) if (get_config('system','disable_directory_keywords')) {
$kw = 0; $kw = 0;
}
$query = $url . '?f=&kw=' . $kw . (($safe_mode != 1) ? '&safe=' . $safe_mode : ''); $query = $url . '?f=&kw=' . $kw . (($safe_mode != 1) ? '&safe=' . $safe_mode : '');
if($token) if ($token) {
$query .= '&t=' . $token; $query .= '&t=' . $token;
}
if(! $globaldir) if (! $globaldir) {
$query .= '&hub=' . App::get_hostname(); $query .= '&hub=' . App::get_hostname();
}
if($search) if ($search) {
$query .= '&name=' . urlencode($search) . '&keywords=' . urlencode($search); $query .= '&name=' . urlencode($search) . '&keywords=' . urlencode($search);
if(strpos($search,'@')) }
if (strpos($search,'@')) {
$query .= '&address=' . urlencode($search); $query .= '&address=' . urlencode($search);
if($keywords) }
if ($keywords) {
$query .= '&keywords=' . urlencode($keywords); $query .= '&keywords=' . urlencode($keywords);
if($advanced) }
if ($advanced) {
$query .= '&query=' . urlencode($advanced); $query .= '&query=' . urlencode($advanced);
if(! is_null($type)) }
if (! is_null($type)) {
$query .= '&type=' . intval($type); $query .= '&type=' . intval($type);
}
$directory_sort_order = get_config('system','directory_sort_order'); $directory_sort_order = get_config('system','directory_sort_order');
if(! $directory_sort_order) if (! $directory_sort_order) {
$directory_sort_order = 'date'; $directory_sort_order = 'date';
}
$sort_order = ((x($_REQUEST,'order')) ? $_REQUEST['order'] : $directory_sort_order); $sort_order = ((x($_REQUEST,'order')) ? $_REQUEST['order'] : $directory_sort_order);
if($sort_order) if ($sort_order) {
$query .= '&order=' . urlencode($sort_order); $query .= '&order=' . urlencode($sort_order);
}
if(App::$pager['page'] != 1) if (App::$pager['page'] != 1) {
$query .= '&p=' . App::$pager['page']; $query .= '&p=' . App::$pager['page'];
}
logger('mod_directory: query: ' . $query); logger('mod_directory: query: ' . $query);
@ -261,54 +274,52 @@ class Directory extends Controller {
//$online = remote_online_status($rr['address']); //$online = remote_online_status($rr['address']);
$online = ''; $online = '';
if(in_array($rr['hash'],$contacts)) if (in_array($rr['hash'],$contacts)) {
$connect_link = ''; $connect_link = '';
}
$location = ''; $location = '';
if(strlen($rr['locale'])) if (strlen($rr['locale'])) {
$location .= $rr['locale']; $location .= $rr['locale'];
}
if (strlen($rr['region'])) { if (strlen($rr['region'])) {
if(strlen($rr['locale'])) if (strlen($rr['locale'])) {
$location .= ', '; $location .= ', ';
}
$location .= $rr['region']; $location .= $rr['region'];
} }
if (strlen($rr['country'])) { if (strlen($rr['country'])) {
if(strlen($location)) if (strlen($location)) {
$location .= ', '; $location .= ', ';
}
$location .= $rr['country']; $location .= $rr['country'];
} }
$age = ''; $age = '';
if (strlen($rr['birthday'])) { if (strlen($rr['birthday'])) {
if(($years = age($rr['birthday'],'UTC','')) > 0) if (($years = age($rr['birthday'],'UTC','')) > 0) {
$age = $years; $age = $years;
} }
}
$page_type = ''; $page_type = '';
$rating_enabled = get_config('system','rating_enabled'); $rating_enabled = get_config('system','rating_enabled');
if($rr['total_ratings'] && $rating_enabled) if ($rr['total_ratings'] && $rating_enabled) {
$total_ratings = sprintf( tt("%d rating", "%d ratings", $rr['total_ratings']), $rr['total_ratings']); $total_ratings = sprintf( tt("%d rating", "%d ratings", $rr['total_ratings']), $rr['total_ratings']);
else }
else {
$total_ratings = ''; $total_ratings = '';
}
$profile = $rr; $profile = $rr;
if ((x($profile,'locale') == 1)
|| (x($profile,'region') == 1)
|| (x($profile,'postcode') == 1)
|| (x($profile,'country') == 1))
$gender = ((x($profile,'gender') == 1) ? t('Gender: ') . $profile['gender']: False); $gender = ((x($profile,'gender') == 1) ? t('Gender: ') . $profile['gender']: False);
$marital = ((x($profile,'marital') == 1) ? t('Status: ') . $profile['marital']: False); $marital = ((x($profile,'marital') == 1) ? t('Status: ') . $profile['marital']: False);
$homepage = ((x($profile,'homepage') == 1) ? t('Homepage: ') : False); $homepage = ((x($profile,'homepage') == 1) ? t('Homepage: ') : False);
$homepageurl = ((x($profile,'homepage') == 1) ? html2plain($profile['homepage']) : ''); $homepageurl = ((x($profile,'homepage') == 1) ? html2plain($profile['homepage']) : '');
$hometown = ((x($profile,'hometown') == 1) ? html2plain($profile['hometown']) : False); $hometown = ((x($profile,'hometown') == 1) ? html2plain($profile['hometown']) : False);
$about = ((x($profile,'about') == 1) ? zidify_links(bbcode($profile['about'])) : False); $about = ((x($profile,'about') == 1) ? zidify_links(bbcode($profile['about'])) : False);
if ($about && $safe_mode) { if ($about && $safe_mode) {
$about = html2plain($about); $about = html2plain($about);
@ -316,7 +327,6 @@ class Directory extends Controller {
$keywords = ((x($profile,'keywords')) ? $profile['keywords'] : ''); $keywords = ((x($profile,'keywords')) ? $profile['keywords'] : '');
$out = ''; $out = '';
if ($keywords) { if ($keywords) {
@ -326,28 +336,30 @@ class Directory extends Controller {
if ($karr) { if ($karr) {
if (local_channel()) { if (local_channel()) {
$r = q("select keywords from profile where uid = %d and is_default = 1 limit 1", $pk = q("select keywords from profile where uid = %d and is_default = 1 limit 1",
intval(local_channel()) intval(local_channel())
); );
if($r) { if ($pk) {
$keywords = str_replace(',',' ', $r[0]['keywords']); $keywords = str_replace(',',' ', $pk[0]['keywords']);
$keywords = str_replace(' ',' ', $keywords); $keywords = str_replace(' ',' ', $keywords);
$marr = explode(' ', $keywords); $marr = explode(' ', $keywords);
} }
} }
foreach ($karr as $k) { foreach ($karr as $k) {
if(strlen($out)) if (strlen($out)) {
$out .= ', '; $out .= ', ';
if($marr && in_arrayi($k,$marr)) }
if ($marr && in_arrayi($k,$marr)) {
$out .= '<a href="' . z_root() . '/directory/f=&keywords=' . urlencode($k) .'"><strong>' . $k . '</strong></a>'; $out .= '<a href="' . z_root() . '/directory/f=&keywords=' . urlencode($k) .'"><strong>' . $k . '</strong></a>';
else }
else {
$out .= '<a href="' . z_root() . '/directory/f=&keywords=' . urlencode($k) .'">' . $k . '</a>'; $out .= '<a href="' . z_root() . '/directory/f=&keywords=' . urlencode($k) .'">' . $k . '</a>';
} }
} }
}
} }
$entry = array( $entry = [
'id' => ++ $t, 'id' => ++ $t,
'profile_link' => $profile_link, 'profile_link' => $profile_link,
'type' => $rr['type'], 'type' => $rr['type'],
@ -390,7 +402,7 @@ class Directory extends Controller {
'common_label' => t('Common connections (estimated):'), 'common_label' => t('Common connections (estimated):'),
'common_count' => intval($common[$rr['address']]), 'common_count' => intval($common[$rr['address']]),
'safe' => $safe_mode 'safe' => $safe_mode
); ];
$arr = array('contact' => $rr, 'entry' => $entry); $arr = array('contact' => $rr, 'entry' => $entry);
@ -406,7 +418,6 @@ class Directory extends Controller {
if ($sort_order == '' && $suggest) { if ($sort_order == '' && $suggest) {
$entries[$addresses[$rr['address']]] = $arr['entry']; // Use the same indexes as originally to get the best suggestion first $entries[$addresses[$rr['address']]] = $arr['entry']; // Use the same indexes as originally to get the best suggestion first
} }
else { else {
$entries[] = $arr['entry']; $entries[] = $arr['entry'];
} }
@ -423,9 +434,7 @@ class Directory extends Controller {
if ($_REQUEST['aj']) { if ($_REQUEST['aj']) {
if ($entries) { if ($entries) {
$o = replace_macros(get_markup_template('directajax.tpl'),array( $o = replace_macros(get_markup_template('directajax.tpl'), [ '$entries' => $entries ] );
'$entries' => $entries
));
} }
else { else {
$o = '<div id="content-complete"></div>'; $o = '<div id="content-complete"></div>';
@ -439,7 +448,7 @@ class Directory extends Controller {
$dirtitle = (($globaldir) ? t('Global Directory') : t('Local Directory')); $dirtitle = (($globaldir) ? t('Global Directory') : t('Local Directory'));
$o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['req'])) . "'; var extra_args = '" . extra_query_args() . "' ; divmore_height = " . intval($maxheight) . "; </script>"; $o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['req'])) . "'; var extra_args = '" . extra_query_args() . "' ; divmore_height = " . intval($maxheight) . "; </script>";
$o .= replace_macros($tpl, array( $o .= replace_macros($tpl, [
'$search' => $search, '$search' => $search,
'$desc' => t('Find'), '$desc' => t('Find'),
'$finddsc' => t('Finding:'), '$finddsc' => t('Finding:'),
@ -454,11 +463,8 @@ class Directory extends Controller {
'$date' => t('Newest to Oldest'), '$date' => t('Newest to Oldest'),
'$reversedate' => t('Oldest to Newest'), '$reversedate' => t('Oldest to Newest'),
'$suggest' => $suggest ? '&suggest=1' : '' '$suggest' => $suggest ? '&suggest=1' : ''
)); ]);
} }
} }
else { else {
if ($_REQUEST['aj']) { if ($_REQUEST['aj']) {
@ -466,9 +472,19 @@ class Directory extends Controller {
echo $o; echo $o;
killme(); killme();
} }
if(\App::$pager['page'] == 1 && $j['records'] == 0 && strpos($search,'@')) { if (App::$pager['page'] == 1 && $j['records'] == 0) {
if (strpos($search,'@')) {
goaway(z_root() . '/chanview/?f=&address=' . $search); goaway(z_root() . '/chanview/?f=&address=' . $search);
} }
else {
$r = q("select xchan_hash from xchan where xchan_name = '%s' limit 1",
dbesc($search)
);
if ($r) {
goaway(z_root() . '/chanview/?f=&hash=' . urlencode($r[0]['xchan_hash']));
}
}
}
info( t("No entries (some entries may be hidden).") . EOL); info( t("No entries (some entries may be hidden).") . EOL);
} }
} }
@ -479,11 +495,9 @@ class Directory extends Controller {
static public function reorder_results($results,$suggests) { static public function reorder_results($results,$suggests) {
if (! $suggests) {
// return $results;
if(! $suggests)
return $results; return $results;
}
$out = []; $out = [];
foreach ($suggests as $k => $v) { foreach ($suggests as $k => $v) {
@ -494,7 +508,6 @@ class Directory extends Controller {
} }
} }
} }
return $out; return $out;
} }

View file

@ -27,11 +27,13 @@ class Dirsearch extends Controller {
$dirmode = intval(get_config('system','directory_mode')); $dirmode = intval(get_config('system','directory_mode'));
if ($dirmode == DIRECTORY_MODE_NORMAL) { if ($dirmode == DIRECTORY_MODE_NORMAL && ! intval($_REQUEST['navsearch'])) {
$ret['message'] = t('This site is not a directory server'); $ret['message'] = t('This site is not a directory server');
json_return_and_die($ret); json_return_and_die($ret);
} }
$network = ((intval($_REQUEST['navsearch'])) ? EMPTY_STR : " AND xchan_network = 'zot6' ");
$access_token = $_REQUEST['t']; $access_token = $_REQUEST['t'];
@ -220,7 +222,7 @@ class Dirsearch extends Controller {
else { else {
$qlimit = " LIMIT " . intval($perpage) . " OFFSET " . intval($startrec); $qlimit = " LIMIT " . intval($perpage) . " OFFSET " . intval($startrec);
if ($return_total) { if ($return_total) {
$r = q("SELECT COUNT(xchan_hash) AS total FROM xchan left join xprof on xchan_hash = xprof_hash where $logic $sql_extra and xchan_network = 'zot6' and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0 $safesql "); $r = q("SELECT COUNT(xchan_hash) AS total FROM xchan left join xprof on xchan_hash = xprof_hash where $logic $sql_extra $network and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0 $safesql ");
if ($r) { if ($r) {
$ret['total_items'] = $r[0]['total']; $ret['total_items'] = $r[0]['total'];
} }
@ -299,7 +301,7 @@ class Dirsearch extends Controller {
// normal directory query // normal directory query
$r = q("SELECT xchan.*, xprof.* from xchan left join xprof on xchan_hash = xprof_hash $r = q("SELECT xchan.*, xprof.* from xchan left join xprof on xchan_hash = xprof_hash
where ( $logic $sql_extra ) $hub_query and xchan_network = 'zot6' and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0 where ( $logic $sql_extra ) $hub_query $network and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0
$safesql $order $qlimit " $safesql $order $qlimit "
); );
@ -353,7 +355,7 @@ class Dirsearch extends Controller {
$ret['results'] = $entries; $ret['results'] = $entries;
if ($kw) { if ($kw) {
$k = dir_tagadelic($kw, $hub, $type); $k = dir_tagadelic($kw, $hub, $type,$safesql);
if ($k) { if ($k) {
$ret['keywords'] = array(); $ret['keywords'] = array();
foreach ($k as $kv) { foreach ($k as $kv) {
@ -430,7 +432,7 @@ class Dirsearch extends Controller {
$quoted_string = false; $quoted_string = false;
} }
else else
$curr['value'] .= ' ' . trim(q); $curr['value'] .= ' ' . trim($q);
} }
} }
} }

View file

@ -180,6 +180,12 @@ class Display extends Controller {
return ''; return '';
} }
} }
if ($target_item['item_type'] == ITEM_TYPE_CUSTOM) {
call_hooks('item_custom_display',$target_item);
notice( t('Page not found.') . EOL);
return '';
}
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0); $static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
@ -224,6 +230,7 @@ class Display extends Controller {
'$conv' => '0', '$conv' => '0',
'$spam' => '0', '$spam' => '0',
'$fh' => '0', '$fh' => '0',
'$dm' => '0',
'$nouveau' => '0', '$nouveau' => '0',
'$wall' => '0', '$wall' => '0',
'$static' => $static, '$static' => $static,

View file

@ -2,15 +2,13 @@
namespace Zotlabs\Module; namespace Zotlabs\Module;
/** use App;
* @brief use Zotlabs\Web\Controller;
*
*/
class Embedphotos extends \Zotlabs\Web\Controller {
function get() { require_once('include/attach.php');
require_once('include/photos.php');
} class Embedphotos extends Controller {
/** /**
* *
@ -24,12 +22,12 @@ class Embedphotos extends \Zotlabs\Web\Controller {
if (! $name) { if (! $name) {
json_return_and_die(array('errormsg' => 'Error retrieving album', 'status' => false)); json_return_and_die(array('errormsg' => 'Error retrieving album', 'status' => false));
} }
$album = $this->embedphotos_widget_album(array('channel' => \App::get_channel(), 'album' => $name)); $album = $this->embedphotos_widget_album(array('channel_id' => local_channel(), 'album' => $name));
json_return_and_die(array('status' => true, 'content' => $album)); json_return_and_die(array('status' => true, 'content' => $album));
} }
if (argc() > 1 && argv(1) === 'albumlist') { if (argc() > 1 && argv(1) === 'albumlist') {
// API: /embedphotos/albumlist // API: /embedphotos/albumlist
$album_list = $this->embedphotos_album_list($a); $album_list = $this->embedphotos_album_list();
json_return_and_die(array('status' => true, 'albumlist' => $album_list)); json_return_and_die(array('status' => true, 'albumlist' => $album_list));
} }
if (argc() > 1 && argv(1) === 'photolink') { if (argc() > 1 && argv(1) === 'photolink') {
@ -41,8 +39,9 @@ class Embedphotos extends \Zotlabs\Web\Controller {
$resource_id = array_pop(explode("/", $href)); $resource_id = array_pop(explode("/", $href));
$x = self::photolink($resource_id); $x = self::photolink($resource_id);
if($x) if ($x) {
json_return_and_die(array('status' => true, 'photolink' => $x, 'resource_id' => $resource_id)); json_return_and_die(array('status' => true, 'photolink' => $x, 'resource_id' => $resource_id));
}
json_return_and_die(array('errormsg' => 'Error retrieving resource ' . $resource_id, 'status' => false)); json_return_and_die(array('errormsg' => 'Error retrieving resource ' . $resource_id, 'status' => false));
} }
@ -50,26 +49,31 @@ class Embedphotos extends \Zotlabs\Web\Controller {
protected static function photolink($resource) { protected static function photolink($resource) {
$channel = \App::get_channel(); $channel = App::get_channel();
$output = EMPTY_STR; $output = EMPTY_STR;
if ($channel) { if ($channel) {
$resolution = ((feature_enabled($channel['channel_id'],'large_photos')) ? 2 : 3); $resolution = ((feature_enabled($channel['channel_id'],'large_photos')) ? 1 : 2);
$r = q("select mimetype, height, width from photo where resource_id = '%s' and $resolution = %d and uid = %d limit 1", $r = q("select mimetype, height, width from photo where resource_id = '%s' and $resolution = %d and uid = %d limit 1",
dbesc($resource), dbesc($resource),
intval($resolution), intval($resolution),
intval($channel['channel_id']) intval($channel['channel_id'])
); );
if(! $r) if (! $r) {
return $output; return $output;
}
if($r[0]['mimetype'] === 'image/jpeg') if ($r[0]['mimetype'] === 'image/jpeg') {
$ext = '.jpg'; $ext = '.jpg';
elseif($r[0]['mimetype'] === 'image/png') }
elseif ($r[0]['mimetype'] === 'image/png') {
$ext = '.png'; $ext = '.png';
elseif($r[0]['mimetype'] === 'image/gif') }
elseif ($r[0]['mimetype'] === 'image/gif') {
$ext = '.gif'; $ext = '.gif';
else }
else {
$ext = EMPTY_STR; $ext = EMPTY_STR;
}
$output = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $resource . ']' . $output = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $resource . ']' .
'[zmg=' . $r[0]['width'] . 'x' . $r[0]['height'] . ']' . z_root() . '/photo/' . $resource . '-' . $resolution . $ext . '[/zmg][/zrl]'; '[zmg=' . $r[0]['width'] . 'x' . $r[0]['height'] . ']' . z_root() . '/photo/' . $resource . '-' . $resolution . $ext . '[/zmg][/zrl]';
@ -89,16 +93,18 @@ class Embedphotos extends \Zotlabs\Web\Controller {
* @param array $args * @param array $args
* @return string with HTML * @return string with HTML
*/ */
function embedphotos_widget_album($args) { function embedphotos_widget_album($args) {
$channel_id = 0; $channel_id = 0;
if(array_key_exists('channel', $args)) if (array_key_exists('channel_id', $args)) {
$channel = $args['channel']; $channel_id = $args['channel_id'];
$channel_id = intval($channel['channel_id']); $channel = channelx_by_n($channel_id);
if(! $channel_id) }
$channel_id = \App::$profile_uid;
if(! $channel_id) if (! $channel_id) {
return ''; return '';
}
$owner_uid = $channel_id; $owner_uid = $channel_id;
require_once('include/security.php'); require_once('include/security.php');
@ -107,32 +113,36 @@ class Embedphotos extends \Zotlabs\Web\Controller {
if (! perm_is_allowed($channel_id,get_observer_hash(),'view_storage')) if (! perm_is_allowed($channel_id,get_observer_hash(),'view_storage'))
return ''; return '';
if($args['album']) if ($args['album']) {
$album = (($args['album'] === '/') ? '' : $args['album']); $album = (($args['album'] === '/') ? '' : $args['album']);
if($args['title']) }
if ($args['title']) {
$title = $args['title']; $title = $args['title'];
}
/** /**
* This may return incorrect permissions if you have multiple directories of the same name. * This may return incorrect permissions if you have multiple directories of the same name.
* It is a limitation of the photo table using a name for a photo album instead of a folder hash * It is a limitation of the photo table using a name for a photo album instead of a folder hash
*/ */
if ($album) { if ($album) {
require_once('include/attach.php');
$x = q("select hash from attach where filename = '%s' and uid = %d limit 1", $x = q("select hash from attach where filename = '%s' and uid = %d limit 1",
dbesc($album), dbesc($album),
intval($owner_uid) intval($owner_uid)
); );
if ($x) { if ($x) {
$y = attach_can_view_folder($owner_uid,get_observer_hash(),$x[0]['hash']); $y = attach_can_view_folder($owner_uid,get_observer_hash(),$x[0]['hash']);
if(! $y) if (! $y) {
return ''; return '';
} }
} }
}
$order = 'DESC'; $order = 'DESC';
$r = q("SELECT p.resource_id, p.id, p.filename, p.mimetype, p.imgscale, p.description, p.created FROM photo p INNER JOIN $r = q("SELECT p.resource_id, p.id, p.filename, p.mimetype, p.imgscale, p.description, p.created FROM photo p INNER JOIN
(SELECT resource_id, max(imgscale) imgscale FROM photo WHERE uid = %d AND album = '%s' AND imgscale <= 4 AND photo_usage IN ( %d, %d ) $sql_extra GROUP BY resource_id) ph (SELECT resource_id, max(imgscale) imgscale FROM photo WHERE uid = %d AND album = '%s' AND imgscale <= 4
AND photo_usage IN ( %d, %d ) $sql_extra GROUP BY resource_id) ph
ON (p.resource_id = ph.resource_id AND p.imgscale = ph.imgscale) ON (p.resource_id = ph.resource_id AND p.imgscale = ph.imgscale)
ORDER BY created $order", ORDER BY created $order",
intval($owner_uid), intval($owner_uid),
@ -141,24 +151,26 @@ class Embedphotos extends \Zotlabs\Web\Controller {
intval(PHOTO_PROFILE) intval(PHOTO_PROFILE)
); );
$photos = array(); $photos = [];
if(count($r)) { if ($r) {
$twist = 'rotright'; $twist = 'rotright';
foreach ($r as $rr) { foreach ($r as $rr) {
if($twist == 'rotright') if ($twist == 'rotright') {
$twist = 'rotleft'; $twist = 'rotleft';
else }
else {
$twist = 'rotright'; $twist = 'rotright';
}
$ext = $phototypes[$rr['mimetype']]; $ext = $phototypes[$rr['mimetype']];
$imgalt_e = $rr['filename']; $imgalt_e = $rr['filename'];
$desc_e = $rr['description']; $desc_e = $rr['description'];
$imagelink = (z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $rr['resource_id'] $imagelink = (z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $rr['resource_id']
. (($_GET['order'] === 'posted') ? '?f=&order=posted' : '')); . (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''));
$photos[] = array( $photos[] = [
'id' => $rr['id'], 'id' => $rr['id'],
'twist' => ' ' . $twist . rand(2,4), 'twist' => ' ' . $twist . rand(2,4),
'link' => $imagelink, 'link' => $imagelink,
@ -169,32 +181,31 @@ class Embedphotos extends \Zotlabs\Web\Controller {
'ext' => $ext, 'ext' => $ext,
'hash' => $rr['resource_id'], 'hash' => $rr['resource_id'],
'unknown' => t('Unknown') 'unknown' => t('Unknown')
); ];
} }
} }
$tpl = get_markup_template('photo_album.tpl'); $o .= replace_macros(get_markup_template('photo_album.tpl'), [
$o .= replace_macros($tpl, array(
'$photos' => $photos, '$photos' => $photos,
'$album' => (($title) ? $title : $album), '$album' => (($title) ? $title : $album),
'$album_id' => rand(), '$album_id' => rand(),
'$album_edit' => array(t('Edit Album'), $album_edit), '$album_edit' => array(t('Edit Album'), $album_edit),
'$can_post' => false, '$can_post' => false,
'$upload' => array(t('Upload'), z_root() . '/photos/' . \App::$profile['channel_address'] . '/upload/' . bin2hex($album)), '$upload' => [ t('Upload'), z_root() . '/photos/' . $channel['channel_address'] . '/upload/' . bin2hex($album) ],
'$order' => false, '$order' => false,
'$upload_form' => $upload_form, '$upload_form' => $upload_form,
'$no_fullscreen_btn' => true '$no_fullscreen_btn' => true
)); ]);
return $o; return $o;
} }
function embedphotos_album_list($a) { function embedphotos_album_list() {
require_once('include/photos.php'); $p = photos_albums_list(App::get_channel(),App::get_observer());
$p = photos_albums_list(\App::get_channel(), \App::get_observer());
if ($p['success']) { if ($p['success']) {
return $p['albums']; return $p['albums'];
} else { }
else {
return null; return null;
} }
} }

View file

@ -23,6 +23,8 @@ class Events extends Controller {
if(! local_channel()) if(! local_channel())
return; return;
$channel = App::get_channel();
if(($_FILES) && array_key_exists('userfile',$_FILES) && intval($_FILES['userfile']['size'])) { if(($_FILES) && array_key_exists('userfile',$_FILES) && intval($_FILES['userfile']['size'])) {
$src = $_FILES['userfile']['tmp_name']; $src = $_FILES['userfile']['tmp_name'];
if($src) { if($src) {
@ -151,7 +153,6 @@ class Events extends Controller {
$share = 1; $share = 1;
$channel = App::get_channel();
$acl = new AccessControl(false); $acl = new AccessControl(false);
@ -193,7 +194,7 @@ class Events extends Controller {
} }
$post_tags = array(); $post_tags = array();
$channel = App::get_channel();
$ac = $acl->get(); $ac = $acl->get();
if(strlen($categories)) { if(strlen($categories)) {
@ -295,6 +296,8 @@ class Events extends Controller {
return; return;
} }
$channel = App::get_channel();
nav_set_selected('Events'); nav_set_selected('Events');
if((argc() > 2) && (argv(1) === 'ignore') && intval(argv(2))) { if((argc() > 2) && (argv(1) === 'ignore') && intval(argv(2))) {
@ -311,8 +314,7 @@ class Events extends Controller {
); );
} }
$first_day = get_pconfig(local_channel(),'system','cal_first_day'); $first_day = intval(get_pconfig(local_channel(),'system','cal_first_day',0));
$first_day = (($first_day) ? $first_day : 0);
$htpl = get_markup_template('event_head.tpl'); $htpl = get_markup_template('event_head.tpl');
App::$page['htmlhead'] .= replace_macros($htpl,array( App::$page['htmlhead'] .= replace_macros($htpl,array(
@ -325,8 +327,6 @@ class Events extends Controller {
$o = ''; $o = '';
$channel = App::get_channel();
$mode = 'view'; $mode = 'view';
$y = 0; $y = 0;
$m = 0; $m = 0;
@ -760,6 +760,62 @@ class Events extends Controller {
intval(local_channel()) intval(local_channel())
); );
if ($r) { if ($r) {
$i = q("select * from item where resource_type = 'event' and resource_id = '%s' and uid = %d",
dbesc($event_id),
intval(local_channel())
);
if ($i) {
$can_delete = false;
$local_delete = true;
$ob_hash = get_observer_hash();
if($ob_hash && ($ob_hash === $i[0]['author_xchan'] || $ob_hash === $i[0]['owner_xchan'] || $ob_hash === $i[0]['source_xchan'])) {
$can_delete = true;
}
// The site admin can delete any post/item on the site.
// If the item originated on this site+channel the deletion will propagate downstream.
// Otherwise just the local copy is removed.
if(is_site_admin()) {
$local_delete = true;
if(intval($i[0]['item_origin']))
$can_delete = true;
}
if($can_delete || $local_delete) {
// if this is a different page type or it's just a local delete
// but not by the item author or owner, do a simple deletion
$complex = false;
if(intval($i[0]['item_type']) || ($local_delete && (! $can_delete))) {
drop_item($i[0]['id']);
}
else {
// complex deletion that needs to propagate and be performed in phases
drop_item($i[0]['id'],true,DROPITEM_PHASE1);
$complex = true;
}
$ii = q("select * from item where id = %d",
intval($i[0]['id'])
);
if($ii) {
xchan_query($ii);
$sync_item = fetch_post_tags($ii);
Libsync::build_sync_packet($i[0]['uid'],array('item' => array(encode_item($sync_item[0],true))));
}
if($complex) {
tag_deliver($i[0]['uid'],$i[0]['id']);
}
}
}
$r = q("update item set resource_type = '', resource_id = '' where resource_type = 'event' and resource_id = '%s' and uid = %d", $r = q("update item set resource_type = '', resource_id = '' where resource_type = 'event' and resource_id = '%s' and uid = %d",
dbesc($event_id), dbesc($event_id),
intval(local_channel()) intval(local_channel())

View file

@ -10,16 +10,15 @@ class Expire extends Controller {
function post() { function post() {
logger('expire: ' . print_r($_POST,true));
if (! ( local_channel() && Apps::system_app_installed(local_channel(),'Expire Posts'))) { if (! ( local_channel() && Apps::system_app_installed(local_channel(),'Expire Posts'))) {
return; return;
} }
if ($_POST['expire-submit']) { if ($_POST['expire-submit']) {
$expire = intval($_POST['selfexpiredays']); $expire = intval($_POST['selfexpiredays']);
if($expire < 0) if ($expire < 0) {
$expire = 0; $expire = 0;
}
set_pconfig(local_channel(),'system','selfexpiredays',$expire); set_pconfig(local_channel(),'system','selfexpiredays',$expire);
info( t('Expiration settings updated.') . EOL); info( t('Expiration settings updated.') . EOL);
} }
@ -39,26 +38,14 @@ logger('expire: ' . print_r($_POST,true));
return $text; return $text;
} }
$setting_fields .= replace_macros(get_markup_template('field_input.tpl'), [
$setting_fields .= replace_macros(get_markup_template('field_input.tpl'), array(
'$field' => array('selfexpiredays', t('Expire and delete all my posts after this many days'), intval(get_pconfig(local_channel(),'system','selfexpiredays',0)), t('Leave at 0 if you wish to manually control expiration of specific posts.')) '$field' => array('selfexpiredays', t('Expire and delete all my posts after this many days'), intval(get_pconfig(local_channel(),'system','selfexpiredays',0)), t('Leave at 0 if you wish to manually control expiration of specific posts.'))
)); ]);
$s .= replace_macros(get_markup_template('generic_app_settings.tpl'), array( return replace_macros(get_markup_template('generic_app_settings.tpl'), [
'$addon' => array('expire', t('Automatic Expiration Settings'), '', t('Submit')), '$addon' => array('expire', t('Automatic Expiration Settings'), '', t('Submit')),
'$content' => $setting_fields '$content' => $setting_fields
)); ]);
return $s;
} }

View file

@ -1,9 +1,11 @@
<?php <?php
namespace Zotlabs\Module; namespace Zotlabs\Module;
use Zotlabs\Web\Controller;
class Feed extends \Zotlabs\Web\Controller { require_once('include/feedutils.php');
class Feed extends Controller {
function init() { function init() {
@ -35,7 +37,6 @@ class Feed extends \Zotlabs\Web\Controller {
killme(); killme();
} }
logger('public feed request from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $channel['channel_address']); logger('public feed request from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $channel['channel_address']);
echo get_public_feed($channel,$params); echo get_public_feed($channel,$params);

View file

@ -15,9 +15,6 @@ class Follow extends Controller {
function init() { function init() {
if(! local_channel()) {
return;
}
if (ActivityStreams::is_as_request() && argc() == 2) { if (ActivityStreams::is_as_request() && argc() == 2) {
$abook_id = intval(argv(1)); $abook_id = intval(argv(1));
@ -27,17 +24,20 @@ class Follow extends Controller {
$r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d", $r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d",
intval($abook_id) intval($abook_id)
); );
if (! $r) if (! $r) {
return; return;
}
$chan = channelx_by_n($r[0]['abook_channel']); $chan = channelx_by_n($r[0]['abook_channel']);
if(! $chan) if (! $chan) {
http_status_exit(404, 'Not found'); http_status_exit(404, 'Not found');
}
$actor = Activity::encode_person($chan,true,true); $actor = Activity::encode_person($chan,true,true);
if(! $actor) if (! $actor) {
http_status_exit(404, 'Not found'); http_status_exit(404, 'Not found');
}
$x = array_merge(['@context' => [ $x = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV, ACTIVITYSTREAMS_JSONLD_REV,
@ -64,6 +64,13 @@ class Follow extends Controller {
} }
if (! local_channel()) {
return;
}
$uid = local_channel(); $uid = local_channel();
$url = notags(trim(punify($_REQUEST['url']))); $url = notags(trim(punify($_REQUEST['url'])));
$return_url = $_SESSION['return_url']; $return_url = $_SESSION['return_url'];
@ -71,16 +78,12 @@ class Follow extends Controller {
$interactive = (($_REQUEST['interactive']) ? intval($_REQUEST['interactive']) : 1); $interactive = (($_REQUEST['interactive']) ? intval($_REQUEST['interactive']) : 1);
$channel = App::get_channel(); $channel = App::get_channel();
if(strpos($url,'@') === false && strpos($url,'/') === false) {
$url = $url . '@' . App::get_hostname();
}
$result = Connect::connect($channel,$url); $result = Connect::connect($channel,$url);
if ($result['success'] == false) { if ($result['success'] == false) {
if($result['message']) if ($result['message']) {
notice($result['message']); notice($result['message']);
}
if ($interactive) { if ($interactive) {
goaway($return_url); goaway($return_url);
} }
@ -102,17 +105,18 @@ class Follow extends Controller {
unset($clone['abook_channel']); unset($clone['abook_channel']);
$abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']); $abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
if($abconfig) if ($abconfig) {
$clone['abconfig'] = $abconfig; $clone['abconfig'] = $abconfig;
}
Libsync::build_sync_packet(0, [ 'abook' => [ $clone ] ], true); Libsync::build_sync_packet(0, [ 'abook' => [ $clone ] ], true);
$can_view_stream = their_perms_contains($channel['channel_id'],$clone['abook_xchan'],'view_stream'); $can_view_stream = their_perms_contains($channel['channel_id'],$clone['abook_xchan'],'view_stream');
// If we can view their stream, pull in some posts // If we can view their stream, pull in some posts
if(($can_view_stream) || ($result['abook']['xchan_network'] === 'rss')) if (($can_view_stream) || ($result['abook']['xchan_network'] === 'rss')) {
Master::Summon([ 'Onepoll', $result['abook']['abook_id'] ]); Master::Summon([ 'Onepoll', $result['abook']['abook_id'] ]);
}
if ($interactive) { if ($interactive) {
goaway(z_root() . '/connedit/' . $result['abook']['abook_id'] . '?follow=1'); goaway(z_root() . '/connedit/' . $result['abook']['abook_id'] . '?follow=1');

View file

@ -0,0 +1,73 @@
<?php
namespace Zotlabs\Module;
use App;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\LDSignatures;
use Zotlabs\Lib\Activity;
use Zotlabs\Web\HTTPSig;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Libprofile;
class Followers extends Controller {
function init() {
if (observer_prohibited(true)) {
http_status_exit(403, 'Forbidden');
}
if (argc() < 2) {
http_status_exit(404, 'Not found');
}
$channel = channelx_by_nick(argv(1));
if (! $channel) {
http_status_exit(404, 'Not found');
}
Libprofile::load(argv(1));
$observer_hash = get_observer_hash();
if (((! (is_array(App::$profile) && count(App::$profile))) || (App::$profile['hide_friends']))) {
http_status_exit(403, 'Forbidden');
}
if (! perm_is_allowed($channel['channel_id'],$observer_hash,'view_contacts')) {
http_status_exit(403, 'Forbidden');
}
$r = q("select * from xchan left join abconfig on abconfig.xchan = xchan_hash left join abook on abook_xchan = xchan_hash where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'their_perms' and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0 and xchan_deleted = 0 and abook_hidden = 0 and abook_pending = 0 and abook_self = 0",
intval($channel['channel_id']),
intval($channel['channel_id']),
dbesc($channel['channel_hash'])
);
if (ActivityStreams::is_as_request()) {
$x = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
z_root() . ZOT_APSCHEMA_REV
]], Activity::encode_follow_collection($r, App::$query_string, 'OrderedCollection'));
$headers = [];
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ;
$x['signature'] = LDSignatures::sign($x,$channel);
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel));
HTTPSig::set_headers($h);
echo $ret;
killme();
}
}
}

View file

@ -0,0 +1,70 @@
<?php
namespace Zotlabs\Module;
use App;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\LDSignatures;
use Zotlabs\Lib\Activity;
use Zotlabs\Web\HTTPSig;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Libprofile;
class Following extends Controller {
function init() {
if (observer_prohibited(true)) {
http_status_exit(403, 'Forbidden');
}
if (argc() < 2) {
http_status_exit(404, 'Not found');
}
$channel = channelx_by_nick(argv(1));
if (! $channel) {
http_status_exit(404, 'Not found');
}
Libprofile::load(argv(1));
$observer_hash = get_observer_hash();
if (((! (is_array(App::$profile) && count(App::$profile))) || (App::$profile['hide_friends']))) {
http_status_exit(403, 'Forbidden');
}
if (! perm_is_allowed($channel['channel_id'],$observer_hash,'view_contacts')) {
http_status_exit(403, 'Forbidden');
}
$r = q("select * from xchan left join abconfig on abconfig.xchan = xchan_hash left join abook on abook_xchan = xchan_hash where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'my_perms' and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0 and xchan_deleted = 0 and abook_hidden = 0 and abook_pending = 0 and abook_self = 0",
intval($channel['channel_id']),
intval($channel['channel_id']),
dbesc($channel['channel_hash'])
);
if (ActivityStreams::is_as_request()) {
$x = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
z_root() . ZOT_APSCHEMA_REV
]], Activity::encode_follow_collection($r, App::$query_string, 'OrderedCollection'));
$headers = [];
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ;
$x['signature'] = LDSignatures::sign($x,$channel);
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel));
HTTPSig::set_headers($h);
echo $ret;
killme();
}
}
}

View file

@ -1,6 +1,9 @@
<?php <?php
namespace Zotlabs\Module; namespace Zotlabs\Module;
use Zotlabs\Web\Controller;
use Zotlabs\Web\HTTPSig;
/** /**
* module: getfile * module: getfile
* *
@ -24,12 +27,15 @@ namespace Zotlabs\Module;
require_once('include/attach.php'); require_once('include/attach.php');
class Getfile extends \Zotlabs\Web\Controller {
class Getfile extends Controller {
function post() { function post() {
$header_verified = false; $header_verified = false;
logger('getfile_args: ' . print_r($_POST,true));
$hash = $_POST['hash']; $hash = $_POST['hash'];
$resource = $_POST['resource']; $resource = $_POST['resource'];
$revision = intval($_POST['revision']); $revision = intval($_POST['revision']);
@ -37,12 +43,14 @@ class Getfile extends \Zotlabs\Web\Controller {
if(argc() > 1) { if(argc() > 1) {
$verify_hash = argv(1); $verify_hash = argv(1);
if($verify_hash !== $hash) { if($verify_hash !== $resource) {
logger('resource mismatch');
killme(); killme();
} }
} }
if(! $hash) { if(! $hash) {
logger('no sender hash');
killme(); killme();
} }
@ -53,7 +61,7 @@ class Getfile extends \Zotlabs\Web\Controller {
continue; continue;
} }
$verified = \Zotlabs\Web\HTTPSig::verify(''); $verified = HTTPSig::verify('');
if($verified && $verified['header_signed'] && $verified['header_valid']) { if($verified && $verified['header_signed'] && $verified['header_valid']) {
$r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' or hubloc_addr = '%s' limit 1", $r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' or hubloc_addr = '%s' limit 1",
dbesc($verified['signer']), dbesc($verified['signer']),

View file

@ -1,19 +1,23 @@
<?php <?php
namespace Zotlabs\Module; namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\PermissionDescription;
require_once("include/bbcode.php"); require_once("include/bbcode.php");
require_once('include/security.php'); require_once('include/security.php');
require_once('include/conversation.php'); require_once('include/conversation.php');
require_once('include/acl_selectors.php'); require_once('include/acl_selectors.php');
class Hq extends \Zotlabs\Web\Controller { class Hq extends Controller {
function init() { function init() {
if(! local_channel()) if(! local_channel())
return; return;
\App::$profile_uid = local_channel(); App::$profile_uid = local_channel();
} }
function post() { function post() {
@ -104,7 +108,7 @@ class Hq extends \Zotlabs\Web\Controller {
} }
if(! $update) { if(! $update) {
$channel = \App::get_channel(); $channel = App::get_channel();
$channel_acl = [ $channel_acl = [
'allow_cid' => $channel['channel_allow_cid'], 'allow_cid' => $channel['channel_allow_cid'],
@ -119,7 +123,7 @@ class Hq extends \Zotlabs\Web\Controller {
'default_location' => $channel['channel_location'], 'default_location' => $channel['channel_location'],
'nickname' => $channel['channel_address'], 'nickname' => $channel['channel_address'],
'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), 'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
'acl' => populate_acl($channel_acl,true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'), 'acl' => populate_acl($channel_acl,true, PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'),
'permissions' => $channel_acl, 'permissions' => $channel_acl,
'bang' => '', 'bang' => '',
'visitor' => true, 'visitor' => true,
@ -165,7 +169,7 @@ class Hq extends \Zotlabs\Web\Controller {
$o .= "<script> var profile_uid = " . local_channel() $o .= "<script> var profile_uid = " . local_channel()
. "; var netargs = '?f='; var profile_page = " . \App::$pager['page'] . ";</script>\r\n"; . "; var netargs = '?f='; var profile_page = " . \App::$pager['page'] . ";</script>\r\n";
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),[ App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),[
'$baseurl' => z_root(), '$baseurl' => z_root(),
'$pgtype' => 'hq', '$pgtype' => 'hq',
'$uid' => local_channel(), '$uid' => local_channel(),
@ -178,6 +182,7 @@ class Hq extends \Zotlabs\Web\Controller {
'$conv' => '0', '$conv' => '0',
'$spam' => '0', '$spam' => '0',
'$fh' => '0', '$fh' => '0',
'$dm' => '0',
'$nouveau' => '0', '$nouveau' => '0',
'$wall' => '0', '$wall' => '0',
'$static' => $static, '$static' => $static,

View file

@ -90,7 +90,7 @@ class Id extends Controller {
xchan_query($r,true); xchan_query($r,true);
$items = fetch_post_tags($r,true); $items = fetch_post_tags($r,true);
$i = Activity::encode_item($items[0],( defined('NOMADIC') ? false : true)); $i = Activity::encode_item($items[0],( get_config('system','activitypub') ? true : false ));
if(! $i) if(! $i)
http_status_exit(404, 'Not found'); http_status_exit(404, 'Not found');

View file

@ -122,7 +122,7 @@ class Import extends Controller {
} }
} }
$codebase = ((defined('NOMADIC')) ? 'zap' : 'osada'); $codebase = 'zap';
if ((! array_path_exists('compatibility/codebase',$data)) || $data['compatibility']['codebase'] !== $codebase) { if ((! array_path_exists('compatibility/codebase',$data)) || $data['compatibility']['codebase'] !== $codebase) {
notice('Data export format is not compatible with this software'); notice('Data export format is not compatible with this software');
@ -142,7 +142,7 @@ class Import extends Controller {
$max_identities = account_service_class_fetch($account_id,'total_identities'); $max_identities = account_service_class_fetch($account_id,'total_identities');
if ($max_identities !== false) { if ($max_identities !== false) {
$r = q("select channel_id from channel where channel_account_id = %d", $r = q("select channel_id from channel where channel_account_id = %d and channel_removed = 0 ",
intval($account_id) intval($account_id)
); );
if ($r && count($r) > $max_identities) { if ($r && count($r) > $max_identities) {
@ -161,6 +161,9 @@ class Import extends Controller {
if ((! $x) || strlen($x) > 64) { if ((! $x) || strlen($x) > 64) {
$x = strtolower(URLify::transliterate($newname)); $x = strtolower(URLify::transliterate($newname));
} }
else {
$x = $newname;
}
$newname = $x; $newname = $x;
} }

274
Zotlabs/Module/Inbox.php Normal file
View file

@ -0,0 +1,274 @@
<?php
namespace Zotlabs\Module;
use App;
use Zotlabs\Web\HTTPSig;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\Activity;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Config;
class Inbox extends Controller {
function post() {
// This SHOULD be handled by the webserver, but in the RFC it is only indicated as
// a SHOULD and not a MUST, so some webservers fail to reject appropriately.
logger('accepting: ' . $_SERVER['HTTP_ACCEPT'],LOGGER_DEBUG);
if ((array_key_exists('HTTP_ACCEPT',$_SERVER)) && ($_SERVER['HTTP_ACCEPT'])
&& (strpos($_SERVER['HTTP_ACCEPT'],'*') === false) && (! ActivityStreams::is_as_request())) {
http_status_exit(406,'not acceptable');
}
$sys_disabled = ((Config::Get('system','disable_discover_tab') || Config::Get('system','disable_activitypub_discover_tab')) ? true : false);
logger('inbox_args: ' . print_r(App::$argv,true));
$is_public = false;
if (argc() == 1 || argv(1) === '[public]') {
$is_public = true;
}
else {
$channels = [ channelx_by_nick(argv(1)) ];
}
$data = file_get_contents('php://input');
if (! $data) {
return;
}
logger('inbox_activity: ' . jindent($data), LOGGER_DATA);
$hsig = HTTPSig::verify($data);
$AS = new ActivityStreams($data);
if ($AS->is_valid() && $AS->type === 'Announce' && is_array($AS->obj)
&& array_key_exists('object',$AS->obj) && array_key_exists('actor',$AS->obj)) {
// This is a relayed/forwarded Activity (as opposed to a shared/boosted object)
// Reparse the encapsulated Activity and use that instead
logger('relayed activity',LOGGER_DEBUG);
$AS = new ActivityStreams($AS->obj);
}
//logger('debug: ' . $AS->debug());
if (! $AS->is_valid()) {
if ($AS->deleted) {
// process mastodon user deletion activities, but only if we can validate the signature
if ($hsig['header_valid'] && $hsig['content_valid'] && $hsig['portable_id']) {
logger('removing deleted actor');
remove_all_xchan_resources($hsig['portable_id']);
}
else {
logger('ignoring deleted actor', LOGGER_DEBUG, LOG_INFO);
}
}
return;
}
// $observer_hash in this case is the sender
if ($hsig['header_valid'] && $hsig['content_valid'] && $hsig['portable_id']) {
$observer_hash = $hsig['portable_id'];
}
else {
$observer_hash = $AS->actor['id'];
}
if (! $observer_hash) {
return;
}
$m = parse_url($observer_hash);
if ($m && $m['scheme'] && $m['host']) {
if (! check_siteallowed($m['scheme'] . '://' . $m['host'])) {
http_status_exit(404,'Permission denied');
}
}
if (is_array($AS->actor) && array_key_exists('id',$AS->actor)) {
Activity::actor_store($AS->actor['id'],$AS->actor);
}
if (is_array($AS->obj) && ActivityStreams::is_an_actor($AS->obj['type'])) {
Activity::actor_store($AS->obj['id'],$AS->obj);
}
if (is_array($AS->obj) && is_array($AS->obj['actor']) && array_key_exists('id',$AS->obj['actor']) && $AS->obj['actor']['id'] !== $AS->actor['id']) {
Activity::actor_store($AS->obj['actor']['id'],$AS->obj['actor']);
}
$test = q("update hubloc set hubloc_connected = '%s' where hubloc_hash = '%s' and hubloc_network = 'activitypub'",
dbesc(datetime_convert()),
dbesc($observer_hash)
);
// $test is ignored
if ($is_public) {
if ($AS->type === 'Follow' && $AS->obj && ActivityStreams::is_an_actor($AS->obj['type'])) {
$channels = q("SELECT * from channel where channel_address = '%s' and channel_removed = 0 ",
dbesc(basename($AS->obj['id']))
);
}
else {
// deliver to anybody following $AS->actor
$channels = q("SELECT * from channel where channel_id in ( SELECT abook_channel from abook left join xchan on abook_xchan = xchan_hash WHERE xchan_network = 'activitypub' and xchan_hash = '%s' ) and channel_removed = 0 ",
dbesc($observer_hash)
);
if (! $channels) {
$channels = [];
}
$parent = $AS->parent_id;
if ($parent) {
// this is a comment - deliver to everybody who owns the parent
$owners = q("SELECT * from channel where channel_id in ( SELECT uid from item where mid = '%s' ) ",
dbesc($parent)
);
if ($owners) {
$channels = array_merge($channels,$owners);
}
}
}
if ($channels === false) {
$channels = [];
}
if (in_array(ACTIVITY_PUBLIC_INBOX,$AS->recips)) {
// look for channels with send_stream = PERMS_PUBLIC
$r = q("select * from channel where channel_id in (select uid from pconfig where cat = 'perm_limits' and k = 'send_stream' and v = '1' ) and channel_removed = 0 ");
if ($r) {
$channels = array_merge($channels,$r);
}
if (! $sys_disabled) {
$channels[] = get_sys_channel();
}
}
}
if (! $channels) {
logger('no deliveries on this site');
return;
}
$saved_recips = [];
foreach ( [ 'to', 'cc', 'audience' ] as $x ) {
if (array_key_exists($x,$AS->data)) {
$saved_recips[$x] = $AS->data[$x];
}
}
$AS->set_recips($saved_recips);
foreach ($channels as $channel) {
if (! get_pconfig($channel['channel_id'],'system','activitypub',true)) {
continue;
}
logger('inbox_channel: ' . $channel['channel_address'],LOGGER_DEBUG);
switch ($AS->type) {
case 'Follow':
if ($AS->obj & ActivityStreams::is_an_actor($AS->obj['type'])) {
// do follow activity
Activity::follow($channel,$AS);
}
break;
case 'Accept':
if ($AS->obj & $AS->obj['type'] === 'Follow') {
// do follow activity
Activity::follow($channel,$AS);
}
break;
case 'Reject':
default:
break;
}
// These activities require permissions
$item = null;
switch ($AS->type) {
case 'Update':
if (is_array($AS->obj) && array_key_exists('type',$AS->obj) && ActivityStreams::is_an_actor($AS->obj['type'])) {
// pretend this is an old cache entry to force an update of all the actor details
$AS->obj['cached'] = true;
$AS->obj['updated'] = datetime_convert('UTC','UTC','1980-01-01', ATOM_TIME);
Activity::actor_store($AS->obj['id'],$AS->obj);
break;
}
case 'Create':
case 'Like':
case 'Dislike':
case 'Announce':
case 'Accept':
case 'Reject':
case 'TentativeAccept':
case 'TentativeReject':
case 'emojiReaction':
// These require a resolvable object structure
if (is_array($AS->obj)) {
$item = Activity::decode_note($AS);
// @wip replies must go to the replyTo endpoint if the top level post originated here.
//if ($item['mid'] !== $item['parent_mid'] && stripos(z_root(), $item['parent_mid']) === 0) {
// $item = null;
// break;
//}
}
else {
logger('unresolved object: ' . print_r($AS->obj,true));
}
break;
case 'Undo':
if ($AS->obj & $AS->obj['type'] === 'Follow') {
// do unfollow activity
Activity::unfollow($channel,$AS);
break;
}
case 'Delete':
Activity::drop($channel,$observer_hash,$AS);
break;
case 'Add':
case 'Remove':
default:
break;
}
if ($item) {
logger('parsed_item: ' . print_r($item,true),LOGGER_DATA);
Activity::store($channel,$observer_hash,$AS,$item);
}
}
http_status_exit(200,'OK');
}
function get() {
}
}

View file

@ -4,12 +4,14 @@ namespace Zotlabs\Module;
/** /**
* *
* This is the POST destination for most all locally posted * As a GET request, this module answers to activitypub and zot6 item fetches and
* acts as a permalink for local content.
*
* Otherwise this is the POST destination for most all locally posted
* text stuff. This function handles status, wall-to-wall status, * text stuff. This function handles status, wall-to-wall status,
* local comments, and remote coments that are posted on this site * local comments, and remote coments that are posted on this site
* (as opposed to being delivered in a feed). * (as opposed to being delivered in a feed).
* Also processed here are posts and comments coming through the * Also processed here are posts and comments coming through the API.
* statusnet/twitter API.
* All of these become an "item" which is our basic unit of * All of these become an "item" which is our basic unit of
* information. * information.
* Posts that originate externally or do not fall into the above * Posts that originate externally or do not fall into the above
@ -29,7 +31,10 @@ use Zotlabs\Lib\Config;
use Zotlabs\Lib\IConfig; use Zotlabs\Lib\IConfig;
use Zotlabs\Lib\Enotify; use Zotlabs\Lib\Enotify;
use Zotlabs\Lib\Apps; use Zotlabs\Lib\Apps;
use Zotlabs\Access\PermissionLimits;
use Zotlabs\Access\AccessControl;
use App; use App;
use URLify;
require_once('include/attach.php'); require_once('include/attach.php');
require_once('include/bbcode.php'); require_once('include/bbcode.php');
@ -54,8 +59,9 @@ class Item extends Controller {
$i = null; $i = null;
// do we have the item (at all)? // do we have the item (at all)?
// add preferential bias to item owners (item_wall = 1)
$r = q("select * from item where mid = '%s' or uuid = '%s' $item_normal limit 1", $r = q("select * from item where mid = '%s' or uuid = '%s' $item_normal order by item_wall desc limit 1",
dbesc(z_root() . '/item/' . $item_id), dbesc(z_root() . '/item/' . $item_id),
dbesc($item_id) dbesc($item_id)
); );
@ -88,11 +94,12 @@ class Item extends Controller {
} }
// if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access // if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access
// with a bias towards those items owned by channels on this site (item_wall = 1)
$sql_extra = item_permissions_sql(0); $sql_extra = item_permissions_sql(0);
if (! $i) { if (! $i) {
$i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra limit 1", $i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
dbesc($r[0]['parent_mid']) dbesc($r[0]['parent_mid'])
); );
} }
@ -114,7 +121,7 @@ class Item extends Controller {
if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream')) if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream'))
http_status_exit(403, 'Forbidden'); http_status_exit(403, 'Forbidden');
$i = Activity::encode_item($items[0],((defined('NOMADIC')) ? false : true)); $i = Activity::encode_item($items[0],((get_config('system','activitypub')) ? true : false));
if(! $i) if(! $i)
http_status_exit(404, 'Not found'); http_status_exit(404, 'Not found');
@ -189,11 +196,12 @@ class Item extends Controller {
} }
// if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access // if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access
// with a bias towards those items owned by channels on this site (item_wall = 1)
$sql_extra = item_permissions_sql(0); $sql_extra = item_permissions_sql(0);
if (! $i) { if (! $i) {
$i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra limit 1", $i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
dbesc($r[0]['parent_mid']) dbesc($r[0]['parent_mid'])
); );
} }
@ -259,7 +267,7 @@ class Item extends Controller {
if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream')) if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream'))
http_status_exit(403, 'Forbidden'); http_status_exit(403, 'Forbidden');
$i = Activity::encode_item_collection($nitems,'conversation/' . $item_id,'OrderedCollection',( defined('NOMADIC') ? false : true)); $i = Activity::encode_item_collection($nitems,'conversation/' . $item_id,'OrderedCollection',( get_config('system','activitypub') ? true : false));
if($portable_id) { if($portable_id) {
ThreadListener::store(z_root() . '/item/' . $item_id,$portable_id); ThreadListener::store(z_root() . '/item/' . $item_id,$portable_id);
} }
@ -286,9 +294,14 @@ class Item extends Controller {
} }
// if it isn't a drop command and isn't a post method and wasn't handled already,
// the default action is a browser request for a persistent uri and this should return
// the text/html page of the item.
if (argc() > 1 && argv(1) !== 'drop') { if (argc() > 1 && argv(1) !== 'drop') {
$x = q("select uid, item_wall, llink, mid from item where mid = '%s' ", $x = q("select uid, item_wall, llink, mid from item where mid = '%s' or mid = '%s' ",
dbesc(z_root() . '/item/' . argv(1)) dbesc(z_root() . '/item/' . argv(1)),
dbesc(z_root() . '/activity/' . argv(1))
); );
if ($x) { if ($x) {
foreach ($x as $xv) { foreach ($x as $xv) {
@ -307,12 +320,20 @@ class Item extends Controller {
function post() { function post() {
// This will change. Figure out who the observer is and whether or not
// they have permission to post here. Else ignore the post.
if((! local_channel()) && (! remote_channel()) && (! x($_REQUEST,'anonname'))) if((! local_channel()) && (! remote_channel()) && (! x($_REQUEST,'anonname')))
return; return;
// drop an array of items.
if (x($_REQUEST,'dropitems')) {
$arr_drop = explode(',',$_REQUEST['dropitems']);
drop_items($arr_drop);
$json = array('success' => 1);
echo json_encode($json);
killme();
}
$uid = local_channel(); $uid = local_channel();
$channel = null; $channel = null;
$observer = null; $observer = null;
@ -326,16 +347,25 @@ class Item extends Controller {
$parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : 0); $parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : 0);
$parent_mid = ((x($_REQUEST,'parent_mid')) ? trim($_REQUEST['parent_mid']) : ''); $parent_mid = ((x($_REQUEST,'parent_mid')) ? trim($_REQUEST['parent_mid']) : '');
$remote_xchan = ((x($_REQUEST,'remote_xchan')) ? trim($_REQUEST['remote_xchan']) : false);
/**
* Who is viewing this page and posting this thing
*/
$remote_xchan = ((x($_REQUEST,'remote_xchan')) ? trim($_REQUEST['remote_xchan']) : false);
$remote_observer = xchan_match( ['xchan_hash' => $remote_xchan ] ); $remote_observer = xchan_match( ['xchan_hash' => $remote_xchan ] );
if (! $remote_observer) { if (! $remote_observer) {
$remote_xchan = $remote_observer = false; $remote_xchan = $remote_observer = false;
} }
// This is the local channel representing who the posted item will belong to.
$profile_uid = ((x($_REQUEST,'profile_uid')) ? intval($_REQUEST['profile_uid']) : 0); $profile_uid = ((x($_REQUEST,'profile_uid')) ? intval($_REQUEST['profile_uid']) : 0);
// *If* you are logged in as the site admin you are allowed to create items for the sys channel.
// This would typically be a webpage or webpage element.
$sys = get_sys_channel(); $sys = get_sys_channel();
if ($sys && $profile_uid && ($sys['channel_id'] == $profile_uid) && is_site_admin()) { if ($sys && $profile_uid && ($sys['channel_id'] == $profile_uid) && is_site_admin()) {
$uid = intval($sys['channel_id']); $uid = intval($sys['channel_id']);
@ -343,14 +373,6 @@ class Item extends Controller {
$observer = $sys; $observer = $sys;
} }
if(x($_REQUEST,'dropitems')) {
$arr_drop = explode(',',$_REQUEST['dropitems']);
drop_items($arr_drop);
$json = array('success' => 1);
echo json_encode($json);
killme();
}
call_hooks('post_local_start', $_REQUEST); call_hooks('post_local_start', $_REQUEST);
// logger('postvars ' . print_r($_REQUEST,true), LOGGER_DATA); // logger('postvars ' . print_r($_REQUEST,true), LOGGER_DATA);
@ -360,6 +382,17 @@ class Item extends Controller {
$consensus = intval($_REQUEST['consensus']); $consensus = intval($_REQUEST['consensus']);
$nocomment = intval($_REQUEST['nocomment']); $nocomment = intval($_REQUEST['nocomment']);
// If this is a poll, grab the poll data
$qtype = intval($_REQUEST['qtype']);
if($_REQUEST['answers'] && is_array($_REQUEST['answers'])) {
$pollchoices = [];
foreach($_REQUEST['answers'] as $q) {
$pollchoices[] = escape_tags($q);
}
$_REQUEST['obj_type'] = ACTIVITY_OBJ_POLL;
}
// 'origin' (if non-zero) indicates that this network is where the message originated, // 'origin' (if non-zero) indicates that this network is where the message originated,
// for the purpose of relaying comments to other conversation members. // for the purpose of relaying comments to other conversation members.
// If using the API from a device (leaf node) you must set origin to 1 (default) or leave unset. // If using the API from a device (leaf node) you must set origin to 1 (default) or leave unset.
@ -411,9 +444,13 @@ class Item extends Controller {
} }
if ($pagetitle) { if ($pagetitle) {
$pagetitle = strtolower(\URLify::transliterate($pagetitle)); $pagetitle = strtolower(URLify::transliterate($pagetitle));
} }
/**
* process collections by tagging them
*/
if (array_key_exists('collections',$_REQUEST) && is_array($_REQUEST['collections']) && count($_REQUEST['collections'])) { if (array_key_exists('collections',$_REQUEST) && is_array($_REQUEST['collections']) && count($_REQUEST['collections'])) {
foreach ($_REQUEST['collections'] as $clct) { foreach ($_REQUEST['collections'] as $clct) {
$r = q("select xchan_url, xchan_hash from xchan left join hubloc on hubloc_hash = xchan_hash where hubloc_addr = '%s' limit 1", $r = q("select xchan_url, xchan_hash from xchan left join hubloc on hubloc_hash = xchan_hash where hubloc_addr = '%s' limit 1",
@ -444,13 +481,19 @@ class Item extends Controller {
$parid = 0; $parid = 0;
$r = false; $r = false;
// If this is a comment, find the parent and preset some stuff
if ($parent || $parent_mid) { if ($parent || $parent_mid) {
if(! x($_REQUEST,'type')) if (! x($_REQUEST,'type')) {
$_REQUEST['type'] = 'net-comment'; $_REQUEST['type'] = 'net-comment';
}
if($obj_type == ACTIVITY_OBJ_NOTE) if ($obj_type == ACTIVITY_OBJ_NOTE) {
$obj_type = ACTIVITY_OBJ_COMMENT; $obj_type = ACTIVITY_OBJ_COMMENT;
}
// fetch the parent item
if ($parent) { if ($parent) {
$r = q("SELECT * FROM item WHERE id = %d LIMIT 1", $r = q("SELECT * FROM item WHERE id = %d LIMIT 1",
@ -474,7 +517,7 @@ class Item extends Controller {
); );
} }
// if interacting with a pubstream item, // if interacting with a pubstream item (owned by the sys channel),
// create a copy of the parent in your stream // create a copy of the parent in your stream
if ($r[0]['uid'] === $sys['channel_id'] && local_channel()) { if ($r[0]['uid'] === $sys['channel_id'] && local_channel()) {
@ -484,10 +527,12 @@ class Item extends Controller {
if (! $r) { if (! $r) {
notice( t('Unable to locate original post.') . EOL); notice( t('Unable to locate original post.') . EOL);
if($api_source) if ($api_source) {
return ( [ 'success' => false, 'message' => 'invalid post id' ] ); return ( [ 'success' => false, 'message' => 'invalid post id' ] );
if(x($_REQUEST,'return')) }
if (x($_REQUEST,'return')) {
goaway(z_root() . "/" . $return_path ); goaway(z_root() . "/" . $return_path );
}
killme(); killme();
} }
@ -509,6 +554,7 @@ class Item extends Controller {
if (! $observer) { if (! $observer) {
$observer = App::get_observer(); $observer = App::get_observer();
if (! $observer) { if (! $observer) {
// perhaps we're allowing moderated comments from anonymous viewers
$observer = anon_identity_init($_REQUEST); $observer = anon_identity_init($_REQUEST);
if ($observer) { if ($observer) {
$moderated = true; $moderated = true;
@ -519,10 +565,12 @@ class Item extends Controller {
if (! $observer) { if (! $observer) {
notice( t('Permission denied.') . EOL) ; notice( t('Permission denied.') . EOL) ;
if($api_source) if ($api_source) {
return ( [ 'success' => false, 'message' => 'permission denied' ] ); return ( [ 'success' => false, 'message' => 'permission denied' ] );
if(x($_REQUEST,'return')) }
if (x($_REQUEST,'return')) {
goaway(z_root() . "/" . $return_path ); goaway(z_root() . "/" . $return_path );
}
killme(); killme();
} }
@ -547,6 +595,7 @@ class Item extends Controller {
} }
} }
else { else {
// fixme - $webpage could also be a wiki page or article and require a different permission to be checked.
if(! perm_is_allowed($profile_uid,$observer['xchan_hash'],($webpage) ? 'write_pages' : 'post_wall')) { if(! perm_is_allowed($profile_uid,$observer['xchan_hash'],($webpage) ? 'write_pages' : 'post_wall')) {
notice( t('Permission denied.') . EOL) ; notice( t('Permission denied.') . EOL) ;
if($api_source) if($api_source)
@ -557,10 +606,13 @@ class Item extends Controller {
} }
} }
// check if this author is being moderated through the 'moderated' (negative) permission
// when posting wall-to-wall
if ($moderated === false && intval($uid) !== intval($profile_uid)) { if ($moderated === false && intval($uid) !== intval($profile_uid)) {
$moderated = perm_is_allowed($profile_uid,$observer['xchan_hash'],'moderated'); $moderated = perm_is_allowed($profile_uid,$observer['xchan_hash'],'moderated');
} }
// If this is a comment, check the moderated permission of the parent; who may be on another site
$remote_moderated = (($parent) ? their_perms_contains($profile_uid,$parent_item['owner_xchan'],'moderated') : false); $remote_moderated = (($parent) ? their_perms_contains($profile_uid,$parent_item['owner_xchan'],'moderated') : false);
if ($remote_moderated) { if ($remote_moderated) {
notice( t('Comment may be moderated.') . EOL); notice( t('Comment may be moderated.') . EOL);
@ -661,10 +713,10 @@ class Item extends Controller {
} }
} }
$acl = new \Zotlabs\Access\AccessControl($channel); $acl = new AccessControl($channel);
$view_policy = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_stream'); $view_policy = PermissionLimits::Get($channel['channel_id'],'view_stream');
$comment_policy = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'post_comments'); $comment_policy = PermissionLimits::Get($channel['channel_id'],'post_comments');
$public_policy = ((x($_REQUEST,'public_policy')) ? escape_tags($_REQUEST['public_policy']) : map_scope($view_policy,true)); $public_policy = ((x($_REQUEST,'public_policy')) ? escape_tags($_REQUEST['public_policy']) : map_scope($view_policy,true));
if($webpage) if($webpage)
@ -684,9 +736,9 @@ class Item extends Controller {
$private = $orig_post['item_private']; $private = $orig_post['item_private'];
} }
if($private || $public_policy || $acl->is_private()) if($public_policy || $acl->is_private()) {
$private = 1; $private = (($private) ? $private : 1);
}
$location = $orig_post['location']; $location = $orig_post['location'];
$coord = $orig_post['coord']; $coord = $orig_post['coord'];
@ -763,14 +815,14 @@ class Item extends Controller {
$allow_empty = ((array_key_exists('allow_empty',$_REQUEST)) ? intval($_REQUEST['allow_empty']) : 0); $allow_empty = ((array_key_exists('allow_empty',$_REQUEST)) ? intval($_REQUEST['allow_empty']) : 0);
$private = intval($acl->is_private() || ($public_policy)); $private = (($private) ? $private : intval($acl->is_private() || ($public_policy)));
// If this is a comment, set the permissions from the parent. // If this is a comment, set the permissions from the parent.
if($parent_item) { if($parent_item) {
$private = 0; $private = 0;
$acl->set($parent_item); $acl->set($parent_item);
$private = intval($acl->is_private() || $parent_item['item_private']); $private = ((intval($parent_item['item_private']) ? $parent_item['item_private'] : $acl->is_private()));
$public_policy = $parent_item['public_policy']; $public_policy = $parent_item['public_policy'];
$owner_hash = $parent_item['owner_xchan']; $owner_hash = $parent_item['owner_xchan'];
$webpage = $parent_item['item_type']; $webpage = $parent_item['item_type'];
@ -876,6 +928,11 @@ class Item extends Controller {
} }
} }
if(($str_contact_allow) && (! $str_group_allow)) {
// direct message - private between individual channels but not groups
$private = 2;
}
/** /**
* *
@ -1103,6 +1160,8 @@ class Item extends Controller {
$plink = z_root() . '/item/' . $uuid; $plink = z_root() . '/item/' . $uuid;
} }
$datarray['aid'] = $channel['channel_account_id']; $datarray['aid'] = $channel['channel_account_id'];
$datarray['uid'] = $profile_uid; $datarray['uid'] = $profile_uid;
$datarray['uuid'] = $uuid; $datarray['uuid'] = $uuid;
@ -1168,7 +1227,7 @@ class Item extends Controller {
if(! array_key_exists('obj',$datarray)) { if(! array_key_exists('obj',$datarray)) {
$copy = $datarray; $copy = $datarray;
$copy['author'] = $observer; $copy['author'] = $observer;
$datarray['obj'] = Activity::encode_item($copy,((defined('NOMADIC')) ? false : true)); $datarray['obj'] = Activity::encode_item($copy,((get_config('system','activitypub')) ? true : false));
} }
// A specific ACL over-rides public_policy completely // A specific ACL over-rides public_policy completely
@ -1176,8 +1235,14 @@ class Item extends Controller {
if(! empty_acl($datarray)) if(! empty_acl($datarray))
$datarray['public_policy'] = ''; $datarray['public_policy'] = '';
if($iconfig) if ($iconfig) {
$datarray['iconfig'] = $iconfig; $datarray['iconfig'] = $iconfig;
}
if ($private) {
IConfig::set($datarray,'ocap','relay',new_token());
}
// preview mode - prepare the body for display and send it via json // preview mode - prepare the body for display and send it via json
@ -1422,13 +1487,14 @@ class Item extends Controller {
if((argc() == 3) && (argv(1) === 'drop') && intval(argv(2))) { if((argc() == 3) && (argv(1) === 'drop') && intval(argv(2))) {
$i = q("select id, uid, item_origin, author_xchan, owner_xchan, source_xchan, item_type from item where id = %d limit 1", $i = q("select * from item where id = %d limit 1",
intval(argv(2)) intval(argv(2))
); );
if($i) { if($i) {
$can_delete = false; $can_delete = false;
$local_delete = false; $local_delete = false;
$regular_delete = false;
if(local_channel() && local_channel() == $i[0]['uid']) { if(local_channel() && local_channel() == $i[0]['uid']) {
$local_delete = true; $local_delete = true;
@ -1437,6 +1503,7 @@ class Item extends Controller {
$ob_hash = get_observer_hash(); $ob_hash = get_observer_hash();
if($ob_hash && ($ob_hash === $i[0]['author_xchan'] || $ob_hash === $i[0]['owner_xchan'] || $ob_hash === $i[0]['source_xchan'])) { if($ob_hash && ($ob_hash === $i[0]['author_xchan'] || $ob_hash === $i[0]['owner_xchan'] || $ob_hash === $i[0]['source_xchan'])) {
$can_delete = true; $can_delete = true;
$regular_delete = true;
} }
// The site admin can delete any post/item on the site. // The site admin can delete any post/item on the site.
@ -1455,6 +1522,35 @@ class Item extends Controller {
return; return;
} }
if ($i[0]['resource_type'] === 'event') {
// delete and sync the event separately
$r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
dbesc($i[0]['resource_id']),
intval($i[0]['uid'])
);
if ($r && $regular_delete) {
$sync_event = $r[0];
q("delete from event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
dbesc($i[0]['resource_id']),
intval($i[0]['uid'])
);
$sync_event['event_deleted'] = 1;
Libsync::build_sync_packet($i[0]['uid'],array('event' => array($sync_event)));
}
}
if ($i[0]['resource_type'] === 'photo') {
attach_delete($i[0]['uid'], $i[0]['resource_id'], true );
$ch = channelx_by_n($i[0]['uid']);
if ($ch && $regular_delete) {
$sync = attach_export_data($ch,$i[0]['resource_id'], true);
if ($sync) {
Libsync::build_sync_packet($i[0]['uid'],array('file' => array($sync)));
}
}
}
// if this is a different page type or it's just a local delete // if this is a different page type or it's just a local delete
// but not by the item author or owner, do a simple deletion // but not by the item author or owner, do a simple deletion

View file

@ -1,6 +1,7 @@
<?php <?php
namespace Zotlabs\Module; namespace Zotlabs\Module;
use App;
use Zotlabs\Lib\Libsync; use Zotlabs\Lib\Libsync;
use Zotlabs\Lib\Activity; use Zotlabs\Lib\Activity;
use Zotlabs\Web\Controller; use Zotlabs\Web\Controller;
@ -46,7 +47,7 @@ class Like extends Controller {
$sys_channel = get_sys_channel(); $sys_channel = get_sys_channel();
$sys_channel_id = (($sys_channel) ? $sys_channel['channel_id'] : 0); $sys_channel_id = (($sys_channel) ? $sys_channel['channel_id'] : 0);
$observer = \App::get_observer(); $observer = App::get_observer();
$verb = notags(trim($_GET['verb'])); $verb = notags(trim($_GET['verb']));
@ -234,7 +235,7 @@ class Like extends Controller {
if($r) { if($r) {
if($r[0]['uid'] === $sys_channel['channel_id'] && local_channel()) { if($r[0]['uid'] === $sys_channel['channel_id'] && local_channel()) {
$r = [ copy_of_pubitem(\App::get_channel(), $r[0]['mid']) ]; $r = [ copy_of_pubitem(App::get_channel(), $r[0]['mid']) ];
} }
} }
@ -283,7 +284,9 @@ class Like extends Controller {
$multi_undo = false; $multi_undo = false;
$item_normal = item_normal(); $item_normal = " and item.item_deleted = 0 and item.item_unpublished = 0 and item.item_delayed = 0
and item.item_pending_remove = 0 and item.item_blocked = 0 and item.obj_type != '" . ACTIVITY_OBJ_FILE . "' ";
$r = q("SELECT id, parent, uid, verb FROM item WHERE verb in ( $verbs ) $item_normal $r = q("SELECT id, parent, uid, verb FROM item WHERE verb in ( $verbs ) $item_normal
AND author_xchan = '%s' AND thr_parent = '%s' and uid = %d ", AND author_xchan = '%s' AND thr_parent = '%s' and uid = %d ",
@ -360,6 +363,16 @@ class Like extends Controller {
$r = q("update item set item_hidden = 0 where id = %d", $r = q("update item set item_hidden = 0 where id = %d",
intval($item['id']) intval($item['id'])
); );
$r = q("select * from item where id = %d",
intval($item['id'])
);
if($r) {
xchan_query($r);
$sync_item = fetch_post_tags($r);
Libsync::build_sync_packet($ch[0]['channel_id'], [ 'item' => [ encode_item($sync_item[0],true) ] ]);
}
Master::Summon(array('Notifier','wall-new',$item['id'])); Master::Summon(array('Notifier','wall-new',$item['id']));
} }

View file

@ -138,6 +138,15 @@ class Linkinfo extends Controller {
$x = Activity::fetch($url); $x = Activity::fetch($url);
if (is_array($x)) { if (is_array($x)) {
$y = new ActivityStreams($x); $y = new ActivityStreams($x);
if ($y->is_valid() && $y->type === 'Announce' && is_array($y->obj)
&& array_key_exists('object',$y->obj) && array_key_exists('actor',$y->obj)) {
// This is a relayed/forwarded Activity (as opposed to a shared/boosted object)
// Reparse the encapsulated Activity and use that instead
logger('relayed activity',LOGGER_DEBUG);
$y = new ActivityStreams($y->obj);
}
if ($y->is_valid()) { if ($y->is_valid()) {
$z = Activity::decode_note($y); $z = Activity::decode_note($y);
$r = q("select hubloc_hash, hubloc_network, hubloc_url from hubloc where hubloc_hash = '%s' OR hubloc_id_url = '%s'", $r = q("select hubloc_hash, hubloc_network, hubloc_url from hubloc where hubloc_hash = '%s' OR hubloc_id_url = '%s'",

356
Zotlabs/Module/Lists.php Normal file
View file

@ -0,0 +1,356 @@
<?php
namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Libsync;
use Zotlabs\Lib\AccessList;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\Activity;
use Zotlabs\Web\HTTPSig;
use Zotlabs\Lib\Config;
use Zotlabs\Lib\LDSignatures;
class Lists extends Controller {
function init() {
if (ActivityStreams::is_as_request()) {
$item_id = argv(1);
if( ! $item_id) {
http_status_exit(404, 'Not found');
}
$x = q("select * from pgrp where hash = '%s' limit 1",
dbesc($item_id)
);
if (! $x) {
http_status_exit(404, 'Not found');
}
$group = array_shift($x);
// process an authenticated fetch
$sigdata = HTTPSig::verify(EMPTY_STR);
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
$portable_id = $sigdata['portable_id'];
if (! check_channelallowed($portable_id)) {
http_status_exit(403, 'Permission denied');
}
if (! check_siteallowed($sigdata['signer'])) {
http_status_exit(403, 'Permission denied');
}
observer_auth($portable_id);
}
elseif (! Config::get('system','require_authenticated_fetch',false)) {
http_status_exit(403,'Permission denied');
}
if (! perm_is_allowed($group['uid'],get_observer_hash(),'view_contacts')) {
http_status_exit(403,'Permission denied');
}
$channel = channelx_by_n($group['uid']);
if (! $channel) {
http_status_exit(404,'Not found');
}
if (! $group['visible']) {
if ($channel['channel_hash'] !== get_observer_hash()) {
http_status_exit(403,'Permission denied');
}
}
$members = AccessList::members($group['uid'],$group['id']);
$x = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
z_root() . ZOT_APSCHEMA_REV
]], Activity::encode_follow_collection($members, App::$query_string, 'OrderedCollection'));
$headers = [];
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ;
$x['signature'] = LDSignatures::sign($x,$channel);
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel));
HTTPSig::set_headers($h);
echo $ret;
killme();
}
if (! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
App::$profile_uid = local_channel();
nav_set_selected('Access Lists');
}
function post() {
if (! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
if ((argc() == 2) && (argv(1) === 'new')) {
check_form_security_token_redirectOnErr('/lists/new', 'group_edit');
$name = notags(trim($_POST['groupname']));
$public = intval($_POST['public']);
$r = AccessList::add(local_channel(),$name,$public);
if ($r) {
info( t('Access list created.') . EOL );
}
else {
notice( t('Could not create access list.') . EOL );
}
goaway(z_root() . '/lists');
}
if ((argc() == 2) && (intval(argv(1)))) {
check_form_security_token_redirectOnErr('/lists', 'group_edit');
$r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d LIMIT 1",
intval(argv(1)),
intval(local_channel())
);
if (! $r) {
notice( t('Access list not found.') . EOL );
goaway(z_root() . '/connections');
}
$group = array_shift($r);
$groupname = notags(trim($_POST['groupname']));
$public = intval($_POST['public']);
if ((strlen($groupname)) && (($groupname != $group['gname']) || ($public != $group['visible']))) {
$r = q("UPDATE pgrp SET gname = '%s', visible = %d WHERE uid = %d AND id = %d",
dbesc($groupname),
intval($public),
intval(local_channel()),
intval($group['id'])
);
if ($r) {
info( t('Access list updated.') . EOL );
}
Libsync::build_sync_packet(local_channel(),null,true);
}
goaway(z_root() . '/lists/' . argv(1) . '/' . argv(2));
}
return;
}
function get() {
$change = false;
logger('mod_lists: ' . \App::$cmd,LOGGER_DEBUG);
if (! local_channel()) {
notice( t('Permission denied') . EOL);
return;
}
// Switch to text mode interface if we have more than 'n' contacts or group members
$switchtotext = get_pconfig(local_channel(),'system','groupedit_image_limit');
if ($switchtotext === false) {
$switchtotext = get_config('system','groupedit_image_limit');
}
if ($switchtotext === false) {
$switchtotext = 400;
}
if ((argc() == 1) || ((argc() == 2) && (argv(1) === 'new'))) {
$new = (((argc() == 2) && (argv(1) === 'new')) ? true : false);
$groups = q("SELECT id, gname FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
intval(local_channel())
);
$i = 0;
foreach ($groups as $group) {
$entries[$i]['name'] = $group['gname'];
$entries[$i]['id'] = $group['id'];
$entries[$i]['count'] = count(AccessList::members(local_channel(),$group['id']));
$i++;
}
$tpl = get_markup_template('privacy_groups.tpl');
$o = replace_macros($tpl, [
'$title' => t('Access Lists'),
'$add_new_label' => t('Create access list'),
'$new' => $new,
// new group form
'$gname' => array('groupname',t('Access list name')),
'$public' => array('public',t('Members are visible to other channels'), false),
'$form_security_token' => get_form_security_token("group_edit"),
'$submit' => t('Submit'),
// groups list
'$title' => t('Access Lists'),
'$name_label' => t('Name'),
'$count_label' => t('Members'),
'$entries' => $entries
]);
return $o;
}
$context = array('$submit' => t('Submit'));
$tpl = get_markup_template('group_edit.tpl');
if((argc() == 3) && (argv(1) === 'drop')) {
check_form_security_token_redirectOnErr('/lists', 'group_drop', 't');
if(intval(argv(2))) {
$r = q("SELECT gname FROM pgrp WHERE id = %d AND uid = %d LIMIT 1",
intval(argv(2)),
intval(local_channel())
);
if($r)
$result = AccessList::remove(local_channel(),$r[0]['gname']);
if($result)
info( t('Access list removed.') . EOL);
else
notice( t('Unable to remove access list.') . EOL);
}
goaway(z_root() . '/lists');
// NOTREACHED
}
if((argc() > 2) && intval(argv(1)) && argv(2)) {
check_form_security_token_ForbiddenOnErr('group_member_change', 't');
$r = q("SELECT abook_xchan from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 limit 1",
dbesc(base64url_decode(argv(2))),
intval(local_channel())
);
if(count($r))
$change = base64url_decode(argv(2));
}
if((argc() > 1) && (intval(argv(1)))) {
require_once('include/acl_selectors.php');
$r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d AND deleted = 0 LIMIT 1",
intval(argv(1)),
intval(local_channel())
);
if(! $r) {
notice( t('Access list not found.') . EOL );
goaway(z_root() . '/connections');
}
$group = $r[0];
$members = AccessList::members(local_channel(), $group['id']);
$preselected = array();
if(count($members)) {
foreach($members as $member)
if(! in_array($member['xchan_hash'],$preselected))
$preselected[] = $member['xchan_hash'];
}
if($change) {
if(in_array($change,$preselected)) {
AccessList::member_remove(local_channel(),$group['gname'],$change);
}
else {
AccessList::member_add(local_channel(),$group['gname'],$change);
}
$members = AccessList::members(local_channel(), $group['id']);
$preselected = array();
if(count($members)) {
foreach($members as $member)
$preselected[] = $member['xchan_hash'];
}
}
$context = $context + array(
'$title' => sprintf(t('Access List: %s'), $group['gname']),
'$details_label' => t('Edit'),
'$gname' => array('groupname',t('Access list name: '),$group['gname'], ''),
'$gid' => $group['id'],
'$drop' => $drop_txt,
'$public' => array('public',t('Members are visible to other channels'), $group['visible'], ''),
'$form_security_token_edit' => get_form_security_token('group_edit'),
'$delete' => t('Delete access list'),
'$form_security_token_drop' => get_form_security_token("group_drop"),
);
}
if(! isset($group))
return;
$groupeditor = array(
'label_members' => t('List members'),
'members' => array(),
'label_contacts' => t('Not in this list'),
'contacts' => array(),
);
$sec_token = addslashes(get_form_security_token('group_member_change'));
$textmode = (($switchtotext && (count($members) > $switchtotext)) ? true : 'card');
foreach($members as $member) {
if($member['xchan_url']) {
$member['archived'] = (intval($member['abook_archived']) ? true : false);
$member['click'] = 'groupChangeMember(' . $group['id'] . ',\'' . base64url_encode($member['xchan_hash']) . '\',\'' . $sec_token . '\'); return false;';
$groupeditor['members'][] = micropro($member,true,'mpgroup', $textmode);
}
else
AccessList::member_remove(local_channel(),$group['gname'],$member['xchan_hash']);
}
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d AND abook_self = 0 and abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 order by xchan_name asc",
intval(local_channel())
);
if(count($r)) {
$textmode = (($switchtotext && (count($r) > $switchtotext)) ? true : 'card');
foreach($r as $member) {
if(! in_array($member['xchan_hash'],$preselected)) {
$member['archived'] = (intval($member['abook_archived']) ? true : false);
$member['click'] = 'groupChangeMember(' . $group['id'] . ',\'' . base64url_encode($member['xchan_hash']) . '\',\'' . $sec_token . '\'); return false;';
$groupeditor['contacts'][] = micropro($member,true,'mpall', $textmode);
}
}
}
$context['$groupeditor'] = $groupeditor;
$context['$desc'] = t('Select a channel to toggle membership');
if($change) {
$tpl = get_markup_template('groupeditor.tpl');
echo replace_macros($tpl, $context);
killme();
}
return replace_macros($tpl, $context);
}
}

View file

@ -76,7 +76,7 @@ class Lockview extends \Zotlabs\Web\Controller {
killme(); killme();
} }
if(($item['item_private'] == 1) && (! strlen($item['allow_cid'])) && (! strlen($item['allow_gid'])) if(intval($item['item_private']) && (! strlen($item['allow_cid'])) && (! strlen($item['allow_gid']))
&& (! strlen($item['deny_cid'])) && (! strlen($item['deny_gid']))) { && (! strlen($item['deny_cid'])) && (! strlen($item['deny_gid']))) {
// if the post is private, but public_policy is blank ("visible to the internet"), and there aren't any // if the post is private, but public_policy is blank ("visible to the internet"), and there aren't any

View file

@ -3,6 +3,7 @@ namespace Zotlabs\Module;
use App; use App;
use Zotlabs\Web\Controller; use Zotlabs\Web\Controller;
use Zotlabs\Lib\PConfig;
require_once('include/security.php'); require_once('include/security.php');
@ -20,7 +21,8 @@ class Manage extends Controller {
$change_channel = ((argc() > 1) ? intval(argv(1)) : 0); $change_channel = ((argc() > 1) ? intval(argv(1)) : 0);
if ((argc() > 2) && (argv(2) === 'default')) { if (argc() > 2) {
if (argv(2) === 'default') {
$r = q("select channel_id from channel where channel_id = %d and channel_account_id = %d limit 1", $r = q("select channel_id from channel where channel_id = %d and channel_account_id = %d limit 1",
intval($change_channel), intval($change_channel),
intval(get_account_id()) intval(get_account_id())
@ -31,6 +33,11 @@ class Manage extends Controller {
intval(get_account_id()) intval(get_account_id())
); );
} }
}
elseif (argv(2) === 'menu') {
$state = intval(PConfig::get($change_channel,'system','include_in_menu', 0));
PConfig::set($change_channel,'system','include_in_menu',1 - $state);
}
goaway(z_root() . '/manage'); goaway(z_root() . '/manage');
} }
@ -60,6 +67,7 @@ class Manage extends Controller {
$channels = $r; $channels = $r;
for ($x = 0; $x < count($channels); $x ++) { for ($x = 0; $x < count($channels); $x ++) {
$channels[$x]['link'] = 'manage/' . intval($channels[$x]['channel_id']); $channels[$x]['link'] = 'manage/' . intval($channels[$x]['channel_id']);
$channels[$x]['include_in_menu'] = intval(PConfig::get($channels[$x]['channel_id'],'system','include_in_menu',0));
$channels[$x]['default'] = (($channels[$x]['channel_id'] == $account['account_default_channel']) ? "1" : ''); $channels[$x]['default'] = (($channels[$x]['channel_id'] == $account['account_default_channel']) ? "1" : '');
$channels[$x]['default_links'] = '1'; $channels[$x]['default_links'] = '1';
$channels[$x]['collections_label'] = t('Collection'); $channels[$x]['collections_label'] = t('Collection');
@ -175,6 +183,8 @@ class Manage extends Controller {
'$desc' => t('Switch to one of your channels by selecting it.'), '$desc' => t('Switch to one of your channels by selecting it.'),
'$msg_default' => t('Default Channel'), '$msg_default' => t('Default Channel'),
'$msg_make_default' => t('Make Default'), '$msg_make_default' => t('Make Default'),
'$msg_include' => t('Add to menu'),
'$msg_no_include' => t('Remove from menu'),
'$create' => $create, '$create' => $create,
'$all_channels' => $channels, '$all_channels' => $channels,
'$mail_format' => t('%d new messages'), '$mail_format' => t('%d new messages'),

View file

@ -64,7 +64,7 @@ class Network extends Controller {
$category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : ''); $category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : '');
$hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : ''); $hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : '');
$verb = ((x($_REQUEST,'verb')) ? $_REQUEST['verb'] : ''); $verb = ((x($_REQUEST,'verb')) ? $_REQUEST['verb'] : '');
$dm = ((x($_REQUEST,'dm')) ? $_REQUEST['dm'] : 0);
$order = get_pconfig(local_channel(), 'mod_network', 'order', 0); $order = get_pconfig(local_channel(), 'mod_network', 'order', 0);
switch ($order) { switch ($order) {
@ -122,8 +122,8 @@ class Network extends Controller {
$def_acl = [ 'allow_gid' => '<' . $r[0]['hash'] . '>' ]; $def_acl = [ 'allow_gid' => '<' . $r[0]['hash'] . '>' ];
} }
$default_cmin = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmin',0) : (-1)); $default_cmin = ((Apps::system_app_installed(local_channel(),'Friend Zoom')) ? get_pconfig(local_channel(),'affinity','cmin',0) : (-1));
$default_cmax = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmax',99) : (-1)); $default_cmax = ((Apps::system_app_installed(local_channel(),'Friend Zoom')) ? get_pconfig(local_channel(),'affinity','cmax',99) : (-1));
$cid = ((x($_GET,'cid')) ? intval($_GET['cid']) : 0); $cid = ((x($_GET,'cid')) ? intval($_GET['cid']) : 0);
$star = ((x($_GET,'star')) ? intval($_GET['star']) : 0); $star = ((x($_GET,'star')) ? intval($_GET['star']) : 0);
@ -229,7 +229,7 @@ class Network extends Controller {
if ($group) { if ($group) {
$contact_str = ''; $contact_str = '';
$contacts = AccessList::members($group); $contacts = AccessList::members(local_channel(),$group);
if ($contacts) { if ($contacts) {
$contact_str = ids_to_querystr($contacts,'xchan',true); $contact_str = ids_to_querystr($contacts,'xchan',true);
} }
@ -336,6 +336,7 @@ class Network extends Controller {
'$conv' => (($conv) ? $conv : '0'), '$conv' => (($conv) ? $conv : '0'),
'$spam' => (($spam) ? $spam : '0'), '$spam' => (($spam) ? $spam : '0'),
'$fh' => '0', '$fh' => '0',
'$dm' => (($dm) ? $dm : '0'),
'$nouveau' => (($nouveau) ? $nouveau : '0'), '$nouveau' => (($nouveau) ? $nouveau : '0'),
'$wall' => '0', '$wall' => '0',
'$static' => $static, '$static' => $static,
@ -382,15 +383,27 @@ class Network extends Controller {
} }
if ($verb) { if ($verb) {
if (substr($verb,0,1) === '.') {
$verb = substr($verb,1);
$sql_extra .= sprintf(" AND item.obj_type like '%s' ",
dbesc(protect_sprintf('%' . $verb . '%'))
);
}
else {
$sql_extra .= sprintf(" AND item.verb like '%s' ", $sql_extra .= sprintf(" AND item.verb like '%s' ",
dbesc(protect_sprintf('%' . $verb . '%')) dbesc(protect_sprintf('%' . $verb . '%'))
); );
} }
}
if (strlen($file)) { if (strlen($file)) {
$sql_extra .= term_query('item',$file,TERM_FILE); $sql_extra .= term_query('item',$file,TERM_FILE);
} }
if ($dm) {
$sql_extra .= " and item_private = 2 ";
}
if ($conv) { if ($conv) {
$item_thread_top = ''; $item_thread_top = '';

View file

@ -0,0 +1,28 @@
<?php
namespace Zotlabs\Module;
use Zotlabs\Lib\Apps;
use Zotlabs\Lib\Libsync;
use Zotlabs\Web\Controller;
class Nocomment extends Controller {
function get() {
$desc = t('This app allows you to disable comments on individual posts.');
$text = '<div class="section-content-info-wrapper">' . $desc . '</div>';
if(! ( local_channel() && Apps::system_app_installed(local_channel(),'No Comment'))) {
return $text;
}
$desc = t('This app is installed. A button to control the ability to comment may be found below the post editor.');
$text = '<div class="section-content-info-wrapper">' . $desc . '</div>';
return $text;
}
}

View file

@ -3,7 +3,7 @@ namespace Zotlabs\Module; /** @file */
use Zotlabs\Lib\Libsync; use Zotlabs\Lib\Libsync;
use Zotlabs\Web\Controller; use Zotlabs\Web\Controller;
use Zotlabs\Lib\Apps;
class Notes extends Controller { class Notes extends Controller {
@ -26,7 +26,7 @@ class Notes extends Controller {
set_pconfig(local_channel(),'notes','text.bak',$old_text); set_pconfig(local_channel(),'notes','text.bak',$old_text);
} }
set_pconfig(local_channel(),'notes','text',$body); set_pconfig(local_channel(),'notes','text',$body);
}
// push updates to channel clones // push updates to channel clones
@ -38,5 +38,26 @@ class Notes extends Controller {
json_return_and_die($ret); json_return_and_die($ret);
} }
}
function get() {
$desc = t('This app allows you to create private notes for your personal use.');
$text = '<div class="section-content-info-wrapper">' . $desc . '</div>';
if(! ( local_channel() && Apps::system_app_installed(local_channel(),'Notes'))) {
return $text;
}
$desc = t('This app is installed. The Notes tool can be found on your network stream page.');
$text = '<div class="section-content-info-wrapper">' . $desc . '</div>';
return $text;
}
} }

View file

@ -33,7 +33,7 @@ class Photo extends \Zotlabs\Web\Controller {
$channel = channelx_by_n($r[0]['uid']); $channel = channelx_by_n($r[0]['uid']);
$obj = json_decode($r[0]['obj'],true); $obj = json_decode($r[0]['obj'],true);
$obj['actor'] = Activity::encode_person($channel,true,((defined('NOMADIC')) ? false : true)); $obj['actor'] = Activity::encode_person($channel,true,((get_config('system','activitypub')) ? true : false));
$x = array_merge(['@context' => [ $x = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV, ACTIVITYSTREAMS_JSONLD_REV,

View file

@ -0,0 +1,24 @@
<?php
namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Apps;
class Photomap extends Controller {
function get() {
$desc = t('This app provides a displayable map when viewing detail of photos that contain location information.');
$text = '<div class="section-content-info-wrapper">' . $desc . '</div>';
if(! ( local_channel() && Apps::system_app_installed(local_channel(),'Photomap'))) {
return $text;
}
return $text . '<br><br>' . t('This app is currently installed.');
}
}

View file

@ -2,6 +2,7 @@
namespace Zotlabs\Module; namespace Zotlabs\Module;
use App; use App;
use Zotlabs\Lib\Apps;
use Zotlabs\Lib\Libsync; use Zotlabs\Lib\Libsync;
use Zotlabs\Lib\Libprofile; use Zotlabs\Lib\Libprofile;
use Zotlabs\Lib\PermissionDescription; use Zotlabs\Lib\PermissionDescription;
@ -215,6 +216,71 @@ class Photos extends Controller {
} }
} }
// this still needs some work
if(defined('FIXED')) {
if((x($_POST,'rotate') !== false) && ( (intval($_POST['rotate']) == 1) || (intval($_POST['rotate']) == 2) )) {
logger('rotate');
$resource_id = argv(2);
$r = q("select * from photo where resource_id = '%s' and uid = %d and imgscale = 0 limit 1",
dbesc($resource_id),
intval($page_owner_uid)
);
if($r) {
$ph = photo_factory(@file_get_contents(dbunescbin($r[0]['content'])), $r[0]['mimetype']);
if($ph->is_valid()) {
$rotate_deg = ( (intval($_POST['rotate']) == 1) ? 270 : 90 );
$ph->rotate($rotate_deg);
$edited = datetime_convert();
q("update attach set filesize = %d, edited = '%s' where hash = '%s' and uid = %d",
strlen($ph->imageString()),
dbescdate($edited),
dbesc($resource_id),
intval($page_owner_uid)
);
$ph->saveImage(dbunescbin($r[0]['content']));
$arr = [
'aid' => get_account_id(),
'uid' => intval($page_owner_uid),
'resource_id' => dbesc($resource_id),
'filename' => $r[0]['filename'],
'imgscale' => 0,
'album' => $r[0]['album'],
'os_path' => $r[0]['os_path'],
'os_storage' => 1,
'os_syspath' => dbunescbin($r[0]['content']),
'display_path' => $r[0]['display_path'],
'photo_usage' => PHOTO_NORMAL,
'edited' => dbescdate($edited)
];
$ph->save($arr);
unset($arr['os_syspath']);
if($width > 1024 || $height > 1024)
$ph->scaleImage(1024);
$ph->storeThumbnail($arr, PHOTO_RES_1024);
if($width > 640 || $height > 640)
$ph->scaleImage(640);
$ph->storeThumbnail($arr, PHOTO_RES_640);
if($width > 320 || $height > 320)
$ph->scaleImage(320);
$ph->storeThumbnail($arr, PHOTO_RES_320);
}
}
}}
if((argc() > 2) && ((x($_POST,'desc') !== false) || (x($_POST,'newtag') !== false))) { if((argc() > 2) && ((x($_POST,'desc') !== false) || (x($_POST,'newtag') !== false))) {
$desc = ((x($_POST,'desc')) ? notags(trim($_POST['desc'])) : ''); $desc = ((x($_POST,'desc')) ? notags(trim($_POST['desc'])) : '');
@ -470,7 +536,7 @@ class Photos extends Controller {
return; return;
} }
$unsafe = ((array_key_exists('unsafe',$_REQUEST) && $_REQUEST['unsafe']) ? 1 : 0); $unsafe = 1 - get_safemode();
require_once('include/bbcode.php'); require_once('include/bbcode.php');
require_once('include/security.php'); require_once('include/security.php');
@ -953,7 +1019,7 @@ class Photos extends Controller {
); );
} }
if($link_item['coord']) { if($link_item['coord'] && Apps::system_app_installed($owner_uid,'Photomap')) {
$map = generate_map($link_item['coord']); $map = generate_map($link_item['coord']);
} }
} }

View file

@ -5,6 +5,7 @@ namespace Zotlabs\Module;
use App; use App;
use Zotlabs\Web\Controller; use Zotlabs\Web\Controller;
use Zotlabs\Lib\Enotify; use Zotlabs\Lib\Enotify;
use Zotlabs\Lib\Apps;
require_once('include/bbcode.php'); require_once('include/bbcode.php');
@ -164,6 +165,10 @@ class Ping extends Controller {
$notify_pubs = ((local_channel()) ? ($vnotify & VNOTIFY_PUBS) && $discover_tab_on : $discover_tab_on); $notify_pubs = ((local_channel()) ? ($vnotify & VNOTIFY_PUBS) && $discover_tab_on : $discover_tab_on);
if ($notify_pubs && local_channel() && ! Apps::system_app_installed(local_channel(),'Public Stream')) {
$notify_pubs = false;
}
$sys = get_sys_channel(); $sys = get_sys_channel();
if ($notify_pubs) { if ($notify_pubs) {
@ -291,6 +296,7 @@ class Ping extends Controller {
$mid = basename($tt['link']); $mid = basename($tt['link']);
$mid = ((strpos($mid, 'b64.') === 0) ? @base64url_decode(substr($mid, 4)) : $mid);
if (in_array($tt['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) { if (in_array($tt['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
// we need the thread parent // we need the thread parent
@ -393,7 +399,7 @@ class Ping extends Controller {
if ($r) { if ($r) {
foreach ($r as $rr) { foreach ($r as $rr) {
$local_result[] = [ $local_result[] = [
'notify_link' => z_root() . '/connections/ifpending', 'notify_link' => z_root() . '/connections/' . $rr['abook_id'],
'name' => $rr['xchan_name'], 'name' => $rr['xchan_name'],
'addr' => $rr['xchan_addr'], 'addr' => $rr['xchan_addr'],
'url' => $rr['xchan_url'], 'url' => $rr['xchan_url'],

View file

@ -19,6 +19,10 @@ class Poster extends Controller {
$u = channelx_by_nick($nick); $u = channelx_by_nick($nick);
if (! $u) {
return;
}
$sql_extra = permissions_sql(intval($u['channel_id'])); $sql_extra = permissions_sql(intval($u['channel_id']));
$r = q("select content from attach where hash = '%s' and uid = %d and os_storage = 1 $sql_extra limit 1", $r = q("select content from attach where hash = '%s' and uid = %d and os_storage = 1 $sql_extra limit 1",
@ -33,5 +37,6 @@ class Poster extends Controller {
killme(); killme();
} }
} }
killme();
} }
} }

View file

@ -75,7 +75,7 @@ class Profile extends \Zotlabs\Web\Controller {
$chan = channelx_by_nick(argv(1)); $chan = channelx_by_nick(argv(1));
if(! $chan) if(! $chan)
http_status_exit(404, 'Not found'); http_status_exit(404, 'Not found');
$p = Activity::encode_person($chan,true,((defined('NOMADIC')) ? false : true)); $p = Activity::encode_person($chan,true,((get_config('system','activitypub')) ? true : false));
if(! $p) { if(! $p) {
http_status_exit(404, 'Not found'); http_status_exit(404, 'Not found');
} }

View file

@ -1,23 +1,23 @@
<?php <?php
namespace Zotlabs\Module; namespace Zotlabs\Module;
/*
* @file Profile_photo.php
* @brief Module-file with functions for uploading and scaling of profile-photos
*
*/
use App; use App;
use Zotlabs\Web\Controller; use Zotlabs\Web\Controller;
use Zotlabs\Lib\Libsync; use Zotlabs\Lib\Libsync;
use Zotlabs\Lib\Libprofile; use Zotlabs\Lib\Libprofile;
use Zotlabs\Daemon\Master;
/*
* @file Profile_photo.php
* @brief Module-file with functions for handling of profile-photos
*
*/
require_once('include/photo_factory.php'); require_once('include/photo_factory.php');
require_once('include/photos.php'); require_once('include/photos.php');
class Profile_photo extends Controller { class Profile_photo extends Controller {
@ -33,7 +33,7 @@ class Profile_photo extends Controller {
return; return;
} }
$channel = \App::get_channel(); $channel = App::get_channel();
Libprofile::load($channel['channel_address']); Libprofile::load($channel['channel_address']);
} }
@ -57,8 +57,6 @@ class Profile_photo extends Controller {
// logger('crop: ' . print_r($_POST,true)); // logger('crop: ' . print_r($_POST,true));
// phase 2 - we have finished cropping // phase 2 - we have finished cropping
if (argc() != 2) { if (argc() != 2) {
@ -73,7 +71,6 @@ class Profile_photo extends Controller {
$image_id = substr($image_id,0,-2); $image_id = substr($image_id,0,-2);
} }
// unless proven otherwise // unless proven otherwise
$is_default_profile = 1; $is_default_profile = 1;
@ -83,12 +80,12 @@ class Profile_photo extends Controller {
intval(local_channel()) intval(local_channel())
); );
if ($r) { if ($r) {
$profile = $r[0]; $profile = array_shift($r);
if(! intval($profile['is_default'])) if (! intval($profile['is_default'])) {
$is_default_profile = 0; $is_default_profile = 0;
} }
} }
}
$srcX = intval($_POST['xstart']); $srcX = intval($_POST['xstart']);
$srcY = intval($_POST['ystart']); $srcY = intval($_POST['ystart']);
@ -101,8 +98,8 @@ class Profile_photo extends Controller {
intval($scale)); intval($scale));
if ($r) { if ($r) {
$base_image = $r[0]; $base_image = array_shift($r);
$base_image['content'] = (($r[0]['os_storage']) ? @file_get_contents(dbunescbin($base_image['content'])) : dbunescbin($base_image['content'])); $base_image['content'] = (($base_image['os_storage']) ? @file_get_contents(dbunescbin($base_image['content'])) : dbunescbin($base_image['content']));
$im = photo_factory($base_image['content'], $base_image['mimetype']); $im = photo_factory($base_image['content'], $base_image['mimetype']);
if ($im->is_valid()) { if ($im->is_valid()) {
@ -126,17 +123,17 @@ class Profile_photo extends Controller {
$p['imgscale'] = PHOTO_RES_PROFILE_300; $p['imgscale'] = PHOTO_RES_PROFILE_300;
$p['photo_usage'] = (($is_default_profile) ? PHOTO_PROFILE : PHOTO_NORMAL); $p['photo_usage'] = (($is_default_profile) ? PHOTO_PROFILE : PHOTO_NORMAL);
$r1 = $im->save($p); $r1 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_300);
$im->scaleImage(80); $im->scaleImage(80);
$p['imgscale'] = PHOTO_RES_PROFILE_80; $p['imgscale'] = PHOTO_RES_PROFILE_80;
$r2 = $im->save($p); $r2 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_80);
$im->scaleImage(48); $im->scaleImage(48);
$p['imgscale'] = PHOTO_RES_PROFILE_48; $p['imgscale'] = PHOTO_RES_PROFILE_48;
$r3 = $im->save($p); $r3 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_48);
if ($r1 === false || $r2 === false || $r3 === false) { if ($r1 === false || $r2 === false || $r3 === false) {
// if one failed, delete them all so we can start over. // if one failed, delete them all so we can start over.
@ -151,7 +148,7 @@ class Profile_photo extends Controller {
return; return;
} }
$channel = \App::get_channel(); $channel = App::get_channel();
// If setting for the default profile, unset the profile photo flag from any other photos I own // If setting for the default profile, unset the profile photo flag from any other photos I own
@ -209,9 +206,9 @@ class Profile_photo extends Controller {
photo_profile_setperms(local_channel(),$base_image['resource_id'],$_REQUEST['profile']); photo_profile_setperms(local_channel(),$base_image['resource_id'],$_REQUEST['profile']);
$sync = attach_export_data($channel,$base_image['resource_id']); $sync = attach_export_data($channel,$base_image['resource_id']);
if($sync) if ($sync) {
Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync), 'profile' => $sync_profiles)); Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync), 'profile' => $sync_profiles));
}
// Similarly, tell the nav bar to bypass the cache and update the avatar image. // Similarly, tell the nav bar to bypass the cache and update the avatar image.
$_SESSION['reload_avatar'] = true; $_SESSION['reload_avatar'] = true;
@ -219,15 +216,15 @@ class Profile_photo extends Controller {
info( t('Shift-reload the page or clear browser cache if the new photo does not display immediately.') . EOL); info( t('Shift-reload the page or clear browser cache if the new photo does not display immediately.') . EOL);
// Update directory in background // Update directory in background
\Zotlabs\Daemon\Master::Summon(array('Directory',$channel['channel_id'])); Master::Summon( [ 'Directory', $channel['channel_id'] ] );
} }
else else {
notice( t('Unable to process image') . EOL); notice( t('Unable to process image') . EOL);
} }
}
goaway(z_root() . '/profiles'); goaway(z_root() . '/profiles');
return; // NOTREACHED
} }
// A new photo was uploaded. Store it and save some important details // A new photo was uploaded. Store it and save some important details
@ -251,7 +248,7 @@ class Profile_photo extends Controller {
if (array_key_exists('HTTP_CONTENT_RANGE',$_SERVER)) { if (array_key_exists('HTTP_CONTENT_RANGE',$_SERVER)) {
$pm = preg_match('/bytes (\d*)\-(\d*)\/(\d*)/',$_SERVER['HTTP_CONTENT_RANGE'],$matches); $pm = preg_match('/bytes (\d*)\-(\d*)\/(\d*)/',$_SERVER['HTTP_CONTENT_RANGE'],$matches);
if ($pm) { if ($pm) {
logger('Content-Range: ' . print_r($matches,true)); logger('Content-Range: ' . print_r($matches,true), LOGGER_DEBUG);
$partial = true; $partial = true;
} }
} }
@ -287,13 +284,11 @@ class Profile_photo extends Controller {
} }
} }
$res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Profile Photos'), 'hash' => $hash)); $res = attach_store(App::get_channel(), get_observer_hash(), '', array('album' => t('Profile Photos'), 'hash' => $hash));
logger('attach_store: ' . print_r($res,true)); logger('attach_store: ' . print_r($res,true), LOGGER_DEBUG);
json_return_and_die([ 'message' => $hash ]); json_return_and_die([ 'message' => $hash ]);
} }
if (($res && intval($res['data']['is_photo'])) || $importing) { if (($res && intval($res['data']['is_photo'])) || $importing) {
@ -326,7 +321,7 @@ class Profile_photo extends Controller {
return; return;
} }
return $this->profile_photo_crop_ui_head($a, $ph, $hash, $smallest); return $this->profile_photo_crop_ui_head($ph, $hash, $smallest);
// This will "fall through" to the get() method, and since // This will "fall through" to the get() method, and since
// App::$data['imagecrop'] is set, it will proceed to cropping // App::$data['imagecrop'] is set, it will proceed to cropping
@ -336,7 +331,6 @@ class Profile_photo extends Controller {
/* @brief Generate content of profile-photo view /* @brief Generate content of profile-photo view
* *
* @param $a Current application
* @return void * @return void
* *
*/ */
@ -349,12 +343,13 @@ class Profile_photo extends Controller {
return; return;
} }
$channel = \App::get_channel(); $channel = App::get_channel();
$pf = 0; $pf = 0;
$newuser = false; $newuser = false;
if(argc() == 2 && argv(1) === 'new') if (argc() == 2 && argv(1) === 'new') {
$newuser = true; $newuser = true;
}
if (argv(1) === 'use') { if (argv(1) === 'use') {
if (argc() < 3) { if (argc() < 3) {
@ -364,7 +359,6 @@ class Profile_photo extends Controller {
$resource_id = argv(2); $resource_id = argv(2);
$pf = (($_REQUEST['pf']) ? intval($_REQUEST['pf']) : 0); $pf = (($_REQUEST['pf']) ? intval($_REQUEST['pf']) : 0);
$c = q("select id, is_default from profile where uid = %d", $c = q("select id, is_default from profile where uid = %d",
@ -391,9 +385,10 @@ class Profile_photo extends Controller {
} }
$havescale = false; $havescale = false;
foreach ($r as $rr) { foreach ($r as $rr) {
if($rr['imgscale'] == PHOTO_RES_PROFILE_80) if ($rr['imgscale'] == PHOTO_RES_PROFILE_80) {
$havescale = true; $havescale = true;
} }
}
// set an already loaded and cropped photo as profile photo // set an already loaded and cropped photo as profile photo
@ -402,7 +397,8 @@ class Profile_photo extends Controller {
$r = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND uid = %d", $r = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND uid = %d",
intval(PHOTO_NORMAL), intval(PHOTO_NORMAL),
intval(PHOTO_PROFILE), intval(PHOTO_PROFILE),
intval(local_channel())); intval(local_channel())
);
$r = q("UPDATE photo SET photo_usage = %d WHERE uid = %d AND resource_id = '%s'", $r = q("UPDATE photo SET photo_usage = %d WHERE uid = %d AND resource_id = '%s'",
intval(PHOTO_PROFILE), intval(PHOTO_PROFILE),
@ -410,8 +406,7 @@ class Profile_photo extends Controller {
dbesc($resource_id) dbesc($resource_id)
); );
$r = q("UPDATE xchan set xchan_photo_date = '%s' $r = q("UPDATE xchan set xchan_photo_date = '%s' where xchan_hash = '%s'",
where xchan_hash = '%s'",
dbesc(datetime_convert()), dbesc(datetime_convert()),
dbesc($channel['xchan_hash']) dbesc($channel['xchan_hash'])
); );
@ -419,11 +414,11 @@ class Profile_photo extends Controller {
photo_profile_setperms(local_channel(),$resource_id,$_REQUEST['profile']); photo_profile_setperms(local_channel(),$resource_id,$_REQUEST['profile']);
$sync = attach_export_data($channel,$resource_id); $sync = attach_export_data($channel,$resource_id);
if($sync) if ($sync) {
Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync))); Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync)));
}
Master::Summon( [ 'Directory',local_channel() ] );
\Zotlabs\Daemon\Master::Summon(array('Directory',local_channel()));
goaway(z_root() . '/profiles'); goaway(z_root() . '/profiles');
} }
@ -437,10 +432,12 @@ class Profile_photo extends Controller {
return; return;
} }
if(intval($r[0]['os_storage'])) if (intval($r[0]['os_storage'])) {
$data = @file_get_contents(dbunescbin($r[0]['content'])); $data = @file_get_contents(dbunescbin($r[0]['content']));
else }
else {
$data = dbunescbin($r[0]['content']); $data = dbunescbin($r[0]['content']);
}
$ph = photo_factory($data, $r[0]['mimetype']); $ph = photo_factory($data, $r[0]['mimetype']);
$smallest = 0; $smallest = 0;
@ -462,17 +459,16 @@ class Profile_photo extends Controller {
} }
if ($multi_profiles) { if ($multi_profiles) {
\App::$data['importfile'] = $resource_id; App::$data['importfile'] = $resource_id;
} }
else { else {
$this->profile_photo_crop_ui_head($a, $ph, $hash, $smallest); $this->profile_photo_crop_ui_head($ph, $hash, $smallest);
} }
// falls through with App::$data['imagecrop'] set so we go straight to the cropping section // falls through with App::$data['imagecrop'] set so we go straight to the cropping section
} }
// present an upload form // present an upload form
$profiles = q("select id, profile_name as name, is_default from profile where uid = %d order by id asc", $profiles = q("select id, profile_name as name, is_default from profile where uid = %d order by id asc",
@ -482,23 +478,25 @@ class Profile_photo extends Controller {
if ($profiles) { if ($profiles) {
for ($x = 0; $x < count($profiles); $x ++) { for ($x = 0; $x < count($profiles); $x ++) {
$profiles[$x]['selected'] = false; $profiles[$x]['selected'] = false;
if($pf && $profiles[$x]['id'] == $pf) if ($pf && $profiles[$x]['id'] == $pf) {
$profiles[$x]['selected'] = true; $profiles[$x]['selected'] = true;
if((! $pf) && $profiles[$x]['is_default']) }
if ((! $pf) && $profiles[$x]['is_default']) {
$profiles[$x]['selected'] = true; $profiles[$x]['selected'] = true;
} }
} }
}
$importing = ((array_key_exists('importfile',\App::$data)) ? true : false); $importing = ((array_key_exists('importfile',App::$data)) ? true : false);
if(! x(\App::$data,'imagecrop')) { if (! array_key_exists('imagecrop', App::$data)) {
$tpl = get_markup_template('profile_photo.tpl'); $tpl = get_markup_template('profile_photo.tpl');
$o .= replace_macros($tpl,array( $o .= replace_macros($tpl, [
'$user' => \App::$channel['channel_address'], '$user' => App::$channel['channel_address'],
'$info' => ((count($profiles) > 1) ? t('Your default profile photo is visible to anybody on the internet. Profile photos for alternate profiles will inherit the permissions of the profile') : t('Your profile photo is visible to anybody on the internet and may be distributed to other websites.')), '$info' => ((count($profiles) > 1) ? t('Your default profile photo is visible to anybody on the internet. Profile photos for alternate profiles will inherit the permissions of the profile') : t('Your profile photo is visible to anybody on the internet and may be distributed to other websites.')),
'$importfile' => (($importing) ? \App::$data['importfile'] : ''), '$importfile' => (($importing) ? App::$data['importfile'] : ''),
'$lbl_upfile' => t('Upload File:'), '$lbl_upfile' => t('Upload File:'),
'$lbl_profiles' => t('Select a profile:'), '$lbl_profiles' => t('Select a profile:'),
'$title' => (($importing) ? t('Use Photo for Profile') : t('Change Profile Photo')), '$title' => (($importing) ? t('Use Photo for Profile') : t('Change Profile Photo')),
@ -517,69 +515,60 @@ class Profile_photo extends Controller {
'$modalerrorlink' => t('Error getting photo link'), '$modalerrorlink' => t('Error getting photo link'),
'$modalerroralbum' => t('Error getting album'), '$modalerroralbum' => t('Error getting album'),
'$form_security_token' => get_form_security_token("profile_photo"), '$form_security_token' => get_form_security_token("profile_photo"),
'$select' => t('Select existing photo'), '$select' => t('Select previously uploaded photo'),
)); ]);
call_hooks('profile_photo_content_end', $o); call_hooks('profile_photo_content_end', $o);
return $o; return $o;
} }
else { else {
// present a cropping form // present a cropping form
$filename = \App::$data['imagecrop'] . '-' . \App::$data['imagecrop_resolution']; $filename = App::$data['imagecrop'] . '-' . App::$data['imagecrop_resolution'];
$resolution = \App::$data['imagecrop_resolution']; $resolution = App::$data['imagecrop_resolution'];
$tpl = get_markup_template("cropbody.tpl"); $o .= replace_macros(get_markup_template('cropbody.tpl'), [
$o .= replace_macros($tpl,array(
'$filename' => $filename, '$filename' => $filename,
'$profile' => intval($_REQUEST['profile']), '$profile' => intval($_REQUEST['profile']),
'$resource' => \App::$data['imagecrop'] . '-' . \App::$data['imagecrop_resolution'], '$resource' => App::$data['imagecrop'] . '-' . App::$data['imagecrop_resolution'],
'$image_url' => z_root() . '/photo/' . $filename, '$image_url' => z_root() . '/photo/' . $filename,
'$title' => t('Crop Image'), '$title' => t('Crop Image'),
'$desc' => t('Please adjust the image cropping for optimum viewing.'), '$desc' => t('Please adjust the image cropping for optimum viewing.'),
'$form_security_token' => get_form_security_token("profile_photo"), '$form_security_token' => get_form_security_token("profile_photo"),
'$done' => t('Done Editing') '$done' => t('Done Editing')
)); ]);
return $o; return $o;
} }
return; // NOTREACHED
} }
/* @brief Generate the UI for photo-cropping /* @brief Generate the UI for photo-cropping
* *
* @param $a Current application
* @param $ph Photo-Factory * @param $ph Photo-Factory
* @return void * @return void
* *
*/ */
function profile_photo_crop_ui_head($ph, $hash, $smallest) {
function profile_photo_crop_ui_head(&$a, $ph, $hash, $smallest){
$max_length = get_config('system','max_image_length'); $max_length = get_config('system','max_image_length');
if(! $max_length) if (! $max_length) {
$max_length = MAX_IMAGE_LENGTH; $max_length = MAX_IMAGE_LENGTH;
if($max_length > 0) }
if ($max_length > 0) {
$ph->scaleImage($max_length); $ph->scaleImage($max_length);
\App::$data['width'] = $ph->getWidth();
\App::$data['height'] = $ph->getHeight();
if(\App::$data['width'] < 500 || \App::$data['height'] < 500) {
$ph->scaleImageUp(400);
\App::$data['width'] = $ph->getWidth();
\App::$data['height'] = $ph->getHeight();
} }
App::$data['width'] = $ph->getWidth();
App::$data['height'] = $ph->getHeight();
\App::$data['imagecrop'] = $hash; if (App::$data['width'] < 500 || App::$data['height'] < 500) {
\App::$data['imagecrop_resolution'] = $smallest; $ph->scaleImageUp(400);
\App::$page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), array()); App::$data['width'] = $ph->getWidth();
App::$data['height'] = $ph->getHeight();
}
App::$data['imagecrop'] = $hash;
App::$data['imagecrop_resolution'] = $smallest;
App::$page['htmlhead'] .= replace_macros(get_markup_template('crophead.tpl'), []);
return; return;
} }
} }

View file

@ -5,6 +5,7 @@ use App;
use Zotlabs\Web\Controller; use Zotlabs\Web\Controller;
use Zotlabs\Lib\Libsync; use Zotlabs\Lib\Libsync;
use Zotlabs\Lib\Libprofile; use Zotlabs\Lib\Libprofile;
use Zotlabs\Daemon\Master;
use Sabre\VObject\Reader; use Sabre\VObject\Reader;
@ -77,7 +78,7 @@ class Profiles extends Controller {
[ [
'aid' => intval(get_account_id()), 'aid' => intval(get_account_id()),
'uid' => intval(local_channel()), 'uid' => intval(local_channel()),
'profile_guid' => random_string(), 'profile_guid' => new_uuid(),
'profile_name' => $name, 'profile_name' => $name,
'fullname' => $r1[0]['fullname'], 'fullname' => $r1[0]['fullname'],
'photo' => $r1[0]['photo'], 'photo' => $r1[0]['photo'],
@ -108,18 +109,18 @@ class Profiles extends Controller {
$name = t('Profile-') . ($num_profiles + 1); $name = t('Profile-') . ($num_profiles + 1);
$r1 = q("SELECT * FROM profile WHERE uid = %d AND id = %d LIMIT 1", $r1 = q("SELECT * FROM profile WHERE uid = %d AND id = %d LIMIT 1",
intval(local_channel()), intval(local_channel()),
intval(\App::$argv[2]) intval(argv(2))
); );
if(! count($r1)) { if(! count($r1)) {
notice( t('Profile unavailable to clone.') . EOL); notice( t('Profile unavailable to clone.') . EOL);
\App::$error = 404; App::$error = 404;
return; return;
} }
unset($r1[0]['id']); unset($r1[0]['id']);
$r1[0]['is_default'] = 0; $r1[0]['is_default'] = 0;
$r1[0]['publish'] = 0; $r1[0]['publish'] = 0;
$r1[0]['profile_name'] = dbesc($name); $r1[0]['profile_name'] = $name;
$r1[0]['profile_guid'] = dbesc(random_string()); $r1[0]['profile_guid'] = new_uuid();
create_table_from_array('profile', $r1[0]); create_table_from_array('profile', $r1[0]);
@ -164,11 +165,6 @@ class Profiles extends Controller {
killme(); killme();
} }
// Run Libprofile::load() here to make sure the theme is set before
// we start loading content
if(((argc() > 1) && (intval(argv(1)))) || !feature_enabled(local_channel(),'multi_profiles')) { if(((argc() > 1) && (intval(argv(1)))) || !feature_enabled(local_channel(),'multi_profiles')) {
if(feature_enabled(local_channel(),'multi_profiles')) if(feature_enabled(local_channel(),'multi_profiles'))
$id = argv(1); $id = argv(1);
@ -191,7 +187,7 @@ class Profiles extends Controller {
$chan = App::get_channel(); $chan = App::get_channel();
Libprofile::load($chan['channel_address'],$r[0]['id']); Libprofile::load($chan['channel_address'],$r[0]['profile_guid']);
} }
} }
@ -323,7 +319,7 @@ class Profiles extends Controller {
$orig_vcard = null; $orig_vcard = null;
$channel = \App::get_channel(); $channel = App::get_channel();
$default_vcard_cat = ((defined('DEFAULT_VCARD_CAT')) ? DEFAULT_VCARD_CAT : 'HOME'); $default_vcard_cat = ((defined('DEFAULT_VCARD_CAT')) ? DEFAULT_VCARD_CAT : 'HOME');
@ -594,15 +590,15 @@ class Profiles extends Controller {
if($r) if($r)
info( t('Profile updated.') . EOL); info( t('Profile updated.') . EOL);
$r = q("select * from profile where id = %d and uid = %d limit 1", $sync = q("select * from profile where id = %d and uid = %d limit 1",
intval(argv(1)), intval(argv(1)),
intval(local_channel()) intval(local_channel())
); );
if($r) { if($sync) {
Libsync::build_sync_packet(local_channel(),array('profile' => $r)); Libsync::build_sync_packet(local_channel(),array('profile' => $sync));
} }
$channel = \App::get_channel(); $channel = App::get_channel();
if($namechanged && $is_default) { if($namechanged && $is_default) {
$r = q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_hash = '%s'", $r = q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_hash = '%s'",
@ -617,9 +613,8 @@ class Profiles extends Controller {
} }
if($is_default) { if($is_default) {
// reload the info for the sidebar widget - why does this not work? Master::Summon(array('Directory',local_channel()));
Libprofile::load($channel['channel_address']); goaway(z_root() . '/profiles/' . $sync[0]['id']);
\Zotlabs\Daemon\Master::Summon(array('Directory',local_channel()));
} }
} }
} }

View file

@ -1,11 +1,15 @@
<?php <?php
namespace Zotlabs\Module; namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\PermissionDescription;
require_once('include/conversation.php'); require_once('include/conversation.php');
require_once('include/acl_selectors.php'); require_once('include/acl_selectors.php');
class Pubstream extends \Zotlabs\Web\Controller { class Pubstream extends Controller {
function get($update = 0, $load = false) { function get($update = 0, $load = false) {
@ -51,7 +55,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
if(local_channel() && (! $update)) { if(local_channel() && (! $update)) {
$channel = \App::get_channel(); $channel = App::get_channel();
$channel_acl = array( $channel_acl = array(
'allow_cid' => $channel['channel_allow_cid'], 'allow_cid' => $channel['channel_allow_cid'],
@ -66,7 +70,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
'default_location' => $channel['channel_location'], 'default_location' => $channel['channel_location'],
'nickname' => $channel['channel_address'], 'nickname' => $channel['channel_address'],
'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), 'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
'acl' => populate_acl($channel_acl,true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'), 'acl' => populate_acl($channel_acl,true,PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'),
'permissions' => $channel_acl, 'permissions' => $channel_acl,
'bang' => '', 'bang' => '',
'visitor' => true, 'visitor' => true,
@ -105,14 +109,14 @@ class Pubstream extends \Zotlabs\Web\Controller {
$o .= '<div id="live-pubstream"></div>' . "\r\n"; $o .= '<div id="live-pubstream"></div>' . "\r\n";
$o .= "<script> var profile_uid = " . ((intval(local_channel())) ? local_channel() : (-1)) $o .= "<script> var profile_uid = " . ((intval(local_channel())) ? local_channel() : (-1))
. "; var profile_page = " . \App::$pager['page'] . "; var profile_page = " . App::$pager['page']
. "; divmore_height = " . intval($maxheight) . "; </script>\r\n"; . "; divmore_height = " . intval($maxheight) . "; </script>\r\n";
//if we got a decoded hash we must encode it again before handing to javascript //if we got a decoded hash we must encode it again before handing to javascript
if($decoded) if($decoded)
$mid = 'b64.' . base64url_encode($mid); $mid = 'b64.' . base64url_encode($mid);
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array( App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
'$baseurl' => z_root(), '$baseurl' => z_root(),
'$pgtype' => 'pubstream', '$pgtype' => 'pubstream',
'$uid' => ((local_channel()) ? local_channel() : '0'), '$uid' => ((local_channel()) ? local_channel() : '0'),
@ -125,11 +129,12 @@ class Pubstream extends \Zotlabs\Web\Controller {
'$conv' => '0', '$conv' => '0',
'$spam' => '0', '$spam' => '0',
'$fh' => '1', '$fh' => '1',
'$dm' => '0',
'$nouveau' => '0', '$nouveau' => '0',
'$wall' => '0', '$wall' => '0',
'$list' => '0', '$list' => '0',
'$static' => $static, '$static' => $static,
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1), '$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
'$search' => '', '$search' => '',
'$xchan' => '', '$xchan' => '',
'$order' => 'comment', '$order' => 'comment',
@ -149,8 +154,8 @@ class Pubstream extends \Zotlabs\Web\Controller {
$pager_sql = ''; $pager_sql = '';
} }
else { else {
\App::set_pager_itemspage(20); App::set_pager_itemspage(20);
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start'])); $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
} }
require_once('include/channel.php'); require_once('include/channel.php');
@ -163,7 +168,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
$sys = get_sys_channel(); $sys = get_sys_channel();
$uids = " and item.uid = " . intval($sys['channel_id']) . " "; $uids = " and item.uid = " . intval($sys['channel_id']) . " ";
$sql_extra = item_permissions_sql($sys['channel_id']); $sql_extra = item_permissions_sql($sys['channel_id']);
\App::$data['firehose'] = intval($sys['channel_id']); App::$data['firehose'] = intval($sys['channel_id']);
} }
if(get_config('system','public_list_mode')) if(get_config('system','public_list_mode'))
@ -179,7 +184,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
$net_query = (($net) ? " left join xchan on xchan_hash = author_xchan " : ''); $net_query = (($net) ? " left join xchan on xchan_hash = author_xchan " : '');
$net_query2 = (($net) ? " and xchan_network = '" . protect_sprintf(dbesc($net)) . "' " : ''); $net_query2 = (($net) ? " and xchan_network = '" . protect_sprintf(dbesc($net)) . "' " : '');
$abook_uids = " and abook.abook_channel = " . intval(\App::$profile['profile_uid']) . " "; $abook_uids = " and abook.abook_channel = " . intval(App::$profile['profile_uid']) . " ";
$simple_update = (($_SESSION['loadtime']) ? " AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' " : ''); $simple_update = (($_SESSION['loadtime']) ? " AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' " : '');

View file

@ -74,7 +74,3 @@ These are handled in a similar fashion to their counterparts in the Unix shell
or C/C++ languages. Do not confuse the argc(),argv() functions with the or C/C++ languages. Do not confuse the argc(),argv() functions with the
global variables $argc,$argv which are passed to command line programs. These global variables $argc,$argv which are passed to command line programs. These
are handled separately by command line and Zotlabs/Daemon class functions. are handled separately by command line and Zotlabs/Daemon class functions.

View file

@ -1,33 +1,44 @@
<?php <?php
namespace Zotlabs\Module; namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
class Removeaccount extends \Zotlabs\Web\Controller { class Removeaccount extends Controller {
function post() { function post() {
if(! local_channel()) if (! local_channel()) {
return; return;
}
if($_SESSION['delegate']) if ($_SESSION['delegate']) {
return; return;
}
if((! x($_POST,'qxz_password')) || (! strlen(trim($_POST['qxz_password'])))) if ((! x($_POST,'qxz_password')) || (! strlen(trim($_POST['qxz_password'])))) {
return; return;
}
if((! x($_POST,'verify')) || (! strlen(trim($_POST['verify'])))) if ((! x($_POST,'verify')) || (! strlen(trim($_POST['verify'])))) {
return; return;
}
if($_POST['verify'] !== $_SESSION['remove_account_verify']) if ($_POST['verify'] !== $_SESSION['remove_account_verify']) {
return; return;
}
$account = App::get_account();
$account = \App::get_account();
$account_id = get_account_id(); $account_id = get_account_id();
$x = account_verify_password($account['account_email'],$_POST['qxz_password']); if (! ($account && $account_id)) {
if(! ($x && $x['account']))
return; return;
}
$x = account_verify_password($account['account_email'],$_POST['qxz_password']);
if (! ($x && $x['account'])) {
return;
}
if ($account['account_password_changed'] > NULL_DATE) { if ($account['account_password_changed'] > NULL_DATE) {
$d1 = datetime_convert('UTC','UTC','now - 48 hours'); $d1 = datetime_convert('UTC','UTC','now - 48 hours');
@ -37,32 +48,29 @@ class Removeaccount extends \Zotlabs\Web\Controller {
} }
} }
$global_remove = intval($_POST['global']); account_remove($account_id);
account_remove($account_id, 1 - $global_remove);
} }
function get() { function get() {
if(! local_channel()) if (! local_channel()) {
goaway(z_root()); goaway(z_root());
}
$hash = random_string(); $hash = random_string();
$_SESSION['remove_account_verify'] = $hash; $_SESSION['remove_account_verify'] = $hash;
$tpl = get_markup_template('removeaccount.tpl');
$o .= replace_macros($tpl, array( $o .= replace_macros(get_markup_template('removeaccount.tpl'), [
'$basedir' => z_root(), '$basedir' => z_root(),
'$hash' => $hash, '$hash' => $hash,
'$title' => t('Remove This Account'), '$title' => t('Remove This Account'),
'$desc' => array(t('WARNING: '), t('This account and all its channels will be completely removed from the network. '), t('This action is permanent and can not be undone!')), '$desc' => [ t('WARNING: '), t('This account and all its channels will be completely removed from this server. '), t('This action is permanent and can not be undone!') ],
'$passwd' => t('Please enter your password for verification:'), '$passwd' => t('Please enter your password for verification:'),
'$global' => array('global', t('Remove this account, all its channels and all its channel clones from the network'), false, t('By default only the instances of the channels located on this hub will be removed from the network')),
'$submit' => t('Remove Account') '$submit' => t('Remove Account')
)); ]);
return $o; return $o;
} }
} }

View file

@ -1,33 +1,43 @@
<?php <?php
namespace Zotlabs\Module; namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
class Removeme extends \Zotlabs\Web\Controller { class Removeme extends Controller {
function post() { function post() {
if(! local_channel()) if (! local_channel()) {
return; return;
}
if($_SESSION['delegate']) if ($_SESSION['delegate']) {
return; return;
}
if((! x($_POST,'qxz_password')) || (! strlen(trim($_POST['qxz_password'])))) if ((! x($_POST,'qxz_password')) || (! strlen(trim($_POST['qxz_password'])))) {
return; return;
}
if((! x($_POST,'verify')) || (! strlen(trim($_POST['verify'])))) if ((! x($_POST,'verify')) || (! strlen(trim($_POST['verify'])))) {
return; return;
}
if($_POST['verify'] !== $_SESSION['remove_account_verify']) if ($_POST['verify'] !== $_SESSION['remove_channel_verify']) {
return; return;
}
$account = App::get_account();
$account = \App::get_account(); if (! $account) {
return;
}
$x = account_verify_password($account['account_email'],$_POST['qxz_password']); $x = account_verify_password($account['account_email'],$_POST['qxz_password']);
if(! ($x && $x['account'])) if (! ($x && $x['account'])) {
return; return;
}
if ($account['account_password_changed'] > NULL_DATE) { if ($account['account_password_changed'] > NULL_DATE) {
$d1 = datetime_convert('UTC','UTC','now - 48 hours'); $d1 = datetime_convert('UTC','UTC','now - 48 hours');
@ -37,35 +47,30 @@ class Removeme extends \Zotlabs\Web\Controller {
} }
} }
$global_remove = intval($_POST['global']); channel_remove(local_channel(),true,true);
channel_remove(local_channel(),1 - $global_remove,true);
} }
function get() { function get() {
if(! local_channel()) if (! local_channel()) {
goaway(z_root()); goaway(z_root());
}
$hash = random_string(); $hash = random_string();
$_SESSION['remove_account_verify'] = $hash; $_SESSION['remove_channel_verify'] = $hash;
$tpl = get_markup_template('removeme.tpl'); $o .= replace_macros(get_markup_template('removeme.tpl'), [
$o .= replace_macros($tpl, array(
'$basedir' => z_root(), '$basedir' => z_root(),
'$hash' => $hash, '$hash' => $hash,
'$title' => t('Remove This Channel'), '$title' => t('Remove This Channel'),
'$desc' => [ t('WARNING: '), t('This channel will be completely removed from the network. '), t('This action is permanent and can not be undone!') ], '$desc' => [ t('WARNING: '), t('This channel will be completely removed from this server. '), t('This action is permanent and can not be undone!') ],
'$passwd' => t('Please enter your password for verification:'), '$passwd' => t('Please enter your password for verification:'),
'$global' => [ 'global', t('Remove this channel and all its clones from the network'), false, t('By default only the instance of the channel located on this hub will be removed from the network'), [ t('No'),t('Yes') ] ],
'$submit' => t('Remove Channel') '$submit' => t('Remove Channel')
)); ]);
return $o; return $o;
} }
} }

23
Zotlabs/Module/Safe.php Normal file
View file

@ -0,0 +1,23 @@
<?php
namespace Zotlabs\Module;
use Zotlabs\Web\Controller;
class Safe extends Controller {
function init() {
$x = get_safemode();
if ($x) {
$_SESSION['safemode'] = 0;
}
else {
$_SESSION['safemode'] = 1;
}
goaway(z_root());
}
}

View file

@ -60,6 +60,7 @@ class Search extends \Zotlabs\Web\Controller {
$o .= search($search,'search-box','/search',((local_channel()) ? true : false)); $o .= search($search,'search-box','/search',((local_channel()) ? true : false));
if (strpos($search,'#') === 0) { if (strpos($search,'#') === 0) {
$tag = true; $tag = true;
$search = substr($search,1); $search = substr($search,1);
@ -131,6 +132,7 @@ class Search extends \Zotlabs\Web\Controller {
'$conv' => '0', '$conv' => '0',
'$spam' => '0', '$spam' => '0',
'$fh' => '0', '$fh' => '0',
'$dm' => '0',
'$nouveau' => '0', '$nouveau' => '0',
'$wall' => '0', '$wall' => '0',
'$static' => $static, '$static' => $static,

View file

@ -2,16 +2,22 @@
namespace Zotlabs\Module\Settings; namespace Zotlabs\Module\Settings;
use App;
use Zotlabs\Lib\Libsync; use Zotlabs\Lib\Libsync;
use Zotlabs\Lib\AccessList; use Zotlabs\Lib\AccessList;
use Zotlabs\Access\Permissions;
use Zotlabs\Access\PermissionRoles;
use Zotlabs\Access\PermissionLimits;
use Zotlabs\Access\AccessControl;
use Zotlabs\Daemon\Master;
use Zotlabs\Lib\Permcat;
class Channel { class Channel {
function post() { function post() {
$channel = \App::get_channel(); $channel = App::get_channel();
check_form_security_token_redirectOnErr('/settings', 'settings'); check_form_security_token_redirectOnErr('/settings', 'settings');
@ -22,10 +28,6 @@ class Channel {
$role = ((x($_POST,'permissions_role')) ? notags(trim($_POST['permissions_role'])) : ''); $role = ((x($_POST,'permissions_role')) ? notags(trim($_POST['permissions_role'])) : '');
$oldrole = get_pconfig(local_channel(),'system','permissions_role'); $oldrole = get_pconfig(local_channel(),'system','permissions_role');
// This mapping can be removed after 3.4 release
if($oldrole === 'social_party') {
$oldrole = 'social_federation';
}
if(($role != $oldrole) || ($role === 'custom')) { if(($role != $oldrole) || ($role === 'custom')) {
@ -37,12 +39,12 @@ class Channel {
intval(local_channel()) intval(local_channel())
); );
$global_perms = \Zotlabs\Access\Permissions::Perms(); $global_perms = Permissions::Perms();
foreach($global_perms as $k => $v) { foreach($global_perms as $k => $v) {
\Zotlabs\Access\PermissionLimits::Set(local_channel(),$k,intval($_POST[$k])); PermissionLimits::Set(local_channel(),$k,intval($_POST[$k]));
} }
$acl = new \Zotlabs\Access\AccessControl($channel); $acl = new AccessControl($channel);
$acl->set_from_array($_POST); $acl->set_from_array($_POST);
$x = $acl->get(); $x = $acl->get();
@ -56,7 +58,7 @@ class Channel {
); );
} }
else { else {
$role_permissions = \Zotlabs\Access\PermissionRoles::role_perms($_POST['permissions_role']); $role_permissions = PermissionRoles::role_perms($_POST['permissions_role']);
if(! $role_permissions) { if(! $role_permissions) {
notice('Permissions category could not be found.'); notice('Permissions category could not be found.');
return; return;
@ -97,8 +99,8 @@ class Channel {
} }
if($role_permissions['perms_connect']) { if($role_permissions['perms_connect']) {
$x = \Zotlabs\Access\Permissions::FilledPerms($role_permissions['perms_connect']); $x = Permissions::FilledPerms($role_permissions['perms_connect']);
$str = \Zotlabs\Access\Permissions::serialise($x); $str = Permissions::serialise($x);
set_abconfig(local_channel(),$channel['channel_hash'],'system','my_perms',$str); set_abconfig(local_channel(),$channel['channel_hash'],'system','my_perms',$str);
$autoperms = intval($role_permissions['perms_auto']); $autoperms = intval($role_permissions['perms_auto']);
@ -106,7 +108,7 @@ class Channel {
if($role_permissions['limits']) { if($role_permissions['limits']) {
foreach($role_permissions['limits'] as $k => $v) { foreach($role_permissions['limits'] as $k => $v) {
\Zotlabs\Access\PermissionLimits::Set(local_channel(),$k,$v); PermissionLimits::Set(local_channel(),$k,$v);
} }
} }
if(array_key_exists('directory_publish',$role_permissions)) { if(array_key_exists('directory_publish',$role_permissions)) {
@ -118,6 +120,12 @@ class Channel {
set_pconfig(local_channel(),'system','permissions_role',$role); set_pconfig(local_channel(),'system','permissions_role',$role);
} }
// The post_comments permission is critical to privacy so we always allow you to set it, no matter what
// permission role is in place.
$post_comments = array_key_exists('post_comments',$_POST) ? intval($_POST['post_comments']) : PERMS_SPECIFIC;
PermissionLimits::Set(local_channel(),'post_comments',$post_comments);
$publish = (((x($_POST,'profile_in_directory')) && (intval($_POST['profile_in_directory']) == 1)) ? 1: 0); $publish = (((x($_POST,'profile_in_directory')) && (intval($_POST['profile_in_directory']) == 1)) ? 1: 0);
$username = ((x($_POST,'username')) ? notags(trim($_POST['username'])) : ''); $username = ((x($_POST,'username')) ? notags(trim($_POST['username'])) : '');
$timezone = ((x($_POST,'timezone_select')) ? notags(trim($_POST['timezone_select'])) : ''); $timezone = ((x($_POST,'timezone_select')) ? notags(trim($_POST['timezone_select'])) : '');
@ -143,17 +151,16 @@ class Channel {
$cntunkmail = ((x($_POST,'cntunkmail')) ? intval($_POST['cntunkmail']) : 0); $cntunkmail = ((x($_POST,'cntunkmail')) ? intval($_POST['cntunkmail']) : 0);
$suggestme = ((x($_POST,'suggestme')) ? intval($_POST['suggestme']) : 0); $suggestme = ((x($_POST,'suggestme')) ? intval($_POST['suggestme']) : 0);
// $anymention = ((x($_POST,'anymention')) ? intval($_POST['anymention']) : 0); // $anymention = ((x($_POST,'anymention')) ? intval($_POST['anymention']) : 0);
// $hyperdrive = ((x($_POST,'hyperdrive')) ? intval($_POST['hyperdrive']) : 0); $hyperdrive = ((x($_POST,'hyperdrive')) ? intval($_POST['hyperdrive']) : 0);
$activitypub = ((x($_POST,'activitypub')) ? intval($_POST['activitypub']) : 0);
$public_uploads = ((isset($_POST['public_uploads'])) ? intval($_POST['public_uploads']) : 0);
$post_newfriend = (($_POST['post_newfriend'] == 1) ? 1: 0); $post_newfriend = (($_POST['post_newfriend'] == 1) ? 1: 0);
$post_joingroup = (($_POST['post_joingroup'] == 1) ? 1: 0); $post_joingroup = (($_POST['post_joingroup'] == 1) ? 1: 0);
$post_profilechange = (($_POST['post_profilechange'] == 1) ? 1: 0); $post_profilechange = (($_POST['post_profilechange'] == 1) ? 1: 0);
$adult = (($_POST['adult'] == 1) ? 1 : 0); $adult = (($_POST['adult'] == 1) ? 1 : 0);
$defpermcat = ((x($_POST,'defpermcat')) ? notags(trim($_POST['defpermcat'])) : 'default'); $defpermcat = ((x($_POST,'defpermcat')) ? notags(trim($_POST['defpermcat'])) : 'default');
$cal_first_day = (((x($_POST,'first_day')) && (intval($_POST['first_day']) == 1)) ? 1: 0); $cal_first_day = (((x($_POST,'first_day')) && intval($_POST['first_day']) >= 0 && intval($_POST['first_day']) < 7) ? intval($_POST['first_day']) : 0);
$mailhost = ((array_key_exists('mailhost',$_POST)) ? notags(trim($_POST['mailhost'])) : ''); $mailhost = ((array_key_exists('mailhost',$_POST)) ? notags(trim($_POST['mailhost'])) : '');
$profile_assign = ((x($_POST,'profile_assign')) ? notags(trim($_POST['profile_assign'])) : ''); $profile_assign = ((x($_POST,'profile_assign')) ? notags(trim($_POST['profile_assign'])) : '');
@ -263,8 +270,8 @@ class Channel {
set_pconfig(local_channel(),'system','email_notify_host',$mailhost); set_pconfig(local_channel(),'system','email_notify_host',$mailhost);
set_pconfig(local_channel(),'system','profile_assign',$profile_assign); set_pconfig(local_channel(),'system','profile_assign',$profile_assign);
// set_pconfig(local_channel(),'system','anymention',$anymention); // set_pconfig(local_channel(),'system','anymention',$anymention);
// set_pconfig(local_channel(),'system','hyperdrive',$hyperdrive); set_pconfig(local_channel(),'system','hyperdrive',$hyperdrive);
set_pconfig(local_channel(),'system','force_public_uploads',$public_uploads); set_pconfig(local_channel(),'system','activitypub',$activitypub);
set_pconfig(local_channel(),'system','autoperms',$autoperms); set_pconfig(local_channel(),'system','autoperms',$autoperms);
$r = q("update channel set channel_name = '%s', channel_pageflags = %d, channel_timezone = '%s', channel_location = '%s', channel_notifyflags = %d, channel_max_anon_mail = %d, channel_max_friend_req = %d, channel_expire_days = %d $set_perms where channel_id = %d", $r = q("update channel set channel_name = '%s', channel_pageflags = %d, channel_timezone = '%s', channel_location = '%s', channel_notifyflags = %d, channel_max_anon_mail = %d, channel_max_friend_req = %d, channel_expire_days = %d $set_perms where channel_id = %d",
@ -286,6 +293,10 @@ class Channel {
intval($publish), intval($publish),
intval(local_channel()) intval(local_channel())
); );
$r = q("UPDATE xchan SET xchan_hidden = %d WHERE xchan_hash = '%s'",
intval(1 - $publish),
intval($channel['channel_hash'])
);
} }
if($name_change) { if($name_change) {
@ -300,12 +311,12 @@ class Channel {
); );
} }
\Zotlabs\Daemon\Master::Summon(array('Directory',local_channel())); Master::Summon( [ 'Directory', local_channel() ] );
Libsync::build_sync_packet(); Libsync::build_sync_packet();
if($email_changed && \App::$config['system']['register_policy'] == REGISTER_VERIFY) { if($email_changed && App::$config['system']['register_policy'] == REGISTER_VERIFY) {
// FIXME - set to un-verified, blocked and redirect to logout // FIXME - set to un-verified, blocked and redirect to logout
// Q: Why? Are we verifying people or email addresses? // Q: Why? Are we verifying people or email addresses?
@ -322,7 +333,7 @@ class Channel {
require_once('include/permissions.php'); require_once('include/permissions.php');
$yes_no = array(t('No'),t('Yes')); $yes_no = [ t('No'), t('Yes') ];
$p = q("SELECT * FROM profile WHERE is_default = 1 AND uid = %d LIMIT 1", $p = q("SELECT * FROM profile WHERE is_default = 1 AND uid = %d LIMIT 1",
@ -333,13 +344,13 @@ class Channel {
load_pconfig(local_channel(),'expire'); load_pconfig(local_channel(),'expire');
$channel = \App::get_channel(); $channel = App::get_channel();
$global_perms = \Zotlabs\Access\Permissions::Perms(); $global_perms = Permissions::Perms();
$permiss = array(); $permiss = [];
$perm_opts = array( $perm_opts = [
array( t('Nobody except yourself'), 0), array( t('Nobody except yourself'), 0),
array( t('Only those you specifically allow'), PERMS_SPECIFIC), array( t('Only those you specifically allow'), PERMS_SPECIFIC),
array( t('Approved connections'), PERMS_CONTACTS), array( t('Approved connections'), PERMS_CONTACTS),
@ -348,13 +359,13 @@ class Channel {
array( t('Anybody in this network'), PERMS_NETWORK), array( t('Anybody in this network'), PERMS_NETWORK),
array( t('Anybody authenticated'), PERMS_AUTHED), array( t('Anybody authenticated'), PERMS_AUTHED),
array( t('Anybody on the internet'), PERMS_PUBLIC) array( t('Anybody on the internet'), PERMS_PUBLIC)
); ];
$limits = \Zotlabs\Access\PermissionLimits::Get(local_channel()); $limits = PermissionLimits::Get(local_channel());
$anon_comments = get_config('system','anonymous_comments',true); $anon_comments = get_config('system','anonymous_comments',true);
foreach($global_perms as $k => $perm) { foreach($global_perms as $k => $perm) {
$options = array(); $options = [];
$can_be_public = ((strstr($k,'view') || ($k === 'post_comments' && $anon_comments)) ? true : false); $can_be_public = ((strstr($k,'view') || ($k === 'post_comments' && $anon_comments)) ? true : false);
foreach($perm_opts as $opt) { foreach($perm_opts as $opt) {
if($opt[1] == PERMS_PUBLIC && (! $can_be_public)) if($opt[1] == PERMS_PUBLIC && (! $can_be_public))
@ -364,8 +375,13 @@ class Channel {
if($k === 'view_stream') { if($k === 'view_stream') {
$options = [$perm_opts[7][1] => $perm_opts[7][0]]; $options = [$perm_opts[7][1] => $perm_opts[7][0]];
} }
if($k === 'post_comments') {
$comment_perms = [ $k, $perm, $limits[$k],'',$options ];
}
else {
$permiss[] = array($k,$perm,$limits[$k],'',$options); $permiss[] = array($k,$perm,$limits[$k],'',$options);
} }
}
// logger('permiss: ' . print_r($permiss,true)); // logger('permiss: ' . print_r($permiss,true));
@ -380,12 +396,8 @@ class Channel {
$adult_flag = intval($channel['channel_pageflags'] & PAGE_ADULT); $adult_flag = intval($channel['channel_pageflags'] & PAGE_ADULT);
$sys_expire = get_config('system','default_expire_days'); $sys_expire = get_config('system','default_expire_days');
// $unkmail = \App::$user['unkmail'];
// $cntunkmail = \App::$user['cntunkmail'];
$hide_presence = intval(get_pconfig(local_channel(), 'system','hide_online_status')); $hide_presence = intval(get_pconfig(local_channel(), 'system','hide_online_status'));
$expire_items = get_pconfig(local_channel(), 'expire','items'); $expire_items = get_pconfig(local_channel(), 'expire','items');
$expire_items = (($expire_items===false)? '1' : $expire_items); // default if not set: 1 $expire_items = (($expire_items===false)? '1' : $expire_items); // default if not set: 1
@ -395,7 +407,6 @@ class Channel {
$expire_starred = get_pconfig(local_channel(), 'expire','starred'); $expire_starred = get_pconfig(local_channel(), 'expire','starred');
$expire_starred = (($expire_starred===false)? '1' : $expire_starred); // default if not set: 1 $expire_starred = (($expire_starred===false)? '1' : $expire_starred); // default if not set: 1
$public_uploads = get_pconfig(local_channel(), 'expire','force_public_uploads',1);
$expire_photos = get_pconfig(local_channel(), 'expire','photos'); $expire_photos = get_pconfig(local_channel(), 'expire','photos');
$expire_photos = (($expire_photos===false)? '0' : $expire_photos); // default if not set: 0 $expire_photos = (($expire_photos===false)? '0' : $expire_photos); // default if not set: 0
@ -436,24 +447,27 @@ class Channel {
)); ));
$subdir = ((strlen(\App::get_path())) ? '<br />' . t('or') . ' ' . z_root() . '/channel/' . $nickname : ''); $subdir = ((strlen(App::get_path())) ? '<br />' . t('or') . ' ' . z_root() . '/channel/' . $nickname : '');
$webbie = $nickname . '@' . \App::get_hostname(); $webbie = $nickname . '@' . App::get_hostname();
$intl_nickname = unpunify($nickname) . '@' . unpunify(\App::get_hostname()); $intl_nickname = unpunify($nickname) . '@' . unpunify(App::get_hostname());
$tpl_addr = get_markup_template("settings_nick_set.tpl"); $prof_addr = replace_macros(get_markup_template('channel_settings_header.tpl'),array(
$prof_addr = replace_macros($tpl_addr,array(
'$desc' => t('Your channel address is'), '$desc' => t('Your channel address is'),
'$nickname' => (($intl_nickname === $webbie) ? $webbie : $intl_nickname . '&nbsp;(' . $webbie . ')'), '$nickname' => (($intl_nickname === $webbie) ? $webbie : $intl_nickname . '&nbsp;(' . $webbie . ')'),
'$compat' => t('Friends using compatible applications can use this address to connect with you.'),
'$subdir' => $subdir, '$subdir' => $subdir,
'$davdesc' => t('Your files/photos are accessible via WebDAV at'), '$davdesc' => t('Your files/photos are accessible as a network drive at'),
'$davpath' => z_root() . '/dav/' . $nickname, '$davpath' => z_root() . '/dav/' . $nickname,
'$basepath' => \App::get_hostname() '$windows' => t('(Windows)'),
'$other' => t('(other platforms)'),
'$or' => t('or'),
'$davspath' => 'davs://' . App::get_hostname() . '/dav/' . $nickname,
'$basepath' => App::get_hostname()
)); ));
$pcat = new \Zotlabs\Lib\Permcat(local_channel()); $pcat = new Permcat(local_channel());
$pcatlist = $pcat->listing(); $pcatlist = $pcat->listing();
$permcats = []; $permcats = [];
if($pcatlist) { if($pcatlist) {
@ -465,9 +479,7 @@ class Channel {
$default_permcat = get_pconfig(local_channel(),'system','default_permcat','default'); $default_permcat = get_pconfig(local_channel(),'system','default_permcat','default');
$stpl = get_markup_template('settings.tpl'); $acl = new AccessControl($channel);
$acl = new \Zotlabs\Access\AccessControl($channel);
$perm_defaults = $acl->get(); $perm_defaults = $acl->get();
$group_select = AccessList::select(local_channel(),$channel['channel_default_group']); $group_select = AccessList::select(local_channel(),$channel['channel_default_group']);
@ -495,19 +507,28 @@ class Channel {
if(in_array($permissions_role,['forum','repository'])) { if(in_array($permissions_role,['forum','repository'])) {
$autoperms = replace_macros(get_markup_template('field_checkbox.tpl'), [ $autoperms = replace_macros(get_markup_template('field_checkbox.tpl'), [
'$field' => [ 'autoperms',t('Automatic membership approval'), ((get_pconfig(local_channel(),'system','autoperms',0)) ? 1 : 0), t('If enabled, connection requests will be approved without your interaction'), $yes_no ]]); '$field' => [ 'autoperms',t('Automatic membership approval'), ((get_pconfig(local_channel(),'system','autoperms',0)) ? 1 : 0), t('If enabled, connection requests will be approved without your interaction'), $yes_no ]]);
// $anymention = replace_macros(get_markup_template('field_checkbox.tpl'), [
// '$field' => [ 'anymention', t('Allow forum delivery with @mentions'), ((get_pconfig(local_channel(),'system','anymention')) ? 1 : 0), t('Allows delivery from projects which do not support !mentions for forums.'), $yes_no ]]);
} }
else { else {
$autoperms = '<input type="hidden" name="autoperms" value="' . intval(get_pconfig(local_channel(),'system','autoperms')) . '" />'; $autoperms = '<input type="hidden" name="autoperms" value="' . intval(get_pconfig(local_channel(),'system','autoperms')) . '" />';
// $anymention = '<input type="hidden" name="anymention" value="' . intval(get_pconfig(local_channel(),'system','anymention')) . '" />';
} }
// $hyperdrive = [ 'hyperdrive', t('Enable hyperdrive'), ((get_pconfig(local_channel(),'system','hyperdrive',true)) ? 1 : 0), t('Dramatically increases the content available in your stream.'), $yes_no ]; $hyperdrive = [ 'hyperdrive', t('Enable hyperdrive'), ((get_pconfig(local_channel(),'system','hyperdrive',true)) ? 1 : 0), t('Import public third-party conversations in which your connections participate.'), $yes_no ];
if (get_config('system','activitypub')) {
$apconfig = true;
$activitypub = replace_macros(get_markup_template('field_checkbox.tpl'), [ '$field' => [ 'activitypub', t('Enable ActivityPub protocol'), ((get_pconfig(local_channel(),'system','activitypub',true)) ? 1 : 0), t(''), $yes_no ]]);
}
else {
$apconfig = false;
$activitypub = '<input type="hidden" name="activitypub" value="1" >' . EOL;
}
$apheader = t('ActivityPub');
$apdoc = t('ActivityPub is an emerging internet standard for social communications. ') . t('It provides access to a large and growing number of existing users and supported software applications, however it is still evolving. If this is enabled you will obtain much greater social reach, however you will almost certainly encounter compatibility issues, with varying levels of severity and personal impact. ') . EOL . t('Your system administrator has allowed this experimental service on this website. Please disable it if you prefer a bit more stability in your life.');
$permissions_set = (($permissions_role != 'custom') ? true : false); $permissions_set = (($permissions_role != 'custom') ? true : false);
$perm_roles = \Zotlabs\Access\PermissionRoles::roles(); $perm_roles = PermissionRoles::roles();
$vnotify = get_pconfig(local_channel(),'system','vnotify'); $vnotify = get_pconfig(local_channel(),'system','vnotify');
$always_show_in_notices = get_pconfig(local_channel(),'system','always_show_in_notices'); $always_show_in_notices = get_pconfig(local_channel(),'system','always_show_in_notices');
@ -521,42 +542,38 @@ class Channel {
$site_firehose = intval(get_config('system','site_firehose',0)) == 1; $site_firehose = intval(get_config('system','site_firehose',0)) == 1;
$o .= replace_macros($stpl,array( $o .= replace_macros(get_markup_template('settings.tpl'), [
'$ptitle' => t('Channel Settings'), '$ptitle' => t('Channel Settings'),
'$submit' => t('Submit'), '$submit' => t('Submit'),
'$baseurl' => z_root(), '$baseurl' => z_root(),
'$uid' => local_channel(), '$uid' => local_channel(),
'$form_security_token' => get_form_security_token("settings"), '$form_security_token' => get_form_security_token("settings"),
'$nickname_block' => $prof_addr, '$nickname_block' => $prof_addr,
'$h_basic' => t('Basic Settings'), '$h_basic' => t('Basic Settings'),
'$username' => array('username', t('Full Name:'), $username,''), '$username' => array('username', t('Full name'), $username,''),
'$email' => array('email', t('Email Address:'), $email, ''), '$email' => array('email', t('Email Address'), $email, ''),
'$timezone' => array('timezone_select' , t('Your Timezone:'), $timezone, '', get_timezones()), '$timezone' => array('timezone_select' , t('Your timezone'), $timezone, t('This is important for showing the correct time on shared events'), get_timezones()),
'$defloc' => array('defloc', t('Default Post Location:'), $defloc, t('Geographical location to display on your posts')), '$defloc' => array('defloc', t('Default post location'), $defloc, t('Optional geographical location to display on your posts')),
'$allowloc' => array('allow_location', t('Use Browser Location:'), ((get_pconfig(local_channel(),'system','use_browser_location')) ? 1 : ''), '', $yes_no), '$allowloc' => array('allow_location', t('Obtain post location from your web browser or device'), ((get_pconfig(local_channel(),'system','use_browser_location')) ? 1 : ''), '', $yes_no),
'$adult' => array('adult', t('Adult Content'), $adult_flag, t('This channel frequently or regularly publishes adult content. (Please tag any adult material and/or nudity with #NSFW)'), $yes_no), '$adult' => array('adult', t('Adult content'), $adult_flag, t('This channel frequently or regularly publishes adult content. (Please tag any adult material and/or nudity with #NSFW)'), $yes_no),
'$h_prv' => t('Security and Privacy Settings'), '$h_prv' => t('Security and Privacy'),
'$permissions_set' => $permissions_set, '$permissions_set' => $permissions_set,
'$perms_set_msg' => t('Your permissions are already configured. Click to view/adjust'), '$perms_set_msg' => t('Your permissions are already configured. Click to view/adjust'),
'$hide_presence' => array('hide_presence', t('Hide my online presence'),$hide_presence, t('Prevents displaying in your profile that you are online'), $yes_no), '$hide_presence' => array('hide_presence', t('Hide my online presence'),$hide_presence, t('Prevents displaying in your profile that you are online'), $yes_no),
'$lbl_pmacro' => t('Simple Privacy Settings:'),
'$pmacro3' => t('Very Public - <em>extremely permissive (should be used with caution)</em>'),
'$pmacro2' => t('Typical - <em>default public, privacy when desired (similar to social network permissions but with improved privacy)</em>'),
'$pmacro1' => t('Private - <em>default private, never open or public</em>'),
'$pmacro0' => t('Blocked - <em>default blocked to/from everybody</em>'),
'$permiss_arr' => $permiss, '$permiss_arr' => $permiss,
'$comment_perms' => $comment_perms,
'$blocktags' => array('blocktags',t('Allow others to tag your posts'), 1-$blocktags, t('Often used by the community to retro-actively flag inappropriate content'), $yes_no), '$blocktags' => array('blocktags',t('Allow others to tag your posts'), 1-$blocktags, t('Often used by the community to retro-actively flag inappropriate content'), $yes_no),
'$lbl_p2macro' => t('Channel Permission Limits'), '$lbl_p2macro' => t('Channel Permission Limits'),
'$expire' => array('expire',t('Expire other channel content after this many days'),$expire, t('0 or blank to use the website limit.') . ' ' . ((intval($sys_expire)) ? sprintf( t('This website expires after %d days.'),intval($sys_expire)) : t('This website does not expire imported content.')) . ' ' . t('The website limit takes precedence if lower than your limit.')), '$expire' => array('expire',t('Expire other channel content after this many days'),$expire, t('0 or blank to use the website limit.') . ' ' . ((intval($sys_expire)) ? sprintf( t('This website expires after %d days.'),intval($sys_expire)) : t('This website does not expire imported content.')) . ' ' . t('The website limit takes precedence if lower than your limit.')),
'$maxreq' => array('maxreq', t('Maximum Friend Requests/Day:'), intval($channel['channel_max_friend_req']) , t('May reduce spam activity')), '$maxreq' => array('maxreq', t('Maximum Friend Requests/Day:'), intval($channel['channel_max_friend_req']) , t('May reduce spam activity')),
'$public_uploads' => [ 'public_uploads', t('Disable access checking on post attachments'), $public_uploads, t('Private media access is only implemented in a very small number of federated networks.'), $yes_no ],
'$permissions' => t('Default Access List'), '$permissions' => t('Default Access List'),
'$permdesc' => t("(click to open/close)"), '$permdesc' => t("(click to open/close)"),
'$aclselect' => populate_acl($perm_defaults, false, \Zotlabs\Lib\PermissionDescription::fromDescription(t('Use my default audience setting for the type of object published'))), '$aclselect' => populate_acl($perm_defaults, false, \Zotlabs\Lib\PermissionDescription::fromDescription(t('Use my default audience setting for the type of object published'))),
@ -580,9 +597,12 @@ class Channel {
'$autoperms' => $autoperms, '$autoperms' => $autoperms,
// '$anymention' => $anymention, // '$anymention' => $anymention,
// '$hyperdrive' => $hyperdrive, '$hyperdrive' => $hyperdrive,
'$activitypub' => $activitypub,
'$h_not' => t('Notification Settings'), '$apconfig' => $apconfig,
'$apheader' => $apheader,
'$apdoc' => $apdoc,
'$h_not' => t('Notifications'),
'$activity_options' => t('By default post a status message when:'), '$activity_options' => t('By default post a status message when:'),
'$post_newfriend' => array('post_newfriend', t('accepting a friend request'), $post_newfriend, '', $yes_no), '$post_newfriend' => array('post_newfriend', t('accepting a friend request'), $post_newfriend, '', $yes_no),
'$post_joingroup' => array('post_joingroup', t('joining a forum/community'), $post_joingroup, '', $yes_no), '$post_joingroup' => array('post_joingroup', t('joining a forum/community'), $post_joingroup, '', $yes_no),
@ -618,7 +638,7 @@ class Channel {
'$vnotify14' => array('vnotify14', t('Unseen likes and dislikes'), ($vnotify & VNOTIFY_LIKE), VNOTIFY_LIKE, '', $yes_no), '$vnotify14' => array('vnotify14', t('Unseen likes and dislikes'), ($vnotify & VNOTIFY_LIKE), VNOTIFY_LIKE, '', $yes_no),
'$vnotify15' => array('vnotify15', t('Unseen forum posts'), ($vnotify & VNOTIFY_FORUMS), VNOTIFY_FORUMS, '', $yes_no), '$vnotify15' => array('vnotify15', t('Unseen forum posts'), ($vnotify & VNOTIFY_FORUMS), VNOTIFY_FORUMS, '', $yes_no),
'$vnotify16' => ((is_site_admin()) ? array('vnotify16', t('Reported content'), ($vnotify & VNOTIFY_REPORTS), VNOTIFY_REPORTS, '', $yes_no) : [] ), '$vnotify16' => ((is_site_admin()) ? array('vnotify16', t('Reported content'), ($vnotify & VNOTIFY_REPORTS), VNOTIFY_REPORTS, '', $yes_no) : [] ),
'$mailhost' => [ 'mailhost', t('Email notification hub (hostname)'), get_pconfig(local_channel(),'system','email_notify_host',\App::get_hostname()), sprintf( t('If your channel is mirrored to multiple hubs, set this to your preferred location. This will prevent duplicate email notifications. Example: %s'),\App::get_hostname()) ], '$mailhost' => [ 'mailhost', t('Email notification hub (hostname)'), get_pconfig(local_channel(),'system','email_notify_host',App::get_hostname()), sprintf( t('If your channel is mirrored to multiple locations, set this to your preferred location. This will prevent duplicate email notifications. Example: %s'),App::get_hostname()) ],
'$always_show_in_notices' => array('always_show_in_notices', t('Show new wall posts, private messages and connections under Notices'), $always_show_in_notices, 1, '', $yes_no), '$always_show_in_notices' => array('always_show_in_notices', t('Show new wall posts, private messages and connections under Notices'), $always_show_in_notices, 1, '', $yes_no),
'$evdays' => array('evdays', t('Notify me of events this many days in advance'), $evdays, t('Must be greater than 0')), '$evdays' => array('evdays', t('Notify me of events this many days in advance'), $evdays, t('Must be greater than 0')),
@ -626,25 +646,30 @@ class Channel {
'$sec_addon' => $plugin['security'], '$sec_addon' => $plugin['security'],
'$notify_addon' => $plugin['notify'], '$notify_addon' => $plugin['notify'],
'$misc_addon' => $plugin['misc'], '$misc_addon' => $plugin['misc'],
'$lbl_time' => t('Date and time'),
'$miscdoc' => t('This section is reserved for use by optional addons and apps to provide additional settings.'),
'$h_advn' => t('Advanced Account/Page Type Settings'), '$h_advn' => t('Advanced Account/Page Type Settings'),
'$h_descadvn' => t('Change the behaviour of this account for special situations'), '$h_descadvn' => t('Change the behaviour of this account for special situations'),
'$pagetype' => $pagetype, '$pagetype' => $pagetype,
'$lbl_misc' => t('Miscellaneous Settings'), '$lbl_misc' => t('Miscellaneous'),
'$photo_path' => array('photo_path', t('Default photo upload folder'), get_pconfig(local_channel(),'system','photo_path'), t('%Y - current year, %m - current month')), '$photo_path' => array('photo_path', t('Default photo upload folder name'), get_pconfig(local_channel(),'system','photo_path'), t('%Y - current year, %m - current month')),
'$attach_path' => array('attach_path', t('Default file upload folder'), get_pconfig(local_channel(),'system','attach_path'), t('%Y - current year, %m - current month')), '$attach_path' => array('attach_path', t('Default file upload folder name'), get_pconfig(local_channel(),'system','attach_path'), t('%Y - current year, %m - current month')),
'$menus' => $menu, '$menus' => $menu,
'$menu_desc' => t('Personal menu to display in your channel pages'), '$menu_desc' => t('Personal menu to display in your channel pages'),
'$removeme' => t('Remove Channel'), '$removeme' => t('Remove Channel'),
'$removechannel' => t('Remove this channel.'), '$removechannel' => t('Remove this channel.'),
'$firefoxshare' => t('Firefox Share $Projectname provider'), '$cal_first_day' => array('first_day', t('Calendar week begins on'), intval(get_pconfig(local_channel(),'system','cal_first_day')), t('This varies by country/culture'),
'$cal_first_day' => array('first_day', t('Start calendar week on Monday'), ((get_pconfig(local_channel(),'system','cal_first_day')) ? 1 : ''), '', $yes_no), [ 0 => t('Sunday'),
)); 1 => t('Monday'),
2 => t('Tuesday'),
3 => t('Wednesday'),
4 => t('Thursday'),
5 => t('Friday'),
6 => t('Saturday')
]),
]);
call_hooks('settings_form',$o); call_hooks('settings_form',$o);
//$o .= '</form>' . "\r\n";
return $o; return $o;
} }
} }

View file

@ -34,20 +34,22 @@ class Oauth2 {
check_form_security_token_redirectOnErr('/settings/oauth2', 'settings_oauth2'); check_form_security_token_redirectOnErr('/settings/oauth2', 'settings_oauth2');
$name = ((x($_POST,'name')) ? escape_tags(trim($_POST['name'])) : ''); $name = ((x($_POST,'name')) ? escape_tags(trim($_POST['name'])) : '');
$clid = ((x($_POST,'clid')) ? escape_tags(trim($_POST['clid'])) : '');
$secret = ((x($_POST,'secret')) ? escape_tags(trim($_POST['secret'])) : ''); $secret = ((x($_POST,'secret')) ? escape_tags(trim($_POST['secret'])) : '');
$redirect = ((x($_POST,'redirect')) ? escape_tags(trim($_POST['redirect'])) : ''); $redirect = ((x($_POST,'redirect')) ? escape_tags(trim($_POST['redirect'])) : '');
$grant = ((x($_POST,'grant')) ? escape_tags(trim($_POST['grant'])) : ''); $grant = ((x($_POST,'grant')) ? escape_tags(trim($_POST['grant'])) : '');
$scope = ((x($_POST,'scope')) ? escape_tags(trim($_POST['scope'])) : ''); $scope = ((x($_POST,'scope')) ? escape_tags(trim($_POST['scope'])) : '');
$ok = true; $ok = true;
if($name == '' || $secret == '') { if($clid == '' || $secret == '') {
$ok = false; $ok = false;
notice( t('Name and Secret are required') . EOL); notice( t('ID and Secret are required') . EOL);
} }
if($ok) { if($ok) {
if ($_POST['submit']==t("Update")){ if ($_POST['submit']==t("Update")){
$r = q("UPDATE oauth_clients SET $r = q("UPDATE oauth_clients SET
client_name = '%s',
client_id = '%s', client_id = '%s',
client_secret = '%s', client_secret = '%s',
redirect_uri = '%s', redirect_uri = '%s',
@ -56,17 +58,19 @@ class Oauth2 {
user_id = %d user_id = %d
WHERE client_id='%s' and user_id = %s", WHERE client_id='%s' and user_id = %s",
dbesc($name), dbesc($name),
dbesc($clid),
dbesc($secret), dbesc($secret),
dbesc($redirect), dbesc($redirect),
dbesc($grant), dbesc($grant),
dbesc($scope), dbesc($scope),
intval(local_channel()), intval(local_channel()),
dbesc($name), dbesc($clid),
intval(local_channel())); intval(local_channel()));
} else { } else {
$r = q("INSERT INTO oauth_clients (client_id, client_secret, redirect_uri, grant_types, scope, user_id) $r = q("INSERT INTO oauth_clients (client_name, client_id, client_secret, redirect_uri, grant_types, scope, user_id)
VALUES ('%s','%s','%s','%s','%s',%d)", VALUES ('%s','%s','%s','%s','%s','%s',%d)",
dbesc($name), dbesc($name),
dbesc($clid),
dbesc($secret), dbesc($secret),
dbesc($redirect), dbesc($redirect),
dbesc($grant), dbesc($grant),
@ -95,6 +99,7 @@ class Oauth2 {
'$submit' => t('Submit'), '$submit' => t('Submit'),
'$cancel' => t('Cancel'), '$cancel' => t('Cancel'),
'$name' => array('name', t('Name'), '', t('Name of application')), '$name' => array('name', t('Name'), '', t('Name of application')),
'$clid' => array('clid', t('Consumer ID'), random_string(16), t('Automatically generated - change if desired. Max length 20')),
'$secret' => array('secret', t('Consumer Secret'), random_string(16), t('Automatically generated - change if desired. Max length 20')), '$secret' => array('secret', t('Consumer Secret'), random_string(16), t('Automatically generated - change if desired. Max length 20')),
'$redirect' => array('redirect', t('Redirect'), '', t('Redirect URI - leave blank unless your application specifically requires this')), '$redirect' => array('redirect', t('Redirect'), '', t('Redirect URI - leave blank unless your application specifically requires this')),
'$grant' => array('grant', t('Grant Types'), '', t('leave blank unless your application specifically requires this')), '$grant' => array('grant', t('Grant Types'), '', t('leave blank unless your application specifically requires this')),
@ -122,7 +127,8 @@ class Oauth2 {
'$title' => t('Add application'), '$title' => t('Add application'),
'$submit' => t('Update'), '$submit' => t('Update'),
'$cancel' => t('Cancel'), '$cancel' => t('Cancel'),
'$name' => array('name', t('Name'), $app['client_id'], t('Name of application')), '$name' => array('name', t('Name'), $app['client_name'], t('Name of application')),
'$clid' => array('clid', t('Consumer ID'), $app['client_id'], t('Automatically generated - change if desired. Max length 20')),
'$secret' => array('secret', t('Consumer Secret'), $app['client_secret'], t('Automatically generated - change if desired. Max length 20')), '$secret' => array('secret', t('Consumer Secret'), $app['client_secret'], t('Automatically generated - change if desired. Max length 20')),
'$redirect' => array('redirect', t('Redirect'), $app['redirect_uri'], t('Redirect URI - leave blank unless your application specifically requires this')), '$redirect' => array('redirect', t('Redirect'), $app['redirect_uri'], t('Redirect URI - leave blank unless your application specifically requires this')),
'$grant' => array('grant', t('Grant Types'), $app['grant_types'], t('leave blank unless your application specifically requires this')), '$grant' => array('grant', t('Grant Types'), $app['grant_types'], t('leave blank unless your application specifically requires this')),

View file

@ -15,7 +15,7 @@ class Siteinfo extends Controller {
function get() { function get() {
if(defined('NOMADIC')) { if(! get_config('system','activitypub')) {
$federated = [ 'zot6' ]; $federated = [ 'zot6' ];
} }
else { else {

View file

@ -1,12 +1,15 @@
<?php <?php
namespace Zotlabs\Module; namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
require_once('include/security.php'); require_once('include/security.php');
require_once('include/bbcode.php'); require_once('include/bbcode.php');
class Subthread extends \Zotlabs\Web\Controller { class Subthread extends Controller {
function get() { function get() {
@ -15,15 +18,16 @@ class Subthread extends \Zotlabs\Web\Controller {
} }
$sys = get_sys_channel(); $sys = get_sys_channel();
$channel = \App::get_channel(); $channel = App::get_channel();
$item_id = ((argc() > 2) ? notags(trim(argv(2))) : 0); $item_id = ((argc() > 2) ? notags(trim(argv(2))) : 0);
if(argv(1) === 'sub') if (argv(1) === 'sub') {
$activity = ACTIVITY_FOLLOW; $activity = ACTIVITY_FOLLOW;
elseif(argv(1) === 'unsub') }
elseif (argv(1) === 'unsub') {
$activity = ACTIVITY_UNFOLLOW; $activity = ACTIVITY_UNFOLLOW;
}
$i = q("select * from item where id = %d and uid = %d", $i = q("select * from item where id = %d and uid = %d",
intval($item_id), intval($item_id),
@ -46,15 +50,9 @@ class Subthread extends \Zotlabs\Web\Controller {
return; return;
} }
$r = q("SELECT parent FROM item WHERE id = %d",
intval($item_id)
);
if($r) {
$r = q("select * from item where id = parent and id = %d limit 1", $r = q("select * from item where id = parent and id = %d limit 1",
dbesc($r[0]['parent']) dbesc($i[0]['parent'])
); );
}
if ((! $item_id) || (! $r)) { if ((! $item_id) || (! $r)) {
logger('subthread: no item ' . $item_id); logger('subthread: no item ' . $item_id);
@ -64,11 +62,12 @@ class Subthread extends \Zotlabs\Web\Controller {
$item = $r[0]; $item = $r[0];
$owner_uid = $item['uid']; $owner_uid = $item['uid'];
$observer = \App::get_observer(); $observer = App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : ''); $ob_hash = (($observer) ? $observer['xchan_hash'] : '');
if(! perm_is_allowed($owner_uid,$ob_hash,'post_comments')) if (! perm_is_allowed($owner_uid,$ob_hash,'post_comments')) {
return; return;
}
$sys = get_sys_channel(); $sys = get_sys_channel();
@ -89,21 +88,22 @@ class Subthread extends \Zotlabs\Web\Controller {
$r = q("select * from xchan where xchan_hash = '%s' limit 1", $r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($item['owner_xchan']) dbesc($item['owner_xchan'])
); );
if($r) if ($r) {
$thread_owner = $r[0]; $thread_owner = $r[0];
else }
else {
killme(); killme();
}
$r = q("select * from xchan where xchan_hash = '%s' limit 1", $r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($item['author_xchan']) dbesc($item['author_xchan'])
); );
if($r) if ($r) {
$item_author = $r[0]; $item_author = $r[0];
else }
else {
killme(); killme();
}
$uuid = new_uuid(); $uuid = new_uuid();
$mid = z_root() . '/item/' . $uuid; $mid = z_root() . '/item/' . $uuid;
@ -115,35 +115,20 @@ class Subthread extends \Zotlabs\Web\Controller {
$body = $item['body']; $body = $item['body'];
$obj = json_encode(array( $obj = Activity::fetch_item( [ 'id' => $item['mid'] ] );
'type' => $objtype, $objtype = $obj['type'];
'id' => $item['mid'],
'parent' => (($item['thr_parent']) ? $item['thr_parent'] : $item['parent_mid']),
'link' => $links,
'title' => $item['title'],
'content' => $item['body'],
'created' => $item['created'],
'edited' => $item['edited'],
'author' => array(
'name' => $item_author['xchan_name'],
'address' => $item_author['xchan_addr'],
'guid' => $item_author['xchan_guid'],
'guid_sig' => $item_author['xchan_guid_sig'],
'link' => array(
array('rel' => 'alternate', 'type' => 'text/html', 'href' => $item_author['xchan_url']),
array('rel' => 'photo', 'type' => $item_author['xchan_photo_mimetype'], 'href' => $item_author['xchan_photo_m'])),
),
));
if (! intval($item['item_thread_top'])) if (! intval($item['item_thread_top']))
$post_type = 'comment'; $post_type = 'comment';
if($activity === ACTIVITY_FOLLOW) if ($activity === ACTIVITY_FOLLOW) {
$bodyverb = t('%1$s is following %2$s\'s %3$s'); $bodyverb = t('%1$s is following %2$s\'s %3$s');
if($activity === ACTIVITY_UNFOLLOW) }
if ($activity === ACTIVITY_UNFOLLOW) {
$bodyverb = t('%1$s stopped following %2$s\'s %3$s'); $bodyverb = t('%1$s stopped following %2$s\'s %3$s');
}
$arr = array(); $arr = [];
$arr['uuid'] = $uuid; $arr['uuid'] = $uuid;
$arr['mid'] = $mid; $arr['mid'] = $mid;
@ -156,10 +141,13 @@ class Subthread extends \Zotlabs\Web\Controller {
$arr['author_xchan'] = $observer['xchan_hash']; $arr['author_xchan'] = $observer['xchan_hash'];
$arr['item_origin'] = 1; $arr['item_origin'] = 1;
$arr['item_notshown'] = 1; $arr['item_notshown'] = 1;
if(intval($item['item_wall']))
if (intval($item['item_wall'])) {
$arr['item_wall'] = 1; $arr['item_wall'] = 1;
else }
else {
$arr['item_wall'] = 0; $arr['item_wall'] = 0;
}
$ulink = '[zrl=' . $item_author['xchan_url'] . ']' . $item_author['xchan_name'] . '[/zrl]'; $ulink = '[zrl=' . $item_author['xchan_url'] . ']' . $item_author['xchan_name'] . '[/zrl]';
$alink = '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]'; $alink = '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]';
@ -169,7 +157,7 @@ class Subthread extends \Zotlabs\Web\Controller {
$arr['verb'] = $activity; $arr['verb'] = $activity;
$arr['obj_type'] = $objtype; $arr['obj_type'] = $objtype;
$arr['obj'] = $obj; $arr['obj'] = json_encode($obj);
$arr['allow_cid'] = $item['allow_cid']; $arr['allow_cid'] = $item['allow_cid'];
$arr['allow_gid'] = $item['allow_gid']; $arr['allow_gid'] = $item['allow_gid'];
@ -184,11 +172,5 @@ class Subthread extends \Zotlabs\Web\Controller {
call_hooks('post_local_end', $arr); call_hooks('post_local_end', $arr);
killme(); killme();
} }
} }

View file

@ -4,10 +4,11 @@ namespace Zotlabs\Module;
use Zotlabs\Lib\Libsync; use Zotlabs\Lib\Libsync;
use Zotlabs\Lib\Apps; use Zotlabs\Lib\Apps;
use Zotlabs\Web\Controller;
require_once('include/socgraph.php'); require_once('include/socgraph.php');
class Suggestions extends \Zotlabs\Web\Controller { class Suggestions extends Controller {
function init() { function init() {
if (! local_channel()) if (! local_channel())

View file

@ -3,6 +3,7 @@ namespace Zotlabs\Module;
use App; use App;
use Zotlabs\Web\Controller; use Zotlabs\Web\Controller;
use Zotlabs\Lib\Apps;
require_once('include/event.php'); require_once('include/event.php');
@ -96,4 +97,19 @@ class Tasks extends Controller {
json_return_and_die($x); json_return_and_die($x);
} }
} }
function get() {
$desc = t('This app provides a simple personal and task list.');
$text = '<div class="section-content-info-wrapper">' . $desc . '</div>';
if(! ( local_channel() && Apps::system_app_installed(local_channel(),'Tasks'))) {
return $text;
}
$obj = new \Zotlabs\Widget\Tasklist;
return $obj->widget([]);
}
} }

Some files were not shown because too many files have changed in this diff Show more