]> git.mxchange.org Git - friendica.git/blob - src/Security/Security.php
Merge remote-tracking branch 'upstream/2021.06-rc' into http-options
[friendica.git] / src / Security / Security.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2021, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 namespace Friendica\Security;
23
24 use Friendica\Database\DBA;
25 use Friendica\Model\Contact;
26 use Friendica\Model\Group;
27 use Friendica\Model\User;
28 use Friendica\Core\Session;
29
30 /**
31  * Secures that User is allow to do requests
32  */
33 class Security
34 {
35         public static function canWriteToUserWall($owner)
36         {
37                 static $verified = 0;
38
39                 if (!Session::isAuthenticated()) {
40                         return false;
41                 }
42
43                 $uid = local_user();
44                 if ($uid == $owner) {
45                         return true;
46                 }
47
48                 if (local_user() && ($owner == 0)) {
49                         return true;
50                 }
51
52                 if (!empty(Session::getRemoteContactID($owner))) {
53                         // use remembered decision and avoid a DB lookup for each and every display item
54                         // DO NOT use this function if there are going to be multiple owners
55                         // We have a contact-id for an authenticated remote user, this block determines if the contact
56                         // belongs to this page owner, and has the necessary permissions to post content
57
58                         if ($verified === 2) {
59                                 return true;
60                         } elseif ($verified === 1) {
61                                 return false;
62                         } else {
63                                 $cid = Session::getRemoteContactID($owner);
64                                 if (!$cid) {
65                                         return false;
66                                 }
67
68                                 $r = q("SELECT `contact`.*, `user`.`page-flags` FROM `contact` INNER JOIN `user` on `user`.`uid` = `contact`.`uid`
69                                         WHERE `contact`.`uid` = %d AND `contact`.`id` = %d AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
70                                         AND `user`.`blockwall` = 0 AND `readonly` = 0  AND (`contact`.`rel` IN (%d , %d) OR `user`.`page-flags` = %d) LIMIT 1",
71                                         intval($owner),
72                                         intval($cid),
73                                         intval(Contact::SHARING),
74                                         intval(Contact::FRIEND),
75                                         intval(User::PAGE_FLAGS_COMMUNITY)
76                                 );
77
78                                 if (DBA::isResult($r)) {
79                                         $verified = 2;
80                                         return true;
81                                 } else {
82                                         $verified = 1;
83                                 }
84                         }
85                 }
86
87                 return false;
88         }
89
90         /**
91          * Create a permission string for an element based on the visitor
92          *
93          * @param integer $owner_id   User ID of the owner of the element
94          * @param boolean $accessible Should the element be accessible anyway?
95          * @return string SQL permissions
96          */
97         public static function getPermissionsSQLByUserId(int $owner_id, bool $accessible = false)
98         {
99                 $local_user = local_user();
100                 $remote_contact = Session::getRemoteContactID($owner_id);
101                 $acc_sql = '';
102
103                 if ($accessible) {
104                         $acc_sql = ' OR `accessible`';
105                 }
106
107                 /*
108                  * Construct permissions
109                  *
110                  * default permissions - anonymous user
111                  */
112                 $sql = " AND (allow_cid = ''
113                          AND allow_gid = ''
114                          AND deny_cid  = ''
115                          AND deny_gid  = ''" . $acc_sql . ") ";
116
117                 /*
118                  * Profile owner - everything is visible
119                  */
120                 if ($local_user && $local_user == $owner_id) {
121                         $sql = '';
122                 /*
123                  * Authenticated visitor. Load the groups the visitor belongs to.
124                  */
125                 } elseif ($remote_contact) {
126                         $gs = '<<>>'; // should be impossible to match
127
128                         $groups = Group::getIdsByContactId($remote_contact);
129
130                         if (is_array($groups)) {
131                                 foreach ($groups as $g) {
132                                         $gs .= '|<' . intval($g) . '>';
133                                 }
134                         }
135
136                         $sql = sprintf(
137                                 " AND (NOT (deny_cid REGEXP '<%d>' OR deny_gid REGEXP '%s')
138                                   AND (allow_cid REGEXP '<%d>' OR allow_gid REGEXP '%s'
139                                   OR (allow_cid = '' AND allow_gid = ''))" . $acc_sql . ") ",
140                                 intval($remote_contact),
141                                 DBA::escape($gs),
142                                 intval($remote_contact),
143                                 DBA::escape($gs)
144                         );
145                 }
146                 return $sql;
147         }
148 }