]> git.mxchange.org Git - friendica.git/blob - src/Core/ACL.php
Merge pull request #4548 from MrPetovan/task/3878-move-bb2diaspora-to-src
[friendica.git] / src / Core / ACL.php
1 <?php\r
2 \r
3 /**\r
4  * @file src/Core/Acl.php\r
5  */\r
6 \r
7 namespace Friendica\Core;\r
8 \r
9 use dba;\r
10 use Friendica\BaseObject;\r
11 use Friendica\Content\Feature;\r
12 use Friendica\Database\DBM;\r
13 use Friendica\Model\Contact;\r
14 use Friendica\Model\GContact;\r
15 use Friendica\Util\Network;\r
16 use const CONTACT_IS_FRIEND;\r
17 use const NETWORK_DFRN;\r
18 use const NETWORK_DIASPORA;\r
19 use const NETWORK_FACEBOOK;\r
20 use const NETWORK_MAIL;\r
21 use const NETWORK_OSTATUS;\r
22 use const PHP_EOL;\r
23 use function dbesc;\r
24 use function defaults;\r
25 use function get_markup_template;\r
26 use function get_server;\r
27 use function local_user;\r
28 use function remote_user;\r
29 use function replace_macros;\r
30 \r
31 /**\r
32  * Handle ACL management and display\r
33  *\r
34  * @author Hypolite Petovan <mrpetovan@gmail.com>\r
35  */\r
36 class ACL extends BaseObject\r
37 {\r
38         /**\r
39          * Returns a select input tag with all the contact of the local user\r
40          *\r
41          * @param string $selname Name attribute of the select input tag\r
42          * @param string $selclass Class attribute of the select input tag\r
43          * @param array $options Available options:\r
44          * - size: length of the select box\r
45          * - mutual_friends: Only used for the hook\r
46          * - single: Only used for the hook\r
47          * - exclude: Only used for the hook\r
48          * @param array $preselected Contact ID that should be already selected\r
49          * @return string\r
50          */\r
51         public static function getSuggestContactSelectHTML($selname, $selclass, array $options = [], array $preselected = [])\r
52         {\r
53                 $a = self::getApp();\r
54 \r
55                 $networks = null;\r
56 \r
57                 $size = defaults($options, 'size', 4);\r
58                 $mutual = !empty($options['mutual_friends']);\r
59                 $single = !empty($options['single']) && empty($options['multiple']);\r
60                 $exclude = defaults($options, 'exclude', false);\r
61 \r
62                 switch (defaults($options, 'networks', Protocol::PHANTOM)) {\r
63                         case 'DFRN_ONLY':\r
64                                 $networks = [NETWORK_DFRN];\r
65                                 break;\r
66                         case 'PRIVATE':\r
67                                 if (!empty($a->user['prvnets'])) {\r
68                                         $networks = [NETWORK_DFRN, NETWORK_MAIL, NETWORK_DIASPORA];\r
69                                 } else {\r
70                                         $networks = [NETWORK_DFRN, NETWORK_FACEBOOK, NETWORK_MAIL, NETWORK_DIASPORA];\r
71                                 }\r
72                                 break;\r
73                         case 'TWO_WAY':\r
74                                 if (!empty($a->user['prvnets'])) {\r
75                                         $networks = [NETWORK_DFRN, NETWORK_MAIL, NETWORK_DIASPORA];\r
76                                 } else {\r
77                                         $networks = [NETWORK_DFRN, NETWORK_FACEBOOK, NETWORK_MAIL, NETWORK_DIASPORA, NETWORK_OSTATUS];\r
78                                 }\r
79                                 break;\r
80                         default: /// @TODO Maybe log this call?\r
81                                 break;\r
82                 }\r
83 \r
84                 $x = ['options' => $options, 'size' => $size, 'single' => $single, 'mutual' => $mutual, 'exclude' => $exclude, 'networks' => $networks];\r
85 \r
86                 Addon::callHooks('contact_select_options', $x);\r
87 \r
88                 $o = '';\r
89 \r
90                 $sql_extra = '';\r
91 \r
92                 if (!empty($x['mutual'])) {\r
93                         $sql_extra .= sprintf(" AND `rel` = %d ", intval(CONTACT_IS_FRIEND));\r
94                 }\r
95 \r
96                 if (!empty($x['exclude'])) {\r
97                         $sql_extra .= sprintf(" AND `id` != %d ", intval($x['exclude']));\r
98                 }\r
99 \r
100                 if (!empty($x['networks'])) {\r
101                         /// @TODO rewrite to foreach()\r
102                         array_walk($x['networks'], function (&$value) {\r
103                                 $value = "'" . dbesc($value) . "'";\r
104                         });\r
105                         $str_nets = implode(',', $x['networks']);\r
106                         $sql_extra .= " AND `network` IN ( $str_nets ) ";\r
107                 }\r
108 \r
109                 $tabindex = (!empty($options['tabindex']) ? 'tabindex="' . $options["tabindex"] . '"' : '');\r
110 \r
111                 if (!empty($x['single'])) {\r
112                         $o .= "<select name=\"$selname\" id=\"$selclass\" class=\"$selclass\" size=\"" . $x['size'] . "\" $tabindex >\r\n";\r
113                 } else {\r
114                         $o .= "<select name=\"{$selname}[]\" id=\"$selclass\" class=\"$selclass\" multiple=\"multiple\" size=\"" . $x['size'] . "$\" $tabindex >\r\n";\r
115                 }\r
116 \r
117                 $stmt = dba::p("SELECT `id`, `name`, `url`, `network` FROM `contact`\r
118                         WHERE `uid` = ? AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''\r
119                         $sql_extra\r
120                         ORDER BY `name` ASC ", intval(local_user())\r
121                 );\r
122 \r
123                 $contacts = dba::inArray($stmt);\r
124 \r
125                 $arr = ['contact' => $contacts, 'entry' => $o];\r
126 \r
127                 // e.g. 'network_pre_contact_deny', 'profile_pre_contact_allow'\r
128                 Addon::callHooks($a->module . '_pre_' . $selname, $arr);\r
129 \r
130                 if (DBM::is_result($contacts)) {\r
131                         foreach ($contacts as $contact) {\r
132                                 if (in_array($contact['id'], $preselected)) {\r
133                                         $selected = ' selected="selected" ';\r
134                                 } else {\r
135                                         $selected = '';\r
136                                 }\r
137 \r
138                                 $trimmed = mb_substr($contact['name'], 0, 20);\r
139 \r
140                                 $o .= "<option value=\"{$contact['id']}\" $selected title=\"{$contact['name']}|{$contact['url']}\" >$trimmed</option>\r\n";\r
141                         }\r
142                 }\r
143 \r
144                 $o .= '</select>' . PHP_EOL;\r
145 \r
146                 Addon::callHooks($a->module . '_post_' . $selname, $o);\r
147 \r
148                 return $o;\r
149         }\r
150 \r
151         /**\r
152          * Returns a select input tag with all the contact of the local user\r
153          *\r
154          * @param string $selname     Name attribute of the select input tag\r
155          * @param string $selclass    Class attribute of the select input tag\r
156          * @param array  $preselected Contact IDs that should be already selected\r
157          * @param int    $size        Length of the select box\r
158          * @param int    $tabindex    Select input tag tabindex attribute\r
159          * @return string\r
160          */\r
161         public static function getMessageContactSelectHTML($selname, $selclass, array $preselected = [], $size = 4, $tabindex = null)\r
162         {\r
163                 $a = self::getApp();\r
164 \r
165                 $o = '';\r
166 \r
167                 // When used for private messages, we limit correspondence to mutual DFRN/Friendica friends and the selector\r
168                 // to one recipient. By default our selector allows multiple selects amongst all contacts.\r
169                 $sql_extra = sprintf(" AND `rel` = %d ", intval(CONTACT_IS_FRIEND));\r
170                 $sql_extra .= sprintf(" AND `network` IN ('%s' , '%s') ", NETWORK_DFRN, NETWORK_DIASPORA);\r
171 \r
172                 $tabindex_attr = !empty($tabindex) ? ' tabindex="' . intval($tabindex) . '"' : '';\r
173 \r
174                 $hidepreselected = '';\r
175                 if ($preselected) {\r
176                         $sql_extra .= " AND `id` IN (" . implode(",", $preselected) . ")";\r
177                         $hidepreselected = ' style="display: none;"';\r
178                 }\r
179 \r
180                 $o .= "<select name=\"$selname\" id=\"$selclass\" class=\"$selclass\" size=\"$size\"$tabindex_attr$hidepreselected>\r\n";\r
181 \r
182                 $stmt = dba::p("SELECT `id`, `name`, `url`, `network` FROM `contact`\r
183                         WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''\r
184                         $sql_extra\r
185                         ORDER BY `name` ASC ", intval(local_user())\r
186                 );\r
187 \r
188                 $contacts = dba::inArray($stmt);\r
189 \r
190                 $arr = ['contact' => $contacts, 'entry' => $o];\r
191 \r
192                 // e.g. 'network_pre_contact_deny', 'profile_pre_contact_allow'\r
193                 Addon::callHooks($a->module . '_pre_' . $selname, $arr);\r
194 \r
195                 $receiverlist = [];\r
196 \r
197                 if (DBM::is_result($contacts)) {\r
198                         foreach ($contacts as $contact) {\r
199                                 if (in_array($contact['id'], $preselected)) {\r
200                                         $selected = ' selected="selected"';\r
201                                 } else {\r
202                                         $selected = '';\r
203                                 }\r
204 \r
205                                 $trimmed = Protocol::formatMention($contact['url'], $contact['name']);\r
206 \r
207                                 $receiverlist[] = $trimmed;\r
208 \r
209                                 $o .= "<option value=\"{$contact['id']}\"$selected title=\"{$contact['name']}|{$contact['url']}\" >$trimmed</option>\r\n";\r
210                         }\r
211                 }\r
212 \r
213                 $o .= '</select>' . PHP_EOL;\r
214 \r
215                 if ($preselected) {\r
216                         $o .= implode(', ', $receiverlist);\r
217                 }\r
218 \r
219                 Addon::callHooks($a->module . '_post_' . $selname, $o);\r
220 \r
221                 return $o;\r
222         }\r
223 \r
224         /**\r
225          * Return the default permission of the provided user array\r
226          *\r
227          * @param array $user\r
228          * @return array Hash of contact id lists\r
229          */\r
230         public static function getDefaultUserPermissions(array $user = null)\r
231         {\r
232                 $matches = [];\r
233 \r
234                 $acl_regex = '/<([0-9]+)>/i';\r
235 \r
236                 preg_match_all($acl_regex, defaults($user, 'allow_cid', ''), $matches);\r
237                 $allow_cid = $matches[1];\r
238                 preg_match_all($acl_regex, defaults($user, 'allow_gid', ''), $matches);\r
239                 $allow_gid = $matches[1];\r
240                 preg_match_all($acl_regex, defaults($user, 'deny_cid', ''), $matches);\r
241                 $deny_cid = $matches[1];\r
242                 preg_match_all($acl_regex, defaults($user, 'deny_gid', ''), $matches);\r
243                 $deny_gid = $matches[1];\r
244 \r
245                 Contact::pruneUnavailable($allow_cid);\r
246 \r
247                 return [\r
248                         'allow_cid' => $allow_cid,\r
249                         'allow_gid' => $allow_gid,\r
250                         'deny_cid' => $deny_cid,\r
251                         'deny_gid' => $deny_gid,\r
252                 ];\r
253         }\r
254 \r
255         /**\r
256          * Return the full jot ACL selector HTML\r
257          *\r
258          * @param array $user\r
259          * @param bool  $show_jotnets\r
260          * @return string\r
261          */\r
262         public static function getFullSelectorHTML(array $user = null, $show_jotnets = false)\r
263         {\r
264                 $perms = self::getDefaultUserPermissions($user);\r
265 \r
266                 $jotnets = '';\r
267                 if ($show_jotnets) {\r
268                         $imap_disabled = !function_exists('imap_open') || Config::get('system', 'imap_disabled');\r
269 \r
270                         $mail_enabled = false;\r
271                         $pubmail_enabled = false;\r
272 \r
273                         if (!$imap_disabled) {\r
274                                 $mailacct = dba::selectFirst('mailacct', ['pubmail'], ['`uid` = ? AND `server` != ""', local_user()]);\r
275                                 if (DBM::is_result($mailacct)) {\r
276                                         $mail_enabled = true;\r
277                                         $pubmail_enabled = !empty($mailacct['pubmail']);\r
278                                 }\r
279                         }\r
280 \r
281                         if (empty($user['hidewall'])) {\r
282                                 if ($mail_enabled) {\r
283                                         $selected = $pubmail_enabled ? ' checked="checked"' : '';\r
284                                         $jotnets .= '<div class="profile-jot-net"><input type="checkbox" name="pubmail_enable"' . $selected . ' value="1" /> ' . L10n::t("Post to Email") . '</div>';\r
285                                 }\r
286 \r
287                                 Addon::callHooks('jot_networks', $jotnets);\r
288                         } else {\r
289                                 $jotnets .= L10n::t('Connectors disabled, since "%s" is enabled.',\r
290                                                 L10n::t('Hide your profile details from unknown viewers?'));\r
291                         }\r
292                 }\r
293 \r
294                 $tpl = get_markup_template('acl_selector.tpl');\r
295                 $o = replace_macros($tpl, [\r
296                         '$showall' => L10n::t('Visible to everybody'),\r
297                         '$show' => L10n::t('show'),\r
298                         '$hide' => L10n::t('don\'t show'),\r
299                         '$allowcid' => json_encode($perms['allow_cid']),\r
300                         '$allowgid' => json_encode($perms['allow_gid']),\r
301                         '$denycid' => json_encode($perms['deny_cid']),\r
302                         '$denygid' => json_encode($perms['deny_gid']),\r
303                         '$networks' => $show_jotnets,\r
304                         '$emailcc' => L10n::t('CC: email addresses'),\r
305                         '$emtitle' => L10n::t('Example: bob@example.com, mary@example.com'),\r
306                         '$jotnets' => $jotnets,\r
307                         '$aclModalTitle' => L10n::t('Permissions'),\r
308                         '$aclModalDismiss' => L10n::t('Close'),\r
309                         '$features' => [\r
310                                 'aclautomention' => Feature::isEnabled($user['uid'], 'aclautomention') ? 'true' : 'false'\r
311                         ],\r
312                 ]);\r
313 \r
314                 return $o;\r
315         }\r
316 \r
317         /**\r
318          * Searching for global contacts for autocompletion\r
319          *\r
320          * @brief Searching for global contacts for autocompletion\r
321          * @param string $search Name or part of a name or nick\r
322          * @param string $mode   Search mode (e.g. "community")\r
323          * @return array with the search results\r
324          */\r
325         public static function contactAutocomplete($search, $mode)\r
326         {\r
327                 if ((Config::get('system', 'block_public')) && (!local_user()) && (!remote_user())) {\r
328                         return [];\r
329                 }\r
330 \r
331                 // don't search if search term has less than 2 characters\r
332                 if (!$search || mb_strlen($search) < 2) {\r
333                         return [];\r
334                 }\r
335 \r
336                 if (substr($search, 0, 1) === '@') {\r
337                         $search = substr($search, 1);\r
338                 }\r
339 \r
340                 // check if searching in the local global contact table is enabled\r
341                 if (Config::get('system', 'poco_local_search')) {\r
342                         $return = GContact::searchByName($search, $mode);\r
343                 } else {\r
344                         $a = self::getApp();\r
345                         $p = $a->pager['page'] != 1 ? '&p=' . $a->pager['page'] : '';\r
346 \r
347                         $response = Network::curl(get_server() . '/lsearch?f=' . $p . '&search=' . urlencode($search));\r
348                         if ($response['success']) {\r
349                                 $lsearch = json_decode($response['body'], true);\r
350                                 if (!empty($lsearch['results'])) {\r
351                                         $return = $lsearch['results'];\r
352                                 }\r
353                         }\r
354                 }\r
355 \r
356                 return defaults($return, []);\r
357         }\r
358 }\r