mirror of
https://codeberg.org/streams/streams.git
synced 2024-09-21 14:35:18 +00:00
Merge branch 'dev'
This commit is contained in:
commit
72d948f00a
59 changed files with 1751 additions and 1136 deletions
29
README.md
29
README.md
|
@ -3,3 +3,32 @@ ZAP
|
|||
|
||||
Zap is an open source decentralised social network with more privacy and less drama.
|
||||
|
||||
|
||||
=====
|
||||
|
||||
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.
|
||||
|
||||
=====
|
||||
|
||||
|
|
|
@ -87,19 +87,21 @@ class Notifier {
|
|||
static public $channel = null;
|
||||
static public $private = false;
|
||||
|
||||
static public function run($argc,$argv){
|
||||
static public function run($argc,$argv) {
|
||||
|
||||
if($argc < 3)
|
||||
if ($argc < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger('notifier: invoked: ' . print_r($argv,true), LOGGER_DEBUG);
|
||||
logger('notifier: invoked: ' . print_r($argv,true), LOGGER_DEBUG, LOG_INFO);
|
||||
|
||||
$cmd = $argv[1];
|
||||
|
||||
$item_id = $argv[2];
|
||||
|
||||
if(! $item_id)
|
||||
if (! $item_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::$deliveries = [];
|
||||
self::$recipients = [];
|
||||
|
@ -112,42 +114,15 @@ class Notifier {
|
|||
|
||||
$sys = get_sys_channel();
|
||||
|
||||
$mail = false;
|
||||
$top_level = false;
|
||||
|
||||
$url_recipients = array();
|
||||
$normal_mode = true;
|
||||
|
||||
|
||||
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') {
|
||||
if ($cmd === 'request') {
|
||||
|
||||
$xchan = $argv[3];
|
||||
if($argc < 5) {
|
||||
if ($argc < 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -160,13 +135,13 @@ class Notifier {
|
|||
self::$encoding = 'zot';
|
||||
$normal_mode = false;
|
||||
}
|
||||
elseif($cmd === 'keychange') {
|
||||
elseif ($cmd === 'keychange') {
|
||||
self::$channel = channelx_by_n($item_id);
|
||||
$r = q("select abook_xchan from abook where abook_channel = %d",
|
||||
intval($item_id)
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
self::$recipients[] = $rr['abook_xchan'];
|
||||
}
|
||||
}
|
||||
|
@ -176,7 +151,7 @@ class Notifier {
|
|||
self::$encoding = 'zot';
|
||||
$normal_mode = false;
|
||||
}
|
||||
elseif(in_array($cmd, [ 'permissions_update', 'permissions_reject', 'permissions_accept', 'permissions_create' ])) {
|
||||
elseif (in_array($cmd, [ 'permissions_update', 'permissions_reject', 'permissions_accept', 'permissions_create' ])) {
|
||||
|
||||
// Get the (single) recipient
|
||||
|
||||
|
@ -184,61 +159,61 @@ class Notifier {
|
|||
intval($item_id)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
$uid = $r[0]['abook_channel'];
|
||||
if ($r) {
|
||||
$recip = array_shift($r);
|
||||
$uid = $recip['abook_channel'];
|
||||
// Get the sender
|
||||
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':
|
||||
ActivityPub::permissions_create($perm_update);
|
||||
break;
|
||||
case 'permissions_accept':
|
||||
|
||||
ActivityPub::permissions_accept($perm_update);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(! $perm_update['success']) {
|
||||
if (! $perm_update['success']) {
|
||||
call_hooks($cmd,$perm_update);
|
||||
}
|
||||
|
||||
if($perm_update['success']) {
|
||||
if($perm_update['deliveries']) {
|
||||
if ($perm_update['success']) {
|
||||
if ($perm_update['deliveries']) {
|
||||
self::$deliveries[] = $perm_update['deliveries'];
|
||||
do_delivery(self::$deliveries);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
self::$recipients[] = $r[0]['abook_xchan'];
|
||||
self::$recipients[] = $recip['abook_xchan'];
|
||||
self::$private = false;
|
||||
self::$packet_type = 'refresh';
|
||||
self::$env_recips = [ $r[0]['xchan_hash'] ];
|
||||
self::$env_recips = [ $$recip['xchan_hash'] ];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif($cmd === 'refresh_all') {
|
||||
elseif ($cmd === 'refresh_all') {
|
||||
logger('notifier: refresh_all: ' . $item_id);
|
||||
|
||||
self::$channel = channelx_by_n($item_id);
|
||||
$r = q("select abook_xchan from abook where abook_channel = %d",
|
||||
intval($item_id)
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
self::$recipients[] = $rr['abook_xchan'];
|
||||
}
|
||||
}
|
||||
self::$private = false;
|
||||
self::$packet_type = 'refresh';
|
||||
}
|
||||
elseif($cmd === 'purge') {
|
||||
elseif ($cmd === 'purge') {
|
||||
$xchan = $argv[3];
|
||||
logger('notifier: purge: ' . $item_id . ' => ' . $xchan);
|
||||
if (! $xchan) {
|
||||
|
@ -250,7 +225,7 @@ class Notifier {
|
|||
self::$private = true;
|
||||
self::$packet_type = 'purge';
|
||||
}
|
||||
elseif($cmd === 'purge_all') {
|
||||
elseif ($cmd === 'purge_all') {
|
||||
logger('notifier: purge_all: ' . $item_id);
|
||||
self::$channel = channelx_by_n($item_id);
|
||||
|
||||
|
@ -278,57 +253,52 @@ class Notifier {
|
|||
intval($item_id)
|
||||
);
|
||||
|
||||
if(! $r)
|
||||
if (! $r) {
|
||||
return;
|
||||
}
|
||||
|
||||
xchan_query($r);
|
||||
|
||||
$r = fetch_post_tags($r);
|
||||
|
||||
$target_item = $r[0];
|
||||
$target_item = array_shift($r);
|
||||
$deleted_item = false;
|
||||
|
||||
if(intval($target_item['item_deleted'])) {
|
||||
if (intval($target_item['item_deleted'])) {
|
||||
logger('notifier: target item ITEM_DELETED', LOGGER_DEBUG);
|
||||
$deleted_item = true;
|
||||
}
|
||||
|
||||
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 ] )) {
|
||||
logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for non published items, but allow an exclusion for transmitting hidden file activities
|
||||
|
||||
if(intval($target_item['item_unpublished']) || intval($target_item['item_delayed']) ||
|
||||
if (intval($target_item['item_unpublished']) || intval($target_item['item_delayed']) ||
|
||||
intval($target_item['item_blocked']) ||
|
||||
( intval($target_item['item_hidden']) && ($target_item['obj_type'] !== ACTIVITY_OBJ_FILE))) {
|
||||
logger('notifier: target item not published, so not forwardable', LOGGER_DEBUG);
|
||||
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",
|
||||
intval($target_item['uid'])
|
||||
);
|
||||
if($s)
|
||||
self::$channel = $s[0];
|
||||
if ($s) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
$thread_is_public = false;
|
||||
|
||||
if($target_item['mid'] === $target_item['parent_mid']) {
|
||||
if ($target_item['mid'] === $target_item['parent_mid']) {
|
||||
$parent_item = $target_item;
|
||||
$top_level_post = true;
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
|
@ -337,26 +307,28 @@ class Notifier {
|
|||
intval($target_item['parent'])
|
||||
);
|
||||
|
||||
if(! $r)
|
||||
if (! $r) {
|
||||
return;
|
||||
}
|
||||
|
||||
xchan_query($r);
|
||||
$r = fetch_post_tags($r);
|
||||
|
||||
$parent_item = $r[0];
|
||||
$parent_item = array_shift($r);
|
||||
$top_level_post = false;
|
||||
$thread_is_public = 1 - intval($parent_item['item_private']) ;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
}
|
||||
|
||||
$m = get_iconfig($target_item,'activitypub','signed_data');
|
||||
if($m)
|
||||
if ($m) {
|
||||
self::$encoded_item = json_decode($m,true);
|
||||
}
|
||||
else {
|
||||
self::$encoded_item = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
|
@ -366,12 +338,7 @@ class Notifier {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
logger('target_item: ' . print_r($target_item,true));
|
||||
|
||||
// self::$encoded_item = encode_item($target_item);
|
||||
|
||||
|
||||
logger('encoded: ' . print_r(self::$encoded_item,true));
|
||||
|
||||
// Send comments to the owner to re-deliver to everybody in the conversation
|
||||
|
@ -385,8 +352,6 @@ class Notifier {
|
|||
|
||||
$relay_to_owner = (((! $top_level_post) && (intval($target_item['item_origin'])) && comment_local_origin($target_item) && $cmd !== 'hyper') ? true : false);
|
||||
|
||||
|
||||
|
||||
$uplink = false;
|
||||
|
||||
// $cmd === 'relay' indicates the owner is sending it to the original recipients
|
||||
|
@ -397,13 +362,13 @@ class Notifier {
|
|||
|
||||
// tag_deliver'd post which needs to be sent back to the original author
|
||||
|
||||
if(($cmd === 'uplink') && intval($parent_item['item_uplink']) && (! $top_level_post)) {
|
||||
if (($cmd === 'uplink') && intval($parent_item['item_uplink']) && (! $top_level_post)) {
|
||||
logger('notifier: uplink');
|
||||
$uplink = true;
|
||||
self::$packet_type = 'response';
|
||||
}
|
||||
|
||||
if(($relay_to_owner || $uplink) && ($cmd !== 'relay')) {
|
||||
if (($relay_to_owner || $uplink) && ($cmd !== 'relay')) {
|
||||
logger('followup relay (upstream delivery)', LOGGER_DEBUG);
|
||||
$sendto = ($uplink) ? $parent_item['source_xchan'] : $parent_item['owner_xchan'];
|
||||
self::$recipients = [ $sendto ];
|
||||
|
@ -419,7 +384,7 @@ class Notifier {
|
|||
|
||||
}
|
||||
else {
|
||||
if($cmd === 'relay') {
|
||||
if ($cmd === 'relay') {
|
||||
logger('owner relay (downstream delivery)');
|
||||
}
|
||||
else {
|
||||
|
@ -429,29 +394,28 @@ class Notifier {
|
|||
// if our parent is a tag_delivery recipient, uplink to the original author causing
|
||||
// a delivery fork.
|
||||
|
||||
if(($parent_item) && intval($parent_item['item_uplink']) && (! $top_level_post) && ($cmd !== 'uplink')) {
|
||||
if (($parent_item) && intval($parent_item['item_uplink']) && (! $top_level_post) && ($cmd !== 'uplink')) {
|
||||
// don't uplink a relayed post to the relay owner
|
||||
if($parent_item['source_xchan'] !== $parent_item['owner_xchan']) {
|
||||
if ($parent_item['source_xchan'] !== $parent_item['owner_xchan']) {
|
||||
logger('notifier: uplinking this item');
|
||||
Master::Summon(array('Notifier','uplink',$item_id));
|
||||
}
|
||||
}
|
||||
|
||||
if($thread_is_public && $cmd === 'hyper') {
|
||||
$rcps = [];
|
||||
if ($thread_is_public && $cmd === 'hyper') {
|
||||
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' ) ",
|
||||
intval($target_item['uid']),
|
||||
dbesc($target_item['author_xchan']),
|
||||
dbesc($target_item['owner_xchan']),
|
||||
dbesc($target_item['source_xchan'])
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rv) {
|
||||
$rcps[] = $rv['abook_xchan'];
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
self::$recipients[] = $rv['abook_xchan'];
|
||||
}
|
||||
}
|
||||
self::$private = false;
|
||||
self::$recipients = $rcps;
|
||||
}
|
||||
else {
|
||||
self::$private = false;
|
||||
|
@ -465,11 +429,9 @@ class Notifier {
|
|||
self::$recipients = array_diff(self::$recipients, [ $target_item['owner_xchan'] ]);
|
||||
}
|
||||
|
||||
|
||||
// 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);
|
||||
return;
|
||||
}
|
||||
|
@ -482,26 +444,26 @@ class Notifier {
|
|||
logger('encoded item: ' . print_r(self::$encoded_item,true), LOGGER_DATA, LOG_DEBUG);
|
||||
|
||||
stringify_array_elms(self::$recipients);
|
||||
if(! self::$recipients) {
|
||||
if (! self::$recipients) {
|
||||
logger('no recipients');
|
||||
return;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
$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
|
||||
where xchan_hash in (" . protect_sprintf(implode(',',self::$recipients)) . ")");
|
||||
|
||||
$recip_list = array();
|
||||
|
||||
if($details) {
|
||||
foreach($details as $d) {
|
||||
|
||||
if ($details) {
|
||||
foreach ($details as $d) {
|
||||
$recip_list[] = $d['xchan_addr'] . ' (' . $d['xchan_hash'] . ')';
|
||||
if(self::$private) {
|
||||
if (self::$private) {
|
||||
self::$env_recips[] = $d['xchan_hash'];
|
||||
}
|
||||
}
|
||||
|
@ -521,7 +483,6 @@ class Notifier {
|
|||
'relay_to_owner' => $relay_to_owner,
|
||||
'uplink' => $uplink,
|
||||
'cmd' => $cmd,
|
||||
'mail' => $mail,
|
||||
'single' => (($cmd === 'single_mail' || $cmd === 'single_activity') ? true : false),
|
||||
'request' => $request,
|
||||
'normal_mode' => $normal_mode,
|
||||
|
@ -529,12 +490,11 @@ class Notifier {
|
|||
'queued' => []
|
||||
];
|
||||
|
||||
|
||||
|
||||
call_hooks('notifier_process', $narr);
|
||||
if($narr['queued']) {
|
||||
foreach($narr['queued'] as $pq)
|
||||
if ($narr['queued']) {
|
||||
foreach ($narr['queued'] as $pq) {
|
||||
self::$deliveries[] = $pq;
|
||||
}
|
||||
}
|
||||
|
||||
// notifier_process can alter the recipient list
|
||||
|
@ -542,7 +502,7 @@ class Notifier {
|
|||
self::$recipients = $narr['recipients'];
|
||||
self::$env_recips = $narr['env_recips'];
|
||||
|
||||
if((self::$private) && (! self::$env_recips)) {
|
||||
if ((self::$private) && (! self::$env_recips)) {
|
||||
// shouldn't happen
|
||||
logger('private message with no envelope recipients.' . print_r($argv,true), LOGGER_NORMAL, LOG_NOTICE);
|
||||
return;
|
||||
|
@ -550,22 +510,19 @@ class Notifier {
|
|||
|
||||
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.
|
||||
|
||||
$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 ) "
|
||||
);
|
||||
|
||||
|
||||
if(! $r) {
|
||||
if (! $hubs) {
|
||||
logger('notifier: no hubs', LOGGER_NORMAL, LOG_NOTICE);
|
||||
return;
|
||||
}
|
||||
|
||||
$hubs = $r;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -579,12 +536,12 @@ class Notifier {
|
|||
$urls = []; // array of urls to check uniqueness of hubs from other networks
|
||||
$hub_env = []; // per-hub envelope so we don't broadcast the entire envelope to all
|
||||
|
||||
foreach($hubs as $hub) {
|
||||
foreach ($hubs as $hub) {
|
||||
|
||||
if(self::$env_recips) {
|
||||
foreach(self::$env_recips as $er) {
|
||||
if($hub['hubloc_hash'] === $er) {
|
||||
if(! array_key_exists($hub['hubloc_site_id'], $hub_env)) {
|
||||
if (self::$env_recips) {
|
||||
foreach (self::$env_recips as $er) {
|
||||
if ($hub['hubloc_hash'] === $er) {
|
||||
if (! array_key_exists($hub['hubloc_site_id'], $hub_env)) {
|
||||
$hub_env[$hub['hubloc_site_id']] = [];
|
||||
}
|
||||
$hub_env[$hub['hubloc_site_id']][] = $er;
|
||||
|
@ -593,15 +550,15 @@ class Notifier {
|
|||
}
|
||||
|
||||
|
||||
if($hub['hubloc_network'] === 'zot6') {
|
||||
if(! in_array($hub['hubloc_sitekey'],$keys)) {
|
||||
if ($hub['hubloc_network'] === 'zot6') {
|
||||
if (! in_array($hub['hubloc_sitekey'],$keys)) {
|
||||
$hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network'];
|
||||
$dhubs[] = $hub;
|
||||
$keys[] = $hub['hubloc_sitekey'];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(! in_array($hub['hubloc_url'],$urls)) {
|
||||
if (! in_array($hub['hubloc_url'],$urls)) {
|
||||
$hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network'];
|
||||
$dhubs[] = $hub;
|
||||
$urls[] = $hub['hubloc_url'];
|
||||
|
@ -611,11 +568,13 @@ class Notifier {
|
|||
|
||||
logger('notifier: will notify/deliver to these hubs: ' . print_r($hublist,true), LOGGER_DEBUG, LOG_DEBUG);
|
||||
|
||||
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);
|
||||
|
||||
if($hub['hubloc_network'] !== 'zot6') {
|
||||
// deliver to any non-zot networks
|
||||
|
||||
if ($hub['hubloc_network'] !== 'zot6') {
|
||||
$narr = [
|
||||
'channel' => self::$channel,
|
||||
'upstream' => $upstream,
|
||||
|
@ -630,7 +589,6 @@ class Notifier {
|
|||
'relay_to_owner' => $relay_to_owner,
|
||||
'uplink' => $uplink,
|
||||
'cmd' => $cmd,
|
||||
'mail' => $mail,
|
||||
'single' => (($cmd === 'single_mail' || $cmd === 'single_activity') ? true : false),
|
||||
'request' => $request,
|
||||
'normal_mode' => $normal_mode,
|
||||
|
@ -638,7 +596,6 @@ class Notifier {
|
|||
'queued' => []
|
||||
];
|
||||
|
||||
|
||||
ActivityPub::notifier_process($narr);
|
||||
|
||||
call_hooks('notifier_hub',$narr);
|
||||
|
@ -660,20 +617,21 @@ class Notifier {
|
|||
|
||||
// Note: Legacy Hubzilla and Osada code. In Zap this should never happen.
|
||||
|
||||
if($cmd === 'single_mail' || $cmd === 'single_activity') {
|
||||
if ($cmd === 'single_mail' || $cmd === 'single_activity') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// default: zot protocol
|
||||
|
||||
$hash = new_uuid();
|
||||
$hash = new_uuid();
|
||||
|
||||
$env = (($hub_env && $hub_env[$hub['hubloc_site_id']]) ? $hub_env[$hub['hubloc_site_id']] : '');
|
||||
if((self::$private) && (! $env)) {
|
||||
if ((self::$private) && (! $env)) {
|
||||
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(
|
||||
[
|
||||
|
@ -687,8 +645,9 @@ class Notifier {
|
|||
);
|
||||
|
||||
// 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'))) {
|
||||
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' ) ",
|
||||
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' ) ",
|
||||
dbesc($target_item['mid']),
|
||||
dbesc($hub['hubloc_host']),
|
||||
dbesc($hub['hubloc_host']),
|
||||
|
@ -703,17 +662,17 @@ class Notifier {
|
|||
self::$deliveries[] = $hash;
|
||||
}
|
||||
|
||||
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'");
|
||||
if($x) {
|
||||
if ($x) {
|
||||
Master::Summon( [ 'Deliver_hooks', $target_item['id'] ] );
|
||||
}
|
||||
}
|
||||
|
||||
if(self::$deliveries)
|
||||
if (self::$deliveries) {
|
||||
do_delivery(self::$deliveries);
|
||||
|
||||
logger('notifier: basic loop complete.', LOGGER_DEBUG);
|
||||
}
|
||||
|
||||
call_hooks('notifier_end',$target_item);
|
||||
|
||||
|
|
|
@ -99,6 +99,76 @@ class Onepoll {
|
|||
if(! $responded)
|
||||
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']) {
|
||||
$fetch_feed = true;
|
||||
$x = null;
|
||||
|
||||
// They haven't given us permission to see their stream
|
||||
|
||||
$can_view_stream = intval(get_abconfig($importer_uid,$contact['abook_xchan'],'their_perms','view_stream'));
|
||||
|
||||
if(! $can_view_stream)
|
||||
$fetch_feed = false;
|
||||
|
||||
// we haven't given them permission to send us their stream
|
||||
|
||||
$can_send_stream = intval(get_abconfig($importer_uid,$contact['abook_xchan'],'my_perms','send_stream'));
|
||||
|
||||
if(! $can_send_stream)
|
||||
$fetch_feed = false;
|
||||
|
||||
if($fetch_feed) {
|
||||
|
||||
if(strpos($contact['xchan_connurl'],z_root()) === 0) {
|
||||
// local channel - save a network fetch
|
||||
$c = channelx_by_hash($contact['xchan_hash']);
|
||||
if($c) {
|
||||
$x = [
|
||||
'success' => true,
|
||||
'body' => json_encode( [
|
||||
'success' => true,
|
||||
'messages' => zot_feed($c['channel_id'], $importer['xchan_hash'], [ 'mindate' => $last_update ])
|
||||
])
|
||||
];
|
||||
}
|
||||
}
|
||||
else {
|
||||
// remote fetch
|
||||
|
||||
$feedurl = str_replace('/poco/','/zotfeed/',$contact['xchan_connurl']);
|
||||
$feedurl .= '?f=&mindate=' . urlencode($last_update) . '&zid=' . $importer['channel_address'] . '@' . \App::get_hostname();
|
||||
$recurse = 0;
|
||||
$x = z_fetch_url($feedurl, false, $recurse, [ 'session' => true ]);
|
||||
}
|
||||
|
||||
logger('feed_update: ' . print_r($x,true), LOGGER_DATA);
|
||||
}
|
||||
|
||||
if(($x) && ($x['success'])) {
|
||||
$total = 0;
|
||||
logger('onepoll: feed update ' . $contact['xchan_name'] . ' ' . $feedurl);
|
||||
|
||||
$j = json_decode($x['body'],true);
|
||||
if($j['success'] && $j['messages']) {
|
||||
foreach($j['messages'] as $message) {
|
||||
// process delivery here once we have parsed the AS
|
||||
logger('onepoll: feed_update: process_delivery: ' . print_r($results,true), LOGGER_DATA);
|
||||
$total ++;
|
||||
}
|
||||
logger("onepoll: $total messages processed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end USE_OUTBOX
|
||||
|
||||
// update the poco details for this connection
|
||||
|
||||
if($contact['xchan_connurl']) {
|
||||
|
|
81
Zotlabs/Lib/ASCollection.php
Normal file
81
Zotlabs/Lib/ASCollection.php
Normal 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'];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -9,6 +9,10 @@ use Zotlabs\Access\PermissionLimits;
|
|||
use Zotlabs\Daemon\Master;
|
||||
|
||||
|
||||
require_once('include/html2bbcode.php');
|
||||
require_once('include/html2plain.php');
|
||||
require_once('include/event.php');
|
||||
|
||||
class Activity {
|
||||
|
||||
static $ACTOR_CACHE_DAYS = 3;
|
||||
|
@ -25,7 +29,12 @@ class Activity {
|
|||
return self::fetch_profile($x);
|
||||
}
|
||||
if (in_array($x['type'], [ ACTIVITY_OBJ_NOTE, ACTIVITY_OBJ_ARTICLE ] )) {
|
||||
return self::fetch_item($x);
|
||||
|
||||
// Use Mastodon-specific note and media hacks if nomadic. Else HTML.
|
||||
// Eventually this needs to be passed in much further up the stack
|
||||
// and base the decision on whether or not we are encoding for ActivityPub or Zot6
|
||||
|
||||
return self::fetch_item($x,((get_config('system','activitypub')) ? true : false));
|
||||
}
|
||||
if ($x['type'] === ACTIVITY_OBJ_THING) {
|
||||
return self::fetch_thing($x);
|
||||
|
@ -141,7 +150,7 @@ class Activity {
|
|||
|
||||
}
|
||||
|
||||
static function fetch_item($x) {
|
||||
static function fetch_item($x,$activitypub = false) {
|
||||
|
||||
if (array_key_exists('source',$x)) {
|
||||
// This item is already processed and encoded
|
||||
|
@ -154,7 +163,7 @@ class Activity {
|
|||
if ($r) {
|
||||
xchan_query($r,true);
|
||||
$r = fetch_post_tags($r,true);
|
||||
return self::encode_item($r[0],((defined('NOMADIC')) ? false : true));
|
||||
return self::encode_item($r[0],$activitypub);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -319,7 +328,6 @@ class Activity {
|
|||
}
|
||||
$ret['attributedTo'] = $i['author']['xchan_url'];
|
||||
|
||||
|
||||
if ($i['mid'] !== $i['parent_mid']) {
|
||||
$ret['inReplyTo'] = $i['thr_parent'];
|
||||
$cnv = get_iconfig($i['parent'],'ostatus','conversation');
|
||||
|
@ -931,7 +939,7 @@ class Activity {
|
|||
];
|
||||
$ret['url'] = $p['xchan_url'];
|
||||
|
||||
if ($activitypub) {
|
||||
if ($activitypub && $feature_complete) {
|
||||
|
||||
if ($c) {
|
||||
$ret['inbox'] = z_root() . '/inbox/' . $c['channel_address'];
|
||||
|
@ -1881,6 +1889,7 @@ class Activity {
|
|||
|
||||
$s['mid'] = $act->id;
|
||||
$s['parent_mid'] = $act->obj['id'];
|
||||
$s['replyto'] = $act->replyto;
|
||||
|
||||
// over-ride the object timestamp with the activity
|
||||
|
||||
|
@ -2345,7 +2354,7 @@ class Activity {
|
|||
intval($item['uid'])
|
||||
);
|
||||
if (! $p) {
|
||||
if (defined('NOMADIC')) {
|
||||
if (! get_config('system','activitypub')) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
|
@ -2811,8 +2820,6 @@ class Activity {
|
|||
|
||||
static function bb_content($content,$field) {
|
||||
|
||||
require_once('include/html2bbcode.php');
|
||||
require_once('include/event.php');
|
||||
$ret = false;
|
||||
|
||||
if (is_array($content[$field])) {
|
||||
|
@ -2876,6 +2883,11 @@ class Activity {
|
|||
|
||||
if ($event) {
|
||||
$event['summary'] = html2bbcode($content['summary']);
|
||||
if (! $event['summary']) {
|
||||
if ($content['name']) {
|
||||
$event['summary'] = html2plain(purify_html($content['name']),256);
|
||||
}
|
||||
}
|
||||
$event['description'] = html2bbcode($content['content']);
|
||||
if ($event['summary'] && $event['dtstart']) {
|
||||
$content['event'] = $event;
|
||||
|
@ -2888,9 +2900,6 @@ class Activity {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,10 +29,6 @@ class ActivityPub {
|
|||
return;
|
||||
}
|
||||
|
||||
if(strpos($arr['target_item']['postopts'],'nopub') !== false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$signed_msg = get_iconfig($arr['target_item'],'activitypub','rawmsg');
|
||||
|
||||
// If we have an activity already stored with an LD-signature
|
||||
|
|
|
@ -24,6 +24,7 @@ class ActivityStreams {
|
|||
public $actor = null;
|
||||
public $obj = null;
|
||||
public $tgt = null;
|
||||
public $replyto = null;
|
||||
public $origin = null;
|
||||
public $owner = null;
|
||||
public $signer = null;
|
||||
|
@ -83,13 +84,14 @@ class ActivityStreams {
|
|||
}
|
||||
|
||||
if($this->is_valid()) {
|
||||
$this->id = $this->get_property_obj('id');
|
||||
$this->type = $this->get_primary_type();
|
||||
$this->actor = $this->get_actor('actor','','');
|
||||
$this->obj = $this->get_compound_property('object');
|
||||
$this->tgt = $this->get_compound_property('target');
|
||||
$this->origin = $this->get_compound_property('origin');
|
||||
$this->recips = $this->collect_recips();
|
||||
$this->id = $this->get_property_obj('id');
|
||||
$this->type = $this->get_primary_type();
|
||||
$this->actor = $this->get_actor('actor','','');
|
||||
$this->obj = $this->get_compound_property('object');
|
||||
$this->tgt = $this->get_compound_property('target');
|
||||
$this->origin = $this->get_compound_property('origin');
|
||||
$this->recips = $this->collect_recips();
|
||||
$this->replyto = $this->get_compound_property('replyTo');
|
||||
|
||||
$this->ldsig = $this->get_compound_property('signature');
|
||||
if($this->ldsig) {
|
||||
|
|
|
@ -29,20 +29,20 @@ class Connect {
|
|||
$my_perms = false;
|
||||
$protocol = '';
|
||||
|
||||
if(substr($url,0,1) === '[') {
|
||||
if (substr($url,0,1) === '[') {
|
||||
$x = strpos($url,']');
|
||||
if($x) {
|
||||
if ($x) {
|
||||
$protocol = substr($url,1,$x-1);
|
||||
$url = substr($url,$x+1);
|
||||
}
|
||||
}
|
||||
|
||||
if(! allowed_url($url)) {
|
||||
if (! check_siteallowed($url)) {
|
||||
$result['message'] = t('Channel is blocked on this site.');
|
||||
return $result;
|
||||
}
|
||||
|
||||
if(! $url) {
|
||||
if (! $url) {
|
||||
$result['message'] = t('Channel location missing.');
|
||||
return $result;
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ class Connect {
|
|||
// 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') {
|
||||
if($r['xchan_network'] === 'activitypub' && ! get_config('system','activitypub')) {
|
||||
$r = null;
|
||||
}
|
||||
}
|
||||
|
@ -141,9 +141,15 @@ class Connect {
|
|||
return $result;
|
||||
}
|
||||
|
||||
if (! check_channelallowed($xchan_hash)) {
|
||||
$result['message'] = t('Channel is blocked on this site.');
|
||||
logger('follow: ' . $result['message']);
|
||||
return $result;
|
||||
|
||||
}
|
||||
// Now start processing the new connection
|
||||
|
||||
if($r['xchan_network'] === 'activitypub') {
|
||||
if($r['xchan_network'] === 'activitypub' && ! get_config('system','activitypub')) {
|
||||
// ActivityPub is not nomadic
|
||||
$result['message'] = t('Protocol not supported');
|
||||
return $result;
|
||||
|
|
|
@ -1537,7 +1537,8 @@ class Libzot {
|
|||
* @brief
|
||||
*
|
||||
* @param array $sender
|
||||
* @param array $arr
|
||||
* @param ActivityStreams object $act
|
||||
* @param array $msg_arr
|
||||
* @param array $deliveries
|
||||
* @param boolean $relay
|
||||
* @param boolean $public (optional) default false
|
||||
|
@ -1891,8 +1892,9 @@ class Libzot {
|
|||
|
||||
// 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.
|
||||
if (! intval($r[0]['item_origin']))
|
||||
if (! intval($r[0]['item_origin'])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -2338,90 +2340,6 @@ class Libzot {
|
|||
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.
|
||||
|
|
|
@ -95,7 +95,7 @@ class Share {
|
|||
$is_photo = (($this->item['obj_type'] === ACTIVITY_OBJ_PHOTO) ? true : false);
|
||||
if($is_photo) {
|
||||
$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) {
|
||||
|
@ -107,7 +107,7 @@ class Share {
|
|||
"' portable_id='" . $this->item['author']['xchan_hash'] .
|
||||
"' avatar='" . $this->item['author']['xchan_photo_s'] .
|
||||
"' link='" . $this->item['plink'] .
|
||||
"' auth='" . (($this->item['author']['network'] === 'zot') ? 'true' : 'false') .
|
||||
"' auth='" . (($this->item['author']['network'] === 'zot6') ? 'true' : 'false') .
|
||||
"' posted='" . $this->item['created'] .
|
||||
"' message_id='" . $this->item['mid'] .
|
||||
"']";
|
||||
|
|
|
@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -38,7 +38,7 @@ class ThreadItem {
|
|||
|
||||
$this->data = $data;
|
||||
$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',((get_config('system','activitypub')) ? true : false));
|
||||
$this->threaded = get_config('system','thread_allow',true);
|
||||
|
||||
$observer = App::get_observer();
|
||||
|
@ -482,7 +482,8 @@ class ThreadItem {
|
|||
'preview_lbl' => t('This is an unsaved preview'),
|
||||
'wait' => t('Please wait'),
|
||||
'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);
|
||||
|
@ -490,22 +491,32 @@ class ThreadItem {
|
|||
|
||||
$result = $arr['output'];
|
||||
|
||||
$censored = false;
|
||||
|
||||
if(strpos($body['html'],"<button id=\"nsfw-wrap-") !== false && $collapse_all === false) {
|
||||
$censored = true;
|
||||
}
|
||||
$censored = ((strpos($body['html'],"<button id=\"nsfw-wrap-") !== false && $collapse_all === false) ? true : false);
|
||||
|
||||
$result['children'] = [];
|
||||
|
||||
// place to store all the author addresses (links if not available) in the thread so we can auto-mention them in JS.
|
||||
$result['authors'] = [];
|
||||
$add_top_author = true;
|
||||
if($observer && ($profile_addr === $observer['xchan_hash'] || $profile_addr === $observer['xchan_addr'])) {
|
||||
$add_top_author = false;
|
||||
}
|
||||
if($add_top_author && (! defined('NOMADIC'))) {
|
||||
$result['authors'][] = $profile_addr;
|
||||
if (get_config('system','activitypub')) {
|
||||
// place to store all the author addresses (links if not available) in the thread so we can auto-mention them in JS.
|
||||
$result['authors'] = [];
|
||||
if ($observer && ($profile_addr === $observer['xchan_hash'] || $profile_addr === $observer['xchan_addr'])) {
|
||||
// ignore it
|
||||
}
|
||||
else {
|
||||
$result['authors'][] = $profile_addr;
|
||||
}
|
||||
if ($item['term']) {
|
||||
foreach ($item['term'] as $t) {
|
||||
if ($t['ttype'] == TERM_MENTION) {
|
||||
if (strpos($t['term'],'@') !== false) {
|
||||
$result['authors'][] = $t['term'];
|
||||
}
|
||||
else {
|
||||
$url = ((($position = strpos($t['url'],'url=')) !== false) ? urldecode(substr($t['url'],$position + 4)) : $t['url']);
|
||||
$result['authors'][] = $url;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$nb_children = count($children);
|
||||
|
@ -523,15 +534,6 @@ class ThreadItem {
|
|||
if(strpos($xz['body'],"<button id=\"nsfw-wrap-") !== false && $collapse_all === false) {
|
||||
$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;
|
||||
}
|
||||
// Collapse
|
||||
|
@ -548,14 +550,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['toplevel'] = ($this->is_toplevel() ? 'toplevel_item' : '');
|
||||
|
||||
|
@ -880,7 +874,7 @@ class ThreadItem {
|
|||
'$myphoto' => $observer['xchan_photo_s'],
|
||||
'$comment' => t('Comment'),
|
||||
'$submit' => t('Submit'),
|
||||
'$edat' => ((defined('NOMADIC')) ? '' : t('Add Conversation Mentions')),
|
||||
'$edat' => ((get_config('system','activitypub')) ? t('Add Conversation Mentions') : EMPTY_STR),
|
||||
'$edbold' => t('Bold'),
|
||||
'$editalic' => t('Italic'),
|
||||
'$eduline' => t('Underline'),
|
||||
|
|
|
@ -96,7 +96,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
|||
. " then POSITION('" . protect_sprintf(dbesc($search))
|
||||
. "' 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) . "%'" ) . " ) ";
|
||||
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -63,7 +63,7 @@ class Activity extends Controller {
|
|||
killme();
|
||||
|
||||
}
|
||||
|
||||
goaway(z_root() . '/item/' . argv(1));
|
||||
}
|
||||
|
||||
}
|
|
@ -53,7 +53,6 @@ class Site {
|
|||
}
|
||||
$mirror_frontpage = ((x($_POST,'mirror_frontpage')) ? intval(trim($_POST['mirror_frontpage'])) : 0);
|
||||
$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);
|
||||
$disable_discover_tab = ((x($_POST,'disable_discover_tab')) ? False : True);
|
||||
$site_firehose = ((x($_POST,'site_firehose')) ? True : False);
|
||||
|
@ -144,7 +143,6 @@ class Site {
|
|||
set_config('system','access_policy', $access_policy);
|
||||
set_config('system','account_abandon_days', $abandon_days);
|
||||
set_config('system','register_text', $register_text);
|
||||
set_config('system','allowed_sites', $allowed_sites);
|
||||
set_config('system','publish_all', $force_publish);
|
||||
set_config('system','disable_discover_tab', $disable_discover_tab);
|
||||
set_config('system','site_firehose', $site_firehose);
|
||||
|
@ -317,7 +315,6 @@ 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.") ],
|
||||
'$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.') ],
|
||||
'$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).") ],
|
||||
'$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.') ],
|
||||
|
|
|
@ -24,6 +24,7 @@ class Apschema extends \Zotlabs\Web\Controller {
|
|||
'emojiReaction' => 'zot:emojiReaction',
|
||||
'expires' => 'zot:expires',
|
||||
'directMessage' => 'zot:directMessage',
|
||||
'replyTo' => 'zot:replyTo'
|
||||
]
|
||||
];
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ class Channel extends Controller {
|
|||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]], Activity::encode_person($channel,true,((defined('NOMADIC')) ? false : true)));
|
||||
]], Activity::encode_person($channel,true,true));
|
||||
|
||||
$headers = [];
|
||||
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ;
|
||||
|
|
|
@ -1,20 +1,24 @@
|
|||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
require_once('include/socgraph.php');
|
||||
|
||||
|
||||
class Connections extends \Zotlabs\Web\Controller {
|
||||
class Connections extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
if(! local_channel())
|
||||
if (! local_channel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = \App::get_channel();
|
||||
if($channel)
|
||||
$channel = App::get_channel();
|
||||
if ($channel) {
|
||||
head_set_icon($channel['xchan_photo_s']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -24,7 +28,7 @@ class Connections extends \Zotlabs\Web\Controller {
|
|||
$o = '';
|
||||
|
||||
|
||||
if(! local_channel()) {
|
||||
if (! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return login();
|
||||
}
|
||||
|
@ -41,14 +45,15 @@ class Connections extends \Zotlabs\Web\Controller {
|
|||
$unconnected = false;
|
||||
$all = false;
|
||||
|
||||
if(! $_REQUEST['aj'])
|
||||
$_SESSION['return_url'] = \App::$query_string;
|
||||
if (! $_REQUEST['aj']) {
|
||||
$_SESSION['return_url'] = App::$query_string;
|
||||
}
|
||||
|
||||
$search_flags = "";
|
||||
$head = '';
|
||||
|
||||
if(argc() == 2) {
|
||||
switch(argv(1)) {
|
||||
if (argc() == 2) {
|
||||
switch (argv(1)) {
|
||||
case 'active':
|
||||
$search_flags = " and abook_blocked = 0 and abook_ignored = 0 and abook_hidden = 0 and abook_archived = 0 AND abook_not_here = 0 ";
|
||||
$head = t('Active');
|
||||
|
@ -80,21 +85,25 @@ class Connections extends \Zotlabs\Web\Controller {
|
|||
$pending = true;
|
||||
break;
|
||||
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 ",
|
||||
intval(local_channel())
|
||||
);
|
||||
if($r && $r[0]['total']) {
|
||||
if ($r && $r[0]['total']) {
|
||||
$search_flags = " and abook_pending = 1 ";
|
||||
if(intval(argv(1))) {
|
||||
$search_flags .= " and abook_id = " . intval(argv(1)) . " ";
|
||||
}
|
||||
$head = t('New');
|
||||
$pending = true;
|
||||
\App::$argv[1] = 'pending';
|
||||
App::$argv[1] = 'pending';
|
||||
}
|
||||
else {
|
||||
$head = t('All');
|
||||
$search_flags = '';
|
||||
$all = true;
|
||||
\App::$argc = 1;
|
||||
unset(\App::$argv[1]);
|
||||
App::$argc = 1;
|
||||
unset(App::$argv[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -109,9 +118,9 @@ class Connections extends \Zotlabs\Web\Controller {
|
|||
}
|
||||
|
||||
$sql_extra = $search_flags;
|
||||
if(argv(1) === 'pending')
|
||||
if (argv(1) === 'pending') {
|
||||
$sql_extra .= " and abook_ignored = 0 ";
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
$sql_extra = " and abook_blocked = 0 ";
|
||||
|
@ -179,7 +188,7 @@ class Connections extends \Zotlabs\Web\Controller {
|
|||
$search_txt = dbesc(protect_sprintf(preg_quote($search)));
|
||||
$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']) {
|
||||
$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())
|
||||
);
|
||||
if($r) {
|
||||
\App::set_pager_total($r[0]['total']);
|
||||
App::set_pager_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
|
||||
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(\App::$pager['itemspage']),
|
||||
intval(\App::$pager['start'])
|
||||
intval(App::$pager['itemspage']),
|
||||
intval(App::$pager['start'])
|
||||
);
|
||||
|
||||
$contacts = array();
|
||||
|
@ -247,7 +256,7 @@ class Connections extends \Zotlabs\Web\Controller {
|
|||
'delete_hover' => t('Delete connection'),
|
||||
'id' => $rr['abook_id'],
|
||||
'thumb' => $rr['xchan_photo_m'],
|
||||
'name' => $rr['xchan_name'],
|
||||
'name' => $rr['xchan_name'] . (($rr['abook_alias']) ? ' <' . $rr['abook_alias'] . '>' : ''),
|
||||
'classes' => ((intval($rr['abook_archived']) || intval($rr['abook_not_here'])) ? 'archived' : ''),
|
||||
'link' => z_root() . '/connedit/' . $rr['abook_id'],
|
||||
'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 . "'" : ""),
|
||||
'$submit' => t('Find'),
|
||||
'$edit' => t('Edit'),
|
||||
'$cmd' => \App::$cmd,
|
||||
'$cmd' => App::$cmd,
|
||||
'$contacts' => $contacts,
|
||||
'$paginate' => paginate($a),
|
||||
|
||||
|
|
|
@ -74,15 +74,6 @@ class Connedit extends Controller {
|
|||
|
||||
$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",
|
||||
intval($contact_id),
|
||||
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_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']);
|
||||
|
@ -184,13 +176,14 @@ class Connedit extends Controller {
|
|||
$abook_pending = (($new_friend) ? 0 : $orig_record[0]['abook_pending']);
|
||||
|
||||
$r = q("UPDATE abook SET abook_profile = '%s', abook_closeness = %d, abook_pending = %d,
|
||||
abook_incl = '%s', abook_excl = '%s'
|
||||
abook_incl = '%s', abook_excl = '%s', abook_alias = '%s'
|
||||
where abook_id = %d AND abook_channel = %d",
|
||||
dbesc($profile_id),
|
||||
intval($closeness),
|
||||
intval($abook_pending),
|
||||
dbesc($abook_incl),
|
||||
dbesc($abook_excl),
|
||||
dbesc($abook_alias),
|
||||
intval($contact_id),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
@ -248,7 +241,6 @@ class Connedit extends Controller {
|
|||
|
||||
}
|
||||
|
||||
|
||||
// pull in a bit of content if there is any to pull in
|
||||
Master::Summon( [ 'Onepoll', $contact_id ]);
|
||||
|
||||
|
@ -287,33 +279,33 @@ class Connedit extends Controller {
|
|||
|
||||
function connedit_clone(&$a) {
|
||||
|
||||
if(! App::$poi)
|
||||
return;
|
||||
if (! App::$poi) {
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
$channel = App::get_channel();
|
||||
$r = q("SELECT abook.*, xchan.*
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
|
||||
intval(local_channel()),
|
||||
intval(App::$poi['abook_id'])
|
||||
);
|
||||
if ($r) {
|
||||
App::$poi = array_shift($r);
|
||||
}
|
||||
|
||||
$r = q("SELECT abook.*, xchan.*
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
|
||||
intval(local_channel()),
|
||||
intval(App::$poi['abook_id'])
|
||||
);
|
||||
if($r) {
|
||||
App::$poi = array_shift($r);
|
||||
}
|
||||
$clone = App::$poi;
|
||||
|
||||
$clone = App::$poi;
|
||||
unset($clone['abook_id']);
|
||||
unset($clone['abook_account']);
|
||||
unset($clone['abook_channel']);
|
||||
|
||||
unset($clone['abook_id']);
|
||||
unset($clone['abook_account']);
|
||||
unset($clone['abook_channel']);
|
||||
|
||||
$abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
|
||||
if($abconfig)
|
||||
$clone['abconfig'] = $abconfig;
|
||||
|
||||
Libsync::build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)));
|
||||
$abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
|
||||
if ($abconfig) {
|
||||
$clone['abconfig'] = $abconfig;
|
||||
}
|
||||
Libsync::build_sync_packet($channel['channel_id'], [ 'abook' => [ $clone ] ] );
|
||||
}
|
||||
|
||||
/* @brief Generate content of connection edit page
|
||||
|
@ -793,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.');
|
||||
|
||||
$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']) ? ' <' . $contact['abook_alias'] . '>' : '')),
|
||||
'$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_new' => t('Add permission role'),
|
||||
|
@ -820,6 +812,7 @@ class Connedit extends Controller {
|
|||
'$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')),
|
||||
'$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_info' => t('This information is public!'),
|
||||
'$rating' => $rating,
|
||||
|
|
|
@ -431,8 +431,7 @@ logger('gis: ' . print_r($gis,true));
|
|||
'$modalerrorlink' => t('Error getting photo link'),
|
||||
'$modalerroralbum' => t('Error getting album'),
|
||||
'$form_security_token' => get_form_security_token("cover_photo"),
|
||||
/// @FIXME - yuk
|
||||
'$select' => t('Select existing photo'),
|
||||
'$select' => t('Select previously uploaded photo'),
|
||||
|
||||
));
|
||||
|
||||
|
|
73
Zotlabs/Module/Followers.php
Normal file
73
Zotlabs/Module/Followers.php
Normal 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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
70
Zotlabs/Module/Following.php
Normal file
70
Zotlabs/Module/Following.php
Normal 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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -90,7 +90,7 @@ class Id extends Controller {
|
|||
xchan_query($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)
|
||||
http_status_exit(404, 'Not found');
|
||||
|
|
257
Zotlabs/Module/Inbox.php
Normal file
257
Zotlabs/Module/Inbox.php
Normal file
|
@ -0,0 +1,257 @@
|
|||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
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);
|
||||
|
||||
$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);
|
||||
|
||||
//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) {
|
||||
|
||||
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)) {
|
||||
// replies must go to the replyTo endpoint if the top level post originated here.
|
||||
$item = Activity::decode_note($AS);
|
||||
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() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ class Item extends Controller {
|
|||
if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream'))
|
||||
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)
|
||||
http_status_exit(404, 'Not found');
|
||||
|
@ -267,7 +267,7 @@ class Item extends Controller {
|
|||
if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream'))
|
||||
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) {
|
||||
ThreadListener::store(z_root() . '/item/' . $item_id,$portable_id);
|
||||
}
|
||||
|
@ -299,8 +299,9 @@ class Item extends Controller {
|
|||
// the text/html page of the item.
|
||||
|
||||
if (argc() > 1 && argv(1) !== 'drop') {
|
||||
$x = q("select uid, item_wall, llink, mid from item where mid = '%s' ",
|
||||
dbesc(z_root() . '/item/' . argv(1))
|
||||
$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() . '/activity/' . argv(1))
|
||||
);
|
||||
if ($x) {
|
||||
foreach ($x as $xv) {
|
||||
|
@ -1224,7 +1225,7 @@ class Item extends Controller {
|
|||
if(! array_key_exists('obj',$datarray)) {
|
||||
$copy = $datarray;
|
||||
$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
|
||||
|
|
|
@ -33,7 +33,7 @@ class Photo extends \Zotlabs\Web\Controller {
|
|||
$channel = channelx_by_n($r[0]['uid']);
|
||||
|
||||
$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' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
|
|
|
@ -394,7 +394,7 @@ class Ping extends Controller {
|
|||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$local_result[] = [
|
||||
'notify_link' => z_root() . '/connections/ifpending',
|
||||
'notify_link' => z_root() . '/connections/' . $rr['abook_id'],
|
||||
'name' => $rr['xchan_name'],
|
||||
'addr' => $rr['xchan_addr'],
|
||||
'url' => $rr['xchan_url'],
|
||||
|
|
|
@ -75,7 +75,7 @@ class Profile extends \Zotlabs\Web\Controller {
|
|||
$chan = channelx_by_nick(argv(1));
|
||||
if(! $chan)
|
||||
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) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
/*
|
||||
* @file Profile_photo.php
|
||||
* @brief Module-file with functions for uploading and scaling of profile-photos
|
||||
*
|
||||
*/
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
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/photos.php');
|
||||
|
||||
|
||||
|
||||
class Profile_photo extends Controller {
|
||||
|
||||
|
||||
|
@ -48,49 +47,46 @@ class Profile_photo extends Controller {
|
|||
|
||||
function post() {
|
||||
|
||||
if(! local_channel()) {
|
||||
if (! local_channel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo');
|
||||
|
||||
if((array_key_exists('cropfinal',$_POST)) && (intval($_POST['cropfinal']) == 1)) {
|
||||
if ((array_key_exists('cropfinal',$_POST)) && (intval($_POST['cropfinal']) == 1)) {
|
||||
|
||||
// logger('crop: ' . print_r($_POST,true));
|
||||
|
||||
|
||||
|
||||
// phase 2 - we have finished cropping
|
||||
|
||||
if(argc() != 2) {
|
||||
if (argc() != 2) {
|
||||
notice( t('Image uploaded but image cropping failed.') . EOL );
|
||||
return;
|
||||
}
|
||||
|
||||
$image_id = argv(1);
|
||||
|
||||
if(substr($image_id,-2,1) == '-') {
|
||||
if (substr($image_id,-2,1) == '-') {
|
||||
$scale = substr($image_id,-1,1);
|
||||
$image_id = substr($image_id,0,-2);
|
||||
}
|
||||
|
||||
|
||||
// unless proven otherwise
|
||||
$is_default_profile = 1;
|
||||
|
||||
if($_REQUEST['profile']) {
|
||||
if ($_REQUEST['profile']) {
|
||||
$r = q("select id, profile_guid, is_default, gender from profile where id = %d and uid = %d limit 1",
|
||||
intval($_REQUEST['profile']),
|
||||
intval(local_channel())
|
||||
);
|
||||
if($r) {
|
||||
$profile = $r[0];
|
||||
if(! intval($profile['is_default']))
|
||||
if ($r) {
|
||||
$profile = array_shift($r);
|
||||
if (! intval($profile['is_default'])) {
|
||||
$is_default_profile = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$srcX = intval($_POST['xstart']);
|
||||
$srcY = intval($_POST['ystart']);
|
||||
$srcW = intval($_POST['xfinal']) - $srcX;
|
||||
|
@ -100,13 +96,13 @@ class Profile_photo extends Controller {
|
|||
dbesc($image_id),
|
||||
dbesc(local_channel()),
|
||||
intval($scale));
|
||||
if($r) {
|
||||
if ($r) {
|
||||
|
||||
$base_image = $r[0];
|
||||
$base_image['content'] = (($r[0]['os_storage']) ? @file_get_contents(dbunescbin($base_image['content'])) : dbunescbin($base_image['content']));
|
||||
$base_image = array_shift($r);
|
||||
$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']);
|
||||
if($im->is_valid()) {
|
||||
if ($im->is_valid()) {
|
||||
|
||||
$im->cropImage(300,$srcX,$srcY,$srcW,$srcH);
|
||||
|
||||
|
@ -139,7 +135,7 @@ class Profile_photo extends Controller {
|
|||
|
||||
$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.
|
||||
notice( t('Image resize failed.') . EOL );
|
||||
$x = q("delete from photo where resource_id = '%s' and uid = %d and imgscale in ( %d, %d, %d ) ",
|
||||
|
@ -156,7 +152,7 @@ class Profile_photo extends Controller {
|
|||
|
||||
// If setting for the default profile, unset the profile photo flag from any other photos I own
|
||||
|
||||
if($is_default_profile) {
|
||||
if ($is_default_profile) {
|
||||
|
||||
$r = q("update profile set photo = '%s', thumb = '%s' where is_default = 1 and uid = %d",
|
||||
dbesc(z_root() . '/photo/profile/l/' . local_channel()),
|
||||
|
@ -210,9 +206,9 @@ class Profile_photo extends Controller {
|
|||
photo_profile_setperms(local_channel(),$base_image['resource_id'],$_REQUEST['profile']);
|
||||
|
||||
$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));
|
||||
|
||||
}
|
||||
|
||||
// Similarly, tell the nav bar to bypass the cache and update the avatar image.
|
||||
$_SESSION['reload_avatar'] = true;
|
||||
|
@ -223,12 +219,12 @@ class Profile_photo extends Controller {
|
|||
Master::Summon( [ 'Directory', $channel['channel_id'] ] );
|
||||
|
||||
}
|
||||
else
|
||||
else {
|
||||
notice( t('Unable to process image') . EOL);
|
||||
}
|
||||
}
|
||||
|
||||
goaway(z_root() . '/profiles');
|
||||
return; // NOTREACHED
|
||||
}
|
||||
|
||||
// A new photo was uploaded. Store it and save some important details
|
||||
|
@ -240,7 +236,7 @@ class Profile_photo extends Controller {
|
|||
$smallest = 0;
|
||||
|
||||
|
||||
if($_REQUEST['importfile']) {
|
||||
if ($_REQUEST['importfile']) {
|
||||
$hash = $_REQUEST['importfile'];
|
||||
$importing = true;
|
||||
}
|
||||
|
@ -249,18 +245,18 @@ class Profile_photo extends Controller {
|
|||
$matches = [];
|
||||
$partial = false;
|
||||
|
||||
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);
|
||||
if($pm) {
|
||||
logger('Content-Range: ' . print_r($matches,true));
|
||||
if ($pm) {
|
||||
logger('Content-Range: ' . print_r($matches,true), LOGGER_DEBUG);
|
||||
$partial = true;
|
||||
}
|
||||
}
|
||||
|
||||
if($partial) {
|
||||
if ($partial) {
|
||||
$x = save_chunk($channel,$matches[1],$matches[2],$matches[3]);
|
||||
|
||||
if($x['partial']) {
|
||||
if ($x['partial']) {
|
||||
header('Range: bytes=0-' . (($x['length']) ? $x['length'] - 1 : 0));
|
||||
json_return_and_die($result);
|
||||
}
|
||||
|
@ -277,7 +273,7 @@ class Profile_photo extends Controller {
|
|||
}
|
||||
}
|
||||
else {
|
||||
if(! array_key_exists('userfile',$_FILES)) {
|
||||
if (! array_key_exists('userfile',$_FILES)) {
|
||||
$_FILES['userfile'] = [
|
||||
'name' => $_FILES['files']['name'],
|
||||
'type' => $_FILES['files']['type'],
|
||||
|
@ -290,27 +286,25 @@ class Profile_photo extends Controller {
|
|||
|
||||
$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 ]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
if(($res && intval($res['data']['is_photo'])) || $importing) {
|
||||
if (($res && intval($res['data']['is_photo'])) || $importing) {
|
||||
$i = q("select * from photo where resource_id = '%s' and uid = %d order by imgscale",
|
||||
dbesc($hash),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if(! $i) {
|
||||
if (! $i) {
|
||||
notice( t('Image upload failed.') . EOL );
|
||||
return;
|
||||
}
|
||||
$os_storage = false;
|
||||
|
||||
foreach($i as $ii) {
|
||||
if(intval($ii['imgscale']) < PHOTO_RES_640) {
|
||||
foreach ($i as $ii) {
|
||||
if (intval($ii['imgscale']) < PHOTO_RES_640) {
|
||||
$smallest = intval($ii['imgscale']);
|
||||
$os_storage = intval($ii['os_storage']);
|
||||
$imagedata = $ii['content'];
|
||||
|
@ -322,12 +316,12 @@ class Profile_photo extends Controller {
|
|||
$imagedata = (($os_storage) ? @file_get_contents(dbunescbin($imagedata)) : dbunescbin($imagedata));
|
||||
$ph = photo_factory($imagedata, $filetype);
|
||||
|
||||
if(! $ph->is_valid()) {
|
||||
if (! $ph->is_valid()) {
|
||||
notice( t('Unable to process image.') . EOL );
|
||||
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
|
||||
// App::$data['imagecrop'] is set, it will proceed to cropping
|
||||
|
@ -337,7 +331,6 @@ class Profile_photo extends Controller {
|
|||
|
||||
/* @brief Generate content of profile-photo view
|
||||
*
|
||||
* @param $a Current application
|
||||
* @return void
|
||||
*
|
||||
*/
|
||||
|
@ -345,7 +338,7 @@ class Profile_photo extends Controller {
|
|||
|
||||
function get() {
|
||||
|
||||
if(! local_channel()) {
|
||||
if (! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL );
|
||||
return;
|
||||
}
|
||||
|
@ -354,10 +347,11 @@ class Profile_photo extends Controller {
|
|||
$pf = 0;
|
||||
$newuser = false;
|
||||
|
||||
if(argc() == 2 && argv(1) === 'new')
|
||||
if (argc() == 2 && argv(1) === 'new') {
|
||||
$newuser = true;
|
||||
}
|
||||
|
||||
if(argv(1) === 'use') {
|
||||
if (argv(1) === 'use') {
|
||||
if (argc() < 3) {
|
||||
notice( t('Permission denied.') . EOL );
|
||||
return;
|
||||
|
@ -365,7 +359,6 @@ class Profile_photo extends Controller {
|
|||
|
||||
$resource_id = argv(2);
|
||||
|
||||
|
||||
$pf = (($_REQUEST['pf']) ? intval($_REQUEST['pf']) : 0);
|
||||
|
||||
$c = q("select id, is_default from profile where uid = %d",
|
||||
|
@ -374,7 +367,7 @@ class Profile_photo extends Controller {
|
|||
|
||||
$multi_profiles = true;
|
||||
|
||||
if(($c) && (count($c) === 1) && (intval($c[0]['is_default']))) {
|
||||
if (($c) && (count($c) === 1) && (intval($c[0]['is_default']))) {
|
||||
$_REQUEST['profile'] = $c[0]['id'];
|
||||
$multi_profiles = false;
|
||||
}
|
||||
|
@ -386,33 +379,34 @@ class Profile_photo extends Controller {
|
|||
intval(local_channel()),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
if(! $r) {
|
||||
if (! $r) {
|
||||
notice( t('Photo not available.') . EOL );
|
||||
return;
|
||||
}
|
||||
$havescale = false;
|
||||
foreach($r as $rr) {
|
||||
if($rr['imgscale'] == PHOTO_RES_PROFILE_80)
|
||||
foreach ($r as $rr) {
|
||||
if ($rr['imgscale'] == PHOTO_RES_PROFILE_80) {
|
||||
$havescale = true;
|
||||
}
|
||||
}
|
||||
|
||||
// set an already loaded and cropped photo as profile photo
|
||||
|
||||
if($havescale) {
|
||||
if ($havescale) {
|
||||
// unset any existing profile photos
|
||||
$r = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND uid = %d",
|
||||
intval(PHOTO_NORMAL),
|
||||
intval(PHOTO_PROFILE),
|
||||
intval(local_channel()));
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
$r = q("UPDATE photo SET photo_usage = %d WHERE uid = %d AND resource_id = '%s'",
|
||||
intval(PHOTO_PROFILE),
|
||||
intval(local_channel()),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
);
|
||||
|
||||
$r = q("UPDATE xchan set xchan_photo_date = '%s'
|
||||
where xchan_hash = '%s'",
|
||||
$r = q("UPDATE xchan set xchan_photo_date = '%s' where xchan_hash = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($channel['xchan_hash'])
|
||||
);
|
||||
|
@ -420,11 +414,11 @@ class Profile_photo extends Controller {
|
|||
photo_profile_setperms(local_channel(),$resource_id,$_REQUEST['profile']);
|
||||
|
||||
$sync = attach_export_data($channel,$resource_id);
|
||||
if($sync)
|
||||
if ($sync) {
|
||||
Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
}
|
||||
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon(array('Directory',local_channel()));
|
||||
Master::Summon( [ 'Directory',local_channel() ] );
|
||||
goaway(z_root() . '/profiles');
|
||||
}
|
||||
|
||||
|
@ -433,154 +427,148 @@ class Profile_photo extends Controller {
|
|||
intval(local_channel())
|
||||
|
||||
);
|
||||
if(! $r) {
|
||||
if (! $r) {
|
||||
notice( t('Photo not available.') . EOL );
|
||||
return;
|
||||
}
|
||||
|
||||
if(intval($r[0]['os_storage']))
|
||||
if (intval($r[0]['os_storage'])) {
|
||||
$data = @file_get_contents(dbunescbin($r[0]['content']));
|
||||
else
|
||||
}
|
||||
else {
|
||||
$data = dbunescbin($r[0]['content']);
|
||||
}
|
||||
|
||||
$ph = photo_factory($data, $r[0]['mimetype']);
|
||||
$smallest = 0;
|
||||
if($ph->is_valid()) {
|
||||
if ($ph->is_valid()) {
|
||||
// go ahead as if we have just uploaded a new photo to crop
|
||||
$i = q("select resource_id, imgscale from photo where resource_id = '%s' and uid = %d order by imgscale",
|
||||
dbesc($r[0]['resource_id']),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if($i) {
|
||||
if ($i) {
|
||||
$hash = $i[0]['resource_id'];
|
||||
foreach($i as $ii) {
|
||||
if(intval($ii['imgscale']) < PHOTO_RES_640) {
|
||||
foreach ($i as $ii) {
|
||||
if (intval($ii['imgscale']) < PHOTO_RES_640) {
|
||||
$smallest = intval($ii['imgscale']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($multi_profiles) {
|
||||
if ($multi_profiles) {
|
||||
App::$data['importfile'] = $resource_id;
|
||||
}
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
|
||||
// present an upload form
|
||||
|
||||
$profiles = q("select id, profile_name as name, is_default from profile where uid = %d order by id asc",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if($profiles) {
|
||||
for($x = 0; $x < count($profiles); $x ++) {
|
||||
if ($profiles) {
|
||||
for ($x = 0; $x < count($profiles); $x ++) {
|
||||
$profiles[$x]['selected'] = false;
|
||||
if($pf && $profiles[$x]['id'] == $pf)
|
||||
if ($pf && $profiles[$x]['id'] == $pf) {
|
||||
$profiles[$x]['selected'] = true;
|
||||
if((! $pf) && $profiles[$x]['is_default'])
|
||||
}
|
||||
if ((! $pf) && $profiles[$x]['is_default']) {
|
||||
$profiles[$x]['selected'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$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');
|
||||
|
||||
$o .= replace_macros($tpl,array(
|
||||
'$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.')),
|
||||
'$importfile' => (($importing) ? App::$data['importfile'] : ''),
|
||||
'$lbl_upfile' => t('Upload File:'),
|
||||
'$lbl_profiles' => t('Select a profile:'),
|
||||
'$title' => (($importing) ? t('Use Photo for Profile') : t('Change Profile Photo')),
|
||||
'$submit' => (($importing) ? t('Use') : t('Upload')),
|
||||
'$profiles' => $profiles,
|
||||
'$single' => ((count($profiles) == 1) ? true : false),
|
||||
'$profile0' => $profiles[0],
|
||||
'$embedPhotos' => t('Use a photo from your albums'),
|
||||
'$embedPhotosModalTitle' => t('Use a photo from your albums'),
|
||||
$o .= replace_macros($tpl, [
|
||||
'$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.')),
|
||||
'$importfile' => (($importing) ? App::$data['importfile'] : ''),
|
||||
'$lbl_upfile' => t('Upload File:'),
|
||||
'$lbl_profiles' => t('Select a profile:'),
|
||||
'$title' => (($importing) ? t('Use Photo for Profile') : t('Change Profile Photo')),
|
||||
'$submit' => (($importing) ? t('Use') : t('Upload')),
|
||||
'$profiles' => $profiles,
|
||||
'$single' => ((count($profiles) == 1) ? true : false),
|
||||
'$profile0' => $profiles[0],
|
||||
'$embedPhotos' => t('Use a photo from your albums'),
|
||||
'$embedPhotosModalTitle' => t('Use a photo from your albums'),
|
||||
'$embedPhotosModalCancel' => t('Cancel'),
|
||||
'$embedPhotosModalOK' => t('OK'),
|
||||
'$modalchooseimages' => t('Choose images to embed'),
|
||||
'$modalchoosealbum' => t('Choose an album'),
|
||||
'$modaldiffalbum' => t('Choose a different album'),
|
||||
'$modalerrorlist' => t('Error getting album list'),
|
||||
'$modalerrorlink' => t('Error getting photo link'),
|
||||
'$modalerroralbum' => t('Error getting album'),
|
||||
'$form_security_token' => get_form_security_token("profile_photo"),
|
||||
'$select' => t('Select existing photo'),
|
||||
));
|
||||
'$embedPhotosModalOK' => t('OK'),
|
||||
'$modalchooseimages' => t('Choose images to embed'),
|
||||
'$modalchoosealbum' => t('Choose an album'),
|
||||
'$modaldiffalbum' => t('Choose a different album'),
|
||||
'$modalerrorlist' => t('Error getting album list'),
|
||||
'$modalerrorlink' => t('Error getting photo link'),
|
||||
'$modalerroralbum' => t('Error getting album'),
|
||||
'$form_security_token' => get_form_security_token("profile_photo"),
|
||||
'$select' => t('Select previously uploaded photo'),
|
||||
]);
|
||||
|
||||
call_hooks('profile_photo_content_end', $o);
|
||||
|
||||
return $o;
|
||||
}
|
||||
else {
|
||||
|
||||
// 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'];
|
||||
$tpl = get_markup_template("cropbody.tpl");
|
||||
$o .= replace_macros($tpl,array(
|
||||
'$filename' => $filename,
|
||||
'$profile' => intval($_REQUEST['profile']),
|
||||
'$resource' => App::$data['imagecrop'] . '-' . App::$data['imagecrop_resolution'],
|
||||
'$image_url' => z_root() . '/photo/' . $filename,
|
||||
'$title' => t('Crop Image'),
|
||||
'$desc' => t('Please adjust the image cropping for optimum viewing.'),
|
||||
$o .= replace_macros(get_markup_template('cropbody.tpl'), [
|
||||
'$filename' => $filename,
|
||||
'$profile' => intval($_REQUEST['profile']),
|
||||
'$resource' => App::$data['imagecrop'] . '-' . App::$data['imagecrop_resolution'],
|
||||
'$image_url' => z_root() . '/photo/' . $filename,
|
||||
'$title' => t('Crop Image'),
|
||||
'$desc' => t('Please adjust the image cropping for optimum viewing.'),
|
||||
'$form_security_token' => get_form_security_token("profile_photo"),
|
||||
'$done' => t('Done Editing')
|
||||
));
|
||||
'$done' => t('Done Editing')
|
||||
]);
|
||||
return $o;
|
||||
}
|
||||
|
||||
return; // NOTREACHED
|
||||
}
|
||||
|
||||
/* @brief Generate the UI for photo-cropping
|
||||
*
|
||||
* @param $a Current application
|
||||
* @param $ph Photo-Factory
|
||||
* @return void
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function profile_photo_crop_ui_head(&$a, $ph, $hash, $smallest){
|
||||
|
||||
function profile_photo_crop_ui_head($ph, $hash, $smallest) {
|
||||
$max_length = get_config('system','max_image_length');
|
||||
if(! $max_length)
|
||||
if (! $max_length) {
|
||||
$max_length = MAX_IMAGE_LENGTH;
|
||||
if($max_length > 0)
|
||||
}
|
||||
if ($max_length > 0) {
|
||||
$ph->scaleImage($max_length);
|
||||
}
|
||||
|
||||
App::$data['width'] = $ph->getWidth();
|
||||
App::$data['height'] = $ph->getHeight();
|
||||
|
||||
if(App::$data['width'] < 500 || App::$data['height'] < 500) {
|
||||
if (App::$data['width'] < 500 || App::$data['height'] < 500) {
|
||||
$ph->scaleImageUp(400);
|
||||
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"), array());
|
||||
App::$page['htmlhead'] .= replace_macros(get_markup_template('crophead.tpl'), []);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -475,8 +475,6 @@ class Channel {
|
|||
$default_permcat = get_pconfig(local_channel(),'system','default_permcat','default');
|
||||
|
||||
|
||||
$stpl = get_markup_template('settings.tpl');
|
||||
|
||||
$acl = new AccessControl($channel);
|
||||
$perm_defaults = $acl->get();
|
||||
|
||||
|
@ -528,9 +526,8 @@ class Channel {
|
|||
$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'),
|
||||
|
||||
'$submit' => t('Submit'),
|
||||
'$baseurl' => z_root(),
|
||||
'$uid' => local_channel(),
|
||||
|
@ -551,11 +548,6 @@ class Channel {
|
|||
|
||||
'$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,
|
||||
'$comment_perms' => $comment_perms,
|
||||
|
||||
|
@ -640,20 +632,16 @@ class Channel {
|
|||
'$h_descadvn' => t('Change the behaviour of this account for special situations'),
|
||||
'$pagetype' => $pagetype,
|
||||
'$lbl_misc' => t('Miscellaneous Settings'),
|
||||
'$photo_path' => array('photo_path', t('Default photo upload folder'), 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')),
|
||||
'$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 name'), get_pconfig(local_channel(),'system','attach_path'), t('%Y - current year, %m - current month')),
|
||||
'$menus' => $menu,
|
||||
'$menu_desc' => t('Personal menu to display in your channel pages'),
|
||||
'$removeme' => t('Remove Channel'),
|
||||
'$removechannel' => t('Remove this channel.'),
|
||||
'$firefoxshare' => t('Firefox Share $Projectname provider'),
|
||||
'$cal_first_day' => array('first_day', t('Start calendar week on Monday'), ((get_pconfig(local_channel(),'system','cal_first_day')) ? 1 : ''), '', $yes_no),
|
||||
));
|
||||
]);
|
||||
|
||||
call_hooks('settings_form',$o);
|
||||
|
||||
//$o .= '</form>' . "\r\n";
|
||||
|
||||
return $o;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ class Siteinfo extends Controller {
|
|||
|
||||
function get() {
|
||||
|
||||
if(defined('NOMADIC')) {
|
||||
if(! get_config('system','activitypub')) {
|
||||
$federated = [ 'zot6' ];
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -111,7 +111,7 @@ class Webfinger extends Controller {
|
|||
'http://webfinger.net/ns/name' => $channel_target['channel_name'],
|
||||
'http://xmlns.com/foaf/0.1/name' => $channel_target['channel_name'],
|
||||
'https://w3id.org/security/v1#publicKeyPem' => $channel_target['xchan_pubkey'],
|
||||
'http://purl.org/zot/federation' => ((defined('NOMADIC')) ? 'zot6' : 'zot6,activitypub')
|
||||
'http://purl.org/zot/federation' => ((get_config('system','activitypub')) ? 'zot6,activitypub' : 'zot6')
|
||||
];
|
||||
|
||||
foreach ($aliases as $alias) {
|
||||
|
@ -150,6 +150,18 @@ class Webfinger extends Controller {
|
|||
'href' => z_root() . '/owa'
|
||||
],
|
||||
|
||||
[
|
||||
'rel' => 'self',
|
||||
'type' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
|
||||
'href' => z_root() . '/channel/' . $channel_target['channel_address']
|
||||
],
|
||||
|
||||
[
|
||||
'rel' => 'self',
|
||||
'type' => 'application/activity+json',
|
||||
'href' => z_root() . '/channel/' . $channel_target['channel_address']
|
||||
],
|
||||
|
||||
[
|
||||
'rel' => 'http://ostatus.org/schema/1.0/subscribe',
|
||||
'template' => z_root() . '/follow?url={uri}'
|
||||
|
@ -157,19 +169,6 @@ class Webfinger extends Controller {
|
|||
];
|
||||
}
|
||||
|
||||
if (! defined('NOMADIC')) {
|
||||
$result['links'][] = [
|
||||
'rel' => 'self',
|
||||
'type' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
|
||||
'href' => z_root() . '/channel/' . $channel_target['channel_address']
|
||||
];
|
||||
$result['links'][] = [
|
||||
'rel' => 'self',
|
||||
'type' => 'application/activity+json',
|
||||
'href' => z_root() . '/channel/' . $channel_target['channel_address']
|
||||
];
|
||||
}
|
||||
|
||||
if (! $result) {
|
||||
header($_SERVER['SERVER_PROTOCOL'] . ' ' . 400 . ' ' . 'Bad Request');
|
||||
killme();
|
||||
|
|
|
@ -1,27 +1,31 @@
|
|||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Module\Webfinger;
|
||||
use Zotlabs\Module\Oauthinfo;
|
||||
|
||||
class Well_known extends \Zotlabs\Web\Controller {
|
||||
class Well_known extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
if(argc() > 1) {
|
||||
if (argc() > 1) {
|
||||
|
||||
$arr = array('server' => $_SERVER, 'request' => $_REQUEST);
|
||||
$arr = [ 'server' => $_SERVER, 'request' => $_REQUEST ];
|
||||
call_hooks('well_known', $arr);
|
||||
|
||||
|
||||
if(! check_siteallowed($_SERVER['REMOTE_ADDR'])) {
|
||||
if (! check_siteallowed($_SERVER['REMOTE_ADDR'])) {
|
||||
logger('well_known: site not allowed. ' . $_SERVER['REMOTE_ADDR']);
|
||||
killme();
|
||||
}
|
||||
|
||||
// from php.net re: REMOTE_HOST:
|
||||
// Note: Your web server must be configured to create this variable. For example in Apache
|
||||
// you'll need HostnameLookups On inside httpd.conf for it to exist. See also gethostbyaddr().
|
||||
// Note: Your web server must be configured to create this variable.
|
||||
// For example in Apache you'll need HostnameLookups On inside httpd.conf
|
||||
// for it to exist. See also gethostbyaddr().
|
||||
|
||||
if(get_config('system','siteallowed_remote_host') && (! check_siteallowed($_SERVER['REMOTE_HOST']))) {
|
||||
if (get_config('system','siteallowed_remote_host') && (! check_siteallowed($_SERVER['REMOTE_HOST']))) {
|
||||
logger('well_known: site not allowed. ' . $_SERVER['REMOTE_HOST']);
|
||||
killme();
|
||||
}
|
||||
|
@ -29,19 +33,19 @@ class Well_known extends \Zotlabs\Web\Controller {
|
|||
switch(argv(1)) {
|
||||
|
||||
case 'webfinger':
|
||||
\App::$argc -= 1;
|
||||
array_shift(\App::$argv);
|
||||
\App::$argv[0] = 'webfinger';
|
||||
$module = new \Zotlabs\Module\Webfinger();
|
||||
App::$argc -= 1;
|
||||
array_shift(App::$argv);
|
||||
App::$argv[0] = 'webfinger';
|
||||
$module = new Webfinger();
|
||||
$module->init();
|
||||
break;
|
||||
|
||||
case 'oauth-authorization-server':
|
||||
case 'openid-configuration':
|
||||
\App::$argc -= 1;
|
||||
App::$argc -= 1;
|
||||
array_shift(\App::$argv);
|
||||
\App::$argv[0] = 'oauthinfo';
|
||||
$module = new \Zotlabs\Module\Oauthinfo();
|
||||
App::$argv[0] = 'oauthinfo';
|
||||
$module = new Oauthinfo();
|
||||
$module->init();
|
||||
break;
|
||||
|
||||
|
@ -50,14 +54,13 @@ class Well_known extends \Zotlabs\Web\Controller {
|
|||
killme();
|
||||
|
||||
default:
|
||||
if(file_exists(\App::$cmd)) {
|
||||
echo file_get_contents(\App::$cmd);
|
||||
if (file_exists(App::$cmd)) {
|
||||
echo file_get_contents(App::$cmd);
|
||||
killme();
|
||||
}
|
||||
elseif(file_exists(\App::$cmd . '.php'))
|
||||
require_once(\App::$cmd . '.php');
|
||||
elseif (file_exists(App::$cmd . '.php'))
|
||||
require_once(App::$cmd . '.php');
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -727,14 +727,14 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
|||
return $ret;
|
||||
}
|
||||
|
||||
$r = q("SELECT channel_id, channel_address, profile.publish FROM channel left join profile on profile.uid = channel.channel_id WHERE channel_removed = 0 AND channel_system = 0 AND (channel_pageflags & %d) = 0",
|
||||
$r = q("SELECT channel_id, channel_address FROM channel left join profile on profile.uid = channel.channel_id WHERE channel_removed = 0 AND channel_system = 0 AND (channel_pageflags & %d) = 0",
|
||||
intval(PAGE_HIDDEN)
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
if (perm_is_allowed($rr['channel_id'], $auth->observer, 'view_storage') && $rr['publish']) {
|
||||
logger('found channel: /cloud/' . $rr['channel_address'], LOGGER_DATA);
|
||||
if (perm_is_allowed($rr['channel_id'], $auth->observer, 'view_storage')) {
|
||||
logger('found channel: ' . $rr['channel_address'], LOGGER_DATA);
|
||||
$ret[] = new Directory($rr['channel_address'], $auth);
|
||||
}
|
||||
}
|
||||
|
|
29
Zotlabs/Update/_1235.php
Normal file
29
Zotlabs/Update/_1235.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Zotlabs\Update;
|
||||
|
||||
class _1235 {
|
||||
|
||||
function run() {
|
||||
|
||||
$r = q("ALTER TABLE item add replyto text NOT NULL DEFAULT ''");
|
||||
|
||||
if($r)
|
||||
return UPDATE_SUCCESS;
|
||||
return UPDATE_FAILED;
|
||||
|
||||
}
|
||||
|
||||
function verify() {
|
||||
|
||||
$columns = db_columns('item');
|
||||
|
||||
if(in_array('replyto',$columns)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
43
Zotlabs/Update/_1236.php
Normal file
43
Zotlabs/Update/_1236.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace Zotlabs\Update;
|
||||
|
||||
class _1236 {
|
||||
|
||||
function run() {
|
||||
|
||||
q("START TRANSACTION");
|
||||
|
||||
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
|
||||
$r1 = q("ALTER TABLE abook ADD abook_alias text NOT NULL");
|
||||
$r2 = q("create index \"abook_alias_idx\" on photo (\"abook_alias\")");
|
||||
|
||||
$r = ($r1 && $r2);
|
||||
}
|
||||
else {
|
||||
$r = q("ALTER TABLE `abook` ADD `abook_alias` char(191) NOT NULL DEFAULT '' ,
|
||||
ADD INDEX `abook_alias` (`abook_alias`)");
|
||||
}
|
||||
|
||||
if($r) {
|
||||
q("COMMIT");
|
||||
return UPDATE_SUCCESS;
|
||||
}
|
||||
|
||||
q("ROLLBACK");
|
||||
return UPDATE_FAILED;
|
||||
|
||||
}
|
||||
|
||||
function verify() {
|
||||
|
||||
$columns = db_columns('abook');
|
||||
|
||||
if(in_array('abook_alias',$columns)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -163,27 +163,26 @@ class WebServer {
|
|||
'type' => 'application/jrd+json',
|
||||
'url' => z_root() . '/.well-known/webfinger?f=&resource=acct%3A' . argv(1) . '%40' . App::get_hostname()
|
||||
],
|
||||
|
||||
[
|
||||
'rel' => 'zot',
|
||||
'type' => 'application/x-zot+json',
|
||||
'url' => z_root() . '/channel/' . argv(1)
|
||||
],
|
||||
|
||||
[
|
||||
'rel' => 'self',
|
||||
'type' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
|
||||
'href' => z_root() . '/channel/' . argv(1)
|
||||
],
|
||||
|
||||
[
|
||||
'rel' => 'self',
|
||||
'type' => 'application/activity+json',
|
||||
'href' => z_root() . '/channel/' . argv(1)
|
||||
]
|
||||
];
|
||||
|
||||
if(! defined('NOMADIC')) {
|
||||
App::$channel_links[] =
|
||||
[
|
||||
'rel' => 'self',
|
||||
'type' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
|
||||
'href' => z_root() . '/channel/' . argv(1)
|
||||
];
|
||||
App::$channel_links[] =
|
||||
[
|
||||
'rel' => 'self',
|
||||
'type' => 'application/activity+json',
|
||||
'href' => z_root() . '/channel/' . argv(1)
|
||||
];
|
||||
}
|
||||
$x = [ 'channel_address' => argv(1), 'channel_links' => App::$channel_links ];
|
||||
call_hooks('channel_links', $x );
|
||||
App::$channel_links = $x['channel_links'];
|
||||
|
|
|
@ -6,9 +6,7 @@ class Clock {
|
|||
|
||||
function widget($arr) {
|
||||
|
||||
$miltime = 0;
|
||||
if(isset($arr['military']) && $arr['military'])
|
||||
$miltime = 1;
|
||||
$miltime = ((isset($arr['military']) && $arr['military']) ? intval($arr['military']) : false);
|
||||
|
||||
$o = <<< EOT
|
||||
<div class="widget">
|
||||
|
@ -29,7 +27,7 @@ function startclock(){
|
|||
showtime()
|
||||
}
|
||||
|
||||
function showtime(){
|
||||
function showtime() {
|
||||
var now = new Date()
|
||||
var hours = now.getHours()
|
||||
var minutes = now.getMinutes()
|
||||
|
|
|
@ -1,24 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
use App;
|
||||
|
||||
class Newmember {
|
||||
|
||||
function widget($arr) {
|
||||
|
||||
if(! local_channel())
|
||||
if (! local_channel()) {
|
||||
return EMPTY_STR;
|
||||
}
|
||||
|
||||
$c = \App::get_channel();
|
||||
if(! $c)
|
||||
$c = App::get_channel();
|
||||
if (! $c) {
|
||||
return EMPTY_STR;
|
||||
}
|
||||
$a = App::get_account();
|
||||
if (! $a) {
|
||||
return EMPTY_STR;
|
||||
}
|
||||
|
||||
$a = \App::get_account();
|
||||
if(! $a)
|
||||
return EMPTY_STR;
|
||||
|
||||
if(! feature_enabled(local_channel(),'start_menu'))
|
||||
// @fixme
|
||||
if (! feature_enabled(local_channel(),'start_menu')) {
|
||||
return EMPTY_STR;
|
||||
}
|
||||
|
||||
$options = [
|
||||
t('Profile Creation'),
|
||||
|
@ -53,14 +58,13 @@ class Newmember {
|
|||
|
||||
// hack to put this in the correct spot of the array
|
||||
|
||||
if($site_firehose || $net_firehose) {
|
||||
if ($site_firehose || $net_firehose) {
|
||||
$options[5]['pubstream'] = t('View public stream');
|
||||
}
|
||||
|
||||
$o = replace_macros(get_markup_template('new_member.tpl'), [
|
||||
'$title' => t('New Member Links'),
|
||||
'$options' => $options
|
||||
|
||||
]);
|
||||
|
||||
return $o;
|
||||
|
|
8
boot.php
8
boot.php
|
@ -48,10 +48,10 @@ require_once('include/items.php');
|
|||
|
||||
|
||||
|
||||
define ( 'STD_VERSION', '19.8.26' );
|
||||
define ( 'STD_VERSION', '19.9.18' );
|
||||
define ( 'ZOT_REVISION', '6.0' );
|
||||
|
||||
define ( 'DB_UPDATE_VERSION', 1234 );
|
||||
define ( 'DB_UPDATE_VERSION', 1236 );
|
||||
|
||||
define ( 'PLATFORM_NAME', 'zap' );
|
||||
define ( 'PLATFORM_ARCHITECTURE', 'zap' );
|
||||
|
@ -75,7 +75,7 @@ define ( 'DIRECTORY_MODE_PRIMARY', 0x0001); // There can only be *one* prima
|
|||
define ( 'DIRECTORY_MODE_SECONDARY', 0x0002); // All other mirror directory servers
|
||||
define ( 'DIRECTORY_MODE_STANDALONE', 0x0100); // A detached (off the grid) hub with itself as directory server.
|
||||
|
||||
// We will look for upstream directories whenever me make contact
|
||||
// We will look for upstream directories whenever we make contact
|
||||
// with other sites, but if this is a new installation and isn't
|
||||
// a standalone hub, we need to seed the service with a starting
|
||||
// point to go out and find the rest of the world.
|
||||
|
@ -470,7 +470,7 @@ define ( 'NAMESPACE_YMEDIA', 'http://search.yahoo.com/mrss/' );
|
|||
|
||||
define ( 'ACTIVITYSTREAMS_JSONLD_REV', 'https://www.w3.org/ns/activitystreams' );
|
||||
|
||||
define ( 'ZOT_APSCHEMA_REV', '/apschema/v1.9' );
|
||||
define ( 'ZOT_APSCHEMA_REV', '/apschema/v1.10' );
|
||||
/**
|
||||
* activity stream defines
|
||||
*/
|
||||
|
|
|
@ -1,52 +1,49 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file include/account.php
|
||||
* @brief Somme account related functions.
|
||||
* @brief Some account related functions.
|
||||
*/
|
||||
|
||||
use Zotlabs\Lib\Crypto;
|
||||
|
||||
require_once('include/config.php');
|
||||
require_once('include/network.php');
|
||||
require_once('include/plugin.php');
|
||||
require_once('include/text.php');
|
||||
require_once('include/language.php');
|
||||
require_once('include/datetime.php');
|
||||
require_once('include/channel.php');
|
||||
|
||||
|
||||
function get_account_by_id($account_id) {
|
||||
$r = q("select * from account where account_id = %d",
|
||||
intval($account_id)
|
||||
);
|
||||
return (($r) ? $r[0] : false);
|
||||
return (($r) ? array_shift($r) : false);
|
||||
}
|
||||
|
||||
function check_account_email($email) {
|
||||
|
||||
$email = punify($email);
|
||||
$result = array('error' => false, 'message' => '');
|
||||
$result = [ 'error' => false, 'message' => '' ];
|
||||
|
||||
// Caution: empty email isn't counted as an error in this function.
|
||||
// Check for empty value separately.
|
||||
|
||||
if(! strlen($email))
|
||||
if (! strlen($email)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
if(! validate_email($email))
|
||||
if (! validate_email($email)) {
|
||||
$result['message'] .= t('Not a valid email address') . EOL;
|
||||
elseif(! allowed_email($email))
|
||||
}
|
||||
elseif (! allowed_email($email)) {
|
||||
$result['message'] = t('Your email domain is not among those allowed on this site');
|
||||
}
|
||||
else {
|
||||
$r = q("select account_email from account where account_email = '%s' limit 1",
|
||||
dbesc($email)
|
||||
);
|
||||
if($r) {
|
||||
if ($r) {
|
||||
$result['message'] .= t('Your email address is already registered at this site.');
|
||||
}
|
||||
}
|
||||
if($result['message'])
|
||||
if ($result['message']) {
|
||||
$result['error'] = true;
|
||||
}
|
||||
|
||||
$arr = array('email' => $email, 'result' => $result);
|
||||
call_hooks('check_account_email', $arr);
|
||||
|
@ -55,54 +52,58 @@ function check_account_email($email) {
|
|||
}
|
||||
|
||||
function check_account_password($password) {
|
||||
$result = array('error' => false, 'message' => '');
|
||||
$result = [ 'error' => false, 'message' => '' ];
|
||||
|
||||
// The only validation we perform by default is pure Javascript to
|
||||
// check minimum length and that both entered passwords match.
|
||||
// Use hooked functions to perform complexity requirement checks.
|
||||
|
||||
$arr = array('password' => $password, 'result' => $result);
|
||||
$arr = [ 'password' => $password, 'result' => $result ];
|
||||
call_hooks('check_account_password', $arr);
|
||||
|
||||
return $arr['result'];
|
||||
}
|
||||
|
||||
function check_account_invite($invite_code) {
|
||||
$result = array('error' => false, 'message' => '');
|
||||
$result = [ 'error' => false, 'message' => '' ];
|
||||
|
||||
$using_invites = get_config('system','invitation_only');
|
||||
|
||||
if($using_invites) {
|
||||
if(! $invite_code) {
|
||||
if ($using_invites) {
|
||||
if (! $invite_code) {
|
||||
$result['message'] .= t('An invitation is required.') . EOL;
|
||||
}
|
||||
$r = q("select * from register where hash = '%s' limit 1", dbesc($invite_code));
|
||||
if(! $r) {
|
||||
if (! $r) {
|
||||
$result['message'] .= t('Invitation could not be verified.') . EOL;
|
||||
}
|
||||
}
|
||||
if(strlen($result['message']))
|
||||
if (strlen($result['message'])) {
|
||||
$result['error'] = true;
|
||||
}
|
||||
|
||||
$arr = array('invite_code' => $invite_code, 'result' => $result);
|
||||
$arr = [ 'invite_code' => $invite_code, 'result' => $result ];
|
||||
call_hooks('check_account_invite', $arr);
|
||||
|
||||
return $arr['result'];
|
||||
}
|
||||
|
||||
function check_account_admin($arr) {
|
||||
if(is_site_admin())
|
||||
if (is_site_admin()) {
|
||||
return true;
|
||||
}
|
||||
$admin_email = trim(get_config('system','admin_email'));
|
||||
if(strlen($admin_email) && $admin_email === trim($arr['email']))
|
||||
if (strlen($admin_email) && $admin_email === trim($arr['email'])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function account_total() {
|
||||
$r = q("select account_id from account where true");
|
||||
if(is_array($r))
|
||||
if ($r) {
|
||||
return count($r);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -138,7 +139,7 @@ function create_account($arr) {
|
|||
|
||||
// Required: { email, password }
|
||||
|
||||
$result = array('success' => false, 'email' => '', 'password' => '', 'message' => '');
|
||||
$result = [ 'success' => false, 'email' => '', 'password' => '', 'message' => '' ];
|
||||
|
||||
$invite_code = ((x($arr,'invite_code')) ? notags(trim($arr['invite_code'])) : '');
|
||||
$email = ((x($arr,'email')) ? notags(punify(trim($arr['email']))) : '');
|
||||
|
@ -149,30 +150,25 @@ function create_account($arr) {
|
|||
$roles = ((x($arr,'account_roles')) ? intval($arr['account_roles']) : 0 );
|
||||
$expires = ((x($arr,'expires')) ? intval($arr['expires']) : NULL_DATE);
|
||||
|
||||
$default_service_class = get_config('system','default_service_class');
|
||||
$default_service_class = get_config('system','default_service_class', EMPTY_STR);
|
||||
|
||||
if($default_service_class === false)
|
||||
$default_service_class = '';
|
||||
|
||||
if((! x($email)) || (! x($password))) {
|
||||
if (! ($email && $password)) {
|
||||
$result['message'] = t('Please enter the required information.');
|
||||
return $result;
|
||||
}
|
||||
|
||||
// prevent form hackery
|
||||
|
||||
if($roles & ACCOUNT_ROLE_ADMIN) {
|
||||
$admin_result = check_account_admin($arr);
|
||||
if(! $admin_result) {
|
||||
$roles = 0;
|
||||
}
|
||||
if (($roles & ACCOUNT_ROLE_ADMIN) && (! check_account_admin($arr))) {
|
||||
$roles = $roles - ACCOUNT_ROLE_ADMIN;
|
||||
}
|
||||
|
||||
// allow the admin_email account to be admin, but only if it's the first account.
|
||||
|
||||
$c = account_total();
|
||||
if (($c === 0) && (check_account_admin($arr)))
|
||||
if (($c === 0) && (check_account_admin($arr))) {
|
||||
$roles |= ACCOUNT_ROLE_ADMIN;
|
||||
}
|
||||
|
||||
// Ensure that there is a host keypair.
|
||||
|
||||
|
@ -183,21 +179,21 @@ function create_account($arr) {
|
|||
}
|
||||
|
||||
$invite_result = check_account_invite($invite_code);
|
||||
if($invite_result['error']) {
|
||||
if ($invite_result['error']) {
|
||||
$result['message'] = $invite_result['message'];
|
||||
return $result;
|
||||
}
|
||||
|
||||
$email_result = check_account_email($email);
|
||||
|
||||
if($email_result['error']) {
|
||||
if ($email_result['error']) {
|
||||
$result['message'] = $email_result['message'];
|
||||
return $result;
|
||||
}
|
||||
|
||||
$password_result = check_account_password($password);
|
||||
|
||||
if($password_result['error']) {
|
||||
if ($password_result['error']) {
|
||||
$result['message'] = $password_result['message'];
|
||||
return $result;
|
||||
}
|
||||
|
@ -219,7 +215,7 @@ function create_account($arr) {
|
|||
'account_service_class' => $default_service_class
|
||||
]
|
||||
);
|
||||
if(! $r) {
|
||||
if (! $r) {
|
||||
logger('create_account: DB INSERT failed.');
|
||||
$result['message'] = t('Failed to store account information.');
|
||||
return($result);
|
||||
|
@ -229,7 +225,7 @@ function create_account($arr) {
|
|||
dbesc($email),
|
||||
dbesc($password_encoded)
|
||||
);
|
||||
if($r && count($r)) {
|
||||
if ($r && count($r)) {
|
||||
$result['account'] = $r[0];
|
||||
}
|
||||
else {
|
||||
|
@ -238,12 +234,12 @@ function create_account($arr) {
|
|||
|
||||
// Set the parent record to the current record_id if no parent was provided
|
||||
|
||||
if(! $parent) {
|
||||
if (! $parent) {
|
||||
$r = q("update account set account_parent = %d where account_id = %d",
|
||||
intval($result['account']['account_id']),
|
||||
intval($result['account']['account_id'])
|
||||
);
|
||||
if(! $r) {
|
||||
if (! $r) {
|
||||
logger('create_account: failed to set parent');
|
||||
}
|
||||
$result['account']['parent'] = $result['account']['account_id'];
|
||||
|
@ -262,19 +258,19 @@ function create_account($arr) {
|
|||
|
||||
function verify_email_address($arr) {
|
||||
|
||||
if(array_key_exists('resend',$arr)) {
|
||||
if (array_key_exists('resend',$arr)) {
|
||||
$email = $arr['email'];
|
||||
$a = q("select * from account where account_email = '%s' limit 1",
|
||||
dbesc($arr['email'])
|
||||
);
|
||||
if(! ($a && ($a[0]['account_flags'] & ACCOUNT_UNVERIFIED))) {
|
||||
if (! ($a && ($a[0]['account_flags'] & ACCOUNT_UNVERIFIED))) {
|
||||
return false;
|
||||
}
|
||||
$account = $a[0];
|
||||
$account = array_shift($a);
|
||||
$v = q("select * from register where uid = %d and password = 'verify' limit 1",
|
||||
intval($account['account_id'])
|
||||
);
|
||||
if($v) {
|
||||
if ($v) {
|
||||
$hash = $v[0]['hash'];
|
||||
}
|
||||
else {
|
||||
|
@ -317,11 +313,12 @@ function verify_email_address($arr) {
|
|||
|
||||
pop_lang();
|
||||
|
||||
if($res)
|
||||
if ($res) {
|
||||
$delivered ++;
|
||||
else
|
||||
}
|
||||
else {
|
||||
logger('send_reg_approval_email: failed to account_id: ' . $arr['account']['account_id']);
|
||||
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
@ -333,19 +330,21 @@ function send_reg_approval_email($arr) {
|
|||
$r = q("select * from account where (account_roles & %d) >= 4096",
|
||||
intval(ACCOUNT_ROLE_ADMIN)
|
||||
);
|
||||
if(! ($r && count($r)))
|
||||
if (! ($r && count($r))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$admins = array();
|
||||
$admins = [];
|
||||
|
||||
foreach($r as $rr) {
|
||||
if(strlen($rr['account_email'])) {
|
||||
$admins[] = array('email' => $rr['account_email'], 'lang' => $rr['account_lang']);
|
||||
foreach ($r as $rr) {
|
||||
if (strlen($rr['account_email'])) {
|
||||
$admins[] = [ 'email' => $rr['account_email'], 'lang' => $rr['account_lang'] ];
|
||||
}
|
||||
}
|
||||
|
||||
if(! count($admins))
|
||||
if (! count($admins)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hash = random_string();
|
||||
|
||||
|
@ -363,20 +362,22 @@ function send_reg_approval_email($arr) {
|
|||
|
||||
$delivered = 0;
|
||||
|
||||
foreach($admins as $admin) {
|
||||
if(strlen($admin['lang']))
|
||||
foreach ($admins as $admin) {
|
||||
if (strlen($admin['lang'])) {
|
||||
push_lang($admin['lang']);
|
||||
else
|
||||
}
|
||||
else {
|
||||
push_lang('en');
|
||||
}
|
||||
|
||||
$email_msg = replace_macros(get_intltext_template('register_verify_eml.tpl'), array(
|
||||
$email_msg = replace_macros(get_intltext_template('register_verify_eml.tpl'), [
|
||||
'$sitename' => get_config('system','sitename'),
|
||||
'$siteurl' => z_root(),
|
||||
'$email' => $arr['email'],
|
||||
'$uid' => $arr['account']['account_id'],
|
||||
'$hash' => $hash,
|
||||
'$details' => $details
|
||||
));
|
||||
]);
|
||||
|
||||
$res = z_mail(
|
||||
[
|
||||
|
@ -386,25 +387,27 @@ function send_reg_approval_email($arr) {
|
|||
]
|
||||
);
|
||||
|
||||
if($res)
|
||||
if ($res) {
|
||||
$delivered ++;
|
||||
else
|
||||
}
|
||||
else {
|
||||
logger('send_reg_approval_email: failed to ' . $admin['email'] . 'account_id: ' . $arr['account']['account_id']);
|
||||
}
|
||||
|
||||
pop_lang();
|
||||
}
|
||||
|
||||
return($delivered ? true : false);
|
||||
return ($delivered ? true : false);
|
||||
}
|
||||
|
||||
function send_register_success_email($email,$password) {
|
||||
|
||||
$email_msg = replace_macros(get_intltext_template('register_open_eml.tpl'), array(
|
||||
$email_msg = replace_macros(get_intltext_template('register_open_eml.tpl'), [
|
||||
'$sitename' => get_config('system','sitename'),
|
||||
'$siteurl' => z_root(),
|
||||
'$email' => $email,
|
||||
'$password' => t('your registration password'),
|
||||
));
|
||||
]);
|
||||
|
||||
$res = z_mail(
|
||||
[
|
||||
|
@ -414,7 +417,7 @@ function send_register_success_email($email,$password) {
|
|||
]
|
||||
);
|
||||
|
||||
return($res ? true : false);
|
||||
return ($res ? true : false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -431,26 +434,27 @@ function account_allow($hash) {
|
|||
dbesc($hash)
|
||||
);
|
||||
|
||||
if(! $register)
|
||||
if (! $register) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$account = q("SELECT * FROM account WHERE account_id = %d LIMIT 1",
|
||||
intval($register[0]['uid'])
|
||||
);
|
||||
|
||||
if(! $account)
|
||||
if (! $account)
|
||||
return $ret;
|
||||
|
||||
$r = q("DELETE FROM register WHERE hash = '%s'",
|
||||
dbesc($register[0]['hash'])
|
||||
);
|
||||
|
||||
$r = q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d)>0 and account_id = %d",
|
||||
$r = q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d) > 0 and account_id = %d",
|
||||
intval(ACCOUNT_BLOCKED),
|
||||
intval(ACCOUNT_BLOCKED),
|
||||
intval($register[0]['uid'])
|
||||
);
|
||||
$r = q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d)>0 and account_id = %d",
|
||||
$r = q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d) > 0 and account_id = %d",
|
||||
intval(ACCOUNT_PENDING),
|
||||
intval(ACCOUNT_PENDING),
|
||||
intval($register[0]['uid'])
|
||||
|
@ -459,14 +463,14 @@ function account_allow($hash) {
|
|||
push_lang($register[0]['lang']);
|
||||
|
||||
$email_tpl = get_intltext_template("register_open_eml.tpl");
|
||||
$email_msg = replace_macros($email_tpl, array(
|
||||
'$sitename' => get_config('system','sitename'),
|
||||
'$siteurl' => z_root(),
|
||||
'$username' => $account[0]['account_email'],
|
||||
'$email' => $account[0]['account_email'],
|
||||
'$password' => '',
|
||||
'$uid' => $account[0]['account_id']
|
||||
));
|
||||
$email_msg = replace_macros($email_tpl, [
|
||||
'$sitename' => get_config('system','sitename'),
|
||||
'$siteurl' => z_root(),
|
||||
'$username' => $account[0]['account_email'],
|
||||
'$email' => $account[0]['account_email'],
|
||||
'$password' => '',
|
||||
'$uid' => $account[0]['account_id']
|
||||
]);
|
||||
|
||||
$res = z_mail(
|
||||
[
|
||||
|
@ -478,8 +482,9 @@ function account_allow($hash) {
|
|||
|
||||
pop_lang();
|
||||
|
||||
if(get_config('system','auto_channel_create'))
|
||||
if (get_config('system','auto_channel_create')) {
|
||||
auto_channel_create($register[0]['uid']);
|
||||
}
|
||||
|
||||
if ($res) {
|
||||
info( t('Account approved.') . EOL );
|
||||
|
@ -505,15 +510,17 @@ function account_deny($hash) {
|
|||
dbesc($hash)
|
||||
);
|
||||
|
||||
if(! count($register))
|
||||
if(! $register) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$account = q("SELECT account_id, account_email FROM account WHERE account_id = %d LIMIT 1",
|
||||
intval($register[0]['uid'])
|
||||
);
|
||||
|
||||
if(! $account)
|
||||
if (! $account) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$r = q("DELETE FROM account WHERE account_id = %d",
|
||||
intval($register[0]['uid'])
|
||||
|
@ -540,15 +547,17 @@ function account_approve($hash) {
|
|||
dbesc($hash)
|
||||
);
|
||||
|
||||
if(! $register)
|
||||
if (! $register) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$account = q("SELECT * FROM account WHERE account_id = %d LIMIT 1",
|
||||
intval($register[0]['uid'])
|
||||
);
|
||||
|
||||
if(! $account)
|
||||
if (! $account) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$r = q("DELETE FROM register WHERE hash = '%s' and password = 'verify'",
|
||||
dbesc($register[0]['hash'])
|
||||
|
@ -576,11 +585,13 @@ function account_approve($hash) {
|
|||
intval($register[0]['uid'])
|
||||
);
|
||||
|
||||
if(! $account)
|
||||
if (! $account) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if(get_config('system','auto_channel_create'))
|
||||
if(get_config('system','auto_channel_create')) {
|
||||
auto_channel_create($register[0]['uid']);
|
||||
}
|
||||
else {
|
||||
$_SESSION['login_return_url'] = 'new_channel';
|
||||
authenticate_success($account[0],null,true,true,false,true);
|
||||
|
@ -612,20 +623,21 @@ function downgrade_accounts() {
|
|||
db_getfunc('UTC_TIMESTAMP')
|
||||
);
|
||||
|
||||
if(! $r)
|
||||
if (! $r) {
|
||||
return;
|
||||
}
|
||||
|
||||
$basic = get_config('system','default_service_class');
|
||||
|
||||
foreach($r as $rr) {
|
||||
if(($basic) && ($rr['account_service_class']) && ($rr['account_service_class'] != $basic)) {
|
||||
foreach ($r as $rr) {
|
||||
if (($basic) && ($rr['account_service_class']) && ($rr['account_service_class'] != $basic)) {
|
||||
$x = q("UPDATE account set account_service_class = '%s', account_expires = '%s'
|
||||
where account_id = %d",
|
||||
dbesc($basic),
|
||||
dbesc(NULL_DATE),
|
||||
intval($rr['account_id'])
|
||||
);
|
||||
$ret = array('account' => $rr);
|
||||
$ret = [ 'account' => $rr ];
|
||||
call_hooks('account_downgrade', $ret );
|
||||
logger('downgrade_accounts: Account id ' . $rr['account_id'] . ' downgraded.');
|
||||
}
|
||||
|
@ -634,7 +646,7 @@ function downgrade_accounts() {
|
|||
intval(ACCOUNT_EXPIRED),
|
||||
intval($rr['account_id'])
|
||||
);
|
||||
$ret = array('account' => $rr);
|
||||
$ret = [ 'account' => $rr ];
|
||||
call_hooks('account_downgrade', $ret);
|
||||
logger('downgrade_accounts: Account id ' . $rr['account_id'] . ' expired.');
|
||||
}
|
||||
|
@ -669,13 +681,14 @@ function downgrade_accounts() {
|
|||
function service_class_allows($uid, $property, $usage = false) {
|
||||
$limit = service_class_fetch($uid, $property);
|
||||
|
||||
if($limit === false)
|
||||
if ($limit === false) {
|
||||
return true; // No service class set => everything is allowed
|
||||
}
|
||||
|
||||
$limit = engr_units_to_bytes($limit);
|
||||
if($usage === false) {
|
||||
if ($usage === false) {
|
||||
// We use negative values for not allowed properties in a subscriber plan
|
||||
return ((x($limit)) ? (bool) $limit : true);
|
||||
return (($limit) ? (bool) $limit : true);
|
||||
} else {
|
||||
return (((intval($usage)) < intval($limit)) ? true : false);
|
||||
}
|
||||
|
@ -706,14 +719,15 @@ function account_service_class_allows($aid, $property, $usage = false) {
|
|||
|
||||
$limit = account_service_class_fetch($aid, $property);
|
||||
|
||||
if($limit === false)
|
||||
if ($limit === false) {
|
||||
return true; // No service class is set => everything is allowed
|
||||
}
|
||||
|
||||
$limit = engr_units_to_bytes($limit);
|
||||
|
||||
if($usage === false) {
|
||||
if ($usage === false) {
|
||||
// We use negative values for not allowed properties in a subscriber plan
|
||||
return ((x($limit)) ? (bool) $limit : true);
|
||||
return (($limit) ? (bool) $limit : true);
|
||||
} else {
|
||||
return (((intval($usage)) < intval($limit)) ? true : false);
|
||||
}
|
||||
|
@ -739,26 +753,27 @@ function account_service_class_allows($aid, $property, $usage = false) {
|
|||
function service_class_fetch($uid, $property) {
|
||||
|
||||
|
||||
if($uid == local_channel()) {
|
||||
if ($uid == local_channel()) {
|
||||
$service_class = App::$account['account_service_class'];
|
||||
}
|
||||
else {
|
||||
$r = q("select account_service_class as service_class
|
||||
from channel c, account a
|
||||
where c.channel_account_id=a.account_id and c.channel_id= %d limit 1",
|
||||
intval($uid)
|
||||
$r = q("select account_service_class
|
||||
from channel c, account a
|
||||
where c.channel_account_id = a.account_id and c.channel_id = %d limit 1",
|
||||
intval($uid)
|
||||
);
|
||||
if($r !== false and count($r)) {
|
||||
$service_class = $r[0]['service_class'];
|
||||
if ($r) {
|
||||
$service_class = $r[0]['account_service_class'];
|
||||
}
|
||||
}
|
||||
if(! x($service_class))
|
||||
if (! $service_class) {
|
||||
return false; // everything is allowed
|
||||
|
||||
}
|
||||
$arr = get_config('service_class', $service_class);
|
||||
|
||||
if(! is_array($arr) || (! count($arr)))
|
||||
if (! is_array($arr) || (! count($arr))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return((array_key_exists($property, $arr)) ? $arr[$property] : false);
|
||||
}
|
||||
|
|
|
@ -1118,7 +1118,9 @@ function bbcode($Text, $options = []) {
|
|||
if (strpos($Text,'[/url]') !== false) {
|
||||
// $Text = preg_replace("/\[url\]([$URLSearchString]*)\[\/url\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);
|
||||
// $Text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>', $Text);
|
||||
|
||||
$Text = preg_replace("/\[url\]([$URLSearchString]*)\[\/url\]/ism", '<a href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);
|
||||
$Text = preg_replace("/\@(\!?)\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '@$1<span class="h-card"><a class="u-url mention" href="$2" ' . $target . ' rel="nofollow noopener" >$3</a></span>', $Text);
|
||||
$Text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<a href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>', $Text);
|
||||
}
|
||||
|
||||
|
@ -1126,6 +1128,7 @@ function bbcode($Text, $options = []) {
|
|||
// $Text = preg_replace("/\#\^\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);
|
||||
// $Text = preg_replace("/\#\^\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>', $Text);
|
||||
$Text = preg_replace("/\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<a class="zrl" href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);
|
||||
$Text = preg_replace("/\@(\!?)\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '@$1<span class="h-card"><a class="zrl u-url mention" href="$2" ' . $target . ' rel="nofollow noopener" >$3</a></span>', $Text);
|
||||
$Text = preg_replace("/\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<a class="zrl" href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>', $Text);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ function abook_store_lowlevel($arr) {
|
|||
'abook_account' => ((array_key_exists('abook_account',$arr)) ? $arr['abook_account'] : 0),
|
||||
'abook_channel' => ((array_key_exists('abook_channel',$arr)) ? $arr['abook_channel'] : 0),
|
||||
'abook_xchan' => ((array_key_exists('abook_xchan',$arr)) ? $arr['abook_xchan'] : ''),
|
||||
'abook_alias' => ((array_key_exists('abook_alias',$arr)) ? $arr['abook_alias'] : ''),
|
||||
'abook_my_perms' => ((array_key_exists('abook_my_perms',$arr)) ? $arr['abook_my_perms'] : 0),
|
||||
'abook_their_perms' => ((array_key_exists('abook_their_perms',$arr)) ? $arr['abook_their_perms'] : 0),
|
||||
'abook_closeness' => ((array_key_exists('abook_closeness',$arr)) ? $arr['abook_closeness'] : 99),
|
||||
|
@ -40,31 +41,37 @@ function abook_store_lowlevel($arr) {
|
|||
|
||||
function rconnect_url($channel_id,$xchan) {
|
||||
|
||||
if(! $xchan)
|
||||
return '';
|
||||
if (! $xchan) {
|
||||
return EMPTY_STR;
|
||||
}
|
||||
|
||||
$r = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s' limit 1",
|
||||
intval($channel_id),
|
||||
dbesc($xchan)
|
||||
);
|
||||
|
||||
if($r)
|
||||
return '';
|
||||
// Already connected
|
||||
if ($r) {
|
||||
return EMPTY_STR;
|
||||
}
|
||||
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($xchan)
|
||||
);
|
||||
|
||||
if(($r) && ($r[0]['xchan_follow']))
|
||||
if (($r) && ($r[0]['xchan_follow'])) {
|
||||
return $r[0]['xchan_follow'];
|
||||
}
|
||||
|
||||
$r = q("select hubloc_url from hubloc where hubloc_hash = '%s' and hubloc_primary = 1 limit 1",
|
||||
dbesc($xchan)
|
||||
);
|
||||
|
||||
if($r)
|
||||
if ($r) {
|
||||
return $r[0]['hubloc_url'] . '/follow?f=&url=%s';
|
||||
return '';
|
||||
}
|
||||
|
||||
return EMPTY_STR;
|
||||
|
||||
}
|
||||
|
||||
|
@ -97,63 +104,67 @@ function abook_self($channel_id) {
|
|||
|
||||
function vcard_from_xchan($xchan, $observer = null, $mode = '') {
|
||||
|
||||
if(! $xchan) {
|
||||
if(App::$poi) {
|
||||
if (! $xchan) {
|
||||
if (App::$poi) {
|
||||
$xchan = App::$poi;
|
||||
}
|
||||
elseif(is_array(App::$profile) && App::$profile['channel_hash']) {
|
||||
elseif (is_array(App::$profile) && App::$profile['channel_hash']) {
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc(App::$profile['channel_hash'])
|
||||
);
|
||||
if($r)
|
||||
if($r) {
|
||||
$xchan = $r[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(! $xchan)
|
||||
if (! $xchan) {
|
||||
return;
|
||||
}
|
||||
|
||||
$connect = false;
|
||||
if(local_channel()) {
|
||||
if (local_channel()) {
|
||||
$r = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
|
||||
dbesc($xchan['xchan_hash']),
|
||||
intval(local_channel())
|
||||
);
|
||||
if(! $r)
|
||||
if (! $r) {
|
||||
$connect = t('Connect');
|
||||
}
|
||||
}
|
||||
|
||||
// don't provide a connect button for transient or one-way identities
|
||||
|
||||
if(in_array($xchan['xchan_network'],['rss','anon','unknown']) || strpos($xchan['xchan_addr'],'guest:') === 0) {
|
||||
if (in_array($xchan['xchan_network'],['rss','anon','unknown']) || strpos($xchan['xchan_addr'],'guest:') === 0) {
|
||||
$connect = false;
|
||||
}
|
||||
|
||||
if(array_key_exists('channel_id',$xchan))
|
||||
if (array_key_exists('channel_id',$xchan)) {
|
||||
App::$profile_uid = $xchan['channel_id'];
|
||||
}
|
||||
|
||||
$url = (($observer)
|
||||
? z_root() . '/magic?f=&owa=1&bdest=' . bin2hex($xchan['xchan_url']) . '&addr=' . $xchan['xchan_addr']
|
||||
: $xchan['xchan_url']
|
||||
);
|
||||
|
||||
return replace_macros(get_markup_template('xchan_vcard.tpl'),array(
|
||||
return replace_macros(get_markup_template('xchan_vcard.tpl'), [
|
||||
'$name' => $xchan['xchan_name'],
|
||||
'$photo' => ((is_array(App::$profile) && array_key_exists('photo',App::$profile)) ? App::$profile['photo'] : $xchan['xchan_photo_l']),
|
||||
'$follow' => (($xchan['xchan_addr']) ? $xchan['xchan_addr'] : $xchan['xchan_url']),
|
||||
'$follow' => urlencode(($xchan['xchan_addr']) ? $xchan['xchan_addr'] : $xchan['xchan_url']),
|
||||
'$link' => zid($xchan['xchan_url']),
|
||||
'$connect' => $connect,
|
||||
'$newwin' => (($mode === 'chanview') ? t('New window') : ''),
|
||||
'$newwin' => (($mode === 'chanview') ? t('New window') : EMPTY_STR),
|
||||
'$newtit' => t('Open the selected location in a different window or browser tab'),
|
||||
'$url' => $url,
|
||||
));
|
||||
]);
|
||||
}
|
||||
|
||||
function abook_toggle_flag($abook,$flag) {
|
||||
|
||||
$field = '';
|
||||
$field = EMPTY_STR;
|
||||
|
||||
switch($flag) {
|
||||
switch ($flag) {
|
||||
case ABOOK_FLAG_BLOCKED:
|
||||
$field = 'abook_blocked';
|
||||
break;
|
||||
|
@ -184,15 +195,15 @@ function abook_toggle_flag($abook,$flag) {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
if(! $field)
|
||||
if (! $field) {
|
||||
return;
|
||||
}
|
||||
|
||||
$r = q("UPDATE abook set $field = (1 - $field) where abook_id = %d and abook_channel = %d",
|
||||
intval($abook['abook_id']),
|
||||
intval($abook['abook_channel'])
|
||||
);
|
||||
|
||||
|
||||
// if unsetting the archive bit, update the timestamps so we'll try to connect for an additional 30 days.
|
||||
|
||||
if(($flag === ABOOK_FLAG_ARCHIVED) && (intval($abook['abook_archived']))) {
|
||||
|
@ -223,8 +234,9 @@ function abook_toggle_flag($abook,$flag) {
|
|||
function mark_orphan_hubsxchans() {
|
||||
|
||||
$dirmode = intval(get_config('system','directory_mode'));
|
||||
if($dirmode == DIRECTORY_MODE_NORMAL)
|
||||
if ($dirmode == DIRECTORY_MODE_NORMAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
$r = q("update hubloc set hubloc_deleted = 1 where hubloc_deleted = 0
|
||||
and hubloc_network = 'zot6' and hubloc_connected < %s - interval %s",
|
||||
|
@ -233,7 +245,7 @@ function mark_orphan_hubsxchans() {
|
|||
|
||||
$r = q("select hubloc_id, hubloc_hash from hubloc where hubloc_deleted = 1 and hubloc_orphancheck = 0");
|
||||
|
||||
if($r) {
|
||||
if ($r) {
|
||||
foreach($r as $rr) {
|
||||
|
||||
// see if any other hublocs are still alive for this channel
|
||||
|
@ -241,14 +253,13 @@ function mark_orphan_hubsxchans() {
|
|||
$x = q("select * from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0",
|
||||
dbesc($rr['hubloc_hash'])
|
||||
);
|
||||
if($x) {
|
||||
if ($x) {
|
||||
|
||||
// yes - if the xchan was marked as an orphan, undo it
|
||||
|
||||
$y = q("update xchan set xchan_orphan = 0 where xchan_orphan = 1 and xchan_hash = '%s'",
|
||||
dbesc($rr['hubloc_hash'])
|
||||
);
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
|
@ -277,7 +288,7 @@ function remove_all_xchan_resources($xchan, $channel_id = 0) {
|
|||
// $channel_id is reserved for future use.
|
||||
|
||||
|
||||
if(intval($channel_id) === 0) {
|
||||
if (intval($channel_id) === 0) {
|
||||
|
||||
if (! $xchan) {
|
||||
return;
|
||||
|
@ -487,9 +498,11 @@ function random_profile() {
|
|||
|
||||
$checkrandom = get_config('randprofile','check'); // False by default
|
||||
$retryrandom = intval(get_config('randprofile','retry'));
|
||||
if($retryrandom == 0) $retryrandom = 5;
|
||||
if ($retryrandom == 0) {
|
||||
$retryrandom = 5;
|
||||
}
|
||||
|
||||
for($i = 0; $i < $retryrandom; $i++) {
|
||||
for ($i = 0; $i < $retryrandom; $i++) {
|
||||
|
||||
$r = q("select xchan_url, xchan_hash from xchan left join hubloc on hubloc_hash = xchan_hash where
|
||||
xchan_hidden = 0 and xchan_system = 0 and
|
||||
|
@ -499,21 +512,24 @@ function random_profile() {
|
|||
db_quoteinterval('30 day')
|
||||
);
|
||||
|
||||
if(!$r) return ''; // Couldn't get a random channel
|
||||
|
||||
if($checkrandom) {
|
||||
if (!$r) {
|
||||
return EMPTY_STR; // Couldn't get a random channel
|
||||
}
|
||||
if ($checkrandom) {
|
||||
$x = z_fetch_url($r[0]['xchan_url']);
|
||||
if($x['success'])
|
||||
if ($x['success']) {
|
||||
return $r[0]['xchan_hash'];
|
||||
else
|
||||
}
|
||||
else {
|
||||
logger('Random channel turned out to be bad.');
|
||||
}
|
||||
}
|
||||
else {
|
||||
return $r[0]['xchan_hash'];
|
||||
}
|
||||
|
||||
}
|
||||
return '';
|
||||
return EMPTY_STR;
|
||||
}
|
||||
|
||||
function update_vcard($arr,$vcard = null) {
|
||||
|
@ -535,7 +551,7 @@ function update_vcard($arr,$vcard = null) {
|
|||
// right is to provide a form to input all the various fields and not
|
||||
// try to extract it from the FN.
|
||||
|
||||
if(! $vcard) {
|
||||
if (! $vcard) {
|
||||
$vcard = new \Sabre\VObject\Component\VCard([
|
||||
'FN' => $fn,
|
||||
'N' => array_reverse(explode(' ', $fn))
|
||||
|
|
|
@ -1478,22 +1478,49 @@ function jot_collections($channel,$collections) {
|
|||
|
||||
}
|
||||
|
||||
function get_item_children($arr, $parent) {
|
||||
$children = array();
|
||||
foreach($arr as $item) {
|
||||
if($item['id'] != $item['parent']) {
|
||||
if(get_config('system','thread_allow',true)) {
|
||||
// Fallback to parent_mid if thr_parent is not set
|
||||
$thr_parent = $item['thr_parent'];
|
||||
if($thr_parent === '')
|
||||
$thr_parent = $item['parent_mid'];
|
||||
|
||||
if($thr_parent === $parent['mid']) {
|
||||
$item['children'] = get_item_children($arr, $item);
|
||||
function get_item_children($arr, $parent) {
|
||||
|
||||
$children = [];
|
||||
if (! $arr) {
|
||||
return $children;
|
||||
}
|
||||
|
||||
$thread_allow = get_config('system','thread_allow',true);
|
||||
$thread_max = intval(get_config('system','thread_maxlevel',2));
|
||||
|
||||
foreach ($arr as $item) {
|
||||
if (intval($item['id']) !== intval($item['parent'])) {
|
||||
if ($thread_allow) {
|
||||
|
||||
$thr_parent = $item['thr_parent'];
|
||||
|
||||
// Fallback to parent_mid if thr_parent is not set
|
||||
if ($thr_parent === EMPTY_STR) {
|
||||
$thr_parent = $item['parent_mid'];
|
||||
}
|
||||
|
||||
if ($thr_parent === $parent['mid']) {
|
||||
$my_children = get_item_children($arr, $item);
|
||||
if ($item['item_level'] > $thread_max) {
|
||||
// Like and Dislike activities are allowed as children of the last supported level.
|
||||
// After that they are ignored.
|
||||
// Any other children deeper than $thread_max are flattened.
|
||||
if(in_array($item['verb'], [ 'Like','Dislike' ])) {
|
||||
if ($item['item_level'] > ($thread_max + 1)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$children = (($my_children) ? array_merge($children,$my_children) : $children);
|
||||
}
|
||||
else {
|
||||
$item['children'] = $my_children;
|
||||
}
|
||||
$children[] = $item;
|
||||
}
|
||||
}
|
||||
else if($item['parent'] == $parent['id']) {
|
||||
elseif (intval($item['parent']) === intval($parent['id'])) {
|
||||
// threads are disabled. Anything that is in this conversation gets added to children.
|
||||
$children[] = $item;
|
||||
}
|
||||
}
|
||||
|
@ -1513,100 +1540,61 @@ function sort_item_children($items) {
|
|||
}
|
||||
|
||||
function add_children_to_list($children, &$arr) {
|
||||
foreach($children as $y) {
|
||||
foreach ($children as $y) {
|
||||
$arr[] = $y;
|
||||
if($y['children'])
|
||||
if ($y['children']) {
|
||||
add_children_to_list($y['children'], $arr);
|
||||
}
|
||||
}
|
||||
|
||||
function flatten_conversation($parent) {
|
||||
if (!isset($parent['children']) || count($parent['children']) == 0) {
|
||||
return $parent;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < count($parent['children']); $i++) {
|
||||
$child = $parent['children'][$i];
|
||||
|
||||
if (isset($child['children']) && count($child['children'])) {
|
||||
// This helps counting only the regular posts
|
||||
$count_post_closure = function($var) {
|
||||
return in_array($var['verb'], ['Create','Update'] );
|
||||
};
|
||||
|
||||
$child_post_count = count(array_filter($child['children'], $count_post_closure));
|
||||
|
||||
$remaining_post_count = count(array_filter(array_slice($parent['children'], $i), $count_post_closure));
|
||||
|
||||
// If there's only one child's children post and this is the last child post
|
||||
if ($child_post_count == 1 && $remaining_post_count == 1) {
|
||||
|
||||
// Searches the post item in the children
|
||||
$j = 0;
|
||||
while((! in_array($child['children'][$j]['verb'], ['Create','Update' ])) && $j < count($child['children'])) {
|
||||
$j ++;
|
||||
}
|
||||
|
||||
$moved_item = $child['children'][$j];
|
||||
unset($parent['children'][$i]['children'][$j]);
|
||||
$parent['children'][] = $moved_item;
|
||||
} else {
|
||||
$parent['children'][$i] = flatten_conversation($child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $parent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function conv_sort($arr, $order) {
|
||||
|
||||
if((!(is_array($arr) && count($arr))))
|
||||
return array();
|
||||
$parents = [];
|
||||
$ret = [];
|
||||
|
||||
$parents = array();
|
||||
if (! (is_array($arr) && count($arr))) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
foreach($arr as $x) {
|
||||
if($x['id'] == $x['parent']) {
|
||||
$parents[] = $x;
|
||||
foreach ($arr as $x) {
|
||||
if (intval($x['id']) === intval($x['parent'])) {
|
||||
$parents[] = $x;
|
||||
}
|
||||
}
|
||||
|
||||
if(stristr($order,'created'))
|
||||
if (stristr($order,'created')) {
|
||||
usort($parents,'sort_thr_created');
|
||||
elseif(stristr($order,'commented'))
|
||||
}
|
||||
elseif (stristr($order,'commented')) {
|
||||
usort($parents,'sort_thr_commented');
|
||||
elseif(stristr($order,'updated'))
|
||||
}
|
||||
elseif (stristr($order,'updated')) {
|
||||
usort($parents,'sort_thr_updated');
|
||||
elseif(stristr($order,'ascending'))
|
||||
}
|
||||
elseif (stristr($order,'ascending')) {
|
||||
usort($parents,'sort_thr_created_rev');
|
||||
}
|
||||
|
||||
|
||||
if(count($parents))
|
||||
foreach($parents as $i=>$_x)
|
||||
if ($parents) {
|
||||
foreach ($parents as $i => $_x) {
|
||||
$parents[$i]['children'] = get_item_children($arr, $_x);
|
||||
}
|
||||
|
||||
if(count($parents)) {
|
||||
foreach($parents as $k => $v) {
|
||||
if(count($parents[$k]['children'])) {
|
||||
foreach ($parents as $k => $v) {
|
||||
if ($parents[$k]['children']) {
|
||||
$parents[$k]['children'] = sort_item_children($parents[$k]['children']);
|
||||
}
|
||||
}
|
||||
|
||||
// foreach ($parents as $i => $parent) {
|
||||
// $parents[$i] = flatten_conversation($parent);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
$ret = array();
|
||||
if(count($parents)) {
|
||||
foreach($parents as $x) {
|
||||
if ($parents) {
|
||||
foreach ($parents as $x) {
|
||||
$ret[] = $x;
|
||||
if(count($x['children']))
|
||||
if ($x['children']) {
|
||||
add_children_to_list($x['children'], $ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1713,119 +1701,6 @@ function prepare_page($item) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
function network_tabs() {
|
||||
|
||||
$no_active='';
|
||||
$starred_active = '';
|
||||
$new_active = '';
|
||||
$all_active = '';
|
||||
$search_active = '';
|
||||
$conv_active = '';
|
||||
$spam_active = '';
|
||||
$postord_active = '';
|
||||
|
||||
if(x($_GET,'new')) {
|
||||
$new_active = 'active';
|
||||
}
|
||||
|
||||
if(x($_GET,'search')) {
|
||||
$search_active = 'active';
|
||||
}
|
||||
|
||||
if(x($_GET,'star')) {
|
||||
$starred_active = 'active';
|
||||
}
|
||||
|
||||
if(x($_GET,'conv')) {
|
||||
$conv_active = 'active';
|
||||
}
|
||||
|
||||
if(x($_GET,'spam')) {
|
||||
$spam_active = 'active';
|
||||
}
|
||||
|
||||
if (($new_active == '')
|
||||
&& ($starred_active == '')
|
||||
&& ($conv_active == '')
|
||||
&& ($search_active == '')
|
||||
&& ($spam_active == '')) {
|
||||
$no_active = 'active';
|
||||
}
|
||||
|
||||
if ($no_active=='active' && x($_GET,'order')) {
|
||||
switch($_GET['order']){
|
||||
case 'post': $postord_active = 'active'; $no_active=''; break;
|
||||
case 'comment' : $all_active = 'active'; $no_active=''; break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($no_active=='active') $all_active='active';
|
||||
|
||||
$cmd = App::$cmd;
|
||||
|
||||
// tabs
|
||||
$tabs = array();
|
||||
|
||||
$tabs[] = array(
|
||||
'label' => t('Commented Order'),
|
||||
'url'=>z_root() . '/' . $cmd . '?f=&order=comment' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''),
|
||||
'sel'=>$all_active,
|
||||
'title'=> t('Sort by Comment Date'),
|
||||
);
|
||||
|
||||
$tabs[] = array(
|
||||
'label' => t('Posted Order'),
|
||||
'url'=>z_root() . '/' . $cmd . '?f=&order=post' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''),
|
||||
'sel'=>$postord_active,
|
||||
'title' => t('Sort by Post Date'),
|
||||
);
|
||||
|
||||
if(feature_enabled(local_channel(),'personal_tab')) {
|
||||
$tabs[] = array(
|
||||
'label' => t('Personal'),
|
||||
'url' => z_root() . '/' . $cmd . '?f=' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . '&conv=1',
|
||||
'sel' => $conv_active,
|
||||
'title' => t('Posts that mention or involve you'),
|
||||
);
|
||||
}
|
||||
|
||||
if(feature_enabled(local_channel(),'new_tab')) {
|
||||
$tabs[] = array(
|
||||
'label' => t('New'),
|
||||
'url' => z_root() . '/' . $cmd . '?f=' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . '&new=1' . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''),
|
||||
'sel' => $new_active,
|
||||
'title' => t('Activity Stream - by date'),
|
||||
);
|
||||
}
|
||||
|
||||
if(feature_enabled(local_channel(),'star_posts')) {
|
||||
$tabs[] = array(
|
||||
'label' => t('Starred'),
|
||||
'url'=>z_root() . '/' . $cmd . '/?f=' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . '&star=1',
|
||||
'sel'=>$starred_active,
|
||||
'title' => t('Favourite Posts'),
|
||||
);
|
||||
}
|
||||
// Not yet implemented
|
||||
|
||||
if(feature_enabled(local_channel(),'spam_filter')) {
|
||||
$tabs[] = array(
|
||||
'label' => t('Spam'),
|
||||
'url'=> z_root() . '/network?f=&spam=1',
|
||||
'sel'=> $spam_active,
|
||||
'title' => t('Posts flagged as SPAM'),
|
||||
);
|
||||
}
|
||||
|
||||
$arr = array('tabs' => $tabs);
|
||||
call_hooks('network_tabs', $arr);
|
||||
|
||||
$tpl = get_markup_template('common_tabs.tpl');
|
||||
|
||||
return replace_macros($tpl, array('$tabs' => $arr['tabs']));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
|
|
|
@ -1064,7 +1064,8 @@ function event_store_item($arr, $event) {
|
|||
$x = [
|
||||
'type' => 'Event',
|
||||
'id' => z_root() . '/event/' . $r[0]['resource_id'],
|
||||
'summary' => bbcode($arr['summary']),
|
||||
'name' => $arr['summary'],
|
||||
// 'summary' => bbcode($arr['summary']),
|
||||
// RFC3339 Section 4.3
|
||||
'startTime' => (($arr['adjust']) ? datetime_convert('UTC','UTC',$arr['dtstart'], ATOM_TIME) : datetime_convert('UTC','UTC',$arr['dtstart'],'Y-m-d\\TH:i:s-00:00')),
|
||||
'content' => bbcode($arr['description']),
|
||||
|
@ -1217,7 +1218,8 @@ function event_store_item($arr, $event) {
|
|||
$y = [
|
||||
'type' => 'Event',
|
||||
'id' => z_root() . '/event/' . $event['event_hash'],
|
||||
'summary' => bbcode($arr['summary']),
|
||||
'name' => $arr['summary'],
|
||||
// 'summary' => bbcode($arr['summary']),
|
||||
// RFC3339 Section 4.3
|
||||
'startTime' => (($arr['adjust']) ? datetime_convert('UTC','UTC',$arr['dtstart'], ATOM_TIME) : datetime_convert('UTC','UTC',$arr['dtstart'],'Y-m-d\\TH:i:s-00:00')),
|
||||
'content' => bbcode($arr['description']),
|
||||
|
|
|
@ -59,7 +59,7 @@ function get_features($filtered = true, $level = (-1)) {
|
|||
'start_menu',
|
||||
t('New Member Links'),
|
||||
t('Display new member quick links menu'),
|
||||
(($account['account_created'] > datetime_convert('','','now - 60 days')) ? true : false),
|
||||
(($account['account_created'] > datetime_convert('','','now - 30 days')) ? true : false),
|
||||
get_config('feature_lock','start_menu'),
|
||||
feature_level('start_menu',1),
|
||||
],
|
||||
|
|
|
@ -45,8 +45,18 @@ function import_channel($channel, $account_id, $seize, $newname = '') {
|
|||
dbesc($channel['channel_hash']),
|
||||
dbesc($channel['channel_address'])
|
||||
);
|
||||
if ($r && $r[0]['channel_guid'] == $channel['channel_guid'] && $r[0]['channel_pubkey'] === $channel['channel_pubkey'] && $r[0]['channel_hash'] === $channel['channel_hash'])
|
||||
if ($r && $r[0]['channel_guid'] == $channel['channel_guid'] && $r[0]['channel_pubkey'] === $channel['channel_pubkey'] && $r[0]['channel_hash'] === $channel['channel_hash']) {
|
||||
// do not return a dead or deleted or system channel
|
||||
if ($r[0]['channel_deleted'] > NULL_DATE
|
||||
|| intval($r[0]['channel_removed'])
|
||||
|| intval($r[0]['channel_moved'])
|
||||
|| intval($r[0]['channel_system'])) {
|
||||
logger('attempt to import to a channel that was removed. ', print_r($channel,true));
|
||||
notice( t('A channel with these settings was discovered and is not usable as it was removed or reserved for system use. Import failed.') . EOL);
|
||||
return false;
|
||||
}
|
||||
return $r[0];
|
||||
}
|
||||
|
||||
if (($r) || (check_webbie(array($channel['channel_address'])) !== $channel['channel_address'])) {
|
||||
if ($r[0]['channel_guid'] === $channel['channel_guid'] || $r[0]['channel_hash'] === $channel['channel_hash']) {
|
||||
|
|
|
@ -1659,6 +1659,7 @@ function item_store($arr, $allow_exec = false, $deliver = true, $linkid = true)
|
|||
$arr['plink'] = ((x($arr,'plink')) ? notags(trim($arr['plink'])) : '');
|
||||
$arr['attach'] = ((x($arr,'attach')) ? notags(trim($arr['attach'])) : '');
|
||||
$arr['app'] = ((x($arr,'app')) ? notags(trim($arr['app'])) : '');
|
||||
$arr['replyto'] = ((x($arr,'replyto')) ? serialise($arr['replyto']) : '');
|
||||
|
||||
$arr['public_policy'] = '';
|
||||
|
||||
|
@ -2139,6 +2140,7 @@ function item_store_update($arr, $allow_exec = false, $deliver = true, $linkid =
|
|||
$arr['tgt_type'] = ((x($arr,'tgt_type')) ? notags(trim($arr['tgt_type'])) : $orig[0]['tgt_type']);
|
||||
$arr['target'] = ((x($arr,'target')) ? trim($arr['target']) : $orig[0]['target']);
|
||||
$arr['plink'] = ((x($arr,'plink')) ? notags(trim($arr['plink'])) : $orig[0]['plink']);
|
||||
$arr['replyto'] = ((x($arr,'replyto')) ? serialise($arr['replyto']) : $orig[0]['replyto']);
|
||||
|
||||
$arr['allow_cid'] = ((array_key_exists('allow_cid',$arr)) ? trim($arr['allow_cid']) : $orig[0]['allow_cid']);
|
||||
$arr['allow_gid'] = ((array_key_exists('allow_gid',$arr)) ? trim($arr['allow_gid']) : $orig[0]['allow_gid']);
|
||||
|
@ -2872,7 +2874,7 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $edit = false)
|
|||
}
|
||||
|
||||
// @todo handle edit and parent correctly
|
||||
|
||||
// @fixme nomadic needs changing to whether or not activitypub is in effect
|
||||
if((! $parent) && (! defined('NOMADIC'))) {
|
||||
|
||||
if($edit) {
|
||||
|
@ -3846,7 +3848,7 @@ function zot_feed($uid, $observer_hash, $arr) {
|
|||
$nonsys_uids = q("SELECT channel_id FROM channel WHERE channel_system = 0");
|
||||
$nonsys_uids_str = ids_to_querystr($nonsys_uids,'channel_id');
|
||||
|
||||
$r = q("SELECT parent, postopts FROM item
|
||||
$r = q("SELECT parent FROM item
|
||||
WHERE uid IN ( %s )
|
||||
AND item_private = 0
|
||||
$item_normal
|
||||
|
@ -3855,7 +3857,7 @@ function zot_feed($uid, $observer_hash, $arr) {
|
|||
);
|
||||
}
|
||||
else {
|
||||
$r = q("SELECT parent, postopts FROM item
|
||||
$r = q("SELECT parent FROM item
|
||||
WHERE uid = %d
|
||||
$item_normal
|
||||
$sql_extra ORDER BY created ASC $limit",
|
||||
|
@ -3869,8 +3871,6 @@ function zot_feed($uid, $observer_hash, $arr) {
|
|||
foreach($r as $rv) {
|
||||
if(array_key_exists($rv['parent'],$parents))
|
||||
continue;
|
||||
if(strpos($rv['postopts'],'nodeliver') !== false)
|
||||
continue;
|
||||
$parents[$rv['parent']] = $rv;
|
||||
if(count($parents) > 200)
|
||||
break;
|
||||
|
|
|
@ -590,51 +590,6 @@ function validate_email($addr) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check $url against our list of allowed sites.
|
||||
*
|
||||
* Wildcards allowed. If allowed_sites is unset return true.
|
||||
*
|
||||
* @param string $url
|
||||
* @return boolean Return true if url is allowed, otherwise return false
|
||||
*/
|
||||
function allowed_url($url) {
|
||||
|
||||
$h = @parse_url($url);
|
||||
|
||||
if(! $h) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$str_allowed = get_config('system', 'allowed_sites');
|
||||
if(! $str_allowed)
|
||||
return true;
|
||||
|
||||
$found = false;
|
||||
|
||||
$host = strtolower($h['host']);
|
||||
|
||||
// always allow our own site
|
||||
|
||||
if($host == strtolower($_SERVER['SERVER_NAME']))
|
||||
return true;
|
||||
|
||||
$fnmatch = function_exists('fnmatch');
|
||||
$allowed = explode(',',$str_allowed);
|
||||
|
||||
if(count($allowed)) {
|
||||
foreach($allowed as $a) {
|
||||
$pat = strtolower(trim($a));
|
||||
if(($fnmatch && fnmatch($pat,$host)) || ($pat == $host)) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $found;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if email address is allowed to register here.
|
||||
*
|
||||
|
@ -1719,7 +1674,7 @@ function check_siteallowed($url) {
|
|||
|
||||
$retvalue = true;
|
||||
|
||||
$arr = array('url' => $url);
|
||||
$arr = [ 'url' => $url ];
|
||||
/**
|
||||
* @hooks check_siteallowed
|
||||
* Used to over-ride or bypass the site black/white block lists.
|
||||
|
@ -1728,24 +1683,27 @@ function check_siteallowed($url) {
|
|||
*/
|
||||
call_hooks('check_siteallowed', $arr);
|
||||
|
||||
if(array_key_exists('allowed',$arr))
|
||||
if (array_key_exists('allowed',$arr)) {
|
||||
return $arr['allowed'];
|
||||
}
|
||||
|
||||
$bl1 = get_config('system','whitelisted_sites');
|
||||
if(is_array($bl1) && $bl1) {
|
||||
foreach($bl1 as $bl) {
|
||||
if($bl === '*')
|
||||
if (is_array($bl1) && $bl1) {
|
||||
foreach ($bl1 as $bl) {
|
||||
if ($bl === '*') {
|
||||
$retvalue = true;
|
||||
if($bl && strpos($url,$bl) !== false)
|
||||
}
|
||||
if ($bl && strpos($url,$bl) !== false)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
$bl1 = get_config('system','blacklisted_sites');
|
||||
if(is_array($bl1) && $bl1) {
|
||||
foreach($bl1 as $bl) {
|
||||
if($bl === '*')
|
||||
if (is_array($bl1) && $bl1) {
|
||||
foreach ($bl1 as $bl) {
|
||||
if ($bl === '*') {
|
||||
$retvalue = false;
|
||||
if($bl && strpos($url,$bl) !== false) {
|
||||
}
|
||||
if ($bl && strpos($url,$bl) !== false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1811,7 +1769,7 @@ function check_channelallowed($hash) {
|
|||
|
||||
$retvalue = true;
|
||||
|
||||
$arr = array('hash' => $hash);
|
||||
$arr = [ 'hash' => $hash ];
|
||||
/**
|
||||
* @hooks check_channelallowed
|
||||
* Used to over-ride or bypass the channel black/white block lists.
|
||||
|
@ -1820,24 +1778,28 @@ function check_channelallowed($hash) {
|
|||
*/
|
||||
call_hooks('check_channelallowed', $arr);
|
||||
|
||||
if(array_key_exists('allowed',$arr))
|
||||
if (array_key_exists('allowed',$arr)) {
|
||||
return $arr['allowed'];
|
||||
}
|
||||
|
||||
$bl1 = get_config('system','whitelisted_channels');
|
||||
if(is_array($bl1) && $bl1) {
|
||||
foreach($bl1 as $bl) {
|
||||
if($bl === '*')
|
||||
if (is_array($bl1) && $bl1) {
|
||||
foreach ($bl1 as $bl) {
|
||||
if ($bl === '*') {
|
||||
$retvalue = true;
|
||||
if($bl && strpos($hash,$bl) !== false)
|
||||
}
|
||||
if ($bl && strpos($hash,$bl) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
$bl1 = get_config('system','blacklisted_channels');
|
||||
if(is_array($bl1) && $bl1) {
|
||||
foreach($bl1 as $bl) {
|
||||
if($bl === '*')
|
||||
if (is_array($bl1) && $bl1) {
|
||||
foreach ($bl1 as $bl) {
|
||||
if ($bl === '*') {
|
||||
$retvalue = false;
|
||||
if($bl && strpos($hash,$bl) !== false) {
|
||||
}
|
||||
if ($bl && strpos($hash,$bl) !== false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1631,7 +1631,7 @@ function prepare_body(&$item,$attach = false,$opts = false) {
|
|||
|
||||
function separate_img_links($s) {
|
||||
$x = preg_replace('/\<a (.*?)\>\<img(.*?)\>\<\/a\>/ism',
|
||||
'<img$2><br><a $1>' . t('Link') . '</a>',$s);
|
||||
'<img$2><br><a $1>' . t('Link') . '</a><br>',$s);
|
||||
return $x;
|
||||
}
|
||||
|
||||
|
@ -2127,6 +2127,7 @@ function trim_and_unpunify($s) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Fetches xchan and hubloc data for an array of items with only an
|
||||
* author_xchan and owner_xchan.
|
||||
|
|
|
@ -17,6 +17,7 @@ CREATE TABLE IF NOT EXISTS `abook` (
|
|||
`abook_account` int(10) unsigned NOT NULL DEFAULT 0 ,
|
||||
`abook_channel` int(10) unsigned NOT NULL DEFAULT 0 ,
|
||||
`abook_xchan` char(191) NOT NULL DEFAULT '',
|
||||
`abook_alias` char(191) NOT NULL DEFAULT '',
|
||||
`abook_my_perms` int(11) NOT NULL DEFAULT 0 ,
|
||||
`abook_their_perms` int(11) NOT NULL DEFAULT 0 ,
|
||||
`abook_closeness` tinyint(3) unsigned NOT NULL DEFAULT 99,
|
||||
|
@ -44,6 +45,7 @@ CREATE TABLE IF NOT EXISTS `abook` (
|
|||
KEY `abook_account` (`abook_account`),
|
||||
KEY `abook_channel` (`abook_channel`),
|
||||
KEY `abook_xchan` (`abook_xchan`),
|
||||
KEY `abook_alias` (`abook_alias`),
|
||||
KEY `abook_my_perms` (`abook_my_perms`),
|
||||
KEY `abook_their_perms` (`abook_their_perms`),
|
||||
KEY `abook_closeness` (`abook_closeness`),
|
||||
|
@ -584,6 +586,7 @@ CREATE TABLE IF NOT EXISTS `item` (
|
|||
`author_xchan` char(191) NOT NULL DEFAULT '',
|
||||
`source_xchan` char(191) NOT NULL DEFAULT '',
|
||||
`mimetype` char(191) NOT NULL DEFAULT '',
|
||||
`replyto` text NOT NULL,
|
||||
`title` text NOT NULL,
|
||||
`summary` mediumtext NOT NULL,
|
||||
`body` mediumtext NOT NULL,
|
||||
|
|
|
@ -16,6 +16,7 @@ CREATE TABLE "abook" (
|
|||
"abook_account" bigint NOT NULL,
|
||||
"abook_channel" bigint NOT NULL,
|
||||
"abook_xchan" text NOT NULL DEFAULT '',
|
||||
"abook_alias" text NOT NULL DEFAULT '',
|
||||
"abook_my_perms" bigint NOT NULL,
|
||||
"abook_their_perms" bigint NOT NULL,
|
||||
"abook_closeness" numeric(3) NOT NULL DEFAULT '99',
|
||||
|
@ -44,6 +45,7 @@ CREATE TABLE "abook" (
|
|||
create index "abook_account" on abook ("abook_account");
|
||||
create index "abook_channel" on abook ("abook_channel");
|
||||
create index "abook_xchan" on abook ("abook_xchan");
|
||||
create index "abook_alias" on abook ("abook_alias");
|
||||
create index "abook_my_perms" on abook ("abook_my_perms");
|
||||
create index "abook_their_perms" on abook ("abook_their_perms");
|
||||
create index "abook_closeness" on abook ("abook_closeness");
|
||||
|
@ -572,6 +574,7 @@ CREATE TABLE "item" (
|
|||
"author_xchan" text NOT NULL DEFAULT '',
|
||||
"source_xchan" text NOT NULL DEFAULT '',
|
||||
"mimetype" text NOT NULL DEFAULT '',
|
||||
"replyto" text NOT NULL,
|
||||
"title" text NOT NULL,
|
||||
"summary" text NOT NULL,
|
||||
"body" text NOT NULL,
|
||||
|
|
313
util/zotsh/zotsh-py3.py
Executable file
313
util/zotsh/zotsh-py3.py
Executable file
|
@ -0,0 +1,313 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys, os
|
||||
import configparser
|
||||
import requests
|
||||
from requests.auth import HTTPBasicAuth
|
||||
import easywebdav
|
||||
import easywebdav.__version__ as easywebdavversion
|
||||
import base64
|
||||
|
||||
__version__= "0.0.2"
|
||||
|
||||
SERVER = None
|
||||
USER = None
|
||||
PASSWD = None
|
||||
VERIFY_SSL=True
|
||||
|
||||
#####################################################
|
||||
|
||||
class CommandNotFound(Exception):
|
||||
pass
|
||||
|
||||
class ZotSH(object):
|
||||
commands = ['cd','ls','exists','mkdir','mkdirs','rmdir','delete','upload','download',
|
||||
'host', 'pwd','cat',
|
||||
'lcd','lpwd', 'lls',
|
||||
'quit', 'help']
|
||||
def __init__(self, host, session=None, davclient=None):
|
||||
self.sessions = {}
|
||||
self.host = host
|
||||
self.session = session
|
||||
self.davclient = davclient
|
||||
|
||||
|
||||
@property
|
||||
def host(self):
|
||||
return self._host
|
||||
|
||||
@host.setter
|
||||
def host(self, host):
|
||||
self._host = host
|
||||
self._hostname = host.replace("https:","").replace("/","")
|
||||
|
||||
@property
|
||||
def hostname(self):
|
||||
return self._hostname
|
||||
|
||||
@hostname.setter
|
||||
def hostname(self, hostname):
|
||||
self._host = "https://%s/" % (hostname)
|
||||
self._hostname = hostname
|
||||
|
||||
@property
|
||||
def session(self):
|
||||
return self._session
|
||||
|
||||
@session.setter
|
||||
def session(self, session):
|
||||
self._session = session
|
||||
self.davclient = easywebdav.connect( self.hostname, protocol='https', session=session, path="dav", verify_ssl=VERIFY_SSL)
|
||||
|
||||
@property
|
||||
def PS1(self):
|
||||
if self.davclient is None:
|
||||
return "[!]> "
|
||||
return "%s:%s> " % (self.hostname, self.davclient.cwd)
|
||||
|
||||
def get_host_session(self, host=None):
|
||||
#~ if host is None:
|
||||
#~ host = self.host
|
||||
#~ if not host.startswith("https"):
|
||||
#~ host = "https://%s/" % (host)
|
||||
#~ if host in self.sessions:
|
||||
#~ session = self.sessions[host]
|
||||
#~ else:
|
||||
#~ session = requests.Session()
|
||||
#~ self.sessions[host] = session
|
||||
#~ if not host == SERVER
|
||||
#~ session.params.update({'davguest':1})
|
||||
#~ return session
|
||||
|
||||
if self.session is None:
|
||||
session = requests.Session()
|
||||
#session.params.update({'davguest':1})
|
||||
else:
|
||||
session = self.session
|
||||
#session.params.update({'davguest': (not host == SERVER) })
|
||||
return session
|
||||
|
||||
def do(self, command, *args):
|
||||
if not command in self.commands:
|
||||
raise CommandNotFound("Unknown command '%s'" % command)
|
||||
|
||||
cmd = getattr(self, "cmd_%s"%command, None)
|
||||
if cmd is None:
|
||||
cmd = getattr(self.davclient, command)
|
||||
|
||||
return cmd(*args)
|
||||
|
||||
def cmd_exists(self, *args):
|
||||
if (len(args)==0):
|
||||
return
|
||||
return self.davclient.exists(args[0])
|
||||
|
||||
def cmd_mkdir(self, *args):
|
||||
if (len(args)==0):
|
||||
return
|
||||
return self.davclient.mkdir(args[0])
|
||||
|
||||
def cmd_mkdirs(self, *args):
|
||||
if (len(args)==0):
|
||||
return
|
||||
return self.davclient.mkdirs(args[0])
|
||||
|
||||
def cmd_rmdir(self, *args):
|
||||
if (len(args)==0):
|
||||
return
|
||||
return self.davclient.rmdir(args[0])
|
||||
|
||||
def cmd_delete(self, *args):
|
||||
if (len(args)==0):
|
||||
return
|
||||
return self.davclient.delete(args[0])
|
||||
|
||||
def cmd_upload(self, *args):
|
||||
if (len(args)==0):
|
||||
return
|
||||
args = list(args)
|
||||
if (len(args)==1):
|
||||
args.append(args[0])
|
||||
|
||||
return self.davclient.upload(args[0], args[1])
|
||||
|
||||
def cmd_download(self, *args):
|
||||
if (len(args)==0):
|
||||
return
|
||||
args = list(args)
|
||||
if (len(args)==1):
|
||||
args.append(args[0])
|
||||
|
||||
return self.davclient.download(args[0], args[1])
|
||||
|
||||
def cmd_host(self, *args):
|
||||
if (len(args)==0):
|
||||
return
|
||||
newhostname = args[0]
|
||||
newhost = "https://%s/" % newhostname
|
||||
if newhostname == "~" or newhost == SERVER:
|
||||
# bach to home server
|
||||
self.host = SERVER
|
||||
self.session = self.get_host_session(SERVER)
|
||||
return
|
||||
|
||||
session_remote = self.get_host_session(newhost)
|
||||
session_home = self.get_host_session(SERVER)
|
||||
|
||||
bnewhost = newhost + 'dav'
|
||||
bnewhost = bnewhost.encode('hex')
|
||||
|
||||
r = session_home.get(
|
||||
SERVER + "magic",
|
||||
params={'bdest': bnewhost, 'owa': 1},
|
||||
allow_redirects=True,
|
||||
verify=VERIFY_SSL )
|
||||
|
||||
self.hostname = newhostname
|
||||
self.session = session_remote
|
||||
|
||||
|
||||
def cmd_pwd(self, *args):
|
||||
return "%s%s" % ( self.davclient.baseurl, self.davclient.cwd )
|
||||
|
||||
def cmd_ls(self, *args):
|
||||
extra_args = ["-a", "-l", "-d"]
|
||||
|
||||
show_hidden = "-a" in args
|
||||
show_list = "-l" in args
|
||||
show_only_dir = "-d" in args
|
||||
args = [ a for a in args if not a in extra_args ]
|
||||
|
||||
|
||||
r = self.davclient.ls(*args)
|
||||
l = max([ len(str(f.size)) for f in r ] + [7,])
|
||||
|
||||
def _fmt(type, size, name):
|
||||
if show_list:
|
||||
return "%s %*d %s" % (type, l, f.size , name)
|
||||
else:
|
||||
return name
|
||||
|
||||
if show_hidden :
|
||||
print(_fmt('d', 0, "./"))
|
||||
if self.davclient.cwd!="/":
|
||||
print(_fmt('d', 0, "../"))
|
||||
|
||||
for f in r:
|
||||
name = f.name.replace("/dav"+self.davclient.cwd,"")
|
||||
type = "-"
|
||||
if name.endswith("/"):
|
||||
type = "d"
|
||||
if name!="":
|
||||
if show_hidden or not name.startswith("."):
|
||||
if not show_only_dir or type=="d":
|
||||
print(_fmt(type, f.size , name))
|
||||
|
||||
def cmd_lpwd(self, *args):
|
||||
return os.getcwd()
|
||||
|
||||
def cmd_lcd(self, *args):
|
||||
if (len(args)==0):
|
||||
return
|
||||
os.chdir(args[0])
|
||||
|
||||
def cmd_lls(self, *args):
|
||||
for f in os.listdir(os.getcwd()):
|
||||
if os.path.isdir(f):
|
||||
f=f+"/"
|
||||
print(f)
|
||||
|
||||
def cmd_help(self, *args):
|
||||
print("ZotSH",__version__)
|
||||
print()
|
||||
print("Commands:")
|
||||
for c in self.commands:
|
||||
print("\t",c)
|
||||
print()
|
||||
print("easywebdav", easywebdavversion.__version__, "(mod)")
|
||||
print("requests", requests.__version__)
|
||||
|
||||
def cmd_cat(self,*args):
|
||||
if (len(args)==0):
|
||||
return
|
||||
rfile = args[0]
|
||||
resp = self.davclient._send('GET', rfile, (200,))
|
||||
print(resp.text)
|
||||
|
||||
def load_conf():
|
||||
global SERVER,USER,PASSWD,VERIFY_SSL
|
||||
homedir = os.getenv("HOME")
|
||||
if homedir is None:
|
||||
homedir = os.path.join(os.getenv("HOMEDRIVE"), os.getenv("HOMEPATH"))
|
||||
|
||||
optsfile = ".zotshrc"
|
||||
if not os.path.isfile(optsfile):
|
||||
optsfile = os.path.join(homedir, ".zotshrc")
|
||||
|
||||
if not os.path.isfile(optsfile):
|
||||
print("Please create a configuration file called '.zotshrc':")
|
||||
print("[zotsh]")
|
||||
print("host = https://yourhost.com/")
|
||||
print("username = your_username")
|
||||
print("password = your_password")
|
||||
sys.exit(-1)
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.read(optsfile)
|
||||
SERVER = config.get('zotsh', 'host')
|
||||
USER = config.get('zotsh', 'username')
|
||||
PASSWD = config.get('zotsh', 'password')
|
||||
if config.has_option('zotsh', 'verify_ssl'):
|
||||
VERIFY_SSL = config.getboolean('zotsh', 'verify_ssl')
|
||||
|
||||
|
||||
def zotsh():
|
||||
|
||||
zotsh = ZotSH( SERVER)
|
||||
|
||||
session_home = zotsh.get_host_session()
|
||||
|
||||
#~ #login on home server
|
||||
print("loggin in...")
|
||||
r = session_home.get(
|
||||
SERVER + "api/account/verify_credentials",
|
||||
auth=HTTPBasicAuth(USER, PASSWD),
|
||||
verify=VERIFY_SSL )
|
||||
|
||||
print("Hi", r.json()['name'])
|
||||
|
||||
zotsh.session = session_home
|
||||
|
||||
# command loop
|
||||
inputs = input(zotsh.PS1)
|
||||
while (inputs != "quit"):
|
||||
inputs = inputs.strip()
|
||||
if len(inputs)>0:
|
||||
toks = [ x.strip() for x in inputs.split(" ") ]
|
||||
|
||||
command = toks[0]
|
||||
args = toks[1:]
|
||||
try:
|
||||
ret = zotsh.do(command, *args)
|
||||
except easywebdav.client.OperationFailed as e:
|
||||
print(e)
|
||||
except CommandNotFound as e:
|
||||
print(e)
|
||||
else:
|
||||
if ret is not None:
|
||||
print(ret)
|
||||
|
||||
|
||||
inputs = input(zotsh.PS1)
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
load_conf()
|
||||
zotsh()
|
||||
sys.exit()
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
|
||||
import sys, os
|
||||
import ConfigParser
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
/**
|
||||
* Redbasic
|
||||
*
|
||||
* Based on duepuntozero Friendica style
|
||||
* Originally by Fabio Comuni <fabrix.xm@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
|
@ -31,6 +29,13 @@ html {
|
|||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.zrl:hover {
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
.threadlevel {
|
||||
margin-right: 0.1rem;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 0.9rem;
|
||||
|
|
|
@ -77,6 +77,25 @@
|
|||
<input type="hidden" name="section" value="{{$section}}">
|
||||
|
||||
<div class="panel-group" id="contact-edit-tools" role="tablist" aria-multiselectable="true">
|
||||
|
||||
<div class="panel">
|
||||
<div class="section-subtitle-wrapper" role="tab" id="alias-tool">
|
||||
<h3>
|
||||
<a data-toggle="collapse" data-parent="#contact-edit-tools" href="#alias-tool-collapse" aria-expanded="true" aria-controls="alias-tool-collapse">
|
||||
{{$alias_label}}
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
<div id="alias-tool-collapse" class="panel-collapse collapse show" role="tabpanel" aria-labelledby="alias-tool">
|
||||
<div class="section-content-tools-wrapper">
|
||||
{{include file="field_input.tpl" field=$alias}}
|
||||
<div class="settings-submit-wrapper" >
|
||||
<button type="submit" name="done" value="{{$submit}}" class="btn btn-primary">{{$submit}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if $notself}}
|
||||
|
||||
{{if $is_pending}}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
{{/if}}
|
||||
{{if $item.title && !$item.event}}
|
||||
<div class="p-2{{if $item.is_new}} bg-primary text-white{{/if}} wall-item-title h3{{if !$item.photo}} rounded-top{{/if}}" id="wall-item-title-{{$item.id}}">
|
||||
{{if $item.title_tosource}}{{if $item.plink}}<a href="{{$item.plink.href}}" title="{{$item.title}} ({{$item.plink.title}})">{{/if}}{{/if}}{{$item.title}}{{if $item.title_tosource}}{{if $item.plink}}</a>{{/if}}{{/if}}
|
||||
{{if $item.title_tosource}}{{if $item.plink}}<a href="{{$item.plink.href}}" title="{{$item.title}} ({{$item.plink.title}})" rel="nofollow noopener">{{/if}}{{/if}}{{$item.title}}{{if $item.title_tosource}}{{if $item.plink}}</a>{{/if}}{{/if}}
|
||||
</div>
|
||||
{{if ! $item.is_new}}
|
||||
<hr class="m-0">
|
||||
|
@ -104,7 +104,7 @@
|
|||
<i class="fa fa-thumbs-o-down{{if $item.my_responses.dislike}} ivoted{{/if}}" ></i>
|
||||
</button>
|
||||
{{/if}}
|
||||
{{if $item.comment && $item.thread_level > 1 && $item.thread_level < 3}}
|
||||
{{if $item.comment && $item.thread_level > 1 && $item.thread_level < $item.thread_max }}
|
||||
<button type="button" title="{{$item.comment_lbl}}" class="btn btn-outline-secondary btn-sm" onclick="openClose('wall-item-comment-wrapper-{{$item.id}}'); $('#comment-edit-text-{{$item.id}}').click(); return false;">
|
||||
<i class="fa fa-comment-o"></i>
|
||||
</button>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
{{/if}}
|
||||
{{if $item.title && !$item.event}}
|
||||
<div class="p-2{{if $item.is_new}} bg-primary text-white{{/if}} wall-item-title h3{{if !$item.photo}} rounded-top{{/if}}" id="wall-item-title-{{$item.id}}">
|
||||
{{if $item.title_tosource}}{{if $item.plink}}<a href="{{$item.plink.href}}" title="{{$item.title}} ({{$item.plink.title}})">{{/if}}{{/if}}{{$item.title}}{{if $item.title_tosource}}{{if $item.plink}}</a>{{/if}}{{/if}}
|
||||
{{if $item.title_tosource}}{{if $item.plink}}<a href="{{$item.plink.href}}" title="{{$item.title}} ({{$item.plink.title}})" rel="nofollow noopener">{{/if}}{{/if}}{{$item.title}}{{if $item.title_tosource}}{{if $item.plink}}</a>{{/if}}{{/if}}
|
||||
</div>
|
||||
{{if ! $item.is_new}}
|
||||
<hr class="m-0">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div id="vcard" class="vcard h-card">
|
||||
<div id="profile-photo-wrapper"><a href="{{$link}}"><img class="vcard-photo photo u-photo" src="{{$photo}}" alt="{{$name}}" /></a></div>
|
||||
{{if $connect}}
|
||||
<div class="connect-btn-wrapper"><a href="follow?f=&url={{$follow}}" class="btn btn-block btn-success btn-sm"><i class="fa fa-plus"></i> {{$connect}}</a></div>
|
||||
<div class="connect-btn-wrapper"><a href="follow?f=&url={{$follow}}" rel="nofollow noopener" class="btn btn-block btn-success btn-sm"><i class="fa fa-plus"></i> {{$connect}}</a></div>
|
||||
{{/if}}
|
||||
<div class="fn p-name">{{$name}}</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue