From 48a33f08e2042b0bb809f43f9bec9d7739af3c28 Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 2 Jun 2023 11:33:44 +0000 Subject: ocap initial checkin --- include/attach.php | 54 +++++++++++++++------ include/items.php | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/security.php | 12 ++++- 3 files changed, 182 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/include/attach.php b/include/attach.php index b7fb17f38..4465a67fe 100644 --- a/include/attach.php +++ b/include/attach.php @@ -338,36 +338,46 @@ function attach_by_id($id, $observer_hash) { return $ret; } -function attach_can_view($uid,$ob_hash,$resource) { +function attach_can_view($uid, $ob_hash, $resource, $token = EMPTY_STR) { - $sql_extra = permissions_sql($uid,$ob_hash); + $sql_extra = permissions_sql($uid, $ob_hash, '', $token); $hash = $resource; - if(! perm_is_allowed($uid,$ob_hash,'view_storage')) { - return false; + if (!$token) { + if(! perm_is_allowed($uid, $ob_hash, 'view_storage')) { + return false; + } } $r = q("select folder from attach where hash = '%s' and uid = %d $sql_extra", dbesc($hash), intval($uid) ); - if(! $r) { + + if(!$r) { return false; } - return attach_can_view_folder($uid,$ob_hash,$r[0]['folder']); + // don't perform recursive folder check when using OCAP. Only when using ACL access. + // For OCAP if the token is valid they can see the thing. + + if ($token) { + return true; + } + + return attach_can_view_folder($uid, $ob_hash, $r[0]['folder'], $token); } -function attach_can_view_folder($uid,$ob_hash,$folder_hash) { +function attach_can_view_folder($uid, $ob_hash, $folder_hash, $token = EMPTY_STR) { - $sql_extra = permissions_sql($uid,$ob_hash); + $sql_extra = permissions_sql($uid, $ob_hash, '', $token); $hash = $folder_hash; - if(! $folder_hash) { - return perm_is_allowed($uid,$ob_hash,'view_storage'); + if(!$folder_hash && !$token) { + return perm_is_allowed($uid, $ob_hash, 'view_storage'); } @@ -508,7 +518,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $upload_path = $arr['directory'] ?? ''; $visible = $arr['visible'] ?? 0; $notify = $arr['notify'] ?? 0; - + $flags = (($arr && array_key_exists('flags', $arr)) ? intval($arr['flags']) : 0); $observer = array(); $dosync = ((array_key_exists('nosync',$arr) && $arr['nosync']) ? 0 : 1); @@ -933,8 +943,8 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { ); } else { - $r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, filetype, folder, filesize, revision, os_storage, is_photo, content, created, edited, os_path, display_path, allow_cid, allow_gid,deny_cid, deny_gid ) - VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ", + $r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, filetype, folder, filesize, revision, os_storage, is_photo, flags, content, created, edited, os_path, display_path, allow_cid, allow_gid,deny_cid, deny_gid ) + VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ", intval($channel['channel_account_id']), intval($channel_id), dbesc($hash), @@ -946,6 +956,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { intval(0), intval(1), intval($is_photo), + intval($flags), dbescbin($os_basepath . $os_relpath), dbesc($created), dbesc($created), @@ -1413,6 +1424,23 @@ function attach_change_permissions($channel_id, $resource, $allow_cid, $allow_gi if(! $r) return; + $private = $allow_cid || $allow_gid || $deny_cid || $deny_gid; + + // preserve any existing tokens that may have been set for this file + // @fixme - we need a way to unconditionally clear these if desired. + + if ($private) { + $token_matches = null; + if (preg_match_all('/\/', $r[0]['allow_cid'], $token_matches, PREG_SET_ORDER)) { + foreach ($token_matches as $m) { + $tok = ''; + if (!str_contains($allow_cid, $tok)) { + $allow_cid .= $tok; + } + } + } + } + if(intval($r[0]['is_dir'])) { if($recurse) { $r = q("select hash, flags, is_dir from attach where folder = '%s' and uid = %d", diff --git a/include/items.php b/include/items.php index f6a93cc2c..a74fe8b50 100644 --- a/include/items.php +++ b/include/items.php @@ -5009,6 +5009,136 @@ function fix_attached_file_permissions($channel,$observer_hash,$body, } } +function list_attached_local_files($body) { + + $files = []; + $match = []; + + // match img and zmg image links + if (preg_match_all("/\[[zi]mg(.*?)](.*?)\[\/[zi]mg]/", $body, $match)) { + $images = array_merge($match[1], $match[2]); + if ($images) { + foreach ($images as $image) { + if (!stristr($image, z_root() . '/photo/')) { + continue; + } + $image_uri = substr($image,strrpos($image,'/') + 1); + if (str_contains($image_uri, '-')) { + $image_uri = substr($image_uri,0, strrpos($image_uri,'-')); + } + if (str_contains($image_uri, '.')) { + $image_uri = substr($image_uri,0, strpos($image_uri,'.')); + } + if ($image_uri && !in_array($image_uri, $files)) { + $files[] = $image_uri; + } + } + } + } + if (preg_match_all("/\[attachment](.*?)\[\/attachment]/",$body,$match)) { + $attaches = $match[1]; + if ($attaches) { + foreach ($attaches as $attach) { + $hash = substr($attach,0,strpos($attach,',')); + if ($hash && !in_array($hash, $files)) { + $files[] = $hash; + } + } + } + } + + return $files; +} + +function fix_attached_permissions($uid, $body, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny, $token = EMPTY_STR) { + + $files = list_attached_local_files($body); + + if (! $files) { + return; + } + + foreach ($files as $file) { + $attach_q = q("select id, hash, flags, is_photo, allow_cid, allow_gid, deny_cid, deny_gid from attach where hash = '%s' and uid = %d", + dbesc($file), + intval($uid) + ); + + if (! $attach_q) { + continue; + } + + $attach = array_shift($attach_q); + + $new_public = !(($str_contact_allow || $str_group_allow || $str_contact_deny || $str_group_deny)); + $existing_public = !(($attach['allow_cid'] || $attach['allow_gid'] || $attach['deny_cid'] || $attach['deny_gid'])); + + if ($existing_public) { + // permissions have already been fixed and they are public. There's nothing for us to do. + continue; + } + + // if flags & 1, the attachment was uploaded directly into a post and needs to have permissions corrected + // or - if it is a private file and a new token was generated, we'll need to add the token to the ACL. + + if (((intval($attach['flags']) & 1) !== 1) && (! $token)) { + continue; + } + + $item_private = 0; + + if ($new_public === false) { + $item_private = (($str_group_allow || ($str_contact_allow && substr_count($str_contact_allow,'<') > 2)) ? 1 : 2); + + // preserve any existing tokens that may have been set for this file + $token_matches = null; + if (preg_match_all('//',$attach['allow_cid'],$token_matches, PREG_SET_ORDER)) { + foreach ($token_matches as $m) { + $tok = ''; + if (!str_contains($str_contact_allow, $tok)) { + $str_contact_allow .= $tok; + } + } + } + if ($token && !str_contains($str_contact_allow, $token)) { + $str_contact_allow .= ''; + } + } + + q("update attach SET allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', flags = 0 + WHERE id = %d AND uid = %d", + dbesc($str_contact_allow), + dbesc($str_group_allow), + dbesc($str_contact_deny), + dbesc($str_group_deny), + intval($attach['id']), + intval($uid) + ); + + if ($attach['is_photo']) { + $r = q("UPDATE photo SET allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' + WHERE resource_id = '%s' AND uid = %d ", + dbesc($str_contact_allow), + dbesc($str_group_allow), + dbesc($str_contact_deny), + dbesc($str_group_deny), + dbesc($file), + intval($uid) + ); + + $r = q("UPDATE item SET allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d + WHERE resource_id = '%s' AND 'resource_type' = 'photo' AND uid = %d", + dbesc($str_contact_allow), + dbesc($str_group_allow), + dbesc($str_contact_deny), + dbesc($str_group_deny), + intval($item_private), + dbesc($file), + intval($uid) + ); + } + } +} function item_create_edit_activity($post) { diff --git a/include/security.php b/include/security.php index 2fbe1da1a..539e5f5b5 100644 --- a/include/security.php +++ b/include/security.php @@ -330,7 +330,7 @@ function change_channel($change_channel) { * @return string additional SQL where statement */ -function permissions_sql($owner_id, $remote_observer = null, $table = '') { +function permissions_sql($owner_id, $remote_observer = null, $table = '', $token = EMPTY_STR) { $local_channel = local_channel(); @@ -412,6 +412,16 @@ function permissions_sql($owner_id, $remote_observer = null, $table = '') { dbesc($gs) ); } + + /* + * OCAP token access + */ + + elseif ($token) { + $sql = " AND ( {$table}allow_cid like '" . protect_sprintf('%%') . + "' OR ( {$table}allow_cid = '' AND {$table}allow_gid = '' AND {$table}deny_cid = '' AND {$table}deny_gid = '' ) )"; + } + } return $sql; -- cgit v1.2.3