2021-12-03 03:01:39 +00:00
< ? php
2018-07-03 23:40:54 +00:00
2022-02-16 04:08:28 +00:00
namespace Code\Lib ;
2018-07-03 23:40:54 +00:00
2023-11-09 20:40:16 +00:00
use App ;
2022-02-16 04:08:28 +00:00
use Code\Render\Theme ;
2022-02-12 20:43:29 +00:00
2018-07-03 23:40:54 +00:00
2021-12-02 23:02:31 +00:00
class AccessList
{
public static function add ( $uid , $name , $public = 0 )
{
$ret = false ;
2022-08-23 10:15:05 +00:00
$hash = new_uuid ();
2021-12-02 23:02:31 +00:00
if ( $uid && $name ) {
$r = self :: byname ( $uid , $name ); // check for dups
if ( $r !== false ) {
// This could be a problem.
2022-08-21 07:36:09 +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
2021-12-02 23:02:31 +00:00
// 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.
2021-12-03 03:01:39 +00:00
$z = q (
" SELECT * FROM pgrp WHERE id = %d LIMIT 1 " ,
2021-12-02 23:02:31 +00:00
intval ( $r )
);
if (( $z ) && $z [ 0 ][ 'deleted' ]) {
q ( 'UPDATE pgrp SET deleted = 0 WHERE id = %d' , intval ( $z [ 0 ][ 'id' ]));
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 );
}
2022-08-23 10:15:05 +00:00
return self :: by_id ( $uid , $r );
2021-12-02 23:02:31 +00:00
}
2021-12-03 03:01:39 +00:00
$r = q (
" INSERT INTO pgrp ( hash, uid, visible, gname, rule )
2022-07-21 07:25:07 +00:00
VALUES ( '%s' , % d , % d , '%s' , '' ) " ,
2021-12-02 23:02:31 +00:00
dbesc ( $hash ),
intval ( $uid ),
intval ( $public ),
dbesc ( $name )
);
$ret = $r ;
}
Libsync :: build_sync_packet ( $uid , null , true );
return (( $ret ) ? $hash : $ret );
}
2022-08-24 19:37:45 +00:00
public static function remove ( $uid , $name ) : bool
2021-12-02 23:02:31 +00:00
{
$ret = false ;
if ( $uid && $name ) {
2021-12-03 03:01:39 +00:00
$r = q (
" SELECT id, hash FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1 " ,
2021-12-02 23:02:31 +00:00
intval ( $uid ),
dbesc ( $name )
);
if ( $r ) {
$group_id = $r [ 0 ][ 'id' ];
$group_hash = $r [ 0 ][ 'hash' ];
} else {
return false ;
}
// remove group from default posting lists
2021-12-03 03:01:39 +00:00
$r = q (
" SELECT channel_default_group, channel_allow_gid, channel_deny_gid FROM channel WHERE channel_id = %d LIMIT 1 " ,
2021-12-02 23:02:31 +00:00
intval ( $uid )
);
if ( $r ) {
$user_info = array_shift ( $r );
$change = false ;
2022-03-17 05:14:45 +00:00
if ( $user_info [ 'channel_default_group' ] === $group_hash ) {
2021-12-02 23:02:31 +00:00
$user_info [ 'channel_default_group' ] = '' ;
$change = true ;
}
2022-08-27 04:01:22 +00:00
if ( str_contains ( $user_info [ 'channel_allow_gid' ], '<' . $group_hash . '>' )) {
2021-12-02 23:02:31 +00:00
$user_info [ 'channel_allow_gid' ] = str_replace ( '<' . $group_hash . '>' , '' , $user_info [ 'channel_allow_gid' ]);
$change = true ;
}
2022-08-27 04:01:22 +00:00
if ( str_contains ( $user_info [ 'channel_deny_gid' ], '<' . $group_hash . '>' )) {
2021-12-02 23:02:31 +00:00
$user_info [ 'channel_deny_gid' ] = str_replace ( '<' . $group_hash . '>' , '' , $user_info [ 'channel_deny_gid' ]);
$change = true ;
}
if ( $change ) {
2021-12-03 03:01:39 +00:00
q (
2022-07-21 07:25:07 +00:00
" UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s'
WHERE channel_id = % d " ,
2022-03-17 05:14:45 +00:00
dbesc ( $user_info [ 'channel_default_group' ]),
2021-12-02 23:02:31 +00:00
dbesc ( $user_info [ 'channel_allow_gid' ]),
dbesc ( $user_info [ 'channel_deny_gid' ]),
intval ( $uid )
);
}
}
// remove all members
2021-12-03 03:01:39 +00:00
$r = q (
" DELETE FROM pgrp_member WHERE uid = %d AND gid = %d " ,
2021-12-02 23:02:31 +00:00
intval ( $uid ),
intval ( $group_id )
);
// remove group
2021-12-03 03:01:39 +00:00
$r = q (
" UPDATE pgrp SET deleted = 1 WHERE uid = %d AND gname = '%s' " ,
2021-12-02 23:02:31 +00:00
intval ( $uid ),
dbesc ( $name )
);
2022-08-24 19:37:45 +00:00
$ret = ( bool ) $r ;
2021-12-02 23:02:31 +00:00
}
Libsync :: build_sync_packet ( $uid , null , true );
return $ret ;
}
// returns the integer id of an access group owned by $uid and named $name
// or false.
2022-08-23 10:15:05 +00:00
public static function byname ( $uid , $name ) : mixed
2021-12-02 23:02:31 +00:00
{
if ( ! ( $uid && $name )) {
return false ;
}
2021-12-03 03:01:39 +00:00
$r = q (
" SELECT id FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1 " ,
2021-12-02 23:02:31 +00:00
intval ( $uid ),
dbesc ( $name )
);
if ( $r ) {
return $r [ 0 ][ 'id' ];
}
return false ;
}
2023-08-17 11:16:29 +00:00
public static function hashbyname ( $uid , $name ) : mixed
{
if ( ! ( $uid && $name )) {
return false ;
}
$r = q (
" SELECT hash FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1 " ,
intval ( $uid ),
dbesc ( $name )
);
if ( $r ) {
return $r [ 0 ][ 'hash' ];
}
return false ;
}
2022-08-23 10:15:05 +00:00
public static function by_id ( $uid , $id ) : mixed
2021-12-02 23:02:31 +00:00
{
if ( ! ( $uid && $id )) {
return false ;
}
2021-12-03 03:01:39 +00:00
$r = q (
" SELECT * FROM pgrp WHERE uid = %d AND id = %d and deleted = 0 " ,
2021-12-02 23:02:31 +00:00
intval ( $uid ),
intval ( $id )
);
if ( $r ) {
return array_shift ( $r );
}
return false ;
}
2023-08-19 22:34:32 +00:00
public function virtualGroupByHash ( $hash )
{
if ( str_starts_with ( $hash , 'connections:' )) {
}
}
2021-12-02 23:02:31 +00:00
2022-08-23 10:15:05 +00:00
public static function rec_byhash ( $uid , $hash ) : mixed
2021-12-02 23:02:31 +00:00
{
if ( ! ( $uid && $hash )) {
return false ;
}
2021-12-03 03:01:39 +00:00
$r = q (
" SELECT * FROM pgrp WHERE uid = %d AND hash = '%s' LIMIT 1 " ,
2021-12-02 23:02:31 +00:00
intval ( $uid ),
dbesc ( $hash )
);
if ( $r ) {
return array_shift ( $r );
}
return false ;
}
2022-08-24 19:37:45 +00:00
public static function member_remove ( $uid , $name , $member ) : bool
2021-12-02 23:02:31 +00:00
{
$gid = self :: byname ( $uid , $name );
if ( ! $gid ) {
return false ;
}
2022-08-21 07:36:09 +00:00
if ( ! ( $uid && $member )) {
2021-12-02 23:02:31 +00:00
return false ;
}
2021-12-03 03:01:39 +00:00
$r = q (
" DELETE FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' " ,
2021-12-02 23:02:31 +00:00
intval ( $uid ),
intval ( $gid ),
dbesc ( $member )
);
Libsync :: build_sync_packet ( $uid , null , true );
2022-08-24 19:37:45 +00:00
return ( bool ) $r ;
2021-12-02 23:02:31 +00:00
}
2022-08-24 19:37:45 +00:00
public static function member_add ( $uid , $name , $member , $gid = 0 ) : bool
2021-12-02 23:02:31 +00:00
{
if ( ! $gid ) {
$gid = self :: byname ( $uid , $name );
}
if ( ! ( $gid && $uid && $member )) {
return false ;
}
2021-12-03 03:01:39 +00:00
$r = q (
" SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1 " ,
2021-12-02 23:02:31 +00:00
intval ( $uid ),
intval ( $gid ),
dbesc ( $member )
);
if ( $r ) {
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
} else {
2021-12-03 03:01:39 +00:00
$r = q (
" INSERT INTO pgrp_member (uid, gid, xchan)
2022-07-21 07:25:07 +00:00
VALUES ( % d , % d , '%s' ) " ,
2021-12-02 23:02:31 +00:00
intval ( $uid ),
intval ( $gid ),
dbesc ( $member )
);
}
Libsync :: build_sync_packet ( $uid , null , true );
2022-08-24 19:37:45 +00:00
return ( bool ) $r ;
2021-12-02 23:02:31 +00:00
}
2022-12-04 07:10:30 +00:00
public static function members ( $uid , $gid , $total = false , $start = 0 , $records = 0 , $sqlExtra = '' ) : mixed
2021-12-02 23:02:31 +00:00
{
$ret = [];
2022-08-23 10:15:05 +00:00
$pager_sql = '' ;
2022-12-04 07:10:30 +00:00
$sql_extra = $sqlExtra ;
2022-08-23 10:15:05 +00:00
2021-12-02 23:02:31 +00:00
if ( $records ) {
$pager_sql = sprintf ( " LIMIT %d OFFSET %d " , intval ( $records ), intval ( $start ));
}
// process virtual groups
2023-08-25 11:24:06 +00:00
if ( str_starts_with ( $gid , ':' ) || str_starts_with ( $gid , 'connections:' )) {
2021-12-02 23:02:31 +00:00
$vg = substr ( $gid , 1 );
switch ( $vg ) {
case '2' :
2022-07-21 07:25:07 +00:00
$sql_extra = " and xchan_network in ('nomad','zot6') " ;
2021-12-02 23:02:31 +00:00
break ;
case '3' :
$sql_extra = " and xchan_network = 'activitypub' " ;
break ;
2022-08-23 10:15:05 +00:00
case '1' :
2021-12-02 23:02:31 +00:00
default :
break ;
}
2023-08-25 11:24:06 +00:00
2021-12-02 23:02:31 +00:00
if ( $total ) {
2021-12-03 03:01:39 +00:00
$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 " ,
2021-12-02 23:02:31 +00:00
intval ( $uid )
);
return ( $r ) ? $r [ 0 ][ 'total' ] : false ;
}
2021-12-03 03:01:39 +00:00
$r = q (
" SELECT * FROM abook left join xchan on xchan_hash = abook_xchan
2022-12-04 07:10:30 +00:00
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 " ,
2021-12-02 23:02:31 +00:00
intval ( $uid )
);
if ( $r ) {
for ( $x = 0 ; $x < count ( $r ); $x ++ ) {
$r [ $x ][ 'xchan' ] = $r [ $x ][ 'abook_xchan' ];
}
}
return $r ;
}
if ( intval ( $gid )) {
if ( $total ) {
2021-12-03 03:01:39 +00:00
$r = q (
2022-07-21 07:25:07 +00:00
" 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
2022-12-04 19:49:46 +00:00
and abook_blocked = 0 and abook_pending = 0 $sqlExtra " ,
2021-12-02 23:02:31 +00:00
intval ( $gid ),
intval ( $uid ),
intval ( $uid )
);
if ( $r ) {
return $r [ 0 ][ 'total' ];
}
}
2021-12-03 03:01:39 +00:00
$r = q (
2022-07-21 07:25:07 +00:00
" SELECT * FROM pgrp_member
LEFT JOIN abook ON abook_xchan = pgrp_member . xchan left join xchan on xchan_hash = abook_xchan
2022-12-04 19:49:46 +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 $sqlExtra ORDER BY xchan_name ASC $pager_sql " ,
2021-12-02 23:02:31 +00:00
intval ( $gid ),
intval ( $uid ),
intval ( $uid )
);
if ( $r ) {
$ret = $r ;
}
}
return $ret ;
}
2022-08-23 10:15:05 +00:00
public static function members_xchan ( $uid , $gid ) : array
2021-12-02 23:02:31 +00:00
{
$ret = [];
if ( intval ( $gid )) {
2021-12-03 03:01:39 +00:00
$r = q (
" SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d " ,
2021-12-02 23:02:31 +00:00
intval ( $gid ),
intval ( $uid )
);
if ( $r ) {
foreach ( $r as $rv ) {
$ret [] = $rv [ 'xchan' ];
}
}
}
return $ret ;
}
2022-08-23 10:15:05 +00:00
public static function select ( $uid , $group = '' ) : string
2021-12-02 23:02:31 +00:00
{
$grps = [];
2021-12-03 03:01:39 +00:00
$r = q (
" SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC " ,
2021-12-02 23:02:31 +00:00
intval ( $uid )
);
$grps [] = [ 'name' => '' , 'hash' => '0' , 'selected' => '' ];
if ( $r ) {
foreach ( $r as $rr ) {
$grps [] = [ 'name' => $rr [ 'gname' ], 'id' => $rr [ 'hash' ], 'selected' => (( $group == $rr [ 'hash' ]) ? 'true' : '' )];
}
}
2022-02-12 20:43:29 +00:00
return replace_macros ( Theme :: get_template ( 'group_selection.tpl' ), [
2021-12-02 23:02:31 +00:00
'$label' => t ( 'Add new connections to this access list' ),
'$groups' => $grps
]);
}
2023-11-10 05:36:54 +00:00
public static function AudienceSelect () : string
2023-11-09 20:40:16 +00:00
{
$grps = [];
$channel = App :: $channel ;
$r = q (
" SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC " ,
intval ( $channel [ 'channel_id' ])
);
2023-11-10 07:37:43 +00:00
$grps = [
[ 'name' => t ( 'Public' ), 'id' => '' , 'selected' => $channel [ 'channel_allow_gid' ] === '' ],
[ 'name' => t ( 'Connections' ), 'id' => 'connections:' . $channel [ 'channel_hash' ],
'selected' => $channel [ 'channel_allow_gid' ] === '<' . 'connections:' . $channel [ 'channel_hash' ] . '>' ]
2023-11-09 20:40:16 +00:00
];
if ( $r ) {
foreach ( $r as $rr ) {
$grps [] = [ 'name' => $rr [ 'gname' ], 'id' => $rr [ 'hash' ],
'selected' => $channel [ 'channel_allow_gid' ] === '<' . $rr [ 'hash' ] . '>' ];
}
}
2023-11-10 05:36:54 +00:00
return replace_macros ( Theme :: get_template ( 'audience_selection.tpl' ), [
'$title' => t ( 'Audience Selection' ),
'$desc' => t ( 'Use this form to select your default posting audience and default permissions for media and file uploads.' ),
'$desc2' => t ( 'Note: If you change your channel type, this form will be reset to the default audience for that type' ),
2023-11-09 20:40:16 +00:00
'$label' => t ( 'Default audience for posts and media access' ),
2023-11-10 07:37:43 +00:00
'$groups' => $grps ,
'$submit' => t ( 'Submit' )
2023-11-09 20:40:16 +00:00
]);
}
2021-12-02 23:02:31 +00:00
2022-08-23 10:15:05 +00:00
public static function widget ( $every = " connections " , $each = " lists " , $edit = false , $group_id = 0 , $cid = '' , $mode = 1 ) : string
2021-12-02 23:02:31 +00:00
{
$groups = [];
2021-12-03 03:01:39 +00:00
$r = q (
" SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC " ,
2021-12-02 23:02:31 +00:00
intval ( $_SESSION [ 'uid' ])
);
$member_of = [];
if ( $cid ) {
$member_of = self :: containing ( local_channel (), $cid );
}
if ( $r ) {
foreach ( $r as $rr ) {
$selected = (( $group_id == $rr [ 'id' ]) ? ' group-selected' : '' );
if ( $edit ) {
$groupedit = [ 'href' => " lists/ " . $rr [ 'id' ], 'title' => t ( 'edit' )];
} 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 ),
];
}
}
2022-02-12 20:43:29 +00:00
return replace_macros ( Theme :: get_template ( 'group_side.tpl' ), [
2021-12-02 23:02:31 +00:00
'$title' => t ( 'Lists' ),
'$edittext' => t ( 'Edit list' ),
'$createtext' => t ( 'Create new list' ),
'$ungrouped' => (( $every === 'contacts' ) ? t ( 'Channels not in any access list' ) : '' ),
'$groups' => $groups ,
'$add' => t ( 'add' ),
]);
}
2022-08-23 10:15:05 +00:00
public static function expand ( $g ) : array
2021-12-02 23:02:31 +00:00
{
if ( ! ( is_array ( $g ) && count ( $g ))) {
return [];
}
$ret = [];
$x = [];
foreach ( $g as $gv ) {
// 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
2022-08-27 04:01:22 +00:00
if ( str_starts_with ( $gv , 'connections:' ) || str_starts_with ( $gv , 'zot:' ) || str_starts_with ( $gv , 'activitypub:' )) {
2021-12-02 23:02:31 +00:00
$sql_extra = EMPTY_STR ;
$channel_hash = substr ( $gv , strpos ( $gv , ':' ) + 1 );
2022-08-27 04:01:22 +00:00
if ( str_starts_with ( $gv , 'zot:' )) {
2022-07-21 07:25:07 +00:00
$sql_extra = " and xchan_network in ('nomad','zot6') " ;
2021-12-02 23:02:31 +00:00
}
2022-08-27 04:01:22 +00:00
if ( str_starts_with ( $gv , 'activitypub:' )) {
2021-12-02 23:02:31 +00:00
$sql_extra = " and xchan_network = 'activitypub' " ;
}
2021-12-03 03:01:39 +00:00
$r = q (
" select channel_id from channel where channel_hash = '%s' " ,
2021-12-02 23:02:31 +00:00
dbesc ( $channel_hash )
);
if ( $r ) {
foreach ( $r as $rv ) {
2021-12-03 03:01:39 +00:00
$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 " ,
2021-12-02 23:02:31 +00:00
intval ( $rv [ 'channel_id' ])
);
if ( $y ) {
foreach ( $y as $yv ) {
$ret [] = $yv [ 'abook_xchan' ];
}
}
}
}
2022-08-23 10:15:05 +00:00
}
else {
2021-12-02 23:02:31 +00:00
$x [] = $gv ;
}
}
if ( $x ) {
stringify_array_elms ( $x , true );
$groups = implode ( ',' , $x );
if ( $groups ) {
$r = q ( " SELECT xchan FROM pgrp_member WHERE gid IN ( select id from pgrp where hash in ( $groups )) " );
if ( $r ) {
foreach ( $r as $rv ) {
$ret [] = $rv [ 'xchan' ];
}
}
}
}
return $ret ;
}
2022-10-11 07:59:26 +00:00
/** @noinspection PhpUnused */
2022-08-27 04:01:22 +00:00
public static function member_of ( $c ) : array | bool
2021-12-02 23:02:31 +00:00
{
2022-08-27 04:01:22 +00:00
return q (
2022-07-21 07:25:07 +00:00
" 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 " ,
2021-12-02 23:02:31 +00:00
dbesc ( $c )
);
}
2022-08-23 10:15:05 +00:00
public static function containing ( $uid , $c ) : array
2021-12-02 23:02:31 +00:00
{
2021-12-03 03:01:39 +00:00
$r = q (
" SELECT gid FROM pgrp_member WHERE uid = %d AND pgrp_member.xchan = '%s' " ,
2021-12-02 23:02:31 +00:00
intval ( $uid ),
dbesc ( $c )
);
$ret = [];
if ( $r ) {
2021-12-03 03:01:39 +00:00
foreach ( $r as $rv ) {
2021-12-02 23:02:31 +00:00
$ret [] = $rv [ 'gid' ];
2021-12-03 03:01:39 +00:00
}
2021-12-02 23:02:31 +00:00
}
return $ret ;
}
2021-12-03 03:01:39 +00:00
}