]> git.mxchange.org Git - friendica.git/blob - src/Security/Security.php
Merge pull request #12298 from annando/api-suggestions
[friendica.git] / src / Security / Security.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2022, 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\DI;
26 use Friendica\Model\Contact;
27 use Friendica\Model\Group;
28 use Friendica\Model\User;
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 (!DI::userSession()->isAuthenticated()) {
40                         return false;
41                 }
42
43                 $uid = DI::userSession()->getLocalUserId();
44                 if ($uid == $owner) {
45                         return true;
46                 }
47
48                 if (DI::userSession()->getLocalUserId() && ($owner == 0)) {
49                         return true;
50                 }
51
52                 if (!empty($cid = DI::userSession()->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                                 $user = User::getById($owner);
64                                 if (!$user || $user['blockwall']) {
65                                         $verified = 1;
66                                         return false;
67                                 }
68
69                                 $contact = Contact::getById($cid);
70                                 if ($contact || $contact['blocked'] || $contact['readonly'] || $contact['pending']) {
71                                         $verified = 1;
72                                         return false;
73                                 }
74                                 
75                                 if (in_array($contact['rel'], [Contact::SHARING, Contact::FRIEND]) || ($user['page-flags'] == User::PAGE_FLAGS_COMMUNITY)) {
76                                         $verified = 2;
77                                         return true;
78                                 } else {
79                                         $verified = 1;
80                                 }
81                         }
82                 }
83
84                 return false;
85         }
86
87         /**
88          * Create a permission string for an element based on the visitor
89          *
90          * @param integer $owner_id   User ID of the owner of the element
91          * @param boolean $accessible Should the element be accessible anyway?
92          * @return string SQL permissions
93          */
94         public static function getPermissionsSQLByUserId(int $owner_id, bool $accessible = false)
95         {
96                 $local_user = DI::userSession()->getLocalUserId();
97                 $remote_contact = DI::userSession()->getRemoteContactID($owner_id);
98                 $acc_sql = '';
99
100                 if ($accessible) {
101                         $acc_sql = ' OR `accessible`';
102                 }
103
104                 /*
105                  * Construct permissions
106                  *
107                  * default permissions - anonymous user
108                  */
109                 $sql = " AND (allow_cid = ''
110                          AND allow_gid = ''
111                          AND deny_cid  = ''
112                          AND deny_gid  = ''" . $acc_sql . ") ";
113
114                 /*
115                  * Profile owner - everything is visible
116                  */
117                 if ($local_user && $local_user == $owner_id) {
118                         $sql = '';
119                 /*
120                  * Authenticated visitor. Load the groups the visitor belongs to.
121                  */
122                 } elseif ($remote_contact) {
123                         $gs = '<<>>'; // should be impossible to match
124
125                         $groups = Group::getIdsByContactId($remote_contact);
126
127                         if (is_array($groups)) {
128                                 foreach ($groups as $g) {
129                                         $gs .= '|<' . intval($g) . '>';
130                                 }
131                         }
132
133                         $sql = sprintf(
134                                 " AND (NOT (deny_cid REGEXP '<%d>' OR deny_gid REGEXP '%s')
135                                   AND (allow_cid REGEXP '<%d>' OR allow_gid REGEXP '%s'
136                                   OR (allow_cid = '' AND allow_gid = ''))" . $acc_sql . ") ",
137                                 intval($remote_contact),
138                                 DBA::escape($gs),
139                                 intval($remote_contact),
140                                 DBA::escape($gs)
141                         );
142                 }
143                 return $sql;
144         }
145 }