]> git.mxchange.org Git - friendica.git/blob - mod/acl.php
Fix mods/README.md format
[friendica.git] / mod / acl.php
1 <?php
2
3 /* ACL selector json backend */
4
5 use Friendica\App;
6 use Friendica\Content\Widget;
7 use Friendica\Core\ACL;
8 use Friendica\Core\Addon;
9 use Friendica\Core\Logger;
10 use Friendica\Core\Protocol;
11 use Friendica\Database\DBA;
12 use Friendica\Model\Contact;
13 use Friendica\Model\Item;
14 use Friendica\Util\Proxy as ProxyUtils;
15 use Friendica\Util\Strings;
16
17 require_once 'include/dba.php';
18
19 function acl_content(App $a)
20 {
21         if (!local_user()) {
22                 return '';
23         }
24
25         $start   = defaults($_REQUEST, 'start'       , 0);
26         $count   = defaults($_REQUEST, 'count'       , 100);
27         $search  = defaults($_REQUEST, 'search'      , '');
28         $type    = defaults($_REQUEST, 'type'        , '');
29         $conv_id = defaults($_REQUEST, 'conversation', null);
30
31         // For use with jquery.textcomplete for private mail completion
32         if (!empty($_REQUEST['query'])) {
33                 if (!$type) {
34                         $type = 'm';
35                 }
36                 $search = $_REQUEST['query'];
37         }
38
39         Logger::log("Searching for ".$search." - type ".$type." conversation ".$conv_id, Logger::DEBUG);
40
41         if ($search != '') {
42                 $sql_extra = "AND `name` LIKE '%%" . DBA::escape($search) . "%%'";
43                 $sql_extra2 = "AND (`attag` LIKE '%%" . DBA::escape($search) . "%%' OR `name` LIKE '%%" . DBA::escape($search) . "%%' OR `nick` LIKE '%%" . DBA::escape($search) . "%%')";
44         } else {
45                 /// @TODO Avoid these needless else blocks by putting variable-initialization atop of if()
46                 $sql_extra = $sql_extra2 = '';
47         }
48
49         // count groups and contacts
50         $group_count = 0;
51         if ($type == '' || $type == 'g') {
52                 $r = q("SELECT COUNT(*) AS g FROM `group` WHERE `deleted` = 0 AND `uid` = %d $sql_extra",
53                         intval(local_user())
54                 );
55                 $group_count = (int) $r[0]['g'];
56         }
57
58         $sql_extra2 .= ' ' . Widget::unavailableNetworks();
59
60         $contact_count = 0;
61         if ($type == '' || $type == 'c') {
62                 // autocomplete for editor mentions
63                 $r = q("SELECT COUNT(*) AS c FROM `contact`
64                                 WHERE `uid` = %d AND NOT `self`
65                                 AND NOT `blocked` AND NOT `pending` AND NOT `archive`
66                                 AND `success_update` >= `failure_update`
67                                 AND `notify` != '' $sql_extra2",
68                         intval(local_user())
69                 );
70                 $contact_count = (int) $r[0]['c'];
71         } elseif ($type == 'f') {
72                 // autocomplete for editor mentions of forums
73                 $r = q("SELECT COUNT(*) AS c FROM `contact`
74                                 WHERE `uid` = %d AND NOT `self`
75                                 AND NOT `blocked` AND NOT `pending` AND NOT `archive`
76                                 AND (`forum` OR `prv`)
77                                 AND `success_update` >= `failure_update`
78                                 AND `notify` != '' $sql_extra2",
79                         intval(local_user())
80                 );
81                 $contact_count = (int) $r[0]['c'];
82         } elseif ($type == 'm') {
83                 // autocomplete for Private Messages
84                 $r = q("SELECT COUNT(*) AS c FROM `contact`
85                                 WHERE `uid` = %d AND NOT `self`
86                                 AND NOT `blocked` AND NOT `pending` AND NOT `archive`
87                                 AND `success_update` >= `failure_update`
88                                 AND `network` IN ('%s', '%s', '%s') $sql_extra2",
89                         intval(local_user()),
90                         DBA::escape(Protocol::ACTIVITYPUB),
91                         DBA::escape(Protocol::DFRN),
92                         DBA::escape(Protocol::DIASPORA)
93                 );
94                 $contact_count = (int) $r[0]['c'];
95         } elseif ($type == 'a') {
96                 // autocomplete for Contacts
97                 $r = q("SELECT COUNT(*) AS c FROM `contact`
98                                 WHERE `uid` = %d AND NOT `self`
99                                 AND NOT `pending` $sql_extra2",
100                         intval(local_user())
101                 );
102                 $contact_count = (int) $r[0]['c'];
103         }
104
105         $tot = $group_count + $contact_count;
106
107         $groups = [];
108         $contacts = [];
109
110         if ($type == '' || $type == 'g') {
111                 /// @todo We should cache this query.
112                 // This can be done when we can delete cache entries via wildcard
113                 $r = q("SELECT `group`.`id`, `group`.`name`, GROUP_CONCAT(DISTINCT `group_member`.`contact-id` SEPARATOR ',') AS uids
114                                 FROM `group`
115                                 INNER JOIN `group_member` ON `group_member`.`gid`=`group`.`id`
116                                 WHERE NOT `group`.`deleted` AND `group`.`uid` = %d
117                                         $sql_extra
118                                 GROUP BY `group`.`name`, `group`.`id`
119                                 ORDER BY `group`.`name`
120                                 LIMIT %d,%d",
121                         intval(local_user()),
122                         intval($start),
123                         intval($count)
124                 );
125
126                 foreach ($r as $g) {
127                         $groups[] = [
128                                 'type'  => 'g',
129                                 'photo' => 'images/twopeople.png',
130                                 'name'  => htmlspecialchars($g['name']),
131                                 'id'    => intval($g['id']),
132                                 'uids'  => array_map('intval', explode(',', $g['uids'])),
133                                 'link'  => '',
134                                 'forum' => '0'
135                         ];
136                 }
137                 if ((count($groups) > 0) && ($search == '')) {
138                         $groups[] = ['separator' => true];
139                 }
140         }
141
142         $r = [];
143         if ($type == '') {
144                 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv`, (`prv` OR `forum`) AS `frm` FROM `contact`
145                                 WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
146                                 AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s', '%s'))
147                                 $sql_extra2
148                                 ORDER BY `name` ASC ",
149                         intval(local_user()),
150                         DBA::escape(Protocol::OSTATUS),
151                         DBA::escape(Protocol::STATUSNET)
152                 );
153         } elseif ($type == 'c') {
154                 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
155                                 WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
156                                 AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s'))
157                                 $sql_extra2
158                                 ORDER BY `name` ASC ",
159                         intval(local_user()),
160                         DBA::escape(Protocol::STATUSNET)
161                 );
162         } elseif ($type == 'f') {
163                 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
164                                 WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
165                                 AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s'))
166                                 AND (`forum` OR `prv`)
167                                 $sql_extra2
168                                 ORDER BY `name` ASC ",
169                         intval(local_user()),
170                         DBA::escape(Protocol::STATUSNET)
171                 );
172         } elseif ($type == 'm') {
173                 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr` FROM `contact`
174                                 WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive`
175                                 AND `success_update` >= `failure_update` AND `network` IN ('%s', '%s', '%s')
176                                 $sql_extra2
177                                 ORDER BY `name` ASC ",
178                         intval(local_user()),
179                         DBA::escape(Protocol::ACTIVITYPUB),
180                         DBA::escape(Protocol::DFRN),
181                         DBA::escape(Protocol::DIASPORA)
182                 );
183         } elseif ($type == 'a') {
184                 $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
185                                 WHERE `uid` = %d AND `pending` = 0 AND `success_update` >= `failure_update`
186                                 $sql_extra2
187                                 ORDER BY `name` ASC ",
188                         intval(local_user())
189                 );
190         } elseif ($type == 'x') {
191                 // autocomplete for global contact search (e.g. navbar search)
192                 $search = Strings::escapeTags(trim($_REQUEST['search']));
193                 $mode = $_REQUEST['smode'];
194
195                 $r = ACL::contactAutocomplete($search, $mode);
196
197                 $contacts = [];
198                 foreach ($r as $g) {
199                         $contacts[] = [
200                                 'photo'   => ProxyUtils::proxifyUrl($g['photo'], false, ProxyUtils::SIZE_MICRO),
201                                 'name'    => htmlspecialchars($g['name']),
202                                 'nick'    => defaults($g, 'addr', $g['url']),
203                                 'network' => $g['network'],
204                                 'link'    => $g['url'],
205                                 'forum'   => !empty($g['community']) ? 1 : 0,
206                         ];
207                 }
208                 $o = [
209                         'start' => $start,
210                         'count' => $count,
211                         'items' => $contacts,
212                 ];
213                 echo json_encode($o);
214                 exit;
215         }
216
217         if (DBA::isResult($r)) {
218                 $forums = [];
219                 foreach ($r as $g) {
220                         $entry = [
221                                 'type'    => 'c',
222                                 'photo'   => ProxyUtils::proxifyUrl($g['micro'], false, ProxyUtils::SIZE_MICRO),
223                                 'name'    => htmlspecialchars($g['name']),
224                                 'id'      => intval($g['id']),
225                                 'network' => $g['network'],
226                                 'link'    => $g['url'],
227                                 'nick'    => htmlentities(defaults($g, 'attag', $g['nick'])),
228                                 'addr'    => htmlentities(defaults($g, 'addr', $g['url'])),
229                                 'forum'   => !empty($g['forum']) || !empty($g['prv']) ? 1 : 0,
230                         ];
231                         if ($entry['forum']) {
232                                 $forums[] = $entry;
233                         } else {
234                                 $contacts[] = $entry;
235                         }
236                 }
237                 if (count($forums) > 0) {
238                         if ($search == '') {
239                                 $forums[] = ['separator' => true];
240                         }
241                         $contacts = array_merge($forums, $contacts);
242                 }
243         }
244
245         $items = array_merge($groups, $contacts);
246
247         if ($conv_id) {
248                 // In multi threaded posts the conv_id is not the parent of the whole thread
249                 $parent_item = Item::selectFirst(['parent'], ['id' => $conv_id]);
250                 if (DBA::isResult($parent_item)) {
251                         $conv_id = $parent_item['parent'];
252                 }
253
254                 /*
255                  * if $conv_id is set, get unknown contacts in thread
256                  * but first get known contacts url to filter them out
257                  */
258                 $known_contacts = array_map(function ($i) {
259                         return $i['link'];
260                 }, $contacts);
261
262                 $unknown_contacts = [];
263
264                 $condition = ["`parent` = ?", $conv_id];
265                 $params = ['order' => ['author-name' => true]];
266                 $authors = Item::selectForUser(local_user(), ['author-link'], $condition, $params);
267                 $item_authors = [];
268                 while ($author = Item::fetch($authors)) {
269                         $item_authors[$author['author-link']] = $author['author-link'];
270                 }
271                 DBA::close($authors);
272
273                 foreach ($item_authors as $author) {
274                         if (in_array($author, $known_contacts)) {
275                                 continue;
276                         }
277
278                         $contact = Contact::getDetailsByURL($author);
279
280                         if (count($contact) > 0) {
281                                 $unknown_contacts[] = [
282                                         'type'    => 'c',
283                                         'photo'   => ProxyUtils::proxifyUrl($contact['micro'], false, ProxyUtils::SIZE_MICRO),
284                                         'name'    => htmlspecialchars($contact['name']),
285                                         'id'      => intval($contact['cid']),
286                                         'network' => $contact['network'],
287                                         'link'    => $contact['url'],
288                                         'nick'    => htmlentities(defaults($contact, 'nick', $contact['addr'])),
289                                         'addr'    => htmlentities(defaults($contact, 'addr', $contact['url'])),
290                                         'forum'   => $contact['forum']
291                                 ];
292                         }
293                 }
294
295                 $items = array_merge($items, $unknown_contacts);
296                 $tot += count($unknown_contacts);
297         }
298
299         $results = [
300                 'tot'      => $tot,
301                 'start'    => $start,
302                 'count'    => $count,
303                 'groups'   => $groups,
304                 'contacts' => $contacts,
305                 'items'    => $items,
306                 'type'     => $type,
307                 'search'   => $search,
308         ];
309
310         Addon::callHooks('acl_lookup_end', $results);
311
312         $o = [
313                 'tot'   => $results['tot'],
314                 'start' => $results['start'],
315                 'count' => $results['count'],
316                 'items' => $results['items'],
317         ];
318
319         echo json_encode($o);
320         exit;
321 }