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