2018-07-03 23:40:54 +00:00
< ? php
namespace Zotlabs\Lib ;
use Zotlabs\Lib\Libsync ;
2019-02-14 23:26:37 +00:00
class AccessList {
2018-07-03 23:40:54 +00:00
static function add ( $uid , $name , $public = 0 ) {
$ret = false ;
2019-10-02 00:44:58 +00:00
if ( $uid && $name ) {
2018-07-03 23:40:54 +00:00
$r = self :: byname ( $uid , $name ); // check for dups
2019-10-02 00:44:58 +00:00
if ( $r !== false ) {
2018-07-03 23:40:54 +00:00
// This could be a problem.
2019-02-14 23:26:37 +00:00
// Let's assume we've just created a list which we once deleted
// all the old members are gone, but the list remains so we don't break any security
// access lists. What we're doing here is reviving the dead list, but old content which
// was restricted to this list may now be seen by the new list members.
2018-07-03 23:40:54 +00:00
2018-09-26 00:47:43 +00:00
$z = q ( " SELECT * FROM pgrp WHERE id = %d LIMIT 1 " ,
2018-07-03 23:40:54 +00:00
intval ( $r )
);
if (( $z ) && $z [ 0 ][ 'deleted' ]) {
2018-09-26 00:47:43 +00:00
q ( 'UPDATE pgrp SET deleted = 0 WHERE id = %d' , intval ( $z [ 0 ][ 'id' ]));
2019-02-14 23:26:37 +00:00
notice ( t ( 'A deleted list with this name was revived. Existing item permissions <strong>may</strong> apply to this list and any future members. If this is not what you intended, please create another list with a different name.' ) . EOL );
2018-07-03 23:40:54 +00:00
}
2021-03-05 22:37:41 +00:00
$hash = self :: by_id ( $uid , $r );
return $hash ;
2018-07-03 23:40:54 +00:00
}
2019-10-02 00:44:58 +00:00
$hash = new_uuid ();
2018-07-03 23:40:54 +00:00
2020-07-22 01:16:27 +00:00
$r = q ( " INSERT INTO pgrp ( hash, uid, visible, gname, rule )
VALUES ( '%s' , % d , % d , '%s' , '' ) " ,
2018-07-03 23:40:54 +00:00
dbesc ( $hash ),
intval ( $uid ),
intval ( $public ),
dbesc ( $name )
);
$ret = $r ;
}
Libsync :: build_sync_packet ( $uid , null , true );
2021-03-05 22:37:41 +00:00
return (( $ret ) ? $hash : $ret );
2018-07-03 23:40:54 +00:00
}
static function remove ( $uid , $name ) {
$ret = false ;
2019-11-04 05:38:19 +00:00
if ( $uid && $name ) {
2018-09-26 00:47:43 +00:00
$r = q ( " SELECT id, hash FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1 " ,
2018-07-03 23:40:54 +00:00
intval ( $uid ),
dbesc ( $name )
);
2019-11-04 05:38:19 +00:00
if ( $r ) {
2018-07-03 23:40:54 +00:00
$group_id = $r [ 0 ][ 'id' ];
$group_hash = $r [ 0 ][ 'hash' ];
}
2019-11-04 05:38:19 +00:00
else {
2018-07-03 23:40:54 +00:00
return false ;
2019-11-04 05:38:19 +00:00
}
2018-07-03 23:40:54 +00:00
// remove group from default posting lists
$r = q ( " SELECT channel_default_group, channel_allow_gid, channel_deny_gid FROM channel WHERE channel_id = %d LIMIT 1 " ,
intval ( $uid )
);
2019-11-04 05:38:19 +00:00
if ( $r ) {
$user_info = array_shift ( $r );
2018-07-03 23:40:54 +00:00
$change = false ;
2019-11-04 05:38:19 +00:00
if ( $user_info [ 'channel_default_group' ] == $group_hash ) {
2018-07-03 23:40:54 +00:00
$user_info [ 'channel_default_group' ] = '' ;
$change = true ;
}
2019-11-04 05:38:19 +00:00
if ( strpos ( $user_info [ 'channel_allow_gid' ], '<' . $group_hash . '>' ) !== false ) {
2018-07-03 23:40:54 +00:00
$user_info [ 'channel_allow_gid' ] = str_replace ( '<' . $group_hash . '>' , '' , $user_info [ 'channel_allow_gid' ]);
$change = true ;
}
2019-11-04 05:38:19 +00:00
if ( strpos ( $user_info [ 'channel_deny_gid' ], '<' . $group_hash . '>' ) !== false ) {
2018-07-03 23:40:54 +00:00
$user_info [ 'channel_deny_gid' ] = str_replace ( '<' . $group_hash . '>' , '' , $user_info [ 'channel_deny_gid' ]);
$change = true ;
}
2019-11-04 05:38:19 +00:00
if ( $change ) {
2018-07-03 23:40:54 +00:00
q ( " UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s'
WHERE channel_id = % d " ,
intval ( $user_info [ 'channel_default_group' ]),
dbesc ( $user_info [ 'channel_allow_gid' ]),
dbesc ( $user_info [ 'channel_deny_gid' ]),
intval ( $uid )
);
}
}
// remove all members
2018-09-26 00:47:43 +00:00
$r = q ( " DELETE FROM pgrp_member WHERE uid = %d AND gid = %d " ,
2018-07-03 23:40:54 +00:00
intval ( $uid ),
intval ( $group_id )
);
// remove group
2018-09-26 00:47:43 +00:00
$r = q ( " UPDATE pgrp SET deleted = 1 WHERE uid = %d AND gname = '%s' " ,
2018-07-03 23:40:54 +00:00
intval ( $uid ),
dbesc ( $name )
);
$ret = $r ;
}
Libsync :: build_sync_packet ( $uid , null , true );
return $ret ;
}
2019-10-24 22:53:44 +00:00
// returns the integer id of an access group owned by $uid and named $name
// or false.
2018-07-03 23:40:54 +00:00
static function byname ( $uid , $name ) {
2019-11-04 05:38:19 +00:00
if ( ! ( $uid && $name )) {
2018-07-03 23:40:54 +00:00
return false ;
2019-11-04 05:38:19 +00:00
}
$r = q ( " SELECT id FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1 " ,
2018-07-03 23:40:54 +00:00
intval ( $uid ),
dbesc ( $name )
);
2019-11-04 05:38:19 +00:00
if ( $r ) {
2018-07-03 23:40:54 +00:00
return $r [ 0 ][ 'id' ];
2019-11-04 05:38:19 +00:00
}
2018-07-03 23:40:54 +00:00
return false ;
}
2019-04-17 06:31:36 +00:00
static function by_id ( $uid , $id ) {
2019-11-04 05:38:19 +00:00
if ( ! ( $uid && $id )) {
2019-04-17 06:31:36 +00:00
return false ;
}
$r = q ( " SELECT * FROM pgrp WHERE uid = %d AND id = %d and deleted = 0 " ,
intval ( $uid ),
intval ( $id )
);
2019-11-04 05:38:19 +00:00
if ( $r ) {
2019-04-17 06:31:36 +00:00
return array_shift ( $r );
}
return false ;
}
2018-07-03 23:40:54 +00:00
static function rec_byhash ( $uid , $hash ) {
2019-11-04 05:38:19 +00:00
if ( ! ( $uid && $hash )) {
2018-07-03 23:40:54 +00:00
return false ;
2019-11-04 05:38:19 +00:00
}
2018-09-26 00:47:43 +00:00
$r = q ( " SELECT * FROM pgrp WHERE uid = %d AND hash = '%s' LIMIT 1 " ,
2018-07-03 23:40:54 +00:00
intval ( $uid ),
dbesc ( $hash )
);
2019-11-04 05:38:19 +00:00
if ( $r ) {
return array_shift ( $r );
}
2018-07-03 23:40:54 +00:00
return false ;
}
static function member_remove ( $uid , $name , $member ) {
$gid = self :: byname ( $uid , $name );
2019-11-04 05:38:19 +00:00
if ( ! $gid ) {
2018-07-03 23:40:54 +00:00
return false ;
2019-11-04 05:38:19 +00:00
}
if ( ! ( $uid && $gid && $member )) {
2018-07-03 23:40:54 +00:00
return false ;
2019-11-04 05:38:19 +00:00
}
2018-09-26 00:47:43 +00:00
$r = q ( " DELETE FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' " ,
2018-07-03 23:40:54 +00:00
intval ( $uid ),
intval ( $gid ),
dbesc ( $member )
);
Libsync :: build_sync_packet ( $uid , null , true );
return $r ;
}
static function member_add ( $uid , $name , $member , $gid = 0 ) {
2019-11-04 05:38:19 +00:00
if ( ! $gid ) {
2018-07-03 23:40:54 +00:00
$gid = self :: byname ( $uid , $name );
2019-11-04 05:38:19 +00:00
}
if ( ! ( $gid && $uid && $member )) {
2018-07-03 23:40:54 +00:00
return false ;
2019-11-04 05:38:19 +00:00
}
2018-07-03 23:40:54 +00:00
2018-09-26 00:47:43 +00:00
$r = q ( " SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1 " ,
2018-07-03 23:40:54 +00:00
intval ( $uid ),
intval ( $gid ),
dbesc ( $member )
);
2019-11-04 05:38:19 +00:00
if ( $r ) {
2018-07-03 23:40:54 +00:00
return true ; // You might question this, but
// we indicate success because the group member was in fact created
// -- It was just created at another time
2019-11-04 05:38:19 +00:00
}
else {
2018-09-26 00:47:43 +00:00
$r = q ( " INSERT INTO pgrp_member (uid, gid, xchan)
2018-07-03 23:40:54 +00:00
VALUES ( % d , % d , '%s' ) " ,
intval ( $uid ),
intval ( $gid ),
dbesc ( $member )
2019-11-04 05:38:19 +00:00
);
}
2018-07-03 23:40:54 +00:00
Libsync :: build_sync_packet ( $uid , null , true );
return $r ;
}
2020-08-07 06:22:24 +00:00
static function members ( $uid , $gid , $total = false , $start = 0 , $records = 0 ) {
2019-11-04 05:38:19 +00:00
$ret = [];
2020-08-07 06:22:24 +00:00
if ( $records ) {
$pager_sql = sprintf ( " LIMIT %d OFFSET %d " , intval ( $records ), intval ( $start ));
}
2020-10-11 22:41:49 +00:00
// process virtual groups
if ( strpos ( $gid , ':' ) === 0 ) {
$vg = substr ( $gid , 1 );
switch ( $vg ) {
case '1' :
$sql_extra = EMPTY_STR ;
break ;
case '2' :
$sql_extra = " and xchan_network = 'zot6' " ;
break ;
case '3' :
$sql_extra = " and xchan_network = 'activitypub' " ;
break ;
default :
break ;
}
if ( $total ) {
$r = q ( " SELECT count(*) FROM abook left join xchan on xchan_hash = abook_xchan WHERE abook_channel = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 $sql_extra ORDER BY xchan_name ASC $pager_sql " ,
intval ( $uid )
);
return ( $r ) ? $r [ 0 ][ 'total' ] : false ;
2020-10-11 23:07:28 +00:00
}
2020-10-11 22:41:49 +00:00
$r = q ( " SELECT * FROM abook left join xchan on xchan_hash = abook_xchan
WHERE abook_channel = % d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 $sql_extra ORDER BY xchan_name ASC $pager_sql " ,
intval ( $uid )
);
2020-10-11 23:07:28 +00:00
if ( $r ) {
for ( $x = 0 ; $x < count ( $r ); $x ++ ) {
$r [ $x ][ 'xchan' ] = $r [ $x ][ 'abook_xchan' ];
}
}
2020-10-11 22:41:49 +00:00
return $r ;
}
2019-11-04 05:38:19 +00:00
if ( intval ( $gid )) {
2020-08-07 06:22:24 +00:00
if ( $total ) {
$r = q ( " SELECT count(xchan) as total FROM pgrp_member
LEFT JOIN abook ON abook_xchan = pgrp_member . xchan left join xchan on xchan_hash = abook_xchan
WHERE gid = % d AND abook_channel = % d and pgrp_member . uid = % d and xchan_deleted = 0 and abook_self = 0
and abook_blocked = 0 and abook_pending = 0 " ,
intval ( $gid ),
intval ( $uid ),
intval ( $uid )
);
if ( $r ) {
return $r [ 0 ][ 'total' ];
}
}
2018-09-26 00:47:43 +00:00
$r = q ( " SELECT * FROM pgrp_member
LEFT JOIN abook ON abook_xchan = pgrp_member . xchan left join xchan on xchan_hash = abook_xchan
2020-08-07 06:22:24 +00:00
WHERE gid = % d AND abook_channel = % d and pgrp_member . uid = % d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC $pager_sql " ,
2018-07-03 23:40:54 +00:00
intval ( $gid ),
2019-10-02 01:29:39 +00:00
intval ( $uid ),
intval ( $uid )
2018-07-03 23:40:54 +00:00
);
2019-11-04 05:38:19 +00:00
if ( $r ) {
2018-07-03 23:40:54 +00:00
$ret = $r ;
2019-11-04 05:38:19 +00:00
}
2018-07-03 23:40:54 +00:00
}
return $ret ;
}
2019-10-02 01:29:39 +00:00
static function members_xchan ( $uid , $gid ) {
2018-07-03 23:40:54 +00:00
$ret = [];
2019-11-04 05:38:19 +00:00
if ( intval ( $gid )) {
2018-09-26 00:47:43 +00:00
$r = q ( " SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d " ,
2018-07-03 23:40:54 +00:00
intval ( $gid ),
2019-10-02 01:29:39 +00:00
intval ( $uid )
2018-07-03 23:40:54 +00:00
);
2019-11-04 05:38:19 +00:00
if ( $r ) {
foreach ( $r as $rv ) {
$ret [] = $rv [ 'xchan' ];
2018-07-03 23:40:54 +00:00
}
}
}
return $ret ;
}
static function select ( $uid , $group = '' ) {
$grps = [];
2018-09-26 00:47:43 +00:00
$r = q ( " SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC " ,
2018-07-03 23:40:54 +00:00
intval ( $uid )
);
2019-11-04 05:38:19 +00:00
$grps [] = [ 'name' => '' , 'hash' => '0' , 'selected' => '' ];
if ( $r ) {
foreach ( $r as $rr ) {
$grps [] = [ 'name' => $rr [ 'gname' ], 'id' => $rr [ 'hash' ], 'selected' => (( $group == $rr [ 'hash' ]) ? 'true' : '' ) ];
2018-07-03 23:40:54 +00:00
}
}
2019-11-04 05:38:19 +00:00
return replace_macros ( get_markup_template ( 'group_selection.tpl' ), [
2019-02-14 23:26:37 +00:00
'$label' => t ( 'Add new connections to this access list' ),
2018-07-03 23:40:54 +00:00
'$groups' => $grps
2019-11-04 05:38:19 +00:00
]);
2018-07-03 23:40:54 +00:00
}
2019-10-02 02:03:48 +00:00
static function widget ( $every = " connections " , $each = " lists " , $edit = false , $group_id = 0 , $cid = '' , $mode = 1 ) {
2018-07-03 23:40:54 +00:00
$o = '' ;
2018-09-14 04:25:37 +00:00
$groups = [];
2018-07-03 23:40:54 +00:00
2018-09-26 00:47:43 +00:00
$r = q ( " SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC " ,
2018-07-03 23:40:54 +00:00
intval ( $_SESSION [ 'uid' ])
);
2018-09-14 04:25:37 +00:00
$member_of = [];
2019-11-04 05:38:19 +00:00
if ( $cid ) {
2018-07-03 23:40:54 +00:00
$member_of = self :: containing ( local_channel (), $cid );
}
2019-11-04 05:38:19 +00:00
if ( $r ) {
foreach ( $r as $rr ) {
2018-07-03 23:40:54 +00:00
$selected = (( $group_id == $rr [ 'id' ]) ? ' group-selected' : '' );
if ( $edit ) {
2019-10-02 00:44:58 +00:00
$groupedit = [ 'href' => " lists/ " . $rr [ 'id' ], 'title' => t ( 'edit' ) ];
2018-07-03 23:40:54 +00:00
}
else {
$groupedit = null ;
}
$groups [] = [
'id' => $rr [ 'id' ],
'enc_cid' => base64url_encode ( $cid ),
'cid' => $cid ,
'text' => $rr [ 'gname' ],
'selected' => $selected ,
'href' => (( $mode == 0 ) ? $each . '?f=&gid=' . $rr [ 'id' ] : $each . " / " . $rr [ 'id' ]) . (( x ( $_GET , 'new' )) ? '&new=' . $_GET [ 'new' ] : '' ) . (( x ( $_GET , 'order' )) ? '&order=' . $_GET [ 'order' ] : '' ),
'edit' => $groupedit ,
'ismember' => in_array ( $rr [ 'id' ], $member_of ),
];
}
}
2019-11-04 05:38:19 +00:00
return replace_macros ( get_markup_template ( 'group_side.tpl' ), [
2019-10-02 00:44:58 +00:00
'$title' => t ( 'Lists' ),
2019-02-14 23:26:37 +00:00
'$edittext' => t ( 'Edit list' ),
'$createtext' => t ( 'Create new list' ),
'$ungrouped' => (( $every === 'contacts' ) ? t ( 'Channels not in any access list' ) : '' ),
2018-07-03 23:40:54 +00:00
'$groups' => $groups ,
'$add' => t ( 'add' ),
2019-11-04 05:38:19 +00:00
]);
2018-07-03 23:40:54 +00:00
}
static function expand ( $g ) {
2019-11-04 05:38:19 +00:00
if ( ! ( is_array ( $g ) && count ( $g ))) {
return [];
}
2018-07-03 23:40:54 +00:00
$ret = [];
$x = [];
2019-11-04 05:38:19 +00:00
foreach ( $g as $gv ) {
2020-09-22 00:26:27 +00:00
// virtual access lists
// connections:abc is all the connection sof the channel with channel_hash abc
// zot:abc is all of abc's zot6 connections
// activitypub:abc is all of abc's activitypub connections
if ( strpos ( $gv , 'connections:' ) === 0 || strpos ( $gv , 'zot:' ) === 0 || strpos ( $gv , 'activitypub:' ) === 0 ) {
$sql_extra = EMPTY_STR ;
$channel_hash = substr ( $gv , strpos ( $gv , ':' ) + 1 );
if ( strpos ( $gv , 'zot:' ) === 0 ) {
$sql_extra = " and xchan_network = 'zot6' " ;
}
if ( strpos ( $gv , 'activitypub:' ) === 0 ) {
$sql_extra = " and xchan_network = 'activitypub' " ;
}
$r = q ( " select channel_id from channel where channel_hash = '%s' " ,
dbesc ( $channel_hash )
);
if ( $r ) {
foreach ( $r as $rv ) {
$y = q ( " select abook_xchan 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 $sql_extra " ,
intval ( $rv [ 'channel_id' ])
);
if ( $y ) {
foreach ( $y as $yv ) {
$ret [] = $yv [ 'abook_xchan' ];
}
}
}
}
}
else {
$x [] = $gv ;
}
2018-07-03 23:40:54 +00:00
}
2019-11-04 05:38:19 +00:00
if ( $x ) {
2018-07-03 23:40:54 +00:00
stringify_array_elms ( $x , true );
$groups = implode ( ',' , $x );
2019-11-04 05:38:19 +00:00
if ( $groups ) {
2018-09-26 00:47:43 +00:00
$r = q ( " SELECT xchan FROM pgrp_member WHERE gid IN ( select id from pgrp where hash in ( $groups )) " );
2019-11-04 05:38:19 +00:00
if ( $r ) {
foreach ( $r as $rv ) {
$ret [] = $rv [ 'xchan' ];
2018-07-03 23:40:54 +00:00
}
}
2020-09-22 00:26:27 +00:00
2018-07-03 23:40:54 +00:00
}
}
return $ret ;
}
static function member_of ( $c ) {
2019-11-04 05:38:19 +00:00
$r = q ( " SELECT pgrp.gname, pgrp.id FROM pgrp LEFT JOIN pgrp_member ON pgrp_member.gid = pgrp.id
WHERE pgrp_member . xchan = '%s' AND pgrp . deleted = 0 ORDER BY pgrp . gname ASC " ,
2018-07-03 23:40:54 +00:00
dbesc ( $c )
);
return $r ;
}
static function containing ( $uid , $c ) {
2018-09-26 00:47:43 +00:00
$r = q ( " SELECT gid FROM pgrp_member WHERE uid = %d AND pgrp_member.xchan = '%s' " ,
2018-07-03 23:40:54 +00:00
intval ( $uid ),
dbesc ( $c )
);
2019-11-04 05:38:19 +00:00
$ret = [];
if ( $r ) {
foreach ( $r as $rv )
$ret [] = $rv [ 'gid' ];
2018-07-03 23:40:54 +00:00
}
2019-11-04 05:38:19 +00:00
2018-07-03 23:40:54 +00:00
return $ret ;
}
}